Условие
Нужно ответить на корпоративные вопросы по 10000 PDF документов. Выбор: fine-tune LLM, prompt engineering, RAG. Что и почему?
Решение
Подход
| Prompt eng | RAG | Fine-tuning | |
|---|---|---|---|
| Когда | Простые задачи, мало данных | Большая база знаний, актуальность | Стиль / структура output, domain language |
| Время setup | Часы | Дни | Недели |
| Latency | Низкая | Средняя (+retrieval) | Низкая |
| Cost | Per token | Per token + vector DB | Train cost + serving |
| Update knowledge | Перепиши prompt | Обнови индекс | Перетренируй |
| Hallucinations | Высокие | Снижены (context-grounded) | Без grounding всё ещё высокие |
| Token cost | Низкий | Средний (большой context) | Низкий после train |
Для 10000 PDF — RAG
Знания меняются → RAG. Fine-tuning приведёт к outdated knowledge + dangerous hallucinations.
Architecture
# 1. Chunking
chunks = []
for pdf in pdfs:
text = extract_text(pdf)
chunks += split_into_chunks(text, size=500, overlap=50)
# 2. Embedding
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('intfloat/multilingual-e5-large')
emb = model.encode(chunks, normalize_embeddings=True)
# 3. Vector DB
import qdrant_client
qc = qdrant_client.QdrantClient(":memory:")
qc.create_collection("docs", vectors_config={"size": 1024, "distance": "Cosine"})
qc.upload_collection("docs", vectors=emb, payload=[{"text": c, "pdf": pdf} for c, pdf in zip(chunks, pdf_ids)])
# 4. Retrieve + generate
def answer(q):
q_emb = model.encode([q], normalize_embeddings=True)[0]
hits = qc.search("docs", q_emb, limit=5)
context = "\n".join([h.payload["text"] for h in hits])
prompt = f"""Контекст:\n{context}\n\nВопрос: {q}\nОтвет (на основе контекста):"""
return llm.generate(prompt)Хитрости RAG
- Hybrid search: dense (embedding) + sparse (BM25) → выше recall.
- Re-ranker: после retrieve top-50 → cross-encoder для precise top-5.
- Query expansion: переформулировка запроса для лучшего retrieval.
- Citation в ответе: указываем источник, снижаем hallucinations.
Когда fine-tune
- Нужен особый формат output (JSON, table).
- Domain language (медицинский, юридический).
- Скорость inference критична (нельзя retrieve).
Используйте LoRA / QLoRA: обучаются 0.1-1% параметров → недорого.
Когда чистый prompt
- Простая задача (summarization, classification).
- Малая знание-база (умещается в 100k токенов context).
- Демо / прототип.
Подводные камни
- RAG неудача chunking: слишком большие chunks → плохой retrieval; слишком малые → теряется контекст. 300-800 токенов + 10-15% overlap.
- Embedding model mismatch: multilingual-e5 для русского лучше чем text-embedding-ada-002 в некоторых случаях.
- Fine-tune на 10000 PDF → модель запомнит факты, но обновить нельзя. Все знания будут stale.
- RAG context window: GPT-4o = 128k, но даже 32k снижают качество («lost in the middle»). Re-ranker + top-5 лучше чем top-50 в prompt.
- Hallucinations с context grounding: даже с RAG модель может «улучшать» context. Проверять цитированием.
Эталонный ответ
Для 10k PDF и обновляющейся знание-базы — RAG: embedding + vector DB + retrieve + LLM. Fine-tuning приведёт к stale knowledge. Prompt engineering недостаточно. Хитрости: hybrid search (dense+BM25), re-ranker, citation. Fine-tune через LoRA — только для стилевых задач, не для knowledge.