Sealessland logo Sealessland
InterviewPrep

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 AgentPrometheus 指标query_prometheus查延迟、QPS、错误率、资源指标
Log AgentLoki 日志query_loki查 error、timeout、panic、日志模式
Experience AgentNeo4j / Milvus / CodeGraphquery_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 最少需要两类能力:

  1. Info():提供工具名、description、参数 schema。
  2. 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 握手流程

  1. Start:启动 codegraph serve --mcp 子进程,建立 stdin/stdout 管道。
  2. initialize:客户端发送协议版本、clientInfo、capabilities。
  3. 服务端返回 protocolVersion、serverInfo、capabilities,其中 tools 表示支持工具能力。
  4. 客户端发送 notifications/initialized
  5. 后续发 tools/listtools/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
MetricPrometheus 指标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 边权重设计

边可以有属性:weightranksupport_countreasonlast_seen_atsuccess_ratecriticality

适合加权的边:

建议属性
Metric - CORRELATES_WITH -> IncidentCaseweight, support_count, reason, last_seen_at
LogEntry - INDICATES -> IncidentCaseweight, support_count, pattern_confidence
IncidentCase - RESOLVED_BY -> Runbookrank, success_rate, verified_at
Service - CALLS -> Servicecriticality, 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

  1. 数据安全:内部文档、故障 case、代码知识块不出本地。
  2. 成本可控:批量 embedding 不用一直调外部 API。
  3. 离线可运行:demo / 内网 / 本地开发不依赖公网。
  4. 延迟稳定:本地推理不受外部 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_modelmodel_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 方法

从简单到复杂:

  1. 规则 rerank:score threshold、service_name 过滤、doc_type 加权、source 去重、相邻 chunk 合并。
  2. 模型 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 幻觉控制四层

  1. Prompt 层:先调工具取证,无证据不下结论,根因必须引用 evidence。
  2. Tool 层:提供结构化 evidence,每条带 source 和类型。
  3. Synthesizer 层:root cause 至少有一条当前运行时证据支撑,历史和文档只做置信度加权。
  4. 审计层:保存 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 /metricsPromQL
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:planplanner_decisionagent_startagent_donefinal

不推完整 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@KTopK 里有多少真相关
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 段

  1. 30 秒项目介绍(第 15 章 1)
  2. ReAct + Tool Calling 流程(第 15 章 2)
  3. GraphRAG + Vector RAG 区别(第 15 章 3)
  4. Milvus metadata + topK/rerank(第 15 章 4)
  5. MCP 接入 CodeGraph 流程(第 15 章 5)

这 5 段背熟,简历第一项目 80% 的追问都能扛住。