'help/create.md', 'title' => 'Как создать проект', 'tour' => 'create-project', 'topics' => 'создать проект, новый проект, запустить сбор', 'chunk_index' => 0, 'content' => 'Проект создаётся в разделе «Проекты», кнопка «Создать».', ]); KnowledgeChunk::create([ 'source_path' => 'help/notify.md', 'title' => 'Уведомления портала', 'tour' => 'notifications', 'topics' => 'уведомления, сообщение, письмо, колокольчик', 'chunk_index' => 0, 'content' => 'Уведомления приходят в колокольчик и на почту.', ]); }); it('на болтовню без сути экскурсию не предлагает', function () { $search = app(KnowledgeSearch::class); $notify = KnowledgeChunk::where('tour', 'notifications')->firstOrFail(); foreach (['привет', 'ага', 'слушаю', 'спасибо'] as $chatter) { expect($search->isOnTopic($notify, $chatter))->toBeFalse(); } }); it('реплика не-вопрос экскурсию не получает, даже если слово совпало', function () { $search = app(KnowledgeSearch::class); $notify = KnowledgeChunk::where('tour', 'notifications')->firstOrFail(); // «сообщение» есть в ключевых словах статьи про уведомления — но человек ни о чём // не спрашивает. Именно так бот и водил на экскурсию по уведомлениям (13.07.2026). expect($search->isOnTopic($notify, 'первое сообщение подряд'))->toBeFalse(); }); it('вопрос по теме статьи экскурсию получает', function () { $search = app(KnowledgeSearch::class); $create = KnowledgeChunk::where('tour', 'create-project')->firstOrFail(); expect($search->isOnTopic($create, 'как создать проект?'))->toBeTrue(); }); it('совпадение по двум ключевым словам тоже считается', function () { $search = app(KnowledgeSearch::class); $notify = KnowledgeChunk::where('tour', 'notifications')->firstOrFail(); expect($search->isOnTopic($notify, 'куда приходит письмо и колокольчик?'))->toBeTrue(); });