162 lines
4.5 KiB
PHP
162 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class MLPredictionService
|
|
{
|
|
/**
|
|
* Dapatkan prediksi dari script Python langsung
|
|
*/
|
|
public function getPrediction(array $data)
|
|
{
|
|
try {
|
|
$payload = [
|
|
'pekerjaan' => $data['pekerjaan'] ?? '',
|
|
'penghasilan' => (float) ($data['penghasilan'] ?? 0),
|
|
'jumlah_tanggungan' => (int) ($data['jumlah_tanggungan'] ?? 0),
|
|
'aset_kepemilikan' => $data['aset_kepemilikan'] ?? '',
|
|
'bantuan_lain' => $data['bantuan_lain'] ?? '',
|
|
'usia' => (int) ($data['usia'] ?? 0),
|
|
];
|
|
|
|
$jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
|
|
$pythonPath = 'python';
|
|
$scriptPath = base_path('ml/predict.py');
|
|
|
|
$descriptorspec = [
|
|
0 => ['pipe', 'r'], // stdin
|
|
1 => ['pipe', 'w'], // stdout
|
|
2 => ['pipe', 'w'], // stderr
|
|
];
|
|
|
|
$process = proc_open(
|
|
$pythonPath . ' ' . escapeshellarg($scriptPath),
|
|
$descriptorspec,
|
|
$pipes,
|
|
base_path()
|
|
);
|
|
|
|
if (!is_resource($process)) {
|
|
Log::error('Gagal menjalankan proses Python ML.');
|
|
return null;
|
|
}
|
|
|
|
fwrite($pipes[0], $jsonPayload);
|
|
fclose($pipes[0]);
|
|
|
|
$output = stream_get_contents($pipes[1]);
|
|
fclose($pipes[1]);
|
|
|
|
$errorOutput = stream_get_contents($pipes[2]);
|
|
fclose($pipes[2]);
|
|
|
|
$exitCode = proc_close($process);
|
|
|
|
if ($exitCode !== 0) {
|
|
Log::error('Python ML exit code bukan 0.', [
|
|
'exit_code' => $exitCode,
|
|
'stderr' => $errorOutput,
|
|
'stdout' => $output,
|
|
]);
|
|
return null;
|
|
}
|
|
|
|
$result = json_decode($output, true);
|
|
|
|
if (!$result || isset($result['error'])) {
|
|
Log::error('Hasil prediksi ML tidak valid.', [
|
|
'output' => $output,
|
|
'stderr' => $errorOutput,
|
|
'decoded' => $result,
|
|
]);
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'probability' => $result['probability'] ?? 0,
|
|
'recommendation' => $result['recommendation'] ?? 'Tidak Layak',
|
|
];
|
|
} catch (\Throwable $e) {
|
|
Log::error('ML Prediction Exception: ' . $e->getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cek apakah script ML bisa dijalankan
|
|
*/
|
|
public function healthCheck()
|
|
{
|
|
try {
|
|
$pythonPath = 'python';
|
|
$scriptPath = base_path('ml/predict.py');
|
|
|
|
if (!file_exists($scriptPath)) {
|
|
return false;
|
|
}
|
|
|
|
$testPayload = json_encode([
|
|
'pekerjaan' => 'buruh',
|
|
'penghasilan' => 500000,
|
|
'jumlah_tanggungan' => 4,
|
|
'aset_kepemilikan' => 'motor',
|
|
'bantuan_lain' => 'tidak',
|
|
'usia' => 50,
|
|
]);
|
|
|
|
$descriptorspec = [
|
|
0 => ['pipe', 'r'],
|
|
1 => ['pipe', 'w'],
|
|
2 => ['pipe', 'w'],
|
|
];
|
|
|
|
$process = proc_open(
|
|
$pythonPath . ' ' . escapeshellarg($scriptPath),
|
|
$descriptorspec,
|
|
$pipes,
|
|
base_path()
|
|
);
|
|
|
|
if (!is_resource($process)) {
|
|
return false;
|
|
}
|
|
|
|
fwrite($pipes[0], $testPayload);
|
|
fclose($pipes[0]);
|
|
|
|
$output = stream_get_contents($pipes[1]);
|
|
fclose($pipes[1]);
|
|
|
|
fclose($pipes[2]);
|
|
|
|
$exitCode = proc_close($process);
|
|
|
|
if ($exitCode !== 0) {
|
|
return false;
|
|
}
|
|
|
|
$result = json_decode($output, true);
|
|
|
|
return is_array($result) && isset($result['probability']) && isset($result['recommendation']);
|
|
} catch (\Throwable $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prediksi untuk banyak data sekaligus
|
|
*/
|
|
public function getBatchPredictions(array $dataArray)
|
|
{
|
|
$results = [];
|
|
|
|
foreach ($dataArray as $item) {
|
|
$results[] = $this->getPrediction($item);
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
} |