Меня зовут Дима Кирпа, я разработчик из команды ML Laboratory в Yandex Infrastructure. Четыре года я делаю внутренний поиск по корпоративному интранету Яндекса. Сегодня предлагаю ненадолго отложить судорожный тюнинг промптов и температуры LLM и окинуть внутренние корпоративные знания более широким взглядом. На примере опыта Яндекса я разберу процесс LLM‑изации интранета компании с самых азов. На время мы вернёмся в ламповый мир старого доброго фича‑инжиниринга, неспешно пройдёмся от настроек ранжирования к настройкам поискового контекста для LLM и увидим, как фичи поиска плавно перетекают в фичи генеративки. Напоследок убедимся, что всё не зря и наши разработки реально приносят пользу компании.
Я расскажу, как устроен бэкенд и ранжирование внутреннего поиска Яндекса, как на базе внутреннего поиска мы построили генеративную Q&A‑систему AI Chat. Покажу обоснования разных внедрений в виде чисел из реальных A/B‑экспериментов. Никакого хайпа, только факты. Цель статьи — доказать, что поиск — это база для корпоративных процессов обмена знаниями, а модель роста от поиска к агенту — самая эффективная.
Почему внедрение LLM может буксовать
Нынче из каждого утюга льются медовые речи о бесконечной пользе больших языковых моделей и автономных агентов. Кажется, найден легендарный рецепт идеальной корпоративной продуктивности. Всего за вечер можно поднять векторную базу над вашей докой и таск‑трекером, прикрутить к ней LangChain, поиграть с промптами и вуаля — вы и ваши коллеги попиваете смузи на шезлонге, наблюдая, как модные генеративные технологии решают задачи.
Если всё было бы так просто, вы бы не читали эту статью. Некоторые попытки внедрения LLM не только не растят эффективность коллег, а скорее отбирают её. Бывают случаи, когда агент не так уж и плох, но коллеги всё равно почему‑то не спешат им пользоваться. Главной корпоративной вопрос‑ответной системой компании остаются лички сотрудников в мессенджере. Агент же после себя оставляет лишь мемы про свои забавные галлюцинации и счета за вызовы LLM.

Это неудивительно. Повышение производительности за счёт новых технологий не может взлететь без настройки рабочих процессов и технической инфраструктуры. Сердцем этой инфраструктуры, на мой взгляд, должен быть поиск. Без качественного инструмента поиска рушится цепочка работы со знаниями:
У людей умирает мотивация писать документацию. Зачем, если всё равно никто не найдёт?
Смерть документации делает плохой поиск ещё хуже.
Плохой поиск по плохой базе становится плохим в квадрате. Порочный круг замыкается.
Отсутствие хорошей документации и поиска приводит к тому, что люди буквально добывают знания и могут тратить часы на простые задачи.
Рушатся и агентские сценарии. Документация и поиск критичны для синтеза кода, так как агенту нужно:
знать, как запускать код, как его тестировать, какие данные отдают внешние API;
искать решения ошибок;
понимать требования к реализуемому коду;
ориентироваться в существующей кодовой базе. В случае с кодом Яндекса просто прочитать всё невозможно, а погрепать регулярками бывает недостаточно в силу объёма;
учитывать, как новый код повлияет на другие сервисы и почему в прошлом были приняты те или иные решения;
соблюдать нефункциональные требования, например требования к памяти или производительности, правила обработки чувствительных данных.

На этом фоне попытки бизнеса внедрить агентов выглядят наивно. Проблемы со знаниями в такой компании нельзя решить взмахом волшебной генеративки. Если натравить LLM на ошмётки знаний, которые вдобавок ей никак не достать, она будет галлюцинировать.
Что такое внутренний поиск
Внутренний поиск Яндекса — это классическая поисковая строка. Пользователь приходит, вводит запрос и получает топ документов с красивым ИИ‑ответом, наподобие ответа Алисы в веб‑поиске.

