Retrievers и сборка RAG-цепочки
Урок соединяет всё в RAG: поиск контекста и генерацию ответа по нему.
Retriever — компонент с единым интерфейсом, который по текстовому запросу возвращает релевантные документы.
Retriever поверх хранилища
Векторное хранилище умеет искать, но в LCEL-цепочку удобнее встраивать Retriever — тонкую обёртку с методом, принимающим запрос и возвращающим документы. Любой VectorStore легко превращается в retriever:
retriever = store.as_retriever(search_kwargs={"k": 4})
docs = retriever.invoke("Что такое индекс?")Полная RAG-цепочка
RAG собирается из знакомых блоков: на вопрос параллельно достаём контекст из retriever и пробрасываем сам вопрос, затем кладём оба в промпт и зовём модель.
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_template(
"Ответь на вопрос, опираясь ТОЛЬКО на контекст.\n"
"Контекст:\n{context}\n\nВопрос: {question}"
)
rag = (
RunnableParallel(context=retriever, question=RunnablePassthrough())
| prompt | model | StrOutputParser()
)
print(rag.invoke("Что такое индекс в базе данных?"))Схема пайплайна
вопрос
├──> retriever ──> релевантные чанки ─┐
└──> passthrough ──> сам вопрос ───────┤
v
prompt(context, question)
v
model
v
ответКак работает под капотом
При invoke("вопрос") RunnableParallel отдаёт строку вопроса сразу двум веткам: retriever кодирует её в вектор, ищет в хранилище и возвращает чанки в context; passthrough кладёт исходный вопрос в question. Получившийся словарь идёт в промпт, который собирает финальный текст с контекстом, затем в модель и парсер. Инструкция «опираясь ТОЛЬКО на контекст» снижает галлюцинации, заземляя ответ на найденных документах.
Частые ошибки
- Не заземлять ответ. Без явного «отвечай только по контексту» модель добавит выдумки.
- Слишком большое
k. Много чанков — больше шума и стоимости, ответ хуже. - Игнорировать пустой результат поиска. Если ничего не нашлось, лучше честно ответить «не знаю», а не выдумывать.
Итог
Retriever— единый интерфейс поиска документов по запросу.- RAG-цепочка собирается из
RunnableParallel(context + question) → prompt → model → parser. - Инструкция «только по контексту» уменьшает галлюцинации.
- Параметр
kрегулирует баланс полноты и шума.