112 lines
2.8 KiB
PHP
112 lines
2.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Intent;
|
|
|
|
use App\Config\CommerceIntentConfig;
|
|
|
|
final class CommerceIntentLite
|
|
{
|
|
public const NONE = 'none';
|
|
public const PRODUCT_SEARCH = 'product_search';
|
|
public const ADVISORY_PRODUCT_SEARCH = 'advisory_product_search';
|
|
|
|
public function __construct(
|
|
private readonly CommerceIntentConfig $config
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* @return array{intent:string, score:int, signals:string[]}
|
|
*/
|
|
public function detect(string $originalPrompt): array
|
|
{
|
|
$p = mb_strtolower(trim($originalPrompt));
|
|
|
|
if ($p === '') {
|
|
return [
|
|
'intent' => self::NONE,
|
|
'score' => 0,
|
|
'signals' => [],
|
|
];
|
|
}
|
|
|
|
$score = 0;
|
|
$signals = [];
|
|
|
|
$strongSignals = $this->config->getStrongSignalsList();
|
|
|
|
foreach ($strongSignals as $signal) {
|
|
if (str_contains($p, strtolower($signal))) {
|
|
$score += 3;
|
|
$signals[] = $signal;
|
|
}
|
|
}
|
|
|
|
if (preg_match('#\d{3,10}#', $p)) {
|
|
$score += 2;
|
|
$signals[] = 'sku';
|
|
}
|
|
|
|
$pricePattern = $this->config->getPricePattern();
|
|
if (preg_match('/\b\d+(?:[.,]\d+)?\s*(' . $pricePattern . ')\b/u', $p) === 1) {
|
|
$score += 2;
|
|
$signals[] = 'price';
|
|
}
|
|
|
|
$sizePattern = $this->config->getSizePattern();
|
|
if (preg_match('/\b(' . $sizePattern . ')\s*[a-z0-9.-]+\b/u', $p) === 1) {
|
|
$score += 2;
|
|
$signals[] = 'size';
|
|
}
|
|
|
|
$sizeTokenPattern = $this->config->getSizeTokenPattern();
|
|
if (preg_match('/\b(' . $sizeTokenPattern . ')\b/u', $p) === 1) {
|
|
$score += 1;
|
|
$signals[] = 'size_token';
|
|
}
|
|
|
|
$colorPattern = $this->config->getColorPattern();
|
|
if (preg_match('/\b(' . $colorPattern . ')\b/u', $p) === 1) {
|
|
$score += 1;
|
|
$signals[] = 'color';
|
|
}
|
|
|
|
$advisorySignals = $this->config->getAdvisorySignals();
|
|
|
|
foreach ($advisorySignals as $signal) {
|
|
if (str_contains($p, $signal)) {
|
|
$score += 1;
|
|
$signals[] = 'advisory:' . $signal;
|
|
}
|
|
}
|
|
|
|
$signals = array_values(array_unique($signals));
|
|
|
|
if ($score >= 3) {
|
|
return [
|
|
'intent' => self::PRODUCT_SEARCH,
|
|
'score' => $score,
|
|
'signals' => $signals,
|
|
];
|
|
}
|
|
|
|
if ($score >= 2) {
|
|
return [
|
|
'intent' => self::ADVISORY_PRODUCT_SEARCH,
|
|
'score' => $score,
|
|
'signals' => $signals,
|
|
];
|
|
}
|
|
|
|
return [
|
|
'intent' => self::NONE,
|
|
'score' => $score,
|
|
'signals' => $signals,
|
|
];
|
|
}
|
|
|
|
} |