RAG нужен, когда ИИ-агент должен отвечать не “из головы модели”, а по вашим документам: базе знаний, инструкциям, регламентам, коммерческим условиям, FAQ, страницам сайта или внутренней вики. В этой инструкции соберем понятную схему: документы превращаются в фрагменты, фрагменты получают embeddings, сохраняются в векторную базу, а агент перед ответом ищет релевантный контекст и ссылается на найденные источники.
Короткая версия: подготовьте документы, нарежьте их на чанки, создайте embeddings, сохраните в vector database, сделайте retriever, подключите retriever к агенту как инструмент и запретите отвечать без найденного контекста.
Что мы собираем
На выходе получится ИИ-агент, который принимает вопрос пользователя, ищет похожие фрагменты в базе знаний, передает найденный контекст в LLM и формирует ответ с опорой на документы. Это не замена полноценной enterprise-системе поиска, а рабочий скелет, который можно развить до поддержки сайта, CRM, Notion, Google Drive, PDF, help center или внутренней базы регламентов.
- Документы лежат в отдельном источнике: папка, CMS, база данных, Google Drive, Notion или help center.
- Индексатор чистит текст, делит его на чанки и сохраняет метаданные: название, URL, раздел, дата обновления.
- Embedding-модель превращает каждый чанк в вектор.
- Qdrant, Chroma, Pinecone или Weaviate хранят векторы и payload с исходными данными.
- Retriever ищет 3-8 самых подходящих фрагментов под вопрос пользователя.
- ИИ-агент использует найденные фрагменты как инструмент, а не как единственный источник “магии”.
Как работает RAG в агенте
RAG расшифровывается как Retrieval-Augmented Generation: генерация с дополнением через поиск. В обычном чате модель отвечает по обученным знаниям и текущему промпту. В RAG-сценарии перед генерацией появляется шаг retrieval: система ищет релевантные фрагменты в вашей базе и добавляет их в контекст ответа.
- Ingestion: загрузка документов из выбранных источников.
- Chunking: деление текста на небольшие смысловые фрагменты.
- Embedding: превращение текста в числовые векторы.
- Indexing: сохранение векторов и метаданных в базе.
- Retrieval: поиск похожих фрагментов по вопросу.
- Generation: ответ модели с учетом найденного контекста.
Что понадобится
- Набор документов, по которым агент должен отвечать.
- LLM для финального ответа: облачная или локальная.
- Embedding-модель: отдельная модель для превращения текста в векторы.
- Векторная база: для старта подойдет Qdrant, Chroma или встроенное хранилище фреймворка.
- Фреймворк или builder: LlamaIndex, LangGraph, Flowise, n8n или собственный код.
- Тестовый список вопросов, по которым можно понять, стал ли поиск полезным.
Шаг 1. Определите границы базы знаний
Не начинайте с загрузки “всего подряд”. Сначала опишите, на какие вопросы агент должен отвечать, а на какие нет. Например: агент поддержки отвечает по тарифам, настройкам и типовым ошибкам, но не консультирует по юридическим вопросам и не обещает индивидуальные скидки.
- Составьте 20-30 реальных вопросов пользователей.
- Отметьте, какие документы должны покрывать каждый вопрос.
- Уберите устаревшие инструкции, дубли и черновики.
- Заранее решите, что агент будет делать, если ответа в базе нет.
Шаг 2. Подготовьте документы
Качество RAG почти всегда начинается с качества текста. Если в документах есть мусорная навигация, повторяющиеся футеры, старые цены, HTML-обрывки и противоречивые правила, агент будет тащить это в ответы. Лучше потратить время на чистку корпуса, чем потом лечить галлюцинации промптом.
- Оставьте заголовки, основной текст, таблицы и важные списки.
- Сохраните URL или путь к исходнику в metadata.
- Для PDF проверьте, что текст извлекается корректно, а не превращается в набор обрывков.
- Разделите разные типы знаний: документация, FAQ, политика, тарифы, внутренние регламенты.
Шаг 3. Разбейте текст на чанки
Чанк - это небольшой фрагмент документа, который будет найден поиском и передан модели. Слишком большие чанки засоряют контекст, слишком маленькие теряют смысл. Для большинства текстовых баз можно начать с 500-900 токенов на чанк и небольшого overlap между соседними фрагментами.
- Делите по смысловым заголовкам, а не строго каждые N символов.
- Добавляйте overlap, чтобы важная мысль не разрывалась на границе чанков.
- В metadata храните title, section, source_url, updated_at и тип документа.
- Не смешивайте в одном чанке разные темы: тарифы отдельно, установка отдельно, ограничения отдельно.
Шаг 4. Создайте embeddings
Embedding-модель превращает текст в вектор: список чисел, по которому можно искать смысловую близость. Важно использовать одну и ту же embedding-модель для индексации документов и для пользовательских запросов. Если поменяли модель, индекс лучше пересобрать.
# Упрощенная идея процесса
documents = load_documents("knowledge_base/")
chunks = split_into_chunks(documents, chunk_size=700, overlap=100)
vectors = embedding_model.embed([chunk.text for chunk in chunks])
vector_database.upsert(chunks, vectors, metadata=True)
Для русскоязычной базы выбирайте embedding-модель, которая хорошо работает с русским языком. Если база смешанная, проверьте качество на русских и английских вопросах отдельно.
Шаг 5. Сохраните индекс в векторную базу
Векторная база хранит не только embeddings, но и полезный payload: текст чанка, ссылку на источник, раздел, тип документа и дату обновления. Это нужно, чтобы агент мог не просто “найти похожее”, а вернуть человеку проверяемый ответ со ссылкой на источник.
- Для локального прототипа можно начать с Chroma или локального Qdrant.
- Для production чаще смотрят на Qdrant, Pinecone, Weaviate или управляемое хранилище в выбранной платформе.
- Включите фильтры по типу документа, языку, продукту, дате и правам доступа, если база не публичная.
- Не храните секреты и персональные данные без отдельной политики доступа.
Шаг 6. Соберите retriever
Retriever получает вопрос пользователя, делает embedding запроса и возвращает несколько наиболее похожих фрагментов. На старте достаточно top_k от 3 до 8. Если ответ получается поверхностным, увеличивайте top_k осторожно: слишком много фрагментов может запутать модель.
query = "Как обновить локальную модель?"
query_vector = embedding_model.embed(query)
results = vector_database.search(query_vector, top_k=5)
context = format_context(results)
После первого поиска добавьте reranking, если база большая или фрагменты часто похожи друг на друга. Reranker перечитывает найденные кандидаты и переставляет их по релевантности уже точнее, чем простой vector search.
Шаг 7. Подключите retriever к агенту как инструмент
В агентной архитектуре поиск по базе лучше оформлять как отдельный tool: например, search_knowledge_base. Тогда агент сможет сам решить, когда искать информацию, а когда отвечать без обращения к базе, если вопрос не требует документов.
- Название инструмента должно быть конкретным: search_docs, search_tariffs, search_support_kb.
- Описание инструмента должно объяснять, когда его использовать.
- Результат инструмента должен возвращать не только текст, но и source_url, title, section.
- Для важных сценариев лучше заставить агента вызывать поиск перед каждым фактическим ответом.
Шаг 8. Напишите системный промпт
Промпт должен не вдохновлять агента, а задавать правила работы с базой знаний. Главное правило: если в найденном контексте нет ответа, агент честно говорит, что не нашел подтверждения, и предлагает уточнить вопрос или обратиться к человеку.
Ты отвечаешь только по найденным фрагментам базы знаний.
Если контекст не содержит ответа, скажи: "Я не нашел подтвержденного ответа в базе знаний".
Не придумывай цены, сроки, ограничения и юридические условия.
В конце ответа укажи источники: название документа и ссылку, если она есть.
Шаг 9. Показывайте источники
Ответ без источников сложно проверять. Даже если интерфейс не показывает сырые фрагменты, сохраните source_url и title в ответе. Для внутреннего агента можно показывать “Документация / Раздел / Дата обновления”, для публичного сайта - ссылки на страницы справки или статьи.
- Показывайте 1-3 источника, которые реально использовались.
- Не подставляйте источники постфактум: они должны приходить из retriever.
- Отдельно логируйте случаи, когда агент ответил без найденного контекста.
- Следите, чтобы пользователь не видел документы, к которым у него нет прав.
Шаг 10. Проверьте на контрольных вопросах
Перед запуском соберите набор “золотых” вопросов: частые вопросы пользователей, спорные формулировки, устаревшие темы, вопросы с отрицательным ответом и запросы вне области базы знаний. Прогоняйте их после каждой пересборки индекса.
- Ответ найден и соответствует документу.
- Источник действительно содержит подтверждение ответа.
- Агент не придумывает информацию, когда в базе ничего нет.
- Агент не смешивает старую и новую версию правил.
- Вопросы с разными формулировками приводят к одинаково полезному ответу.
Шаг 11. Настройте обновление базы
RAG быстро устаревает, если индекс не обновляется вместе с документами. Для статей сайта можно пересобирать индекс после публикации. Для базы поддержки - по расписанию или по webhook из CMS. Для критичных данных лучше делать инкрементальное обновление: изменился документ - пересобрались только его чанки.
- Храните doc_id и chunk_id, чтобы обновлять конкретные фрагменты.
- Удаляйте старые чанки при изменении документа.
- Логируйте дату последней индексации.
- Раз в неделю проверяйте вопросы, по которым агент не нашел ответ.
Типовые ошибки
- Загрузить в базу все подряд и ждать точных ответов.
- Не сохранять ссылки на источники и потом не понимать, откуда агент взял ответ.
- Использовать разные embedding-модели для индекса и запроса.
- Давать агенту отвечать по памяти модели, когда нужен ответ по документам.
- Не проверять русскоязычные запросы, если embedding-модель в основном обучена на английском.
- Не учитывать права доступа: внутренний документ может всплыть в публичном ответе.
Мини-чеклист запуска
- Есть список вопросов, которые агент должен закрывать.
- Документы очищены от дублей, мусора и устаревших правил.
- Каждый чанк хранит source_url, title, section и updated_at.
- Embedding-модель одинаковая для индекса и пользовательского запроса.
- Retriever возвращает релевантные фрагменты на контрольных вопросах.
- Промпт запрещает придумывать ответ без найденного контекста.
- Ответы показывают источники.
- Есть процесс обновления индекса после изменения документов.
Частые вопросы
RAG заменяет fine-tuning?
Обычно нет. RAG лучше подходит для актуальных знаний, документов, справки, цен, регламентов и источников, которые часто меняются. Fine-tuning полезнее для стиля, формата ответа или устойчивого поведения модели, но не для постоянного обновления базы фактов.
Можно ли сделать RAG без векторной базы?
Для маленькой базы можно начать с встроенного in-memory индекса или обычного полнотекстового поиска. Но как только документов становится больше, нужны обновления, фильтры, метаданные и стабильная скорость, удобнее использовать vector database.
Что выбрать для старта: Qdrant, Chroma или Pinecone?
Для локального прототипа удобны Chroma или локальный Qdrant. Для проекта, где важны фильтры, payload, масштабирование и понятная эксплуатация, часто выбирают Qdrant или managed-сервис вроде Pinecone. Выбор зависит от инфраструктуры и требований к данным.
Почему агент все равно ошибается, если есть RAG?
RAG не гарантирует истину автоматически. Ошибки появляются из-за плохих документов, неверного chunking, слабой embedding-модели, неправильного top_k, отсутствия reranking или слишком свободного промпта. Поэтому RAG нужно тестировать как отдельную систему поиска, а не только как чат.
Нужно ли показывать пользователю источники?
Да, если речь идет о поддержке, бизнес-процессах, документации или обучающих материалах. Источники помогают проверить ответ, найти оригинальный документ и быстрее исправить проблему, если агент использовал не тот фрагмент.