2026-08-03-[ADR]-OGAS-ArkhivRAG 设计文档

2938 个字
15 分钟
2026-08-03-[ADR]-OGAS-ArkhivRAG 设计文档

OGAS-ArkhivRAG 设计文档#

  • 状态:持续更新(跟随当前代码库)
  • 读者:扩展 Eagle-RAG 的工程师(核心、领域插件、下游 Agent)
  • 范围eagle_rag 后端的架构及其对外接口(REST / SSE / MCP)。前端是 Core 能力的展示层,仅在约束后端时提及。

1. 上下文与范围#

Eagle-RAG 是一个行业无关、多租户(kb_name)的多模态 RAG 数据层,面向 Agent 与 LLM。它只承担四项职责(ADR-008):

  • ingest(入库)——把文件/URL 路由到正确的解析器,做向量化并建索引;
  • retrieve(检索)——对文本块与视觉切片做多模态召回;
  • assemble context(组装上下文)——融合、重排、带溯源的答案生成;
  • admin metadata(管理元数据)——任务审计、知识库生命周期、标签、健康探针。

它被下游 Agent 通过 REST / SSE / MCP 消费;内置 Next.js 前端只展示 Core(knowhere + pixelrag)检索能力。垂直领域(plugins/biomed 实验性、plugins/lakehouse_bi 开发中)以后端 + MCP 形态交付。

系统运行在内网(无鉴权)、固定的基础设施之上:Milvus 2.6、PostgreSQL 16、Redis 7、MinIO,外加 Knowhere 解析服务(或进程内 knowhere-parse-sdk)与 PixelRAG 进程内库。AI 供应商被限定为DeepSeek + Qwen

本文描述系统在代码中的真实形态,可作为快速复习的入口和扩展功能、编写插件时可引用的资料源。

2. 目标与非目标#

目标#

  • 双入库管线,按「格式 + 内容形态」路由:Knowhere(语义骨架:类型化 chunk、doc_nav 章节树、知识图谱边)处理文本类文档;PixelRAG(视觉切片,2048 维)处理扫描件/图片文档。见 eagle_rag/ingest/router.py
  • 多模态融合,通过 eagle_visual 上的四个锚点字段(chunk_typeparent_sectioncontent_summarysource_chunk_id)锚定到 Knowhere 语义树,支持父文档召回(先 type="section_summary",再按 path 前缀下钻)。
  • 双层多租户plugin_namespace(Milvus Database + PG 仓储过滤)把一次部署绑定到单一领域;kb_name 在该领域内对标量检索做知识库过滤。
  • 路由查询引擎auto / text / visual / hybrid),由 FallbackChain 选择器链 + 插件可扩展的 collection 计划构成,随后做逐计划重排、RRF 融合、跨 collection 去重与最终重排。
  • 插件微内核:Core 与领域插件共用同一套 Hook/MCP 扩展路径;热路径 Hook(PARSE / CHUNK / QUERY_ASSEMBLE)只做增强、绝不重新切块。
  • 可靠性:Celery 三队列(router / knowhere / pixelrag)+ with_retry + 死信;解析器 fail-closed(无 mock 兜底)。
  • 统一对外接口:REST + SSE 流式(/query/stream/search/stream)与 FastMCP 工具(core_ingestcore_querycore_retrieve_textcore_retrieve_visual)。

非目标#

  • 不做 Agent 工作流,不做副作用型 MCP 工具(ADR-008 红线)。规划、工具循环与决策属于下游 Agent 宿主。
  • 不做运行时领域切换——每个实例一个 default_namespace(ADR-002)。多行业 = 多套部署(EAGLE_RAG_PROFILE),而非运行时切换。
  • 不做格式转换/Office 渲染——已移除 LibreOffice 与 pixelrag-serve;Excel 直接走 Knowhere。
  • 无 FAISS、无 OpenAI / Cohere / 其他供应商——视觉存储由 Milvus HNSW/DiskANN 承载;模型仅 DeepSeek + Qwen。
  • 不是向量数据库、工作流引擎或通用 Web 服务——产品是只读为主的 RAG 数据层。
  • 不做跨存储强一致——入库是异步任务管线,带审计轨迹;MinIO / Milvus / PG 之间接受最终一致。

