Skip to content

Как построить RAG чат-бот

Коротко:

RAG chat-bot за 30 минут: (1) Chunk документы на 500-1000 токенов, (2) Embed через OpenAI text-embedding-3-small ($0.02/1M), (3) Store в Qdrant (Rust open-source), (4) User query → embed → similaritySearch top-5 chunks, (5) Inject в prompt → Claude/GPT-5 generates answer with sources. Stack: Node.js + LangChain.js + Qdrant. Cost: ~$0.001 за query.

Ниже: пошаговая инструкция, рабочие примеры, типичные ошибки, FAQ.

Попробовать бесплатно →

Пошаговая настройка

  1. Установите Qdrant: docker run -p 6333:6333 qdrant/qdrant
  2. Chunk docs: recursive text splitter с overlap 100 токенов
  3. Generate embeddings через OpenAI API (batch 100 docs за запрос)
  4. Upsert в Qdrant collection с payload (source URL, title)
  5. Query pipeline: user input → embed → Qdrant search top-5 → format context
  6. LLM call с system prompt: "Отвечай только из context, укажи sources"
  7. UI: streaming response для UX, show citations в footnotes

Рабочие примеры

СценарийКонфиг
LangChain.js full pipelineimport { QdrantVectorStore } from '@langchain/qdrant'; import { OpenAIEmbeddings } from '@langchain/openai'; import { ChatOpenAI } from '@langchain/openai'; const store = await QdrantVectorStore.fromDocuments( chunks, new OpenAIEmbeddings(), { url: 'http://qdrant:6333', collectionName: 'docs' } ); const docs = await store.similaritySearch(query, 5); const llm = new ChatOpenAI({ model: 'gpt-5' }); const answer = await llm.invoke([ { role: 'system', content: `Context: ${docs.join('\n')}` }, { role: 'user', content: query } ]);
Qdrant HNSW tuningPUT /collections/docs {"vectors": {"size": 1536, "distance": "Cosine"}, "hnsw_config": {"m": 16, "ef_construct": 100}}
Python (LlamaIndex)from llama_index.core import VectorStoreIndex, SimpleDirectoryReader docs = SimpleDirectoryReader('./docs').load_data() index = VectorStoreIndex.from_documents(docs) query_engine = index.as_query_engine() response = query_engine.query('Your question')
Chunking strategyfrom langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=800, chunk_overlap=100, separators=['\n\n', '\n', '.', ' '] )
Hybrid search (dense + sparse)# Qdrant: create named vectors (dense + sparse BM25) # Then batch search с weight

Типичные ошибки

  • Chunks too small → lose context. Too large → cosine dilution. 500-1000 токенов sweet spot
  • Not using overlap between chunks — info на boundary теряется. Overlap 10-20% (100-200 токенов)
  • Вектор DB без filter по source/date → irrelevant matches. Используйте metadata filter
  • Embedding model mismatch: embedded с text-embedding-3-small, query с text-embedding-3-large — не сработает
  • Hallucinations не исчезают полностью — add "Если context не содержит ответа, скажи Не знаю"

Больше по теме

Часто задаваемые вопросы

Сколько documents нужно?

100 небольших docs уже работают. 10k+ — нужна rerank для quality. 100k+ — sharding vector DB, hybrid search.

Cost?

Embeddings: $0.02/1M токенов. LLM call: $0.15-15/1M. Для 1k queries/день ~$0.50-5.

Лучший LLM для RAG?

Claude Opus 4.7 — лучший для long context. GPT-5 — balanced. Gemini 2.5 — 2M context. Llama 3 70B self-host — free.

Как мониторить RAG quality?

Ragas (Python) measures context_precision, context_recall, answer_relevancy. Set thresholds в CI.