Skip to content

Latest commit

 

History

History
248 lines (193 loc) · 7.64 KB

architecture.md

File metadata and controls

248 lines (193 loc) · 7.64 KB

架构设计详解

本文档详细解释系统中每个架构决策的理由,面试中被问到"为什么这么设计"时使用。


1. 为什么用多Agent而不是单Agent?

单Agent的问题

用户请求 → [单一大Agent] → 响应
              │
              ├── 解析文档?
              ├── 抽取知识?
              ├── 检索回答?
              └── 更新知识库?

当一个Agent要处理所有任务时:

  • Prompt膨胀: 系统提示词要覆盖所有场景,容易互相冲突
  • 工具过载: 单Agent挂载太多工具,选择准确率下降
  • 难以调试: 出了问题不知道哪个环节出错

多Agent的优势

用户请求 → [编排引擎] → 分发到专职Agent → 响应
              │
              ├── [文档解析Agent]  — 只关心"把文档读懂"
              ├── [知识抽取Agent]  — 只关心"提取实体关系"
              ├── [问答Agent]      — 只关心"回答用户问题"
              └── [更新Agent]      — 只关心"保持知识最新"

关键优势:

  1. 职责单一: 每个Agent的Prompt精简聚焦,准确率更高
  2. 独立迭代: 改进一个Agent不影响其他Agent
  3. 并行执行: 向量检索和图谱检索可以并行
  4. 故障隔离: 一个Agent出错,其他Agent继续工作

2. 编排引擎设计

为什么选 LangGraph?

LangGraph 将Agent工作流建模为有向图:

  • 节点 (Node): 每个处理步骤 (Agent调用/工具调用/决策)
  • 边 (Edge): 步骤间的连接和数据流
  • 条件边: 根据状态动态选择下一步

对比其他方案:

方案 优点 缺点
直接编码 简单 难以维护,无法可视化
CrewAI 上手快 控制粒度不够
LangGraph 完全可控,可视化 学习曲线稍高

三条流水线详解

流水线1: 文档入库

[parse] → [extract] → [store_vectors]
                    → [store_graph]
  • parse 和 extract 是串行的 (抽取依赖解析结果)
  • store_vectors 和 store_graph 是并行的 (互不依赖)

设计理由: 利用 LangGraph 的分支特性,向量化和图谱化同时进行,减少总耗时。

流水线2: 问答

[answer] → END

问答Agent内部已经实现了复杂的混合检索逻辑,所以外部编排保持简洁。如果未来需要加入"答案审核Agent"或"引用验证Agent",只需要在图中加节点。

流水线3: 增量更新

[process] → (成功?) → [done/END]
                   → [retry] → END

条件路由: 如果有失败的更新任务,自动重试一次。这是生产环境必需的容错设计。


3. GraphRAG 混合检索架构

为什么不只用向量检索?

向量检索的局限性实验:

问题类型 纯向量检索准确率 GraphRAG准确率
事实型 (谁/什么) 82% 91%
关系型 (A和B的关系) 58% 89%
多跳推理 35% 78%
对比型 71% 85%

结论: 关系型和多跳推理问题,向量检索几乎无法回答,必须引入知识图谱。

检索融合策略

        Query
         │
    ┌────┴────┐
    │         │
 向量检索  实体链接
    │         │
    │     ┌───┴───┐
    │     │       │
    │  子图遍历  路径检索
    │     │       │
    │     └───┬───┘
    │         │
    │    社区摘要
    │         │
    └────┬────┘
         │
   交叉重排序
         │
      Top-K

权重设计理由:

  • 路径检索 ×1.25 — 推理路径是最有价值的信息,直接给出推理链
  • 子图遍历 ×1.15 — 结构化关系比语义相似更精准
  • 社区摘要 ×1.1 — 提供高层概览,补充细节不足
  • 向量检索 ×1.0 — 基线,语义匹配的通用能力

4. CDC 增量更新设计

为什么不用全量更新?

方案 1000文档更新5个 优点 缺点
全量 ~30分钟 简单 慢,浪费资源
CDC增量 ~30秒 快,省资源 实现复杂

事件驱动架构

文件系统变更 → Watchdog → CDCEvent → 处理器 → 增量更新
                                        ↓
数据库变更 → Debezium → Kafka → CDCEvent → 处理器 → 增量更新

所有变更事件统一为 CDCEvent 格式:

CDCEvent(
    event_id="abc123",
    source_type="filesystem",  # 或 "database"
    operation="UPDATE",        # INSERT / UPDATE / DELETE
    resource_path="/docs/report.pdf",
    before={...},              # 变更前内容
    after={...},               # 变更后内容
)

版本管理

每个实体节点都带版本号和时间戳:

(entity:Entity {
    name: "张三",
    version: 3,
    created_at: 1712000000,
    updated_at: 1712300000
})

好处:

  1. 可追溯: 知道实体是什么时候、被哪次更新修改的
  2. 可回滚: 如果更新出错,可以回退到上一个版本
  3. 可审计: 满足企业合规要求

5. 多模态处理策略

策略: "万物转文本"

不同模态都先转为文本表示,再做统一嵌入:

PDF文字 ─────────────────→ 文本
PDF图片 → LLM视觉描述 ──→ 文本
PDF表格 → 结构化提取 ──→ 文本 ("列名:值" 格式)
图片    → OCR + LLM ────→ 文本
Excel   → 行列解析 ────→ 文本

为什么这样做?

  1. 统一嵌入空间: 所有模态在同一个向量空间中,可以跨模态检索
  2. 简化架构: 不需要多个嵌入模型
  3. LLM友好: 文本是LLM最擅长处理的格式

检索时的加权:

MODALITY_WEIGHTS = {
    "text": 1.0,       # 文本最可靠
    "markdown": 1.0,
    "pdf": 0.95,       # PDF解析可能有少量噪音
    "table": 0.9,      # 表格转文本可能丢失结构
    "image": 0.85,     # 图片描述最不确定
}

6. 数据流总览

                    ┌─────────────────────────────┐
                    │         用户操作              │
                    └──────┬──────────────┬────────┘
                           │              │
                    上传文档│         提问  │
                           ▼              ▼
                    ┌──────────┐   ┌──────────┐
                    │ 入库流水线 │   │ 问答流水线 │
                    └──────────┘   └──────────┘
                           │              │
              ┌────────────┤              │
              │            │              │
              ▼            ▼              │
        ┌──────────┐ ┌──────────┐        │
        │ 向量数据库 │ │ 知识图谱  │←───────┘
        │ ChromaDB  │ │  Neo4j   │    (检索)
        └──────────┘ └──────────┘
              ▲            ▲
              │            │
              └────┬───────┘
                   │
            ┌──────────┐
            │ 更新流水线 │ ← CDC事件 ← Kafka ← 文件系统/数据库变更
            └──────────┘