feat: extract modelName and modelNumber separately in vision pipeline
Vision prompt now distinguishes MODEL_NAME (human-readable product name, e.g. "ThinkPad T490s") from MODEL_NUMBER (part/product code, e.g. "20NXS0BA00"). Both fields flow through the pipeline and are written to the article. Specs research uses model number as search subject when available, falling back to model name. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c10c306a5a
commit
525424a6a1
6 changed files with 24 additions and 12 deletions
|
|
@ -16,7 +16,7 @@ final class OllamaVisionAgent
|
|||
) {
|
||||
}
|
||||
|
||||
/** @return array{manufacturer: string, model: string, serial: string} */
|
||||
/** @return array{manufacturer: string, modelName: string, modelNumber: string, serial: string} */
|
||||
public function analyze(string $imagePath): array
|
||||
{
|
||||
$prompt = $this->prompts->render('vision_analyze');
|
||||
|
|
@ -25,7 +25,8 @@ final class OllamaVisionAgent
|
|||
|
||||
return [
|
||||
'manufacturer' => $this->extractField($response, 'MANUFACTURER'),
|
||||
'model' => $this->extractField($response, 'MODEL'),
|
||||
'modelName' => $this->extractField($response, 'MODEL_NAME'),
|
||||
'modelNumber' => $this->extractField($response, 'MODEL_NUMBER'),
|
||||
'serial' => $this->extractField($response, 'SERIAL'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,11 +43,14 @@ PROMPT,
|
|||
|
||||
'vision_analyze' => <<<'PROMPT'
|
||||
Look at this nameplate/label photo of IT hardware.
|
||||
Extract the manufacturer (brand), model number/designation, and serial number visible on the label.
|
||||
Do not guess or add information not on the label.
|
||||
Extract the manufacturer, model name, model number, and serial number visible on the label.
|
||||
- MODEL_NAME is the human-readable product name (e.g. "ThinkPad T490s", "EliteBook 840 G6", "Galaxy S24 Ultra").
|
||||
- MODEL_NUMBER is the part/product code or designation (e.g. "20NXS0BA00", "5SS67UC", "SM-S928B"). Often printed as "Model No.", "Part No.", "Type", or "P/N".
|
||||
Do not guess or add information not visible on the label.
|
||||
Respond in exactly this format (use empty string if not visible):
|
||||
MANUFACTURER: <brand name, e.g. Dell, HP, Lenovo, Medion>
|
||||
MODEL: <model number or designation>
|
||||
MODEL_NAME: <human-readable product name>
|
||||
MODEL_NUMBER: <part/product code or model number>
|
||||
SERIAL: <serial number>
|
||||
PROMPT,
|
||||
|
||||
|
|
|
|||
|
|
@ -67,8 +67,11 @@ final class DraftArticleHandler
|
|||
if (isset($vision['manufacturer']) && '' !== $vision['manufacturer']) {
|
||||
$article->setManufacturer((string) $vision['manufacturer']);
|
||||
}
|
||||
if (isset($vision['model']) && '' !== $vision['model']) {
|
||||
$article->setModelNumber((string) $vision['model']);
|
||||
if (isset($vision['modelNumber']) && '' !== $vision['modelNumber']) {
|
||||
$article->setModelNumber((string) $vision['modelNumber']);
|
||||
}
|
||||
if (isset($vision['modelName']) && '' !== $vision['modelName']) {
|
||||
$article->setModelName((string) $vision['modelName']);
|
||||
}
|
||||
|
||||
if ([] !== $message->attributes) {
|
||||
|
|
|
|||
|
|
@ -37,13 +37,14 @@ final class PhotoUploadHandler
|
|||
|
||||
$job->recordStep('vision', [
|
||||
'manufacturer' => $result['manufacturer'],
|
||||
'model' => $result['model'],
|
||||
'modelName' => $result['modelName'],
|
||||
'modelNumber' => $result['modelNumber'],
|
||||
'serial' => $result['serial'],
|
||||
]);
|
||||
$this->jobRepository->save($job);
|
||||
|
||||
if ('' === $result['model']) {
|
||||
$job->markNeedsReview('OllamaVisionAgent: no model name detected on nameplate');
|
||||
if ('' === $result['modelNumber'] && '' === $result['modelName']) {
|
||||
$job->markNeedsReview('OllamaVisionAgent: no model detected on nameplate');
|
||||
$this->jobRepository->save($job);
|
||||
|
||||
return;
|
||||
|
|
@ -52,7 +53,8 @@ final class PhotoUploadHandler
|
|||
$this->bus->dispatch(new SpecsResearchMessage(
|
||||
jobId: $message->jobId,
|
||||
articleTypeId: $message->articleTypeId,
|
||||
modelName: $result['model'],
|
||||
modelNumber: $result['modelNumber'],
|
||||
modelName: $result['modelName'],
|
||||
serialNumber: $result['serial'],
|
||||
manufacturer: $result['manufacturer'],
|
||||
));
|
||||
|
|
|
|||
|
|
@ -39,9 +39,11 @@ final class SpecsResearchHandler
|
|||
return;
|
||||
}
|
||||
|
||||
$searchSubject = $message->modelNumber !== '' ? $message->modelNumber : $message->modelName;
|
||||
|
||||
try {
|
||||
$specsText = $this->specsAgent->research(
|
||||
$message->modelName,
|
||||
$searchSubject,
|
||||
$articleType->getName(),
|
||||
$message->manufacturer,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ final readonly class SpecsResearchMessage
|
|||
public function __construct(
|
||||
public string $jobId,
|
||||
public string $articleTypeId,
|
||||
public string $modelNumber,
|
||||
public string $modelName,
|
||||
public string $serialNumber,
|
||||
public string $manufacturer = '',
|
||||
|
|
|
|||
Loading…
Reference in a new issue