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:
@@ -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。
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user