Мы существуем в виде отдельного портала на своём собственном домене и как поисковые строки на поверхностях других сервисов интранета. Таких внутренних сервисов довольно много, например, корпоративная Вики, наш таск‑трекер Яндекс Трекер, кодовый репозиторий. Мы ищем по более чем 50 системам, и суммарно в наших индексах лежит более миллиарда документов. Без специализированного инструмента добывать знания в таких масштабах невозможно. Почти каждая новая информационная площадка в интранете очень хочет попасть к нам на выдачу, иначе её ждёт забвение.

Внутренний поиск существует уже почти 17 лет. Мы появились задолго до агентов, LLM и даже трансформеров. Начинали как простой полнотекстовый поиск отдельно по каждой из подключённых систем. Такой поиск работает на базе инвертированного индекса и ищет точные совпадения слов запроса со словами документов. Векторные индексы в те времена были не в ходу, а проблема поиска «по смыслу» уже стояла.
Древние решали эту проблему изящно и просто. Для каждого пришедшего на ум слова из нашего корпоративного лексикона они руками перечисляли его синонимы и записывали результат в файлик. Во время обращения в индекс, пользовательский запрос дообогащался синонимами из словаря и полнота выдачи росла. Так было обеспечено базовое качество кандидатогенерации — получения кандидатов, то есть тех документов, которые подходят под текст запроса. Но как из миллионов кандидатов достать топ-10 лучших?
Придумать костыль, на котором можно долго продержаться, тут уже не получится. Приходится прибегать к магии ML
Качество ранжирования
Что такое ранжирование? Это чёрный ящик, который принимает на вход тройку [запрос, документ‑кандидат, пользователь] и превращает её в число, характеризующее «релевантность». По этой релевантности документы сортируются между собой, образуя топ выдачи. Следовательно, секрет успеха ранжирования зарыт в трёх компонентах:
знания модели о входящей тройке, выражаемые в поисковых фичах (или факторах);
качество самой модели, грамотный подбор её гиперпараметров;
качество того, что вы считаете релевантностью, то есть таргетом модели.

