Генерация с дополнением извлечением (RAG)
PRX реализует генерацию с дополнением извлечением (RAG) для улучшения ответов LLM релевантным контекстом из памяти и хранилищ знаний агента. Вместо того чтобы полагаться исключительно на параметрические знания LLM, RAG извлекает соответствующие документы и внедряет их в промпт -- снижая галлюцинации и обосновывая ответы на фактической актуальной информации.
Обзор
Конвейер RAG выполняется перед каждым вызовом LLM в цикле агента:
Сообщение пользователя
│
▼
┌──────────────────────────┐
│ 1. Формулировка запроса │ Извлечение поисковых терминов из
│ │ сообщения пользователя + контекста разговора
└──────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ 2. Генерация эмбеддинга │ Преобразование запроса в вектор с помощью
│ │ настроенного провайдера эмбеддингов
└──────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ 3. Поиск по памяти │ Поиск по бэкендам памяти:
│ │ векторное сходство + полнотекстовый
└──────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ 4. Фильтрация │ Скоринг и фильтрация результатов выше
│ по релевантности │ порога релевантности
└──────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ 5. Внедрение контекста │ Форматирование результатов и внедрение
│ │ в системный промпт / контекстное окно
└──────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ 6. Генерация LLM │ Модель генерирует ответ с
│ │ полным доступным контекстом
└──────────────────────────┘Конфигурация
Включите RAG в config.toml:
[memory]
backend = "embeddings" # RAG требует бэкенд эмбеддингов
[memory.embeddings]
# Провайдер эмбеддингов: "openai" | "ollama" | "local"
provider = "openai"
model = "text-embedding-3-small"
dimensions = 1536
# Бэкенд векторного хранилища
vector_store = "sqlite" # "sqlite" | "postgres" | "qdrant"
[rag]
enabled = true
# Максимальное количество извлечённых чанков для внедрения в контекст.
max_results = 10
# Минимальный балл релевантности (0.0 до 1.0) для включения чанка.
relevance_threshold = 0.3
# Максимальное количество токенов, выделенных для RAG-контекста.
# Предотвращает переполнение контекстного окна.
max_context_tokens = 4000
# Стратегия выбора чанков при превышении max_context_tokens.
# "top_k" -- наивысшие баллы релевантности в первую очередь
# "mmr" -- максимальная маргинальная релевантность (разнообразие + релевантность)
selection_strategy = "top_k"Провайдеры эмбеддингов
PRX поддерживает множество провайдеров эмбеддингов:
| Провайдер | Модель | Размерность | Примечания |
|---|---|---|---|
| OpenAI | text-embedding-3-small | 1536 | Лучшее соотношение качество/стоимость |
| OpenAI | text-embedding-3-large | 3072 | Наивысшее качество |
| Ollama | nomic-embed-text | 768 | Локальный, без стоимости API |
| Ollama | mxbai-embed-large | 1024 | Локальный, более высокое качество |
| Local | fastembed | 384 | Встроенный, без сети |
Настройка провайдера эмбеддингов:
# Эмбеддинги OpenAI
[memory.embeddings]
provider = "openai"
model = "text-embedding-3-small"
api_key = "${OPENAI_API_KEY}"
# Эмбеддинги Ollama (локальные)
[memory.embeddings]
provider = "ollama"
model = "nomic-embed-text"
endpoint = "http://localhost:11434"
# Встроенные локальные эмбеддинги (без внешнего сервиса)
[memory.embeddings]
provider = "local"
model = "fastembed"Стратегии разбиения на чанки
Перед тем как документы могут быть преобразованы в эмбеддинги и найдены, они должны быть разбиты на чанки. PRX поддерживает несколько стратегий разбиения:
| Стратегия | Описание | Лучше всего для |
|---|---|---|
fixed_size | Разбиение по фиксированному количеству токенов с перекрытием | Однородные документы |
sentence | Разбиение по границам предложений | Проза и естественный текст |
paragraph | Разбиение по границам абзацев | Структурированные документы |
semantic | Разбиение по тематическим границам с использованием эмбеддингов | Длинные разнородные документы |
recursive | Иерархическое разбиение (заголовок > абзац > предложение) | Markdown/код |
[rag.chunking]
strategy = "recursive"
# Целевой размер чанка в токенах.
chunk_size = 512
# Перекрытие между соседними чанками (предотвращает потерю контекста на границах).
chunk_overlap = 64
# Для рекурсивной стратегии: разделители в порядке приоритета.
separators = ["\n## ", "\n### ", "\n\n", "\n", ". "]Конвейер извлечения
Шаги 1-3: Запрос, эмбеддинг, поиск
Модуль RAG извлекает поисковый запрос из последнего сообщения пользователя (опционально переформулированный через LLM при query_reformulation = true), преобразует его в вектор с помощью провайдера эмбеддингов и выполняет поиск по всем бэкендам памяти одновременно -- векторное сходство (косинусное) и полнотекстовый поиск (FTS5/pg_trgm). Результаты объединяются и дедуплицируются.
Шаг 4: Фильтрация по релевантности
Каждый результат получает балл релевантности от 0.0 до 1.0. Результаты ниже relevance_threshold отбрасываются. Скоринг учитывает:
- Косинусное сходство векторов (основной сигнал)
- Балл полнотекстового совпадения (коэффициент усиления)
- Свежесть (более новые воспоминания получают небольшое преимущество)
- Приоритет источника (основные воспоминания ранжируются выше разговорных)
Шаг 5: Внедрение контекста
Отфильтрованные результаты форматируются структурированными XML-тегами (<context><memory source="..." relevance="...">) и внедряются в промпт LLM. Общий внедрённый контекст ограничен max_context_tokens для предотвращения переполнения контекстного окна.
Стратегии выбора
Top-K
Стратегия по умолчанию. Выбирает K чанков с наивысшими баллами, вмещающихся в max_context_tokens. Простая и предсказуемая, но может возвращать избыточные результаты, когда несколько чанков покрывают одну тему.
Максимальная маргинальная релевантность (MMR)
MMR балансирует релевантность с разнообразием. Она итеративно выбирает чанки, которые одновременно релевантны запросу и отличаются от уже выбранных:
[rag]
selection_strategy = "mmr"
# Lambda управляет балансом релевантность-разнообразие.
# 1.0 = чистая релевантность (аналогично top_k)
# 0.0 = чистое разнообразие
mmr_lambda = 0.7MMR рекомендуется, когда база знаний содержит перекрывающуюся или избыточную информацию.
Индексация документов
Автоматическая индексация
Воспоминания, сохранённые через инструмент memory_store, автоматически преобразуются в эмбеддинги и индексируются. Дополнительная настройка не требуется.
Ручная загрузка документов
Для массовой загрузки документов используйте CLI:
# Индексация одного файла или каталога
prx rag index /path/to/document.md
prx rag index /path/to/docs/ --recursive
# Переиндексация всех документов (пересоздание эмбеддингов)
prx rag reindexПоддерживаемые форматы: Markdown (.md), простой текст (.txt), PDF (.pdf), HTML (.html) и исходный код (.rs, .py, .js).
Тонкая настройка производительности
| Параметр | Рекомендация |
|---|---|
chunk_size | 256-512 токенов для Q&A, 512-1024 для суммаризации |
chunk_overlap | 10-20% от chunk_size |
max_results | 5-15 для большинства сценариев |
relevance_threshold | 0.3-0.5 (настраивайте по качеству) |
Замечания по безопасности
- RAG-контекст внедряется в промпт LLM. Убедитесь, что сохранённые документы не содержат конфиденциальных данных, если агент не авторизован для доступа к ним.
- При
memory.acl_enabled = trueRAG соблюдает списки контроля доступа. Извлекаются только воспоминания, доступные текущему принципалу. - Вызовы API эмбеддингов передают содержимое документов провайдеру эмбеддингов. Для конфиденциальных данных используйте локальный провайдер (
ollamaилиlocal).