Skip to main content
Glama
Mily-Lv
by Mily-Lv

RAG-MCP-SERVER

Модульный RAG-сервис с подключаемой архитектурой и сквозной наблюдаемостью. Предоставляет возможности поиска в виде инструментов MCP (Model Context Protocol) и может напрямую вызываться MCP-клиентами, такими как Claude Desktop, GitHub Copilot.

Основная цель дизайна — решить две конкретные болевые точки в RAG-инженерии:

  1. Трудно локализовать проблему в пайплайне — результат поиска неверный, проблема в извлечении, слиянии или переранжировании? На всех 10 этапах двух контуров — индексации и запроса — поэтапно фиксируются время выполнения, число кандидатов, оценки и изменения ранжирования, Dashboard позволяет визуально отследить историю.

  2. Настройка по ощущениям — стало ли лучше или хуже от смены модели Embedding? Совместная оценка Hit Rate@K / MRR и Ragas Faithfulness / Context Precision на фиксированном тестовом наборе даёт регрессию; калибровка по метрикам, а не по субъективным суждениям.


Оглавление


Related MCP server: mcp-rag-assistant

Обзор архитектуры

                    ┌──────────────────────────────────────────┐
  文档 (PDF/DOCX/    │           Ingestion Pipeline             │
  MD/TXT)      ───▶ │  load → split → transform → embed →      │
                    │  upsert                                  │
                    └────────────────┬─────────────────────────┘
                                     │  SHA256 指纹 + SQLite 摄取历史
                                     │  (文档级增量索引 / 幂等)
                                     ▼
                    ┌──────────────────────────────────────────┐
                    │   ChromaDB (Dense)  +  BM25 (Sparse)     │
                    └────────────────┬─────────────────────────┘
                                     ▼
                    ┌──────────────────────────────────────────┐
  查询          ───▶│            Query Engine                  │
                    │  query_processing → dense ┐              │
                    │                            ├→ RRF fusion │
                    │                    sparse ┘      │       │
                    │                                  ▼       │
                    │                              rerank      │
                    │                    (失败回退至 RRF 顺序) │
                    └────────────────┬─────────────────────────┘
                                     ▼
             ┌───────────────┬───────────────┬──────────────────┐
             │  MCP Server   │  CLI Scripts  │  Dashboard       │
             │  (3 tools)    │  (5 scripts)  │  (Streamlit 6页) │
             └───────────────┴───────────────┴──────────────────┘

  贯穿全程:TraceContext(trace → stage)写入 logs/traces.jsonl

Подключаемая платформа

Для каждого ключевого этапа определён единый базовый интерфейс Base; переключение осуществляется через Factory + YAML-конфигурацию, замена компонента не требует изменений кода:

Этап

Интерфейс

Реализованные Provider

LLM

BaseLLM

openai / azure / deepseek / kimi / ollama

Vision LLM

BaseVisionLLM

openai / azure / kimi

Embedding

BaseEmbedding

openai / azure / siliconflow / bge / ollama

Vector Store

BaseVectorStore

chroma

Splitter

BaseSplitter

recursive

Reranker

BaseReranker

llm / cross_encoder (BGE)

Evaluator

BaseEvaluator

custom / ragas / composite

Loader

BaseLoader

pdf / docx / markdown / text

Любая OpenAI-совместимая конечная точка подключается через provider: "openai" + собственный base_url без добавления нового кода.


Ключевые возможности

Гибридный поиск: BM25-разрежённый поиск отвечает за точное совпадение по собственным именам и терминам, Dense-векторный поиск — за смысловое соответствие; после двунаправленного извлечения кандидатов выполняется слияние RRF, затем точное ранжирование Reranker. Если бэкенд-переранжировщик не срабатывает, автоматически выполняется откат к порядку слияния RRF: один таймаут не прерывает весь пайплайн.

Инкрементальная индексация и идемпотентность: отпечаток содержимого SHA256 + таблица SQLite ingestion_history обеспечивают документно-уровневую инкрементность. Повторная загрузка пропускается, перестройка выполняется только при изменении содержимого; дублирующееся добавление не создаёт грязных данных.

Мультимодальность: PyMuPDF извлекает встроенные изображения из PDF с сохранением исходных позиций, Vision LLM формирует описание картинки и вшивает его в Chunk, что позволяет переиспользовать чисто текстовый RAG-пайплайн для «поиска текстом с выдачей изображений». Ответ MCP возвращает картинку через ImageContent.

