«Можно обучить вашего бота отвечать по нашему регламенту?» — этот вопрос мы слышим почти от каждого вуза или колледжа после первого демо. Регламент учреждения — это десятки или сотни страниц внутренних правил, и да, мы можем подключить его к боту. Но не просто «скормить в контекст», как многие думают. Расскажем технически — что работает, что нет.
Почему «скормить всё в контекст» не работает
Современные большие языковые модели (GPT‑4, Claude, GigaChat и аналоги) поддерживают контекстное окно от 8 000 до 200 000+ токенов. Логичное предложение: возьмём 200‑страничный регламент вуза (примерно 100 000 токенов), положим целиком в системный промпт, и при каждом вопросе пользователя LLM будет искать ответ.
На практике этот подход проваливается по четырём причинам:
- Стоимость. Каждый запрос с большим контекстом стоит в 100+ раз дороже короткого. Бот, к которому в день обращаются 500 человек, нагенерит счёт за месяц больше, чем подписка на сам сервис.
- Скорость. Обработка 100 K токенов занимает 15–30 секунд. Пользователь ждёт 30 секунд ответа на «когда родительское собрание?» — закроет чат до получения ответа.
- Точность. Несмотря на большое контекстное окно, LLM имеют тенденцию «терять» информацию из середины длинного контекста (это известный эффект lost in the middle). Релевантный параграф из середины документа может быть проигнорирован, даже если он там есть.
- Галлюцинации. На длинных контекстах модели чаще фантазируют — собирают ответ из обрывков разных частей текста, получая результат, которого в исходнике нет.
Что работает: RAG (Retrieval Augmented Generation)
RAG — это паттерн, при котором мы не загружаем весь документ в контекст. Вместо этого мы заранее разбиваем его на фрагменты, индексируем по смыслу, и при каждом вопросе пользователя находим только релевантные фрагменты и подсовываем их LLM.
Схема в трёх блоках:
- Подготовка (один раз). Разбиваем документ на чанки → каждому чанку считаем embedding → складываем в векторную базу.
- Запрос (на каждый вопрос). Получаем вопрос пользователя → считаем его embedding → ищем топ‑5 ближайших чанков в базе.
- Генерация. Передаём в LLM системный промпт + найденные 5 чанков + вопрос → получаем ответ с ссылками на источник.
Шаг 1: правильное чанкование
Самая частая ошибка — разбить документ на чанки по фиксированной длине (например, по 500 слов). Результат: предложения рвутся посередине, абзацы режутся, контекст теряется.
Правильно — резать по смысловым границам:
- По разделам / параграфам. Регламент обычно структурирован: «Глава 1», «Раздел 2», «Пункт 3.4». Эту структуру мы используем как границы чанков.
- С overlap. Соседние чанки перекрываются на 100–200 слов — чтобы пограничные мысли не терялись.
- С контекстной шапкой. К каждому чанку добавляется заголовок раздела/главы, чтобы LLM при ответе понимал, откуда этот фрагмент: «Глава 4, Раздел 2.1: Правила поступления».
Размер чанка тоже важен: слишком маленький — теряем контекст, слишком большой — собираем в ответ мало релевантной информации. Эмпирически работает 500–1500 слов на чанк для типовых регламентов.
Шаг 2: эмбеддинг и индекс
Для каждого чанка мы считаем вектор (embedding) — числовое представление его смысла в N‑мерном пространстве. Похожие по смыслу тексты имеют близкие векторы.
Для русского текста хорошо работают модели типа e5‑mistral‑7b‑embed или multilingual‑e5‑large. У GigaChat (Сбер) есть собственная embeddings‑модель с поддержкой русского, она тоже пригодна.
Векторы складываем в векторную БД (мы используем pgvector — это расширение PostgreSQL, которое позволяет делать nearest‑neighbor поиск прямо в обычной БД). Альтернативы: Qdrant, Milvus, Weaviate — всё это работает.
Шаг 3: поиск + ranking
Когда пользователь задаёт вопрос, мы считаем embedding для его текста и ищем топ‑K чанков с близким вектором (обычно K = 5–10).
Простой косинусный поиск работает базово, но даёт неоптимальный результат: иногда «близкий по словам» чанк не является «близким по смыслу». Поэтому добавляем второй этап — re‑ranking:
- Делаем первичную выборку: 20–30 кандидатов по embedding‑поиску.
- Прогоняем кандидатов через дополнительную модель‑reranker, которая принимает «вопрос + кандидат» и оценивает реальную релевантность.
- Берём топ‑5 после re‑ranking.
Этот двухэтапный подход повышает точность с примерно 70–75 % до 88–93 % в наших измерениях на русских образовательных текстах.
Шаг 4: ответ + ссылки на источник
Теперь у LLM есть короткий промпт: «Вот вопрос: X. Вот несколько фрагментов из регламента: Y1, Y2, Y3. Ответь, используя только их. Если ответа в них нет — скажи об этом честно». Дополнительно мы требуем ссылок на источник в каждом ответе.
Результат для пользователя выглядит так:
- «Заявление подаётся в течение первых 10 дней семестра. Срок рассмотрения — до 5 рабочих дней. Документ нужно сдать в канцелярию, каб. 105».
- «Источник: Регламент учебной деятельности, Глава 3, Раздел 2.1».
Это критично по двум причинам. Первая — пользователь может проверить ответ в исходном документе, если что‑то покажется странным. Вторая — мы сразу ловим галлюцинации: если LLM выдала ответ без ссылки на конкретный пункт, что‑то не так.
Когда бот говорит «я не знаю»
Самая ценная фича системы — это не способность отвечать. Это способность честно отказаться, когда ответа нет.
Если в найденных чанках нет релевантной информации, бот отвечает, не выдумывая: «По регламенту учреждения у меня нет точного ответа на этот вопрос. Уточните, пожалуйста, в учебной части по адресу: каб. 105 или по почте hello@mycampushub.ru».
Это работает за счёт явного промпта «не выдумывай, если ответа нет — скажи». Плюс мы измеряем confidence по найденным чанкам: если ни один из топ‑5 не имеет достаточной близости к вопросу, мы даже не вызываем LLM, а сразу возвращаем fallback.
Реальный пример с вузом
Один из наших клиентов — региональный вуз, 4 500 студентов. Они прислали регламент: 230 страниц, разделы про поступление, академические задолженности, переводы, отчисления, восстановление, стипендии, общежитие, академические отпуска и т. д.
Что мы сделали:
- Разрезали регламент на 412 чанков по структурным границам (главы и параграфы), средний размер чанка — 850 слов.
- Посчитали embeddings, проиндексировали в pgvector.
- Подключили к существующему боту вуза (он уже отвечал на вопросы о расписании).
- Прогнали тесты на наборе из 200 типовых вопросов от студентов и родителей. Точность ответов — 89 %, в 11 % бот отказывался (правильно: вопросов нет в регламенте).
Количество обращений в учебную часть про «как восстановиться», «когда можно перевестись» и подобные регламентные вопросы упало примерно вдвое уже за первый месяц.
Что в итоге
Обучить ИИ‑бота отвечать по большому документу — реально, но это не «положить всё в контекст». Это RAG: чанкование по структуре, embeddings, ранжирование, явные ссылки на источник, fallback на «не знаю».
Технически это не так сложно, как кажется — почти все компоненты есть в виде готовых библиотек. Сложно правильно подобрать параметры для конкретного документа: размер чанка, размер overlap, число K в поиске, температуру LLM, формат промпта.
В CampusHub это часть подключения «под ключ» — мы делаем всю настройку, тестируем на реальных вопросах, доводим до production‑готовности. Если у вашего вуза или колледжа есть большой регламент и хочется, чтобы бот по нему отвечал, — оставьте заявку, обсудим вашу специфику.