Merge branch 'main' of https://github.com/mhilya/sista_mif_ta
This commit is contained in:
commit
15fa7e2acb
|
|
@ -23,9 +23,13 @@ from filelock import FileLock, Timeout
|
||||||
# ──────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────
|
||||||
BASE_DIR = Path(__file__).parent.parent
|
BASE_DIR = Path(__file__).parent.parent
|
||||||
ML_DIR = BASE_DIR / "ml_assets"
|
ML_DIR = BASE_DIR / "ml_assets"
|
||||||
|
DATA_DIR = BASE_DIR.parent / "data"
|
||||||
|
KETERANGAN_PATH = DATA_DIR / "keterangan_ts_kemendiktisaintek.csv"
|
||||||
|
COORDS_PATH = DATA_DIR / "kabupaten_coords.json"
|
||||||
PIPELINE_PATH = ML_DIR / "ml_pipeline_internal.pkl"
|
PIPELINE_PATH = ML_DIR / "ml_pipeline_internal.pkl"
|
||||||
STATUS_PATH = ML_DIR / "retrain_status.json"
|
STATUS_PATH = ML_DIR / "retrain_status.json"
|
||||||
LOCK_PATH = ML_DIR / "retrain_status.lock"
|
LOCK_PATH = ML_DIR / "retrain_status.lock"
|
||||||
|
METRICS_PATH = ML_DIR / "metrics_internal_only.json"
|
||||||
RETRAIN_WORKER = Path(__file__).parent / "retrain_worker.py"
|
RETRAIN_WORKER = Path(__file__).parent / "retrain_worker.py"
|
||||||
TEMP_DIR = ML_DIR / "tmp"
|
TEMP_DIR = ML_DIR / "tmp"
|
||||||
TEMP_DIR.mkdir(parents=True, exist_ok=True)
|
TEMP_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
@ -237,6 +241,40 @@ def retrain_status():
|
||||||
except Exception:
|
except Exception:
|
||||||
return JSONResponse(content={"stage": "unknown", "message": "Status tidak terbaca."})
|
return JSONResponse(content={"stage": "unknown", "message": "Status tidak terbaca."})
|
||||||
|
|
||||||
|
@app.get("/api/v1/metrics/internal", dependencies=[Depends(verify_token)])
|
||||||
|
def get_internal_metrics():
|
||||||
|
if not METRICS_PATH.exists():
|
||||||
|
return JSONResponse(status_code=404, content={"status": "error", "message": "Metrics file not found"})
|
||||||
|
try:
|
||||||
|
data = json.loads(METRICS_PATH.read_text(encoding="utf-8"))
|
||||||
|
return JSONResponse(content=data)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to read metrics: {e}")
|
||||||
|
return JSONResponse(status_code=500, content={"status": "error", "message": "Failed to read metrics"})
|
||||||
|
|
||||||
|
from fastapi.responses import Response
|
||||||
|
|
||||||
|
@app.get("/api/v1/data/keterangan", dependencies=[Depends(verify_token)])
|
||||||
|
def get_keterangan_csv():
|
||||||
|
if not KETERANGAN_PATH.exists():
|
||||||
|
return JSONResponse(status_code=404, content={"status": "error", "message": "CSV file not found"})
|
||||||
|
try:
|
||||||
|
return Response(content=KETERANGAN_PATH.read_bytes(), media_type="text/csv")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to read CSV: {e}")
|
||||||
|
return JSONResponse(status_code=500, content={"status": "error", "message": "Failed to read CSV"})
|
||||||
|
|
||||||
|
@app.get("/api/v1/data/kabupaten_coords", dependencies=[Depends(verify_token)])
|
||||||
|
def get_coords_json():
|
||||||
|
if not COORDS_PATH.exists():
|
||||||
|
return JSONResponse(status_code=404, content={"status": "error", "message": "Coords file not found"})
|
||||||
|
try:
|
||||||
|
data = json.loads(COORDS_PATH.read_text(encoding="utf-8"))
|
||||||
|
return JSONResponse(content=data)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to read coords: {e}")
|
||||||
|
return JSONResponse(status_code=500, content={"status": "error", "message": "Failed to read coords"})
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/v1/retrain/reload", dependencies=[Depends(verify_token)])
|
@app.post("/api/v1/retrain/reload", dependencies=[Depends(verify_token)])
|
||||||
def reload_model():
|
def reload_model():
|
||||||
|
|
|
||||||
|
|
@ -101,11 +101,7 @@ public function index(Request $request)
|
||||||
'map_lokasi' => $chartLokasi,
|
'map_lokasi' => $chartLokasi,
|
||||||
];
|
];
|
||||||
|
|
||||||
$metricsPath = base_path('../fastapi/ml_assets/metrics_internal_only.json');
|
$mlMetrics = app(\App\Services\FastApiWorkerService::class)->getInternalMetrics();
|
||||||
$mlMetrics = null;
|
|
||||||
if (file_exists($metricsPath)) {
|
|
||||||
$mlMetrics = json_decode(file_get_contents($metricsPath), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$manualOverrideCount = ClassificationResult::where('source_type', 'internal_mif')
|
$manualOverrideCount = ClassificationResult::where('source_type', 'internal_mif')
|
||||||
->where('status', 'manual_override')
|
->where('status', 'manual_override')
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,20 @@ public function index()
|
||||||
'total_kemendik' => KemendikRawData::count(),
|
'total_kemendik' => KemendikRawData::count(),
|
||||||
];
|
];
|
||||||
|
|
||||||
$keteranganPath = base_path('../data/keterangan_ts_kemendiktisaintek.csv');
|
|
||||||
$keterangan = [];
|
$keterangan = [];
|
||||||
if (file_exists($keteranganPath)) {
|
$csvText = app(\App\Services\FastApiWorkerService::class)->getKemendikKeteranganCsv();
|
||||||
$lines = file($keteranganPath);
|
|
||||||
|
if ($csvText) {
|
||||||
|
$lines = explode("\n", trim($csvText));
|
||||||
if (count($lines) > 0) {
|
if (count($lines) > 0) {
|
||||||
$rawHeaders = str_getcsv(trim($lines[0]), ';');
|
$rawHeaders = str_getcsv(trim($lines[0]), ';');
|
||||||
$headers = array_map('trim', $rawHeaders);
|
$headers = array_map('trim', $rawHeaders);
|
||||||
|
|
||||||
for ($i = 1; $i < count($lines); $i++) {
|
for ($i = 1; $i < count($lines); $i++) {
|
||||||
$row = str_getcsv(trim($lines[$i]), ';');
|
$rowStr = trim($lines[$i]);
|
||||||
|
if ($rowStr === '') continue;
|
||||||
|
|
||||||
|
$row = str_getcsv($rowStr, ';');
|
||||||
foreach ($headers as $index => $header) {
|
foreach ($headers as $index => $header) {
|
||||||
$val = trim($row[$index] ?? '');
|
$val = trim($row[$index] ?? '');
|
||||||
if ($val !== '') {
|
if ($val !== '') {
|
||||||
|
|
@ -75,8 +79,7 @@ public function index()
|
||||||
}, ['< 2 Juta' => 0, '2 - 4 Juta' => 0, '4 - 6 Juta' => 0, '> 6 Juta' => 0]);
|
}, ['< 2 Juta' => 0, '2 - 4 Juta' => 0, '4 - 6 Juta' => 0, '> 6 Juta' => 0]);
|
||||||
$chartPendapatan = array_filter($chartPendapatan);
|
$chartPendapatan = array_filter($chartPendapatan);
|
||||||
|
|
||||||
$coordsPath = base_path('../data/kabupaten_coords.json');
|
$kabupatenCoords = app(\App\Services\FastApiWorkerService::class)->getKabupatenCoords() ?? [];
|
||||||
$kabupatenCoords = file_exists($coordsPath) ? json_decode(file_get_contents($coordsPath), true) : [];
|
|
||||||
|
|
||||||
$charts = [
|
$charts = [
|
||||||
'status' => collect($statusCounts),
|
'status' => collect($statusCounts),
|
||||||
|
|
|
||||||
|
|
@ -172,4 +172,61 @@ public function reloadModel(): array
|
||||||
return ['error' => "Kesalahan sistem internal: {$e->getMessage()}"];
|
return ['error' => "Kesalahan sistem internal: {$e->getMessage()}"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ambil data metrics internal ML dari FastAPI
|
||||||
|
*/
|
||||||
|
public function getInternalMetrics(): ?array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$response = $this->getClient(5)->get($this->baseUrl . '/api/v1/metrics/internal');
|
||||||
|
|
||||||
|
if ($response->successful()) {
|
||||||
|
return $response->json();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->status() !== 404) {
|
||||||
|
Log::warning("FastAPI Metrics Error: HTTP {$response->status()} | {$response->body()}");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (ConnectionException $e) {
|
||||||
|
Log::warning("FastAPI Metrics Connection Error: {$e->getMessage()}");
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error("FastAPI Metrics System Error: {$e->getMessage()}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ambil data CSV keterangan Kemendikbud dari FastAPI
|
||||||
|
*/
|
||||||
|
public function getKemendikKeteranganCsv(): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$response = $this->getClient(5)->get($this->baseUrl . '/api/v1/data/keterangan');
|
||||||
|
if ($response->successful()) {
|
||||||
|
return $response->body();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ambil data JSON koordinat kabupaten dari FastAPI
|
||||||
|
*/
|
||||||
|
public function getKabupatenCoords(): ?array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$response = $this->getClient(5)->get($this->baseUrl . '/api/v1/data/kabupaten_coords');
|
||||||
|
if ($response->successful()) {
|
||||||
|
return $response->json();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue