You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.2 KiB
73 lines
2.2 KiB
<?php |
|
|
|
namespace App\Http\Controllers\Api\V1; |
|
|
|
use App\Http\Controllers\Api\Concerns\RespondsWithJson; |
|
use App\Http\Controllers\Controller; |
|
use App\Services\AiChatService; |
|
use App\Support\ApiActor; |
|
use Illuminate\Http\JsonResponse; |
|
use Illuminate\Http\Request; |
|
use Throwable; |
|
|
|
class AiChatController extends Controller |
|
{ |
|
use RespondsWithJson; |
|
|
|
public function __construct( |
|
private readonly AiChatService $aiChat |
|
) { |
|
} |
|
|
|
/** |
|
* POST /api/v1/ai/chat |
|
* Body: { "message": "...", "history": [...] } |
|
*/ |
|
public function chat(Request $request): JsonResponse |
|
{ |
|
if (! $this->aiChat->isAvailable()) { |
|
return $this->fail('AI service belum dikonfigurasi (OLLAMA_BASE_URL kosong).', 'service_unavailable', 503); |
|
} |
|
|
|
$validated = $request->validate([ |
|
'message' => ['required', 'string', 'min:2', 'max:2000'], |
|
'history' => ['sometimes', 'array', 'max:20'], |
|
'history.*.role' => ['required_with:history', 'string', 'in:user,assistant'], |
|
'history.*.content' => ['required_with:history', 'string', 'max:4000'], |
|
]); |
|
|
|
/** @var ApiActor|null $actor */ |
|
$actor = $request->attributes->get('api_actor'); |
|
$username = $actor instanceof ApiActor ? $actor->identifier : 'unknown'; |
|
|
|
try { |
|
$result = $this->aiChat->chat( |
|
query: $validated['message'], |
|
username: $username, |
|
displayName: $username, |
|
jobTitle: '', |
|
history: $validated['history'] ?? [], |
|
); |
|
|
|
return $this->ok([ |
|
'answer' => $result['answer'], |
|
'context_count' => $result['meta']['context_count'], |
|
'model' => $result['meta']['model'], |
|
]); |
|
} catch (Throwable $e) { |
|
return $this->fail('Gagal memproses permintaan AI: '.$e->getMessage(), 'server_error', 500); |
|
} |
|
} |
|
|
|
/** |
|
* GET /api/v1/ai/status |
|
*/ |
|
public function status(): JsonResponse |
|
{ |
|
return $this->ok([ |
|
'available' => $this->aiChat->isAvailable(), |
|
'base_url' => config('ollama.base_url') ?: null, |
|
'model' => config('ollama.chat_model'), |
|
]); |
|
} |
|
}
|
|
|