Обучение модели и подбор гиперпараметров — скучная часть, описанная миллион раз до меня. Скажу лишь, что мы используем CatBoost в качестве финальной ранжирующей модели, которая на вход получает скоры других моделек и простых факторов.
Что касается таргетов: мы обучаем две CatBoost‑модели на двух таргетах и делаем от них линейную комбинацию.
Первая модель предсказывает длительность пребывания на документе. Время пребывания считаем как время между взаимодействиями с поиском.
Вторая, более важная модель, учится pairwise, выбирая среди пары документов лучший.
Задачи наших пользователей сложны, ответы на некоторые вопросы знают единицы людей во всём мире. Сделать качественную разметку в таких условиях нереально. Асессоры просто не понимают запросы пользователей. Поэтому на данный момент мы обучаемся на собственных поисковых логах.
На сладкое я приберёг поисковые факторы. Обучить хорошую модель на хороших данных‑дело техники. Собрать же хорошие и полные данные — искусство.
Факторы
Во внутреннем поиске суммарно около двух тысяч факторов ранжирования.
На поиске по Вики, например, их 992. Из них 173 — факторы качества документа, 68 — персональные факторы, 5 нейросетевых факторов и 1 персональный нейросетевой. Остальное — факторы классической текстовой релевантности и степени совпадений с разными кусками документа (например, с заголовком).
Наибольшую пользу приносят факторы кликовой популярности документа за несколько недель, эмбеддинговые семантические факторы и факторы персонализации.
Топ нашего feature importance в поиске по Вики
Доля (%) | Текст |
7,3% | Отношение количества кликнувших людей к количеству просмотревших документ людей |
5,2% | Количество кликов в документ |
3,4% | Эмбеддинговая близость запроса к документу |
3,3% | Сколько людей имеют доступ к документу |
3,3% | Фактор текстовой релевантности |
3,2% | Фактор текстовой релевантности |
2,9% | CTR документа |
2,7% | Количество кликнувших пользователей |
2,4% | Фактор текстовой релевантности |
2,2% | Количество просмотров страницы |
1,8% | Персональная DSSM |
1,8% | Стаж задающего запрос сотрудника |
1,5% | Совпадение с заголовком |
1,4% | Фактор текстовой релевантности |
1,1% | Ветка сотрудника |
1,1% | Совпадение с заголовком |
1% | Среднее время нахождения пользователей на документе |
0,9% | Фактор текстовой релевантности |
0,9% | Фактор текстовой релевантности |
0,9% | CTR пользователя на данный документ |
Поведенческий сигнал
Как говорил Лао Цзы, путь в тысячу сэкономленных часов в компании начинается с одного поискового фактора. Честь быть первым поисковым фактором я советую отдать не семантической близости от навороченной модели, а самым банальным кликам из выдачи. Почему?
Их очень просто и дёшево посчитать (при условии, конечно, что у вас настроена хорошая аналитика).
По нашим приборам, именно эти фичи вносят наибольший вклад в ранжирование. Кто лучше пользователей может сказать, нравятся ли им документы или нет?
Имеет смысл считать кликовый сигнал за разные периоды. За год, полгода, месяц, неделю. Эти сигналы несут в себе разную семантику, а в сумме могут показывать динамику интереса к документу.
Например, у документа про раньше популярную, но ставшую deprecated технологию много кликов за последний год. А за прошлую неделю кликов 0.
В то же время для свежего документа про крутую модельку за год кликов гораздо меньше, но за неделю — больше всех.
Разные периоды позволят ловить ажиотаж на новые документы и поднимать их наверх в выдаче здесь и сейчас, не ожидая накопления годовых кликов.
При этом и клики за большой период выкидывать не стоит. Мы живём в условиях дефицита кликового сигнала. Как минимум, потому что количество пользователей интранета ограничено количеством сотрудников компании. Долгосрочные клики в интранете являются стабилизатором, фиксирующим на выдаче документы с устойчивым интересом аудитории. По нашему опыту, оптимальный кликовый сигнал накапливается за месяц. Естественно, в вашей компании это число может быть другим. Всё зависит от ваших масштабов и скорости появления документации.
Важно отметить, что лучше брать сигнал за число дней, кратное 7. В компаниях существует сильная зависимость рабочих процессов от дня недели. Если понедельников в обучающей выборке будет больше, чем пятниц, получим несбалансированные данные, которые не охватывают no release Friday, например.
Манипулировать потоками кликового сигнала можно самыми разными способами, далеко не только за счёт изменения временного периода. Глобальное правило такое: потоки разбиваем для точности и складываем для полноты.
Например, если конкретная группа пользователей делала клик в документацию X много раз, то высока вероятность, что пользователь из этой группы сделает этот клик вновь.
Мы разбили общий поток кликов по группам пользователей. Это снизило полноту покрытия документов кликами, но зато, если клик есть, он точно что‑то значит. Для суммирования кликового сигнала можно использовать хостовые клики: для родительских путей документации суммировать клики их детей.
Одним из самых сильных кликовых сигналов в поиске по Трекеру у нас является количество кликов по очереди тикета. Их гораздо больше, чем кликов в данный конкретный тикет, а потому его покрытие по базе url почти 100%. Формула из него может извлечь, заведён ли тикет в полезной очереди или же очередь нужна только роботам, а пользовательских кликов там нет.
Сильный приём — комбинировать разведение и сведение кликовых потоков. Можно сгруппировать клики по очередям, но разнести клики по группам пользователей. Получается, топ-1 по важности в поиске по Трекеру — фактор наличия кликов от заданной группы в заданную очередь. Пользователи постоянно кликают примерно в одни и те же очереди, соответствующие их рабочему контексту. Чаще всего это их собственная проектная очередь, в которой они ищут свои задачи и опыт предков. Получаются хостово‑персональные факторы.
С кликами появляется небольшой баг: пользователь может решить хакнуть систему и накрутить популярность своей документации. Или просто очень сильно заинтересоваться каким‑то документом, сделав в него миллион кликов. Конечно, на любой запрос накрученный документ в топ-1 появляться не будет (так как у нас более 900 факторов), но картинку исказит. Чтобы предохраниться от таких эффектов, можно считать не только количество кликов, но ещё и количество уникальных пользователей, сделавших клик. По нашему fstr, такой фактор для формулы выходит даже полезнее обычных кликов.
Важно упомянуть про два важных свойства кликового сигнала:
Система становится в некотором смысле самообучаемой. На базе взаимодействий пользователя с ней она корректирует своё поведение.
Замкнутый цикл обратной связи. Если на документ никто никогда не кликал, вероятность попасть в выдачу и получить первые клики мала. Для противодействия этому эффекту необходимо использовать данные о свежести документа.
Если ваш путь в поиск только начинается, вы могли расстроиться. Как собирать клики из поиска, которого нет?
Для старта приемлемой заменой кликам может стать посещение документации: сколько раз и сколько уникальных пользователей открыли страницу с документацией. Такие факторы в нашем ранжировании тоже приносят пользу, иногда даже побеждая клики. Всё‑таки посещений документов больше, чем кликов, так как любой клик ведёт к посещению, но не любое посещение происходит из клика.
Цитирования
Хвалёный page‑rank и основанные на цитированиях факторы у нас тоже используются в ранжировании, но в топ по важности не попадают. Вероятно, это происходит по причине слабой ссылочной связности интранета.
Если на страницу ссылаются много других страниц и она обновлялась в последний месяц, то, скорее всего, это хорошая страница. Но если на страницу не ссылается никто, это не значит, что она плохая. В силу ограничений прав доступа, люди часто перепечатывают кусок цитируемой страницы и сверху докидывают своего содержания. По нашим оценкам, примерно 15% запросов от пользователей достают из индекса документы, содержащие идентичные куски.
В целом, это понятное явление с точки зрения мотивации сотрудника. Зачем указывать ссылки — мы же не диссертацию пишем. Создавая доку, вряд ли я осознанно вношу туда ложь, с которой требуется бороться ссылками на внешние источники. А семантические связи между сущностями вида «родитель — потомок» оформляются в интерфейсе системы документирования или управления задачами.
В отличие от дикого интернета, в интранете относительно ограниченное число источников, большинство из которых поддерживают графовую структуру в себе нативно. Речь не только про связь задач в таск‑трекере — Вики‑документация тоже представляет из себя дерево, где для каждой страницы можно сделать подстраницу. В результате желание ссылаться на доку становится ещё менее выраженным. Если хочется почитать связанные доки — иди на уровень выше по дереву и выбирай что хочешь. Такой шаблон работы со знаниями отлично покрывается поведенческими факторами. Если люди часто ходят в подстраницы кластера, значит кластер хорош и эту хорошесть в себе унаследуют потомки. Плюс, посещения не ломаются правами доступа. Документ можно посетить, только имея к нему доступ.
Ссылки же имеют свойство устаревать.
Представьте, вы в поте лица ищете ту самую страницу, наткнулись на ссылку с подписью «ответы на все вопросы и секреты» на древней Вики от мудрых предков, переходите по ней и получаете 404.
Ссылки в интранете гораздо более статичны, чем посещения. Если посещения при переносе страницы перетекут на новый url почти мгновенно, то ссылки в половине интранета не обновятся никогда. Если в компании вдруг резко изобрели агентские системы и написали про это классную документацию, то все побегут её читать, но далеко не все пойдут про неё писать, да ещё и ссылаясь на неё явно в тексте.
Соответствие запроса документу
База в факторах соответствия документа запросу — классические BM25-фичи по разным кускам документа. Имеет смысл отдельно выделять совпадения именно по заголовку, так как в нём часто находится суть документа. В случае с разными сущностями разбивку можно делать по‑разному.
Например, в Вики‑страницах, кроме заголовка и самого текста особо ничего интересного нет. В тикетах таск‑трекера же можно отдельно выделить комментарии к тикету, которые несут отличный от описания сигнал.
Запросы при этом, благодаря тому самому словарю синонимов от предков, дообогащены и участвуют в подсчёте факторов. Потому факторы несут в себе элемент семантичности.
Но этим ограничиваться мы не стали. Как и в любом уважающем себя поиске мы таки завезли эмбеддинговые фичи. Мы используем пачку специализированных поисковых DSSM, а также миксованные кликово‑эмбеддинговые факторы.
Персональные факторы
Факторы персонализации чаще всего дают сильный эффект, когда они считаются в паре с документом. Например, является ли задающий запрос пользователь автором документа‑кандидата. Подобных эвристик мы придумывали огромное множество до тех пор, пока не решили инкорпорировать знания про соответствие всего контекста пользователя документу‑кандидату в одно число.
Мы обучили DSSM, которой в качестве запросной части вместо запроса подаётся описание профессии пользователя и его положение в оргструктуре, а в документную — заголовок и url документа. Для ML‑инженера такая модель на запрос «модель» будет откликаться на доки про ML‑модельки, а для 3D‑дизайнера на тот же запрос — оценивать документацию про 3D‑модельки.

