Archive pre-refactor interview notes and add current deep-dives on architecture evolution, issue-derived stories, and evidence gates.
1371 lines
50 KiB
Markdown
1371 lines
50 KiB
Markdown
# SuperBizAgent 架构演进深读
|
||
|
||
**用途**:巩固知识 + 面试准备 + 举一反三
|
||
**不是**:逐字讲稿、纯知识点清单、当前 API 手册
|
||
**材料日期**:2026-07-24
|
||
**依据**:`mvp/architecture/*` 现行文档、`archive/2026-07-05-legacy`、`archive/2026-07-22-legacy`、ISS-014 / ISS-015
|
||
|
||
---
|
||
|
||
## 0. 怎么用这份材料
|
||
|
||
| 目标 | 用法 |
|
||
|---|---|
|
||
| 巩固 | 按「决策环」读:目标 → 设计 → 失效模式 → 修复 → 留下的原则 |
|
||
| 面试 | 每个决策都能答三句:为什么、出过什么问题、和业界差在哪 |
|
||
| 举一反三 | 每节末尾的「迁移问题」用来练:换场景你会怎么选 |
|
||
|
||
**一条总主线(先背这句)**
|
||
|
||
> 这个项目一直在解同一个题:**概率系统(LLM)如何在故障诊断里给出可审计、可约束、可回放的结论。**
|
||
> 演进不是换框架追热点,而是不断重划边界:**什么交给模型推理,什么必须由确定性系统强制。**
|
||
|
||
**读的时候盯住四个轴**
|
||
|
||
1. **谁推理**:单 Agent / 多角色 / Graph
|
||
2. **谁约束**:Prompt 约定 / 代码门禁 / Harness
|
||
3. **证据如何成立**:隐式检索 / 显式 Tool / 引用验真 / 语义审查
|
||
4. **如何证明系统可信**:Trace、Eval、Release、Feedback
|
||
|
||
**图目录(面试白板优先练带 ★ 的)**
|
||
|
||
| 图 | 位置 | 白板优先级 |
|
||
|---|---|---|
|
||
| 核心矛盾:推理放大 / 越界阉割 | §1.2 | ★★ |
|
||
| 四阶段演进 | §2 | ★★★ |
|
||
| Phase0 医院会诊愿景 | §3.1 | ★ |
|
||
| Phase1 三角色 + 双入口 | §4.1 | ★★ |
|
||
| Phase2 五段证据流水线 | §5.1 | ★★★ |
|
||
| 证据绑定外键模型 | §5.1 | ★★★ |
|
||
| Phase2→3 职责迁移 | §6.2 | ★★★ |
|
||
| 当前系统总览 | §6.2 | ★★★ |
|
||
| Diagnosis 时序 | §6.2 | ★★ |
|
||
| 数据三层 | §6.3-C | ★★★ |
|
||
| 业界定位 | §6.5 | ★★ |
|
||
| Trace / Run 模型 | §7.2 | ★★ |
|
||
| 白板 60 秒速画 | §15 | ★★★ |
|
||
|
||
---
|
||
|
||
## 1. 问题域:为什么不是「套一个 Chatbot」
|
||
|
||
### 1.1 故障诊断对系统的真实要求
|
||
|
||
| 要求 | 普通 Chatbot | 诊断 Agent |
|
||
|---|---|---|
|
||
| 答案形态 | 通顺、有帮助即可 | 结论必须能指向证据 |
|
||
| 错误成本 | 用户再问一次 | 误导排障、误操作风险 |
|
||
| 可解释 | 可选 | 必须能回放「查了什么、为何这样说」 |
|
||
| 工具 | 可有可无 | 日志/指标/知识库是事实来源 |
|
||
| 失败 | 道歉重试 | 要区分:没查到 / 查到了推不出 / 系统故障 |
|
||
|
||
所以早期文档就把定位写成:**面向故障诊断的可追踪 Agent 工程,不是通用对话机器人。**
|
||
|
||
### 1.2 核心矛盾(后面所有设计都围着它转)
|
||
|
||
```text
|
||
LLM 擅长:规划路径、归纳症状、组织语言、在不确定下提出假设
|
||
LLM 不擅长:保证引用真实、遵守预算、不越权、不在失败时编造
|
||
|
||
因此:
|
||
推理能力要放大
|
||
越界能力要阉割
|
||
```
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph Prob["概率侧 · 交给模型"]
|
||
P1["规划排查路径"]
|
||
P2["选择下一个 Tool"]
|
||
P3["归纳症状与假设"]
|
||
P4["组织诊断表达"]
|
||
end
|
||
|
||
subgraph Det["确定性侧 · 交给系统"]
|
||
D1["只读 / Schema / 预算"]
|
||
D2["引用是否真实存在"]
|
||
D3["是否属于本 Run"]
|
||
D4["能否对用户发布"]
|
||
end
|
||
|
||
User["用户问题"] --> Prob
|
||
Prob -->|"Draft / tool_call"| Det
|
||
Det -->|"放行或 Fallback"| Out["公开通道 SSE"]
|
||
Det -.->|"拒绝越界"| Prob
|
||
```
|
||
|
||
**面试一句话**
|
||
|
||
> 我们不是在提高模型智商,而是在给模型装护栏,并让每次越界都可观测。
|
||
|
||
**举一反三**
|
||
|
||
- 客服退款 Agent:同样要把「查订单」与「执行退款」拆成不同权限边界。
|
||
- 代码修改 Agent:同样要把「提议 diff」与「落地 apply/merge」拆开。
|
||
- 任何 Tool-using Agent:先问「模型输出里哪些字段必须能被系统复验」。
|
||
|
||
---
|
||
|
||
## 2. 演进总图:四个阶段在解决什么
|
||
|
||
```text
|
||
Phase 0 愿景:医院会诊式多角色协作
|
||
解决「复杂诊断需要分工」的组织问题(设计层)
|
||
|
||
Phase 1 MVP:Planner / Executor / Verifier + 显式 Tool + Trace
|
||
解决「先跑通可追踪闭环」的落地问题
|
||
|
||
Phase 2 证据工程化:Gatekeeper + Composer + evidence_v2 + 双入口 + Skill
|
||
解决「幻觉与证据不可核验」的质量问题
|
||
|
||
Phase 3 重构:单 Diagnosis ReAct Agent + 确定性 Harness
|
||
解决「把 ReAct 拆成多 LLM 角色后的编排税与成本失控」
|
||
|
||
Phase 4 收敛:ISS-015 停止策略 / Repair / Reasoning 治理 / 信息化 Fallback
|
||
解决「架构对了但运行质量与审计治理未完成」
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
P0["Phase 0 愿景<br/>医院会诊 Multi-Agent"]
|
||
P1["Phase 1 MVP<br/>Planner → Executor → Verifier"]
|
||
P2["Phase 2 证据工程化<br/>+ Gatekeeper + Composer"]
|
||
P3["Phase 3 重构 ★当前<br/>单 ReAct Agent + Harness"]
|
||
P4["Phase 4 收敛<br/>ISS-015 运行质量"]
|
||
|
||
P0 -->|"复杂度前置,先收敛"| P1
|
||
P1 -->|"幻觉:引用不可核验"| P2
|
||
P2 -->|"编排税 / Token / 重复 ReAct"| P3
|
||
P3 -->|"架构冻结后的策略债"| P4
|
||
|
||
P0 -.- N0["组织问题"]
|
||
P1 -.- N1["闭环问题"]
|
||
P2 -.- N2["正确性问题"]
|
||
P3 -.- N3["运行时问题"]
|
||
P4 -.- N4["治理与体验"]
|
||
```
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph Add["Phase 0→2:做加法"]
|
||
A1["加角色"]
|
||
A2["加证据契约"]
|
||
A3["加代码验真"]
|
||
A4["加双入口 / Skill"]
|
||
end
|
||
|
||
subgraph Move["Phase 3:做迁移,不是做减法能力"]
|
||
M1["推理 → 回到单 Agent"]
|
||
M2["约束 → 上收 Harness"]
|
||
M3["验真语义 → Evidence/Semantic/Release"]
|
||
end
|
||
|
||
Add -->|"负债:编排重复实现 ReAct"| Move
|
||
```
|
||
|
||
**重要心智模型**
|
||
|
||
- Phase 0→2 是在加能力、加约束。
|
||
- Phase 3 不是否定证据工程,而是**把证据工程从「角色流水线」搬进「执行边界」**。
|
||
- 面试时最容易说错的是:「我们从复杂架构简化成单 Agent,所以更粗糙」。
|
||
正确说法是:「推理合并回 Agent,约束上收到 Harness,证据门禁更硬而不是更软。」
|
||
|
||
---
|
||
|
||
## 3. Phase 0:为什么一开始会想到「多 Agent 医院会诊」
|
||
|
||
### 3.1 为什么这么设计
|
||
|
||
早期完整架构用医院隐喻:
|
||
|
||
| 角色 | 隐喻 | 意图 |
|
||
|---|---|---|
|
||
| Supervisor | 院长 | 调度谁来干、何时停 |
|
||
| Planner | 分诊 | 判类型、拆步骤、选专科 |
|
||
| SubAgent | 专科医生 | API/DB/Cache 各有工具与 Prompt |
|
||
| Verifier | 质检 | 防误诊 |
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
U["用户输入"] --> Sup["Supervisor<br/>院长:谁来干 / 何时停"]
|
||
Sup --> Pl["Planner<br/>分诊:fault_category + 步骤"]
|
||
Pl --> SA["SubAgent 层"]
|
||
SA --> API["ExternalApi"]
|
||
SA --> DB["Database"]
|
||
SA --> Cache["Cache ..."]
|
||
API --> V["Verifier 质检"]
|
||
DB --> V
|
||
Cache --> V
|
||
V -->|PASS| R["诊断报告"]
|
||
V -->|REVISE| Pl
|
||
```
|
||
|
||
这在**组织设计**上合理:真实 SRE 排障也是「先分流、再专科、再交叉验证」。
|
||
同时规划了 Skill、进程隔离、MCP、进化引擎——那是生产级愿景,不是第一周实现清单。
|
||
|
||
### 3.2 会出现什么问题(如果直接实现)
|
||
|
||
1. **复杂度前置**:还没证明通用 Executor 不够用,就先拆专科,评测和 Prompt 成本指数上升。
|
||
2. **边界模糊**:Planner 既分诊又写报告、SubAgent 既查证又下结论时,出了幻觉不知道该改谁。
|
||
3. **没有触发条件的演进**:为“架构完整”而拆,而不是为“可测量的失败模式”而拆。
|
||
|
||
### 3.3 如何解决(当时的正确收敛)
|
||
|
||
演进路线文档明确:
|
||
|
||
- 当前文档只写已可运行的能力。
|
||
- SubAgent / MCP / 隔离都要有触发条件(Executor 过载、工具权限差异、评测能量化收益)。
|
||
- **没有 baseline 前,不自动优化 Prompt,不拆进程。**
|
||
|
||
### 3.4 和业界主流的关系
|
||
|
||
| 方向 | 业界常见 | 本项目早期 | 评论 |
|
||
|---|---|---|---|
|
||
| Multi-Agent 分工 | CrewAI / AutoGen / 手写角色群 | 医院会诊模型 | 叙事强,落地成本高 |
|
||
| 先单 Agent 再拆 | Anthropic 等实践更常从单循环长出来 | 先愿景后收敛 MVP | 本项目最终也回到「先单后拆」 |
|
||
| 专科路由 | 大厂内部常按域拆服务/Agent | 作为 P2 演进项 | 触发条件写清楚是加分项 |
|
||
|
||
**迁移问题**
|
||
|
||
> 如果你负责一个「销售 + 售后 + 财务」客服,你会第一天就拆三个 Agent 吗?
|
||
> 什么指标出现后你才拆?
|
||
|
||
---
|
||
|
||
## 4. Phase 1:MVP 为什么是「Planner → Executor → Verifier」
|
||
|
||
### 4.1 为什么这么设计
|
||
|
||
目标从“完整医院”收敛为“可演示、可追踪的诊断闭环”:
|
||
|
||
```text
|
||
用户问题
|
||
→(意图:只有诊断才走全链路)
|
||
→ Planner:定排查方向
|
||
→ Executor:调 lookup_knowledge / logs / metrics
|
||
→ Verifier:质量门禁
|
||
→ session / step / tool_invocation 可回放
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Entries["双入口"]
|
||
ChatIn["POST /api/chat"]
|
||
AiOpsIn["POST /api/ai_ops"]
|
||
end
|
||
|
||
ChatIn --> CS["ChatService"]
|
||
AiOpsIn --> AS["AiOpsService"]
|
||
|
||
CS --> Intent{"意图"}
|
||
Intent -->|闲聊/文档| Light["轻量路径"]
|
||
Intent -->|诊断| P["Planner"]
|
||
P --> E["Executor"]
|
||
E --> T["Tools<br/>knowledge / logs / metrics"]
|
||
T --> E
|
||
E --> V["Verifier LLM"]
|
||
V --> Ans["答案 + self_evaluation"]
|
||
|
||
AS --> Sup["Supervisor"]
|
||
Sup --> P2["Planner"]
|
||
Sup --> E2["Executor"]
|
||
E2 --> T2["Prometheus / logs / knowledge"]
|
||
T2 --> Rule["Rule Evaluation"]
|
||
|
||
Ans --> Trace["session / step / tool_invocation"]
|
||
Rule --> Trace
|
||
```
|
||
|
||
并行还有 AIOps 入口:告警驱动,Supervisor 调度 Planner/Executor,先用**规则评估**做轻量聚焦检查。
|
||
|
||
**设计动机拆解**
|
||
|
||
| 决策 | 动机 |
|
||
|---|---|
|
||
| 意图识别前置 | 闲聊/文档问答不该付全链路 Token |
|
||
| Planner 与 Executor 分离 | 避免「边想边查」时计划被工具噪声带偏(当时的假设) |
|
||
| Verifier 独立 | 写答案的人不该同时当唯一质检 |
|
||
| 工具显式 | 决策可见,才能进 Trace |
|
||
| Chat 与 AIOps 双入口 | 交互诊断 vs 告警诊断触发方式不同 |
|
||
|
||
### 4.2 出现的问题
|
||
|
||
1. **Verifier 是模型**:能抓“说不通”,难抓“引用根本不存在”。
|
||
2. **Executor 输出形态不稳**:有时直接写用户答案,有时罗列工具结果,后续难自动验。
|
||
3. **RAG 早期 L0 可跳过 L1**:关键词唯一命中被当成高置信,语义上可能完全不相关。
|
||
4. **AIOps 与 Chat 验证强度不一致**:一边规则、一边 LLM,故事难统一。
|
||
|
||
### 4.3 如何解决(通向 Phase 2)
|
||
|
||
- 坚持 `lookup_knowledge` 是 Tool,不用隐式 Chat Advisor 吞掉检索。
|
||
- L0 从“可终局召回”降为 hint(domain/entity + filter 信号)。
|
||
- 开始要求更结构化的证据输出,并引入代码级验真(下一阶段 Gatekeeper)。
|
||
|
||
### 4.4 和业界主流的区别
|
||
|
||
| 主题 | 业界常见做法 | Phase 1 选择 | 差异本质 |
|
||
|---|---|---|---|
|
||
| RAG 接入 | Spring AI Advisor / 中间件静默注入上下文 | 显式 `lookup_knowledge` Tool | **可观测的 Agent 决策** vs 隐式增强 |
|
||
| 质量 | 输出后再人工抽检,或单一 LLM-as-Judge | 链路内 Verifier | 已有门禁意识,但还偏“模型审模型” |
|
||
| 编排 | 直接单 ReAct | 先拆 Planner/Executor/Verifier | 用角色表达生命周期,后续证明这是重复实现 |
|
||
| 告警场景 | 独立 SOAR/runbook 系统 | 同进程 AIOps Agent + rule eval | MVP 一体,但入口语义分叉 |
|
||
|
||
**面试深挖答法**
|
||
|
||
> 问:为什么 RAG 不走 Advisor?
|
||
> 答:Advisor 适合“聊天时附带资料”。诊断系统要回答的是「第几步为什么查库、查到了什么、结论绑哪条证据」。
|
||
> 隐式检索会让 Trace 里只剩最终答案,丢了决策过程。这是可审计性要求,不是接口偏好。
|
||
|
||
**迁移问题**
|
||
|
||
> 法律问答系统能否用隐式 RAG?若答案必须附法条编号,你的检索还敢静默注入吗?
|
||
|
||
---
|
||
|
||
## 5. Phase 2:证据工程化——本项目最「重」也最有辨识度的阶段
|
||
|
||
### 5.1 为什么这么设计
|
||
|
||
到这个阶段,团队已经看清:**诊断 Agent 的第一敌人不是文笔,是证据幻觉。**
|
||
|
||
于是 Chat 复杂链路变成:
|
||
|
||
```text
|
||
Planner
|
||
→ Executor(只产微观事实,不产最终用户答案)
|
||
→ Gatekeeper(代码验引用:invocation / raw_path / excerpt)
|
||
→ Verifier(只判断:已验真 excerpt 能否推出 claim)
|
||
→ Composer(只表达被允许的内容)
|
||
```
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
PL["Planner<br/>plan / skill"]
|
||
EX["Executor<br/>只产微观事实"]
|
||
GK["Gatekeeper<br/>0 LLM 引用验真"]
|
||
VF["Verifier<br/>能否推出 claim"]
|
||
CM["Composer<br/>只表达允许内容"]
|
||
OUT["用户答案"]
|
||
|
||
PL --> EX
|
||
EX --> Tools["Tools"]
|
||
Tools --> EX
|
||
EX -->|"executor_evidence_v2"| GK
|
||
GK -->|"verified bindings"| VF
|
||
VF -->|"PASS / LOW / REJECT"| CM
|
||
CM --> OUT
|
||
|
||
Tools -.->|"tool_invocation<br/>+ evidence_refs"| GK
|
||
```
|
||
|
||
并固化契约 `executor_evidence_v2`:
|
||
|
||
```text
|
||
每条 claim 必须带 evidence_bindings:
|
||
tool_name
|
||
+ source_invocation_id
|
||
+ raw_path e.g. $.alerts[0] / $.no_evidence
|
||
+ evidence_excerpt 必须能在工具返回中找到的原文片段
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
Claim["claim<br/>CPU=92% 告警 firing"]
|
||
Bind["evidence_binding"]
|
||
Inv["tool_invocation id=517"]
|
||
Raw["raw_response JSON"]
|
||
Path["raw_path: $.alerts[0]"]
|
||
Ex["evidence_excerpt 原文片段"]
|
||
|
||
Claim --> Bind
|
||
Bind --> Inv
|
||
Bind --> Path
|
||
Bind --> Ex
|
||
Inv --> Raw
|
||
Path -->|"必须能定位"| Raw
|
||
Ex -->|"必须是子串/抽取"| Raw
|
||
|
||
GK["Gatekeeper = 外键 + 路径 + 原文检查"]
|
||
Bind --- GK
|
||
Raw --- GK
|
||
```
|
||
|
||
**这是在学数据库的什么?**
|
||
|
||
> 有点像「外键约束」:claim 不能指向不存在的 invocation,也不能指向对不上的路径。
|
||
> Gatekeeper 就是约束检查器;Verifier 才是业务规则引擎。
|
||
|
||
### 5.2 分层门禁在解决哪类错误
|
||
|
||
| 错误类型 | 例子 | 谁抓 |
|
||
|---|---|---|
|
||
| 伪造调用 | 编造 invocation id | Gatekeeper |
|
||
| 路径漂移 | id 对但 raw_path 指到别的字段/条目 | Gatekeeper |
|
||
| excerpt 编造 | 引用了工具没返回的句子 | Gatekeeper |
|
||
| 推不过去 | excerpt 真实,但推不出 root cause | Verifier |
|
||
| 表达越权 | 把 no-evidence 说成“已排除根因” | Composer / 规则 |
|
||
| 告警跑偏 | payload 是 A,报告大谈 B 告警 | AIOps rule evaluation |
|
||
|
||
**负向证据(negative_observation)为什么重要**
|
||
|
||
排障里「查了但没有」也是信息。
|
||
若不建模 `$.no_evidence`,模型要么沉默,要么把“没查到”说成“不存在问题”。
|
||
|
||
### 5.3 这个阶段实际暴露/放大的问题
|
||
|
||
ISS-014 后来总结得很准——**设计在质量上前进了,在运行结构上负债了**:
|
||
|
||
#### 问题 A:ReAct 被外层重复实现
|
||
|
||
```text
|
||
完整 ReAct 生命周期:
|
||
想 → 动 → 观察 → 再想 → 最终答
|
||
|
||
被拆成多个 LLM 角色后:
|
||
Planner ≈ 想
|
||
Executor ≈ 动/观察循环
|
||
Verifier ≈ 自检
|
||
Composer ≈ 最终答
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Native["框架已具备的 ReAct"]
|
||
direction LR
|
||
T["Thought"] --> A["Action"] --> O["Observation"] --> T
|
||
O --> F["Final"]
|
||
end
|
||
|
||
subgraph Outer["Phase2 外层又演一遍"]
|
||
direction LR
|
||
PL["Planner≈Thought"] --> EX["Executor≈Act/Obs"]
|
||
EX --> VF["Verifier≈自检"]
|
||
VF --> CM["Composer≈Final"]
|
||
end
|
||
|
||
Native -.->|"重复实现 + JSON 接力税"| Outer
|
||
```
|
||
|
||
于是你要额外维护:多 Prompt、多 Schema、角色间 JSON 搬运、多套重试、ThreadLocal 隐式状态、失败×低置信×补证据的分支组合。
|
||
|
||
#### 问题 B:Tool 返回面向开发者,不面向 Agent(违反 ACI)
|
||
|
||
一次检索结果里混着:
|
||
|
||
- Agent 真正需要的证据
|
||
- rerank/debug 字段
|
||
- 重复正文与打包上下文
|
||
- 不一致的空结果/错误语义
|
||
|
||
后果:上下文膨胀、模型抓错字段、Token 预算被噪声吃掉(ISS-012)。
|
||
|
||
#### 问题 C:确定性约束与业务编排耦合
|
||
|
||
Gatekeeper 本质是**纯函数式校验**,却以流水线“角色/步骤”的姿态嵌在业务编排里,导致:
|
||
|
||
- 生命周期和业务步骤缠在一起
|
||
- 失败语义要和 LLM 节点失败一起解释
|
||
- 后续想做预算/取消/投影时,没有统一执行边界
|
||
|
||
#### 问题 D:双入口与多验证器让产品语义分叉
|
||
|
||
Chat 与 AIOps 两套服务、两套验证强度、两套叙事,Demo 很全,但“系统到底是什么”变难讲,实现分叉成本高。
|
||
|
||
### 5.4 当时为什么仍值得做(面试一定要会辩护)
|
||
|
||
即使后来重构掉多角色,Phase 2 不是弯路,而是**必要的认知阶段**:
|
||
|
||
1. 证明了「引用必须可机器复验」。
|
||
2. 证明了「写证据的人 / 验证引用的人 / 判断推导的人 / 对外表达的人」关注点不同。
|
||
3. 沉淀了 eval fixture、trace 检查清单、bad case(幻觉、窄范围越权、负向证据等)。
|
||
4. 为 Phase 3 提供了**可迁移的门禁语义**(不是推倒重来,是换装载位置)。
|
||
|
||
**面试金句**
|
||
|
||
> Phase 2 解决的是正确性模型;Phase 3 解决的是运行时模型。
|
||
> 没有 Phase 2,单 Agent 只会更快地产生不可验的漂亮废话。
|
||
|
||
### 5.5 和业界主流的区别
|
||
|
||
| 能力 | 常见开源 Agent 示例 | Phase 2 | 你的辨识度 |
|
||
|---|---|---|---|
|
||
| 工具调用 | ReAct / OpenAI tool calls | 有 | 常规 |
|
||
| 引用标注 | 让模型自己说 sources | **强制 binding + 代码核验** | 强 |
|
||
| 输出分层 | 直接 final answer | evidence 草稿与用户答案分离 | 强 |
|
||
| 验证 | 单次 LLM judge | 确定性 Gatekeeper + 语义 Verifier | 强 |
|
||
| 编排 | 一个 loop 或一个 graph 节点集 | 固定 Sequential 五段 | 偏重,后成负债 |
|
||
| RAG | 中间件注入或单次 retrieve | Tool 化 + L0 hint + VectorStore/fallback | 工程化中等偏上 |
|
||
|
||
对比常见口号:
|
||
|
||
- **RAGAS / LLM-as-Judge**:偏离线或事后评估;本项目把一部分检查**前移到请求路径**。
|
||
- **LangGraph hitl / interrupt**:偏人工确认;本项目 Phase 2 偏自动门禁。
|
||
- **Guardrails 类库**:常做 schema/topic/toxicity;本项目护栏围绕**证据所有权与可推导性**。
|
||
|
||
**迁移问题**
|
||
|
||
> 若你做「根据内部 Wiki 答合规问题」,最小可行的 Gatekeeper 要校验哪些字段?
|
||
> (文档 id、chunk id、原文 offset、quote 是否子串匹配……)
|
||
|
||
---
|
||
|
||
## 6. Phase 3:为什么重构为「单 ReAct Agent + Harness」
|
||
|
||
### 6.1 重构触发条件(不是审美驱动)
|
||
|
||
ISS-014 的判定可以翻译成四个可对外讲的信号:
|
||
|
||
1. **结构重复**:外层编排 ≈ 框架已提供的 ReAct。
|
||
2. **成本症状**:上下文重复搬运、Token 易爆、多角色固定税。
|
||
3. **失败语义组合爆炸**:每个角色的 FAIL/LOW_CONFID/RETRY 交叉。
|
||
4. **安全能力放错层**:该确定性的事还在业务流水线里“扮演角色”。
|
||
|
||
### 6.2 目标结构
|
||
|
||
```text
|
||
POST /api/chat (唯一执行入口, SSE)
|
||
→ ChatApplicationUseCase
|
||
→ Intent Router
|
||
SYSTEM_CHAT | KNOWLEDGE_QUERY | DIAGNOSIS
|
||
|
||
DIAGNOSIS:
|
||
Diagnosis ReAct Agent
|
||
规划 / 选 Tool / 观察 / 写 DiagnosisDraft
|
||
→ EvidenceGuard (0 LLM, 结构+引用+Run ownership)
|
||
→ SemanticGuard (隔离单轮 LLM, 无 Tool/无记忆)
|
||
→ Release Policy (SUPPORTED 才公开, 否则 SAFE_FALLBACK / stable failure)
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
Browser["Browser / API Client"] --> Chat["POST /api/chat<br/>named SSE"]
|
||
Chat --> App["ChatApplicationUseCase"]
|
||
App --> Router{"Intent Router"}
|
||
|
||
Router --> Sys["SYSTEM_CHAT<br/>无 Tool"]
|
||
Router --> Know["KNOWLEDGE_QUERY<br/>单次 lookup + 引用校验"]
|
||
Router --> Diag["DIAGNOSIS"]
|
||
|
||
Diag --> Agent["Diagnosis ReAct Agent"]
|
||
Agent --> TB["Harness ToolBoundary"]
|
||
TB --> Redis["Redis canonical"]
|
||
TB --> Agent
|
||
Agent --> Draft["DiagnosisDraft"]
|
||
|
||
Draft --> EG["EvidenceGuard<br/>0 LLM"]
|
||
EG --> SG["SemanticGuard<br/>隔离单轮"]
|
||
SG --> RP["Release Policy"]
|
||
RP -->|SUPPORTED| SSE["公开 content"]
|
||
RP -->|否则| FB["SAFE_FALLBACK / failure"]
|
||
|
||
App --> Run["diagnosis_run"]
|
||
Agent --> Step["agent_step metadata"]
|
||
TB --> Inv["tool_invocation metadata"]
|
||
App --> TL["diagnosis_trace_event"]
|
||
Agent --> RA["agent_reasoning_audit"]
|
||
```
|
||
|
||
**职责迁移图(面试最常画)**
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph Old["Phase 2 角色"]
|
||
O1["Planner"]
|
||
O2["Executor"]
|
||
O3["Gatekeeper"]
|
||
O4["Verifier"]
|
||
O5["Composer"]
|
||
end
|
||
|
||
subgraph New["Phase 3 归属"]
|
||
N1["Diagnosis Agent 内部"]
|
||
N2["Agent + ToolBoundary"]
|
||
N3["EvidenceGuard"]
|
||
N4["SemanticGuard"]
|
||
N5["Draft + Release Policy"]
|
||
end
|
||
|
||
O1 --> N1
|
||
O2 --> N2
|
||
O3 --> N3
|
||
O4 --> N4
|
||
O5 --> N5
|
||
```
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as Client
|
||
participant App as UseCase
|
||
participant A as Diagnosis Agent
|
||
participant TB as ToolBoundary
|
||
participant R as Redis
|
||
participant EG as EvidenceGuard
|
||
participant SG as SemanticGuard
|
||
participant RP as Release
|
||
|
||
C->>App: POST /api/chat
|
||
App->>C: metadata(session_id, run_id)
|
||
App->>A: query + safe previous_turn
|
||
loop ReAct
|
||
A->>TB: tool + tool_call_id + args
|
||
TB->>R: canonical raw + projection
|
||
TB-->>A: bounded agent_result
|
||
end
|
||
A-->>App: DiagnosisDraft
|
||
App->>EG: Draft + current Run invocations
|
||
EG-->>App: verified snapshot / fail
|
||
App->>SG: query + Draft + snapshot
|
||
SG-->>App: SUPPORTED / UNSUPPORTED
|
||
App->>RP: decide
|
||
RP-->>C: content | fallback
|
||
RP-->>C: done(SUCCESS|FALLBACK|FAILED)
|
||
```
|
||
|
||
**职责重划一览**
|
||
|
||
| 旧角色 | 新归属 | 说明 |
|
||
|---|---|---|
|
||
| Planner | Diagnosis Agent 内部 | 不再单独付一次“只规划”的链路税 |
|
||
| Executor Tool loop | Diagnosis Agent + ToolBoundary | 循环回到 Agent;边界在 Harness |
|
||
| Gatekeeper | EvidenceGuard | 仍 0 LLM,更明确是执行约束 |
|
||
| Verifier | SemanticGuard | 保留“独立上下文审查”,去掉工具与记忆 |
|
||
| Composer | Agent Draft + Release Policy | 表达权在 Agent,**发布权**在 Harness |
|
||
| ChatService 大流程状态机 | UseCase + RunControl | 生命周期 first-terminal-wins |
|
||
| AIOps 独立入口 | (收敛到统一 Chat 叙事) | 减少产品分叉(以现行文档为准) |
|
||
|
||
### 6.3 关键设计为什么“长这样”
|
||
|
||
#### A. 单 Agent:把推理完整性还给一次上下文
|
||
|
||
**为什么**
|
||
|
||
- 诊断需要根据观察动态改计划;硬切成 Planner 产出静态 plan 再交给 Executor,容易在信息到齐前定死路线,或为修正路线再开重试环。
|
||
- 同一 Run 内共享连贯工作记忆,比 JSON 接力更符合 ReAct。
|
||
|
||
**不是什么**
|
||
|
||
- 不是取消规划,而是取消“规划必须是另一个 Agent 节点”。
|
||
- 不是取消验证,而是验证不再以“业务协作角色”存在。
|
||
|
||
#### B. Harness:确定性控制面
|
||
|
||
Harness 管的是:
|
||
|
||
- Run/deadline/cancel/预算
|
||
- Tool schema/只读/次数
|
||
- canonical invocation(Redis)与 Agent projection
|
||
- Evidence / Semantic / Release
|
||
- metadata Trace 与 reasoning 审计隔离
|
||
|
||
**一句话**
|
||
|
||
> Agent 是员工;Harness 是门禁、报销制度、权限系统和发布流程。
|
||
|
||
#### C. 数据三层(ACI 的核心落地)
|
||
|
||
```text
|
||
Redis canonical invocation
|
||
完整 request / raw_response / agent_result
|
||
短 TTL,Harness only
|
||
|
||
Agent projection
|
||
有界、聚合、可继续推理的观察
|
||
唯一允许回流 Agent 的视图
|
||
|
||
Durable audit (MySQL)
|
||
长期 metadata:谁、何时、哪个 tool、状态、字节数…
|
||
不存 Prompt 全文、不存 raw、不存 Thought 当事实
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
ToolExec["Tool 真实执行"] --> Raw["raw_response 可能很大"]
|
||
Raw --> Canon["Redis canonical<br/>Harness only · TTL · 完整"]
|
||
Canon --> Proj["ToolResultProjector"]
|
||
Proj --> AgentView["agent_result 有界投影"]
|
||
AgentView --> Agent["Diagnosis Agent 继续推理"]
|
||
Canon --> EG["EvidenceGuard 验真"]
|
||
AgentView --> EG
|
||
ToolExec --> Meta["MySQL tool_invocation<br/>metadata-only 长期审计"]
|
||
|
||
Agent -.->|"禁止直连"| Canon
|
||
Agent -.->|"禁止见 raw"| Raw
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
Q["同一 Tool 调用,三份不同视图"]
|
||
Q --> C["① canonical raw<br/>验真用 · 短 TTL · Harness only"]
|
||
Q --> P["② projection<br/>推理用 · 有界 · 回 Agent"]
|
||
Q --> M["③ metadata audit<br/>长期用 · MySQL · 无正文 raw"]
|
||
```
|
||
|
||
这直接回应 Phase 2 的上下文膨胀:
|
||
**验真需要完整事实,推理只需要有界观察,审计需要长期元数据——三者不是同一份 JSON。**
|
||
|
||
#### D. EvidenceGuard vs SemanticGuard 为什么拆开
|
||
|
||
| | EvidenceGuard | SemanticGuard |
|
||
|---|---|---|
|
||
| 要不要模型 | 否 | 是(隔离单轮) |
|
||
| 问什么 | 引用是否真实、是否属于本 Run、结构是否合法 | 整份报告是否被证据支持、是否越界表达 |
|
||
| 失败含义 | 数据/契约问题 | 语义/推理问题 |
|
||
| 类比 | 类型检查 / 外键 | 代码 review / 逻辑审查 |
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
Draft["DiagnosisDraft"] --> EG{"EvidenceGuard<br/>物理/结构/归属"}
|
||
EG -->|fail| FB1["不可发布<br/>契约/引用问题"]
|
||
EG -->|verified snapshot| SG{"SemanticGuard<br/>整份语义是否越证"}
|
||
SG -->|UNSUPPORTED| FB2["SAFE_FALLBACK"]
|
||
SG -->|SUPPORTED| RP["Release<br/>公开 typed report"]
|
||
|
||
EG -.- E1["0 LLM"]
|
||
SG -.- E2["隔离 · 无 Tool · 无记忆"]
|
||
```
|
||
|
||
混成一个“超级 Verifier”会重新出现:模型既要装法官又要装扫描仪,且失败原因不可分。
|
||
|
||
#### E. Release Policy 为什么必须存在
|
||
|
||
即使 Draft 写得漂亮:
|
||
|
||
- Evidence 失败 → 不能当成功答案出去
|
||
- Semantic UNSUPPORTED → 只能 SAFE_FALLBACK
|
||
- cancel/timeout → 禁止 late content
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
Internal["内部 Draft<br/>staging 制品"] --> Gate{"Release Policy"}
|
||
Gate -->|SUPPORTED| Pub["公开 SSE<br/>production"]
|
||
Gate -->|UNSUPPORTED / evidence fail| Safe["SAFE_FALLBACK<br/>有界说明"]
|
||
Gate -->|tech fail| Fail["stable failure"]
|
||
Gate -->|cancel/timeout| Stop["终态 · 禁 late content"]
|
||
```
|
||
|
||
**公开通道与内部草稿必须切断。**
|
||
这对应安全发布思想:staging 制品不能直接当 production。
|
||
|
||
#### F. Reasoning 分表
|
||
|
||
Provider 若返回 `reasoning_content` 等字段:
|
||
|
||
- 可进 `agent_reasoning_audit`(截断、计字节)
|
||
- 不进普通 Trace / SSE / Evidence / 业务判断
|
||
- Provider 没返回时记 unavailable,**禁止伪造**
|
||
|
||
这是在学:
|
||
**思维链若存在,它是敏感审计数据,不是可引用事实,更不是产品功能输出。**
|
||
|
||
### 6.4 重构时明确放弃/降级的东西
|
||
|
||
| 放弃 | 原因 |
|
||
|---|---|
|
||
| 业务层 StateGraph/多角色 Sequential | 与框架 ReAct 重复,编排税高 |
|
||
| 以 DB `tool_invocation.id` 为引用主键的重协议 | 改为框架 `tool_call_id` + 当前 Run ownership,贴合运行时 |
|
||
| 完整历史进下一轮 | PreviousTurn 仅最近一次成功发布的有界字段 |
|
||
| 把 self_evaluation 多种 LLM 评估缠在主叙事 | 收敛到 Guard + Release + Timeline |
|
||
| 推倒证据思想 | **保留**“先物理验真、再语义审查、再发布” |
|
||
|
||
### 6.5 和业界主流架构的对照(面试高频)
|
||
|
||
#### 6.5.1 总表
|
||
|
||
| 架构族 | 代表形态 | 优点 | 风险 | 与本项目 |
|
||
|---|---|---|---|---|
|
||
| 单 ReAct + Tools | 多数 Demo / 助手 | 简单、动态 | 易幻觉、难审计 | **骨架相同**,本项目多了硬 Harness |
|
||
| Multi-Agent 协作 | Crew / 手写角色群 | 分工清晰 | 重复上下文、权责漂移 | Phase 2 接近;Phase 3 退出主路径 |
|
||
| Graph 编排 | LangGraph 等 | 可控分支、打断、持久状态 | 易把业务状态机写重 | **业务层不用 Graph**;框架内部实现无关 |
|
||
| Router + Experts | 意图路由到专科 | 域深 | 需分类准、评测全 | Intent Router 轻量存在;专科专家未拆 |
|
||
| Agent + Guardrail 管道 | 输入/输出护栏产品 | 合规快 | 常缺“证据所有权” | 本项目护栏更偏 **tool evidence** |
|
||
| SOAR / Runbook | 固定剧本自动化 | 稳定可预期 | 难覆盖长尾自然语言 | Playbook 是演进项,不是当前主路径 |
|
||
|
||
#### 6.5.2 你要能讲清的「三个不一样」
|
||
|
||
**1)和“纯 ReAct Demo”不一样**
|
||
|
||
```text
|
||
纯 ReAct: model ↔ tools ↔ final text
|
||
本项目: model ↔ (ToolBoundary/projection) ↔ draft
|
||
↔ EvidenceGuard ↔ SemanticGuard ↔ Release ↔ public SSE
|
||
+ Run budget/cancel + Timeline + reasoning audit
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Demo["纯 ReAct Demo"]
|
||
M1["Model"] <--> T1["Tools"]
|
||
M1 --> F1["final text 直接出门"]
|
||
end
|
||
|
||
subgraph Ours["本项目"]
|
||
M2["Model"] <--> TB["ToolBoundary + projection"]
|
||
M2 --> D["Draft 仅内部"]
|
||
D --> G1["EvidenceGuard"]
|
||
G1 --> G2["SemanticGuard"]
|
||
G2 --> R["Release"]
|
||
R --> PUB["public SSE"]
|
||
H["Harness: budget / cancel / timeline / reasoning audit"]
|
||
H -.-> M2
|
||
H -.-> TB
|
||
H -.-> R
|
||
end
|
||
```
|
||
|
||
**2)和“Multi-Agent 很强”叙事不一样**
|
||
|
||
> 多 Agent 的正确动机是:权限不同、知识不同、失败域不同、需要并行。
|
||
> 错误动机是:用角色名重新描述一遍 ReAct 步骤。
|
||
> 我们踩过后面这种坑,所以合并。
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Wrong["错误动机:给 ReAct 步骤起名"]
|
||
W1["Planner"] --> W2["Executor"] --> W3["Verifier"] --> W4["Composer"]
|
||
end
|
||
|
||
subgraph Right["合法动机:真正的失败域/权限不同"]
|
||
R1["只读诊断 Agent"]
|
||
R2["变更执行 Agent<br/>需审批"]
|
||
R3["财务退款 Agent<br/>强权限"]
|
||
end
|
||
|
||
Wrong -.->|"本项目 Phase2 偏这类"| X["合并回单 Agent"]
|
||
Right -.->|"才值得 Multi-Agent"| Y["保持拆分"]
|
||
```
|
||
|
||
**3)和“上 LangGraph 就企业级”不一样**
|
||
|
||
> Graph 解决的是状态与边;企业级还依赖:预算、取消、发布、数据分层、评测、审计隔离。
|
||
> 没有这些,Graph 只是更复杂的 if-else。
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Axes["横轴:编排复杂度 → 纵轴:控制面完整度 ↑"]
|
||
direction TB
|
||
Q2["② 目标区<br/>编排克制 + 控制面强<br/>★ 本项目当前"]
|
||
Q1["① 重 Graph 且有护栏<br/>企业工作流 + 审批/预算"]
|
||
Q3["③ Demo 常见区<br/>纯 ReAct · 控制面弱"]
|
||
Q4["④ 重编排轻护栏<br/>裸 Graph / 角色流水线过重"]
|
||
end
|
||
|
||
Q2 ~~~ Q1
|
||
Q3 ~~~ Q4
|
||
|
||
P2["Phase2 五段"] -.->|"偏右上但仍角色税高"| Q4
|
||
Now["Phase3 Agent+Harness"] --> Q2
|
||
Demo["纯 ReAct Demo"] --> Q3
|
||
```
|
||
|
||
白板口述版(不必画象限,画两点对比即可):
|
||
|
||
```text
|
||
控制面强
|
||
^
|
||
| ★ 本项目(单 Agent + Harness)
|
||
| · 企业 Graph+护栏
|
||
|
|
||
| Phase2 五段(能力强,编排税高)
|
||
|
|
||
| 纯 ReAct Demo 裸 Graph 无护栏
|
||
+-------------------------------------> 编排复杂
|
||
```
|
||
|
||
#### 6.5.3 和 OpenAI/Anthropic 工具调用范式
|
||
|
||
| 点 | 主流 API 范式 | 本项目 |
|
||
|---|---|---|
|
||
| tool_call_id | 协议层已有 | **直接作为证据引用主键之一**,不另造平行 ID 体系 |
|
||
| tool result | 多原样回灌 | **必须经 projector**,raw 进 Redis canonical |
|
||
| 并行 tools | 常见 | 受预算与只读边界约束 |
|
||
| 输出 | 自由文本或 JSON mode | 结构化 `DiagnosisDraft` + 分析项绑定 tool_call_id |
|
||
|
||
#### 6.5.4 和 RAG 主流(Modular RAG / Agentive RAG)
|
||
|
||
| 点 | 主流 | 本项目 |
|
||
|---|---|---|
|
||
| Query rewrite / rerank | 管线模块可选 | 可作为检索内部能力,但**对 Agent 应投影掉调试细节** |
|
||
| 引用 | 答案角标 | 运行时绑定 tool_call + Guard |
|
||
| 知识问答 vs 诊断 | 常混一个 bot | Intent 拆 SYSTEM / KNOWLEDGE / DIAGNOSIS |
|
||
| 评测 | 离线黄金集 | 有 diagnosis eval;RAG 有历史闭环设计 |
|
||
|
||
### 6.6 重构后仍未结束的问题(诚实加分)
|
||
|
||
ISS-015 说明架构冻结后的运行质量债:
|
||
|
||
- 重复检索直到预算耗尽
|
||
- Evidence Repair 的 schema/parse 问题
|
||
- Reasoning 真实 Provider 与访问治理未完
|
||
- Fallback 信息量不足(用户不知道已经看到了什么)
|
||
|
||
**面试怎么讲**
|
||
|
||
> 重构完成不等于产品完成。我们把架构风险从“结构错误”推进到了“策略与治理”,并用独立 Issue 跟踪,而不是偷偷在主链打补丁改变架构。
|
||
|
||
**迁移问题**
|
||
|
||
> 你在什么情况下会把已经合并的单 Agent 再拆开?请给出 3 个可量化触发条件。
|
||
> (参考本项目旧路线:Executor prompt 膨胀、工具权限显著分叉、分类评测证明拆分收益。)
|
||
|
||
---
|
||
|
||
## 7. 横切演进:五条独立故事线
|
||
|
||
面试官不一定按时间问,可能横切打穿。下面每条都按「为什么 → 问题 → 解决 → 业界」压缩。
|
||
|
||
### 7.1 RAG
|
||
|
||
| 阶段 | 策略 | 失效 | 收敛 |
|
||
|---|---|---|---|
|
||
| 早期 | L0 唯一命中可跳过 L1 | 关键词≠语义 | L0 降级为 hint |
|
||
| 中期 | VectorStore 主路径 + SDK fallback | 迁移期 schema/score 语义变 | auto 模式保主链 |
|
||
| 全程 | 显式 Tool | 隐式 Advisor 丢决策 | 坚持 Tool 化 |
|
||
| 当前 | projector 后的有界 evidence | 原始检索大包撑爆上下文 | canonical/projection 分离 |
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Early["早期 L0 可终局"]
|
||
E0["L0 关键词"] -->|唯一命中| Skip["跳过 L1 · 当答案"]
|
||
E0 -->|0/多命中| L1a["L1 向量"]
|
||
end
|
||
|
||
subgraph Now["当前"]
|
||
A["Agent 显式 lookup_knowledge"] --> L0["L0 hint<br/>domain/entity/filter"]
|
||
L0 --> L1["L1 VectorStore"]
|
||
L1 -->|fail| FB["Milvus SDK fallback"]
|
||
L1 --> Proj["projector 有界 evidence"]
|
||
FB --> Proj
|
||
Proj --> AgentObs["Agent 观察"]
|
||
Proj --> Canon["canonical 供 Guard 验真"]
|
||
end
|
||
|
||
Early -.->|"关键词≠语义"| Now
|
||
```
|
||
|
||
**业界差在**:很多系统优化召回率;本项目同等强调**召回结果如何成为可引用证据**。
|
||
|
||
### 7.2 Trace 与数据模型
|
||
|
||
```text
|
||
早期: session + step + tool_invocation
|
||
→ 中期: + diagnosis_run 精确一次运行
|
||
→ 当前: run 为真理源
|
||
+ 统一 diagnosis_trace_event Timeline
|
||
+ agent_step / tool_invocation metadata-only
|
||
+ agent_reasoning_audit 独立
|
||
```
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
CS["chat_session<br/>sessionId 多轮目录"]
|
||
CS --> R1["diagnosis_run runId=1"]
|
||
CS --> R2["diagnosis_run runId=2"]
|
||
R1 --> S1["agent_step metadata"]
|
||
R1 --> I1["tool_invocation metadata"]
|
||
R1 --> T1["diagnosis_trace_event Timeline"]
|
||
R1 --> A1["agent_reasoning_audit 受限"]
|
||
|
||
API1["GET .../trace?runId="] --> T1
|
||
API1 --> S1
|
||
API1 --> I1
|
||
API2["GET .../trace/reasoning?runId="] --> A1
|
||
|
||
API1 -.->|"不返回 reasoning 原文"| X["普通审计面"]
|
||
API2 -.->|"敏感审计面"| Y["独立治理 ISS-015"]
|
||
```
|
||
|
||
原则:
|
||
|
||
- 禁止“取最新一条”代替 exact `runId`
|
||
- Trace 写失败可观测,但不应改变业务结果
|
||
- 普通 Trace API 不返回 reasoning 原文
|
||
|
||
**业界差在**:很多 Demo 只有 LangSmith 外部 tracing;本项目把**业务可读 Timeline** 当作产品能力(并对敏感 reasoning 另通道)。
|
||
|
||
### 7.3 入口与会话
|
||
|
||
```text
|
||
双入口 Chat/AIOps
|
||
→ 统一 Chat + Intent
|
||
PreviousTurn: 全历史 / 失败上下文
|
||
→ 仅最近 SUCCESS published 有界字段
|
||
```
|
||
|
||
原则:多轮要的是**安全状态接力**,不是把噪声和未验证草稿接着喂给下一轮。
|
||
|
||
### 7.4 质量体系
|
||
|
||
```text
|
||
人工看 Demo
|
||
→ Gatekeeper/Verifier 在线门禁
|
||
→ diagnosis eval fixtures + baseline
|
||
→ Trace inspection checklist
|
||
→ 重构后 E2E + ISS-015 运行质量
|
||
```
|
||
|
||
原则:架构变更必须能指出**哪类 case 从红变绿/从绿变红**。
|
||
|
||
### 7.5 安全发布
|
||
|
||
```text
|
||
模型直接吐最终答案
|
||
→ Verifier 后再答
|
||
→ Draft 永不为公开,除非 Release 点头
|
||
```
|
||
|
||
类比持续交付:构建产物 ≠ 生产流量。
|
||
|
||
---
|
||
|
||
## 8. 决策环模板(用来巩固任意设计点)
|
||
|
||
对任何一个设计点,用同一模板自问自答:
|
||
|
||
```text
|
||
1. 威胁模型:若没有它,最可能出现什么坏结果?
|
||
2. 责任人:这件事该由模型判断,还是系统强制?
|
||
3. 数据面:完整事实 / 模型可见 / 长期审计 是否分层?
|
||
4. 失败语义:失败时用户看到什么?内部能诊断什么?
|
||
5. 可证伪:用什么 eval/trace 证明它有效?
|
||
6. 演进触发:什么指标会让我们改掉它?
|
||
```
|
||
|
||
### 练习:套到「SemanticGuard 无 Tool」
|
||
|
||
1. 威胁:Guard 自己再查库 → 主 Agent 与 Guard 证据集不一致,审查失去基线。
|
||
2. 责任:语义是否成立交给模型;能否再取证不交给它。
|
||
3. 数据:只给 query + full draft + verified snapshot。
|
||
4. 失败:技术失败有限重试后降级,不把内部异常吐给用户。
|
||
5. 可证伪:unsupported-claim、fabricated-invocation 等 fixture。
|
||
6. 触发:若误杀率过高,优先生证据投影与 Draft schema,而不是给 Guard 加 Tool。
|
||
|
||
---
|
||
|
||
## 9. 面试题库(按深度)
|
||
|
||
### 9.1 2 分钟:你的系统是什么
|
||
|
||
**结构建议**
|
||
|
||
1. 领域:故障诊断,不是通用聊天。
|
||
2. 当前形态:单 Diagnosis Agent + Harness 门禁 + 唯一 Chat 入口。
|
||
3. 演进一句:多角色证据流水线教会我们验真,再重构掉重复的 ReAct 编排。
|
||
4. 差异化:证据所有权、发布策略、Run 级回放。
|
||
|
||
### 9.2 为什么题(必练)
|
||
|
||
| 问题 | 得分要点 |
|
||
|---|---|
|
||
| 为什么最终单 Agent? | 多角色重复 ReAct;合并推理,上收约束 |
|
||
| 为什么还要 SemanticGuard? | 物理真不等于语义成立;且必须隔离上下文 |
|
||
| 为什么 EvidenceGuard 不用模型? | 引用归属是确定性的;用模型会引入不可复现误判 |
|
||
| 为什么 Redis 存 raw、MySQL 不存? | 验真要完整、长期存要控敏控体积、Agent 不能见 raw |
|
||
| 为什么 reasoning 单独 API? | 敏感、非事实、防污染普通审计与产品通道 |
|
||
| 为什么 PreviousTurn 极简? | 防把失败/fallback/raw 污染下一 Run |
|
||
| 为什么不业务层上 Graph? | 要的是边界清晰不是边更多;框架内部实现另算 |
|
||
|
||
### 9.3 对抗题(高级)
|
||
|
||
**Q:多 Agent 不是更清晰吗?你们是不是退步了?**
|
||
|
||
A:清晰应体现在**边界**(谁能写生产、谁能看 raw、谁能发布),不是体现在**角色数量**。
|
||
我们把 Gatekeeper/Verifier/Composer 的**语义**保留为 Guard/Release,把重复的 LLM 角色去掉。
|
||
角色变少,强制约束变多——这是进展。
|
||
|
||
**Q:和 LangGraph 生产案例比,你们会不会太简陋?**
|
||
|
||
A:Graph 擅长长流程状态、人机回环、复杂分支。
|
||
我们当前主路径是短周期诊断 ReAct,瓶颈在证据与发布,不在多图分支。
|
||
若以后出现:多日工单、人工批准变更、跨系统编排,再评估 Graph/工作流引擎——那是触发条件,不是名片。
|
||
|
||
**Q:SemanticGuard 不还是 LLM-as-Judge 吗?靠谱吗?**
|
||
|
||
A:是,所以它被降权:
|
||
- 只能看已验真快照;
|
||
- 无 Tool 不能“补证据自圆其说”;
|
||
- 不能单独发布,必须过 Release;
|
||
- 技术失败有降级路径。
|
||
它不是唯一真理,而是**最后一道语义保险丝**。
|
||
|
||
**Q:你们如何证明重构没有丢掉 Phase 2 的防幻觉能力?**
|
||
|
||
A:映射门禁 + 回归夹具 + E2E trace:
|
||
伪造引用、无证据负向观察、unsupported claim、narrow scope 等 case;
|
||
并看 release_outcome 与 timeline 事件是否仍能解释失败阶段。
|
||
|
||
### 9.4 让你“现场设计”的题(举一反三)
|
||
|
||
1. 给「SQL 查询 Agent」设计 EvidenceGuard:如何防止 `DROP`、如何防止编造查询结果?
|
||
2. 给「改代码 Agent」设计 Release Policy:什么情况下允许自动 PR?什么必须 human approval?
|
||
3. 工具从 3 个变成 30 个时,你先上 MCP 还是先上 Tool Registry + 权限组?为什么?
|
||
4. 若产品要“展示思考过程”,你如何在不污染事实证据的前提下做 UI?
|
||
|
||
每题都试着用第 8 节模板答。
|
||
|
||
---
|
||
|
||
## 10. 一张总对照表(背这张就够串场)
|
||
|
||
| 维度 | Phase 1 | Phase 2 | Phase 3(当前) |
|
||
|---|---|---|---|
|
||
| 主问题 | 跑通闭环 | 证据可核验 | 去掉重复编排、收敛控制面 |
|
||
| 推理结构 | 三角色 | 五段流水线 | 单 ReAct Agent |
|
||
| 确定性验真 | 弱/无 | Gatekeeper | EvidenceGuard |
|
||
| 语义审查 | Verifier | Verifier | SemanticGuard(隔离) |
|
||
| 对外表达 | 多在 Executor/Verifier 后直接 | Composer | Draft + Release |
|
||
| 工具结果 | 较原始 | 进 DB 细节多 | canonical / projection / audit 三层 |
|
||
| 入口 | Chat + AIOps | 同左 + Skill | 统一 Chat + Intent |
|
||
| 回放 | step/tool | + run + self_eval | Timeline + 独立 reasoning |
|
||
| 主要负债 | 幻觉 | 编排税/Token | 运行策略与治理(ISS-015) |
|
||
| 业界近似 | 初级 Tool Agent | 重型 multi-agent 流水线 | ReAct + 强 Guardrail/Harness |
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
P1["Phase1<br/>P→E→V"] --> P2["Phase2<br/>+GK +Composer"]
|
||
P2 --> P3["Phase3<br/>Agent + Harness"]
|
||
|
||
P1 -.- L1["能跑"]
|
||
P2 -.- L2["能验"]
|
||
P3 -.- L3["能控"]
|
||
```
|
||
|
||
**一图串三阶段(面试收口用)**
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph P1["Phase1 闭环"]
|
||
direction LR
|
||
A1["Plan"] --> A2["Act"] --> A3["Verify"]
|
||
end
|
||
subgraph P2["Phase2 正确性"]
|
||
direction LR
|
||
B1["Plan"] --> B2["Act"] --> B3["Gate 0LLM"] --> B4["Verify"] --> B5["Compose"]
|
||
end
|
||
subgraph P3["Phase3 运行时"]
|
||
direction LR
|
||
C1["单 Agent ReAct"] --> C2["Evidence"] --> C3["Semantic"] --> C4["Release"]
|
||
end
|
||
P1 -->|"引用不可核验"| P2
|
||
P2 -->|"外层重复 ReAct"| P3
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 可复用的原则清单(收口)
|
||
|
||
1. **先威胁模型,后角色图**
|
||
2. **能确定性检查的,不要交给模型装公正**
|
||
3. **模型可见数据必须有界(ACI)**
|
||
4. **完整事实、推理视图、长期审计三者分离**
|
||
5. **公开通道与内部草稿切断(Release)**
|
||
6. **Run 级身份贯穿:禁止“最新一条”**
|
||
7. **显式 Tool 决策优于隐式中间件魔法**(在可审计领域)
|
||
8. **多 Agent 的合法理由是权限/知识/失败域,不是给 ReAct 步骤起名**
|
||
9. **演进要有触发条件与评测,反自动炫技**
|
||
10. **重构保留语义,迁移装载位置,不把历史能力一笔勾销**
|
||
|
||
---
|
||
|
||
## 12. 建议复习路径(3 天)
|
||
|
||
### Day 1 巩固
|
||
|
||
- 读现行 4 篇架构:`current-mvp-architecture` / `agent-orchestration` / `harness-quality-gates` / `session-trace-lifecycle`
|
||
- 用第 8 节模板重写:ToolBoundary、EvidenceGuard、Release
|
||
- **默画 §15 图 A + 图 D**(当前主链、数据三层)
|
||
- 输出:一页「当前系统边界图」(手绘即可)
|
||
|
||
### Day 2 演进与辩护
|
||
|
||
- 读 `executor-evidence-pipeline-refactor` + ISS-014 摘要
|
||
- 练习:为 Phase 2 辩护 2 分钟,再为 Phase 3 重构辩护 2 分钟
|
||
- **默画 §15 图 B + 图 C**(五段流水线、职责迁移)
|
||
- 输出:10 行「旧角色 → 新组件」映射表(不看文档默写)
|
||
|
||
### Day 3 业界与迁移
|
||
|
||
- 用第 6.5 节表格,挑 2 个外部架构(如 LangGraph multi-agent、纯 ReAct SaaS 助手)做优缺点
|
||
- **默画 §15 图 E + 图 F**,并按 §15.7 组合练 3 个开场
|
||
- 做第 9.4 两道现场设计题
|
||
- 读 ISS-015:准备一段“未完成但可控”的诚实收尾
|
||
|
||
---
|
||
|
||
## 13. 附录:关键文件索引
|
||
|
||
| 主题 | 路径 |
|
||
|---|---|
|
||
| 当前架构入口 | `mvp/architecture/README.md` |
|
||
| 单 Agent 重构总因 | `mvp/issues/archived/ISS-014-single-react-agent-harness-aci-ptk-refactor.md` |
|
||
| 运行质量后续 | `mvp/issues/active/ISS-015-diagnosis-runtime-quality-and-reasoning-audit.md` |
|
||
| 旧五段编排 | `mvp/architecture/archive/2026-07-22-legacy/agent-orchestration.md` |
|
||
| 旧证据契约 | `mvp/architecture/archive/2026-07-22-legacy/executor-evidence-pipeline-refactor.md` |
|
||
| 旧演进路线 | `mvp/architecture/archive/2026-07-22-legacy/evolution-roadmap.md` |
|
||
| 早期愿景 | `mvp/architecture/archive/2026-07-05-legacy/agent-architecture.md` |
|
||
| 早期 MVP | `mvp/architecture/archive/2026-07-05-legacy/agent-architecture-mvp.md` |
|
||
|
||
---
|
||
|
||
## 14. 最后一道自测(不看文档回答)
|
||
|
||
1. 用一句话说清:Phase 2 与 Phase 3 各自解决的**不同类问题**是什么?
|
||
2. 为什么说 Gatekeeper 和 EvidenceGuard “神似”但“层不同”?
|
||
3. 若去掉 SemanticGuard,只留 EvidenceGuard,系统会怎样坏?
|
||
4. 若去掉 EvidenceGuard,只留 SemanticGuard,系统会怎样坏?
|
||
5. 举一个**不该**再拆多 Agent 的场景,和一个**该**拆的场景。
|
||
6. 你的系统与“LangChain + 向量库问答机器人”的本质三点差异?
|
||
7. ISS-015 若只准做一件事,你先做哪个?为什么?(停止策略 / Repair / Reasoning 治理 / Fallback 信息量)
|
||
|
||
能流畅答完 1–6,面试架构部分通常已经稳;第 7 题用来展示判断力而非背诵。
|
||
|
||
**加试:默画**
|
||
|
||
8. 60 秒画出「当前 Diagnosis 主链」(入口 → Agent → 三道门 → SSE)。
|
||
9. 90 秒画出「Phase2 五段」并标注哪一段是 0 LLM。
|
||
10. 60 秒画出「数据三层」并标出 Agent 能看见哪一层。
|
||
|
||
---
|
||
|
||
## 15. 白板默画清单(面试实战)
|
||
|
||
> 目标:不是画得好看,而是**边画边讲决策**。
|
||
> 建议每天抽 1 张限时默画,画完对照本节「必须出现的框」。
|
||
|
||
### 15.1 图 A · 60 秒:当前主链(必考)
|
||
|
||
```text
|
||
Client
|
||
│ POST /api/chat (SSE)
|
||
▼
|
||
UseCase ── Intent ──┬─ SYSTEM
|
||
├─ KNOWLEDGE
|
||
└─ DIAGNOSIS
|
||
│
|
||
▼
|
||
Diagnosis Agent ◄── projection
|
||
│ tool_call_id
|
||
▼
|
||
ToolBoundary ──► Redis canonical
|
||
│
|
||
▼
|
||
DiagnosisDraft
|
||
│
|
||
┌────────────┼────────────┐
|
||
▼ ▼ ▼
|
||
EvidenceGuard SemanticGuard Release
|
||
(0 LLM) (隔离LLM) (发布权)
|
||
│ │ │
|
||
└────────────┴────► SSE content / fallback
|
||
```
|
||
|
||
**边画边说的三句**
|
||
|
||
1. 唯一入口,意图分流,诊断才进 Agent。
|
||
2. Agent 只见投影,raw 只在 Harness。
|
||
3. Draft 默认不公开,Release 点头才出门。
|
||
|
||
**必须出现的框**:Intent、Agent、ToolBoundary/Redis、Evidence、Semantic、Release、SSE。
|
||
|
||
### 15.2 图 B · 90 秒:Phase2 五段 + 证据外键
|
||
|
||
```text
|
||
Planner → Executor ⇄ Tools
|
||
│
|
||
▼ executor_evidence_v2
|
||
Gatekeeper (0 LLM)
|
||
│ check id / path / excerpt
|
||
▼
|
||
Verifier (LLM)
|
||
▼
|
||
Composer → Answer
|
||
```
|
||
|
||
证据外键小图:
|
||
|
||
```text
|
||
claim ──binding──► invocation_id
|
||
├──► raw_path
|
||
└──► excerpt ⊆ raw_response
|
||
```
|
||
|
||
**边画边说**
|
||
|
||
> 这段解决的是正确性:先代码验引用,再模型验推导,最后控表达。
|
||
|
||
### 15.3 图 C · 60 秒:职责迁移(回答“是不是退步”)
|
||
|
||
```text
|
||
Planner ─────────────► Agent 内部
|
||
Executor loop ────────► Agent + ToolBoundary
|
||
Gatekeeper ───────────► EvidenceGuard
|
||
Verifier ─────────────► SemanticGuard
|
||
Composer ─────────────► Draft + Release
|
||
```
|
||
|
||
**金句**:角色变少,强制约束变多;语义保留,装载位置变了。
|
||
|
||
### 15.4 图 D · 60 秒:数据三层(ACI)
|
||
|
||
```text
|
||
Tool 执行
|
||
│
|
||
├──────────────► MySQL metadata(长期、无 raw)
|
||
│
|
||
▼
|
||
Redis canonical(完整 raw,短 TTL,Harness only)
|
||
│
|
||
▼ projector
|
||
agent_result 投影 ──────────► 只回 Agent
|
||
│
|
||
└─────────────────────► EvidenceGuard 也可读 canonical
|
||
```
|
||
|
||
**必须标**:Agent 禁止直连 Redis / 禁止见 raw。
|
||
|
||
### 15.5 图 E · 45 秒:业界定位两点对比
|
||
|
||
```text
|
||
纯 ReAct: Model ↔ Tools → 文本直接出门
|
||
|
||
本项目: Model ↔ Boundary → Draft
|
||
→ Guard → Guard → Release → 出门
|
||
+ budget/cancel/timeline
|
||
```
|
||
|
||
### 15.6 图 F · 45 秒:演进箭头(开场用)
|
||
|
||
```text
|
||
愿景 Multi-Agent
|
||
→ MVP P/E/V(能跑)
|
||
→ +Gate/Composer(能验)
|
||
→ 单 Agent + Harness(能控)
|
||
→ ISS-015(治运行)
|
||
```
|
||
|
||
### 15.7 现场组合策略
|
||
|
||
| 面试官问题类型 | 先画哪张 | 再补哪张 |
|
||
|---|---|---|
|
||
| 介绍项目 | F 演进 | A 当前主链 |
|
||
| 如何防幻觉 | B 或 A 的 Guard | D 数据三层 |
|
||
| 为什么重构 | C 迁移 | B→A 对比 |
|
||
| 和 LangGraph/多 Agent 比 | E 定位 | C 合法拆分动机 |
|
||
| 数据怎么存 / 怎么审计 | D 三层 | Trace session/run 树 |
|
||
|
||
### 15.8 默画评分(自评)
|
||
|
||
| 分数 | 标准 |
|
||
|---|---|
|
||
| 5 | 限时内画完 + 边讲决策 + 主动说取舍 |
|
||
| 4 | 画完且框齐全,讲解连贯 |
|
||
| 3 | 框基本全,但讲成组件清单 |
|
||
| 2 | 漏 Release / 数据分层 / 0LLM 门禁 |
|
||
| 1 | 只画了 Model↔Tools |
|
||
|
||
**红线(扣分项)**
|
||
|
||
- 把 SemanticGuard 画成带 Tool 的第二 Agent
|
||
- 让 raw_response 直接回到 Agent
|
||
- Draft 不经 Release 就连到用户
|
||
- 说“我们简化成单 Agent 所以不做验证了”
|