From de5a5b09d931893f9c124f0fdef801cc78964386 Mon Sep 17 00:00:00 2001 From: zhuyongxin Date: Fri, 24 Jul 2026 18:14:49 +0800 Subject: [PATCH] docs(interview): refresh materials for single-agent harness narrative Archive pre-refactor interview notes and add current deep-dives on architecture evolution, issue-derived stories, and evidence gates. --- interview/README.md | 88 +- interview/architecture-evolution-deep-dive.md | 1370 +++++++++++++++++ interview/archive/2026-07-24-legacy/README.md | 66 + .../2026-07-24-legacy/_ARCHIVE_NOTE.md | 36 + .../acceptance-checklist.md | 0 .../aiops-lightweight-verifier.md | 0 .../aiops-query-augmentation.md | 0 .../2026-07-24-legacy}/architecture.md | 0 .../2026-07-24-legacy}/demo-script.md | 0 .../2026-07-24-legacy}/design-tradeoffs.md | 0 .../rag-breadcrumb-embedding-acceptance.md | 0 .../2026-07-24-legacy}/rag-refactor-story.md | 0 .../rag-retrieval-quality-report.md | 0 .../rag-vectorstore-interview-notes.md | 0 .../rag-vectorstore-live-acceptance.md | 0 .../2026-07-24-legacy}/story-cases.md | 0 interview/issues-interview-stories.md | 380 +++++ .../topic-evidence-attribution-and-gates.md | 739 +++++++++ 18 files changed, 2622 insertions(+), 57 deletions(-) create mode 100644 interview/architecture-evolution-deep-dive.md create mode 100644 interview/archive/2026-07-24-legacy/README.md create mode 100644 interview/archive/2026-07-24-legacy/_ARCHIVE_NOTE.md rename interview/{ => archive/2026-07-24-legacy}/acceptance-checklist.md (100%) rename interview/{ => archive/2026-07-24-legacy}/aiops-lightweight-verifier.md (100%) rename interview/{ => archive/2026-07-24-legacy}/aiops-query-augmentation.md (100%) rename interview/{ => archive/2026-07-24-legacy}/architecture.md (100%) rename interview/{ => archive/2026-07-24-legacy}/demo-script.md (100%) rename interview/{ => archive/2026-07-24-legacy}/design-tradeoffs.md (100%) rename interview/{ => archive/2026-07-24-legacy}/rag-breadcrumb-embedding-acceptance.md (100%) rename interview/{ => archive/2026-07-24-legacy}/rag-refactor-story.md (100%) rename interview/{ => archive/2026-07-24-legacy}/rag-retrieval-quality-report.md (100%) rename interview/{ => archive/2026-07-24-legacy}/rag-vectorstore-interview-notes.md (100%) rename interview/{ => archive/2026-07-24-legacy}/rag-vectorstore-live-acceptance.md (100%) rename interview/{ => archive/2026-07-24-legacy}/story-cases.md (100%) create mode 100644 interview/issues-interview-stories.md create mode 100644 interview/topic-evidence-attribution-and-gates.md diff --git a/interview/README.md b/interview/README.md index c960c70..7704a4e 100644 --- a/interview/README.md +++ b/interview/README.md @@ -1,66 +1,40 @@ -# SuperBizAgent 面试资料包 +# SuperBizAgent 面试资料 + +**更新日期**:2026-07-24 +**当前主叙事**:单 Diagnosis ReAct Agent + 确定性 Harness(ISS-014 后) + +## 当前入口 + +| 文档 | 用途 | +|---|---| +| [architecture-evolution-deep-dive.md](architecture-evolution-deep-dive.md) | **主材料**:架构演进深读(为什么设计 / 问题 / 重构 / 业界对比 / 图与白板) | +| [issues-interview-stories.md](issues-interview-stories.md) | **故事材料**:从已解决 Issues 提炼的可讲案例(STAR / 追问 / 挂载演进) | +| [topic-evidence-attribution-and-gates.md](topic-evidence-attribution-and-gates.md) | **主题深读**:证据归因幻觉 + 质量门禁(质量辨识度主故事) | + +配套现行架构事实(非面试话术): + +| 文档 | 用途 | +|---|---| +| [mvp/architecture/README.md](../mvp/architecture/README.md) | 当前架构文档入口 | +| [mvp/architecture/current-mvp-architecture.md](../mvp/architecture/current-mvp-architecture.md) | 分层、主链、API、安全边界 | +| [mvp/demo/README.md](../mvp/demo/README.md) | Demo 运行与输出 | +| [mvp/issues/active/ISS-015-diagnosis-runtime-quality-and-reasoning-audit.md](../mvp/issues/active/ISS-015-diagnosis-runtime-quality-and-reasoning-audit.md) | 架构冻结后的运行质量收敛 | ## 一句话定位 -SuperBizAgent 是一个面向企业故障诊断场景的 Agent 工程项目。它把用户问题或 AIOps 告警转换成可追踪的 Agent 执行链路,并把工具证据、模型步骤、最终答案、自评估和用户反馈统一沉淀到诊断 Trace 中。 +SuperBizAgent 是面向故障诊断的可追踪 Agent 系统:业务侧一个 Diagnosis Agent 负责推理与写 Draft;Harness 负责预算、工具边界、证据验真、语义审查与安全发布。每次执行用 `sessionId + runId` 回放统一 Timeline。 -## 面试重点 +## 建议使用方式 -- **Agent 编排**:Chat 复杂问题走 `Planner -> Executor -> Verifier`;AIOps 告警入口走 `Supervisor -> Planner / Executor`。 -- **工具证据链**:知识库、日志、指标、Prometheus 告警都通过显式工具调用进入链路,并记录到 `tool_invocation`。 -- **可追踪诊断**:一次诊断对应一个 `sessionId`,可通过 `GET /api/diagnosis/{sessionId}/trace` 回放。 -- **质量门禁**:Chat Verifier 校验 groundedness;AIOps 规则评估检查报告完整性、payload 聚焦和证据工具覆盖。 -- **RAG 工程化**:`lookup_knowledge` 是显式 Agent Tool,底层通过 Spring AI VectorStore 主路径 + Milvus SDK fallback。 -- **反馈闭环**:用户反馈 `useful` 会沉淀 `case_library`,`not_useful` 保留 bad case 信号。 +1. 先读深读文档 §0–§6 + §10,建立演进骨架。 +2. 按 §15 默画白板图 A/C/D(当前主链、职责迁移、数据三层)。 +3. 需要事实核对时回到 `mvp/architecture/*`,不要用归档面试稿当现行口径。 +4. 未完成项用 ISS-015 收尾,体现判断力而非完美叙事。 -## 推荐阅读顺序 +## 归档 -1. `mvp/architecture/interview-one-pager.md`:一页式架构图和 2-5 分钟讲解。 -2. `mvp/demo/ten-minute-interview-demo.md`:10 分钟现场演示脚本。 -3. `interview/story-cases.md`:可复用的面试故事案例。 -4. `interview/architecture.md`:面试版系统架构。 -5. `interview/design-tradeoffs.md`:关键设计取舍。 -6. `interview/demo-script.md`:更细的命令式演示脚本。 -7. `interview/acceptance-checklist.md`:面试前验收清单。 -8. RAG 专题文档:`rag-refactor-story.md`、`rag-vectorstore-interview-notes.md`、`rag-retrieval-quality-report.md`。 +2026-07-24 之前的面试资料(多角色编排、双入口、旧 RAG/AIOps 讲解等)已移至: -## 核心演示链路 - -### Chat 诊断 - -```text -POST /api/chat --> ChatService --> Planner -> Executor -> Verifier --> lookup_knowledge / query_logs / query_metrics --> diagnosis_session + agent_step + tool_invocation --> GET /api/diagnosis/{sessionId}/trace --> POST /api/feedback -``` - -### AIOps 告警诊断 - -```text -POST /api/ai_ops --> AiOpsService --> PAYLOAD_TARGETED / AUTO_DISCOVERY --> ai_ops_supervisor --> planner_agent / executor_agent --> queryPrometheusAlerts + logs + metrics + lookup_knowledge --> alert report --> aiops_rule_evaluation --> GET /api/diagnosis/{sessionId}/trace -``` - -## 当前完成度 - -- Chat 诊断链路:可运行、可追踪、有 Verifier。 -- AIOps 告警链路:可运行、可追踪、支持 payload scope control。 -- RAG 检索链路:Spring AI VectorStore 主路径、Milvus SDK fallback、L0 hint、检索评测 baseline。 -- Trace API:统一返回 session、agent steps、tool invocations 和 summary。 -- Demo 材料:`mvp/demo/README.md`、`mvp/demo/ten-minute-interview-demo.md`。 - -## 主叙事 - -这个项目不是简单调用大模型,而是在做一个可审计、可验证、可回归的 Agent 诊断系统。模型可以规划和推理,但每一步工具证据、最终结论、Verifier 结果和用户反馈都能被 Trace API 回放。面试时重点展示“从问题到证据到答案到验证再到反馈”的闭环。 +[archive/2026-07-24-legacy/](archive/2026-07-24-legacy/) +仅用于历史追溯,不代表当前 runtime、API 或验收口径。说明见同目录 `_ARCHIVE_NOTE.md`。 diff --git a/interview/architecture-evolution-deep-dive.md b/interview/architecture-evolution-deep-dive.md new file mode 100644 index 0000000..5b5fbaa --- /dev/null +++ b/interview/architecture-evolution-deep-dive.md @@ -0,0 +1,1370 @@ +# 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 愿景
医院会诊 Multi-Agent"] + P1["Phase 1 MVP
Planner → Executor → Verifier"] + P2["Phase 2 证据工程化
+ Gatekeeper + Composer"] + P3["Phase 3 重构 ★当前
单 ReAct Agent + Harness"] + P4["Phase 4 收敛
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
院长:谁来干 / 何时停"] + Sup --> Pl["Planner
分诊: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
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
plan / skill"] + EX["Executor
只产微观事实"] + GK["Gatekeeper
0 LLM 引用验真"] + VF["Verifier
能否推出 claim"] + CM["Composer
只表达允许内容"] + 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
+ 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
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
named SSE"] + Chat --> App["ChatApplicationUseCase"] + App --> Router{"Intent Router"} + + Router --> Sys["SYSTEM_CHAT
无 Tool"] + Router --> Know["KNOWLEDGE_QUERY
单次 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
0 LLM"] + EG --> SG["SemanticGuard
隔离单轮"] + 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
Harness only · TTL · 完整"] + Canon --> Proj["ToolResultProjector"] + Proj --> AgentView["agent_result 有界投影"] + AgentView --> Agent["Diagnosis Agent 继续推理"] + Canon --> EG["EvidenceGuard 验真"] + AgentView --> EG + ToolExec --> Meta["MySQL tool_invocation
metadata-only 长期审计"] + + Agent -.->|"禁止直连"| Canon + Agent -.->|"禁止见 raw"| Raw +``` + +```mermaid +flowchart TB + Q["同一 Tool 调用,三份不同视图"] + Q --> C["① canonical raw
验真用 · 短 TTL · Harness only"] + Q --> P["② projection
推理用 · 有界 · 回 Agent"] + Q --> M["③ metadata audit
长期用 · MySQL · 无正文 raw"] +``` + +这直接回应 Phase 2 的上下文膨胀: +**验真需要完整事实,推理只需要有界观察,审计需要长期元数据——三者不是同一份 JSON。** + +#### D. EvidenceGuard vs SemanticGuard 为什么拆开 + +| | EvidenceGuard | SemanticGuard | +|---|---|---| +| 要不要模型 | 否 | 是(隔离单轮) | +| 问什么 | 引用是否真实、是否属于本 Run、结构是否合法 | 整份报告是否被证据支持、是否越界表达 | +| 失败含义 | 数据/契约问题 | 语义/推理问题 | +| 类比 | 类型检查 / 外键 | 代码 review / 逻辑审查 | + +```mermaid +flowchart TB + Draft["DiagnosisDraft"] --> EG{"EvidenceGuard
物理/结构/归属"} + EG -->|fail| FB1["不可发布
契约/引用问题"] + EG -->|verified snapshot| SG{"SemanticGuard
整份语义是否越证"} + SG -->|UNSUPPORTED| FB2["SAFE_FALLBACK"] + SG -->|SUPPORTED| RP["Release
公开 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
staging 制品"] --> Gate{"Release Policy"} + Gate -->|SUPPORTED| Pub["公开 SSE
production"] + Gate -->|UNSUPPORTED / evidence fail| Safe["SAFE_FALLBACK
有界说明"] + 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
需审批"] + R3["财务退款 Agent
强权限"] + end + + Wrong -.->|"本项目 Phase2 偏这类"| X["合并回单 Agent"] + Right -.->|"才值得 Multi-Agent"| Y["保持拆分"] +``` + +**3)和“上 LangGraph 就企业级”不一样** + +> Graph 解决的是状态与边;企业级还依赖:预算、取消、发布、数据分层、评测、审计隔离。 +> 没有这些,Graph 只是更复杂的 if-else。 + +```mermaid +flowchart TB + subgraph Axes["横轴:编排复杂度 →  纵轴:控制面完整度 ↑"] + direction TB + Q2["② 目标区
编排克制 + 控制面强
★ 本项目当前"] + Q1["① 重 Graph 且有护栏
企业工作流 + 审批/预算"] + Q3["③ Demo 常见区
纯 ReAct · 控制面弱"] + Q4["④ 重编排轻护栏
裸 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
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
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
P→E→V"] --> P2["Phase2
+GK +Composer"] + P2 --> P3["Phase3
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 所以不做验证了” diff --git a/interview/archive/2026-07-24-legacy/README.md b/interview/archive/2026-07-24-legacy/README.md new file mode 100644 index 0000000..c960c70 --- /dev/null +++ b/interview/archive/2026-07-24-legacy/README.md @@ -0,0 +1,66 @@ +# SuperBizAgent 面试资料包 + +## 一句话定位 + +SuperBizAgent 是一个面向企业故障诊断场景的 Agent 工程项目。它把用户问题或 AIOps 告警转换成可追踪的 Agent 执行链路,并把工具证据、模型步骤、最终答案、自评估和用户反馈统一沉淀到诊断 Trace 中。 + +## 面试重点 + +- **Agent 编排**:Chat 复杂问题走 `Planner -> Executor -> Verifier`;AIOps 告警入口走 `Supervisor -> Planner / Executor`。 +- **工具证据链**:知识库、日志、指标、Prometheus 告警都通过显式工具调用进入链路,并记录到 `tool_invocation`。 +- **可追踪诊断**:一次诊断对应一个 `sessionId`,可通过 `GET /api/diagnosis/{sessionId}/trace` 回放。 +- **质量门禁**:Chat Verifier 校验 groundedness;AIOps 规则评估检查报告完整性、payload 聚焦和证据工具覆盖。 +- **RAG 工程化**:`lookup_knowledge` 是显式 Agent Tool,底层通过 Spring AI VectorStore 主路径 + Milvus SDK fallback。 +- **反馈闭环**:用户反馈 `useful` 会沉淀 `case_library`,`not_useful` 保留 bad case 信号。 + +## 推荐阅读顺序 + +1. `mvp/architecture/interview-one-pager.md`:一页式架构图和 2-5 分钟讲解。 +2. `mvp/demo/ten-minute-interview-demo.md`:10 分钟现场演示脚本。 +3. `interview/story-cases.md`:可复用的面试故事案例。 +4. `interview/architecture.md`:面试版系统架构。 +5. `interview/design-tradeoffs.md`:关键设计取舍。 +6. `interview/demo-script.md`:更细的命令式演示脚本。 +7. `interview/acceptance-checklist.md`:面试前验收清单。 +8. RAG 专题文档:`rag-refactor-story.md`、`rag-vectorstore-interview-notes.md`、`rag-retrieval-quality-report.md`。 + +## 核心演示链路 + +### Chat 诊断 + +```text +POST /api/chat +-> ChatService +-> Planner -> Executor -> Verifier +-> lookup_knowledge / query_logs / query_metrics +-> diagnosis_session + agent_step + tool_invocation +-> GET /api/diagnosis/{sessionId}/trace +-> POST /api/feedback +``` + +### AIOps 告警诊断 + +```text +POST /api/ai_ops +-> AiOpsService +-> PAYLOAD_TARGETED / AUTO_DISCOVERY +-> ai_ops_supervisor +-> planner_agent / executor_agent +-> queryPrometheusAlerts + logs + metrics + lookup_knowledge +-> alert report +-> aiops_rule_evaluation +-> GET /api/diagnosis/{sessionId}/trace +``` + +## 当前完成度 + +- Chat 诊断链路:可运行、可追踪、有 Verifier。 +- AIOps 告警链路:可运行、可追踪、支持 payload scope control。 +- RAG 检索链路:Spring AI VectorStore 主路径、Milvus SDK fallback、L0 hint、检索评测 baseline。 +- Trace API:统一返回 session、agent steps、tool invocations 和 summary。 +- Demo 材料:`mvp/demo/README.md`、`mvp/demo/ten-minute-interview-demo.md`。 + +## 主叙事 + +这个项目不是简单调用大模型,而是在做一个可审计、可验证、可回归的 Agent 诊断系统。模型可以规划和推理,但每一步工具证据、最终结论、Verifier 结果和用户反馈都能被 Trace API 回放。面试时重点展示“从问题到证据到答案到验证再到反馈”的闭环。 + diff --git a/interview/archive/2026-07-24-legacy/_ARCHIVE_NOTE.md b/interview/archive/2026-07-24-legacy/_ARCHIVE_NOTE.md new file mode 100644 index 0000000..6a56f69 --- /dev/null +++ b/interview/archive/2026-07-24-legacy/_ARCHIVE_NOTE.md @@ -0,0 +1,36 @@ +# Archive Note + +**归档日期**:2026-07-24 +**状态**:历史面试材料,不代表当前 runtime / 架构口径 + +## 为何归档 + +本目录保存切换到「单 Diagnosis Agent + Harness」之前整理的面试资料包,内容仍以: + +- Chat:`Planner -> Executor -> Verifier`(及后续五段 Gatekeeper/Composer) +- AIOps 独立入口与规则评估 +- 旧 Trace / Demo 叙事 + +为主。现行可运行架构见: + +- `mvp/architecture/` +- `interview/architecture-evolution-deep-dive.md`(当前面试深读主文档) + +## 归档文件 + +| 文件 | 原用途 | +|---|---| +| `README.md` | 旧面试资料包入口 | +| `architecture.md` | 旧面试版系统架构 | +| `design-tradeoffs.md` | 旧设计取舍 | +| `demo-script.md` | 旧命令式演示脚本 | +| `acceptance-checklist.md` | 旧面试前验收清单 | +| `story-cases.md` | 旧故事案例 | +| `rag-*.md` | 旧 RAG 专题与验收笔记 | +| `aiops-*.md` | 旧 AIOps 讲解材料 | + +## 使用边界 + +- 可作历史决策与旧 Demo 话术追溯。 +- 不得当作当前 API、编排或验收标准。 +- 若引用其中内容,须同时说明归档日期与现行替代文档。 diff --git a/interview/acceptance-checklist.md b/interview/archive/2026-07-24-legacy/acceptance-checklist.md similarity index 100% rename from interview/acceptance-checklist.md rename to interview/archive/2026-07-24-legacy/acceptance-checklist.md diff --git a/interview/aiops-lightweight-verifier.md b/interview/archive/2026-07-24-legacy/aiops-lightweight-verifier.md similarity index 100% rename from interview/aiops-lightweight-verifier.md rename to interview/archive/2026-07-24-legacy/aiops-lightweight-verifier.md diff --git a/interview/aiops-query-augmentation.md b/interview/archive/2026-07-24-legacy/aiops-query-augmentation.md similarity index 100% rename from interview/aiops-query-augmentation.md rename to interview/archive/2026-07-24-legacy/aiops-query-augmentation.md diff --git a/interview/architecture.md b/interview/archive/2026-07-24-legacy/architecture.md similarity index 100% rename from interview/architecture.md rename to interview/archive/2026-07-24-legacy/architecture.md diff --git a/interview/demo-script.md b/interview/archive/2026-07-24-legacy/demo-script.md similarity index 100% rename from interview/demo-script.md rename to interview/archive/2026-07-24-legacy/demo-script.md diff --git a/interview/design-tradeoffs.md b/interview/archive/2026-07-24-legacy/design-tradeoffs.md similarity index 100% rename from interview/design-tradeoffs.md rename to interview/archive/2026-07-24-legacy/design-tradeoffs.md diff --git a/interview/rag-breadcrumb-embedding-acceptance.md b/interview/archive/2026-07-24-legacy/rag-breadcrumb-embedding-acceptance.md similarity index 100% rename from interview/rag-breadcrumb-embedding-acceptance.md rename to interview/archive/2026-07-24-legacy/rag-breadcrumb-embedding-acceptance.md diff --git a/interview/rag-refactor-story.md b/interview/archive/2026-07-24-legacy/rag-refactor-story.md similarity index 100% rename from interview/rag-refactor-story.md rename to interview/archive/2026-07-24-legacy/rag-refactor-story.md diff --git a/interview/rag-retrieval-quality-report.md b/interview/archive/2026-07-24-legacy/rag-retrieval-quality-report.md similarity index 100% rename from interview/rag-retrieval-quality-report.md rename to interview/archive/2026-07-24-legacy/rag-retrieval-quality-report.md diff --git a/interview/rag-vectorstore-interview-notes.md b/interview/archive/2026-07-24-legacy/rag-vectorstore-interview-notes.md similarity index 100% rename from interview/rag-vectorstore-interview-notes.md rename to interview/archive/2026-07-24-legacy/rag-vectorstore-interview-notes.md diff --git a/interview/rag-vectorstore-live-acceptance.md b/interview/archive/2026-07-24-legacy/rag-vectorstore-live-acceptance.md similarity index 100% rename from interview/rag-vectorstore-live-acceptance.md rename to interview/archive/2026-07-24-legacy/rag-vectorstore-live-acceptance.md diff --git a/interview/story-cases.md b/interview/archive/2026-07-24-legacy/story-cases.md similarity index 100% rename from interview/story-cases.md rename to interview/archive/2026-07-24-legacy/story-cases.md diff --git a/interview/issues-interview-stories.md b/interview/issues-interview-stories.md new file mode 100644 index 0000000..0b3bc04 --- /dev/null +++ b/interview/issues-interview-stories.md @@ -0,0 +1,380 @@ +# 从 Issues 提炼的面试故事 + +**更新日期**:2026-07-24 +**用途**:从 `mvp/issues` 已解决问题中,筛出可讲、值得讲、能举一反三的案例 +**配套**:[architecture-evolution-deep-dive.md](architecture-evolution-deep-dive.md)(讲演进骨架);本文讲**具体踩坑与决策** + +--- + +## 0. 怎么用 + +| 场景 | 用法 | +|---|---| +| 行为面试 / 项目深挖 | 选 2–3 个 ★★★ 故事,用 STAR 讲 | +| 架构追问 | 把故事挂回演进阶段(Phase2 证据 / Phase3 重构 / 工程化) | +| 避免踩坑 | ★ 仅作补充,勿当主叙事;过时方案要说「后来被什么吸收」 | + +**总原则** + +> 面试官要的不是 Issue 编号,而是:**现象 → 根因分层 → 你选了什么杠杆 → 如何验证 → 后来边界怎么演进**。 + +--- + +## 1. 全景评分(先看这张表) + +| Issue / 主题 | 面试价值 | 最适合回答的问题类型 | 一句话钩子 | 注意 | +|---|:---:|---|---|---| +| **证据归因幻觉** + Gatekeeper 链路 | ★★★ | 防幻觉 / 质量门禁 | 「工具调了,结论仍是编的」 | 旧角色名要映射到现在 Guard | +| **ISS-014** 单 Agent + Harness | ★★★ | 架构重构 / 为什么简化 | 「不是砍验证,是换装载层」 | 主故事,深读文档已覆盖 | +| **ISS-008** 窄范围越界 | ★★★ | Agent 约束 / Prompt 不够 | 「只问 CPU,却去查全家桶」 | 好举一反三 | +| **ISS-009** 负向证据 | ★★★ | 证据建模 / no-hit | 「没查到也是证据」 | 区分「无问题」vs「无数据」 | +| **ISS-001→002→004→015** 重复检索族 | ★★★ | 迭代加深 / Prompt vs 硬约束 | 「去重了仍狂调 20 次」 | 讲演进链,别只讲一次补丁 | +| **ISS-010** session/run 隔离 | ★★★ | 可观测 / 多轮正确性 | 「同会话多轮 Trace 串台」 | 和 runId 真理源强绑定 | +| **ISS-012** Token/上下文膨胀 | ★★★ | 成本 / ACI / 上下文工程 | 「工具返回把上下文撑爆」 | 接到 projection 三层数据 | +| **ISS-006 + fixtures + baseline diff** | ★★ | 工程化 / 回归 | 「改 Prompt 怎么知道没退步」 | 体现测试思维 | +| **ISS-007** 摘要失真 → 自证循环 | ★★★ | 信息通路设计 | 「证据在,摘要丢了关键句」 | 可与归因幻觉合并讲 | +| **ISS-013** SSE / 入口解耦 | ★★ | 后端工程 / 协议边界 | 「假流式 + Controller 过重」 | 偏工程,Agent 味稍淡 | +| **ISS-005** 证据状态契约 | ★★ | 契约 / 失败语义 | 「failed/no_evidence/deduped 语义乱」 | 作 001/007 的基础设施铺垫 | +| **RAG 子问题集** | ★★ | RAG 专题 | L0 降级、显式 Tool、breadcrumb | 合成一条 RAG 故事,勿逐条念 | +| **ISS-003** 总 Review | ★ | 过程 | 问题发现清单 | 不宜单独讲 | +| **ISS-015**(进行中) | ★★ | 诚实收尾 / 判断力 | 「架构冻了,策略还在收」 | 讲未完成,勿假装已完美 | + +--- + +## 2. 推荐主故事包(面试只带这 5 个就够) + +### 故事包怎么组合(15 分钟项目介绍) + +```text +1) 开场架构(2 min) → 深读文档 / ISS-014 结论 +2) 质量核心(4 min) → 证据归因幻觉 + Gatekeeper/EvidenceGuard +3) 约束演进(3 min) → 重复检索 001→002→硬预算 / 窄范围 008 +4) 工程底座(3 min) → run 隔离 010 + eval harness 006 +5) 重构与未完(3 min) → ISS-014 为什么合并 + ISS-015 诚实项 +``` + +--- + +## 3. ★★★ 故事详解(可直接练口述) + +### 3.1 证据归因幻觉(最高辨识度) + +| 项 | 内容 | +|---|---| +| 来源 | `executor-evidence-attribution-hallucination` + ISS-007 + design-note 自证循环 | +| 完整深读 | [topic-evidence-attribution-and-gates.md](topic-evidence-attribution-and-gates.md) | +| 阶段 | Phase 2 正确性建设 | +| 现象 | 多次 E2E:工具已调 `lookup_knowledge/logs/metrics`,Verifier 仍大面积 `LOW_CONFID`;答案里出现 OOM、Full GC 次数等**工具返回里没有的「精确事实」** | +| 错误归因(你要主动否定) | 「是不是 Verifier 太严 / 只认 RAG?」——查 `evidence_refs` 后发现并非如此 | +| 真根因 | **Executor 证据归因幻觉**:把 runbook/历史模式/模型常识写进「当前已证实事实」,未区分 direct / reference / hypothesis / missing | +| 解法演进 | ① 结构化 claim + binding(invocation/path/excerpt)② **代码 Gatekeeper** 验引用 ③ Verifier 只判可推导 ④ Composer 控表达 → 后来迁到 EvidenceGuard + SemanticGuard + Release | +| 验证 | 固定 session 表(groundedness、no_evidence 计数);eval fixture;Trace 可指出「哪条 claim 无 binding」 | +| 现行映射 | Gatekeeper → **EvidenceGuard**;Verifier → **SemanticGuard**;最终出门 → **Release** | + +**STAR 口述(约 90 秒)** + +> 我们诊断链路经常 LOW_CONFID。第一反应像是验证器太狠,但拉 Trace 发现工具其实调用成功了。 +> 对比答案和 tool raw 后定位到:模型会把知识库里的「常见故障模式」写成「这次故障已观测事实」。 +> 所以我们把「有没有这句证据」从 LLM 判断里拆出来,做成代码级引用校验;模型只负责在已验真片段上做推导。 +> 这直接把问题从「提示词求稳」升级成「证据所有权与类型系统」。 +> 后来重构单 Agent 时,这层语义保留了,只是从流水线角色变成了 Harness 门禁。 + +**追问预备** + +- Q: 为什么不靠更强模型? + A: 分布上仍会混用常识与观测;确定性校验可回归、可解释。 +- Q: excerpt 子串匹配会不会太死? + A: 对防伪造必须偏严;表达层再允许归纳,但不允许无根引用。 +- Q: 和 RAG 引用角标有何不同? + A: 角标常是生成时装饰;我们校验的是**当次 Run 的 tool_call 所有权**。 + +**举一反三** + +- 客服:「政策规定 7 天」≠「本单已同意退款」 +- 代码 Agent:「README 说应有测试」≠「本 PR 已有测试」 + +--- + +### 3.2 窄范围查询越界(ISS-008) + +| 项 | 内容 | +|---|---| +| 现象 | 用户只要确认 `payment-service` 是否有 HighCPU 告警;Agent 却扩展到内存、日志、根因故事 | +| 根因 | ReAct 默认「有工具就多查」;Prompt 未区分 **observation 任务** vs **root-cause 任务**;claim 类型未收窄 | +| 解法 | 窄范围只允许 `observation` / `negative_observation`;禁止随手 root_cause;工具选择与输出 schema 双约束 | +| 验证 | narrow-highcpu 类 fixture:该 PASS 的 observation 不因「没讲根因」被打成失败 | +| 现行 | DiagnosisDraft 分析项仍强调证据绑定;范围控制在 Agent 指令 + Guard 语义审查 | + +**金句** + +> Agent 的能力上限往往不是「会不会查」,而是「知不知道何时停、查什么算完成」。 + +**举一反三** + +- SQL Agent:用户要 `SELECT count` 时禁止顺手 `UPDATE` +- 调查 Agent:「只要时间线」时禁止输出处置工单 + +--- + +### 3.3 负向证据(ISS-009) + +| 项 | 内容 | +|---|---| +| 现象 | 工具明确 no-hit 时,模型要么不说,要么说成「已排除该根因」,且引用对不上 | +| 根因 | 只建模「命中证据」,没有一等公民的 **no_evidence 路径**(如 `$.no_evidence`) | +| 解法 | `negative_observation` + 固定 raw_path/excerpt 契约;Gatekeeper 校验「无证据」也可以是合法引用 | +| 价值 | 排障里「查过没有」改变后验;也避免虚假排除 | + +**金句** + +> 在证据系统里,空结果若不可引用,模型就会用语言填补真空——那就是幻觉温床。 + +--- + +### 3.4 重复检索演进链(ISS-001 → 002 → 004 → 015) + +这是**最好的「迭代加深」故事**:同主题三次升级约束强度。 + +```text +ISS-001 同文档内容重复进上下文 + → session 文档去重 / Prompt「别重复」 + +ISS-002 去重后仍 lookup 20+ 次(换 query 刷同一域) + → 根因:约束只打在 Planner,Executor 不知情 + → Executor 注入 map + 每域一次等 Prompt 约束 + +ISS-004 Prompt 仍挡不住「再确认一次」 + → 设计域级水位 / 硬限制(后被架构变更吸收) + +ISS-014/015 约束归属变化 + → 不再靠 Executor 旁路状态打补丁 + → Harness 预算 + Agent 硬停止 + 重复 lookup 策略(015 进行中) +``` + +**面试怎么讲这条链** + +> 第一阶段我们以为是重复文档,做了内容去重。 +> 第二阶段发现模型换关键词继续刷,说明**去重粒度错了**,且约束注入点错了(只告诉了 Planner)。 +> 第三阶段承认 Prompt 约定不是安全边界,必须**预算/次数硬停止**。 +> 架构重构后,这些不再散落在 Tool 旁路,而进入统一 Harness 控制面。 +> 这说明我处理 Agent 问题的习惯是:先观测 → 分层根因 → 逐步把约束从「软」推到「硬」,并在架构变了以后迁移装载点,而不是叠补丁。 + +**对应业界概念**:Action masking / tool budget / circuit breaker;不是调参玄学。 + +--- + +### 3.5 Session / Run Trace 隔离(ISS-010) + +| 项 | 内容 | +|---|---| +| 现象 | 同 `sessionId` 多轮诊断时,步骤/工具/评价串台或「取最新一条」导致回放错乱 | +| 根因 | 缺少把**一次执行**定为真理源的 `runId`;查询与写入未全程 exact id | +| 解法 | `diagnosis_run`;step/invocation/trace 均挂 run;API 强制 `runId`;禁止 latest 语义 | +| 价值 | 评测、排障、面试 Demo 都依赖可复现回放 | + +**金句** + +> 可观测性若不能精确到一次 Run,就只是日志堆,不是诊断系统的记忆。 + +**举一反三** + +- 工作流引擎的 `workflowId` vs `runId` +- CI 的 pipeline vs job attempt + +--- + +### 3.6 Token 与上下文膨胀(ISS-012)→ ACI / 三层数据 + +| 项 | 内容 | +|---|---| +| 现象 | Executor 上下文暴涨;工具结果含 debug/rerank/大段重复;成本与截断不可控 | +| 根因 | Tool 返回**面向开发者**而非 Agent;完整 raw 与模型可见视图未分离 | +| 解法方向 | Token 可观测;硬预算;结果投影;证据引用带稳定 id(后由 ISS-014 的 Redis canonical + projector 落地) | +| 现行 | canonical / projection / durable audit 三层 | + +**金句** + +> 上下文工程首先是接口设计问题:Agent 的观察通道必须有界,验真通道才能完整。 + +--- + +### 3.7 单 Agent + Harness 重构(ISS-014) + +深读文档已写透,这里只留**Issue 视角的故事钩子**: + +| 项 | 内容 | +|---|---| +| 触发 | 多角色 = 外层重复 ReAct;JSON 接力;Token;失败语义组合爆炸 | +| 保留 | 物理验真 → 语义审查 → 发布 的正确性模型 | +| 迁移 | 角色流水线 → 执行边界(Harness) | +| 证据 | 阶段 E2E:成功诊断 ~8k tokens / 1 次 tool;Knowledge Query 独立路径修复 invalid schema | + +**和 3.1 的关系(必说清)** + +> 014 不是推翻 007/归因幻觉的成果,而是避免用「五个 LLM 角色」去实现本该由一个 ReAct + 一层确定性门禁完成的事。 + +--- + +### 3.8 评测 Harness(ISS-006 + fixtures + baseline diff) + +| 项 | 内容 | +|---|---| +| 动机 | 只有 Demo 无法判断改 Prompt/Tool 是否退步 | +| 做法 | 固定 case;expected tools/verdict/keywords;**确定性** trace 校验(非一上来 LLM-as-judge);baseline + diff | +| 价值 | 把 Agent 质量从「感觉」变成「回归」 | + +**金句** + +> 没有 baseline diff 的 Agent 迭代,只是在用生产用户当测试集。 + +**注意**:面试强调「先确定性检查,再考虑 LLM judge」,显得克制。 + +--- + +### 3.9 SSE 与入口解耦(ISS-013) + +| 项 | 内容 | +|---|---| +| 现象 | `/api/chat` 与 `/api/chat_stream` 双入口;stream 实为整答后假分片;Controller 编排过重 | +| 解法 | 唯一 `POST /api/chat` named SSE;UseCase 拥有业务;Controller 只协议;disconnect → cancel Run | +| 适合 | 问到 Spring/API 设计、背压、职责边界时 | + +--- + +## 4. ★★ 可合并讲的「专题束」 + +### 4.1 RAG 专题束(不要逐 Issue 报菜名) + +把 `mvp/issues/rag/*` 收成 **一条 2 分钟故事**: + +```text +问题簇: + L0 关键词当终局、breadcrumb 不进向量、切片丢层级、 + 无 packing/rerank、分数语义不清、Advisor 隐式注入 vs 显式 Tool + +收敛原则: + 1) 检索决策要对 Agent 可见 → lookup_knowledge 保持 Tool + 2) L0 降级为 hint,不替代语义召回 + 3) 向量主路径可演进(VectorStore)+ 过渡期 fallback + 4) 召回质量与「能否被引用验真」一起设计 +``` + +**面试官若只问 RAG**:用这条;若问 Agent 质量:退回 3.1。 + +### 4.2 证据契约束(ISS-005 + 007 + 结构化输出设计笔记) + +```text +统一 evidence 状态:supported / no_evidence / deduped / failed +摘要不可当唯一证据源 +Executor 产出可绑定结构,Gatekeeper 验,Verifier 判 +``` + +适合接在「你们怎么保证工具结果语义一致」类问题。 + +--- + +## 5. 不建议当主故事的 + +| 项 | 原因 | 若被问到怎么说 | +|---|---|---| +| ISS-003 总 Review | 清单型,缺单点冲突 | 「那是问题发现基线,具体落地看 005/006/014」 | +| ISS-004 原文方案细节 | 实现被 014/015 吸收,细节易过时 | 「方向是硬水位,装载点已迁到 Harness 预算/停止策略」 | +| 归因幻觉的旧 Prompt 补丁 alone | 不完整 | 必须接到 Gatekeeper/Guard | +| 未归档的「计划中」口吻 | 很多已 done | 统一用「已归档 / 被 014 吸收 / 015 进行中」三态 | + +--- + +## 6. 问题类型 → Issue 速查 + +| 面试官问… | 优先故事 | +|---|---| +| 怎么防幻觉? | 3.1 归因幻觉 + Guard 映射 | +| Prompt 够不够? | 3.4 重复检索链 + 3.2 窄范围 | +| 多 Agent 为什么又合并? | 3.7 ISS-014(挂 3.1 证明没砍质量) | +| 成本 / Token? | 3.6 + 数据三层 | +| 如何回归? | 3.8 eval | +| 如何调试一次错误诊断? | 3.5 run 隔离 + Timeline | +| 没找到证据怎么办? | 3.3 负向证据 + Release fallback | +| SSE / 接口设计? | 3.9 | +| RAG 怎么做的? | 4.1 专题束 | +| 还有什么没做完? | ISS-015:硬停止、Repair schema、reasoning 治理、信息化 fallback | + +--- + +## 7. 与架构演进的挂载图 + +```text +Phase1 能跑 + └─ 暴露:重复检索 001/002 + +Phase2 能验 + ├─ 证据状态 005 + ├─ 归因幻觉 + 007 自证循环 + ├─ 窄范围 008 / 负向证据 009 + ├─ eval 006 / baseline + └─ run 隔离 010 + +Phase2 负债 + └─ Token 012、入口 013、角色编排税 + +Phase3 能控 + └─ 014 单 Agent + Harness(吸收 004/012/013 与证据门禁语义) + +Phase4 治理中 + └─ 015 停止策略 / Repair / reasoning / fallback 信息量 +``` + +--- + +## 8. 建议你精炼的「个人贡献表述」模板 + +按真实参与度改主语,结构建议: + +```text +我负责/主导了 ___(问题)。 +通过 Trace 看到 ___(证据),排除了 ___(错误假设)。 +方案上选择 ___ 而不是 ___,因为 ___。 +用 ___(fixture/E2E/指标)验证。 +后续在 014 重构中,该能力迁移为 ___,我学到 ___。 +``` + +示例(归因幻觉): + +```text +我负责排查 Chat 诊断大面积 LOW_CONFID。 +通过对比 tool raw 与最终答案,确认是证据归因幻觉而非 Verifier 误杀。 +推动「结构化 claim + 代码 Gatekeeper + Verifier 只做推导」而不是继续堆 Prompt。 +用固定 E2E session 与 eval fixture 回归。 +014 重构后该语义保留为 EvidenceGuard/SemanticGuard/Release。 +``` + +--- + +## 9. 源文件索引 + +| 故事 | 路径 | +|---|---| +| 归因幻觉 | `mvp/issues/archived/executor-evidence-attribution-hallucination.md` | +| 自证/摘要 | `mvp/issues/archived/ISS-007-...` / `design-notes/executor-self-evidence-loop-design-note.md` | +| 窄范围 | `mvp/issues/archived/ISS-008-...` | +| 负向证据 | `mvp/issues/archived/ISS-009-...` | +| 重复检索 | `ISS-001` `ISS-002` `ISS-004` | +| Run 隔离 | `ISS-010` | +| Token | `ISS-012` | +| SSE | `ISS-013` | +| 重构 | `ISS-014-single-react-agent-harness-aci-ptk-refactor.md` | +| 评测 | `ISS-006` `expand-diagnosis-eval-fixtures` `diagnosis-eval-baseline-diff` | +| 进行中 | `mvp/issues/active/ISS-015-...` | +| RAG 簇 | `mvp/issues/rag/*` | + +--- + +## 10. 自测 + +1. 不看文档,讲清「工具调用成功为何仍 LOW_CONFID」的根因与门禁分层。 +2. 用 001→002→004→015 说明你如何升级约束强度。 +3. 画旧 Gatekeeper 到新 EvidenceGuard 的映射,并说明 014 保留了什么。 +4. 举一个负向证据防止的错误用户话术。 +5. 用一句话说明 eval harness 为什么先做确定性检查。 + +能答 1–3,项目深挖通常已够用;4–5 用于区分「做过功能」和「有质量体系」。 diff --git a/interview/topic-evidence-attribution-and-gates.md b/interview/topic-evidence-attribution-and-gates.md new file mode 100644 index 0000000..f7ec754 --- /dev/null +++ b/interview/topic-evidence-attribution-and-gates.md @@ -0,0 +1,739 @@ +# 主题深读:证据归因幻觉 + 现行质量门禁 + +**用途**:巩固知识 + 面试准备 + 举一反三 +**不是**:逐字讲稿、旧 Issue 复述、过时五段流水线说明书 +**材料日期**:2026-07-24 +**叙事原则**:**以现行设计为主讲;早期 Issue 只说明「问题从哪来」** +**主题定位**:质量辨识度主故事——「工具调了,结论为何仍不能直接给用户」 + +**现行依据(面试默认口径)** + +| 层级 | 路径 | +|---|---| +| 架构 | `mvp/architecture/current-mvp-architecture.md` | +| 编排 | `mvp/architecture/agent-orchestration.md` | +| 门禁 | `mvp/architecture/harness-quality-gates.md` | +| Draft 契约 | `.../harness/contract/DiagnosisDraft.java`、`AnalysisKind.java` | +| 物理验真 | `.../harness/guard/evidence/EvidenceGuard.java` | +| 语义审查 | `.../harness/guard/semantic/SemanticGuard.java`、`semantic-guard-prompt.md` | +| 发布 | `.../harness/release/DiagnosisReleaseUseCase.java`、`SafeFallbackFactory.java` | +| Agent 规则 | `src/main/resources/prompts/diagnosis-agent-prompt.md` | + +**历史依据(只作起源,不代表 runtime)** + +- `mvp/issues/archived/executor-evidence-attribution-hallucination.md`(2026-07-07,旧 Executor 链路) +- Phase2 Gatekeeper / `executor_evidence_v2` 归档文档 + +**配套** + +- 演进骨架 → [architecture-evolution-deep-dive.md](architecture-evolution-deep-dive.md) +- 故事索引 → [issues-interview-stories.md](issues-interview-stories.md) §3.1 + +--- + +## 0. 怎么用 / 怎么讲 + +| 目标 | 用法 | +|---|---| +| 巩固 | 先背现行三道门与 `DiagnosisDraft` 引用闭包,再看历史问题为何逼出这套设计 | +| 面试 | **先讲现在怎么拦,再补一句早期怎么发现**;禁止把主链路讲成 Planner→Executor→Verifier | +| 举一反三 | 用现行组件名迁移到客服/代码/合规场景 | + +**开场主线(先背这句,现行口径)** + +> 当前系统里,Diagnosis Agent 是唯一报告作者,它在 ReAct 里查只读工具并写出结构化 `DiagnosisDraft`。 +> 但 Draft **默认不能出门**:必须先过 **EvidenceGuard(0 LLM,验 tool_call 归属与投影)**,再过 **SemanticGuard(隔离单轮,判是否越证)**,最后由 **Release Policy** 决定公开报告还是 SAFE_FALLBACK。 +> 这套门禁要防的核心失败,是早期线上已经见过的 **证据归因幻觉**:有工具调用,却把 runbook/常识写成「本 Run 已证实事实」。 + +**禁止的过时口径** + +| 不要说 | 要说 | +|---|---| +| 我们主链路是 Planner→Executor→Gatekeeper→Verifier→Composer | 单 Diagnosis Agent + Harness 门禁 | +| Gatekeeper 验 `source_invocation_id + raw_path + excerpt` | EvidenceGuard 验 `tool_call_id` + 当前 Run canonical/projection | +| Verifier 输出 LOW_CONFID/PASS | SemanticGuard 输出 `SUPPORTED` / `UNSUPPORTED` | +| 工具有 metrics/Prometheus | 现行诊断 Tool:`lookup_knowledge` / `query_logs` / `query_mysql` | +| 引用主键是 DB `tool_invocation.id` | 框架 `tool_call_id`;完整调用在 Redis canonical | + +**四轴(现行)** + +1. **谁写报告**:仅 Diagnosis Agent +2. **谁保证引用真**:EvidenceGuard + Redis canonical(Harness only) +3. **谁保证语义不越界**:SemanticGuard(无 Tool、无记忆) +4. **谁决定用户看见什么**:Release Policy(Draft ≠ 公开 SSE) + +**图目录** + +| 图 | 位置 | 白板优先级 | +|---|---|---| +| 现行主链(质量视角) | §1 | ★★★ | +| DiagnosisDraft 引用闭包 | §2 | ★★★ | +| EvidenceGuard 校验步骤 | §3 | ★★★ | +| AnalysisKind × EvidenceStatus | §3.3 | ★★ | +| SemanticGuard 输入冻结 | §4 | ★★★ | +| Release / Repair / Fallback | §5 | ★★★ | +| 数据三层如何服务验真 | §6 | ★★ | +| 历史问题 → 现行映射(30 秒) | §8 | ★★ | +| 白板速画 | §13 | ★★★ | + +--- + +## 1. 现行设计:质量门禁长什么样 + +### 1.1 在系统中的位置 + +```text +POST /api/chat (SSE) + → ChatApplicationUseCase + → Intent Router → DIAGNOSIS + → Diagnosis ReAct Agent + 只读 Tool × 3,观察的是 projection + 产出 DiagnosisDraft + → DiagnosisReleaseUseCase + EvidenceGuard →(可选 EvidenceRepair 一次)→ SemanticGuard → Release + → 公开 content | SAFE_FALLBACK | failure +``` + +```mermaid +flowchart TB + Q["query + safe previous_turn"] --> A["Diagnosis Agent
唯一报告作者 · ReAct"] + A <--> TB["ToolBoundary"] + TB --> Redis["Redis canonical
Harness only"] + TB --> Proj["bounded agent_result"] + Proj --> A + A --> Draft["DiagnosisDraft
内部制品"] + Draft --> RU["DiagnosisReleaseUseCase"] + RU --> EG["EvidenceGuard · 0 LLM"] + EG -->|invalid| RP["EvidenceRepair 最多一次"] + RP --> EG + EG -->|valid snapshot| SG["SemanticGuard · 隔离单轮"] + SG -->|SUPPORTED| Out["Release SUCCESS
公开 typed report"] + SG -->|UNSUPPORTED / 不可用| FB["SAFE_FALLBACK"] + EG -->|仍 invalid| FB +``` + +**面试一句话** + +> Agent 负责「尽量基于证据写对」;Harness 负责「写错了也不能当成功答案发出去」。 + +### 1.2 职责切分(现行,必背) + +| 组件 | 做 | 不做 | +|---|---|---| +| **Diagnosis Agent** | 规划、调 Tool、写完整 Draft、证据不足时写 limitations | HTTP/SSE、预算、物理验真、语义终审、发布 | +| **ToolBoundary** | schema/只读/预算、写 canonical、projector、只回有界观察 | 业务推理 | +| **EvidenceGuard** | Draft 结构、analysis 闭包、`tool_call_id` 属本 Run、READY/可引用、kind↔status、投影可解析 | 调模型、改报告语义 | +| **EvidenceRepair** | 在证据失败时尝试一次结构化修复 | 无限重试、绕过验真 | +| **SemanticGuard** | 在 verified snapshot 上判断整份报告是否被支持 | Tool、记忆、Redis、改写报告、部分放行 | +| **Release** | SUPPORTED 才公开 Draft;否则固定 fallback/failure | 把未验证 Draft 流式出去 | + +对应代码入口:`DiagnosisReleaseUseCase.execute(run, query, draft)`。 + +### 1.3 和「纯 ReAct Demo」的差(质量视角) + +```text +纯 ReAct: Model ↔ Tools → 文本直接给用户 + +现行: Model ↔ ToolBoundary/projection → DiagnosisDraft + → EvidenceGuard → SemanticGuard → Release → SSE + + run 预算/取消 + Timeline(EVIDENCE/SEMANTIC/RELEASE 事件) +``` + +--- + +## 2. 现行契约:`DiagnosisDraft` 如何逼归因诚实 + +### 2.1 结构(代码事实) + +```text +DiagnosisDraft + conclusion? + text + based_on_analysis_ids[] ← 必须指向本 Draft 内 analysis_id + analysis[] + analysis_id ← 唯一 + kind: NORMAL | NEGATIVE_OBSERVATION + text + tool_call_ids[] ← 至少一个;必须是本 Run 真实 id + action_plan[] + action + based_on_analysis_ids[] + requires_human_confirmation + recommendations[] + text + based_on_analysis_ids[] + limitations ← 必填 scope(EvidenceGuard 校验) + scope + missing_info[] +``` + +```mermaid +flowchart TB + C["conclusion / actions / recommendations"] -->|"based_on_analysis_ids"| A["analysis_id"] + A -->|"tool_call_ids"| T["本 Run tool_call_id"] + T --> Canon["Redis canonical
runId + toolCallId"] + Canon --> Status["evidence_status
FOUND / NO_EVIDENCE"] + A --> Kind["kind NORMAL / NEGATIVE"] + Kind -.->|"must match"| Status +``` + +**设计意图(对着归因幻觉)** + +| 约束 | 防什么 | +|---|---| +| 每条 analysis 必须带 `tool_call_ids` | 「凭空结论」「常识当观测」 | +| conclusion 不直接绑 tool,只绑 analysis | 结论必须落在已声明的分析链上,形成闭包 | +| `limitations` 强制存在 | 证据不足时不能装成完整结案 | +| `kind` 二分 | 负向观察与正向命中不能混用同一类证据状态 | + +### 2.2 Agent Prompt 里的硬规则(现行) + +`diagnosis-agent-prompt.md` 关键口径(面试可直接引用思想,不必背原文): + +1. **唯一报告作者**;内部规划,不对外输出 CoT。 +2. **PreviousTurn 不是本 Run 证据**,不能引用其 tool_call_id。 +3. 只有 `evidence_status=EVIDENCE_FOUND|NO_EVIDENCE` 且带真实 `tool_call_id` 的观察才能当证据。 +4. **NORMAL** 只能引 FOUND;**NEGATIVE_OBSERVATION** 只能引 NO_EVIDENCE。 +5. **NO_EVIDENCE ≠ 系统健康 / 已排除根因**。 +6. Tool **ERROR 不是证据**,禁止引用。 +7. 证据不足:`conclusion=null`,写 scope/missing_info,**禁止编根因**。 +8. 不暴露 raw、凭据、内部错误、hidden reasoning。 + +**金句** + +> Prompt 负责教 Agent「怎么写才诚实」;EvidenceGuard 负责「写得不诚实就过不了」。两者缺一不可,但**安全边界在代码**。 + +### 2.3 和早期「分区文案」的关系(30 秒) + +早期 Issue 要求 Executor 输出「已证实 / 推测 / 缺口 / 动作」分区。 +现行不是同一套 JSON 字段名,但**语义被结构吸收了**: + +| 早期分区意图 | 现行落点 | +|---|---| +| 已证实事实 | `analysis`(NORMAL + FOUND) | +| 负向观察 | `analysis`(NEGATIVE_OBSERVATION + NO_EVIDENCE) | +| 证据缺口 | `limitations.missing_info` + 可空 `conclusion` | +| 建议动作 | `action_plan` / `recommendations`(必须 based_on analysis) | +| 禁止常识当事实 | Guard 不认无 tool_call 的 analysis;Semantic 审越证 | + +--- + +## 3. EvidenceGuard:现行物理验真(0 LLM) + +### 3.1 它在防什么 + +不是「这句话好不好听」,而是: + +> 报告里声明依赖的每一个 tool_call,是否真的在本 Run 发生过、状态是否可引用、投影是否自洽、analysis kind 是否与 evidence_status 匹配,以及 conclusion/action 是否只引用存在的 analysis。 + +### 3.2 校验流水(按代码路径讲) + +`EvidenceGuard.validate(RunContext, DiagnosisDraft)` 大致两段: + +**A. Draft 结构与报告闭包** + +- draft / analysis 非空 +- `analysis_id` 存在且唯一 +- `kind`、`text` 必填 +- 每条 analysis 的 `tool_call_ids` 非空 +- conclusion / action_plan / recommendations:text 非空,且 `based_on_analysis_ids` 非空、id 都认识 +- `limitations.scope` 必填 + +**B. 逐 tool_call 验真** + +对每个 `tool_call_id`: + +1. 用 `runId + toolCallId` 生成 key,查 **Redis canonical** +2. 找不到 → `INVOCATION_MISSING`(典型:编造 id) +3. id 不一致 → `INVOCATION_ID_MISMATCH` +4. `!isReferencableBy(runId)` 或 agent_result 空 → `INVOCATION_NOT_REFERENCABLE` + (跨 Run、未 READY、不可引用状态) +5. `analysis.kind.accepts(invocation.evidenceStatus)` + - NORMAL ↔ EVIDENCE_FOUND + - NEGATIVE_OBSERVATION ↔ NO_EVIDENCE + 否则 `EVIDENCE_KIND_MISMATCH` +6. 按 tool 反序列化 **agent_result 投影**(不是让模型再读 raw 讲故事): + - `lookup_knowledge` / `query_logs` / `query_mysql` +7. 投影内 `tool_call_id`、`evidence_status` 与 canonical 一致 +8. FOUND 必须有可展示证据条目;NO_EVIDENCE 必须空列表且 count=0 +9. 通过则写入 `VerifiedEvidence`,汇总为 `VerifiedEvidenceSnapshot` + +```mermaid +flowchart TB + Draft["DiagnosisDraft"] --> S["结构 + analysis 闭包"] + S --> Loop["foreach tool_call_id"] + Loop --> Key["key = runId + toolCallId"] + Key --> Redis["Canonical store"] + Redis -->|missing| V1["INVOCATION_MISSING"] + Redis -->|not referencable| V2["NOT_REFERENCABLE"] + Redis -->|ok| K["kind vs evidence_status"] + K -->|mismatch| V3["KIND_MISMATCH"] + K --> P["Parse projection"] + P -->|invalid| V4["PROJECTION_*"] + P --> Snap["VerifiedEvidenceSnapshot"] +``` + +### 3.3 `AnalysisKind` × `EvidenceStatus`(高频考点) + +```text +NORMAL → 只能绑 EVIDENCE_FOUND +NEGATIVE_OBSERVATION → 只能绑 NO_EVIDENCE +ERROR → 根本不是证据(Agent Prompt + 边界) +``` + +**面试例子** + +| Agent 想说 | 错误绑法 | Guard | +|---|---|---| +| 「CPU 告警 92%」 | 编造 tool_call_id | MISSING | +| 「未查到池耗尽日志」 | kind=NORMAL 却绑 NO_EVIDENCE | KIND_MISMATCH | +| 「已排除内存泄漏」 | 仅 NO_EVIDENCE 却写排除结论 | 物理可能过,**Semantic 应 UNSUPPORTED** | +| 引用上一轮 previous_turn 的 id | 非本 Run canonical | MISSING / NOT_REFERENCABLE | + +### 3.4 为什么验的是 projection 且 canonical 在 Redis + +| 设计 | 原因 | +|---|---| +| Agent 只见 projection | 有界 ACI;降低上下文里的 debug 噪声与胡拼素材 | +| Guard 读 canonical 元数据 + 校验投影 | 确认「Agent 引用的 id」对应真实调用,且投影自洽 | +| Agent 不能访问 Redis | 防止自己翻 raw 再编第二套故事 | +| MySQL `tool_invocation` 只 metadata | 长期审计 ≠ 验真主存;完整 raw 短 TTL | + +**与早期 Gatekeeper 的差异(讲清楚就加分)** + +| 早期 Gatekeeper | 现行 EvidenceGuard | +|---|---| +| 多角色流水线中的一环 | Harness Release 路径上的确定性步骤 | +| `source_invocation_id` + `raw_path` + `excerpt` 字符串闭合 | `tool_call_id` + Run ownership + 投影结构/状态闭合 | +| 面向 `executor_evidence_v2` claims | 面向 `DiagnosisDraft` analysis 闭包 | +| 工具集合含 metrics 等 | 现行三 Tool;投影类型 Rag/Logs/Mysql | + +语义继承:**都是 0 LLM 的物理/契约验真**;协议与装载层已现代化。 + +### 3.5 失败码怎么用于口述 + +挑几个最能讲故事的 `EvidenceViolationCode`: + +| Code | 一句话 | +|---|---| +| `TOOL_REFERENCE_MISSING` | analysis 根本没绑工具 | +| `INVOCATION_MISSING` | 引用了不存在的 tool_call(归因造假) | +| `INVOCATION_NOT_REFERENCABLE` | 调用存在但不可作为证据(错 Run/未就绪/空结果) | +| `EVIDENCE_KIND_MISMATCH` | 负向/正向证据用错 kind | +| `ANALYSIS_REFERENCE_UNKNOWN` | 结论引用了不存在的 analysis_id | +| `PROJECTION_INVALID` | 投影与契约不一致,不能当干净证据 | + +--- + +## 4. SemanticGuard:现行语义保险丝 + +### 4.1 输入被故意冻死 + +`SemanticGuardInput.from(query, draft, verifiedSnapshot)`: + +```text +只给: + 原始 query + + 完整 Draft 视图 + + EvidenceGuard 产出的 verified snapshot + +明确没有: + Tool / 记忆 / Redis / 主 Agent 回调 / 诊断历史 +``` + +Prompt(`semantic-guard-prompt.md`)要求: + +- 查:evidence 是否支持各 analysis;analysis 是否支持 conclusion;action/recommendation 是否越界;limitations 是否如实 +- **禁止**改写、纠正、摘要扩展、**部分批准** +- 只返回 `{"verdict":"SUPPORTED|UNSUPPORTED","reason":"..."}` + +### 4.2 它专门接住 EvidenceGuard 接不住的归因幻觉 + +EvidenceGuard 通过只说明: + +> 「你引用的调用是真的,投影也合法。」 + +仍可能: + +| 漏洞 | 例子 | 谁拦 | +|---|---|---| +| 真日志推不出该根因 | 只有超时日志 → 写「确定是死锁」 | SemanticGuard | +| 负向观察说成排除 | NO_EVIDENCE → 「不可能是池耗尽」 | SemanticGuard + Agent 规则 | +| 结论超出 analysis 集合语义 | analysis 只谈 A,conclusion 谈 B | SemanticGuard | +| 建议动作无分析支撑 | 乱给变更建议 | SemanticGuard + 结构上 based_on | + +```mermaid +flowchart LR + EG["EvidenceGuard
物理真"] --> SG["SemanticGuard
语义立"] + SG -->|SUPPORTED| R["可发布"] + SG -->|UNSUPPORTED| F["Fallback
保留 observed_facts"] +``` + +### 4.3 为什么必须隔离、且无 Tool + +| 若 SemanticGuard 能再查库 | 后果 | +|---|---| +| 自建第二证据世界 | 与主 Agent / snapshot 不一致 | +| 「审稿时补证」 | 绕过用户可见的排查过程 | +| 又变成带 Tool 的第二 Executor | 归因问题换个角色重演 | + +**金句** + +> SemanticGuard 是保险丝,不是第二名侦探。 + +### 4.4 技术失败策略(现行) + +- 输入/输出字节上限(`SemanticGuardLimits`) +- 同输入有限重试;仍失败 → `semanticUnavailable` fallback(有 snapshot 时仍可带已验证事实) +- 不把内部异常原文甩给用户 + +--- + +## 5. Release:Draft 与公开通道切断 + +### 5.1 `DiagnosisReleaseUseCase` 决策序 + +```text +1) EvidenceGuard.validate +2) 若失败 → EvidenceRepair 一次 → 再 validate +3) 仍失败 → EVIDENCE_VALIDATION_FAILED fallback +4) SemanticGuard.review(query, draft, snapshot) +5) SUPPORTED → SUCCESS(公开 candidate Draft + snapshot 元数据路径) +6) UNSUPPORTED → SEMANTIC_UNSUPPORTED fallback(可带 observed_facts) +7) Semantic 技术不可用 → SEMANTIC_UNAVAILABLE fallback +``` + +Timeline 会记:`EVIDENCE_GUARD_INITIAL` / `RECHECK` / semantic / release 决策(普通 Trace 可回放阶段,不靠「感觉」)。 + +### 5.2 SAFE_FALLBACK 在防什么 + +不是空白 500,而是**可信的不完整**: + +| Fallback 类型 | 用户侧含义(思想) | +|---|---| +| 证据校验失败 | 引用/结构没过,不能确认根因;可带 validation 问题方向 | +| 语义不支持 | 已有可验证事实,但撑不起当前根因结论 | +| 语义不可用 | 有事实,但审不过/审不了,暂不发根因 | + +`SafeFallbackFactory` 会从 snapshot 抽取有界 `observed_facts` / sources(有上限),并给出 `failure_stage`、`next_steps` 等——**在不泄 Prompt/raw/内部 Draft 细节的前提下**尽量可操作。 + +**金句** + +> 我们宁可发布「已经核实到什么、卡在哪」,也不发布「流畅但未过门禁的完整故事」。 + +### 5.3 PreviousTurn 与门禁的衔接 + +- 仅 **同 Session、最近一次 DIAGNOSIS + SUCCESS + published_result** 可进下一轮 +- Fallback/失败/raw **不进** PreviousTurn +- Prompt 明确:previous_turn **不可当本 Run 证据** + +防止「上一轮没过门禁的句子」在下一轮被当成已证实事实——这是归因幻觉的跨轮版本。 + +--- + +## 6. Tool 边界:归因幻觉的上游防线 + +门禁是下游闸门;上游仍要减少「胡拼素材」。 + +```text +framework tool_call_id + → exact Run / schema / read-only / budget + → 执行 + → Redis canonical(request/raw/agent_result/status) + → projector → bounded agent_result + → 只把 projection 给 Agent + → MySQL 仅 metadata audit +``` + +现行 Agent 可见 Tool 固定三个: + +- `lookup_knowledge` +- `query_logs` +- `query_mysql` + +**与归因的关系** + +| 机制 | 作用 | +|---|---| +| 投影有界 | 少把 rerank/debug 大字段留给模型拼案情 | +| 统一 evidence_status | FOUND/NO_EVIDENCE/ERROR 语义稳定,供 kind 匹配 | +| 每调必有 tool_call_id | Draft 绑定有稳定主键 | +| 禁止 Agent 见 Redis | 不能「翻完整 raw 再假装引用」 | + +--- + +## 7. Reasoning 明确不是证据(现行安全边界) + +架构硬约束: + +- Provider reasoning 若存在,进独立 `agent_reasoning_audit` +- **不进**普通 SSE、Trace 正文、Evidence Snapshot、业务判断 +- **不能**绕过 EvidenceGuard / SemanticGuard +- 未返回则记 unavailable,**禁止伪造** + +面试若被问「你们保存思考过程吗」: + +> 审计与事实分离。思考不是 tool evidence,更不能当发布依据。 + +--- + +## 8. 历史问题:只用来回答「为什么要这套现行设计」 + +### 8.1 早期现象(30–45 秒够) + +2026-07 旧 Chat 链路(Planner/Executor/Verifier…)上: + +- 多次 E2E:`lookup_* / logs / metrics` 有调用,仍大量 `LOW_CONFID` +- 答案出现工具 raw 中不存在的「精确事故事实」(OOM 次数、慢 SQL 秒数等) +- 根因命名:**证据归因幻觉**——把 runbook/常识/他服事实写成「本会话已证实」 +- 曾伴随摘要失真、自证闭环(自己总结再自己绑引用) + +**正确用法** + +> 这段证明「只靠模型自觉 + 事后 LLM Verifier」不够,必须把物理引用做成确定性约束,并把发布权从生成模型手里拿走。 + +**错误用法** + +> 把整场面试讲成旧五段角色和 `executor_evidence_v2` 字段细节,却说不清现在的类名与 API。 + +### 8.2 语义迁移表(历史 → 现行) + +| 历史概念 | 现行概念 | 说明 | +|---|---|---| +| Executor 综合答案 | Diagnosis Agent 写 Draft | 仍是模型生成,但是唯一作者 | +| claim + excerpt binding | analysis + `tool_call_ids` | 主键协议变更 | +| Gatekeeper | EvidenceGuard | 仍 0 LLM;装入 Release 用例 | +| Verifier LOW_CONFID | SemanticGuard UNSUPPORTED | 隔离输入;二元 verdict | +| Composer 控表达 | Draft 结构 + Release/Fallback | 表达权在 Agent,发布权在 Harness | +| 调低阈值换 PASS | **明确不做** | 用 fallback 信息量换体验 | + +```mermaid +flowchart LR + H1["早期:归因幻觉被发现"] --> H2["正确性模型:物理验真+语义审+控表达"] + H2 --> H3["ISS-014:装载到单 Agent + Harness"] + H3 --> Now["现行:Draft→EG→SG→Release"] +``` + +### 8.3 一句话定位两阶段 + +> 早期 Issue 解决的是 **「要什么正确性」**; +> 现行架构解决的是 **「正确性如何成为默认运行路径」**。 + +--- + +## 9. 和业界主流的区别(用现行组件说) + +| 常见做法 | 缺口 | 本项目现行 | +|---|---|---| +| 纯 ReAct 直接吐最终答案 | 无发布闸 | Draft 默认内部,Release 才公开 | +| 答案末尾 sources 角标 | 角标可假 | `tool_call_id` 必须在本 Run canonical 可解析 | +| 单一 LLM-as-Judge | 真伪与语义混判、不可复现引用检查 | EG 代码 + SG 隔离模型 | +| 质检 Agent 再带 Tool | 第二证据世界 | SG 无 Tool,冻结 snapshot | +| 离线 RAGAS | 不挡单次错误出门 | 在线门禁 + Timeline + eval 夹具 | +| 只靠更强模型 | 无工程边界 | 与模型代际正交的 Harness | + +**三个不一样(现行表述)** + +1. **引用是 Run 级所有权问题**,不是文案装饰。 +2. **物理与语义拆分**,失败阶段可进 Trace / fallback。 +3. **公开通道与生成通道切断**,SUPPORTED 才是成功产品语义。 + +--- + +## 10. 决策环(填的是现行答案) + +| # | 问题 | 现行答案 | +|---|---|---| +| 1 | 威胁? | 带 tool 外观的完整假案情进入 SSE | +| 2 | 谁强制? | EG 强制引用;SG 强制语义;Release 强制发布 | +| 3 | 数据面? | canonical / projection / metadata audit;reasoning 另表 | +| 4 | 失败用户看到? | SAFE_FALLBACK(阶段、有界事实、下一步),非假成功 | +| 5 | 如何证明? | 单元/契约测 violation;E2E release_outcome;Timeline 事件 | +| 6 | 演进? | 误杀先查投影与 schema/Repair;不给 SG 加 Tool;停止策略见 ISS-015 | + +--- + +## 11. 面试题库(默认用现行答) + +### 11.1 90 秒主叙述(推荐背这个版本) + +> 故障诊断里最危险的不是完全不查工具,而是查了一点真实信号就补成完整事故——我们早期在旧链路上把它定义为证据归因幻觉。 +> **现在**的做法是:唯一 Diagnosis Agent 用 ReAct 查三个只读工具,只看投影,输出结构化 DiagnosisDraft;每条分析必须绑定本 Run 的 tool_call_id。 +> Draft 先过 EvidenceGuard:纯代码检查结构闭包、调用是否存在于当前 Run 的 Redis canonical、证据状态是否与 NORMAL/负向观察匹配、投影是否自洽。 +> 通过后生成 verified snapshot,再交给无工具的 SemanticGuard 做整份语义是否越证的审查。 +> 只有 SUPPORTED 才经 Release 进入 SSE;否则走 SAFE_FALLBACK,宁可告诉用户已核实事实和卡住的阶段,也不发未验证根因。 +> 所以质量辨识度是三句话:**可调用 ≠ 可归因;可归因 ≠ 语义成立;语义成立才可发布。** + +### 11.2 为什么题 + +| 问题 | 现行得分点 | +|---|---| +| 怎么防幻觉? | Draft 绑定 tool_call_id → EG → SG → Release | +| 为什么 EG 不用模型? | 归属与状态是确定性的;要可回归 | +| 为什么还要 SG? | 真调用推不出假根因;负向≠排除 | +| 为什么 SG 不能有 Tool? | 冻结证据集,防第二世界 | +| 引用主键为什么是 tool_call_id? | 框架协议 id;与当次调用一致;不靠「最新 DB 行」 | +| Agent 能看 raw 吗? | 不能;只看 projection;canonical Harness only | +| 证据不足怎么办? | conclusion 可空 + limitations;或 fallback;不编根因 | +| 和旧 Gatekeeper 啥关系? | 语义祖先;现装在 Harness,协议已换 | + +### 11.3 对抗题 + +**Q:这不就是多 Agent 质检吗?** + +A:不是。业务侧只有一个带 Tool 的 Diagnosis Agent。SG 是无 Tool 的隔离单轮审查,属于 Harness 控制面,不是协作同事。 + +**Q:你们重构掉多角色后质量是不是弱了?** + +A:弱的是重复的 LLM 角色编排;强的是默认路径上的确定性 EG + 发布切断。正确性模型保留,装载点从流水线角色变成 Release 用例。 + +**Q:投影校验不看 raw 原文子串,会不会漏?** + +A:现行 EG 强调 **调用所有权 + 状态 + 投影结构自洽 + kind 匹配**,再交给 SG 做语义。上游靠 projector 把可引用证据做成稳定结构。若追问 excerpt 级闭合,可承认协议从早期 raw_path/excerpt 演进到投影契约,并强调 **不能引用 ERROR/跨 Run/不可引用调用** 仍是硬的。 + +**Q:用户体验会不会总是 fallback?** + +A:体验做在「信息化 fallback + 成功路径的 limitations」,不是放宽 Guard。ISS-015 继续收敛停止策略与 fallback 信息量。 + +### 11.4 现场设计题 + +1. 给「工单退款 Agent」设计等价于 `tool_call_ids` + EG 的字段。 +2. 若增加第四个 Tool,EG 要补哪些分支?kind/status 如何扩展? +3. Knowledge Query 路径(非完整 DIAGNOSIS)如何复用「引用必须真实」而不照搬整份 SemanticGuard? +4. 如何用 Timeline 事件向面试官演示一次 UNSUPPORTED 的失败阶段? + +--- + +## 12. 原则清单(现行) + +1. **唯一报告作者,多个确定性关卡** +2. **Draft 是 staging,SSE 是 production** +3. **引用主键 = 本 Run 的 framework tool_call_id** +4. **NORMAL / NEGATIVE 与 FOUND / NO_EVIDENCE 强匹配** +5. **NO_EVIDENCE 不是健康证明** +6. **ERROR 与跨 Run id 绝不能当证据** +7. **PreviousTurn 不是证据** +8. **SemanticGuard 冻结 snapshot,无 Tool** +9. **Reasoning 不是证据** +10. **历史 Issue 论证问题,现行代码定义答案** + +--- + +## 13. 白板默画(只画现行) + +### 13.1 图 A · 60 秒主链 + +```text +Diagnosis Agent → DiagnosisDraft + ↓ +EvidenceGuard (0 LLM, tool_call_id) + ↓ verified snapshot +SemanticGuard (no tools) + ↓ SUPPORTED? +Release → SSE or SAFE_FALLBACK +``` + +### 13.2 图 B · 45 秒闭包 + +```text +conclusion.based_on → analysis_id → tool_call_ids + ↓ + Redis canonical (this runId) + ↓ + FOUND / NO_EVIDENCE + ↓ + kind must match +``` + +### 13.3 图 C · 30 秒历史锚点(可选) + +```text +早期发现:有 tool 仍假案情 + → 要物理验真 + 语义审 + 发布权 + → 现装在 EG / SG / Release +``` + +### 13.4 红线 + +- 画出 Planner/Executor/Composer 当主路径 +- 说 Verifier 输出 LOW_CONFID 当现行 API +- SG 带检索箭头 +- Draft 直连用户 +- 说 metrics Tool 仍是诊断三件套之一(现行是 knowledge/logs/mysql) + +--- + +## 14. 复习路径(偏现行) + +| 步骤 | 动作 | +|---|---| +| 1 | 读 `diagnosis-agent-prompt.md` + `DiagnosisDraft` / `AnalysisKind` | +| 2 | 通读 `EvidenceGuard.validate` 与 `EvidenceViolationCode` | +| 3 | 读 `DiagnosisReleaseUseCase` + `semantic-guard-prompt.md` | +| 4 | 对照 `harness-quality-gates.md` 默画 §13 图 A/B | +| 5 | 用 §11.1 录音;再花 20 秒提早期归因幻觉作动机 | +| 6 | 扫一眼归档 Issue 标题与现象表即可,不背旧字段 | + +--- + +## 15. 源文件索引 + +### 现行(主) + +| 内容 | 路径 | +|---|---| +| 架构总览 | `mvp/architecture/current-mvp-architecture.md` | +| 执行序列 | `mvp/architecture/agent-orchestration.md` | +| 门禁 | `mvp/architecture/harness-quality-gates.md` | +| Draft | `src/main/java/.../harness/contract/DiagnosisDraft.java` | +| Kind/Status | `AnalysisKind.java` / `EvidenceStatus.java` | +| EG | `.../guard/evidence/EvidenceGuard.java` | +| SG | `.../guard/semantic/SemanticGuard.java` | +| Release | `.../release/DiagnosisReleaseUseCase.java` | +| Fallback | `.../release/SafeFallbackFactory.java` | +| Agent Prompt | `src/main/resources/prompts/diagnosis-agent-prompt.md` | +| SG Prompt | `src/main/resources/prompts/semantic-guard-prompt.md` | + +### 历史(辅) + +| 内容 | 路径 | +|---|---| +| 归因幻觉发现 | `mvp/issues/archived/executor-evidence-attribution-hallucination.md` | +| 自证闭环笔记 | `mvp/issues/design-notes/executor-self-evidence-loop-design-note.md` | +| 旧证据契约 | `mvp/architecture/archive/2026-07-22-legacy/executor-evidence-pipeline-refactor.md` | +| 重构承接 | `mvp/issues/archived/ISS-014-...` | +| 运行质量后续 | `mvp/issues/active/ISS-015-...` | + +--- + +## 16. 自测(必须能用现行组件名回答) + +1. 画出 Draft 从产生到 SSE 的完整门禁序,并标出哪步 0 LLM。 +2. `NORMAL` 与 `NEGATIVE_OBSERVATION` 分别能绑哪种 `evidence_status`? +3. EvidenceGuard 如何发现「编造 tool_call_id」? +4. 为什么 conclusion 要 `based_on_analysis_ids` 而不是直接绑 tool? +5. SemanticGuard 的输入有哪三样?为什么不能有 Tool? +6. Evidence 失败时 Repair 最多几次?仍失败用户看到什么产品语义? +7. PreviousTurn 为什么不能提供可引用的 tool_call_id? +8. Reasoning 能否帮助 Draft 过 EG/SG? +9. 用 20 秒说明早期归因幻觉与现行三道门的关系(动机 vs 实现)。 +10. 举一个「EG 通过但 SG 应 UNSUPPORTED」的例子。 + +--- + +## 17. 和旧版材料的关系 + +若你曾按「五段流水线 + excerpt 外键」准备: + +- **保留**:归因幻觉定义、物理/语义拆分、发布切断思想 +- **替换**:所有主路径类名、Tool 列表、verdict 枚举、引用主键、API +- **降级**:Executor/Gatekeeper/Composer 仅出现在「历史动机」小节 + +**面试默认叠词顺序** + +```text +1. 现行:Agent → Draft → EG → SG → Release +2. 机制:tool_call_id、kind/status、snapshot、fallback +3. 动机:早期归因幻觉(可选一句) +4. 演进:正确性模型保留,装载进 Harness(若追问重构) +```