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.
This commit is contained in:
zhuyongxin
2026-07-24 18:14:49 +08:00
parent e47f2dead0
commit de5a5b09d9
18 changed files with 2622 additions and 57 deletions
@@ -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 回放。面试时重点展示“从问题到证据到答案到验证再到反馈”的闭环。
@@ -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、编排或验收标准。
- 若引用其中内容,须同时说明归档日期与现行替代文档。
@@ -0,0 +1,166 @@
# 面试前验收清单
## 1. 环境检查
- 当前分支包含最新架构文档和面试材料。
- MySQL 可连接。
- Redis 可连接。
- Milvus/Zilliz 可连接。
- 模型 API key 可用。
- `mvp-demo` profile 开启 mock Prometheus 和 mock CLS。
启动服务:
```powershell
mvn spring-boot:run "-Dspring-boot.run.profiles=mvp-demo"
```
编译检查:
```powershell
mvn -q -DskipTests compile
```
目标测试:
```powershell
mvn -q "-Dtest=AiOpsServiceTest,ChatServiceSequentialAgentTest,DiagnosisTraceServiceTest,VectorSearchServiceTest,LookupKnowledgeToolTest" test
```
## 2. Chat Demo 验收
请求:
```powershell
$sessionId = "interview-chat-payment-timeout-001"
$body = @{
Id = $sessionId
Question = "支付接口最近出现超时,请结合知识库、日志和指标判断可能原因,并给出修复建议。"
} | ConvertTo-Json
Invoke-RestMethod `
-Method Post `
-Uri "http://localhost:9900/api/chat" `
-ContentType "application/json" `
-Body $body
```
验收:
- 返回 `data.success = true`。
- 返回 `data.sessionId = interview-chat-payment-timeout-001`。
- `diagnosis_session.agent_flow = CHAT`。
- Trace API 返回 session、steps、toolInvocations。
- 复杂问题下 trace 中能看到 verifier 相关数据。
SQL:
```powershell
python scripts/query_mysql.py "SELECT session_id, agent_flow, status, step_count, tool_call_count FROM diagnosis_session WHERE session_id='interview-chat-payment-timeout-001'"
```
## 3. AIOps Demo 验收
请求:
```powershell
$aiopsSessionId = "interview-aiops-payment-cpu-001"
$aiopsBody = @{
sessionId = $aiopsSessionId
alertName = "HighCPUUsage"
service = "payment-service"
severity = "P1"
description = "服务 payment-service 的 CPU 使用率持续超过 80%,当前值为 92%。实例: pod-payment-service-7d8f9c6b5-x2k4m。"
timeRange = "last_15m"
userRequest = "请结合 Prometheus 活动告警、system-metrics 日志和知识库生成告警分析报告。"
} | ConvertTo-Json
Invoke-WebRequest `
-Method Post `
-Uri "http://localhost:9900/api/ai_ops" `
-ContentType "application/json" `
-Body $aiopsBody
```
验收:
- SSE 首条包含 `type=session`。
- SSE 最后包含 `type=done`。
- `diagnosis_session.agent_flow = AI_OPS`。
- `diagnosis_session.status = SUCCESS`。
- `diagnosis_session.answer` 有最终报告。
- Trace API 返回 AIOps steps 和 tool invocations。
- 报告主章节聚焦 `HighCPUUsage/payment-service`。
- 其他 active alerts 不应展开成独立主根因章节。
- `self_evaluation.aiops_rule_evaluation` 存在。
SQL:
```powershell
python scripts/query_mysql.py "SELECT session_id, agent_flow, status, total_duration_ms, step_count, tool_call_count FROM diagnosis_session WHERE session_id='interview-aiops-payment-cpu-001'"
```
```powershell
python scripts/query_mysql.py "SELECT tool_name, COUNT(*) AS cnt FROM tool_invocation WHERE session_id='interview-aiops-payment-cpu-001' GROUP BY tool_name ORDER BY tool_name"
```
Scope 检查:
```powershell
python scripts/query_mysql.py "SELECT (answer LIKE '%HighCPUUsage%') AS has_main_alert, (answer LIKE '%payment-service%') AS has_service FROM diagnosis_session WHERE session_id='interview-aiops-payment-cpu-001'"
```
## 4. Trace API 验收
```powershell
Invoke-RestMethod `
-Method Get `
-Uri "http://localhost:9900/api/diagnosis/interview-aiops-payment-cpu-001/trace"
```
如果 PowerShell 对长 JSON 或特殊字符不稳定,可以用:
```powershell
curl.exe --silent --show-error --max-time 60 "http://localhost:9900/api/diagnosis/interview-aiops-payment-cpu-001/trace"
```
## 5. RAG 验收
```powershell
Invoke-RestMethod `
-Uri "http://127.0.0.1:9900/api/search/similar?query=ERR_TIMEOUT&topK=3" `
-Method Get
```
验收:
- 返回 `code = 200`。
- top candidates 中包含 `ERR_TIMEOUT` 相关文档。
- `scoreLabel` 能体现当前检索路径语义。
- 如果走 VectorStore,日志应出现 Spring AI VectorStore search。
## 6. 常见问题
### MySQL stale connection
现象:
```text
HikariPool - Connection is not available
No operations allowed after connection closed
```
处理:
- 重启服务。
- 确认 HikariPool 使用当前配置启动成功。
- 再跑 trace 或 AIOps 请求。
### SSE 客户端显示异常
PowerShell `Invoke-WebRequest` 有时对 SSE 或长 JSON 处理不稳定。可以改用 `curl.exe` 或直接查询 MySQL 和 Trace API 验证结果。
### OpenSpec 全量校验失败
`openspec validate --all --strict` 可能因为历史未完成 change 失败。面试演示主要依赖已归档 spec、MVP trace 和 RAG 验收材料,可以单独验证相关 spec。
@@ -0,0 +1,74 @@
# AIOps 轻量规则验证器
## 1. 改动是什么
AIOps 现在有一个确定性的后置质量门禁。最终告警报告持久化后,`AiOpsRuleEvaluationService` 会检查:
- 最终报告是否存在,且不是明显过短。
- payload 模式下,报告是否提到输入的告警和服务。
- 是否有证据工具调用,例如 `lookup_knowledge`、`query_metrics`、`query_logs`。
结果写入:
```text
diagnosis_session.self_evaluation.aiops_rule_evaluation
```
Trace API 会通过 session self-evaluation 展示这个结果。
## 2. 为什么先做规则型
这还不是完整 LLM Verifier。
AIOps 第一阶段质量风险比较具体,适合先用规则:
- 报告有没有生成。
- 报告有没有聚焦 payload。
- 有没有使用证据工具。
- 有没有把无关告警展开成主诊断对象。
规则验证稳定、便宜、容易解释,也不会在当前链路里额外引入一次隐藏模型调用。
## 3. 判定结果
当前评估器输出:
```text
PASS
WARN
FAIL
```
含义:
- `PASS`:核心检查通过。
- `WARN`:报告存在,但可能缺少 payload 关键词或证据工具。
- `FAIL`:缺少最终报告、报告过短等关键问题。
缺少 payload 关键词或证据工具先给 `WARN`,因为 demo/mock 环境下证据可能不可用,且报告措辞可能与 payload 字段不完全一致。
## 4. 面试回答
如果被问:为什么 AIOps 也需要验证器?
```text
Chat 已经有 LLM Verifier,因为用户问题开放度高。
AIOps 的第一阶段质量风险更明确:报告是否聚焦输入告警、是否使用证据工具、报告是否完整。
所以我先做了轻量规则验证器,把结果写入 self_evaluation,让 Trace 不只展示 Agent 做了什么,也展示输出是否通过基础质量门。
```
如果被问:为什么不直接复用 Chat Verifier?
```text
AIOps 验证语义和 Chat 不一样。
它要检查 alert scope、payload focus、证据工具覆盖,以及是否过度展开无关 active alerts。
直接复用 Chat Verifier 会混淆这些语义。
规则评估先提供稳定质量门,后续 AIOps LLM Verifier 可以基于同一套 trace contract 扩展。
```
## 5. 后续增强
- 引入 AIOps LLM Verifier,逐条校验根因和建议是否有 evidence refs。
- 把 rule evaluation 的 checks 在 Trace API 中结构化展示。
- 将 payload scope violation 沉淀为 bad case。
@@ -0,0 +1,75 @@
# AIOps 查询增强说明
## 1. 改动是什么
AIOps 在 `PAYLOAD_TARGETED` 模式下,会从告警 payload 中稳定生成一条推荐知识库检索 query。
参与拼接的非空字段:
```text
alertName service severity description timeRange userRequest
```
示例:
```text
HighCPUUsage payment-service P1 CPU 使用率超过 80% last_15m
```
最终会进入 Prompt:
```text
Recommended lookup_knowledge query: ...
```
## 2. 为什么重要
AIOps payload 里包含高价值检索词:
- 告警名称。
- 服务名。
- 严重等级。
- 症状描述。
- 时间范围。
- 用户补充请求。
如果完全让 Agent 从长 Prompt 里自己组织检索 query,可能遗漏服务名或告警名。推荐 query 让检索种子更稳定。
## 3. 设计取舍
这是 Prompt 层 query augmentation,不是隐藏检索。
我没有在 Agent 运行前自动调用 `lookup_knowledge`,原因是项目强调可追踪性:工具调用应该由 Agent 显式发起,并记录到 `tool_invocation`。
当前设计:
```text
AIOps payload
-> deterministic recommended retrieval query
-> Agent prompt
-> Agent 显式调用 lookup_knowledge
-> tool_invocation 记录真实检索行为
```
## 4. 面试回答
如果被问:AIOps payload 怎么提升 RAG 检索?
```text
我没有把告警 payload 粗暴替换成一个宽泛领域,而是提取 alertName、service、severity、description、timeRange 等高信号字段,拼成推荐的 lookup_knowledge query。
Agent 仍然显式调用工具,所以 trace 仍然能看到真实检索行为,但 query 不再完全依赖模型临场发挥。
```
如果被问:为什么不自动检索?
```text
自动检索会在 Agent 真正决策前制造一份隐藏证据。
这个项目的重点是可观测 Agent 执行,所以我选择 Prompt 层增强:给 Agent 一个更好的 query seed,但不改变工具调用必须显式可追踪的契约。
```
## 5. 后续增强
- 将 recommended query 写入 trace 的结构化字段,便于对比 Agent 实际 query。
- 对 payload 字段加权,例如 alertName/service 权重大于 timeRange。
- 后续接入 Query Transformer 时,保留原始 query、推荐 query、改写 query 三者的可追踪关系。
@@ -0,0 +1,97 @@
# 面试版系统架构
## 1. 系统分层
```mermaid
flowchart TB
API["API 层\nChatController / DiagnosisTraceController / SearchController"] --> Service["应用服务层\nChatService / AiOpsService / DiagnosisTraceService"]
Service --> Agent["Agent 编排层\nPlanner / Executor / Verifier / Supervisor"]
Agent --> Tools["工具层\nlookup_knowledge / query_logs / query_metrics / Prometheus"]
Tools --> RAG["RAG 检索\nL0 hint + VectorSearchService"]
RAG --> VectorStore["Spring AI VectorStore"]
RAG --> SDK["Milvus SDK fallback"]
Agent --> Trace["Trace 持久化"]
Tools --> Trace
Trace --> Session["diagnosis_session"]
Trace --> Step["agent_step"]
Trace --> Invocation["tool_invocation"]
Session --> TraceAPI["GET /api/diagnosis/{sessionId}/trace"]
Step --> TraceAPI
Invocation --> TraceAPI
```
## 2. Chat 链路
```mermaid
flowchart TD
User["用户问题"] --> ChatAPI["POST /api/chat"]
ChatAPI --> Strategy["ChatService.executeChatWithStrategy"]
Strategy --> Complexity{"复杂问题?"}
Complexity -->|否| Single["单 ReactAgent 快速回答"]
Complexity -->|是| Planner["chat_planner"]
Planner --> Executor["chat_executor"]
Executor --> Tools["证据工具"]
Tools --> Executor
Executor --> Verifier["chat_verifier"]
Verifier --> Decision{"PASS / LOW_CONFID / REJECT"}
Decision --> Answer["最终答复"]
Planner --> Step["agent_step"]
Executor --> Step
Verifier --> Step
Tools --> Invocation["tool_invocation"]
Answer --> Session["diagnosis_session"]
```
讲解重点:
- Planner 拆解问题和排查方向。
- Executor 必须通过工具收集证据。
- Verifier 只基于 `tool_trace_summary` 校验答案,不做新检索。
- Trace API 能回放模型步骤和工具证据。
## 3. AIOps 链路
```mermaid
flowchart TD
Alert["告警 payload 或空请求"] --> API["POST /api/ai_ops"]
API --> AiOps["AiOpsService"]
AiOps --> Mode{"是否有 payload?"}
Mode -->|有| Targeted["PAYLOAD_TARGETED\n聚焦输入告警"]
Mode -->|无| Discovery["AUTO_DISCOVERY\n先发现活跃告警"]
Targeted --> Supervisor["ai_ops_supervisor"]
Discovery --> Supervisor
Supervisor --> Planner["planner_agent"]
Supervisor --> Executor["executor_agent"]
Planner --> Tools["Prometheus / 日志 / 知识库"]
Executor --> Tools
Tools --> Report["告警分析报告"]
Report --> Eval["AiOpsRuleEvaluationService"]
Eval --> SelfEval["self_evaluation.aiops_rule_evaluation"]
```
讲解重点:
- AIOps 有明确产品边界:有 payload 时必须聚焦该告警。
- payload 字段会生成 recommended `lookup_knowledge` query。
- 当前 AIOps 先用规则评估做质量门,后续再扩展 LLM Verifier。
## 4. Trace 数据模型
| 表 | 作用 |
|---|---|
| `diagnosis_session` | 一次诊断的主记录:问题、状态、答案、自评估、反馈 |
| `agent_step` | Agent 模型调用记录:输入、输出、耗时、token、是否有工具调用 |
| `tool_invocation` | 工具调用事实:工具名、入参、输出预览、检索层、相关性、成功状态 |
## 5. 为什么 Trace 是核心
故障诊断系统的风险不只是“答案错”,还包括“答案看起来对但无法解释”。这个项目把执行链路拆成 session、step、tool 三层,让面试官可以看到:
- 模型为什么这么答。
- 调了哪些工具。
- 工具返回了什么证据。
- Verifier 如何判断答案可信度。
- 用户反馈如何回写到同一个 session。
这就是它区别于普通 Chatbot 的地方。
@@ -0,0 +1,145 @@
# 面试演示脚本
## 1. 30 秒开场
```text
这是一个 Agent 工程项目,场景是企业故障诊断。
它支持两类入口:用户主动提问的 Chat 诊断,以及告警事件驱动的 AIOps 诊断。
项目重点不是单次模型回答,而是把 Agent 编排、工具证据、Verifier 评估、最终报告和反馈都沉淀成可回放的 Trace。
```
## 2. 启动服务
```powershell
mvn spring-boot:run "-Dspring-boot.run.profiles=mvp-demo"
```
服务地址:
```text
http://localhost:9900
```
`mvp-demo` profile 下:
- Prometheus 告警使用 mock 数据。
- CLS 日志使用 mock 数据。
- MySQL、Redis、Milvus/Zilliz 和模型配置仍使用当前项目配置。
## 3. Demo 1:Chat 诊断
目标:展示用户问题如何进入多 Agent 诊断、调用工具、经过 Verifier,并生成 Trace。
```powershell
$sessionId = "interview-chat-payment-timeout-001"
$body = @{
Id = $sessionId
Question = "支付接口最近出现超时,请结合知识库、日志和指标判断可能原因,并给出修复建议。"
} | ConvertTo-Json
Invoke-RestMethod `
-Method Post `
-Uri "http://localhost:9900/api/chat" `
-ContentType "application/json" `
-Body $body
```
讲解点:
- `ChatService` 会根据问题复杂度选择轻量回答或复杂 Agent 流程。
- 复杂问题走 `Planner -> Executor -> Verifier`。
- Executor 调用知识库、日志、指标等证据工具。
- Verifier 基于 `tool_trace_summary` 生成 groundedness 评估。
- 最终写入 `diagnosis_session`、`agent_step`、`tool_invocation`。
查询 Trace:
```powershell
Invoke-RestMethod `
-Method Get `
-Uri "http://localhost:9900/api/diagnosis/$sessionId/trace"
```
展示点:
- `data.session.agentFlow = CHAT`
- `data.steps` 中能看到 planner/executor/verifier
- `data.toolInvocations` 中能看到证据工具
- `data.session.selfEvaluation` 中有 verifier 结果
## 4. Demo 2:AIOps 告警诊断
目标:展示告警 payload 如何触发 AIOps,并且报告聚焦目标告警。
```powershell
$aiopsSessionId = "interview-aiops-payment-cpu-001"
$aiopsBody = @{
sessionId = $aiopsSessionId
alertName = "HighCPUUsage"
service = "payment-service"
severity = "P1"
description = "服务 payment-service 的 CPU 使用率持续超过 80%,当前值为 92%。实例: pod-payment-service-7d8f9c6b5-x2k4m。"
timeRange = "last_15m"
userRequest = "请结合 Prometheus 活动告警、system-metrics 日志和知识库生成告警分析报告。"
} | ConvertTo-Json
Invoke-WebRequest `
-Method Post `
-Uri "http://localhost:9900/api/ai_ops" `
-ContentType "application/json" `
-Body $aiopsBody
```
讲解点:
- `/api/ai_ops` 接受可选 `AIOpsRequest`。
- 首条 SSE 消息会返回 `type=session`。
- `AiOpsService` 根据 payload 判断模式:
- `PAYLOAD_TARGETED`:聚焦传入告警。
- `AUTO_DISCOVERY`:没有 payload 时先查 active alerts。
- AIOps 当前用 rule evaluation 检查报告完整性、payload 聚焦和证据工具覆盖。
查询 Trace:
```powershell
Invoke-RestMethod `
-Method Get `
-Uri "http://localhost:9900/api/diagnosis/$aiopsSessionId/trace"
```
展示点:
- `data.session.agentFlow = AI_OPS`
- `data.session.answer` 有最终告警报告
- `data.toolInvocations` 有 `query_metrics`、`query_logs`、`lookup_knowledge`
- 报告主线聚焦 `HighCPUUsage/payment-service`
## 5. Demo 3:反馈闭环
```powershell
$feedback = @{
sessionId = $sessionId
feedback = "useful"
} | ConvertTo-Json
Invoke-RestMethod `
-Method Post `
-Uri "http://localhost:9900/api/feedback" `
-ContentType "application/json" `
-Body $feedback
```
讲解点:
- feedback 写回同一个 `diagnosis_session`。
- `useful` 会沉淀 `case_library`。
- `not_useful` 不改变 `status`,只作为质量信号。
## 6. 收尾总结
```text
这个 Demo 展示的是完整 Agent 闭环:
用户问题或告警 -> Agent 编排 -> 工具证据 -> 自评估 -> Trace 回放 -> 用户反馈 -> 案例沉淀。
我关注的不是一次回答,而是这个回答能否被审计、验证和持续改进。
```
@@ -0,0 +1,107 @@
# 关键设计取舍
## 1. 为什么先做 Trace,而不是只返回答案
普通 Chatbot 只关注最终回答,但故障诊断更需要可审计性。一次诊断至少要回答:
- 结论是什么。
- 证据来自哪里。
- 哪些步骤由哪个 Agent 完成。
- 如果答案不可靠,系统怎么降级。
因此项目把一次会话拆成:
- `diagnosis_session`:会话摘要、最终答案、自评估、用户反馈。
- `agent_step`:模型输入输出、耗时、token 和工具调用标记。
- `tool_invocation`:真实工具调用参数、输出预览、成功状态和检索元数据。
代价是实现复杂度上升,收益是可回放、可调试、可演示。
## 2. 为什么 RAG 不直接隐藏在 Advisor 里
Spring AI Advisor 可以让 RAG 更隐式,但本项目的核心是 Agent 证据链。`lookup_knowledge` 必须作为显式工具调用出现,这样 Trace 里才能看到:
- Agent 什么时候决定检索。
- 用了什么 query。
- 命中了哪些文档。
- 相关性等级是什么。
- 证据如何支撑最终答案。
所以当前设计是:
```text
Executor -> lookup_knowledge -> VectorSearchService -> VectorStore / SDK fallback
```
这牺牲了一点框架自动化,但保留了可审计性。
## 3. 为什么 L0 只做 hint,不直接返回
旧版 L0 关键词唯一命中时可能直接跳过 L1。这个策略速度快,但风险是:关键词子串命中不等于最终语义相关。
当前改成:
```text
L0 = domain/entity hint
L1 = semantic retrieval
postprocess = evidence shaping + trace
```
L0 仍然有价值:错误码、服务名、告警名、指标名都很适合做精确 hint。但最终证据仍需要 L1 和后处理支撑。
## 4. 为什么保留 Milvus SDK fallback
Spring AI VectorStore 是当前读路径主方向,但 SDK fallback 没有删除,原因有三点:
- 迁移安全:旧 SDK 路径已经被验证过。
- 运行韧性:VectorStore 配置、schema、collection 出问题时可以回退。
- 面试稳定:检索抽象迁移不应该破坏主 demo。
这不是“没有迁完”,而是分阶段迁移:先稳定读路径,再决定是否迁移写入和索引。
## 5. 为什么 Chat 有 Verifier,AIOps 先用规则评估
Chat 问题更开放,容易出现跨领域推理,所以需要 LLM Verifier 做 groundedness 校验。
AIOps 当前优先解决更具体的问题:
- 最终报告是否存在。
- payload 模式是否聚焦输入告警。
- 是否使用了证据工具。
- 是否把无关活跃告警展开成主根因。
这些用规则就能稳定检查。后续可以在同一个 `self_evaluation` 容器下增加 AIOps LLM Verifier。
## 6. 为什么 AIOps payload scope 先用 Prompt + Rule
真实告警环境里可能同时有多个 active alerts。用户传入 `HighCPUUsage/payment-service` 时,Agent 如果把所有告警都展开分析,报告会跑偏。
当前选择:
- Prompt 中加入 `PAYLOAD_TARGETED`。
- 从 payload 生成 recommended `lookup_knowledge` query。
- 用 `AiOpsRuleEvaluationService` 检查报告是否聚焦输入告警。
没有先做硬过滤,是因为有些相关告警可以作为风险背景。目标不是屏蔽上下文,而是控制主诊断对象。
## 7. 为什么反馈不改 status
`status` 表示执行状态,`feedback` 表示用户评价。一个执行成功但用户觉得没用的诊断,应该是:
```text
status = SUCCESS
feedback = not_useful
```
这样才能区分系统异常和质量问题。`useful` 反馈会沉淀 `case_library`,`not_useful` 作为 bad case 信号保留。
## 8. 可以主动承认的限制
- AIOps 还没有完整 LLM Verifier。
- RAG 还没有 hybrid search、rerank、邻居 chunk 扩展。
- `case_library` 的 rootCause/solution 仍需要结构化抽取。
- `tool_invocation.step_id` 关联还可以更严格。
- `mvp-demo` profile 使用 mock 日志和指标,主要服务稳定面试演示。
主动讲清这些限制,能体现工程判断:先把可追踪闭环打通,再逐步增强质量门和生产可靠性。
@@ -0,0 +1,91 @@
# RAG Breadcrumb Embedding 验收说明
## 1. 改动是什么
索引路径现在构造 embedding 文本时,不只使用 chunk 内容,还会把结构上下文拼进去:
```text
Title: {title}
Path: {breadcrumb}
Content:
{content}
```
Milvus 中存储的 `content` 字段仍然保留原始 chunk 内容。这样展示和证据输出保持干净,而向量本身携带章节语义。
## 2. 为什么必须重新索引
Embedding 是索引时物化的。已有向量是用旧的 content-only 文本生成的,所以只有代码变化并不会改变线上检索结果。
验收关键点:
```text
只改代码 != live retrieval 已变化
代码改动 + 重新索引 + live query report = 行为验收完成
```
## 3. 如何验证
1. 启动 Spring Boot 应用。
2. 通过现有索引路径重新索引知识库。
3. 运行:
```bash
python scripts/eval_rag_live_acceptance.py
```
脚本输出:
```text
eval/rag-retrieval/reports/live-post-reindex.json
eval/rag-retrieval/reports/live-post-reindex.md
```
默认覆盖:
- breadcrumb 敏感的 RAG chunk context query。
- 需要章节路径的诊断流程问题。
- `ERR_TIMEOUT` 精确错误码检索。
- MySQL 连接池排障。
- AIOps payment-service 延迟告警检索。
## 4. 看什么结果
对 breadcrumb 敏感 case:
- top candidates 是否暴露预期 `title`。
- top candidates 是否暴露预期 `breadcrumb`。
- 命中内容是否能看出所属章节。
对核心排障 case:
- 结果数量是否稳定。
- top candidates 是否仍然命中核心文档。
- 没有因为拼接 title/breadcrumb 导致核心检索退化。
## 5. 面试回答
如果被问:你怎么验证 breadcrumb 参与 embedding 后真的生效?
```text
我把 deterministic regression 和 live acceptance 分开。
离线 fixture baseline 不依赖服务,可以做稳定回归。
但 embedding 改动只会影响新生成的向量,所以我另外加了 live post-reindex acceptance 脚本。
脚本会调用真实 /api/search/similar,对 breadcrumb 敏感、排障和 AIOps query 生成 JSON/Markdown 报告。
这样能证明代码改了,也能证明 live vector collection 已经刷新。
```
如果被问:为什么脚本不自动 reindex?
```text
reindex 会修改向量库,而且依赖环境中的知识库数据。
我把 reindex 保持为显式动作,验收脚本只做读取验证。
这样如果检索没有改善,我能区分是代码问题、索引未刷新,还是运行时检索行为问题。
```
## 6. 后续增强
- 将 live acceptance 结果加入面试 Demo 输出。
- 增加 breadcrumb hit rate 统计。
- 对同章节 chunk 做邻居扩展,进一步利用 breadcrumb。
@@ -0,0 +1,127 @@
# RAG 重构故事
## 1. 起点
原始 RAG 实现已经能支撑 MVP:
- 文档可以上传、切片、向量化,并写入 Milvus/Zilliz。
- Agent 可以显式调用 `lookup_knowledge`。
- AIOps 诊断能在告警流程里检索排障知识。
- 工具调用会落到 `tool_invocation`,检索步骤可见。
但它有几个工程问题:
- 检索实现过于依赖 Milvus SDK,业务代码承担了太多底层搜索细节。
- L0 和 L1 职责不清,L0 关键词命中容易被当作最终召回决策。
- chunk 级检索容易丢失章节上下文。
- `breadcrumb` 存在 metadata 中,但没有充分参与 embedding、filter 和上下文重建。
- 检索质量主要靠手工接口和日志判断,缺少可重复的 golden cases。
所以重构目标不是“全盘替换成框架”,而是:
```text
通用 RAG 基础设施交给 Spring AI,
业务可观测链路保留在项目里。
```
## 2. 我如何拆解问题
我把迁移拆成几个阶段,因为 RAG 同时影响 Agent 工具层、AIOps、向量检索、证据打包和 Trace。
第一步是建立 baseline。`eval/rag-retrieval/` 中的 golden cases 用来对比后续改动,而不是只靠直觉判断检索有没有变好。
第二步是明确职责:
```text
L0 = domain/entity hint
L1 = semantic retrieval
postprocess = evidence shaping + trace-friendly output
```
L0 仍然有价值,但不再默认绕过语义检索。它更适合提取服务名、告警名、错误码、领域和 metadata filter。
第三步是增强 evidence 输出。Agent 不应该只拿到 raw chunk,而应该拿到带 source、title、breadcrumb、score、hit reason 的证据块。
最后,我把 Spring AI `VectorStore` 接入为读取主路径,同时保留原 Milvus SDK 作为 fallback。
## 3. 当前架构
```text
Agent / API
-> lookup_knowledge or /api/search/similar
-> L0 domain/entity hint
-> VectorSearchService
-> Spring AI VectorStore
-> Milvus SDK fallback
-> relevance normalization
-> tool_invocation trace
```
`VectorSearchService` 仍然是公共检索门面。Agent 工具层不需要知道底层是 SDK 还是 Spring AI。
支持三种模式:
```text
auto -> 优先 Spring AI VectorStore,失败后 fallback 到 SDK
spring-ai -> 强制 Spring AI VectorStore
sdk -> 强制 Milvus SDK
```
## 4. 关键取舍
### 保留显式工具
我没有把检索藏进 Spring AI Advisor。原因是这个项目强调 Agent 执行可见性:`lookup_knowledge` 的 query、命中文档、相关性和证据预览都要进入 Trace。
### 保留 SDK fallback
SDK fallback 不是废代码,而是迁移安全网。实际验证时,第一次 VectorStore 指向了错误 collection,`auto` 模式 fallback 到 SDK 后仍能返回结果。修正 collection 后,Spring AI 路径成为主路径。
### L0 降权
生产事故中经常有精确标识:错误码、告警名、服务名、指标名。L0 适合做 hint,但不应该做最终裁判。
### 分数语义拆开
SDK 使用 L2 distance,Spring AI 暴露 similarity。混在一个字段里会让 relevance normalization 出错。
当前拆成:
```text
score -> 兼容旧逻辑的距离型分数
rawScore -> 底层原始分数
scoreLabel -> rawScore 的语义
```
### 暂不迁移写入
写入和索引仍走 SDK。这是有意分阶段:先验证读路径,再评估 `VectorStore.add(...)` 是否适合现有 metadata 和 chunk 模型。
## 5. 验证方式
我用了三层验证:
- 单元测试:SDK mode、Spring AI mode、auto fallback、category filter、distance metadata mapping。
- Live API:`GET /api/search/similar?query=ERR_TIMEOUT&topK=3`。
- 代表性 query 对比:错误码、支付超时、MySQL 连接池、AIOps 告警式 query、抽象 RAG 设计问题。
核心排障和 AIOps query 在 SDK 与 VectorStore 下 top3 一致。差异主要集中在抽象设计类问题和 metadata taxonomy,这些被记录为后续质量工作。
## 6. 面试短版
```text
这个 RAG 系统最初是基于 Milvus SDK 的自研 MVP。它能跑,但底层检索细节过多地散落在业务代码里,L0/L1 职责也不够清晰。
我按阶段重构:先加 retrieval baseline,再把 L0 降级为 domain/entity hint,再增强 evidence postprocess,最后把读取主路径切到 Spring AI VectorStore,并保留 SDK fallback。
我没有把 lookup_knowledge 替换成隐式 Advisor,因为这个项目的核心是可追踪 Agent:面试官可以看到什么时候检索、检索了什么、证据如何支撑诊断。
```
## 7. 可主动承认的不足
- metadata taxonomy 还需要清理,例如 `database` 与 `infrastructure`。
- 抽象设计问题可能需要 query rewrite 或更好的文档索引。
- 邻居 chunk / 同章节上下文扩展还不完整。
- rerank、RRF、BM25、hybrid retrieval 还没有接入。
- 写入路径仍使用 SDK。
这些不是当前迁移阻塞项,而是后续检索质量优化方向。
@@ -0,0 +1,148 @@
# RAG 检索质量报告
## 1. 目的
这份报告回答一个面试关键问题:
```text
迁移到 Spring AI VectorStore 后,怎么证明检索质量没有退化?
```
这不是完整 benchmark,而是针对当前 Milvus/Zilliz collection 的代表性 live smoke comparison。
## 2. 验证设置
服务端点:
```text
GET http://127.0.0.1:9900/api/search/similar
```
collection:
```text
biz
```
对比模式:
```text
retrieval.vector-store.mode=sdk
retrieval.vector-store.mode=spring-ai
```
每个 case:
```text
topK=3
```
## 3. 测试案例
| Case | Query | 目的 |
|---|---|---|
| `err-timeout` | `ERR_TIMEOUT` | 精确错误码检索 |
| `payment-service-timeout` | `payment-service timeout` | 服务超时排障 |
| `mysql-connection-pool` | `MySQL connection pool is exhausted. How should I diagnose it?` | 数据库排障 |
| `high-cpu-payment` | `HighCPUUsage payment-service` | AIOps 告警式检索 |
| `rag-l0-l1` | `Should L0 keyword matching decide the final retrieval result?` | 抽象 RAG 设计问题 |
| `database-filter` | `mysql timeout`, category=`database` | metadata filter 行为 |
## 4. 对比摘要
| Case | SDK 数量 | VectorStore 数量 | Top1 一致 | TopK 重叠 | 结论 |
|---|---:|---:|---|---:|---|
| `err-timeout` | 3 | 3 | 是 | 3/3 | 文档和顺序一致 |
| `payment-service-timeout` | 3 | 3 | 是 | 3/3 | 文档和顺序一致 |
| `mysql-connection-pool` | 3 | 3 | 是 | 3/3 | 文档和顺序一致 |
| `high-cpu-payment` | 3 | 3 | 是 | 3/3 | AIOps 核心 query 一致 |
| `rag-l0-l1` | 3 | 1 | 是 | 1/3 | VectorStore 尾部结果更少 |
| `database-filter` | 0 | 0 | 不适用 | 不适用 | filter 行为一致,taxonomy 有问题 |
## 5. 代表性结果
### ERR_TIMEOUT
SDK:
```text
1. ERR_TIMEOUT score=0.5659486 label=l2_distance
2. ERR_GATEWAY_TIMEOUT score=0.6048740 label=l2_distance
3. Error handling score=0.7735061 label=l2_distance
```
VectorStore:
```text
1. ERR_TIMEOUT score=0.5659486 rawScore=0.4340513 label=similarity
2. ERR_GATEWAY_TIMEOUT score=0.6048740 rawScore=0.3951259 label=similarity
3. Error handling score=0.7735061 rawScore=0.2264938 label=similarity
```
解释:
- 排序一致。
- 兼容 `score` 与 SDK L2 distance 一致。
- `rawScore` 暴露 Spring AI similarity。
### MySQL connection pool
两条路径都返回:
```text
1. MySQL connection pool config
2. wait_timeout timeout
3. idle-timeout
```
说明迁移保留了核心基础设施排障检索能力。
### HighCPUUsage payment-service
两条路径都返回 payment-service 高 CPU 相关排障文档,说明 AIOps 告警式 query 没有退化。
### rag-l0-l1
VectorStore 只返回一个候选,但 Top1 与 SDK 一致。这说明抽象设计类 query 需要后续 query rewrite、补充索引或 threshold 调整。
### database-filter
两条路径都返回 0,因为相关 MySQL 文档当前分类是 `infrastructure`,不是 `database`。这是 metadata taxonomy 问题,不是 VectorStore 回归。
## 6. 分数兼容结论
对比验证了当前分数设计:
```text
SDK:
score = L2 distance
rawScore = L2 distance
scoreLabel = l2_distance
VectorStore:
score = Milvus metadata.distance
rawScore = Spring AI similarity
scoreLabel = similarity
```
这样既保持 `lookup_knowledge` 原有归一化逻辑,又能暴露 VectorStore 语义。
## 7. 验收结论
Spring AI VectorStore 读路径可以接受用于当前 MVP/面试:
- 核心排障和 AIOps case 与 SDK top3 一致。
- 分数兼容性保留。
- VectorStore 语义通过 `rawScore` 和 `scoreLabel` 可观察。
- SDK fallback 仍保留运行安全。
后续检索质量工作不阻塞这次迁移,应作为独立优化继续推进。
## 8. 下一步
- 增加自动 live comparison 脚本。
- 在 offline evaluator 中加入 topK overlap、top1 hit、MRR。
- 规范 metadata category,例如 `database` 与 `infrastructure`。
- 为抽象设计类 query 增加 query rewriting。
- 后续再评估是否迁移写入路径到 `VectorStore.add(...)`。
@@ -0,0 +1,119 @@
# RAG VectorStore 面试要点
## 1. 60 秒讲法
```text
我把 RAG 检索从 Milvus SDK-only 重构为 Spring AI VectorStore 主路径,同时保留 SDK fallback。
关键不是换了一个依赖,而是保留 VectorSearchService 作为边界,所以 lookup_knowledge 和 Agent workflow 不需要改。
现在支持 auto、spring-ai、sdk 三种模式。auto 会优先尝试 VectorStore,失败后 fallback 到 SDK。
```
现场验证时,第一次发现 VectorStore 指向了错误 collection:`business_knowledge`,而实际 Zilliz collection 是 `biz`。fallback 生效,所以系统仍能通过 SDK 返回结果。修正 collection 后,同一个 query 成功走 Spring AI VectorStore。
## 2. 架构回答
```text
Agent / API
-> lookup_knowledge or /api/search/similar
-> VectorSearchService
-> Spring AI VectorStore
-> Milvus SDK fallback
-> Milvus/Zilliz collection: biz
```
关键设计:`VectorSearchService` 是检索门面,避免 Spring AI 或 SDK 细节扩散到 Agent 工具层。
## 3. 为什么保留 SDK
- 迁移安全:原 SDK 路径已验证可用。
- 运行韧性:VectorStore schema、filter 或配置失败时,检索仍可用。
- Demo 稳定:检索抽象变化不应该破坏主诊断演示。
这在实际验证中发挥了作用:VectorStore 配置错时,`auto` 模式 fallback 到 SDK,API 没有失败。
## 4. 为什么引入 Spring AI VectorStore
使用 `VectorStore` 可以让项目更接近标准 RAG 抽象:
- 业务代码不再持有全部 Milvus search 细节。
- 后续 QueryTransformer、DocumentPostProcessor、Retriever 等能力更容易接入。
- 面试中也更容易解释和 Spring AI 生态的关系。
但我没有一次性迁移写入,因为读写同时迁移会让问题难定位。当前先稳定读路径。
## 5. 为什么保留 L0
L0 现在不是最终答案来源,而是确定性 hint 层:
- 提取 domain/entity。
- 在可能时生成 category filter。
- 给 trace 提供解释信号。
当前职责:
```text
L0 = domain/entity hint
L1 = semantic retrieval through VectorStore/SDK
postprocess = evidence trace + relevance normalization
```
真实故障诊断里有很多精确标识,完全只靠向量检索并不稳。
## 6. 为什么不用隐藏 Advisor
`lookup_knowledge` 保持显式工具,因为:
- Trace 要展示什么时候检索。
- `tool_invocation` 要记录输入、输出预览、相关性和 metadata。
- 面试故事是可审计 Agent 执行,而不只是答案质量。
Advisor 后续可以接入,但需要先解决可观测性。
## 7. 分数设计
当前结果故意拆成:
```text
score -> 兼容旧 relevance normalization 的分数
rawScore -> 当前检索实现原始分数
scoreLabel -> rawScore 的语义
```
SDK:
```text
score = L2 distance
rawScore = L2 distance
scoreLabel = l2_distance
```
VectorStore:
```text
score = metadata.distance if present
rawScore = Spring AI document score
scoreLabel = similarity
```
这样避免把 similarity 当成 L2 distance 的隐蔽 bug。
## 8. 如何证明 VectorStore 被使用
- 日志出现 `Starting Spring AI VectorStore search` 和 `Spring AI VectorStore search complete`。
- API 响应中 `scoreLabel=similarity`。
- `rawScore` 是 Spring AI similarity,`score` 仍是兼容 distance。
## 9. 常见追问
### 为什么不删 SDK?
这是迁移,不是重写。fallback 提供回滚安全,并且已经证明配置错误时仍能保证主链路可用。
### `lookup_knowledge` 变了吗?
外部契约没变。它仍然调用 `VectorSearchService.searchSimilarDocuments(...)`,变化在门面背后的实现。
### 这是完整 Spring AI RAG 了吗?
还不是。当前是 Spring AI VectorStore 读路径 + 显式工具 + 自定义 evidence trace + SDK 写入。这样做是为了保留审计能力和分阶段迁移安全。
@@ -0,0 +1,198 @@
# RAG VectorStore Live 验收说明
## 1. 目的
本文记录 RAG 检索重构的 live 验收结论。
这次重构的目标不只是接入 Spring AI 抽象,而是证明线上读路径能够:
- 优先使用 Spring AI `VectorStore` 做 Milvus 检索。
- 保留原 Milvus SDK 作为 fallback。
- 保持 `lookup_knowledge` 工具契约稳定。
- 保持基于 L2 distance 的相关性归一化兼容。
## 2. 当前检索形态
```text
lookup_knowledge / /api/search/similar
-> VectorSearchService.searchSimilarDocuments(...)
-> retrieval.vector-store.mode
-> auto
-> Spring AI VectorStore
-> VectorStore 失败时 fallback 到 Milvus SDK
-> spring-ai
-> 只走 Spring AI VectorStore
-> sdk
-> 只走 Milvus SDK
```
## 3. 已验证配置
live Milvus/Zilliz 数据库中存在 collection:
```text
biz
```
Spring AI VectorStore 配置与 SDK 使用的 collection 对齐:
```yaml
spring:
ai:
vectorstore:
type: milvus
milvus:
initialize-schema: false
database-name: ${milvus.database}
collection-name: biz
embedding-dimension: ${milvus.vector-dim}
metric-type: L2
id-field-name: id
content-field-name: content
metadata-field-name: metadata
embedding-field-name: vector
```
为什么重要:早期配置使用 `business_knowledge`,而真实 collection 是 `biz`。这个错配证明了 fallback 生效,但也说明修正前 VectorStore 不是成功主路径。
## 4. 验收命令
健康检查:
```powershell
Invoke-RestMethod `
-Uri "http://127.0.0.1:9900/milvus/health" `
-Method Get
```
期望:
```json
{
"collections": ["biz"],
"message": "ok"
}
```
直接检索:
```powershell
Invoke-RestMethod `
-Uri "http://127.0.0.1:9900/api/search/similar?query=ERR_TIMEOUT&topK=3" `
-Method Get
```
期望结果形态:
```json
{
"code": 200,
"message": "success",
"data": [
{
"content": "### ERR_TIMEOUT ...",
"score": 0.5662,
"rawScore": 0.4337,
"scoreLabel": "similarity",
"metadata": {
"distance": 0.5662,
"title": "ERR_TIMEOUT",
"category": "api"
}
}
]
}
```
## 5. 日志证明了什么
collection 修正前:
```text
Starting Spring AI VectorStore search
Spring AI VectorStore retrieval failed, falling back to Milvus SDK
Starting Milvus SDK search
```
collection 修正后:
```text
Starting Spring AI VectorStore search: query=ERR_TIMEOUT
Spring AI VectorStore search complete, candidates=3
```
这证明:
- `auto` 模式确实先尝试 VectorStore。
- VectorStore 失败时 fallback 可用。
- 配置对齐后,主路径是 Spring AI VectorStore,而不是 SDK fallback。
## 6. 分数语义
项目保留三个分数字段:
```text
rawScore -> 当前检索实现的原始分数
scoreLabel -> rawScore 的语义
score -> lookup relevance normalization 使用的兼容分数
```
SDK:
```text
rawScore = L2 distance
scoreLabel = l2_distance
score = L2 distance
```
Spring AI VectorStore:
```text
rawScore = Spring AI similarity score
scoreLabel = similarity
score = Milvus distance metadata when available
```
使用 `metadata.distance` 的原因:`LookupKnowledgeTool` 已经基于 L2 distance 做相关性归一化。Spring AI Milvus 主分数是 similarity,但 metadata 中仍有 Milvus distance。用 distance 保持旧逻辑稳定,同时通过 `rawScore` 暴露新语义。
## 7. 回归检查
目标测试:
```powershell
mvn -q "-Dtest=VectorSearchServiceTest,LookupKnowledgeToolTest" test
```
相关 spec:
```powershell
openspec.cmd validate rag-knowledge-retrieval --specs
openspec.cmd validate rag-retrieval-evaluation --specs
```
diff 检查:
```powershell
git diff --check
```
验收结论:
```text
目标测试通过。
相关 spec 通过。
diff-check 无错误。
```
## 8. 验收结论
VectorStore 读路径可以接受:
- Spring AI VectorStore 已集成,并在 `auto` 模式中优先使用。
- SDK fallback 保留且已被实际验证。
- live collection 配置与现有 Milvus collection 对齐。
- `lookup_knowledge` 对外契约保持稳定。
- 旧的 L2 relevance normalization 仍兼容。
写入和索引路径仍使用 Milvus SDK。这是有意的分阶段迁移,不是验收失败项。
@@ -0,0 +1,225 @@
# 面试故事案例
**用途**:把项目能力讲成可被面试官理解的工程故事
**使用方式**:按问题选择一个故事,不需要从头到尾背诵
## 故事 1:从黑盒 Chatbot 到可追踪 Agent
### 面试官问题
```text
这个项目和普通调用大模型有什么区别?
```
### 30 秒回答
```text
普通 Chatbot 只给最终答案,出了问题很难解释答案怎么来的。
我这个项目把诊断过程拆成 Planner、Executor、Verifier,并把每个 Agent 步骤和每次工具调用落库。
最后通过 Trace API 可以回放:模型怎么规划、调用了哪些工具、工具返回了什么证据、Verifier 怎么判断答案可信。
```
### 展开讲法
一开始最容易做的是:用户问题进来,直接让模型回答。但故障诊断场景不能只看答案,因为答案可能看起来合理却没有证据支撑。
所以我把系统拆成三层:
- `diagnosis_session` 记录一次诊断的主状态和最终答案。
- `agent_step` 记录 Planner、Executor、Verifier 的模型调用。
- `tool_invocation` 记录知识库、日志、指标等真实工具证据。
这样就能做到:答案不是孤立文本,而是一条可审计的执行链。
### 可展示文件
- `mvp/architecture/interview-one-pager.md`
- `mvp/architecture/session-trace-lifecycle.md`
- `mvp/demo/output/trace-response.json`
### 主动说不足
```text
当前 tool_invocation.step_id 还不是每次都强绑定具体 agent_step,后续可以加 runId 和更严格的 step 关联,让多轮同 session 诊断更清晰。
```
## 故事 2:RAG 从自研 SDK 检索迁移到 Spring AI VectorStore
### 面试官问题
```text
你的 RAG 是怎么设计的?为什么不用框架全包?
```
### 30 秒回答
```text
我把 RAG 分成两部分:通用检索基础设施尽量交给 Spring AI VectorStore,业务可观测链路留在项目里。
所以 Agent 仍然显式调用 lookup_knowledge,底层通过 VectorSearchService 走 Spring AI VectorStore,失败时 fallback 到原 Milvus SDK。
这样既能减少自研检索代码,又不会丢失工具调用 trace。
```
### 展开讲法
旧实现里,Milvus SDK 查询、topK、filter、score 映射都在业务代码里。它能跑,但后续扩展成本高。
我没有直接把 RAG 隐藏进 Advisor,因为这个项目的核心是 Agent 工程,需要知道 Agent 何时检索、检索了什么、证据怎么支撑诊断。
于是我保留了边界:
```text
Executor -> lookup_knowledge -> VectorSearchService -> VectorStore / SDK fallback
```
同时把 L0 从“直接返回结果”降级为 domain/entity hint,降低关键词误召回的风险。
### 可展示文件
- `mvp/architecture/rag-architecture.md`
- `mvp/architecture/retrieval-observability.md`
- `interview/rag-refactor-story.md`
### 主动说不足
```text
当前还没有完整 hybrid search 和 rerank。
我先做 golden cases、VectorStore 主路径和 SDK fallback,是为了让每一步迁移都能被验证。
```
## 故事 3:Verifier 如何降低幻觉风险
### 面试官问题
```text
Agent 怎么保证不胡说?
```
### 30 秒回答
```text
我没有假设模型天然可靠,而是加了 Verifier。
Executor 给出答案后,Verifier 只拿 executor_final_answer 和 tool_trace_summary,不允许做新检索。
它把答案里的关键事实逐条校验,输出 PASS、LOW_CONFID 或 REJECT。
这个结果会写回 self_evaluation,Trace API 可以看到。
```
### 展开讲法
Verifier 的关键不是再问一次模型“你觉得对吗”,而是让它基于真实工具调用做 groundedness 检查。
`ToolTraceSummaryService` 会从 `tool_invocation` 里整理证据索引,包含:
- 工具名。
- 输入摘要。
- 输出摘要。
- evidence level。
- source invocation ids。
Verifier 输出结构化 JSON,ChatService 根据 verdict 决定是否输出、补证据或降级。
### 可展示文件
- `mvp/architecture/harness-quality-gates.md`
- `mvp/architecture/feedback-architecture.md`
- `src/main/resources/prompts/chat-verifier-prompt.md`
### 主动说不足
```text
AIOps 当前还是轻量 rule evaluation,不是完整 LLM Verifier。
这是有意收敛:先用规则保证 payload 聚焦和工具证据使用,后续再加 AIOps LLM Verifier。
```
## 故事 4:AIOps 告警为什么要做 payload scope control
### 面试官问题
```text
AIOps 场景和普通 Chat 有什么区别?
```
### 30 秒回答
```text
AIOps 告警有一个很关键的问题:环境里可能同时有很多活跃告警,Agent 容易跑偏。
所以我把 AIOps 分成 PAYLOAD_TARGETED 和 AUTO_DISCOVERY。
如果请求带 alert payload,最终报告必须聚焦输入告警,并且会把 alertName、service、severity、description 拼成 recommended lookup_knowledge query。
```
### 展开讲法
没有 payload 时,Agent 可以先查询活跃告警,再选择目标排查。
但有 payload 时,用户已经告诉系统“我要查这个告警”。这时如果 Agent 把其他活跃告警写成主根因,产品体验会很差。
所以我做了两件事:
- Prompt 中明确 `PAYLOAD_TARGETED` 范围。
- `AiOpsRuleEvaluationService` 检查最终报告是否聚焦输入告警,以及是否使用证据工具。
### 可展示文件
- `mvp/architecture/agent-orchestration.md`
- `mvp/architecture/current-mvp-architecture.md`
- `interview/aiops-query-augmentation.md`
- `interview/aiops-lightweight-verifier.md`
### 主动说不足
```text
当前 scope control 主要靠 prompt 和规则评估。
后续可以把 AIOps 也接入类似 Chat Verifier 的事实校验,让告警报告的每个根因和建议都有 evidence refs。
```
## 故事 5:反馈不是点赞按钮,而是案例沉淀入口
### 面试官问题
```text
用户反馈在系统里有什么用?
```
### 30 秒回答
```text
反馈不只是前端按钮。
用户提交 useful 后,系统会把同一个 diagnosis_session 沉淀为 case_library。
not_useful 不会改执行状态,而是作为 bad case 信号保留。
这样 status、self_evaluation、feedback 三个维度是分开的。
```
### 展开讲法
我刻意没有把 `not_useful` 写成 `FAILED`。因为失败表示系统执行异常,而用户觉得不好用是质量标签。
当前设计里:
```text
status -> 执行是否成功
self_evaluation -> 系统自己判断证据和事实支撑度
feedback -> 用户是否认可
```
`useful` 会进入 `CaseLibraryService.createFromSession`,生成可复用案例。后续可以做相似案例推荐或高质量样本积累。
### 可展示文件
- `mvp/architecture/feedback-architecture.md`
- `mvp/architecture/data-model.md`
- `mvp/demo/output/feedback-response.json`
### 主动说不足
```text
当前 case_library 的 rootCause 和 solution 还直接使用完整 answer。
后续应该从报告中结构化抽取 rootCause、solution、errorCode 和 service,提高案例复用质量。
```
## 结尾万能总结
```text
这个项目我最想展示的不是某一个模型效果,而是 Agent 工程化能力:
一个诊断答案从哪里来、用了什么证据、是否被验证、用户是否认可、后续怎么沉淀和回归。
这些链路都被结构化记录下来,所以它可以继续演进,而不是一次性 demo。
```