analyze('займы под залог авто и спецтехники', 'Красноярский край')) ->toBe(['займы под залог авто и спецтехники']); }); it('разбирает JSON-массив запросов из ответа модели', function () { Config::set('services.aitunnel', [ 'key' => 'k', 'base_url' => 'https://api.aitunnel.ru/v1', 'chat_model' => 'gpt-4o-mini', 'timeout_sec' => 30, ]); $http = app(HttpFactory::class); $http->fake([ '*/chat/completions' => $http->response([ 'choices' => [['message' => ['content' => '["автоломбард","займ под залог авто","МФО","ломбард"]']]], ], 200), ]); $a = new AitunnelQueryAnalyzer($http); $out = $a->analyze('займы под залог авто', 'Красноярский край'); expect($out)->toBe(['автоломбард', 'займ под залог авто', 'МФО', 'ломбард']); }); it('режет markdown-обёртку и пустые/дубли, ограничивает число', function () { Config::set('services.aitunnel.key', 'k'); $http = app(HttpFactory::class); $http->fake([ '*/chat/completions' => $http->response([ 'choices' => [['message' => ['content' => "```json\n[\"автоломбард\",\"\",\"автоломбард\",\"займ под залог\"]\n```"]]], ], 200), ]); $a = new AitunnelQueryAnalyzer($http); $out = $a->analyze('займы', 'Красноярский край'); expect($out)->toBe(['автоломбард', 'займ под залог']); }); it('добавляет в промт наш сайт и конкурентов, когда они переданы', function () { Config::set('services.aitunnel', [ 'key' => 'k', 'base_url' => 'https://api.aitunnel.ru/v1', 'chat_model' => 'gpt-4o-mini', 'timeout_sec' => 30, ]); $http = app(HttpFactory::class); $http->fake(['*/chat/completions' => $http->response(['choices' => [['message' => ['content' => '["автоломбард"]']]]], 200)]); $a = new AitunnelQueryAnalyzer($http); $a->analyze('займы под залог', 'Красноярск', 'lkomega.ru', ['comp1.ru', 'https://2gis.ru/firm/1']); $http->assertSent(function ($req) { $c = $req->data()['messages'][0]['content'] ?? ''; return str_contains($c, 'посмотри наш сайт lkomega.ru') && str_contains($c, 'а также наших главных конкурентов') && str_contains($c, 'comp1.ru'); }); }); it('без сайта и конкурентов — контекстные фразы в промт НЕ попадают', function () { Config::set('services.aitunnel', [ 'key' => 'k', 'base_url' => 'https://api.aitunnel.ru/v1', 'chat_model' => 'gpt-4o-mini', 'timeout_sec' => 30, ]); $http = app(HttpFactory::class); $http->fake(['*/chat/completions' => $http->response(['choices' => [['message' => ['content' => '["автоломбард"]']]]], 200)]); $a = new AitunnelQueryAnalyzer($http); $a->analyze('займы под залог', 'Красноярск'); // без сайта/конкурентов $http->assertSent(function ($req) { $c = $req->data()['messages'][0]['content'] ?? ''; return ! str_contains($c, 'посмотри наш сайт') && ! str_contains($c, 'наших главных конкурентов'); }); }); it('при ошибке сети — fallback из описания', function () { Config::set('services.aitunnel.key', 'k'); $http = app(HttpFactory::class); $http->fake(['*/chat/completions' => $http->response('boom', 500)]); $a = new AitunnelQueryAnalyzer($http); expect($a->analyze('ломбард', 'Красноярский край'))->toBe(['ломбард']); });