Неожиданно, что полезными факторами могут быть факторы, использующие информацию только про пользователя, не учитывающие ни текст запроса, ни содержание и качество документа. У нас очень сильно играет роль опыт задающего вопрос сотрудника. Визуально он помогает доставать документы, понятные сотруднику. На запрос про хитрую внутреннюю технологию стажёру поиск даст страницы с введением в тему, а для опытного синьора — документы про рецепты и лайфхаки.
Query‑only факторы
Часть сильных факторов строятся исключительно на базе запроса. Например, классификатор намерения (или интента). Согласно классическому исследованию A taxonomy of web search Андрея Бродера, существуют три мотивации сделать запрос в поисковую систему:
Навигационная — это поиск конкретной страницы. Пользователь знает, что страница существует, скорее всего, он на ней уже бывал. Поиск ему нужен, как отображение связанных со страницей понятий в его голове на реальную ссылку на документ. Клик в таком запросе один, ведущий на тот самый конкретный url. В интранете классическим навигационным запросом может быть ID тикета в таск‑трекере
Информационная — это поиск знаний и ответов на вопросы. Какой‑то конкретный документ запросом не подразумевается. Задача — найти максимальное количество релевантной информации. Пользователь может кликать в разные документы выдачи, переформулировать и уточнять запрос, продвигаясь по исследованию. В интранете таким запросом может быть «как работает api внутреннего поиска». На такие запросы пользователю уместно показывать генеративные ответы, суммаризирующие знания из нескольких документов
Транзакционная — мотивация для совершения действия. В интранете примером может быть запрос «оформить отпуск». Пользователь хочет получить от поиска кнопку. А в идеальном сценарии хочет, чтобы агент оформил отпуск за него
Понимание интента запроса сильно помогает ранжированию. В поиске по Трекеру это топ-12 фактор по fstr CatBoost.
Мы обучили его после внедрения генеративного ответа на выдачу. В одну корзинку положили сессии, которые мы считаем решёнными генеративкой, в другую — сессии, которые решены выдачей. Получаем задачу бинарной классификации. Конечно, в данном случае предсказывается не совсем интент, а полезность генеративки на запрос. Однако постоянный рост качества генеративного ответа приближает показание классификатора к реальному классификатору интента.
Впоследствии такой классификатор интента можно использовать как раз‑таки для направления запроса в генеративку или в агента. На нашей выдаче такой классификатор стоит и даёт экономию GPU и комфорт пользователям. Генеративка вылетает не на все запросы, а только на те, где она уместна.
Инфраструктура
На самом деле для скорости работы поиска мы используем каскад ранжирующих моделей. На этапе кандидатогенерации с помощью обученного методом логистической регрессии полинома за минимум времени среди всех кандидатов мы отсекаем от 36 000 до 172 800 документов, которые попадают на ранжирование. На первой стадии документ ранжируется тем же CatBoost, но порезанным по количеству деревьев. Он не видит часть факторов, его качество ниже, но он быстрый и оставляет после себя от 50 до 100 документов, которые уже ранжируются полным CatBoost.
Вся машинерия расчёта факторов делится между нашим бэкендом и внутренним Яндексовым поисковым движком SaaS (почитать про опыт его использования коллегами из Лавки можно в статье коллег). Задача бэкенда — составить запрос в поисковый движок, прокинув в него знания про пользователя и запрос, получить документы от движка по сгенерированному запросу, смешать документы из разных индексов в одну выдачу и дедуплицировать. Последнее можно воспринимать как отдельную стадию ранжирования, которая оценивает документы не по отдельности, а в совокупности. Да, 5 одинаковых документов могут идеально отвечать на запрос пользователя, но зачем показывать дубли, когда можно показать максимально разнообразный ответ? Тут неявно в тройку [запрос, документ, пользователь] мы добавляем четвёртый элемент — выдачу.
Я вскользь упомянул про смешивание разных источников данных. Физически данные Вики, Трекера и других источников у нас разделены. Это сделано по историческим причинам и из соображений снижения нагрузки на критические индексы, без которых работа в компании остановится. Также у таск‑трекера и Вики есть уникальные относительно друг друга фичи. Например, персональный фактор, является ли задающий запрос, исполнителем тикета. Быть исполнителем Вики нельзя, поэтому там этот фактор не имеет смысла.
Чтобы ранжировать между собой разные сущности, наш CatBoost учится на независимых пространствах факторов, как на одном большущем, в котором сконкатенированы все возможные факторы. При добавлении нового источника, мы генерируем синтетику и добавляем новое пространство факторов к уже существующему. Синтетику можно генерировать, например, из посещений документов.
Очень важно, что поиск относительно легко измерять, а значит можно улучшать. На наших приборах выводятся понятные поисковые метрики средней позиции клика, CTR выдачи, времени между взаимодействиями с поиском и локальные аналоги метрик счастья пользователя из веб‑поиска. С их помощью вектор развития строится предельно ясно.
От синих ссылок к генответу
В 2022 наступил переломный момент появления LLM. Технологию начали применять в поисковых системах, агрегируя готовые ответы из содержимого найденных документов. Так же сделал и наш старший брат в вебе. Перед нами встал новый вызов — повторить успех LLM у себя.

