Общая картина · 01 / 12

RAG: найти опору для ответа

Когда ответ должен опираться на загруженный документ, сначала находят относящийся к вопросу фрагмент. context-retriever выполняет этот поиск и возвращает текст с источником.

Заранее · document-ingestor

Готовит материал

Делит документ на чанки и сохраняет текст, векторы и связь с файлом.

При вопросе · context-retriever

Ищет фрагменты

Сопоставляет вопрос с чанками в общей БД и возвращает подходящие.

После поиска · приложение

Формирует ответ

Может передать найденный текст языковой модели вместе с вопросом.

подготовка поиск формирование ответа
Перейти к примеру ↓

Сквозной пример · 02 / 12

Один вопрос к документу

Вымышленное «Положение о командировках» уже обработано ingestor. Вопрос звучит иначе, чем нужный абзац.

ВопросКогда компенсируют дорогу после поездки?
Нужный чанк«Компания возмещает расходы на проезд по подтверждающим документам после возвращения сотрудника».
В результате важны и сам отрывок, и источник: Положение о командировках.pdf.

Идея поиска · 03 / 12

Три способа найти нужный чанк

Вопрос можно сопоставить с сохранёнными фрагментами по смыслу, по словам или обоими способами вместе.

semantic · смысл

Близкие векторы

Помогает связать «компенсируют дорогу» с отрывком про «возмещение проезда».

fulltext · слова

Совпавшие лексемы

Ищет по словам и их формам в русском тексте; вопрос с «проездом» найдёт соответствующий чанк.

hybrid · объединение

Два списка кандидатов

Учитывает место чанка в смысловой и словесной выдаче, затем формирует общий порядок.

Выбор задаёт search_type. В веб-форме заранее выбран hybrid, а запрос HTTP API без этого поля использует semantic.

Связь сервисов · 04 / 12

Где выполняется поиск

Ingestor сохраняет чанки в PostgreSQL. Retriever ищет в этой БД; для semantic и hybrid он через NATS получает вектор вопроса от ingestor.

Подготовка документов и поиск в общей PostgreSQL Клиент передаёт файл document-ingestor, который записывает чанки в PostgreSQL. Клиент передаёт вопрос context-retriever, который выполняет поиск по этой базе. Для смыслового и гибридного поиска retriever через NATS запрашивает у ingestor вектор вопроса. Клиент файл Клиент вопрос document-ingestor подготовка чанков context-retriever поиск по чанкам NATS запрос ↔ вектор PostgreSQL общая база данных documents chunks векторы · текст запись SQL-поиск
ПодготовкаКлиент → document-ingestor → PostgreSQL: текст и векторы чанков.
ПоискКлиент → context-retriever ↔ PostgreSQL: запросы по чанкам и результаты.
Вектор вопросаRetriever ↔ NATS ↔ ingestor в режимах semantic и hybrid.
Одна БД хранит подготовленные чанки; NATS передаёт вектор вопроса, а retriever выполняет SQL-поиск.
ingestor retriever обмен сообщениями хранилище

Смысловой путь · 05 / 12

Вектор вопроса создаёт ingestor

Чтобы сравнить вопрос с векторами чанков, retriever отправляет его текст в document-ingestor через NATS и получает эмбеддинг в ответ.

Вопрос

Retriever принимает текст и выбранный режим поиска.

NATS

Запрос идёт по теме vectorize.request с адресом для ответа.

Ingestor

Считает вектор через настроенный механизм эмбеддингов.

Ответ

Вектор возвращается retriever и участвует в SQL-поиске.

Внешний API Ollama — предпочтительный вариант; встроенный Candle — альтернатива. Текущий манифест выбирает Candle. Для вопроса и чанков нужна совместимая модель.
В коде: src/context_search.rb#vectorize_query, document-ingestor/src/config.ru · Как работает запрос–ответ NATS

Поиск в PostgreSQL · 06 / 12

Смысловой поиск по векторам

Вектор вопроса сравнивается с векторами сохранённых чанков. Ближайшие по косинусному расстоянию фрагменты становятся кандидатами для результата.

Вопрос

«Когда компенсируют дорогу?» превращается в набор чисел той же размерности, что и сохранённые векторы.

Условный вектор[0.12, −0.04, …]

Чанки в БД

PostgreSQL упорядочивает фрагменты по расстоянию от вектора вопроса.

01 · Возмещение проезда02 · Отчёт после поездки03 · Оформление билетов
pgvector: оператор <=> означает косинусное расстояние; для ответа сервис вычисляет similarity = 1 − distance.
В коде: Sequel-запрос src/models/chunk.rb#search_similar · Операторы pgvector

Поиск в PostgreSQL · 07 / 12

Полнотекстовый поиск по словам