3. 真正的设计#

3.1 技术选型与取舍#

关注点选择理由
编排框架LlamaIndexllama_index.core + 官方集成包)提供 RAG 原语(节点 schema、BaseRetrieverCustomQueryEngineMilvusVectorStore、模型包),又不引入 Agent 编排。LangChain 曾评估并否决:其差异化是 Agent/LCEL 工作流,恰是 ADR-008 排除的范围;迁移需要重写检索器、生成链路与全部模型集成,召回收益为零。
API / 流式FastAPI + uvicorn + sse-starlette内网异步 API;SSE 匹配流式步骤(session/step/sources/token/done)。
任务队列Celery(Redis broker)异步持久化入库;三队列不同并发(router 4 / knowhere 8 / pixelrag 1)。
向量库Milvus 2.6(pymilvus + llama-index-vector-stores-milvus每个 plugin_namespace 一个 Database;双集合 eagle_text(1536 维)/ eagle_visual(2048 维);HNSW/DiskANN + 标量过滤。
关系库PostgreSQL 16 + SQLModel + SQLAlchemy 2 + Alembic文档注册表、去重、会话、任务审计、标签目录。store 内不写 DDL,只走迁移。
对象存储MinIO分布式 worker 共享文件;kb_name 前缀隔离。
解析Knowhere(knowhere-python-sdk HTTP :5005 或进程内 knowhere-parse-sdk)+ PixelRAG 库(pixelrag_render + pixelrag_embed两条专业化管线,均 fail-closed,无 mock。
模型DeepSeek-V4-Pro(LLM/路由)、Qwen-VL-Max(VLM)、text-embedding-v4(1536 维)、Qwen3-VL-Embedding-2B(2048 维,本地或百炼)、qwen3-rerank产品级供应商锁定;新模型经 LlamaIndex 集成包或插件 EncoderRegistry 进入。
MCPFastMCP ≥ 2.3(HTTP 默认,stdio 兜底)+ tenacity/pybreaker为下游 Agent 提供标准工具面,带重试与熔断。
前端Next.js 16 / React 19 / TS / Bun / Tailwind v4 / HeroUI v3 / next-intlCore 展示层;本仓库垂类无 UI。

3.2 模块划分(核心)#

模块职责关键文件
api/FastAPI 路由、Pydantic schema、MCP server、SSEapi/query.pyapi/ingest.pyapi/mcp_server.pyapi/schemas/
ingest/路由矩阵、Knowhere/PixelRAG 适配器、runneringest/router.pyingest/runner.pyingest/knowhere_adapter.pyingest/pixelrag_adapter.py
index/Milvus store、按 DB 的客户端池、注册表、标签目录index/milvus_text_store.pyindex/milvus_visual_store.pyindex/milvus_pool.pyindex/registry.py
retrievers/文本(图)检索与视觉检索retrievers/knowhere_graph_retriever.pyretrievers/pixelrag_visual_retriever.py
router/查询路由、RRF 融合、重排、LLM 工厂router/router_engine.pyrouter/selectors.pyrouter/rerank_fusion.py
generation/多模态答案生成generation/multimodal_engine.py
plugins/微内核:管理器、HookBus、Core 默认插件、编排器plugins/manager.pyplugins/hookbus.pyplugins/core_defaults.pyplugins/ingest_orchestrator.pyplugins/retriever_orchestrator.py
db/SQLModel 模型、按 namespace 隔离的仓储db/models/db/repositories/db/namespace.py
tasks/Celery 应用、任务状态、死信tasks/celery_app.pytasks/state.pytasks/dead_letter.py
kb/sessions/storage/attachments/admin/telemetry/知识库生命周期、会话、MinIO/去重、附件惰性解析、运维、可观测性

3.3 业务流:入库#

POST /ingest (file | bytes | object_key | URL)
└─ runner.ingest()
├─ 生成 job/document id
├─ 按 (sha256, kb_name, plugin_namespace) 去重
├─ 上传 MinIO(kb_name 前缀隔离)
├─ 创建审计 + 注册文档
└─ app.send_task(ingest_router) # router_queue
└─ ingest.router.ingest_router
└─ FallbackChain 路由 # 格式 + 内容形态
前缀 knowhere:/pixelrag:
→ settings.router.mode (text/visual/hybrid)
→ http(s) URI → PixelRAG
→ PDF 形态探测 (pypdf/pdfplumber)
→ 扩展名 → content_type
├─ knowhere → knowhere_parse # knowhere_queue
│ └─ 解析(api SDK :5005 | parser SDK 进程内)
│ ├─ 文本节点 + section_summary 节点
│ ├─ doc_nav 章节树
│ ├─ 关键词目录(document_keywords)
│ └─ 视觉分发 → knowhere_visual_chunks / pixelrag_build
└─ pixelrag → pixelrag_build # pixelrag_queue(并发 1)
└─ 渲染切片 → Qwen3-VL 2048 维 → upsert eagle_visual

文本管线用 Qwen text-embedding-v4(1536 维)写入 eagle_text;视觉切片带四个融合锚点字段落入 eagle_visual。热路径 PARSE / CHUNK Hook 只增强节点,必须保留 Knowhere 的 doc_nav / path / 类型化 chunk(ADR-005)。

3.4 业务流:查询#

POST /query | /search | /query/stream | /search/stream
└─ EagleRouterQueryEngine
├─ 解析附件(惰性解析;不写 Milvus)
├─ route_query: FallbackChain
│ ForcedModeSelector → AttachmentSelector → LLMIntentSelector → HeuristicSelector
├─ _plan_query_route: CLASSIFY_QUERY Hook → QueryRouteDecision(collection 计划)
│ + scope 感知并集(scope_filter: kb_names ∪ document_ids ∪ tags)
├─ RetrieverOrchestrator.retrieve
│ 每个计划:ANN(Qwen 文本 | Qwen3-VL 视觉 | 插件编码器)
│ → 计划内重排 → supplement Hook
│ → merge_rrf → dedupe_cross_collection → RRF_POST_MERGE → 最终重排
├─ 两阶段父文档召回:section_summary → path 前缀下钻
└─ 生成(EagleMultimodalQueryEngine)
文本答案走 DeepSeek;图像推理走 Qwen-VL-Max
SSE 事件:session → step(route/recall/rerank) → sources → token* → done

代码中的关键保证:空召回列表不参与 RRF 产生虚排位(merge_rrf);跨 collection 重复按 source_chunk_id / (document_id, path) 折叠(dedupe_cross_collection);单个 collection 计划失败时跳过并记录审计,而不是让整个查询失败(G14)。

3.5 插件微内核#

PluginManagersettings.plugins.enabled 加载模块(仅仓库内模块;Core eagle_rag.plugins.core_defaults 永远最先加载)。每个插件声明 namespace 清单;实例绑定 settings.plugins.default_namespace = Milvus Database + PG 仓储过滤。HookBus 支持 invoke_first / invoke_all / invoke_transform;热路径 Hook 是 PARSE / CHUNK / QUERY_ASSEMBLE,编排 Hook 包括 CLASSIFY_*EMBED_*UPSERT_VECTORSCLASSIFY_QUERYQUERY_DENSE_EXPANDRETRIEVE_SUPPLEMENTRRF_POST_MERGE。编码器经 EncoderRegistry 注册;MCP 工具经 mcp_registry.py 注册,带 RAG-only 命名(assert_rag_only_tool_name)与 G3 namespace 过滤(仅暴露 core_* + default_namespace 插件工具)。

4. 系统上下文图#

┌─────────────────────────────┐
│ 内置 UI(Core 展示层) │
└──────────────┬──────────────┘
│ REST/SSE
┌───────────────┐ ▼ ┌──────────────────┐
│ 下游 Agent │ REST/SSE/MCP │ │
│ (LLM 宿主) │──────────────────► │ Eagle-RAG │
│ │ │ (数据层) │
└───────────────┘ │ │
└───┬──────┬───────┘
文件 / URL ──────────────────────►│ │
│ │
┌──────────────┐ HTTP :5005 / 进程内 │ │
│ Knowhere │◄─────────────────────────┤ │
│ (解析器) │ │ │
└──────────────┘ │ │
┌──────────────┐ 库引用(pixelrag_*) │ │
│ PixelRAG │◄─────────────────────────┤ │
└──────────────┘ │ │
┌──────────────┐ DeepSeek / Qwen(百炼) │
│ LLM / VLM / │◄─────────────────────────┤
│ embed / rerank│ │
└──────────────┘ │
┌──────────────┐ │
│ Milvus / PG / │◄────────────────────────┤
│ Redis / MinIO │ │
└──────────────┘ │

该图展示 Eagle-RAG 与外部世界的边界:Agent 不直接访问存储,Eagle-RAG 也不拥有 Agent 工作流——它只把检索与上下文组装暴露为工具。

5. API#

REST / SSE#

  • POST /ingest——四种来源(文件 / 字节流 / MinIO 对象 / URL);返回 job id、去重状态与审计日志。经 kb_name 多租户(缺省回退 settings.kb_name)。
  • POST /searchPOST /search/stream——仅检索;返回 text + image 来源,含路径、分数、chunk_count、关键词、页码。
  • POST /queryPOST /query/stream——检索 + 生成。SSE 依次发出 sessionsteproute / recall / rerank)、sourcestoken*done
  • POST /attachments——单张 PixelRAG 图片(默认上限 5 MB);在查询/搜索时惰性解析,从不写入 Milvus。
  • 证据类——GET /documents/{id}/structure/documents/{id}/file/documents/{id}/chunks/{chunk_id}
  • 知识库/标签/会话/运维——GET /tags/sessions*/admin/probes、任务审计。

请求要点(api/schemas/query.py):modeauto|text|visual|hybrid)、filterssource_type / pipeline / year)、scope_filterScopeSelection{kb_names, document_ids, tags}并集语义)、attachments(按 id)以及 MCP 的内联图片字节。