Ключевой суперсилой нашего AI Chat с самого начала стало базовое качество подбора контекста и крутые фичи поиска. В наследство от него генеративка получила навык оценки качества документов, персонализацию и умение фильтровать источники.
Поиск умеет сужаться, например, до поиска только по Вики, или даже у́же — поиска только по Вики, только документов за авторством заданного человека, только в заданном подразделе. В обычных поисковых сценариях эта фича не вполне раскрылась, но в генеративном ответе отыгралась по полной. Благодаря фильтрации создатели различных сервисов интранета Яндекса легко встраивают чат на свои поверхности, делая его узким экспертом по заданной доменной области.
Допустим, наши коллеги разработали крутую внутреннюю админку и хотят разгрузить свой саппорт от однотипных обращений. Они пишут документацию, прикручивают наш чат в свой интерфейс, задают ему фильтр поиска по заданной доке и получают ИИ‑эксперта по своей админке. Заметьте, как здесь решается упомянутая ранее проблема мотивации писать документацию. И также заметьте, что соблазн побеспокоить коллегу в мессенджере снижается. Что легче — переключиться и открыть мессенджер, чтобы дёрнуть чью‑то личку, или ткнуть на кнопку с чатом ровно в том интерфейсе, в котором возникли вопросы?
Если бы мы оказались в параллельной Вселенной без внутреннего поиска и, как это многие делают сегодня, сразу бы бросились делать генеративный пайплайн от начала и до конца, мы бы потеряли возможность на реальных пользователях обкатывать качество самого важного элемента системы. В генеративном ответе топ документов для контекста от пользователя спрятан за ответом LLM. Замерять успешность ответа ИИ‑помощника, а тем более агентских систем сложнее. Делать backpropogation и точно определять, какой именно документ внёс вклад в генерацию — задача тоже нетривиальная.
Банальный тезис, но на практике связка поиск‑генеративка работает в плюс для обеих сторон. LLM дали поиску возможность решить старые архитектурные болячки. Самый горячий пример — кандидатогенерация и работа с синонимами. Классический подход требовал строить громоздкий пайплайн: эмбеддить все документы, складывать их в толстенький HNSW‑индекс, а потом мучительно под танцы с бубном тюнить алгоритм смешивания KNN с полнотекстовым поиском. Или же вообще внедрить что‑то похожее на SPLADE. Сейчас эту боль можно банальным образом хотя бы частично переложить на LLM. В момент запроса, генеративка просто реформулирует запрос пользователя, обогащая его чем‑то новым и превращая в более понятный поиску текст.
Может показаться, что гонять LLM на каждый чих пользователя в выдачу — расточительно. Однако в нашей системе RPS на индексатор на один‑два порядка выше, чем RPS на поиск. При базе в миллиард документов использовать LLM‑реформулятор на чтении дешевле, чем постоянно пересчитывать и обновлять эмбеддинги документов при записи. Вдобавок текстовый выхлоп реформулятора легко интерпретировать и дебажить. Получается понятное разделение ответственности между LLM и поисковым движком.
Помимо оптимизации поиска генеративка поменяла и восприятие пользователей. Долгое время классическая поисковая строка приучала людей ужимать запросы до обрывков ключевых слов. Пользователи не предполагали, что движок поймёт сложный контекст. В чат же люди приносят развернутые человеческие вопросы. По ним можно понять не что они ищут, а что они делают, и предложить им больше опций с помощью того же реформулятора.
Важно, что в формате диалога пользователи толерантны к скорости работы системы. Если в обычном поиске юзер начинает скучать уже через секунду‑две, то в чате пользователи резко ловят дзен и готовы дать модели время на размышления. Это окно задержки развязывает руки и позволяет ставить под капот тяжёлые модели, выжимая максимум качества в дискавери‑сценариях.
Результаты A/B

