AgentOps 故障诊断平台:终极面试复习文档
AIOps 多 Agent 故障诊断项目的完整面试复习资料,覆盖 ReAct、Tool Calling、MCP、GraphRAG、Vector RAG、可观测性、审计链路、RAG 评估和模拟面试失败点复盘。
适用对象:docs/agent-resume.pdf 中第一项目 AgentOps 故障诊断平台。
目标:把简历里的高风险技术点整理成可背、可追问、可举例的面试答案。
0. 项目一句话介绍
AgentOps 是一个基于 Go / Gin + CloudWeGo Eino 的 AIOps 多 Agent 故障诊断平台。它把故障诊断拆成多证据源取证流程:Metrics Agent 查 Prometheus 指标,Log Agent 查 Loki 日志,Experience Agent 查 Neo4j 历史经验图谱、Milvus 文档向量库和 CodeGraph MCP 代码索引,最后由 Synthesizer 综合证据生成结构化 RCA 报告。
可背版本:
这个项目的核心是把故障诊断从单轮问答改成可审计的多 Agent 取证流程。第一轮 Metrics Agent 和 Log Agent 并发查当前运行时证据,Planner 根据 Evidence Board 决定是否进入 Experience Agent,Experience Agent 再查 GraphRAG、Vector RAG 和 CodeGraph MCP,最终 Synthesizer 结合所有证据输出 root cause、confidence、evidence 和建议动作。
1. 总体架构
1.1 诊断链路
用户创建 incident
→ API 写入 incident 并投递 Redis Stream 任务
→ Worker 消费任务
→ Orchestrator 启动诊断
→ Round 1: Metrics Agent + Log Agent 并发取证
→ Evidence Board 汇总第一轮证据
→ Planner 判断是否需要 Experience Agent
→ Round 2: Experience Agent 查历史经验 / 文档 / 代码定位
→ Synthesizer 综合证据生成 RCA
→ SSE 推送诊断进度
→ DB 保存 agent_steps 和 tool_calls 审计记录
1.1.1 纯 Agent 架构图
用户创建 incident
|
v
+-------------------+
| API (Gin) |
| POST /api/diag |
+-------------------+
|
v
+-------------------+
| Redis Stream |
| (任务队列) |
+-------------------+
|
v
+-------------------+
| Worker 进程 |
| (消费任务) |
+-------------------+
|
v
+----------------------------------------------------------+
| Orchestrator |
| |
| +------------+ +------------+ |
| | Planner | |Synthesizer | |
| | (调度决策) | | (最终裁决) | |
| +------------+ +------------+ |
| | ^ |
| | 决策是否进 R2 | 汇总所有证据 |
| v | |
| +====================================================+ |
| || Evidence Board || |
| || (跨 Agent 共享证据板: summary + evidence pointers)|| |
| +====================================================+ |
| | | |
| Round 1 Round 2 (条件触发) |
| (固定并行) | |
| / \ v |
| v v +------------------+ |
| +----+ +----+ | Experience Agent | |
| |Met | |Log | | (历史经验/文档/ | |
| |Agt | |Agt | | 代码定位) | |
| +----+ +----+ +------------------+ |
+============================================================+
| | | | |
v v v v v
+-------+ +-------+ +-------+ +--------+ +----------+
|PromQL | |LogQL | |Cypher | |向量检索 | |MCP tools |
|HTTP | |HTTP | |Neo4j | |Milvus | |codegraph |
|API | |API | |Driver | | | |serve |
+-------+ +-------+ +-------+ +--------+ +----------+
| | | | |
v v v v v
+---------+ +---------+ +---------+ +--------+ +----------+
|Promethe-| |Loki | |Neo4j | |Milvus | |CodeGraph |
|us | |(日志) | |(图谱) | |(向量库) | |(代码索引) |
|(指标) | +---------+ +---------+ +--------+ +----------+
+---------+
============================================================
审计层: agent_steps + tool_calls (PostgreSQL)
推送层: SSE events via Redis pub/sub
观测层: Grafana (人工验证)
============================================================
架构要点说明:
- Orchestrator 内部包含 Planner、Synthesizer 和 Evidence Board 三个核心组件
- Round 1 固定并行启动 Metrics Agent 和 Log Agent,两者互不依赖
- Round 2 由 Planner 根据 Evidence Board 判断是否触发,只有 Experience Agent 参与
- Evidence Board 是跨 Agent 共享的证据板,传 summary 给 Planner 和 Synthesizer
- 每个 Agent 只看到自己被授权的工具 schema(role-level tool filtering)
- 底层执行环境各异(HTTP API / 图数据库 / 向量库 / MCP),但统一封装为 Tool
- 审计、推送、观测三条旁路对 ReAct 主循环零影响
1.2 三类 Agent
| Agent | 证据源 | 工具 | 职责 |
|---|---|---|---|
| Metrics Agent | Prometheus 指标 | query_prometheus | 查延迟、QPS、错误率、资源指标 |
| Log Agent | Loki 日志 | query_loki | 查 error、timeout、panic、日志模式 |
| Experience Agent | Neo4j / Milvus / CodeGraph | query_graph, query_vector_rag, codegraph_* | 查历史案例、文档、代码路径 |
1.3 Planner 和 Synthesizer 边界
Planner 是调度器,只判断是否需要进入 Experience Agent。
Synthesizer 是最终裁决者,负责跨证据源融合、冲突消解、输出 root cause、confidence、evidence 和建议。
可背版本:
Planner 的职责是路由和调度。它根据 Round 1 的指标和日志证据判断是否需要追加历史经验检索。每个 Agent 是单一证据源专家,给局部判断;Synthesizer 是最终裁决者,负责把指标、日志、历史案例、文档和代码定位信息融合成结构化 RCA。
2. ReAct、Tool Calling、Eino 对象边界
2.1 ReAct 循环
正确结构:
Thought / Reasoning
→ Action / Tool Call
→ Observation
→ Thought / Reasoning
→ ...
→ Final Answer
可背版本:
ReAct 是模型边推理边调用工具的循环。模型先根据当前上下文判断需要什么证据,发出 tool call;工具执行后返回 observation;observation 回到下一轮模型上下文,模型继续 reasoning。证据足够时停止调用工具并输出 final answer。
2.2 Eino Tool
Eino Tool 最少需要两类能力:
Info():提供工具名、description、参数 schema。InvokableRun():收到 arguments 后执行真实系统调用,返回 observation。
可背版本:
Tool 是模型可调用的外部能力封装。Info 给模型看,让模型知道工具叫什么、能做什么、参数怎么填;Run/Invoke 给框架用,当模型生成 tool call 后,框架调用对应 Tool 执行真实系统操作并返回 observation。
2.3 ToolsNode
ToolsNode 是 ReAct 图里的工具执行节点。
输入:上一轮 ChatModel 输出的 assistant message,其中包含 tool_calls。
输出:tool role message,也就是工具执行结果。
可背版本:
ToolsNode 接收 ChatModel 输出的 tool_calls,按 tool name 找到对应 Tool,执行后把结果转成 tool message,供下一轮 ChatModel 继续推理。
2.4 ReAct Agent 为什么是图
ReAct Agent 内部有分支:
ChatModel 输出含 tool_calls → 进入 ToolsNode
ChatModel 输出不含 tool_calls → END
ToolsNode 执行完成 → 回到 ChatModel
达到 MaxStep → 结束或返回已有证据
可背版本:
ReAct Agent 本质是一个流程图。ChatModel 决定下一步是否调用工具;如果有 tool_calls 就分支到 ToolsNode,工具返回后再回到 ChatModel;如果没有 tool_calls 就结束输出 final。
3. Tool Calling 和普通 API 调用
3.1 区别
普通 API 调用:开发者在代码里提前写死调用时机和参数。
Tool Calling:模型根据上下文动态决定调用哪个工具、何时调用、填什么参数。
可背版本:
普通 API 调用是确定性流程,开发者提前决定查什么。Tool Calling 把证据收集策略交给模型在受限工具集合里动态决策。故障诊断是开放问题,模型需要根据上一轮 observation 调整下一步查询,所以适合 Tool Calling。
3.2 arguments 是什么
Tool call 的 arguments 通常是 JSON 字符串。自然语言可以作为 JSON 字段值存在。
例子:
{
"name": "query_prometheus",
"arguments": "{\"query\":\"rate(http_requests_total[5m])\"}"
}
3.3 Tool 安全边界
控制手段:
- role-level tool filtering
- 参数 schema
- handler 服务端校验
- timeout
- MaxStep
- 审计日志
- 最小权限工具集合
- 结果截断和结构化
可背版本:
我不会只靠 prompt 控制工具安全。prompt 是软约束,schema 是半约束,真正边界在后端:每个 Agent 只暴露最小必要工具集,handler 校验参数,工具有 timeout 和结果截断,ReAct 有 MaxStep,所有 tool call 都进入审计表。
AgentOps 项目终极面试复习文档(第二部分)
接 part1,继续 MCP / GraphRAG / RAG / 可观测性 / 审计 / 评估。
4. Tool schema 如何进入模型
4.1 本地 Tool
本地 Tool 通过 Info() 提供:
name
description
parameters schema
Eino 构建 ReAct Agent 时收集 ToolInfo,绑定到 ToolCallingModel。
4.2 MCP Tool
CodeGraph MCP 工具通过 tools/list 下发 schema。
流程:
codegraph serve --mcp
→ MCP tools/list
→ 返回 name / description / inputSchema
→ eino-ext mcp adapter 转成 schema.ToolInfo
→ appwire 按 role 过滤
→ react.NewAgent 绑定到 ToolCallingModel
→ LLM 请求携带 tools schema
可背版本:
在本项目里,Tool schema 由 ToolInfo 提供。本地工具的 ToolInfo 来自代码里的 Info 方法;CodeGraph MCP 工具的 ToolInfo 来自 MCP tools/list 返回的 inputSchema。Eino 在构建 ReAct Agent 时收集这些 ToolInfo,按角色过滤后绑定到 ToolCallingModel,所以每个 Agent 的 LLM 上下文里只包含它被允许使用的工具 schema。
5. MCP 接入 CodeGraph
5.1 为什么接 MCP
旧方式:每次用 CLI 跑 codegraph explore/node,schema 手写,参数维护在业务代码里。
新方式:启动 CodeGraph MCP server,通过 stdio JSON-RPC 通信。
codegraph serve --mcp --path <projectRoot>
核心收益:
- schema 自动跟随服务端,避免手写漂移
- 工具粒度更细,LLM 能独立选择 callers 而不是塞进一个 mode 参数
- 协议标准化,接其他 MCP server 只改启动命令
5.2 MCP 握手流程
Start:启动codegraph serve --mcp子进程,建立 stdin/stdout 管道。initialize:客户端发送协议版本、clientInfo、capabilities。- 服务端返回 protocolVersion、serverInfo、capabilities,其中
tools表示支持工具能力。 - 客户端发送
notifications/initialized。 - 后续发
tools/list和tools/call。
关键设计:
- 响应路由靠请求 id 匹配 response channel
- 通知和请求靠有无 id 区分
initialized标志位是 sendRequest 守卫的解锁条件- 握手前调任何方法会被拒绝
可背版本:
MCP 握手包括 Start、initialize 和 initialized notification。Start 负责启动 CodeGraph MCP 子进程并接管 stdin/stdout;initialize 用 JSON-RPC 协商协议版本和双方能力;服务端返回 capabilities.tools 后,客户端发送 notifications/initialized 表示会话就绪。之后可以调用 tools/list 获取工具 schema,调用 tools/call 执行工具。
5.3 CodeGraph MCP 工具
当前暴露 4 个工具:
codegraph_explore
codegraph_node
codegraph_callers
codegraph_search
| 工具 | 用途 |
|---|---|
codegraph_explore | 主用,一次性返回相关符号源码和调用路径 |
codegraph_node | 查看单个符号或文件 |
codegraph_callers | 查谁调用了某个符号 |
codegraph_search | 快速按名字定位符号 |
5.4 为什么只给 Experience Agent
Metrics Agent 专注 Prometheus 指标。
Log Agent 专注 Loki 日志。
CodeGraph 属于历史经验增强和代码定位工具,适合在已有可疑方向后使用,所以只给 Experience Agent。
可背版本:
我按证据源拆分 Agent。Metrics Agent 只查指标,Log Agent 只查日志,Experience Agent 查历史经验、文档和代码定位。CodeGraph 属于代码定位工具,给 Metrics/Log 会扩大工具集合、增加乱调工具概率,也会污染它们的职责边界。
6. GraphRAG 历史经验定位
6.1 图谱节点设计
| 节点 | 含义 | 关键字段 |
|---|---|---|
Service | 服务或依赖组件 | name, owner, language, endpoint |
Instance | 服务实例 | uid, host |
Metric | Prometheus 指标 | uid, kind, description |
LogEntry | 日志模式 | uid, level, msg |
CodePath | 代码路径 | uid, file, line |
IncidentCase | 历史故障案例 | id, title, severity, root_cause, created_at |
Runbook | 处置手册 | id, title, steps |
6.2 图谱关系设计
| 关系 | 含义 |
|---|---|
HAS_INSTANCE | 服务有哪些实例 |
EXPOSES_METRIC | 实例暴露哪些指标 |
EMITS_LOG | 实例出现哪些典型日志模式 |
RUNS | 实例运行哪些代码路径 |
CALLS | 服务依赖哪些下游服务 |
CORRELATES_WITH | 指标和历史故障相关 |
INDICATES | 日志模式指向历史故障 |
RESOLVED_BY | 历史故障由哪个 Runbook 解决 |
6.3 历史经验定位链路
当前服务
→ 服务实例
→ 指标 / 日志模式
→ 历史故障案例
→ Runbook
例子:
redcart-backend
→ redcart-backend-pod-0
→ redcart_http_request_duration_seconds
→ PG connection pool exhaustion during peak
→ PostgreSQL 连接池耗尽处置
可背版本:
GraphRAG 从当前 incident 的 service_name 出发,先找到服务实例,再沿着指标和日志模式找到相关历史 IncidentCase,最后通过 RESOLVED_BY 找到 Runbook。这样 Experience Agent 拿到的是一条可解释的历史经验路径,而不是孤立文本片段。
6.4 Cypher 设计
分三类查询:
第一类:查服务实例、指标、代码路径。
MATCH (s:Service {name: $svc})-[:HAS_INSTANCE]->(i:Instance)-[:EXPOSES_METRIC]->(m:Metric)
OPTIONAL MATCH (i)-[:RUNS]->(c:CodePath)
RETURN metric, codepath, instance
第二类:查历史案例和 Runbook。
MATCH (s:Service {name: $svc})-[:HAS_INSTANCE]->(i:Instance)
OPTIONAL MATCH (i)-[:EMITS_LOG]->(l:LogEntry)-[:INDICATES]->(ic:IncidentCase)
OPTIONAL MATCH (i)-[:EXPOSES_METRIC]->(m:Metric)-[:CORRELATES_WITH]->(ic2:IncidentCase)
OPTIONAL MATCH (ic)-[:RESOLVED_BY]->(r:Runbook)
OPTIONAL MATCH (ic2)-[:RESOLVED_BY]->(r2:Runbook)
RETURN cases, runbooks
第三类:查依赖服务。
MATCH (s:Service {name: $svc})-[:CALLS]->(dep:Service)
RETURN dep
为什么拆开:
- 职责清晰
- 返回结构稳定
- 避免一条大查询造成组合爆炸
- 后续可以单独优化历史案例排序
6.5 边权重设计
边可以有属性:weight、rank、support_count、reason、last_seen_at、success_rate、criticality。
适合加权的边:
| 边 | 建议属性 |
|---|---|
Metric - CORRELATES_WITH -> IncidentCase | weight, support_count, reason, last_seen_at |
LogEntry - INDICATES -> IncidentCase | weight, support_count, pattern_confidence |
IncidentCase - RESOLVED_BY -> Runbook | rank, success_rate, verified_at |
Service - CALLS -> Service | criticality, timeout_ms, weight |
次数转权重公式:
score = α * log(1 + support_count)
+ β * type_bias
+ γ * severity_bias
+ δ * recency_bias
+ η * runtime_evidence_boost
weight = softmax(score / T)
注意:
- 先用
log(1 + count)压缩长尾 - 在同一源节点、同一关系类型下做 softmax
- 不同关系类型不要混在一起归一化
- rank 表示人工顺序,weight 表示相关性强弱
- 工程上很多场景直接用 score 排序就够,softmax 主要用于需要概率解释时
可背版本:
边上的次数不能直接当权重。我会先做 log 压缩,再加边类型、severity、新鲜度和当前运行时证据 boost,最后在同源同类型边内做 softmax。不同关系类型不要混归一化。weight 表示相关性,rank 表示顺序。
AgentOps 项目终极面试复习文档(第三部分)
接 part2,继续 RAG / 可观测性 / 审计 / 评估 / 高危追问。
7. Vector RAG 和 Embedding
7.1 Vector RAG 完整链路
离线:
RedCart README / 架构文档 / OpenAPI / Runbook / 代码知识块
→ 清洗
→ 语义分块
→ fastembed-go + ONNX Runtime 生成 embedding
→ Milvus 存储
在线:
Experience Agent 生成 query
→ Milvus topK 检索
→ 过滤 / 去重 / rerank
→ 返回文档证据给 Synthesizer
可背版本:
Vector RAG 解决非结构化文档的语义召回。离线阶段把 RedCart 文档分块、本地 embedding、写入 Milvus;在线阶段根据故障 query 做 topK 检索,再经过过滤、去重和 rerank,返回文档证据。
7.2 GraphRAG 和 Vector RAG 互补
| 通道 | 擅长 | 不擅长 |
|---|---|---|
| Vector RAG | 文档语义召回、长尾知识、新文档快速入库 | 关系推理、多跳路径 |
| GraphRAG | 结构化关系、历史案例、多跳查询 | 覆盖所有文档细节、建图成本高 |
可背版本:
Vector RAG 负责非结构化文档的语义召回,GraphRAG 负责结构化关系和历史经验多跳推理。故障诊断里既需要查文档机制,也需要沿服务依赖、指标、日志模式、历史案例和 Runbook 做关系推理。只做向量会缺少关系约束,只做图谱会覆盖不完整、建图成本高,所以我用双通道互补。
7.3 为什么本地 embedding
- 数据安全:内部文档、故障 case、代码知识块不出本地。
- 成本可控:批量 embedding 不用一直调外部 API。
- 离线可运行:demo / 内网 / 本地开发不依赖公网。
- 延迟稳定:本地推理不受外部 API 限流和网络影响。
可背版本:
我选 fastembed-go + ONNX Runtime 做本地 embedding,是为了数据不出本地、成本可控、离线可运行和延迟稳定。AIOps 里会处理内部架构文档、历史故障和代码知识块,发送到外部 embedding API 有安全和成本风险。
7.4 文档分块策略
| 策略 | 原理 | 适用 |
|---|---|---|
| 固定大小 | 按固定 token 切 | 通用 |
| 滑动窗口 | 固定大小 + overlap | 长文档 |
| 语义分块 | 按句子/段落边界 | 高质量 |
| 递归切分 | 先段落,超长再句子 | 技术手册 |
chunk 太小:语义残缺,召回碎片。
chunk 太大:多主题混合,embedding 语义变稀,污染上下文。
常见经验值:512 tokens / 64 overlap。
Small-to-Big:检索匹配子块,喂模型时带父章节上下文。
可背版本:
我优先按语义结构切,比如标题、段落、API 小节、Runbook 步骤,并控制 chunk size 和 overlap。chunk 太小会语义残缺,太大会把多个主题混在一起。对于 Runbook 或 API 文档,可以考虑 Small-to-Big:检索匹配子块,喂给模型时带父章节上下文。
7.5 Milvus metadata
不能只存 vector。应存:
chunk_id
source_path
title
heading
doc_type
service_name
chunk_index
content
embedding_model
model_version
hash
created_at / updated_at
用途:过滤、回溯、去重、增量更新、证据展示、模型升级追踪。
可背版本:
Milvus 里除了 vector,还要存 chunk 原文和 metadata,包括 source_path、title、heading、doc_type、service_name、chunk_index、hash、embedding_model、model_version 和更新时间。它们用于过滤、回溯、去重、增量更新和最终 RCA 证据展示。
7.6 Embedding 模型升级
不同 embedding 模型的向量空间不一致,维度和分布都可能不同,不能混用。
生产上要记录 embedding_model 和 model_version,升级时双写新旧 collection,验证后切流。
可背版本:
Embedding 模型升级后,历史向量需要重建或单独建新 collection。不同模型的向量空间不一致,混用会导致相似度不可比。生产上要在 metadata 里记录 embedding_model 和 model_version,升级时可以双写,验证后切流。
7.7 Tokenizer / Embedding / Rerank 区别
- Tokenizer:把文本切成 token id,只是输入预处理,不理解语义。
- Embedding:把文本编码成稠密向量,用于相似度检索。内部会用到 tokenizer。
- Rerank:对 query 和候选 chunk 成对输入模型,直接输出相关性分数。精度更高但更慢。
可背版本:
Tokenizer 只是把文本变成 token id,不等于 embedding 或 rerank。Embedding 是把文本语义压缩成向量做粗召回。Rerank 是对候选结果做二次精排,判断 query 和 chunk 的匹配程度。
8. topK 和 Rerank
8.1 topK 怎么选
K 太小:漏召回,复杂问题只看到局部。
K 太大:噪声多,相似但无关的 chunk 混进来,上下文成本高。
默认 5 左右;复杂问题先取 20-50,再 rerank 到 3-5。
8.2 两阶段检索
Query
→ 向量检索 Top-50(粗召回)
→ Rerank 重排(精排)
→ 取 Top-5 给 LLM
8.3 Rerank 方法
从简单到复杂:
- 规则 rerank:score threshold、service_name 过滤、doc_type 加权、source 去重、相邻 chunk 合并。
- 模型 rerank:Cross-Encoder、bge-reranker、ColBERT、LLM rerank。
Cross-Encoder 把 query 和 chunk 一起输入模型打相关性分,精度比单独 embedding 相似度高,但慢,所以只对粗召回后的几十个候选做。
可背版本:
Milvus topK 是粗召回,不直接等于证据。生产上做两阶段检索:先召回 Top-20 或 Top-50,再用规则或 reranker 模型重新排序,最后取 Top-3 或 Top-5 给 LLM。规则 rerank 包括 score threshold、服务名匹配、文档类型加权、source 去重和相邻 chunk 合并;模型 rerank 可以用 bge-reranker 或 cross-encoder。
8.4 混合检索(可选扩展)
当前项目主要 Vector + Graph。生产上可增加 BM25 或全文检索。
融合方法:
- RRF(Reciprocal Rank Fusion):按排名融合,不需要归一化分数。
- 线性加权:
score = w1 * bm25_score + w2 * vector_score。
可背版本:
当前项目主要是 Milvus 向量检索 + Neo4j GraphRAG。BM25 混合检索我没有作为主链路落地,但从生产角度看,技术文档里有接口名、错误码、配置项这类精确词,纯向量可能漏召。后续可以增加 BM25,再用 RRF 把 BM25 排名和向量排名融合。
9. 证据融合和幻觉控制
9.1 证据权重
| 类型 | 权重 |
|---|---|
| Prometheus 当前指标 | 最高 |
| Loki 当前日志 | 最高 |
| Neo4j 历史案例 | 中高 |
| Milvus 文档 chunk | 中 |
| CodeGraph 代码定位 | 中低 |
9.2 冲突处理
如果 Vector RAG 召回”库存锁可能导致下单慢”,但 Prometheus 没有 DB wait,Loki 没有 lock timeout:
- 不能直接定库存锁根因。
- 作为低置信度候选路径。
- 建议补查库存锁相关指标或日志。
可背版本:
Prometheus 和 Loki 是当前运行时证据,权重最高;GraphRAG 历史案例和 Vector RAG 文档证据主要用于解释机制和提高置信度。RAG 召回到某个机制时,必须看当前指标和日志是否支持。没有运行时证据支撑时,只能作为候选方向,不能直接定 root cause。
9.3 幻觉控制四层
- Prompt 层:先调工具取证,无证据不下结论,根因必须引用 evidence。
- Tool 层:提供结构化 evidence,每条带 source 和类型。
- Synthesizer 层:root cause 至少有一条当前运行时证据支撑,历史和文档只做置信度加权。
- 审计层:保存 tool call request/response,最终 RCA 可回放。
可背版本:
我从 prompt、tool、synthesizer 和审计四层控制幻觉。prompt 要求先取证再下结论;tool 提供结构化 evidence;Synthesizer 要求 root cause 至少有当前运行时证据支撑;callback 审计保存 tool call request/response,方便回放判断是不是证据错、参数错或模型解释错。
10. 可观测性:Prometheus / Loki / Grafana
10.1 三者分工
| 组件 | 职责 | 查询语言 |
|---|---|---|
| Prometheus | 采集和存储指标,pull /metrics | PromQL |
| Loki | 存储日志,Promtail 推日志 | LogQL |
| Grafana | 统一展示和查询入口 | - |
10.2 PromQL 常见写法
当前请求总量:
redcart_http_requests_total
5 分钟请求速率(QPS):
rate(redcart_http_requests_total[5m])
按接口聚合 QPS:
sum(rate(redcart_http_requests_total[5m])) by (path)
错误率:
sum(rate(redcart_http_requests_total{status=~"5.."}[5m]))
/
sum(rate(redcart_http_requests_total[5m]))
P99 延迟:
histogram_quantile(
0.99,
sum(rate(redcart_http_request_duration_seconds_bucket[5m])) by (le, path)
)
10.3 LogQL 常见写法
查 redcart 所有日志:
{job="redcart"}
查包含 error 的日志:
{job="redcart"} |= "error"
统计最近 5 分钟 error 日志数量:
count_over_time({job="redcart"} |= "error" [5m])
日志量频率:
rate({job="redcart"}[5m])
10.4 Grafana 接入
添加两个 datasource:
- Prometheus:
http://127.0.0.1:9090 - Loki:
http://127.0.0.1:3100
工程化用 provisioning YAML 固化 datasource 和 dashboard。
10.5 Agent 和 Grafana 的关系
Agent 不通过 Grafana 查询,而是直接封装 Prometheus 和 Loki 的 HTTP API 作为 Tool。
Grafana 用于人工观测和验证,Agent Tool 用于自动化取证。
可背版本:
Prometheus 存指标,用 PromQL 查,比如 rate 看 QPS、histogram_quantile 看 P99。Loki 存日志,用 LogQL 查,比如
{job="redcart"} |= "error"查错误日志。Grafana 接 Prometheus 和 Loki 两个 datasource 做人工观测。Agent 不通过 Grafana,而是直接封装 Prometheus/Loki HTTP API 作为 Tool 自动取证。
11. SSE 诊断流
11.1 为什么选 SSE
- 单向:后端到前端的进度推送,前端只需要接收。
- HTTP 友好:基于普通 HTTP,浏览器原生 EventSource。
- 自动重连:EventSource 默认断线重连。
- 部署简单:鉴权和代理比 WebSocket 简单。
11.2 推什么
高层 agent event:plan、planner_decision、agent_start、agent_done、final。
不推完整 tool call 细节。tool call 的 request/response/status 进审计表,前端按需拉取。
11.3 断线处理
EventSource 自动重连。断线期间漏掉的事件靠前端重新拉 incident detail 补齐。
更完整可给 SSE event 加 id,用 Last-Event-ID 做断点续传。
11.4 取消诊断
另设 HTTP cancel endpoint,修改 incident 状态,通过 context cancellation 通知 worker/orchestrator 停止。SSE 只推 cancelled 事件。
可背版本:
我选 SSE 是因为诊断流是后端到前端的单向进度推送。SSE 基于 HTTP,浏览器原生 EventSource,支持自动重连。实时流只推高层 agent event,完整 tool call 细节进审计表。如果用户要取消诊断,另设 HTTP cancel endpoint,通过 context cancellation 停止 orchestrator。
12. Eino Callback 审计
12.1 thought / action / observation
- thought:模型当前一轮的推理摘要和工具选择。
- action:模型发出的 tool call,包括工具名和参数。
- observation:工具执行后的返回结果,作为下一轮模型输入。
12.2 为什么保存中间 tool call
- 审计:知道模型查了什么、参数是什么、返回了什么。
- 复盘:RCA 错了时回看哪一步被带偏。
- 可解释:最终报告结论可追溯到具体指标、日志、图谱路径、文档 chunk。
- 调试:发现重复查询、参数错误、schema 误导。
12.3 tool_calls 表字段
incident_id
agent_name
tool_name
request(JSON)
response(JSON)
status
error
latency_ms
created_at
request 和 response 都要存:request 表示模型调用意图,response 表示外部系统返回证据,两者一起才能复现一轮工具调用。
12.4 callback 写库失败
不应该中断诊断。callback 是观测链路,不是控制流。
失败原因:PostgreSQL 不可用、连接池满、写入超时、JSONB 格式不合法、字段过长、并发写压力、迁移未执行。
处理:normalize JSON、截断长内容、记录日志,主流程继续返回 RCA。
可背版本:
callback 写库失败不应该中断诊断,因为它是观测链路。失败可能来自数据库不可用、连接池满、写入超时、JSONB 格式问题、字段过长或迁移未执行。处理上我会 normalize JSON、截断长内容、记录日志,主流程继续输出诊断报告。
13. RAG 评估指标
13.1 检索层
| 指标 | 含义 |
|---|---|
| Recall@K | 正确文档是否在 TopK 里 |
| Precision@K | TopK 里有多少真相关 |
| MRR | 正确结果排名越靠前越好 |
| NDCG | 排名质量,考虑相关性等级 |
13.2 生成层
| 指标 | 含义 |
|---|---|
| Faithfulness | 答案是否忠于检索材料 |
| Answer Relevance | 答案是否回答问题 |
| Context Relevance | 检索上下文是否相关 |
13.3 AIOps 端到端
- root cause 命中率
- 证据引用正确率
- 修复建议可执行性
- tool call 质量:是否调用必要工具、是否重复无效查询、是否证据不足时强行下结论
可背版本:
我会分层评估。检索层看 Recall@K、MRR、Precision@K;生成层看 Faithfulness、Answer Relevance、Context Relevance;AIOps 端到端看 root cause 命中率、证据引用正确率、修复建议可执行性和 tool call 质量。
14. 高危追问速答
Q: RAG 能彻底解决幻觉吗?
不能。RAG 缓解幻觉的局限性在于:检索结果可能不准确、LLM 可能无视检索结果凭内部知识回答、对检索结果做了错误推理。需要多层防控:prompt 约束、结构化 evidence、Synthesizer 权重裁决、审计回放。
Q: 检索不到内容时怎么办?
核心是”不知道就说不知道”。判断阈值,明确告知用户,引导换种问法。硬答比答不上更致命。
Q: 如果 Metrics 说是 DB 慢,Log 没有错误,Experience 查到库存锁历史案例,Synthesizer 怎么裁决?
以当前运行时证据为最高权重。DB 慢是当前事实;Log 无错误只表示没有明显 error pattern;库存锁历史案例是候选方向,需要当前 lock timeout、DB wait 或库存锁指标支撑。缺少当前证据时,库存锁只能作为低置信度疑点。
Q: Evidence Board 存什么?
在线推理传 summary 保持上下文干净;完整 tool call 的 request/response/status 落库。更好的结构是 summary + evidence pointers,既控制 token,又能追溯原始证据。
Q: 怎么防止 LLM 乱调工具、无限循环?
role-level tool filtering 限制工具集合;schema 和 handler 校验参数;MaxStep 防止无限循环;timeout 防止单次工具卡死;审计表记录所有 tool call 方便复盘。
Q: 你的项目和普通 RAG Chatbot 有什么区别?
普通 RAG Chatbot 是用户一问就固定跑一次检索。我的项目是 Agentic RAG:检索能力封装为 Tool,由 ReAct Agent 根据当前 observation 决定是否调用。Planner 根据 Evidence Board 决定是否触发 Experience Agent,多 Agent 按证据源分工,Synthesizer 做跨证据源裁决。
15. 必背 5 段
1. 30 秒项目介绍
AgentOps 是基于 Go / Gin + CloudWeGo Eino 的 AIOps 多 Agent 故障诊断平台。第一轮 Metrics Agent 和 Log Agent 并发查 Prometheus 指标和 Loki 日志,Planner 根据 Evidence Board 决定是否进入 Experience Agent,Experience Agent 查 Neo4j 历史经验图谱、Milvus 文档向量库和 CodeGraph MCP 代码索引,最后 Synthesizer 综合所有证据输出结构化 RCA。
2. ReAct + Tool Calling
ReAct 是模型边推理边调用工具的循环:Thought → Action → Observation → Thought → … → Final。Tool 至少提供 Info 和 Run 两类能力。ToolsNode 接收 ChatModel 的 tool_calls,执行后把结果转成 tool message 回到下一轮。ReAct Agent 本质是图,因为有分支:有 tool_calls 进 ToolsNode,没有就 END。
3. GraphRAG + Vector RAG
Vector RAG 解决非结构化文档的语义召回,GraphRAG 解决结构化关系和历史经验多跳推理。只做向量会缺少关系约束,只做图谱会覆盖不完整、建图成本高。双通道让文档语义和关系路径互补。冲突时以 Prometheus/Loki 当前运行时证据为最高权重。
4. Milvus metadata + topK/rerank
Milvus 里除了 vector,还要存 chunk 原文和 metadata,包括 source_path、doc_type、service_name、embedding_model、model_version。topK 是粗召回,生产上做两阶段检索:先召回 Top-20 或 Top-50,再按 score threshold、metadata 过滤、source 去重、rerank 取 Top-3 或 Top-5 给 LLM。
5. MCP 接入 CodeGraph
旧方式是每次 exec CLI,schema 手写。MCP 接入是启动 codegraph serve —mcp,通过 stdio JSON-RPC 握手:Start 子进程、initialize、服务端返回 capabilities.tools、发送 notifications/initialized。之后 tools/list 自动拿到 4 个 codegraph 工具的 name、description、inputSchema,eino-ext 把 inputSchema 转成 ToolInfo,Experience Agent 拿到这些工具 schema。
16. 模拟面试失败点复盘
以下是你模拟面试时具体卡住或答错的点,每条标注”你当时怎么答”和”面试安全版”。
16.1 ReAct 少了 Observation
你当时答:Reasoning -> Action。
问题:少了工具返回后的 Observation,闭环不完整。
面试安全版:
ReAct 是 Thought/Reasoning -> Action/Tool Call -> Observation -> Reasoning -> … -> Final。模型先判断需要什么证据,发 tool call;工具返回 observation 后进入下一轮上下文。证据足够时停止工具调用,输出 final answer。
16.2 Eino Tool 答成 read/write
你当时答:Tool 至少要提供 read 和 write。
问题:这是文件系统 Backend 思路,不是 Eino Tool 抽象。
面试安全版:
Eino Tool 至少要提供两类能力:Info 和 Run/Invoke。Info 给模型看工具名、description、参数 schema;Run/Invoke 给框架用,在收到 tool call 后执行真实系统调用并返回 observation。
16.3 ToolsNode 职责答泛了
你当时答:Node 可以是 chat 节点,或者工具调用。
问题:这是 Graph node 的泛化说法,没回答 ToolsNode 这个具体节点。
面试安全版:
ToolsNode 是工具执行节点。它接收 ChatModel 输出的 tool_calls,按 tool name 找到对应 Tool,执行后把结果转成 tool role message,供下一轮 ChatModel 继续推理。
16.4 arguments 答成”可以自然语言”
你当时答:arguments 看软件设计,主 agent 唤醒子 agent 时传自然语言也行。
问题:Tool Calling 协议层 arguments 通常是 JSON 字符串。自然语言可以作为 JSON 字段值存在,但外层仍是结构化参数。
面试安全版:
Tool call 至少包含 tool name 和 arguments。arguments 通常是 JSON 字符串,由模型按 schema 填充。即使是唤醒子 Agent,也会设计成 JSON 参数。handler 负责解析和校验,非法 JSON 或缺字段应返回结构化错误。
16.5 Tool schema 进入模型说得太泛
你当时答:tool 少的时候可以直接给模型;coding agent 会渐进披露 schema。
问题:泛泛而谈,没落到你项目和 Eino。
面试安全版:
在本项目里,每个 Tool 通过 Info 提供 name、description、parameter schema。构建 ReAct Agent 时,Eino 收集这些 ToolInfo 并绑定到 ToolCallingModel。不同 Agent 先按 role 过滤工具集合,所以模型每轮请求只会携带该 Agent 允许使用的 schema。
16.6 Tool 类型说成”HTTP toolcall”
你当时答:这个项目里是 http toolcall。
问题:项目里不只有 HTTP。Prometheus/Loki 是 HTTP API;Neo4j/Milvus 是数据库/RAG;CodeGraph 是 MCP;本质是统一 Tool 抽象。
面试安全版:
本项目把不同外部能力统一封装成 Tool。Prometheus/Loki 底层是 HTTP API,Neo4j 是图数据库查询,Milvus 是向量检索,CodeGraph 是 MCP 工具服务。Agent 看到的是统一的 Tool schema 和 observation,底层执行方式由 handler 或 MCP adapter 封装。
16.7 Tool Calling 和普通 API 调用没说到核心
你当时答:要知道如何制定参数,直接调很难做正确决策。
方向对,但应强调决策权差异。
面试安全版:
普通 API 调用是开发者提前写死调用时机和参数。Tool Calling 是模型根据当前上下文动态决定调用哪个工具、何时调用、填什么参数。诊断场景是开放问题,需要根据上一轮 observation 调整下一步取证,所以适合 Tool Calling。
16.8 Vector RAG 是什么不知道
你当时答:Vector RAG 解决啥,我还真不知道。
这是高风险点,因为简历写了”Milvus 文档向量检索”。
面试安全版:
Vector RAG 解决非结构化文档知识的语义召回。我的项目里它用于检索 RedCart 的 README、架构文档、OpenAPI、Runbook 和代码知识块,补充图谱里没有结构化进去的长尾知识。它返回的是文档 chunk 和来源信息,用于解释机制和补充诊断证据。
16.9 “图优先”裁决太粗
你当时答:图厉害,图优先吧。
问题:证据融合不能固定图优先。当前运行时证据通常权重最高。
面试安全版:
不能机械图优先。Prometheus/Loki 当前运行时证据权重最高;GraphRAG 历史案例提高某个方向的置信度;Vector RAG 文档证据解释机制。历史案例如果缺少当前指标/日志支撑,只能作为候选方向。
16.10 本地 embedding 只答”方便”
你当时答:因为方便。
问题:本地 embedding 的工程理由很多,“方便”太弱。
面试安全版:
本地 embedding 主要是数据不出本地、成本可控、离线可运行、延迟稳定。故障诊断平台会处理内部文档、历史 case 和代码知识块,本地 fastembed-go + ONNX Runtime 更适合内网/demo 环境。
16.11 Milvus metadata 不知道
你当时答:不知道。
面试安全版:
Milvus 里除了 vector,还要存 chunk 原文和 metadata,包括 chunk_id、source_path、title、heading、doc_type、service_name、chunk_index、hash、embedding_model、model_version 和更新时间。这些用于过滤、回溯、去重、增量更新和最终 RCA 证据展示。
16.12 topK 不知道
你当时答:不知道。
面试安全版:
topK 要平衡召回率和噪声。K 太小会漏证据,K 太大会把无关 chunk 塞进上下文。一般默认 5 左右,复杂问题可以先取 10,再按 score threshold、source 去重、metadata boost、rerank 过滤,最终给 LLM 3-5 条高质量证据。
16.13 SSE 只答”支持流式输出”
你当时答:SSE 支持流式输出,体验好。
问题:WebSocket 也支持流式。SSE 的关键是单向、HTTP 友好、原生 EventSource、自动重连。
面试安全版:
我选 SSE 是因为诊断流是后端到前端的单向进度推送,前端只需要接收 plan、agent_start、agent_done、final。SSE 基于 HTTP,浏览器原生 EventSource,支持自动重连,部署和鉴权比 WebSocket 简单。WebSocket 更适合强双向交互。
16.14 Callback 写库失败原因没想全
你当时反问:为什么会失败呢?
面试安全版:
callback 写库失败可能来自 PostgreSQL 不可用、连接池满、写入超时、JSONB 格式不合法、字段过长、并发写压力或迁移未执行。审计链路失败不应中断诊断,应该记录日志、normalize JSON、截断长内容,主流程继续返回 RCA。
16.15 Planner / Synthesizer 边界答得不严谨
你当时答:送给 agent 做裁决。
问题:最终裁决者是 Synthesizer,不是普通 Agent。
面试安全版:
Planner 是调度器,只决定是否需要追加 Experience Agent;各 Agent 是证据源专家,给局部判断;Synthesizer 是最终裁决者,负责跨证据源融合、冲突消解、输出根因、置信度和建议。
16.16 EvidenceBoard 只说 summary
你当时答:summary,上下文干净。
方向对,但要补审计回放。
面试安全版:
在线推理可以传 summary 保持上下文干净;完整 tool call 的 request/response/status 落库。更好的结构是 summary + evidence pointers,既控制 token,又能追溯原始证据。
16.17 Rerank / RAG 污染完全没准备
你当时说:这些真一个也不会了。
面试安全版:
Milvus topK 只是语义相似初筛,不能直接等于诊断证据。我会做 score threshold、service_name/doc_type 过滤、source 去重、相邻 chunk 合并、metadata boost,并把 Prometheus/Loki 当前运行时证据作为最高权重,避免文档语义相似结果污染 RCA。
16.18 Prometheus / Loki / Grafana 基础概念没熟
你当时问:这些 QL 都是什么。
面试安全版:
Prometheus 存指标,用 PromQL 查,比如 rate 看 QPS、histogram_quantile 看 P99。Loki 存日志,用 LogQL 查,比如 {job=“redcart”} |= “error” 查错误日志。Grafana 接 Prometheus 和 Loki 两个 datasource 做人工观测。Agent 不通过 Grafana,而是直接封装 Prometheus/Loki HTTP API 作为 Tool 自动取证。
16.19 次数转权重想用 softmax 直接做
你当时问:softmax 对一个节点的所有边归一化然后 +bias?
方向对,但直接 softmax 原始次数会让高频边一家独大。
面试安全版:
次数不能直接当权重。先 log(1+count) 压缩长尾,再加业务 bias,然后在同源节点同类型边内做 softmax。不同关系类型不要混归一化。weight 表示相关性,rank 表示顺序。工程上很多场景直接用 log(1+count)+bias 排序就够了,softmax 主要用于需要概率解释时。
16.20 “设计一个新 tool”被判定绕题
你当时答:针对 Log 没错误的情况,设计一个新 tool 收集日志数量特征。
面试官判定绕题。你的思路其实对,但答题顺序错了。
面试安全版(两段式):
当前系统里,Synthesizer 会按现有证据裁决:Metrics 是强运行时证据,Log 无错误表示缺少 error pattern,Experience 历史案例只能提升某个方向的置信度,不能单独定根因。
但我也会反思 Log Agent 的工具能力。如果当前日志工具只支持关键词检索,它很难表达”某时间段内读写日志量下降”这种统计特征。后续可以增加一个 log statistics tool,按时间窗口返回日志量、error rate、关键模式频次,让 Log Agent 不只查文本,还能补充日志侧时间序列证据。
17. 总体短板归类
你的短板不是”完全不会”,而是三类:
A. 框架术语边界不稳
比如 Tool / ToolsNode / Agent / Function Call / Tool Call / MCP。
解决方法:背清对象边界(第 2、3、4、5 章)。
B. RAG 工程细节薄
Vector RAG、metadata、topK、rerank、证据融合、RAG 污染。
解决方法:按”召回 → 过滤 → rerank → 融合 → 防污染”这条链背(第 7、8、9 章)。
C. 可观测性基础弱
Prometheus、Loki、Grafana、PromQL、LogQL、SSE。
解决方法:记住”指标、日志、展示”三分法和几个常用查询(第 10、11 章)。
18. 最该背的 5 段
- 30 秒项目介绍(第 15 章 1)
- ReAct + Tool Calling 流程(第 15 章 2)
- GraphRAG + Vector RAG 区别(第 15 章 3)
- Milvus metadata + topK/rerank(第 15 章 4)
- MCP 接入 CodeGraph 流程(第 15 章 5)
这 5 段背熟,简历第一项目 80% 的追问都能扛住。