MCP(/mcp,HTTP 默认,stdio 兜底)#

工具用途
core_ingest将文件/URL 摄入知识库
core_query多模态查询,返回答案 + 来源
core_retrieve_text仅文本检索
core_retrieve_visual视觉检索(支持内联 image_base64

工具只允许检索/组装上下文;assert_rag_only_tool_name 禁止副作用命名。领域插件注册 {namespace}_{name} 工具。

设计理由#

  • kb_name 贯穿所有 API、MCP 工具、Celery 任务、Milvus 标量过滤与仓储调用——多租户是横切关注点,不是开关。
  • 流式是一等公民:检索 + VLM 生成较慢,客户端可以增量看到 route → recall → rerank → sources → tokens。
  • scope_filter 把完整并集过滤下推到 Milvus(_resolve_scope_filter),标签经标签目录解析为 document_id,并带文档数量上限保护。
  • 按设计不做鉴权(内网);需要时由网关补。

6. 数据存储#

Milvus 2.6(每个 plugin_namespace 一个 Database)#

  • eagle_text——1536 维文本块(HNSW/DiskANN),标量过滤 kb_namedocument_idyearsource_typetypepath;去重主键 (sha256, kb_name, plugin_namespace)
  • eagle_visual——2048 维视觉切片,带融合锚点:chunk_typetile|image|table)、parent_sectioncontent_summarysource_chunk_id
  • 客户端按 DB 名池化(index/milvus_pool.py),永不关闭。

