diff --git a/migrations/Version20260520050000.php b/migrations/Version20260520050000.php new file mode 100644 index 0000000..482dcb6 --- /dev/null +++ b/migrations/Version20260520050000.php @@ -0,0 +1,63 @@ + + +If the model number is correct or no model number was provided, omit the CORRECTED_MODEL_NUMBER line entirely. +PROMPT; + + $this->addSql('UPDATE app.prompt_templates SET body = :body, updated_at = NOW() WHERE key = :key', [ + 'body' => $body, + 'key' => 'specs_research', + ]); + } + + public function down(Schema $schema): void + { + $body = <<<'PROMPT' +You are a hardware specifications expert. Extract the technical specifications for the {{articleType}}: "{{subject}}". + +Web search results: +{{searchResults}} + +Based on the search results above, list all technical specifications including: +processor, RAM, storage variants, display size and resolution, GPU, battery capacity, +ports, connectivity, weight, dimensions, OS, and any other relevant specs. +Be specific and accurate. If a spec is not found in the search results, omit it rather than guessing. +PROMPT; + + $this->addSql('UPDATE app.prompt_templates SET body = :body, updated_at = NOW() WHERE key = :key', [ + 'body' => $body, + 'key' => 'specs_research', + ]); + } +} diff --git a/src/Infrastructure/AI/Agent/SpecsResearchAgent.php b/src/Infrastructure/AI/Agent/SpecsResearchAgent.php index 8fc0ec8..618b0da 100644 --- a/src/Infrastructure/AI/Agent/SpecsResearchAgent.php +++ b/src/Infrastructure/AI/Agent/SpecsResearchAgent.php @@ -18,7 +18,10 @@ final class SpecsResearchAgent ) { } - public function research(string $modelName, string $articleTypeName, string $manufacturer = ''): string + /** + * @return array{specsText: string, correctedModelNumber: string} + */ + public function research(string $modelName, string $articleTypeName, string $manufacturer = ''): array { $subject = trim(($manufacturer !== '' ? $manufacturer.' ' : '').$modelName); @@ -36,6 +39,23 @@ final class SpecsResearchAgent throw new \RuntimeException("No specifications found for model: {$modelName}"); } - return $result; + 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, + ]; } } diff --git a/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php b/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php index fa0b87e..d1aaaa2 100644 --- a/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php +++ b/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php @@ -67,8 +67,10 @@ final class DraftArticleHandler if (isset($vision['manufacturer']) && '' !== $vision['manufacturer']) { $article->setManufacturer((string) $vision['manufacturer']); } - if (isset($vision['modelNumber']) && '' !== $vision['modelNumber']) { - $article->setModelNumber((string) $vision['modelNumber']); + $correctedModelNumber = (string) ($job->getOutputData()['specs_research']['correctedModelNumber'] ?? ''); + $modelNumber = $correctedModelNumber !== '' ? $correctedModelNumber : (string) ($vision['modelNumber'] ?? ''); + if ('' !== $modelNumber) { + $article->setModelNumber($modelNumber); } if (isset($vision['modelName']) && '' !== $vision['modelName']) { $article->setModelName((string) $vision['modelName']); diff --git a/src/Infrastructure/Messenger/Handler/SpecsResearchHandler.php b/src/Infrastructure/Messenger/Handler/SpecsResearchHandler.php index 4f458e0..ec43d90 100644 --- a/src/Infrastructure/Messenger/Handler/SpecsResearchHandler.php +++ b/src/Infrastructure/Messenger/Handler/SpecsResearchHandler.php @@ -45,7 +45,7 @@ final class SpecsResearchHandler $searchSubject = implode(' ', $parts); try { - $specsText = $this->specsAgent->research( + $result = $this->specsAgent->research( $searchSubject, $articleType->getName(), $message->manufacturer, @@ -57,13 +57,16 @@ final class SpecsResearchHandler return; } - $job->recordStep('specs_research', ['specsText' => $specsText]); + $job->recordStep('specs_research', [ + 'specsText' => $result['specsText'], + 'correctedModelNumber' => $result['correctedModelNumber'], + ]); $this->jobRepository->save($job); $this->bus->dispatch(new JsonCodingMessage( jobId: $message->jobId, articleTypeId: $message->articleTypeId, - specsText: $specsText, + specsText: $result['specsText'], serialNumber: $message->serialNumber, )); }