self_rag_mcp
Self-RAG 检索引擎
自反思检索增强生成 系统,基于 LangGraph 和 Qdrant 构建,并通过 SSE 传输以 MCP(模型上下文协议)服务器形式对外提供。
与盲目检索并生成的标准 RAG 流水线不同,Self-RAG 让 LLM 成为自身质量控制的积极参与者——决定是否检索、对检索结果进行评分、验证生成内容,并在答案不够好时进行重试。
目录
Related MCP server: mcp-rag-agent
什么是 Self-RAG?
标准 RAG 存在一个根本性问题:它总是执行检索(即使没有必要),从不检查检索到的文档是否相关,也从不验证生成的答案是否真正基于这些文档。
Self-RAG(首次提出于论文 Self-RAG: Learning to Retrieve, Generate, and Critique Through Self-Reflection)通过在每个阶段插入反思步骤来解决这一问题:
阶段 | 标准 RAG | Self-RAG |
检索决策 | 总是检索 | LLM 决定是否需要检索 |
文档过滤 | 使用所有检索到的文档 | LLM 对每个文档的相关性进行评分 |
生成 | 只生成一次 | 生成,然后验证是否基于上下文 |
答案质量 | 不检查 | LLM 对有用性进行评分,必要时重试 |
本实现使用 LangGraph 将 Self-RAG 流程建模为带条件边的有状态有向图,支持动态路由、重试循环和完整的状态可追溯性。
架构概览
┌─────────────────────────────────────────────────────────────────┐
│ MCP Client (SSE) │
│ rich interactive terminal │
└──────────────────────────┬──────────────────────────────────────┘
│ SSE http://127.0.0.1:8000/sse
┌──────────────────────────▼──────────────────────────────────────┐
│ MCP Server (SSE) │
│ MCPServer · 3 tools exposed │
│ rag_answer · retrieve · server_health │
└──────────┬──────────────────────────────┬───────────────────────┘
│ │
┌──────────▼──────────┐ ┌───────────▼──────────────────────┐
│ Self-RAG Graph │ │ Hybrid Retriever │
│ (LangGraph) │ │ │
│ │ │ 1. Qdrant Hybrid Search │
│ retrieval_decision │ │ Dense (OpenAI embeddings) │
│ retrieve │ │ Sparse (BM25 / FastEmbed) │
│ relevance_grader │ │ Fusion: RRF │
│ context_builder │ │ │
│ generator │ │ 2. MMR Diversity Reranking │
│ support_grader │ │ │
│ usefulness_grader │ │ 3. FlashRank Cross-Encoder │
│ │ │ (ms-marco-MiniLM-L-12-v2) │
└──────────┬──────────┘ │ │
│ │ 4. Parent Document Expansion │
│ └───────────────┬──────────────────┘
│ │
┌──────────▼──────────────────▼──────────────────────────────────┐
│ Qdrant │
│ │
│ self_rag_documents (child chunks · dense + sparse) │
│ self_rag_parents (parent chunks · dense only) │
└─────────────────────────────────────────────────────────────────┘Self-RAG 图流程
flowchart TD
START([START]) --> RD[retrieval_decision]
RD -->|should_retrieve = true| RET[retrieve]
RD -->|should_retrieve = false| GEN[generator]
RET --> REL[relevance_grader]
REL --> CTX[context_builder]
CTX --> GEN
GEN --> SUP[support_grader]
SUP -->|fully_supported\npartially_supported| USE[usefulness_grader]
SUP -->|not_supported\n& retry_count < max_retries| INC1[increment_retry]
SUP -->|not_supported\n& retry_count >= max_retries| USE
INC1 --> GEN
USE -->|useful| END([END])
USE -->|not_useful\n& retry_count >= max_retries| END
USE -->|not_useful\n& retry_count < max_retries| INC2[increment_retry_for_retrieval]
INC2 --> RET
style START fill:#2d6a4f,color:#fff
style END fill:#2d6a4f,color:#fff
style RD fill:#1d3557,color:#fff
style RET fill:#457b9d,color:#fff
style REL fill:#457b9d,color:#fff
style CTX fill:#457b9d,color:#fff
style GEN fill:#e63946,color:#fff
style SUP fill:#f4a261,color:#000
style USE fill:#f4a261,color:#000
style INC1 fill:#6d6875,color:#fff
style INC2 fill:#6d6875,color:#fff节点参考
retrieval_decision
图的入口点。LLM 分析用户的问题,并决定是否确实需要外部知识检索。
对话式查询(
"Hello"、"What is 2+2")→ 跳过检索,直接进入generator事实性 / 领域性查询 → 进入
retrieve
使用结构化输出:RetrievalDecision { thought: str, answer: "YES" | "NO" }
retrieve
针对 Qdrant 运行完整的混合检索流水线:
混合搜索 — 结合稠密(OpenAI
text-embedding-3-small)和稀疏(通过 FastEmbed 实现的 BM25)向量,在服务端使用倒数排名融合(RRF)进行融合MMR — 最大边际相关性重排序,以增加多样性(避免返回近乎重复的块)
FlashRank — 轻量级 ONNX 交叉编码器重排序器(
ms-marco-MiniLM-L-12-v2),用于最终相关性评分父块扩展 — 子块用于精确检索,但将完整父块返回给 LLM 以提供更丰富的上下文
relevance_grader
过滤检索到的文档。LLM 针对问题对每个文档逐一评分。
评分为
YES的文档 → 保留为relevant_documents评分为
NO的文档 → 丢弃
使用结构化输出:RelevanceGrade { thought: str, answer: "YES" | "NO" }
context_builder
将相关文档格式化为结构化的 XML 上下文块,针对 LLM 注意力进行优化:
<context>
<document index="1">
<metadata>Source: hr.pdf | Relevance Score: 0.9821</metadata>
<content>
Human Resource Management (HRM) refers to...
</content>
</document>
</context>generator
LLM 仅使用上下文块中的事实生成答案。提示词明确指示模型不要使用外部知识,并引用文档索引([Doc 1])。
support_grader
验证生成的答案是否基于上下文。逐条声明进行审计。
返回以下之一:
fully_supported— 每条声明都有上下文支撑partially_supported— 部分声明有依据,部分没有not_supported— 答案包含幻觉或与上下文矛盾
使用结构化输出:SupportGrade { thought: str, label: "fully_supported" | "partially_supported" | "not_supported" }
usefulness_grader
评估答案是否真正解决了用户的问题——即使答案有依据,也可能回避问题或不完整。
返回以下之一:
useful— 答案直接满足查询not_useful— 答案偏离主题、不完整或回避问题
使用结构化输出:UsefulnessGrade { thought: str, label: "useful" | "not_useful" }
increment_retry / increment_retry_for_retrieval
簿记节点,在循环回 generator 或 retrieve 之前递增图状态中的 retry_count。
路由逻辑
路由器 | 条件 | 下一节点 |
|
|
|
|
| |
|
|
|
|
| |
|
| |
|
|
|
|
| |
|
|
检索流水线
Query
│
▼
Qdrant Hybrid Search (Dense + BM25 + RRF) k=20 candidates
│
▼
MMR Diversity Reranking k=15 diverse docs
│
▼
FlashRank Cross-Encoder top_k=4 final docs
│
▼
Parent Document Expansion fetch full parent chunks
│
▼
List[Document] → relevance_grader为什么采用这种多阶段漏斗?
混合搜索(稠密 + 稀疏)比单独使用任何一种都能获得更好的召回率——稠密向量捕捉语义匹配,BM25 捕捉精确关键词匹配
MMR 防止 LLM 看到 4 个近乎相同的块——强制多样性
FlashRank(ONNX int8 量化)以约 0.1 秒的时间提供交叉编码器质量,而完整的 PyTorch CrossEncoder 需要约 19 秒
父块扩展意味着检索精度来自小子块,但 LLM 获得的是完整的周边上下文
摄取流水线
文档被分割为父子块层级结构:
PDF Document
│
├── Parent Chunk 1 (1200 chars, overlap=0) → stored in self_rag_parents
│ ├── Child Chunk 1a (600 chars, overlap=150) → stored in self_rag_documents
│ ├── Child Chunk 1b
│ └── Child Chunk 1c
│
├── Parent Chunk 2
│ ├── Child Chunk 2a
│ └── Child Chunk 2b
...子块同时使用稠密 + 稀疏向量进行索引,以实现混合搜索精度
父块仅存储稠密向量,用于检索后的上下文扩展
UUID 是确定性的(UUID5),因此重新摄取是幂等的
MCP 服务器与客户端
该系统以 MCP 服务器形式通过 SSE 传输对外提供,兼容任何 MCP 客户端(Claude Desktop、自定义客户端等)。
工具
工具 | 描述 |
| 运行完整的 Self-RAG 图——检索决策 → 检索 → 评分 → 生成 → 验证 → 重试 |
| 仅进行原始混合检索,不进行生成或评分 |
| 返回检索器和重排序器组件的运行状态 |
交互式客户端
包含一个功能丰富的终端客户端,提供菜单驱动界面:
╭─────────────────────────────────╮
│ Self-RAG MCP Interactive Client │
│ Connected via SSE Transport │
╰─────────────────────────────────╯
[1] 💬 Ask Question (rag_answer)
[2] 🔍 Raw Search (retrieve)
[3] 🏥 System Health (server_health)
[4] 📋 List Tools
[0] 🚪 Exit项目结构
self_rag_retrieval/
├── src/self_rag/
│ ├── clients/
│ │ ├── llm.py # LiteLLM chat model + OpenAI embeddings (cached)
│ │ └── qdrant.py # Qdrant client singleton
│ ├── core/
│ │ └── config.py # Pydantic settings from .env
│ ├── graph/
│ │ ├── engine.py # Compiled graph singleton (lru_cache)
│ │ ├── routes.py # Conditional edge routing functions
│ │ └── workflow.py # LangGraph StateGraph definition
│ ├── ingestion/
│ │ ├── chunker.py # Parent-child chunk splitting
│ │ ├── indexer.py # Qdrant collection management
│ │ ├── loaders.py # PDF loader
│ │ └── pipeline.py # Ingestion orchestration
│ ├── mcp/
│ │ ├── server.py # MCPServer with 3 tools + startup warmup
│ │ ├── mcp_client.py # Rich interactive terminal client
│ │ └── tools.py # Tool implementations (answer, retrieve, health)
│ ├── models/
│ │ ├── graph_state.py # LangGraph TypedDict state
│ │ └── schemas.py # Pydantic structured output schemas
│ ├── nodes/
│ │ ├── context_builder.py # XML context formatter
│ │ ├── generator.py # LLM answer generation
│ │ ├── relevance_grader.py # Per-document relevance grading
│ │ ├── retrieval_decision.py # Retrieval necessity classifier
│ │ ├── retrieve.py # Retrieval node
│ │ ├── support_grader.py # Hallucination / grounding checker
│ │ └── usefulness_grader.py # Answer quality checker
│ ├── prompts/
│ │ ├── generation.py
│ │ ├── relevance.py
│ │ ├── retrieval.py
│ │ ├── support.py
│ │ └── usefulness.py
│ ├── retrieval/
│ │ ├── mmr.py # Maximal Marginal Relevance
│ │ ├── reranker.py # FlashRank ONNX cross-encoder
│ │ ├── retriever.py # HybridRetriever orchestrator (cached)
│ │ └── vector_store.py # Qdrant vector store (dense + sparse, cached)
│ └── services/
│ └── rag_service.py # Business layer wrapping the graph
├── scripts/
│ └── ingest.py # CLI ingestion script
├── tests/
│ ├── test_mcp_server.py
│ ├── test_mcp_tools.py
│ └── test_routes.py
├── docker-compose.yaml
├── pyproject.toml
└── .env安装与配置
前置条件
Python 3.12+
uv 包管理器
Docker(用于 Qdrant)
OpenRouter API 密钥
1. 克隆仓库并安装依赖
git clone <repo-url>
cd self_rag_retrieval
uv sync2. 配置环境
cp .env.example .env编辑 .env:
OPENROUTER_API_KEY=sk-or-v1-...
CHAT_MODEL=openrouter/openai/gpt-4.1-mini
EMBEDDING_MODEL=openai/text-embedding-3-small
QDRANT_URL=http://localhost:6333
QDRANT_COLLECTION=self_rag_documents
QDRANT_PARENT_COLLECTION=self_rag_parents
DATA_DIR=src/self_rag/data3. 启动 Qdrant
docker compose up -d4. 添加文档
将 PDF 文件放入 src/self_rag/data/。
5. 摄取文档
# First time
uv run python scripts/ingest.py
# Full rebuild (wipes existing collections)
uv run python scripts/ingest.py --reset配置
所有设置都在 .env 中,并由 Pydantic 验证。关键参数:
变量 | 默认值 | 描述 |
|
| 用于所有评分和生成节点的 LLM |
|
| 稠密嵌入模型 |
|
| 子块大小(字符) |
|
| 子块重叠 |
|
| 父块大小(字符) |
|
| 混合搜索候选池 |
|
| MMR 多样性过滤后的文档 |
|
| FlashRank 后的最终文档 |
|
| 最大 Self-RAG 重试循环 |
|
| LLM 温度(0 = 确定性) |
运行系统
终端 1 — 启动 MCP 服务器
uv run python src/self_rag/mcp/server.py服务器在接受连接之前会预热所有模型:
INFO Warming up retriever...
INFO Warming up reranker...
INFO Warming up graph...
INFO Warmup complete — server ready.
INFO Uvicorn running on http://127.0.0.1:8000终端 2 — 启动交互式客户端
uv run python src/self_rag/mcp/mcp_client.py示例问题(HR 领域)
What is Human Resource Management and what are its main objectives?
What are the nine broad areas of HRM activities identified by ASTD?
What is the difference between training and organizational development?
How does compensation and benefits management work in HRM?
What is the role of HRM in the new millennium?
What is the significance of HR planning in an organization?
Explain the scope of HRM and what it covers in an employee's working life.运行测试
uv run pytest tests/ -vtests/test_routes.py::test_retrieval_decision_retrieve PASSED
tests/test_routes.py::test_retrieval_decision_skip PASSED
tests/test_routes.py::test_support_fully_supported_... PASSED
tests/test_routes.py::test_support_not_supported_retries... PASSED
tests/test_routes.py::test_usefulness_useful_ends PASSED
...
24 passed测试覆盖:
test_routes.py— 所有路由分支(检索决策、支持评分、有用性评分)test_mcp_tools.py— 使用模拟的 Qdrant/LLM 测试工具函数(空输入、截断、异常、健康检查)test_mcp_server.py— 服务器类型、工具注册、工具描述
技术栈
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAdaptive Retrieval-Augmented Self-Refinement MCP Server — a closed-loop system that lets LLMs iteratively verify and correct their own claims using uncertainty-guided retrieval.111MIT
- AlicenseNot gradedqualityBmaintenanceEnables document-based Q&A with multi-modal RAG, hybrid retrieval, knowledge graph reasoning, and multi-agent orchestration via MCP tools.4MIT
- FlicenseNot gradedqualityBmaintenanceExposes a Retrieval-Augmented Generation pipeline as MCP tools, allowing users to index documents and query them through any MCP-compatible client like Claude or IDEs.
- AlicenseNot gradedqualityBmaintenanceMCP server providing tools for entity extraction, query refinement, and relevance checking to build Agentic RAG applications.MIT
Related MCP Connectors
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
MCP server exposing the Backtest360 engine API as tools for AI agents.
MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/FireWizard-V9/self_rag_mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server