Инструменты MCP:

Tool

Назначение

query_knowledge_hub

гибридный поиск + переранжирование, результат с указанием источников (включая изображения)

list_collections

список всех коллекций со статистикой по документам/чанк-ам

get_document_summary

сводка и обзор чанков для указанного документа

Dashboard (Streamlit, и страницы): обзор системы / просмотр данных / управление загрузкой / трассировка загрузки / трассировка запросов / панель оценки.


Быстрый старт

Требования к окружению

Python ≥ 3.10.

Установка

git clone <your-repo-url>
cd RAG-MCP-SERVER

python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux / macOS
source .venv/bin/activate

pip install -e ".[dev]"

У всех зависимостей заданы верхние границы версий. mcp зафиксирован на <2.0 (в 2.x переименованы такие поля, как CallToolResult.isError), langchain-community — на <0.4 (в 0.4 удалён chat_models.vertexai, из-за чего может не собраться импорт ragas).

Конфигурация

cp config/settings.yaml.example config/settings.yaml

Отредактируйте файл config/settings.yaml, указав свои API-ключи. Этот файл уже входит в .gitignore, не добавляйте его в репозиторий.

Загрузка документов

python scripts/ingest.py --path ./your_docs --collection my_kb
python scripts/ingest.py --path ./your_docs --collection my_kb --force   # 强制重建
python scripts/ingest.py --path ./your_docs --dry-run                    # 只看会处理哪些文件

Запрос

python scripts/query.py -q "你的问题" -c my_kb --top-k 5 --verbose

Параметр --verbose выводит промежуточные результаты для dense / sparse / fusion / rerank.

Запуск Dashboard

python scripts/start_dashboard.py

Подключение MCP-клиента

На примере Claude Desktop, в файл claude_desktop_config.json добавьте:

{
  "mcpServers": {
    "rag-mcp-server": {
      "command": "<绝对路径>/.venv/Scripts/python.exe",
      "args": ["<绝对路径>/main.py"]
    }
  }
}

Описание конфигурации

Ключевые секции конфигурации (полные комментарии см. в config/settings.yaml.example):

retrieval:
  dense_top_k: 20
  sparse_top_k: 20
  fusion_top_k: 10
  rrf_k: 60
  # 路由开关,用于 A/B 基线:只测 dense 则 enable_sparse: false,反之亦然
  enable_dense: true
  enable_sparse: true

rerank:
  enabled: true
  provider: "llm"           # 走已配置的 LLM,零额外依赖
  # provider: "cross_encoder"  # 本地 BGE cross-encoder,需 pip install sentence-transformers
  top_k: 5

evaluation:
  enabled: true
  provider: "composite"     # 同时跑检索指标与生成指标
  backends: ["custom", "ragas"]
  metrics: ["hit_rate", "mrr", "faithfulness", "context_precision"]

embedding.dimensions нельзя менять после первой загрузки — существующая коллекция Chroma привязана к размерности векторов.


Наблюдаемость

Каждое добавление и каждый запрос создают trace, записываемый в logs/traces.jsonl, и структура trace → stages[]; каждый stage записывает elapsed_ms и data этого этапа.

Контур

Этапы

Ingestion

load → split → transform → embed → upsert

Query

query_processing → dense_retrieval → sparse_retrieval → fusion → rerank

Отслеживание изменений ранга

Если записывать только списки оценок по завершении каждого этапа, невозможно ответить на вопрос «улучшил ли этап порядок и какой конкретный чанк переместился». Поэтому этапы fusion и rerank дополнительно фиксируют изменения ранга (src/core/query_engine/rank_tracking.py):

  • нумерация с 1; rank_delta = rank_before - rank_after, положительное значение означает повышение ранга

  • для fusion в качестве rank_before берётся лучший ранг чанка среди двух каналов, то есть ответ на вопрос «поднял ли RRF его с уровня одного канала»; одновременно фиксируются dense_rank / sparse_rank, показывающие, каким из каналов был найден чанк

  • для rerank в качестве rank_before используется позиция чанка в объединённом списке, переданном ранкеру; это точно показывает, кого ранкер улучшил, а кого понизил

  • для новов вошедших чанков указывается None, а не поддельное повышение ранга

  • сводка уровня этапа: moved_up / moved_down / new / max_gain / max_drop / dropped

