SuperSeller3000/src/Infrastructure/AI/Agent/SpecsResearchAgent.php

62 lines
2 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Infrastructure\AI\Agent;
use App\Infrastructure\AI\OllamaClientInterface;
use App\Infrastructure\AI\PromptTemplateService;
use App\Infrastructure\Search\WebSearchInterface;
final class SpecsResearchAgent
{
public function __construct(
private readonly OllamaClientInterface $client,
private readonly PromptTemplateService $prompts,
private readonly WebSearchInterface $search,
private readonly string $model,
) {
}
/**
* @return array{specsText: string, correctedModelNumber: string}
*/
public function research(string $modelName, string $articleTypeName, string $manufacturer = ''): array
{
$subject = trim(($manufacturer !== '' ? $manufacturer.' ' : '').$modelName);
$searchResults = $this->search->search("{$subject} {$articleTypeName} specifications");
$prompt = $this->prompts->render('specs_research', [
'articleType' => $articleTypeName,
'subject' => $subject,
'searchResults' => $searchResults !== '' ? $searchResults : 'No web results available.',
]);
$result = $this->client->generate($this->model, $prompt);
if ('' === trim($result)) {
throw new \RuntimeException("No specifications found for model: {$modelName}");
}
return $this->parseResponse($result);
}
/** @return array{specsText: string, correctedModelNumber: string} */
private function parseResponse(string $raw): array
{
$correctedModelNumber = '';
if (preg_match('/^CORRECTED_MODEL_NUMBER:\s*(\S+)/m', $raw, $matches)) {
$correctedModelNumber = trim($matches[1]);
// Strip the line from the specs text
$raw = preg_replace('/^CORRECTED_MODEL_NUMBER:[^\n]*\n?/m', '', $raw) ?? $raw;
}
return [
'specsText' => trim($raw),
'correctedModelNumber' => $correctedModelNumber,
];
}
}