PostgreSQL хранит поисковое представление текста каждого чанка. Вопрос разбирается на русские лексемы, после чего сервис выбирает совпавшие фрагменты.

Запрос

«Возмещают проезд?»

Слова нормализуются с русской конфигурацией PostgreSQL.

Условие

Хотя бы одно слово

Лексемы соединяются оператором «или»; порядок слов не требуется.

Результат

Ранжирование

ts_rank_cd ставит выше более подходящие совпадения в сохранённых чанках.

content_tsv @@ to_tsquery('russian', …) — проверка совпадения. В этом сервисе fulltext не означает поиск точной фразы.
В коде: src/models/chunk.rb#search_fulltext, document-ingestor/src/models/chunk.rb · Полнотекстовый поиск PostgreSQL

Совмещение результатов · 08 / 12

Гибридный поиск объединяет два списка

Смысловой и полнотекстовый поиск независимо выбирают кандидатов. Метод RRF повышает чанки, которые стоят высоко в обоих списках.

Смысловой список

Близость векторов

1 · Возмещение проезда2 · Отчёт о поездке
Словесный список

Совпадение лексем

1 · Билеты и проезд2 · Возмещение проезда
Общий порядок

RRF

1 · Возмещение проезда2 · Билеты и проезд
Вклад каждого списка: 1 / (k + место). В коде k = 60, исходно берётся до 20 кандидатов каждого вида; отсутствующий в списке чанк получает вклад 0.

Контекст результата · 09 / 12

Поиск добавляет соседние чанки

Найденный чанк может обрываться посреди правила. После смыслового или гибридного поиска сервис проверяет соседние фрагменты того же документа и при близком содержании добавляет их.

Найденный чанк и близкие соседи в одном документе В документе подряд расположены чанки 4, 5 и 6. Поиск нашёл чанк 5. Сервис может добавить чанк 4 или 6, если сосед близок по вектору к предыдущему фрагменту цепочки. Чанк 4 условие возмещения Чанк 5 · найден расходы на проезд Чанк 6 подтверждающие документы один документ · соседние номера · проверка близости
Чанк 4 · условие возмещения
Чанк 5 · найден по вопросу
Чанк 6 · подтверждающие документы
Соседи нужны, чтобы условие и продолжение мысли не потерялись при разбиении исходного текста. Их добавление зависит от векторной близости.
найденный чанк возможный сосед проверка соседства

Интерфейсы · 10 / 12

Как обратиться к поиску

Веб-страница, HTTP-клиент, ассистент и другой сервис могут запустить одну и ту же логику ContextSearch.search через разные входы.

HTTP и веб-форма

POST /api/search

Sinatra принимает вопрос и параметры, возвращает JSON с чанками. Главная страница вызывает этот маршрут.

Инструмент ассистента

MCP · context_search

StackServiceBase открывает поиск клиенту MCP как инструмент с параметрами вопроса.

Обмен сервисов

NATS · context.search

Принимает запрос по теме и отправляет результат по адресу ответа.

POST /api/vectorize лишь проверяет получение вектора через ingestor; сам поиск чанков выполняет POST /api/search или соответствующий MCP/NATS-вызов.

Данные ответа · 11 / 12

Ответ содержит текст и источник

Результат содержит текст чанка, сведения о документе и оценку для выбранного режима. Ниже — сокращённый ответ на вопрос из примера.

{
  "query": "Когда компенсируют дорогу?",
  "search_type": "hybrid",
  "results_count": 1,
  "results": [{
    "content": "Компания возмещает расходы на проезд...",
    "score": 0.0325,
    "document": { "file_name": "Положение о командировках.pdf" }
  }]
}
Найденный фрагмент«Компания возмещает расходы на проезд…»
ИсточникПоложение о командировках.pdf
Оценкаscore: 0.0325 · условное значение для hybrid
В полном ответе есть chunk_id, номер чанка, метаданные и, когда доступны, подробные оценки scores. Для hybrid добавляется search_metadata.
В коде: src/context_search.rb#format_results · Описание полей ответа (на URL сервиса)

Условия работы · 12 / 12

Что нужно для поиска

Retriever работает с чанками, уже подготовленными ingestor. Все режимы обращаются к PostgreSQL; смысловой и гибридный дополнительно запрашивают вектор вопроса.

Данные

Готовые чанки

Для демонстрации дождитесь статуса completed у загруженного документа.

Все режимы

PostgreSQL

Сервис читает текст, векторы, поисковое поле и сведения об исходном файле.

semantic · hybrid

NATS и ingestor

Нужны для векторизации нового вопроса; fulltext обходится без этого шага.

HTTP API · спецификация на адресе сервиса Презентация подготовки: GET /presentation на адресе ingestor