From e2759394ca2c89dcd9c844634a20bfd892909eb6 Mon Sep 17 00:00:00 2001 From: WeiCHEN Date: Mon, 7 Sep 2026 21:27:21 +0800 Subject: [PATCH] =?UTF-8?q?docs(system):=20=E7=BA=B3=E7=AE=A1=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E6=9E=B6=E6=9E=84=E8=AE=BE=E8=AE=A1=E4=B8=8E=E6=BC=94?= =?UTF-8?q?=E8=BF=9B=E8=A7=84=E5=88=92=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .doc/system-design/architecture-design.md | 593 ++++++++++++++++++++++ 1 file changed, 593 insertions(+) create mode 100644 .doc/system-design/architecture-design.md diff --git a/.doc/system-design/architecture-design.md b/.doc/system-design/architecture-design.md new file mode 100644 index 00000000..8d79f64d --- /dev/null +++ b/.doc/system-design/architecture-design.md @@ -0,0 +1,593 @@ +# 项目对话与任务协同系统 —— 架构设计文档 + +> 版本:v0.1(骨架设计阶段) +> 日期:2026-09-07 + +--- + +## 一、项目背景 + +### 1.1 已有能力 + +团队已经构建了一个**智能体小队**,底层基于 PI-agent 实现,并对外暴露了调用接口。该智能体小队能够根据输入的任务,调度多个智能体协同工作,完成复杂任务的执行与产出。 + +### 1.2 新的系统目标 + +基于上述智能体小队的能力,构建一个**项目级对话与任务协同系统**,承担以下职责: + +1. **日常对话处理**:与项目成员进行自然语言交互,回答问题、提供信息、辅助决策。 +2. **工作区感知**:系统能够感知工作区的全部内容,包括: + - 所有用户的对话历史 + - 用户上传的文档 + - 智能体输出的信息 + - 智能体生成的文档 +3. **任务执行**:根据用户的请求执行任务,任务可以路由到: + - 智能体小队(复杂、多步、需要协作的任务) + - 单个智能体(边界清晰、可独立完成的任务) + +### 1.3 关键设计决策:对话系统复用 PI-agent + +经过评估,**对话系统复用 PI-agent 作为编排层**是更合适的方案,理由: + +- 智能体小队本身已是基于 PI-agent 实现,能力栈一致,技术复用度高 +- 对话系统与执行系统共享 PI-agent 框架,减少技术异构性 +- 未来扩展(如新增工具、新增技能)可以统一在 PI-agent 生态内完成 + +因此本系统的技术栈统一在 PI-agent 之上,分层划分职责。 + +--- + +## 二、系统需求 + +### 2.1 用户与角色 + +系统服务于**多用户、多项目**的场景。典型用户角色包括: + +- 系统工程师 +- 项目经理 +- 软件工程师 +- 其他项目相关角色 + +每个用户在不同的项目下可以承担不同的角色(编制人、审核人、批准人),角色的差异决定了用户对文档的权限边界。 + +### 2.2 项目与工作流 + +- 一个项目下会有**多个工作流**(如需求分析、设计、实施、验收等阶段各自对应一个工作流)。 +- 同一时间,一个项目**只能激活一个工作流**。 +- 工作流由若干**阶段**组成,阶段之间存在进入/退出约束。 +- 工作流内包含若干**文档任务**,每个文档任务有明确的状态机。 + +### 2.3 文档任务 + +文档任务是工作流的核心载体,规则如下: + +- 每个文档任务都有**编制负责人**,只有编制负责人可以发起文档编制。 +- 其他用户**不能**直接发起文档编制,但可以向项目补充信息和材料。 +- 文档之间存在**网状依赖关系**: + - 一个补充信息可能影响多个文档 + - 一个文档可能影响多个阶段、多个其他文档 + - 依赖图是 DAG 甚至带反向引用(修订回溯)的结构 + +### 2.4 文档的编制、审核、批准 + +每个文档在其生命周期内涉及三类角色: + +| 角色 | 权限 | +|------|------| +| 编制人 | 可修改文档正文、查看修改历史、撤回修改 | +| 审核人 | 不可修改正文,只能添加审核意见、通过或驳回 | +| 批准人 | 不可修改正文,只能添加批准意见、最终通过或最终驳回 | + +- 审核驳回 → 文档回到编制阶段,附上意见 +- 批准驳回 → 升级处理(需更高决策流程) + +### 2.5 文档认领机制 + +为了让编制人对文档形成稳定的认知,避免被他人擅自修改打乱思路: + +- **认领定义**(最小实现):点开过文档、或者通过对话导出过文档,即视为认领。 +- **认知偏差保护**:文档被编制负责人认领后: + - 若自上次修改后**编制负责人未查看过新版本** → 智能体小队可直接修改,不通知编制负责人 + - 若编制负责人**已查看过最新版本** → 修改前必须通知编制负责人确认 + +无论哪种情况,都需要告知: +- **发起人**:补充了什么信息、编辑后可能产生什么影响 +- **被通知者**:同样的信息(确认时需要知道全貌) + +### 2.6 多用户并发 + +- 一个项目会有**多个用户同时**与智能体对话。 +- 用户的请求类型多样:补充材料、发起任务、查询进度、闲聊等。 +- 项目状态是全局唯一的,需要协调多个用户的并发请求,避免冲突。 + +--- + +## 三、系统骨架设计 + +### 3.1 总体架构:三层模型 + +系统采用三层架构,明确分离对话、决策、执行三种职责: + +``` +┌───────────────────────────────────────────────┐ +│ L1 协作对话层(PI-agent,对话系统) │ +│ - 与单个用户的多轮对话 │ +│ - 不做项目状态决策 │ +│ - 输出:候选意图 + 证据 + 置信度 │ +└───────────────────────────────────────────────┘ + │ 提交候选意图 + ▼ +┌───────────────────────────────────────────────┐ +│ L2 项目协调层(项目协调引擎,独立服务) │ +│ - 持有项目状态、工作流状态、文档依赖图 │ +│ - 验证候选意图的合法性 │ +│ - 决定接受 / 拒绝 / 排队 / 转交 │ +│ - 触发文档版本、依赖重算、通知 │ +└───────────────────────────────────────────────┘ + │ 派发的执行任务 + ▼ +┌───────────────────────────────────────────────┐ +│ L3 任务执行层(智能体小队 + 单智能体) │ +│ - 起草、修订、审核、检索 │ +│ - 输出文档版本、检索结果 │ +└───────────────────────────────────────────────┘ +``` + +**为什么需要独立的 L2?** + +- 多用户并行时,需要一个**全局状态持有者**决定谁的动作被接受。 +- 文档依赖图是**强结构化数据**,不适合塞进 LLM 的 prompt 推理。 +- 权限规则是**确定性的**,应该由规则引擎执行而非 LLM 自觉。 +- L1 的 PI-agent 是对话接口,L3 的智能体是执行单元,**L2 是调度者**。 + +### 3.2 Context:对话与执行的统一上下文 + +整个系统的核心信号是:**项目状态、用户负责的文档、进行中的任务,都会成为对话和执行的上下文**。 + +这不是 prompt 里的提示词,而是一个**结构化数据对象**,由后端服务组装,对话系统和执行智能体共同消费。 + +#### 3.2.1 UserProjectContext 结构 + +``` +UserProjectContext { + user: { + id, name, role, project_role + } + + project: { + id, name, + current_workflow, // 当前激活的工作流 + current_stage, // 工作流的当前阶段 + stage_rules // 当前阶段的进入/退出约束 + } + + user_docs: { + composed: [DocA, DocB, ...] // 用户编制的文档 + reviewed: [DocC, ...] // 用户审核的文档 + approved: [DocD, ...] // 用户批准的文档 + claimed: [DocE, ...] // 用户认领过的文档 + } + + pending: { + confirm_modifications: [...], // 需要用户确认的批次修改 + pending_reviews: [...], // 待用户审核的文档 + pending_approvals: [...], // 待用户批准的文档 + my_drafts_in_progress: [...], // 用户编制中的文档 + unread_supplements: [...] // 项目内用户未读的信息补充 + } + + available_actions: [ + "COMPOSE_DOC" // 限制: 仅 user_docs.composed + "SUPPLEMENT_INFO" // 限制: 当前阶段允许 + "REVIEW_DOC" // 限制: 仅 user_docs.reviewed + "APPROVE_DOC" // 限制: 仅 user_docs.approved + "EXPORT_DOC" // 限制: 认领后会触发认知偏差检查 + "VIEW_DOC" // 限制: 项目内所有相关文档 + ... + ] + + recent_events: [...] // 项目内最近 N 条事件 +} +``` + +#### 3.2.2 Context 的两个关键角色 + +**角色一:意图判断的"已知信息"** + +LLM 拿到 Context 后,看到的不是"用户在说什么",而是"用户是谁 + 项目在哪 + 用户能做什么 + 现在有什么事"。意图判断从"开放式分类"变成"在已知约束下选择"。 + +意图判断的 prompt 模板极简化: + +``` +你是用户的项目助理。基于用户的项目上下文回答或执行。 + +【用户项目上下文】 +{{context_json}} + +【用户输入】 +{{user_input}} + +【判断】 +- 用户的真实意图是? (从 available_actions 里选) +- 需要追问吗? 需要哪些信息? +- 还是直接执行? 执行什么动作? +``` + +**角色二:任务执行的"硬约束"** + +执行智能体被调用时也会拿到 Context,把"能不能做"、"做了之后会触发什么"、"不能做什么"这些硬约束前置到执行层。 + +例如,智能体小队被调用去修改 DocA 时: + +``` +任务:修改 DocA 的第3.2 节 +约束: +- 编制人是 UserX(不能改 DocA 的其他章节,除非有明确授权) +- 当前阶段: 编制中(允许修改) +- DocA 当前版本: v3,编制人 UserX 已查看 v2(认知偏差敏感) + → 修改后必须通知 UserX 确认 +- DocA 引用了 DocC(下游依赖,需记录影响但不自动改 DocC) +- DocA 被 DocE 引用(上游依赖,DocE 需要被标记"待复核") +``` + +#### 3.2.3 Context 的组装与生命周期 + +**组装服务**(最小实现): + +``` +context_service.assemble(user_id, project_id) -> UserProjectContext: + user = db.get_user(user_id) + project = db.get_project(project_id) + workflow = db.get_workflow(project.current_workflow) + stage = workflow.stages[project.current_stage] + user_docs = db.get_user_doc_relations(user_id, project_id) + pending = db.get_pending_for_user(user_id, project_id) + events = db.get_recent_events(project_id, limit=20) + actions = compute_available_actions(user, project, stage, user_docs) + + return UserProjectContext(...) +``` + +**生命周期**: +- Context 是**只读快照**,每次用户发起对话时由后端组装。 +- 对话期间如果发生重要项目事件,协调层通过事件流通知对话系统,触发 Context 重新组装。 +- Context 是结构化数据,不依赖 LLM 处理,可以直接查询和聚合。 + +### 3.3 多用户并发的协调 + +L1 的 PI-agent **不直接决策**,每个用户的对话实例只负责: + +1. 解析用户输入,产出**候选意图**(不是决策,是提案)。 +2. 把候选意图 + 上下文证据打包提交给 L2。 +3. 等 L2 给回执后,再生成对话回复。 + +L2 收到候选意图后做: +- **冲突检测**:该时刻其他用户提交了什么?是否冲突? +- **状态检查**:当前工作流阶段是否允许该动作? +- **权限检查**:该用户在他提到的对象上有该权限吗? +- **依赖检查**:依赖的文档是否已就绪? + +通过 → 接受;不通过 → 返回带原因的状态码给 PI-agent(例如 `REJECT_REASON_DOC_PENDING`、`REJECT_REASON_ROLE_NOT_OWNER`),PI-agent 用回执生成自然语言反馈。 + +### 3.4 文档认领与认知偏差机制(骨架版) + +#### 3.4.1 认领判定(最小实现) + +``` +用户与某文档发生以下交互 → 标记该文档为该用户已认领 + - 通过对话打开文档查看 + - 通过对话导出文档 +``` + +#### 3.4.2 认知偏差检查(文档级,最小实现) + +``` +doc.modify(doc_id, new_content): + if doc.claimed_by_user contains current_user: + require_owner_confirmation() // 编制负责人确认 + else: + modify_directly() // 直接修改 + + notify_originator_and_affected(): + - 补充了什么信息 + - 修改了哪些章节 + - 可能的下游影响 +``` + +**延后细化项**(数据结构预留位置,实现延后): +- 章节级别的已读标记 +- "纯查阅模式"(避免用户误触) +- 影响图的递归分析 +- 通知分级(P0/P1/P2/P3) + +### 3.5 文档状态机(骨架版) + +``` +DRAFT // 编制中 + ├── DRAFT_AUTO_MODIFIED // 未认领用户被直接修改 + ├── DRAFT_PENDING_CONFIRM // 认领用户被修改,待确认 +DRAFT_REVISED // 编制完成 + ↓ +UNDER_REVIEW // 待审核 + ├── REVIEW_PASSED + └── REVIEW_REJECTED → DRAFT // 审核驳回 +PENDING_APPROVAL // 待批准 + ├── APPROVED // 已批准 + └── REJECTED → DRAFT (升级) // 批准驳回 +``` + +每个状态关联: +- 允许的操作 +- 需要的角色 +- 触发的通知 +- 依赖的检查 + +### 3.6 信息补充的批次化处理 + +信息补充是事件流,文档修改是批次处理,两者解耦: + +``` +信息补充事件 ──→ 待处理信息池(每个文档一个池) + │ + │ 触发条件(手动触发优先) + ▼ + 修改批次(一次性生成新版本) + │ + │ 影响分析 + 认知偏差检查 + ▼ + 确认 / 执行 +``` + +触发条件(骨架阶段先支持手动触发): +- **对话触发**:用户主动说"可以开始改了" +- **阈值触发**:累积信息量达到阈值(后续迭代) +- **时间触发**:超过某个时间窗口(后续迭代) +- **阶段触发**:当前工作流阶段即将结束(后续迭代) + +--- + +## 四、意图识别框架方案 + +### 4.1 为什么不采用简单的"剥洋葱"分类 + +最初的设计直觉是建立一个意图分类图(树或图结构),从粗粒度意图类型开始,逐层细化分支,最终落到具体任务。 + +这种思路在**单用户、单轮、任务边界清晰**的场景下可行,但在本系统中遇到根本性挑战: + +| 问题 | 原因 | +|------|------| +| 路径爆炸 | 文档类型 × 当前阶段 × 涉及角色 × 历史决策 × 用户权限,组合后分支极大 | +| 状态被忽略 | "帮我继续那份合同"和"开始新的合同"完全不同入口,需要状态上下文 | +| 模糊输入 | "那个事你帮我处理下"这种请求无法单路径归类 | +| 多用户并发 | 多个用户同时对话,单个用户的意图图无法反映全局冲突 | + +因此本系统采用更精细的四步法,结合 Context 实现意图识别。 + +### 4.2 四步法意图识别框架 + +``` +用户输入 + ↓ +[Step 1] 领域路由(Domain Routing) + ↓ +[Step 2] 意图细化 + 槽位识别(Intent + Slot Filling) + ↓ +[Step 3] 状态机查询(State Lookup) + ↓ +[Step 4] 动态规划与执行(Plan-Execute) +``` + +#### 4.2.1 第一步:领域路由 + +**职责**:将请求归入大类。 +- 闲聊 / 检索 +- 工作流类(起草、修订、审核、批准、查询进度) +- 文档类(生成、导出、查看、修订) +- 查询类(项目状态、文档状态、待办事项) +- 外部系统操作类 + +**实现要点**: +- 分支控制在 5-6 个以内 +- 可使用 LLM 分类,也可使用规则 +- 故意保持粗粒度,下面还有修正机会 + +**关键**:注入 Context 之后,LLM 看到的不是"用户说什么",而是"用户是谁 + 项目在哪 + 用户能做什么",分类准确率大幅提升。 + +#### 4.2.2 第二步:意图细化 + 槽位识别 + +**职责**:在大类下识别具体意图,并抽取关键参数。 + +``` +候选意图: + - 起草(槽位:文档类型、模板、关联项目阶段) + - 修订(槽位:目标文档、修订章节、修订依据) + - 审核(槽位:目标文档、审核标准) + - 批准(槽位:目标文档) + - 查询进度(槽位:项目、工作流、文档) +``` + +**核心设计**:**不要追求一次到位**。允许输出"需要澄清的槽位列表",通过追问填槽。 + +``` +SlotFillingResult { + intent: "MODIFY_DOC", + filled_slots: { + target_doc: "DocA", // 已识别 + section: "3.2", // 已识别 + }, + missing_slots: [ + "modification_basis" // 缺少:依据是什么补充材料 + ], + clarification_question: "您希望根据哪份补充材料来修订第3.2 节?" +} +``` + +#### 4.2.3 第三步:状态机查询 + +**职责**:调用 L2 协调层,查实例的当前状态、历史决策、待办动作。 + +这一步是"剥洋葱"思路缺失的关键。意图识别完毕后,**不是直接执行**,而是先看"它现在在哪"。 + +``` +StateLookup { + doc_state: "DRAFT", + doc_version: "v3", + claimed_by: ["UserX"], + last_viewed_by_owner: "v2", // 编制人看过 v2 + pending_actions: ["PENDING_CONFIRM_FOR_MOD_v3"], + blocking_dependencies: ["DocC状态: 待复核"] +} +``` + +基于状态查询结果,可以决定: +- 是否需要编制负责人确认(认知偏差) +- 是否需要等待依赖文档就绪 +- 是否需要排队等待其他用户动作完成 + +#### 4.2.4 第四步:动态规划与执行 + +**职责**:基于前三步结果,动态生成执行计划。 + +``` +[规划] LLM 根据意图 + 状态 + 上下文生成执行计划 +[校验] 工作流规则引擎校验计划合法性 +[执行] 一步步执行,每步有 checkpoint +[审批] 对应人工节点挂起,收集批准后再继续 +[沉淀] 状态写回工作流引擎,文档归档到工作区 +``` + +**关键原则**: +- 计划应该是**动态生成的、有校验的、有人工节点的** +- 关键节点(审批、对外发送、修改已发布文档)必须有人工 gate +- 不要让 agent 自主完成闭环动作 + +### 4.3 候选意图的多输出策略 + +LLM 在意图判断时,**不要直接选一个**,而是输出 top3 + 置信度: + +``` +Candidates: + 1. SUPPLEMENT_INFO (置信度: 0.72) + 证据: 用户提到"附件"、"参考"、"情况说明" + + 2. INITIATE_MODIFY (置信度: 0.45) + 证据: 用户提到"改一下"、"更新" + + 3. CASUAL_CHAT (置信度: 0.15) + 证据: 问候语 + 无明确项目对象 +``` + +再结合 Context 中的规则佐证: +- 候选 1 是否匹配当前工作流阶段允许的信息收集动作? +- 候选 2 提到的对象是不是该用户有权限编辑的文档? +- 候选 3 是不是真的没有项目对象? + +最后由 L2 做终审,无论 L1 觉得哪个候选最可能,都要提交给 L2 校验。 + +### 4.4 用户澄清策略 + +**原则**:**必要时追问,但不滥用追问**。 + +``` +if top1_confidence > 0.75 and top1_passes_rule_check: + execute_directly() +elif top1_and_top2_confidence_close and neither_passed: + ask_user_to_clarify() // "您是想……还是想……?" +else: + fall_through_to_L2_review() // L2 终审决定 +``` + +澄清问题应该: +- 一句话能问清 +- 给出候选项让用户选择 +- 不要超过 2-3 个问题 + +### 4.5 意图识别的可观测性 + +复杂意图系统上线后一定会出错。**必须**记录日志: + +``` +IntentLog { + session_id, + user_input, + context_snapshot_id, + step1_domain: "WORKFLOW", + step1_confidence: 0.91, + step2_intent: "MODIFY_DOC", + step2_filled_slots: {...}, + step2_missing_slots: [...], + step3_state_lookup: {...}, + step4_plan: {...}, + final_outcome: "ACCEPTED" | "REJECTED" | "PENDING_USER" | "PENDING_L2", + reject_reason: null | "REJECT_REASON_..." +} +``` + +错了能定位,能加规则或加 few-shot 样本修正。 + +--- + +## 五、实施优先级与延后项 + +### 5.1 骨架阶段必须做 + +按优先级落地,每步独立可测: + +| 步骤 | 内容 | 验证方式 | +|------|------|----------| +| 第 1 步 | 数据模型 + Context 组装 API | 手动调用 API 验证 Context 正确性 | +| 第 2 步 | 项目与文档状态机(正常流程) | 单元测试覆盖所有合法转移 | +| 第 3 步 | 对话系统接入 Context | 简单动作:打开/导出/查看待办 | +| 第 4 步 | 执行智能体接入 Context | 验证智能体在 Context 约束下行为正确 | +| 第 5 步 | 基础事件流与通知(消息列表) | 事件写入数据库、消息列表可读 | +| 第 6 步 | 审核、批准的最小闭环 | 端到端走通一个完整审批流 | + +### 5.2 数据模型预留但实现延后 + +数据结构上为以下能力留好位置,实现上先简化: + +- 文档章节级别的已读标记(先做文档级) +- 影响图的递归分析(先做直接依赖列表) +- 通知分级(P0/P1/P2/P3,先做平铺) +- 意见流的独立存储(先做内嵌字段) +- 批次修改的自动触发(先做手动触发) +- 跨项目协调(先做单项目) + +### 5.3 关键设计原则总结 + +1. **骨架优先**:先跑通最小可用闭环,再迭代细节。 +2. **职责分离**:对话(L1)、协调(L2)、执行(L3)各司其职。 +3. **Context 驱动**:让系统基于已知事实判断,而不是让 LLM 从零推理。 +4. **状态机核心**:项目、工作流、文档的所有规则都落到状态机转移约束里。 +5. **规则优先于 LLM**:确定性逻辑(权限、状态、依赖)由规则引擎执行,LLM 只做语言理解。 +6. **可观测性先行**:每一步意图判断都要可追溯,能定位错误。 + +--- + +## 附录 A:术语表 + +| 术语 | 定义 | +|------|------| +| PI-agent | 智能体框架,对话和执行系统的统一技术栈 | +| 智能体小队 | 基于 PI-agent 的多智能体协同执行系统 | +| Context | UserProjectContext,对话与执行的统一上下文 | +| 工作流 | 项目下的一个流程,由多个阶段组成 | +| 文档任务 | 工作流内的文档编制任务 | +| 编制人 | 负责文档起草与修订的角色 | +| 审核人 | 负责文档审核的角色,不可修改正文 | +| 批准人 | 负责文档最终批准的角色,不可修改正文 | +| 认领 | 用户对文档形成认知的动作(点开/导出) | +| 认知偏差 | 编制人看过文档后被他人擅自修改会扰乱其判断的现象 | +| 候选意图 | L1 对话层输出的意图提案,非最终决策 | +| L1 / L2 / L3 | 协作对话层 / 项目协调层 / 任务执行层 | + +--- + +## 附录 B:下一步建议 + +按本文档落地时,下一步建议从以下两项开始: + +1. **数据模型 + Context 组装 API(第 1 步)**:定义数据库表、Context 数据结构、组装查询接口。 +2. **状态机设计(第 2 步)**:细化工作流阶段流转、文档状态流转的完整定义。 + +这两块是骨架的基础,定了之后后续步骤就能顺次展开。 \ No newline at end of file