Внутренний поиск стал крутым не в один день. Каждое его усложнение (в т.ч. внедрение AI Chat) мы доказывали через A/B‑тесты.
Галопом опишу нашу эволюцию за последние несколько лет.
Четыре года назад поиск был хорошим классическим BM25. Он отставал от внешних технологий лет на 10. Не умел даже искать по разным источникам в одной выдаче. Таск‑трекер на одной вкладке, а Вики — на другой. Возникала иллюзия, что примерно любое изменение должно его улучшить. Однако оказалось, что улучшать надёжные, как швейцарские часы, технологии не такая простая задачка.
Первый крупный эксперимент — иллюстрация к вопросу, почему векторный поиск с ранжированием только на семантических эмбеддах не даёт сильного качества. Наша первая попытка затащить нейросетевые модели в ранжирование провалилась. Мы получили сильное падение кликовых метрик и визуальное ухудшение выдачи. Эксперимент заключался в попытке затащить простые вектора с улицы в качестве поисковой фичи. Мы наивно полагали, что любой эмбедд лучше отсутствия эмбедда. По факту же вышло, что новые фичи стали поднимать вверх по ранжированию плохие документы. Вроде и похоже, но не то. Авось не прокатило. Так мы выучили, что эмбедды надо внедрять аккуратно, а модели общих познаний подходит скорее для молодого продукта, когда нет базового качества, или для простого интранета без своего птичьего языка.
Набив шишки, добавили новые специализированные поисковые эмбедды, которые с помощью кликов научили их понимать наш внутренний язык. В этот раз нам удалось получить рост качества в 2% NDCG и топовую по важности фичу. Результат сильный, но далеко не настолько, насколько мы ожидали. Из чего заключили вывод: эмбедды не серебряная пуля. Они вносят заметный вклад, но опираться только на них нельзя.
Гораздо больший эффект на качество ранжирования оказала персонализация. Мы добавили 2–3 десятка сильных персональных факторов, в т.ч. тот самый нейросетевой и получили падение на 4% бескликовых запросов и на 8% увеличение кликов в топ-3 документ. Вывод — персонализация очень нужна пользователям. Люди работают в рамках какого‑то подмножества интранета и очень важно дать модели понимание, что же попадает в это подмножество.
Дошлифовав эмбеддами и персонализацией ранжирование на отдельных источниках, мы решили двинуться дальше и научиться смешивать в выдаче разные поисковые источники и сделать то самое заветное сквозное ранжирование всех основных источников интранета.
Эксперимент на сквозной поиск показал падение перезапросов на 25%, на 8% рост кликов и на 4% падение запросов без кликов. Числа могут не впечатлить, но это самое масштабное изменение во внутреннем поиске за последние годы. Имея сильный baseline, выбить подобные метрики — событие. Вывод такой же, как и в случае с персонализацией, — сквозной поиск очень нужен людям. Если у вас его нет, подумайте о его внедрении.
Следующим шагом новый сквозной поиск мы затащили внутрь AI Chat'а. Поиск в нём был и раньше, но моделька сама решала, какой источник ей приоритетнее. Теперь же ранжирование было отдано целиком на откуп поиску.
Эксперимент показал падение количество сессий с кликами в выдачу на 5%, а количество долгих кликов на 15%. Выводов два. Первый — генеративный ответ — не пустой хайп, а по‑настоящему полезный инструмент. Люди отказываются от привычного способа получения информации в классическом поиске, с которым работали годами, в пользу AI‑чата, если он работает хорошо. Второй — качество поиска прямо влияет на качество генеративного ответа. Поиск — это база. Причём база, влияние которой видно на масштабе всей компании.
Итоги

