708 lines
66 KiB
Markdown
708 lines
66 KiB
Markdown
# ГЛАВА 12. RAG: КОГДА МОДЕЛИ НЕ ХВАТАЕТ СОБСТВЕННЫХ ЗНАНИЙ
|
||
|
||
---
|
||
|
||
У каждого эксперта есть предел. Он может знать всё о гражданском праве — но не помнить конкретный пункт из приложения к договору, подписанному вчера. Он может блестяще рассуждать об архитектуре ПО — но не знать, что ваша команда три дня назад перешла на новый API. Знания, вшитые в голову (или в веса модели), — это **параметрическая память**. Она мощна, но у неё есть дата отсечения (knowledge cutoff) и физический предел — нельзя запомнить всё.
|
||
|
||
Параметрическая память LLM — это то, что модель «выучила» за время тренировки. После деплоя она статична. Новый регламент компании, свежий баг-репорт, обновлённый прайс-лист — модель о них не знает, пока вы не сообщите ей явно.
|
||
|
||
Наивное решение — засунуть всё в context window. Как мы разобрали в [Главе 5](05_long_context.md), это путь с квадратичной стоимостью, деградацией качества (Lost in the Middle) и растущей латенси. Запихнуть 500 документов в контекст — это дорого, медленно и ненадёжно.
|
||
|
||
**RAG (Retrieval-Augmented Generation)** — альтернативная стратегия: вместо того чтобы давать модели *всё*, дать ей *только то, что нужно*. Библиотекарь не читает все книги в библиотеке перед каждым ответом — он знает, где искать, находит нужный том, открывает нужную страницу и цитирует. RAG превращает LLM из эрудита, ограниченного собственной памятью, в исследователя с доступом к актуальной базе знаний.
|
||
|
||
Lewis et al. (2020) формализовали эту идею в рамках NeurIPS: модель, которая *сначала* извлекает релевантные документы, *а потом* генерирует ответ с опорой на них, — превосходит чисто параметрические модели на knowledge-intensive задачах. С тех пор RAG стал одним из базовых паттернов production-систем на LLM.
|
||
|
||
---
|
||
|
||
## 12.1. Почему context stuffing не масштабируется
|
||
|
||
Казалось бы, зачем возиться с retrieval, если у Claude Opus 4.6 контекст 1M токенов? Три причины.
|
||
|
||
**Стоимость.** Даже с оптимизациями (Flash Attention (Dao et al., 2022), KV-кэш, PagedAttention (Kwon et al., 2023)), inference стоимость растёт с длиной контекста. Отправить 200K токенов в каждый вызов API — это десятки центов за запрос. При 1000 запросов в день расходы становятся значительными.
|
||
|
||
**Качество.** Lost in the Middle (Liu et al., 2023): релевантная информация, помещённая в середину длинного контекста, обрабатывается хуже, чем та же информация в начале или в конце. Модель «видит» длинный контекст, но attention-веса распределяются неравномерно. Подробный разбор — в [Главе 5, раздел 5.3](05_long_context.md).
|
||
|
||
**Латенси.** Time-to-first-token растёт с длиной входа. Для интерактивных приложений (чат, поиск, автокомплит) задержка в 5–10 секунд на prefill — неприемлема.
|
||
|
||
RAG решает все три проблемы: вместо того чтобы скармливать модели всю базу знаний, мы извлекаем 5–20 релевантных фрагментов и подаём только их. Контекст остаётся коротким, стоимость — низкой, качество — высоким.
|
||
|
||
| Стратегия | Стоимость за запрос | Латенси | Качество на 500 документах |
|
||
|-----------|--------------------|---------|-----------------------------|
|
||
| Context stuffing (все документы) | $$$ | Высокая (секунды на prefill) | Деградирует (Lost in the Middle) |
|
||
| RAG (top-10 чанков) | $ | Низкая (~200 мс retrieval + стандартный inference) | Стабильное (фокус на релевантном) |
|
||
| Fine-tuning | Амортизировано | Быстрая (нет retrieval) | Хорошее для узкой области, не обновляется |
|
||
|
||
---
|
||
|
||
## 12.2. Анатомия RAG-пайплайна
|
||
|
||
Стандартный RAG-пайплайн — это конвейер из шести этапов. Каждый можно настраивать и заменять независимо:
|
||
|
||
```
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│ Документы │ ─→ │ Чанкинг │ ─→ │ Embedding │
|
||
│ (корпус) │ │ (нарезка) │ │ (векторы) │
|
||
└─────────────┘ └─────────────┘ └──────┬──────┘
|
||
│
|
||
▼
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||
│ Генерация │ ←─ │ Reranking │ ←─ │ Retrieval │
|
||
│ (LLM) │ │ (пересорт) │ │ (поиск) │
|
||
└─────────────┘ └─────────────┘ └─────────────┘
|
||
```
|
||
|
||
**1. Чанкинг** — нарезка документов на фрагменты фиксированного или переменного размера.
|
||
**2. Embedding** — превращение каждого фрагмента в вектор в семантическом пространстве (см. [Главу 1](01_tokens_vectors_and_semantic_space.md)).
|
||
**3. Индексация** — сохранение векторов в хранилище с поддержкой similarity search.
|
||
**4. Retrieval** — поиск топ-k фрагментов, ближайших к запросу пользователя.
|
||
**5. Reranking** — пересортировка результатов более точной моделью.
|
||
**6. Генерация** — LLM генерирует ответ, опираясь на извлечённые фрагменты.
|
||
|
||
Этапы 1–3 выполняются **один раз** при индексации корпуса (offline). Этапы 4–6 — **при каждом запросе** (online). Это ключевое архитектурное свойство: RAG разделяет подготовку данных и inference.
|
||
|
||
---
|
||
|
||
## 12.3. Чанкинг: как нарезать документы
|
||
|
||
Чанкинг — первый этап, и ошибки здесь каскадируются на все последующие. Слишком маленькие чанки — точный retrieval, но потерянный контекст. Слишком большие — контекст сохранён, но релевантность размывается.
|
||
|
||
### Стратегии чанкинга
|
||
|
||
| Стратегия | Размер | Плюсы | Минусы | Когда использовать |
|
||
|-----------|--------|-------|--------|-------------------|
|
||
| Fixed-size (по символам/токенам) | 256–1024 токенов | Просто, предсказуемо | Режет предложения и абзацы | Однородные тексты, логи |
|
||
| Sentence-level | 1–5 предложений | Сохраняет грамматическую целостность | Разброс размеров | Справочные статьи, FAQ |
|
||
| Recursive (LangChain-стиль) | Адаптивный | Сначала делит по `\n\n`, потом по `\n`, потом по предложениям | Сложнее контролировать | Markdown, документация |
|
||
| Semantic | Динамический | Группирует по смысловой близости | Требует embedding на этапе чанкинга | Длинные нарративные тексты |
|
||
| Document-aware | По структуре документа | Учитывает заголовки, разделы, таблицы | Нужен парсер формата | PDF, HTML, код |
|
||
|
||
### Overlap
|
||
|
||
Overlap (перекрытие) между чанками — 10–20% от размера чанка — решает проблему «разрезанного абзаца». Если критическое предложение попало на границу, перекрытие гарантирует, что оно целиком окажется хотя бы в одном чанке.
|
||
|
||
> **Промпт для генерации кода.** *«Напиши recursive text splitter для документов: chunk_size 512 токенов, overlap 64 токена (~12%), разделители по приоритету — двойной перенос строки, одинарный перенос, точка с пробелом, пробел. Используй LangChain RecursiveCharacterTextSplitter или аналог текущей версии фреймворка. Покажи пример нарезки одного документа.»*
|
||
|
||
### Практические рекомендации
|
||
|
||
- **Документация, база знаний**: recursive splitting, 400–600 токенов, overlap 50–80.
|
||
- **Код**: document-aware splitting по функциям/классам (tree-sitter для AST).
|
||
- **Юридические документы**: sentence-level с сохранением номеров пунктов в метаданных.
|
||
- **Таблицы**: не режьте — сериализуйте строки с заголовками в каждом чанке.
|
||
|
||
---
|
||
|
||
## 12.4. Embedding и retrieval
|
||
|
||
### Dense embeddings
|
||
|
||
Embedding-модели превращают текст в вектор фиксированной размерности. Семантически близкие тексты оказываются рядом в пространстве (подробнее — [Глава 1](01_tokens_vectors_and_semantic_space.md)). Для RAG это означает: запрос «как настроить авторизацию» окажется близко к чанку про OAuth, даже если в чанке нет слова «авторизация».
|
||
|
||
Популярные модели (2025–2026):
|
||
|
||
| Модель | Размерность | Контекст | Особенности |
|
||
|--------|------------|----------|-------------|
|
||
| OpenAI `text-embedding-3-large` | 3072 (сжимаемо) | 8K токенов | Matryoshka: можно усечь до 256–1536 dim |
|
||
| Cohere `embed-v4` | 1536 (по умолчанию; сжимаемо до 256) | 128K токенов | Мультимодальные (текст + изображения), search/classification |
|
||
| `bge-large-en-v1.5` (BAAI) | 1024 | 512 токенов | Open-source, English |
|
||
| `bge-m3` (BAAI) | 1024 | 8K токенов | Open-source, мультиязычный, multi-granularity |
|
||
| Voyage `voyage-4-large` | 1024 (Matryoshka: 256/512/2048) | 32K токенов | Серия voyage-4 (large/standard/lite) |
|
||
|
||
**Matryoshka embeddings** (Kusupati et al., 2022) — подход, где первые координаты полного вектора уже сохраняют большую часть полезного сигнала. Это позволяет хранить укороченные векторы (256 dim вместо 3072) с минимальной потерей качества retrieval — и экономить на хранении и скорости поиска.
|
||
|
||
### Sparse retrieval: BM25
|
||
|
||
Dense embeddings ловят *семантическую* близость — но иногда нужна *лексическая*. Если пользователь ищет «ошибка ERR-4021», dense embedding может не найти точный номер ошибки, зато BM25 найдёт моментально — по точному совпадению терминов.
|
||
|
||
BM25 — вероятностная модель ранжирования, основанная на TF-IDF с нормализацией по длине документа. Несмотря на возраст (Robertson et al., 1994), BM25 остаётся конкурентным baseline и в 2026 году.
|
||
|
||
### Hybrid search
|
||
|
||
Лучшая практика — **гибридный поиск**: объединение dense и sparse retrieval с последующим слиянием результатов.
|
||
|
||
```python
|
||
# Псевдокод: hybrid search с Reciprocal Rank Fusion (RRF)
|
||
def hybrid_search(query: str, k: int = 10) -> list[Chunk]:
|
||
dense_results = vector_db.search(embed(query), top_k=k * 2)
|
||
sparse_results = bm25_index.search(query, top_k=k * 2)
|
||
|
||
# Reciprocal Rank Fusion (Cormack et al., 2009)
|
||
scores: dict[str, float] = {}
|
||
for rank, chunk in enumerate(dense_results):
|
||
scores[chunk.id] = scores.get(chunk.id, 0) + 1 / (60 + rank)
|
||
for rank, chunk in enumerate(sparse_results):
|
||
scores[chunk.id] = scores.get(chunk.id, 0) + 1 / (60 + rank)
|
||
|
||
return sorted(scores, key=scores.get, reverse=True)[:k]
|
||
```
|
||
|
||
RRF (Reciprocal Rank Fusion) — простой и эффективный способ объединения: чем выше документ стоит в каждом списке, тем больше вклад он получает в итоговый score; вклад убывает с номером позиции, после чего результаты суммируются. Это устойчивее, чем нормализация скоров, потому что шкалы dense и sparse метрик — разные.
|
||
|
||
### Векторные базы данных
|
||
|
||
| База | Тип | Особенности |
|
||
|------|-----|-------------|
|
||
| Qdrant | Dedicated | Фильтрация по payload, distributed, Rust |
|
||
| ChromaDB | Embedded | Простой API, для прототипов |
|
||
| Pinecone | Managed | Serverless, автомасштабирование |
|
||
| Weaviate | Dedicated | Hybrid search из коробки, GraphQL |
|
||
| pgvector | Extension | PostgreSQL-расширение, HNSW-индекс |
|
||
|
||
Для прототипа — ChromaDB или pgvector. Для production с > 10M векторов — Qdrant или Pinecone. Критерий выбора: не «какая база модная», а *как она интегрируется с вашим стеком*, поддерживает ли фильтрацию по метаданным и какой latency на вашем объёме.
|
||
|
||
### Квантизация
|
||
|
||
Хранение 10M векторов по 3072 dim в float32 — это ~115 ГБ. Квантизация (int8, binary) снижает объём в 4–32 раз с потерей ~1–3% retrieval quality. На масштабе — это компромисс, который почти всегда оправдан.
|
||
|
||
---
|
||
|
||
## 12.5. Reranking и фильтрация
|
||
|
||
### Зачем нужен reranking
|
||
|
||
Embedding-based retrieval — быстрый, но грубый. Bi-encoder (embedding-модель) обрабатывает запрос и документ *независимо*, а потом сравнивает их векторы. Cross-encoder (reranker) смотрит на пару (запрос, документ) *совместно* — и точнее определяет релевантность.
|
||
|
||
Аналогия: bi-encoder — это фильтр по резюме (быстро, но много false positives). Cross-encoder — это техническое собеседование (дороже, но отсеивает точно).
|
||
|
||
```
|
||
Retrieval (top-50, быстро) → Reranking (top-50 → top-5, точно) → LLM (top-5)
|
||
```
|
||
|
||
### Инструменты
|
||
|
||
| Reranker | Тип | Особенности |
|
||
|----------|-----|-------------|
|
||
| Cohere Rerank | API | Коммерческий, высокое качество |
|
||
| `bge-reranker-v2-m3` | Open-source | Мультиязычный, можно запустить локально |
|
||
| `cross-encoder/ms-marco-MiniLM-L-6-v2` | Open-source | Лёгкий, быстрый |
|
||
| Voyage Rerank | API | Code-aware |
|
||
|
||
### Metadata filtering
|
||
|
||
Reranking работает на уровне семантики. Но часто нужна фильтрация по метаданным *до* или *вместе* с semantic search. Паттерн: при поисковом запросе передайте вектор запроса, top-k и словарь фильтров (`source`, `updated_after`, `department`, `language`). Все major vector-базы (Qdrant, Weaviate, Pinecone, pgvector) поддерживают metadata-фильтры при search.
|
||
|
||
Фильтрация по дате, источнику, отделу, языку — снижает шум и повышает precision без дополнительных вычислений.
|
||
|
||
### The retrieval-generation gap
|
||
|
||
Важный нюанс: высокое качество retrieval не гарантирует высокое качество генерации. Модель может получить правильные чанки — и всё равно сгаллюцинировать, если:
|
||
- Чанк содержит нужный факт, но в неочевидной формулировке.
|
||
- Несколько чанков противоречат друг другу.
|
||
- Модель «предпочитает» свои параметрические знания извлечённому контексту.
|
||
|
||
Этот зазор между retrieval quality и generation faithfulness — одна из центральных проблем RAG. Решение — в правильном prompt engineering (раздел 12.6) и в eval-фреймворках (раздел 12.8).
|
||
|
||
---
|
||
|
||
## 12.6. Генерация с контекстом: prompt engineering для RAG
|
||
|
||
### Инъекция контекста
|
||
|
||
RAG-промпт — это промпт с явно выделенной секцией для извлечённого контекста. XML-разметка (см. [Главу 7](07_markup_tags_and_prompt_architecture.md)) — идеальный формат:
|
||
|
||
```xml
|
||
<system>
|
||
Ты — ассистент технической поддержки. Отвечай ТОЛЬКО
|
||
на основе предоставленных документов. Если ответа нет
|
||
в документах — скажи "Информация не найдена в базе знаний".
|
||
</system>
|
||
|
||
<retrieved_documents>
|
||
<document id="1" source="docs/auth.md" updated="2025-11-15">
|
||
OAuth 2.0 используется для авторизации внешних приложений.
|
||
Токен обновления действует 30 дней. Для внутренних сервисов
|
||
используется mTLS.
|
||
</document>
|
||
<document id="2" source="docs/api-limits.md" updated="2026-01-03">
|
||
Rate limit для API v3: 1000 req/min для плана Enterprise,
|
||
100 req/min для Free.
|
||
</document>
|
||
</retrieved_documents>
|
||
|
||
<user_query>
|
||
Какой rate limit для Enterprise-клиентов?
|
||
</user_query>
|
||
|
||
<instructions>
|
||
Ответь на вопрос пользователя, цитируя конкретные документы.
|
||
Формат: [doc_id] после каждого утверждения.
|
||
</instructions>
|
||
```
|
||
|
||
### Citation grounding
|
||
|
||
Требование цитировать источники — один из самых эффективных способов снизить галлюцинации в RAG. Когда модель должна указать `[doc_id]` после каждого утверждения, это:
|
||
1. **Фиксирует attention** на извлечённых документах, а не на параметрической памяти.
|
||
2. **Создаёт проверяемый артефакт** — можно программно верифицировать, что cited document действительно содержит claim.
|
||
3. **Повышает калибровку** — модель реже выдумывает, если знает, что нужно привязать ответ к конкретному источнику.
|
||
|
||
### «Отвечай только по документам» — работает ли?
|
||
|
||
Инструкция «Answer ONLY based on provided context» снижает extrinsic hallucinations, но не устраняет их полностью. Модели с сильными параметрическими знаниями (GPT-5.4, Claude Opus 4.6) иногда «дополняют» ответ собственными знаниями, даже если промпт запрещает это.
|
||
|
||
Повышает надёжность:
|
||
- Explicit «If the answer is not in the documents, say so» — модели лучше реагируют на явный fallback.
|
||
- Structured output с полем `"source_doc_id"` — если поле обязательное, модель вынуждена привязаться к документу или вернуть null.
|
||
- Верификация постфактум — второй вызов или regex-проверка наличия citation (см. [Главу 13](13_anti_hallucination_loop.md)).
|
||
|
||
### Handling «Я не знаю»
|
||
|
||
RAG-система, которая не умеет отказываться отвечать, — бомба замедленного действия. Если в извлечённых документах нет ответа, модель должна сказать об этом. Это проектируется явно через системный промпт:
|
||
|
||
```
|
||
You are a support assistant.
|
||
Rules:
|
||
1. Answer ONLY from <retrieved_documents>.
|
||
2. Cite [doc_id] for every claim.
|
||
3. If no document answers the question, respond:
|
||
{"answer": null, "reason": "Not found in knowledge base"}
|
||
4. NEVER fabricate information.
|
||
```
|
||
|
||
---
|
||
|
||
## 12.7. Продвинутые паттерны
|
||
|
||
Базовый RAG (single query → retrieval → generation) — отправная точка. Production-системы часто требуют более сложных архитектур.
|
||
|
||
### Multi-hop RAG
|
||
|
||
Некоторые вопросы невозможно ответить одним retrieval. «Какой бюджет был у проекта, руководитель которого ушёл в Q3?» — требует сначала найти руководителя, потом найти проект, потом найти бюджет.
|
||
|
||
Паттерн: **query decomposition → sequential retrieval → synthesis**.
|
||
|
||
```
|
||
Вопрос: "Какой бюджет у проекта, руководитель которого ушёл в Q3?"
|
||
|
||
→ Подзапрос 1: "Кто из руководителей проектов ушёл в Q3?"
|
||
→ Retrieval → "Иванов, проект Alpha"
|
||
|
||
→ Подзапрос 2: "Какой бюджет проекта Alpha?"
|
||
→ Retrieval → "12.5M руб."
|
||
|
||
→ Синтез: "Бюджет проекта Alpha (руководитель Иванов, ушёл в Q3) — 12.5M руб."
|
||
```
|
||
|
||
Это пересекается с chain-of-thought декомпозицией из [Главы 9](09_multistep_reasoning.md), но на уровне retrieval, а не рассуждения.
|
||
|
||
### GraphRAG
|
||
|
||
Edge et al. (2024) предложили строить **граф знаний** поверх чанков: извлекать сущности и отношения, строить граф, затем использовать community summaries для ответов на сложные вопросы, требующие «глобального» понимания корпуса.
|
||
|
||
```
|
||
Документы → Чанки → LLM извлекает (сущность, отношение, сущность)
|
||
→ Граф → Community detection → Summaries → Retrieval по summaries
|
||
```
|
||
|
||
GraphRAG силён на вопросах вида «каковы основные темы в этом корпусе» или «как связаны X и Y через цепочку отношений» — то, что плоский vector search не покрывает.
|
||
|
||
### RAPTOR
|
||
|
||
Sarthi et al. (ICLR 2024): **рекурсивная абстрактивная обработка**. Чанки кластеризуются, для каждого кластера генерируется summary, summaries снова кластеризуются — и так до корневого уровня. Получается дерево абстракций, по которому retrieval может идти на разных уровнях детализации.
|
||
|
||
Полезно, когда вопросы варьируются от «что конкретно написано в параграфе 3.2?» до «о чём вообще эта документация?».
|
||
|
||
### Self-RAG
|
||
|
||
Asai et al. (ICLR 2024): модель сама решает, **когда нужен retrieval**, а когда — нет. На каждом шаге генерации модель выдаёт специальные токены: `[Retrieve]` (нужен поиск), `[No Retrieve]` (знаю сам), `[Relevant]`/`[Irrelevant]` (оценка полученного контекста), `[Supported]`/`[Not Supported]` (самопроверка faithfulness).
|
||
|
||
Это элегантнее, чем «всегда ищи» или «никогда не ищи» — модель адаптивно включает retrieval только там, где параметрической памяти недостаточно.
|
||
|
||
### HyDE
|
||
|
||
Gao et al. (ACL 2023): **Hypothetical Document Embeddings**. Вместо того чтобы искать по запросу пользователя напрямую, модель сначала генерирует *гипотетический документ*, который мог бы содержать ответ, а затем ищет по embedding этого документа.
|
||
|
||
```
|
||
Запрос: "Как настроить mTLS между сервисами?"
|
||
→ LLM генерирует гипотетический ответ (может быть неточным)
|
||
→ Embedding гипотетического ответа → Vector search
|
||
→ Находит реальные документы, семантически близкие к ответу
|
||
```
|
||
|
||
HyDE помогает при vocabulary mismatch: запрос пользователя и документ корпуса могут описывать одно и то же разными словами. Гипотетический документ «переводит» запрос на язык корпуса.
|
||
|
||
### Corrective RAG (CRAG)
|
||
|
||
Базовый RAG предполагает, что retrieval уже принёс «достаточно хорошие» документы. CRAG (Yan et al., 2024) делает следующий шаг: **сначала оценивает качество retrieval, а потом решает, что делать дальше**.
|
||
|
||
Паттерн такой:
|
||
- retriever возвращает top-k документов;
|
||
- лёгкий retrieval evaluator выставляет confidence score;
|
||
- при высоком confidence система сразу идёт в генерацию;
|
||
- при низком confidence запускается коррекция: web search, альтернативный retriever, очистка или декомпозиция документов.
|
||
|
||
Это особенно полезно для шумных корпоративных корпусов, где часть документов устарела, дублируется или противоречит друг другу. CRAG переводит RAG из одношаговой схемы «нашли → сгенерировали» в более надёжную схему **«нашли → оценили → при необходимости исправили → только потом сгенерировали»**.
|
||
|
||
---
|
||
|
||
## 12.8. Оценка качества RAG-системы
|
||
|
||
Без метрик RAG — это чёрный ящик поверх чёрного ящика. Нужно измерять три независимых измерения.
|
||
|
||
### Три измерения качества
|
||
|
||
```
|
||
┌─────────────────────┐
|
||
│ Retrieval Quality │
|
||
│ (нашли ли нужное?) │
|
||
└──────────┬──────────┘
|
||
│
|
||
┌──────────────┼──────────────┐
|
||
▼ ▼
|
||
┌──────────────────────┐ ┌──────────────────────┐
|
||
│ Faithfulness │ │ Answer Relevancy │
|
||
│ (ответ верен │ │ (ответ полезен │
|
||
│ контексту?) │ │ пользователю?) │
|
||
└──────────────────────┘ └──────────────────────┘
|
||
```
|
||
|
||
1. **Retrieval quality** — нашла ли система нужные документы? Измеряется через context precision (какая доля извлечённых чанков релевантна) и context recall (какая доля нужной информации извлечена).
|
||
|
||
2. **Faithfulness** — генерирует ли модель ответ, *верный* извлечённым документам? Или добавляет факты, которых в контексте нет? Это ключевая метрика для RAG: галлюцинация *при наличии правильных документов* — самый коварный режим отказа (см. [Главу 3](03_hallucinations.md)).
|
||
|
||
3. **Answer relevancy** — полезен ли ответ пользователю? Можно извлечь правильные документы и сгенерировать faithful ответ, который при этом не отвечает на вопрос.
|
||
|
||
Отдельная современная тонкость: retrieval и параметрическая память модели находятся в режиме **tug-of-war**. Даже если вы положили в контекст документ, модель не обязана ему подчиниться; и наоборот, неверный retrieved факт может «переписать» корректный prior модели. Поэтому в eval-наборе полезно иметь не только обычные вопросы, но и **conflict cases**, где retrieved context специально противоречит prior модели. Это быстро показывает, умеет ли система различать «контекст прав» и «контекст шумит».
|
||
|
||
### RAGAS framework
|
||
|
||
Es et al. (EACL 2024) предложили RAGAS — автоматический eval-framework для RAG, который оценивает все три измерения с помощью LLM-as-a-judge:
|
||
|
||
| Метрика | Что измеряет | Как считается |
|
||
|---------|-------------|---------------|
|
||
| Context Precision | Доля релевантных чанков в top-k | LLM оценивает каждый чанк |
|
||
| Context Recall | Покрытие ground-truth ответа контекстом | LLM сопоставляет claims с чанками |
|
||
| Faithfulness | Все ли claims в ответе подтверждены контекстом | LLM разбивает ответ на claims, проверяет каждый |
|
||
| Answer Relevancy | Отвечает ли ответ на вопрос | LLM генерирует вопросы по ответу, сравнивает с оригиналом |
|
||
|
||
> **Промпт для генерации кода.** *«Настрой eval-пайплайн с RAGAS (ragas.io): подготовь датасет из вопросов, ground-truth-ответов, retrieved contexts и сгенерированных ответов. Оцени метрики faithfulness, context_precision, answer_relevancy. Покажи пример запуска evaluate() и интерпретацию результатов. Целевые значения: faithfulness ≥ 0.85, context_precision ≥ 0.70.»*
|
||
|
||
### RAGChecker и более тонкая диагностика
|
||
|
||
RAGAS хорошо подходит для быстрой итерации, но часто остаётся слишком грубым инструментом: видно, что «RAG плохой», но не видно, **какой модуль сломался**. Для этого появились более детальные фреймворки, например RAGChecker (Ru et al., 2024), который разносит диагностику по retrieval- и generation-модулю и даёт более точную картину причин деградации.
|
||
|
||
Практическое правило:
|
||
- **RAGAS** — когда нужна быстрая обратная связь в цикле разработки;
|
||
- **RAGChecker или аналогичная fine-grained диагностика** — когда нужно понять, почему система просела после изменения retriever, reranker, чанкинга или промпта.
|
||
|
||
### Ручная оценка
|
||
|
||
LLM-as-a-judge — удобно для итеративной разработки, но не заменяет human evaluation. Минимальный протокол:
|
||
|
||
1. Соберите 50–100 вопросов, покрывающих типичные сценарии.
|
||
2. Для каждого зафиксируйте ground-truth ответ и релевантные документы.
|
||
3. Прогоните RAG-пайплайн, соберите ответы.
|
||
4. Оцените по шкале 1–5: faithfulness, completeness, relevancy.
|
||
5. Посчитайте процент critical failures (полностью неверные ответы).
|
||
|
||
### Когда RAG проваливается
|
||
|
||
RAG не панацея. Типичные режимы отказа:
|
||
|
||
| Режим отказа | Причина | Как обнаружить |
|
||
|-------------|---------|----------------|
|
||
| Retrieval miss | Нужного документа нет в корпусе | Context recall → 0 |
|
||
| Relevant but buried | Нужный чанк на позиции 50+, не попал в top-k | Увеличить k, добавить reranking |
|
||
| Unfaithful generation | Модель игнорирует контекст | Faithfulness metric, citation check |
|
||
| Contradictory chunks | Два чанка противоречат друг другу | Ручная проверка, metadata filtering по дате |
|
||
| Bad chunking | Критическая информация разрезана | Проверить чанки вручную, увеличить overlap |
|
||
| Wrong context dominates prior | Retriever принёс ошибочный факт, и модель послушно встроила его в ответ | Conflict-set eval, retrieval confidence, contradiction check |
|
||
|
||
---
|
||
|
||
## 12.9. Data layer: жизненный цикл знаний
|
||
|
||
В предыдущих секциях мы разобрали, как строить retrieval pipeline: чанкинг, embedding, reranking, генерация. Но в production качество RAG-системы чаще ломается не на этапе retrieval, а на этапе данных: документы устаревают, индекс загрязняется дубликатами, удалённые файлы продолжают отдаваться, а access control игнорируется. Эта секция — про инженерию данных в RAG.
|
||
|
||
### Ingestion pipeline: от источника до индекса
|
||
|
||
Ingestion — это не одноразовая загрузка, а постоянный pipeline. Источники разнообразны: файлы, базы данных, API, веб-сайты, корпоративные мессенджеры, email.
|
||
|
||
Этапы ingestion-конвейера:
|
||
|
||
```
|
||
Источник → Extraction (парсинг формата) → Cleaning (удаление мусора, нормализация)
|
||
→ Chunking → Enrichment (metadata: source, date, author, ACL)
|
||
→ Embedding → Indexing
|
||
```
|
||
|
||
Критический этап — **metadata enrichment**. Метаданные, добавленные при ingestion (источник, дата, автор, ACL-тег, версия документа), определяют качество фильтрации на этапе retrieval. Без metadata filtering релевантность падает: система отдаёт устаревшие документы наравне с актуальными, а чанки из разных контекстов смешиваются.
|
||
|
||
### Freshness: актуальность индекса
|
||
|
||
Документы устаревают. Регламент обновился, API поменялся, сотрудник уволился — а в индексе лежат старые чанки. Два паттерна обновления:
|
||
|
||
- **Incremental ingestion** — отслеживание изменений в источнике (webhooks, polling, Change Data Capture). Переиндексируются только изменённые документы. Эффективно, но требует, чтобы источник поддерживал change tracking.
|
||
- **Full re-index** — периодическая полная переиндексация. Проще в реализации, но дороже по compute. Подходит для источников без change tracking или для небольших корпусов.
|
||
|
||
**Provenance tracking**: каждый чанк должен хранить ссылку на исходный документ, дату индексации и версию. Без provenance невозможно отличить свежий чанк от устаревшего — и невозможно корректно удалить данные.
|
||
|
||
**Deletion semantics**: при удалении документа из источника все его чанки должны удаляться из индекса. Типичный анти-паттерн — «призраки»: удалённые документы продолжают влиять на ответы, потому что их чанки остались в vector store.
|
||
|
||
### ACL-aware индексация и retrieval
|
||
|
||
В enterprise-среде не все документы доступны всем пользователям. RAG без access control — это потенциальная утечка данных.
|
||
|
||
Два подхода:
|
||
|
||
| Подход | Механизм | Плюсы | Минусы |
|
||
|--------|----------|-------|--------|
|
||
| Metadata-фильтрация | Запрос + ACL-фильтр при retrieval | Один индекс, проще поддерживать | Embedding «видит» все документы; фильтрация — на финальном этапе |
|
||
| Tenant-изолированные индексы | Отдельный индекс на tenant/роль | Strict isolation, нет риска утечки | Дороже в поддержке, дублирование общих документов |
|
||
|
||
Metadata-фильтрация при retrieval — минимальное требование для production RAG в организациях. Для систем со strict compliance (финансы, медицина) tenant-изоляция надёжнее.
|
||
|
||
### Contextual retrieval и enrich-before-embed
|
||
|
||
Стандартный embedding чанка теряет контекст документа: чанк из середины регламента превращается в безликий фрагмент. Anthropic Contextual Retrieval (2024): перед embedding'ом каждый чанк обогащается кратким описанием контекста документа, из которого он извлечён (prepended context). LLM генерирует 1–2 предложения: «Этот фрагмент из регламента безопасности, раздел про доступ к production-среде».
|
||
|
||
Это улучшает retrieval accuracy без изменения retrieval-алгоритма — за счёт того, что embedding теперь кодирует не только содержание чанка, но и его место в документе. Стоимость: один LLM-вызов на чанк на этапе ingestion. Оправдано для корпусов с высокой ценностью (внутренняя документация, юридические базы); избыточно для ephemeral данных (логи, временные заметки).
|
||
|
||
### Re-embed и re-index: миграция embedding-модели
|
||
|
||
При смене embedding-модели (новая версия, другой провайдер) все чанки нужно перевекторизовать — старые и новые embeddings несовместимы.
|
||
|
||
Практическое правило: **хранить исходный текст чанка**, а не только embedding. Без исходного текста миграция невозможна — придётся заново проходить весь ingestion pipeline от источников.
|
||
|
||
**Blue-green indexing**: создаём новый индекс параллельно старому, прогоняем eval-сет на обоих, переключаем трафик после верификации. Это тот же паттерн, что blue-green deployment в backend — только для vector store.
|
||
|
||
### Hosted retrieval: File Search и managed RAG
|
||
|
||
OpenAI File Search, Google Vertex AI Search, Azure AI Search — managed-решения, где провайдер берёт на себя ingestion, chunking, embedding и retrieval.
|
||
|
||
Преимущество: zero-ops для retrieval pipeline — загрузил файлы, получил API для поиска. Недостаток: меньше контроля над chunking-стратегией, выбором embedding-модели и reranking.
|
||
|
||
Для быстрого старта и средних нагрузок hosted retrieval часто достаточен. Для тонкой настройки, strict data residency или корпусов с нестандартной структурой (код, таблицы, мультимодальные документы) — self-hosted pipeline даёт больше контроля.
|
||
|
||
Качество RAG-системы определяется не только retrieval-алгоритмом, но и дисциплиной управления данными. Ingestion pipeline, freshness, ACL-aware indexing и provenance — это infrastructure, без которой даже идеальный retriever будет отдавать мусор.
|
||
|
||
---
|
||
|
||
## 12.10. RAG failure diagnosis playbook
|
||
|
||
Когда RAG-система даёт неверный ответ, недостаточно сказать «RAG сломался». Нужно определить, *какой именно компонент* отказал. Этот playbook — пошаговая диагностика для каждого из восьми режимов отказа (§12.8).
|
||
|
||
### Диагностическая процедура
|
||
|
||
Для каждого инцидента фиксируйте в диагностической карточке:
|
||
|
||
1. **Вопрос пользователя** — точный текст.
|
||
2. **Ответ системы** — что вернул RAG.
|
||
3. **Эталонный ответ** — что должно было быть (из golden dataset или ручная разметка).
|
||
4. **Извлечённые чанки** — top-k результатов retrieval (до reranking и после).
|
||
5. **Промпт, отправленный в LLM** — с injected контекстом.
|
||
6. **Метрики** — faithfulness, context_precision, answer_relevancy (из RAGAS или ручные).
|
||
|
||
Теперь — восемь режимов отказа и что делать в каждом.
|
||
|
||
---
|
||
|
||
### Режим 1: Retrieval miss — нужного документа нет в топе
|
||
|
||
**Симптомы:** RAGAS context_precision < 0.5. В извлечённых чанках нет информации, которая есть в корпусе.
|
||
|
||
**Диагностика:**
|
||
1. Вручную проверьте корпус — есть ли в нём ответ на вопрос? Если нет → это не retrieval miss, это missing content (Режим 7).
|
||
2. Найдите правильный чанк вручную. На какой он позиции в retrieval-результате?
|
||
3. Проверьте embedding запроса: совпадает ли «язык» запроса с языком корпуса? (разные термины для одного понятия)
|
||
|
||
**Исправление:**
|
||
- Позиция 11-20 → увеличьте k (retrieve top-30 вместо top-10), добавьте reranking.
|
||
- Позиция 21+ → попробуйте HyDE (§12.7): сгенерируйте гипотетический ответ, ищите по нему.
|
||
- Систематически → пересмотрите chunking (слишком мелкие чанки теряют контекст), попробуйте contextual retrieval (§12.9).
|
||
- Разный «язык» → добавьте синонимы в запрос (query expansion), используйте hybrid search (dense + BM25).
|
||
|
||
---
|
||
|
||
### Режим 2: Relevant but buried — чанк найден, но не в топе
|
||
|
||
**Симптомы:** Ручная проверка показывает, что нужный чанк есть на позиции 8-15, но в генерацию попадают только top-5.
|
||
|
||
**Диагностика:** Проверьте позицию правильного чанка в retrieval results. Если она стабильно 6-15 → проблема в ранжировании.
|
||
|
||
**Исправление:**
|
||
- Добавьте reranking (cross-encoder) — это самый эффективный способ поднять релевантные чанки.
|
||
- Увеличьте k для reranking: retrieval top-50 → rerank → top-5.
|
||
- Проверьте metadata filtering: возможно, правильный чанк имеет устаревшую дату и исключается фильтром.
|
||
|
||
---
|
||
|
||
### Режим 3: Unfaithful generation — модель игнорирует контекст
|
||
|
||
**Симптомы:** RAGAS faithfulness < 0.7. Правильные чанки в контексте есть, но модель генерирует ответ «мимо» них или дополняет своими знаниями.
|
||
|
||
**Диагностика:**
|
||
1. Сравните claims в ответе с содержанием извлечённых чанков (вручную или через RAGAS).
|
||
2. Есть ли в ответе факты, которых нет ни в одном чанке? → модель использует параметрическую память.
|
||
3. Есть ли в ответе утверждения, противоречащие чанкам? → модель «переспорила» контекст.
|
||
|
||
**Исправление:**
|
||
- Усилите промпт: `"Answer ONLY using the provided documents. If the answer is not in the documents, say 'Not found in knowledge base'."`
|
||
- Добавьте citation grounding: требуйте `[doc_id]` после каждого утверждения (§12.6).
|
||
- Используйте structured output с обязательным полем `source_doc_id` — модель вынуждена привязаться к документу.
|
||
- Добавьте Verifier (Глава 13): второй LLM-вызов проверяет faithfulness ответа.
|
||
- Проверьте conflict cases: возможно, retrieved context противоречит сильным prior модели — тогда модель «выбирает» prior.
|
||
|
||
---
|
||
|
||
### Режим 4: Contradictory chunks — чанки противоречат друг другу
|
||
|
||
**Симптомы:** Ответ модели непоследователен. В retrieved chunks есть взаимоисключающая информация (например, «API v1 активен» и «API v1 отключён с марта»).
|
||
|
||
**Диагностика:** Просмотрите retrieved chunks на предмет противоречий. Обратите внимание на даты — часто противоречие вызвано устаревшим документом.
|
||
|
||
**Исправление:**
|
||
- Metadata filtering по дате: `updated_after: 2025-01-01` или `version: latest`.
|
||
- Provenance tracking (§12.9): каждый чанк хранит дату индексации и версию исходного документа.
|
||
- В промпт добавьте инструкцию: `"If documents contradict each other, prefer the most recent one (by date). If ambiguity remains, state both positions with sources."`
|
||
- Deletion semantics: убедитесь, что удалённые документы действительно удалены из индекса.
|
||
|
||
---
|
||
|
||
### Режим 5: Bad chunking — информация разрезана
|
||
|
||
**Симптомы:** Извлечённый чанк содержит часть нужной информации, но ответ модели неполный или неверный. При ручной проверке видно, что соседний чанк содержит недостающую часть, но она не попала в контекст.
|
||
|
||
**Диагностика:** Просмотрите retrieved chunks. Есть ли «оборванные» предложения на границах? Числа, отделённые от единиц измерения? Таблицы, разрезанные пополам?
|
||
|
||
**Исправление:**
|
||
- Увеличьте overlap до 20-25% от размера чанка.
|
||
- Перейдите на семантический или document-aware chunking (§12.3).
|
||
- Для таблиц: не нарезайте их — сериализуйте с повторением заголовков в каждом чанке.
|
||
- Проверьте recursive splitting: правильный ли порядок разделителей? Добавьте domain-specific разделители.
|
||
|
||
---
|
||
|
||
### Режим 6: Missing content — ответа нет в корпусе
|
||
|
||
**Симптомы:** RAGAS context_recall = 0. Ручная проверка корпуса подтверждает: ответа на вопрос действительно нет в проиндексированных документах. RAG не сломан — просто знания отсутствуют.
|
||
|
||
**Диагностика:** Проверьте корпус вручную. Может ли человек найти ответ? Если нет → missing content.
|
||
|
||
**Исправление:**
|
||
- Расширьте корпус: добавьте недостающие документы.
|
||
- Настройте fallback: если retrieval confidence ниже порога → web search или «я не знаю».
|
||
- Используйте Corrective RAG (CRAG, §12.7): при низком confidence retrieval → автоматический web search.
|
||
- В промпте — явный fallback: `"If no document answers the question, respond: {'answer': null, 'reason': 'Not found in knowledge base'}"`.
|
||
|
||
---
|
||
|
||
### Режим 7: Wrong context dominates prior — неверный чанк «переубедил» модель
|
||
|
||
**Симптомы:** Retrieval принёс ошибочный или устаревший факт. Модель использовала его для ответа, проигнорировав свои (верные) параметрические знания. Ответ неверен, но faithful по отношению к неверному контексту.
|
||
|
||
**Диагностика:** Faithfulness высокий (> 0.85), но ответ фактически неверен. Проверьте: если убрать retrieved context и задать вопрос напрямую — модель отвечает правильно? Если да → проблема в контексте, не в модели.
|
||
|
||
**Исправление:**
|
||
- Reranking: качественный reranker должен опустить неверный чанк.
|
||
- Добавьте conflict cases в eval-набор: пары (правильный факт, контекст с неправильным фактом) — проверяйте, что модель выбирает контекст только когда он достовернее prior.
|
||
- Retrieval confidence: если все retrieved chunks имеют низкий similarity score → fallback к «я не знаю».
|
||
- Metadata filtering: исключите устаревшие документы по дате или версии.
|
||
|
||
---
|
||
|
||
### Режим 8: Query formulation mismatch — запрос и корпус на «разных языках»
|
||
|
||
**Симптомы:** Пользователь использует разговорные термины («как ускорить сайт»), а корпус — технические («оптимизация TTFB и LCP»). Embedding близости нет, retrieval пустой.
|
||
|
||
**Диагностика:** Сравните формулировку запроса с формулировками в корпусе. Есть ли семантическая близость? Проверьте cosine similarity запрос-чанк.
|
||
|
||
**Исправление:**
|
||
- HyDE (§12.7): сгенерируйте гипотетический ответ «техническим языком», ищите по нему.
|
||
- Query expansion: добавьте синонимы и технические термины к запросу.
|
||
- Hybrid search: BM25 поймает точные совпадения терминов, dense — семантическую близость.
|
||
- Multi-query retrieval: сгенерируйте 3-5 переформулировок запроса, объедините результаты.
|
||
|
||
---
|
||
|
||
### Диагностическая карточка инцидента
|
||
|
||
Используйте этот шаблон для каждого production-инцидента RAG:
|
||
|
||
```text
|
||
## RAG Incident #NNN
|
||
- Дата: [YYYY-MM-DD HH:MM]
|
||
- Вопрос: [точный текст]
|
||
- Ответ системы: [текст]
|
||
- Эталонный ответ: [текст или null]
|
||
- Режим отказа: [1-8]
|
||
- Root cause: [конкретный компонент/настройка]
|
||
- Исправление: [что изменено]
|
||
- Верификация исправления: [повторный прогон на этом и похожих кейсах]
|
||
- Добавлен в eval-набор: [да/нет, ID тест-кейса]
|
||
```
|
||
|
||
> **Промпт для ИИ:** «Напиши Python-скрипт для автоматической диагностики RAG-инцидента. Принимает: запрос, ответ системы, retrieved chunks (до и после reranking), ground-truth ответ (опционально). Автоматически определяет вероятный режим отказа (1-8) по правилам: (1) нет релевантных чанков → режим 1/6/8; (2) чанки есть, но faithfulness низкий → режим 3; (3) в чанках противоречия → режим 4; (4) ответ faithful, но неверен → режим 7. Генерирует diagnostic report в Markdown. Используй RAGAS для расчёта faithfulness и context_precision.»
|
||
|
||
---
|
||
|
||
## Практический вывод
|
||
|
||
### Когда RAG, когда long context, когда fine-tuning
|
||
|
||
| Критерий | RAG | Long context | Fine-tuning |
|
||
|----------|-----|-------------|-------------|
|
||
| Данные обновляются часто | Индексируй заново | Перезагрузи весь контекст | Переобучи модель |
|
||
| Нужна точная цитата | Citation grounding | Возможно, но сложнее | Модель не цитирует |
|
||
| Объём данных > 1M токенов | Масштабируется | Не влезет в контекст | Ограничено |
|
||
| Нужен специфический «тон» | RAG не меняет поведение | Аналогично | Обучает стилю |
|
||
| Латенси критична | Retrieval добавляет ~100–300 мс | Prefill долгий | Нет overhead |
|
||
| Простота реализации | Пайплайн из 6 компонент | Просто — запихни в контекст | Нужны данные и GPU |
|
||
|
||
**Правило:** RAG — для актуальных фактов из большого корпуса. Long context — для коротких документов (< 100K токенов), когда retrieval overhead не оправдан. Fine-tuning — для изменения поведения модели, а не для вливания фактов (факты забываются после fine-tuning — catastrophic forgetting).
|
||
|
||
### Чеклист: минимальный production RAG
|
||
|
||
1. **Чанкинг**: recursive splitting, 400–600 токенов, overlap 50–80. Проверьте вручную 20 чанков — читаемы ли они?
|
||
2. **Embedding**: начните с `text-embedding-3-large` или `bge-m3`. Matryoshka-редукция до 512–1024 dim для экономии.
|
||
3. **Vector store**: pgvector для MVP, Qdrant для production.
|
||
4. **Hybrid search**: dense + BM25 + RRF. Это baseline, который обычно лучше чистого dense.
|
||
5. **Reranking**: всегда. Даже лёгкий `bge-reranker` добавляет 3–8% к retrieval precision.
|
||
6. **Prompt**: XML-разметка, citation grounding, explicit «I don't know» fallback.
|
||
7. **Eval**: RAGAS + 50 ручных вопросов. Отслеживайте faithfulness ≥ 0.85.
|
||
8. **Мониторинг**: логируйте retrieval results, latency, user feedback.
|
||
|
||
### Типичные ошибки
|
||
|
||
- **Нет reranking**. Top-k от embedding-поиска содержит 30–50% нерелевантного шума. Без reranking модель получает плохой контекст.
|
||
- **Нет eval**. «Вроде работает» — это не метрика. Без faithfulness/relevancy вы не знаете, что сломалось.
|
||
- **Слепое доверие retrieval**. Retrieval нашёл — значит, правда? Нет. Устаревший документ, чанк с противоречием, неполная информация — всё это попадает в контекст.
|
||
- **Плохой чанкинг**. Разрезали таблицу пополам, потеряли заголовок, оторвали число от его описания — и модель галлюцинирует, потому что контекст бессмыслен.
|
||
- **Игнорирование метаданных**. RAG без фильтрации по дате, источнику, версии — это поиск без фильтров: найдёт, но не обязательно то, что нужно *сейчас*.
|
||
- **Нет систематической диагностики отказов**. Когда RAG ошибается, недостаточно править промпт наугад. Используйте **RAG failure diagnosis playbook** (§12.10): восемь режимов отказа с пошаговой процедурой диагностики и исправления для каждого.
|
||
|
||
### Задания
|
||
|
||
1. **Постройте минимальный RAG-пайплайн.** Возьмите 20–50 документов из вашего проекта (документация, FAQ, регламенты). Нарежьте recursive splitter'ом (400–600 токенов, overlap 50–80), проиндексируйте в pgvector или ChromaDB, подключите reranker. Составьте 10 вопросов с эталонными ответами. Измерьте faithfulness и context_precision через RAGAS. **Ожидаемый результат:** работающий пайплайн с базовыми метриками; понимание, где теряется качество — на этапе retrieval или генерации.
|
||
|
||
2. **A/B-тест dense vs. hybrid retrieval.** На том же корпусе сравните два режима: (a) только dense embedding search, (b) hybrid (dense + BM25 + RRF). Прогоните одинаковый набор из 10+ вопросов, сравните context_precision и answer_relevancy. **Ожидаемый результат:** количественная оценка прироста от гибридного поиска на ваших данных (типичный выигрыш — 5–15% precision).
|
||
|
||
3. **Проверьте чанкинг вручную.** Выберите 20 случайных чанков из индекса и оцените: читаемы ли они без окружающего контекста? Сохранён ли смысл? Не разрезана ли таблица или список? **Ожидаемый результат:** список проблемных чанков и скорректированные параметры splitter'а.
|
||
|
||
4. **Проведите диагностику RAG-инцидента.** Возьмите 3 реальных кейса, где RAG-система дала неверный ответ. Для каждого заполните диагностическую карточку, определите режим отказа, найдите root cause, предложите и примените исправление. Измерьте метрики до и после. **Ожидаемый результат:** 3 заполненные карточки + улучшение faithfulness/context_precision минимум на 10 п.п. для исправленных кейсов.
|
||
|
||
---
|
||
|
||
## Источники
|
||
|
||
- Lewis, P., et al. (2020). "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks." NeurIPS 2020.
|
||
- Gao, Y., et al. (2024). "Retrieval-Augmented Generation for Large Language Models: A Survey." arXiv:2312.10997.
|
||
- Edge, D., et al. (2024). "From Local to Global: A Graph RAG Approach to Query-Focused Summarization." Microsoft Research.
|
||
- Sarthi, P., et al. (2024). "RAPTOR: Recursive Abstractive Processing for Tree-Organized Retrieval." ICLR 2024.
|
||
- Asai, A., et al. (2024). "Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection." ICLR 2024.
|
||
- Yan, S., et al. (2024). "Corrective Retrieval Augmented Generation." arXiv:2401.15884.
|
||
- Es, S., et al. (2024). "RAGAS: Automated Evaluation of Retrieval Augmented Generation." EACL 2024.
|
||
- Ru, D., et al. (2024). "RAGChecker: A Fine-grained Framework for Diagnosing Retrieval-Augmented Generation." arXiv:2408.08067.
|
||
- Wu, K., Wu, E., Zou, J. (2025). "ClashEval: Quantifying the tug-of-war between an LLM's internal prior and external evidence." arXiv:2404.10198.
|
||
- Gao, L., et al. (2023). "Precise Zero-Shot Dense Retrieval without Relevance Labels." (HyDE) ACL 2023.
|
||
- Liu, N., et al. (2023). "Lost in the Middle: How Language Models Use Long Contexts." TACL.
|
||
- Kwon, W., et al. (2023). "Efficient Memory Management for Large Language Model Serving with PagedAttention." SOSP 2023.
|
||
- Kusupati, A., et al. (2022). "Matryoshka Representation Learning." NeurIPS 2022.
|
||
- Robertson, S., et al. (1994). "Okapi at TREC-3." NIST Special Publication.
|
||
- Anthropic. (2024). "Introducing Contextual Retrieval." Anthropic Blog.
|
||
|
||
---
|
||
|
||
**Навигация:**
|
||
- Назад: [Глава 11. Не заставляй модель считать — дай ей инструмент](11_tools.md)
|
||
- Далее: [Глава 13. Антигаллюцинационный контур и защита от деградации](13_anti_hallucination_loop.md)
|