PostgreSQL 16(SQLModel + Alembic)#

表:documentsdocument_keywords(标签目录)、imagessessions + messagestask_audit(审计/重试)、document_dedupknowledge_basesattachmentsnotificationsmcp_call_logsystem_settingmetric_samples。每条注册表数据都带 kb_name + plugin_namespace;仓储按 namespace 过滤(db/repositories/)。

Redis 7 / MinIO#

Redis 是 Celery broker + 结果后端;MinIO 按 kb_name 前缀存储上传文件,worker 按 object key 拉取。

取舍#

选 Milvus 而非 FAISS,因为需要托管 ANN + 标量过滤 + Database 隔离;代价是外部服务依赖以及与 PG 的最终一致。PG 保存关系型事实(注册表、审计、会话);Milvus 只放可重建的向量(重新解析即可恢复)。

7. 代码与伪代码#

只在代码本身就是设计点的地方贴代码:

# 查询路由(简化自 router/router_engine.py)
decision = FallbackChain([
ForcedModeSelector(default_mode=cfg.mode), # text/visual/hybrid 覆盖
AttachmentSelector(), # 图片附件 → visual
LLMIntentSelector(llm, prompt, enabled), # LLM 意图分类
HeuristicSelector(rules, default), # 关键词兜底
]).select(ctx)
# RRF 融合核心(router/rerank_fusion.py)——空列表防护是设计点
non_empty = [lst for lst in plan_results if lst]
for lst in non_empty:
for rank, nws in enumerate(lst, start=1):
scores[key(nws)] += 1 / (k + rank) # k = settings.router.rrf_k

