52 lines
1.7 KiB
PHP
52 lines
1.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Exceptions\OllamaUnavailableException;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\StoreTicketRequest;
|
|
use App\Models\Ticket;
|
|
use App\Services\EmbeddingService;
|
|
use App\Services\SemanticSearchService;
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
class TicketController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly EmbeddingService $embeddingService,
|
|
private readonly SemanticSearchService $semanticSearchService,
|
|
) {}
|
|
|
|
public function store(StoreTicketRequest $request): JsonResponse
|
|
{
|
|
try {
|
|
$embedding = $this->embeddingService->embed($request->string('message')->toString());
|
|
} catch (OllamaUnavailableException $e) {
|
|
return response()->json([
|
|
'message' => 'Ollama is unavailable. Could not generate embedding.',
|
|
], 503);
|
|
}
|
|
|
|
$ticket = Ticket::query()->create([
|
|
'message' => $request->string('message')->toString(),
|
|
'embedding' => $embedding,
|
|
]);
|
|
|
|
try {
|
|
$result = $this->semanticSearchService->findBestArticle($ticket);
|
|
} catch (OllamaUnavailableException $e) {
|
|
return response()->json([
|
|
'message' => 'Ticket saved, but Ollama ranking is unavailable.',
|
|
'ticket_id' => $ticket->id,
|
|
], 202);
|
|
}
|
|
|
|
return response()->json([
|
|
'ticket_id' => $ticket->id,
|
|
'best_article' => $result['best_article'],
|
|
'confidence' => $result['confidence'],
|
|
'explanation' => $result['explanation'],
|
|
'top_3_candidates' => $result['top_3_candidates'],
|
|
], 201);
|
|
}
|
|
} |