agentic-rag
agentic-rag
基于真实语料库的、带引用且感知修订版本的检索——语料来自 IETF RFC 生态系统:RFC 全文、RFC 索引中真实的 Obsoletes/Obsoleted-by/Updates 取代关系图、真实的社区提交的 RFC 勘误,以及真实的 IANA 协议参数注册表——通过 HTTPS 获取(corpus_fetch/),并经 ragpack 摄取到可搜索的向量存储中(321,124 个真实分块),然后通过 consilium 主干进行路由和引用门控。
提出一个关于 IETF 协议规范、RFC 的作者/状态、真实勘误修正或 IANA 注册表条目的真实问题,得到的答案将完全由真实引用的分块构成——或者诚实地弃答。唯一的例外是废弃问题(“什么取代了 RFC 2616?”):RFC 2616 自身文本没有“当前修订版”可检索(它被六份后续文档完全取代,即 RFC 7230-7235——IETF 著名的多路废弃案例),因此该问题由 SupersessionModule 回答,这是一个对真实 Obsoletes/Obsoleted-by 图进行确定性图查找的模块,而非检索。答案路径中没有任何 LLM。
快速开始
git clone https://github.com/trentmilam/agentic-rag
cd agentic-rag
py -3.12 -m venv .venv
.venv\Scripts\python -m pip install -r requirements.txt
.venv\Scripts\python -m pip install -e .
.venv\Scripts\python scripts\verify.py这就是整个引导过程。可编辑安装使得 import consilium、import ragpack、import linkgraph、import activerag 和 import chainrag 能够解析——pyproject.toml 的 package-dir 将每个名称映射到 packages/ 中。
Related MCP server: 3GPP Evidence Graph
一个仓库,五个合并的工具
agentic-rag 过去通过将 consilium 和 linkgraph 的根目录插入 sys.path 来从兄弟仓库导入它们,并要求 RAGpack 从第三个仓库以可编辑方式 pip 安装。克隆它意味着克隆四个仓库,三个提交分别固定在三份不同的文件中——这些文件已经彼此漂移。linkgraph 还读取本仓库的数据文件,因此这两个工具跨仓库边界相互导入。
现在它们是一个仓库了。每个合并的工具都将其整个树保留在 packages/<name>/ 下,因此它相对于自身根目录解析的所有内容仍然可以解析,并且每个工具都保留了自己的提交历史,而不是被压缩成一个导入提交:
包 | 是什么 | 测试 |
路由/引用门控主干:Registry、Router、compose、完整性门、ComputeModule | 5 个评估套件 | |
摄取、分块、嵌入、Qdrant 存储封装器 | 20 | |
MCP 关系工具背后的跨文档关系图 | 50 | |
证据稀疏性检测和有界搜索重试 | 54 | |
基于区块链协议文档的第二个垂直领域,证明主干并非特定于语料库 | -- |
它们嵌套在 packages/ 下而不是放在仓库根目录,这是有具体原因的:名为 consilium 的顶层目录会作为隐式命名空间包遮蔽 consilium 包,因为工作目录在 sys.path 上先于可编辑安装。导入随后解析到一个空命名空间,consilium.__file__ 为 None。CI 断言每个包都解析到本仓库内的文件,因此这类静默错误绑定会导致构建失败,而不是让所有测试针对错误的副本通过。
rag-reliability 是唯一仍在本仓库之外的依赖。它为上述三个工具提供 graphrx、headroom、vecstamp、chunkledger、plumbline 和 legigate,目前通过路径解析;将其打包为声明式依赖是待办事项。CI 以固定版本检出它,并且如果这些集成测试被跳过则失败,因此唯一剩余的路径依赖不会在无人注意的情况下腐烂。
语料库
来源类型 | 是什么 | 真实分块 | 当前(未废弃) |
| RFC 全文(逐字) | 306,939 | 225,809 |
| 每个 RFC 的索引卡片(标题/作者/日期/状态/废弃/更新) | 5,854 | 4,663 |
| 真实的社区提交的 RFC 修正 | 7,295 | 7,295(不适用——无修订概念) |
| 7 个真实的 IANA 协议参数注册表,渲染为 Markdown 表格 | 1,036 | 1,036(不适用——无修订概念) |
总共 321,124 个真实分块,使用真实的 BAAI/bge-base-en-v1.5 模型嵌入。rfc_text/rfc_index 是仅有的具有修订概念的来源类型——那里的 is_current 是真实的结构性事实(参见修订保护),而非猜测。
五个模块,一个路由器
agenticrag/bootstrap.py::build_registry 组装了一个真实的 5 模块 consilium Registry:上述 4 个检索模块(每个都直接从 Qdrant 加载,默认 current_only=True——参见 agenticrag/registry_loader.py),加上 SupersessionModule(agenticrag/supersession.py),一个 ComputeModule,在构造时解析 data/entities/revisions.json——实时索引中所有 9,794 个 RFC 的真实 Obsoletes/Obsoleted-by 图——并以确定性的、循环安全的图遍历(限制在 50 个访问节点——这是一个防御性上限,并非预期的真实限制;真实的 IETF 废弃组件很小)回答废弃问题。
build_registry 还会在进程配置的嵌入器与摄取存储时使用的嵌入器不匹配时大声失败(首先调用 verify_embedder_marker)——否则余弦分数将静默地毫无意义——并在模块加载后关闭它自己打开的任何 Qdrant 客户端(之后检索完全在内存中进行),因此它不会在调用者的整个进程生命周期内持有本地模式存储的锁。
errata 的 trust_tier(0.55,远低于 rfc_text/rfc_index/iana_registry 的 0.9-0.95)是测量出来的,而非猜测:在摄取的 5,061 条真实勘误记录中,只有 2,400 条(47.4%)被 RFC 编辑确认为 Verified——1,781 条(35.2%)为 Held for Document Update,679 条(13.4%)被直接 Rejected,201 条(4.0%)仍为 Reported。不到一半的真实提交修正得到 RFC 编辑确认,因此该模块在修正主要文本的同时,自身并非统一权威。
MCP 服务器
agenticrag/mcp/server.py 将答案路径暴露为基于 stdio 的 Model Context Protocol 服务器(mcp>=1.28.1,FastMCP)。四个工具:
search(query)—— 完整的带引用/弃答答案路径(consilium.compute.answer_v3),原样传递(诚实的弃答保持弃答);get_obsoletion_chain(rfc_id)/get_corrections(rfc_id)/get_related(entity_id)—— 关系图,通过linkgraph兄弟包(agenticrag/relationships.py);如果该兄弟包缺失,每个都返回一个文档化的{"ok": false, "fallback": ...}信封。
运行它:.venv\Scripts\python -m agenticrag.mcp.server(stdio 传输——MCP 客户端启动它并通过 stdin/stdout 说协议)。工具逻辑是轻导入的,没有 mcp/Qdrant 依赖,因此可以在没有这两者的情况下进行单元测试(agenticrag/mcp/test_server.py)。
验证
快速验证(快速,无需语料库——不需要已摄取的语料库):
verify.bat :: or: .venv\Scripts\python -m pytest -q运行 MCP 工具包装器测试和废弃图遍历的循环安全套件。这是 CI 在每次推送时运行的内容(参见上面的徽章)。
完整验证(需要快速开始中已摄取的 321k 分块语料库):
.venv\Scripts\python eval\eval_agenticrag.py在已摄取语料库的情况下是确定性的;无需重新摄取。使用真实的嵌入器——正是摄取语料库时使用的那个——因此这证明了端到端的真实语义检索,而不仅仅是接线。在此硬件上大约需要 ~3.3 分钟(实测,完整运行:196 秒):一次性的 ~60 秒注册表构建(对语料库进行一次扫描以找出小的毒物隔离集——不是加载全部 321k 向量),然后路由器/答案传递每次约 ~12 秒。每次传递都将路由和检索作为原生 Qdrant 向量搜索运行;Qdrant 的嵌入式本地模式是精确的暴力搜索(无 ANN 索引),因此搜索仍会扫描过滤后的子集——但在原生代码中,仅物化 top-k,比旧的纯 Python 逐块扫描快约 ~16 倍。(亚秒级搜索需要 Qdrant 服务器模式的 HNSW 索引;本地模式保持仓库自包含——无需运行服务器。)它检查:每种来源类型的一个范围内查询(合理的模块 + >=1 个真实引用);RFC 2616 废弃查询(后继集合恰好为 {7230, 7231, 7232, 7233, 7234, 7235});一个范围外查询(诚实弃答);修订保护的结构性排除(见下文);一个真正当前的 RFC(791)解析为 current;以及一个不存在的 RFC 编号(99999)解析为 not_found,而不是崩溃。
eval/prove_revision_guard.py 是相同的结构性证明,作为独立的、带叙述的脚本。eval/smoke_ingest_real.py 使用零成本的 HashEmbedder 证明 fetch->ingest->Qdrant 接线(需要 corpus_fetch.fetch_all 已运行,但不需要 GPU/嵌入模型)。
修订保护,已证明
RFC 2616(HTTP/1.1)是一个真实的、单一的、完整的文档——它没有“当前修订版”;它被六份不同的文档完全取代。这里的保护属性是两个真实的、可检查的事实,而不是一个“修正值”:
结构性排除。 RFC 2616 自身的
rfc_text分块存在于 Qdrant 中(以current_only=False第二次加载rfc_text模块证明它们存在),但默认的current_only=True模块(每个查询实际使用的)中不存在——因为data/entities/revisions.json["RFC2616"]["obsoleted_by"]是真实的且非空。数据存在;它是被结构性过滤掉的,而不是意外缺失。正确的答案路径。
SupersessionModule是了解 RFC 2616 发生了什么情况的显式方式——一个命名它的查询返回真实的 6 路后继列表(RFC 7230-7235)。
路由器校准——测量而非猜测
consilium.router.Router 声明的库默认值(floor=0.11、anchor_centroid=0.25、anchor_best_chunk=0.25)假设不相关文本之间的基线余弦接近零——对于词袋 HashEmbedder 成立,但对于在 321k 分块语料库上的真实密集嵌入器不一定成立(即使在更小的 ~1,100 分块规模上也会出现同样的差距)。agenticrag/calibrate.py 直接针对真实语料库 + 真实嵌入器测量这一点,而不是假设它;参见 agenticrag/bootstrap.py::ROUTER_KWARGS 了解由此产生的每个实例 kwargs 以及证明该决策的真实数字。
.venv\Scripts\python agenticrag\calibrate.pyGPU 说明(仅摄取)
GPU 只对一步重要:语料库摄取(ingest/run_ingest.py),它通过 onnxruntime 使用 BAAI/bge-base-en-v1.5 嵌入约 ~321k 个分块。在查询时你只嵌入(短的)查询字符串,因此启动器在 CPU 上运行良好,无需 GPU 设置——这就是它们不再接触任何 GPU 配置的原因。
预期且无害的警告:如果安装了 onnxruntime-gpu,但其匹配的 CUDA 运行时 DLL 不在搜索路径上,你会看到一段醒目的红色 CUDAExecutionProvider / Error loading ... cublasLt64_*.dll ... missing 提示块——在任何运行中,无论是摄取还是查询,而不仅仅是摄取。这并非故障:onnxruntime 会回退到 CPU 并继续运行(对于查询,嵌入只是一个短字符串,因此 CPU 回退是即时的)。忽略它,或安装下面的 DLL 以消除该提示。
为了快速摄取,onnxruntime-gpu 的 CUDA 执行提供程序需要这些 CUDA 运行时 DLL 位于 DLL 搜索路径上。仅 pip install onnxruntime-gpu 不会捆绑它们,没有它们时 onnxruntime 会回退到 CPU(实测:~6 块/秒——计算得出:完整 321,124 块语料库约需 14.9 小时),而不是报错。要获得真正的 GPU 执行(实测:在 RTX 5090 上约 650 块/秒,即完整语料库约 8 分钟),请将匹配的 CUDA 运行时 wheel 安装到此仓库自己的 venv 中,例如:
.venv\Scripts\python -m pip install nvidia-cublas-cu13 nvidia-cudnn-cu13(将 -cuNN 后缀与你的 onnxruntime-gpu 构建的 CUDA 主版本匹配),或者在运行摄取之前,将任何支持 CUDA 的 PyTorch 安装的 torch/lib 目录放到 PATH 上。无论哪种方式,这都是一次性摄取的可选加速,绝不是运行演示或提供查询所必需的。
摄取重跑(已知限制)
ingest/run_ingest.py 支持从头开始的 --recreate 重建和快速增量路径(仅重新嵌入内容哈希发生变化的原始文件)。增量路径有两个已知限制,刻意未加以掩盖:(1)它仅根据每个原始文件的字节哈希来判断"已更改",因此如果某个 RFC 在后续的 rfc-index.txt 刷新中变为新废弃状态而其自身文本文件未变,其 is_current 标志可能会过期;(2)它不会删除因重新摄取而块数减少的文档的孤立 Qdrant 点。要获得保证一致性的存储,请运行 ingest/run_ingest.py --recreate(完整重建)。在增量路径中消除这两个限制是未来的工作。
布局
agenticrag/
embed_config.py shared Settings (model/qdrant path) + embedder-consistency guard
registry_loader.py loads a consilium Module's chunks straight from Qdrant (current_only guard)
bootstrap.py build_registry(embedder, client=None) -> Registry; the 5 Descriptors; ROUTER_KWARGS
supersession.py SupersessionModule -- real Obsoletes/Obsoleted-by graph walk, cycle-safe
relationships.py thin bridge into linkgraph (get_related / _obsoletion_chain / _corrections)
calibrate.py real router-score measurement script
mcp/
server.py FastMCP server: search + the 3 relationship tools (stdio)
test_server.py fixture-only tests for the tool logic (no mcp package, no Qdrant)
corpus_fetch/ real HTTPS fetch of RFC full text / rfc-index.txt / errata / IANA registries
ingest/
connectors/ per-source-type extract() -> ExtractedDoc (+ the revisions-index builder)
run_ingest.py raw files -> chunk -> embed -> Qdrant, real is_current currency check
eval/
smoke_ingest_real.py corpus_fetch -> ingest -> Qdrant wiring smoke (HashEmbedder)
eval_agenticrag.py production eval (full verify; needs the ingested corpus)
prove_revision_guard.py standalone, narrated revision-guard proof
test_supersession_cycle_safety.py cycle-safety unit tests (synthetic graph; corpus-free)
tests/ unit tests for connectors / registry_loader / bootstrap (corpus-free)
packages/ the five merged tools, each keeping its own tree and history
consilium/ routing / citation-gating spine (+ its 5 eval suites)
ragpack/ ingest / chunk / embed / Qdrant store (src-layout)
linkgraph/ cross-document relationship graph
activerag/ evidence-thinness detection and bounded hunt-and-retry
chainrag/ the blockchain-docs vertical
app.py gr.ChatInterface chat UI
run_demo.py scripted 3-question narrated transcript许可证
代码:MIT (c) 2026 Trent Milam。
语料库不包含在此仓库中(data/ 已被 gitignore);它在构建时从 rfc-editor.org 和 iana.org 获取。IETF RFC/勘误文本受 IETF Trust Legal Provisions 约束(获取过程保留每份文档自身的版权/Trust 声明完整);IANA 注册表数据由 IANA 发布。本项目不重新分发其中任何内容——它会在你的机器上本地获取。
This server cannot be deployed
Maintenance
Related MCP Connectors
Cloud or self-hosted knowledge for AI agents: hybrid search, reranking, GraphRAG, scoped MCP tools.
Read-only hosted MCP over CanonicAI's cited Answers corpus on canonicai.com.
Page-cited retrieval for embedded docs, datasheets, MISRA, CMSIS, and RTOS references.
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Related MCP Servers
- AlicenseAqualityAmaintenanceMCP server that parses 3GPP .docx specifications into structured sections with full-text search, letting LLMs browse, search, and follow cross-references without a vector database.1320MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to retrieve and explore evidence from 3GPP meeting documents through MCP, including temporal knowledge graph queries, document section navigation, and citation-backed answers.-
- FlicenseNot gradedqualityBmaintenanceEnables retrieval-augmented question answering with source-grounded citations, document retrieval, and idempotent ingestion through MCP tools.-
- AlicenseNot gradedqualityCmaintenanceEnables any MCP-capable LLM client to search self-hosted long-term memory over markdown and PDF documents, combining dense semantic vectors with BM25 keyword retrieval and optional cross-encoder reranking. Exposes a read-only tool surface for querying incidents, runbooks, and other knowledge-base content, while writes happen out-of-band through ingestion jobs or a token-gated internal API.2MIT