Наш AI Chat экономит 225 рабочих часов каждый день. Это время команды из 28 разработчиков, которое можно потратить на более интересные задачи. При этом на данный момент AI Chat используют 25% сотрудников компании. Потребление только растёт за счёт подключения технологии во всё новые сервисы. Внутренним поиском в сумме пользуются 85% сотрудников компании. Это 100% сотрудников, у которых к поиску есть доступ. Все разработчики, инженеры, штатные менеджеры используют нас в своей работе. Поиск стал ключевым компонентом многих процессов
Какие выводы можно сделать из нашего опыта?
Инвестиции в поиск — это инвестиции в культуру работы со знаниями. Если знания легко найти, у людей появляется железная мотивация эти знания фиксировать. Почините поиск, и вы почините проблему потери экспертизы.
Многие устали от новостей про ИИ. Все кругом крутят‑вертят промпты, но хочется видеть реальные результаты. Наш опыт утверждает, что в задачах корпоративного интранета LLM — добро. Это не игрушка, а реальный инструмент, который сокращает часы рутинного чтения длинных текстов и берет часть когнитивной нагрузки на себя.
LLM‑генерация и ML‑ранжирование образуют неразрывный симбиоз. Не тратьте время и деньги на дорогие модели, надеясь, что они сами разберутся в помойке ваших данных. Нейросеть хороша настолько, насколько хороши те топ-3 документа, которые вы ей скормили. Инвестируйте в ранжирование, победите проблему Garbage In, и тогда генеративный ИИ принесет вашему бизнесу реальную пользу.
Напоследок отмечу, что внутренний поиск находится в стадии быстрого роста. Каждый день мы тестируем новые гипотезы и запускам A/B. Впереди у нас плотная работа с LLM в ранжировании, с агентским поиском и новыми классными фичами. Надеюсь, мы ещё не раз придём делиться опытом — буду рад пообщаться на эту тему 4 июня на infra.conf'26.
Жду этого и от вас. Расскажите, как устроен корпоративный поиск в вашей компании.