Фрагмент реального trace:

stage=fusion   elapsed=0.2ms
  rank_changes: {moved_up: 3, moved_down: 1, unchanged: 1, max_gain: 2, dropped: 18}
  rank=2  before=4  delta=+2   dense_rank=4  sparse_rank=4

stage=rerank   elapsed=12231ms
  rank_changes: {moved_up: 1, moved_down: 1, unchanged: 3, max_gain: 1}
  rank=1  before=2  delta=+1

На странице «Трассировка запросов» Dashboard это отображается в виде каскадной диаграммы этапов и таблицы изменения ранних позиций.


Система оценки

python scripts/evaluate.py --collection my_kb
python scripts/experiment.py --variants dense,sparse,hybrid,hybrid_rerank
  • Метрики извлечения (CustomEvaluator): Hit Rate@K, MRR — требует, чтобы тестовый набор предоставлял expected_chunk_ids в качестве ground truth

  • Метрики генерации (RagasEvaluator): Faithfulness, Answer Relevancy, Context Precision

  • CompositeEvaluator запускает оба типа бэкенда одновременно и объединяет результаты; каждый бэкенд выбирает из общего списка metrics свои метрики другого, сбой одного бэкенда не влияет на остальные

scripts/experiment.py предназначен для A/B-сравнения различных вариантов поиска и выводит метрики и задержки каждого варианта, чтобы ответить на вопрос «стоит ли включение rerank этих 12 секунд».


Тестирование

Многофакторное тестирование, всего 1456 тестов:

pytest tests/unit                      # 1298 passed, 1 skipped
pytest tests/integration -m "not llm"  #   94 passed, 10 skipped
pytest tests/e2e -m "not llm"          #   30 passed,  2 skipped

С параметром -m "not llm" исключаются тесты, требующие реальных API-вызовов LLM. При отсутствии учётных данных для какого-либо Provider соответствующие тесты пропускаются методом skip с указанием причины, а не падают.

Критические ветви покрыты целевыми тестами:

Ключевая зона

Тесты

слияние RRF

test_fusion_rrf.py

путь отката reranker

test_reranker_fallback.py

идемпотентная вставка

test_vector_upserter_idempotency.py

отслеживание изменений ранга

test_rank_tracking.py

согласованность токенизатора

test_sparse_encoder.py / test_query_processor.py

параллельное создание Chroma-клиента

test_chroma_client.py

контракт хранилища векторных данных

test_vector_store_contract.py


Структура проекта

src/
├── core/
│   ├── query_engine/       # 混合检索:dense / sparse / RRF fusion / rerank
│   │   └── rank_tracking.py  # 排名变化计算(融合与重排共用)
│   ├── response/           # 响应组装、引用生成、多模态拼装
│   ├── trace/              # TraceContext:trace → stage
│   ├── tokenization.py     # BM25 分词器(索引端与查询端唯一实现)
│   └── settings.py         # YAML 配置加载与校验
├── ingestion/
│   ├── chunking/ embedding/ storage/ transform/
│   ├── pipeline.py         # 五阶段摄取流水线
│   └── document_manager.py # 文档删除(跨 Chroma / BM25 / 图片 / 摄取历史)
├── libs/                   # 可插拔底座:base_*.py + *_factory.py
│   ├── llm/ embedding/ loader/ reranker/ splitter/ vector_store/ evaluator/
├── mcp_server/             # MCP 协议与 3 个 Tool
└── observability/
    ├── dashboard/          # Streamlit 六页
    └── evaluation/         # ragas / composite / eval_runner

scripts/   ingest / query / evaluate / experiment / start_dashboard
config/    settings.yaml.example + prompts/
tests/     unit / integration / e2e

data/ (Chroma, BM25-индекс, извлечённые изображения, история загрузок) и logs/ (trace) — это локально генерируемые во время выполнения артефакты; они исключены через .gitignore, не входят в репозиторий и создаются автоматически при первом запуске.


License

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides RAG-based knowledge retrieval and document management as MCP tools, supporting hybrid search, reranking, and retrieval process visualization.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    A pluggable, observable modular RAG framework that exposes query knowledge hub, list collections, and get document summary tools via MCP, enabling AI assistants to perform hybrid search and document retrieval with reranking.
    2
    MIT