Серверное оборудование для бизнеса — надёжные решения для любых задач Подробнее →
Статья

RAG на практике: поиск по документам с LLM

RAG (Retrieval-Augmented Generation) — архитектурный паттерн, который решает одну из главных проблем LLM: они не знают о ваших внутренних документах. Вместо дорогостоящего fine-tuning мы учим модель искать нужную информацию в базе знаний прямо во время запроса.

Что такое RAG и зачем он нужен

Классический LLM отвечает только на основе знаний, заложенных при обучении. RAG добавляет этап retrieval: перед генерацией ответа система ищет релевантные фрагменты из вашей базы документов и передаёт их в контекст модели.

Схема работы:

  • Пользователь задаёт вопрос
  • Вопрос преобразуется в embedding (векторное представление)
  • В векторной базе данных ищутся похожие фрагменты документов
  • Найденные фрагменты + вопрос передаются в LLM
  • LLM генерирует ответ на основе найденного контекста

Embeddings: превращаем текст в векторы

Embedding — числовой вектор, кодирующий семантический смысл текста. Похожие по смыслу тексты имеют близкие векторы в многомерном пространстве.

Популярные модели для русского языка:

  • intfloat/multilingual-e5-large — хороший баланс качества и скорости
  • deepvk/USER-bge-m3 — одна из лучших для русского
  • text-embedding-3-small от OpenAI — через API
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('intfloat/multilingual-e5-large')
embeddings = model.encode(['Как настроить NFS сервер?'])

Векторные базы данных: Chroma vs Milvus

Chroma — простой старт, идеален для прототипов и небольших коллекций:

import chromadb

client = chromadb.PersistentClient(path='./chroma_db')
collection = client.get_or_create_collection('docs')

collection.add(
    documents=['текст документа'],
    embeddings=[[0.1, 0.2, ...]],
    ids=['doc_001']
)

results = collection.query(query_embeddings=[query_vec], n_results=5)

Milvus — production-решение для больших объёмов (миллионы векторов), поддерживает горизонтальное масштабирование, несколько индексов (HNSW, IVF_FLAT), фильтрацию по метаданным.

Chunking: стратегии разбивки документов

От качества разбивки документов зависит 50% качества всей RAG-системы:

  • Fixed-size chunking: разбивка по N символов с overlap. Просто, но теряет смысловые границы
  • Sentence splitting: разбивка по предложениям. Лучше сохраняет контекст
  • Recursive character splitting: иерархическое разбивание по `



.` — рекомендуется как baseline

  • Semantic chunking: разбивка по изменению embedding — дорого, но качественно
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=64,
    separators=['

', '
', '. ', ' ']
)
chunks = splitter.split_text(document_text)

LangChain pipeline

Полный RAG pipeline на LangChain:

from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import Ollama

vectorstore = Chroma(persist_directory='./chroma_db',
                     embedding_function=embeddings)
retriever = vectorstore.as_retriever(search_kwargs={'k': 5})

llm = Ollama(model='llama3')
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=retriever,
    return_source_documents=True
)

result = qa_chain('Как настроить Prometheus alerting?')

Оценка качества RAG

Метрики для оценки системы:

  • Faithfulness — насколько ответ соответствует найденным документам (не галлюцинирует)
  • Answer Relevancy — насколько ответ релевантен вопросу
  • Context Recall — все ли нужные документы были найдены

Фреймворк RAGAS автоматизирует оценку:

pip install ragas

Деплой через FastAPI

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Query(BaseModel):
    question: str

@app.post('/ask')
async def ask(query: Query):
    result = qa_chain(query.question)
    return {
        'answer': result['result'],
        'sources': [d.metadata for d in result['source_documents']]
    }

RAG — не серебряная пуля, но при правильной настройке chunking и embedding-модели даёт впечатляющие результаты для корпоративного поиска по документам.

2 Ответа

  1. Попробовал USER-bge-m3 для русскоязычной базы знаний — качество заметно лучше, чем multilingual-e5-large, особенно на технических текстах. Правда, и памяти кушает больше.

  1. Хорошая статья! Единственное — RAGAS для оценки требует внешний LLM-судью, что добавляет стоимость и задержку. Для быстрой оценки качества retrieval можно просто смотреть на cosine similarity найденных чанков.