其余不再贴代码:真正的重点在第 3–6 节的取舍,而非实现细节。

8. 约束的程度#

这是一个强约束的存量系统,更靠近「大量决策已被锁定」的一端:

  • 已锁定:基础设施(Milvus 2.6 / PG 16 / Redis / MinIO)、模型供应商(仅 DeepSeek + Qwen)、解析 SDK(Knowhere、PixelRAG 库)、LlamaIndex 作为集成层、ADR-008 红线(无 Agent 工作流、无副作用 MCP 工具)、单域部署、中英双语文档、仓库规范(ruff/mypy、仅 Alembic 改 DDL、英文注释)。
  • 缝隙内的自由度:插件 Hook 与清单、经 EncoderRegistry 新增 collection/编码器、新增带 namespace 的 MCP 工具、入库/查询路由规则、Core 前端(仅展示;垂类无 UI)。
  • 设计启示:新功能应扩展插件/Hook 而非改核心;框架替换(如 LlamaIndex → LangChain)成本高、收益低——锁定的决策已覆盖通用部分,剩余的自研逻辑(路由、融合、多租户、插件总线)是与框架无关的领域代码。

遗留说明:eagle_rag/__init__.py 的 docstring 仍保留重构前的描述 "for the finance and tax domain";产品现已行业无关(AGENTS.md),建议在后续清理中更新。

分享到社交平台

将本文分享给你的朋友们

2026-08-03-[ADR]-OGAS-ArkhivRAG 设计文档
https://zhongye1.github.io/posts/rfc_agentic_project/2026-08-03-adr-ogas-arkhiv/
作者
Zhongye
发布于
2026-06-19
版权声明
CC BY-NC-SA 4.0

评论

Profile Image of the Author
Zhongye
南漂中
公告
新的博客站!旧站点传送门 👇
音乐
专辑封面

音乐

暂无播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章数
150
分类数
14
标签数
210
总字数
477,253
运行天数
0
最后更新
0 天前
总访问量
42296
访客数
29212

目录