Harness Times
这里是全站 137 道面试问题的总入口。它们不是「常见题汇总」,而是按 面试官的真实提问顺序反推出来的:先问机制,再问代价,最后问你有没有在真实场景里撞过墙。 每道题都配了参考答案、追问链(答对之后会往哪追)和加分点(哪句话能证明你真做过)。
建议用法:先只看问题,心里答一遍,再展开对照。凡是答不出「代价和边界」的,就是还没掌握。 自评「已能答出」的记录只存在你这台机器的浏览器里,不会上传。
01 Transformer 与自注意力 3 问
为什么注意力复杂度是 O(n²)?这对做 Agent 意味着什么? 高频
seq × seq 的注意力矩阵,所以算力随序列长度呈平方增长。对 Agent 的直接含义有三层:第一,上下文越长,成本不是线性上涨而是平方级上涨,这是"长上下文很贵"的物理原因;第二,往上下文里多塞一倍内容,代价远不止翻一倍;第三,裁剪、压缩、状态外置不是优化技巧,而是必须做的基本功。
追问链
- 那 KV Cache 的显存占用怎么估算?它和 n² 是同一个量级吗?
- 如果只关心首 token 延迟,哪个成本占主导?
多头注意力比单头好在哪?
工程意义在于:模型能同时维持多种关系,这是长链路任务里"既记住目标又盯住细节"的基础。注意头的数量与 head_dim 的乘积大致等于隐藏维度,所以加头并不等比例增加算力,但头太多也会稀释每个头的表达空间。
位置编码解决什么问题?没有会怎样?
对工程的启示:相对位置方案让模型对超出训练长度的位置有一定外推能力,但外推能力有限。"把窗口调大"不等于"模型真的能用好长窗口",这就是长上下文需要专门训练和评测的原因。
02 KV Cache:多轮对话的隐性账单 7 问
KV Cache 是什么?为什么多轮对话能省下来钱? 高频
多轮对话之所以能省,是因为第二轮的 prompt 里,绝大部分是第一轮已经算过的内容。前缀完全一致时,这段直接命中缓存,不重复计算,在按 token 计价的 API 上直接体现为折扣。
追问链
- 那缓存命中率取决于什么?
- 显存占用怎么估?和 batch size 是什么关系?
缓存命中率取决于什么?—— 这道题几乎决定你懂不懂成本。 高频
常见破坏点包括:system prompt 里塞了当前时间戳或随机 ID、把工具列表按使用频率每次重排、把检索结果按时间排序每次都变、few-shot 示例顺序随机、会话 ID 注入到 prompt 开头。这些写法看起来无害,实际每一轮都在让缓存重置。
追问链
- 那你系统里具体哪些地方在破坏缓存?你怎么改的?
- 改成稳定前缀之后,命中率大概提升了多少?
Agent 场景下,token 成本的大头在哪? 高频
所以成本杠杆的优先级通常是:① 前缀缓存友好(提升命中率,直接对应 API 折扣);② 工具结果裁剪(只回关键字段,不要把整页 JSON 塞进去);③ 历史摘要化(保留决策与结论,丢掉过程);④ 状态外置(大块数据落盘,按需回读);⑤ 模型分级路由(简单环节用便宜档位)。
长上下文和 RAG 该怎么选?
适合长上下文:全集较小且必须整体把握(例如一次代码评审要把整个文件读完)、需要跨段落的推理与全局一致性。
适合 RAG:库很大、每次只需要极少相关片段、需要精确引用来源。
真实系统几乎都是混合:用检索把候选收窄到可控范围,再把候选完整放进上下文,这样既控制了 token 又保住了精度。反过来做——把整个库塞进长上下文——成本和延迟都不可接受,而且要面对"中间内容被忽略"的注意力衰减问题。
把同一个请求的序列长度从 8k 提到 32k,KV Cache 显存和注意力算力各变成原来的几倍?这两个倍率分别对应什么工程手段? 高频
依据是两条完全不同的增长律:KV Cache 显存
∝ n(公式 2 · batch · seq · n_layers · n_kv_heads · head_dim · bytes),而注意力算力 ∝ n²(中间那张 [n, n] 分数矩阵)。对应的手段也完全不同:显存这条线靠 GQA / MQA 降 n_kv_heads、量化降 bytes、PagedAttention 降碎片;算力这条线靠 FlashAttention / 分块计算 把单次前向算便宜。
- 判据一:显存是「装得下多少并发」的容量问题,算力是「要算多久」的时长问题。
- 判据二:把「长上下文优化」说成一个笼统手段,几乎一定会在追问里露馅。
追问链
- 这两个倍率里,哪一个会先成为你在线上遇到的瓶颈?
- 如果显存够、算力也够,但并发就是上不去,你会先查什么?
你的 Agent 每轮都往 system prompt 里写「当前时间:…」,前缀缓存命中率几乎为 0。除了把时间挪到末尾,还有哪些更稳的改法?各自代价是什么? 高频
① 做成工具——把「取当前时间」变成
get_current_time,模型需要时才调,system prompt 一个字节都不动;代价是多一次工具往返。② 降精度并接受偶发失效——只写到「天」甚至「周」,命中率大幅回升;代价是少数跨天边界的请求会拿到略过期的时间。
③ 挪到尾部——放进最后一条 user 消息,动态内容不再破坏前缀。
判据:任何时候都问一句「这段字节跨轮会变吗」——会变的,一律不许出现在前缀里。
追问链
- 你项目里还有哪些「跨轮会变」的字段被写在了头部?
- 你怎么量化这次改动带来的收益?
应用侧的前缀缓存和推理引擎侧的 KV Cache 是一回事吗?这两者里,你能完全控制哪一个?
前缀缓存(应用侧)指你的请求前缀保持字节稳定,从而命中服务端已有的计算结果——你能完全控制,靠稳定序列化保证(键排序、分隔符固定、不做「美化」式重排)。
KV Cache(引擎侧)是推理框架在层内缓存的 K/V 张量,由引擎按 LRU 或分页管理,还受并发与显存压力影响——你只能间接影响,做法是把高频复用的前缀做短、做稳。
判据:能被你的 JSON 序列化规则左右的,是前者;会被别人抢占显存而失效的,是后者。两者协同,但归属不同层。
追问链
- 如果服务端把你的长前缀淘汰了,应用侧还能做什么?
- 「稳定序列化」具体要固定哪几件事?
03 MoE 与稀疏激活 6 问
为什么 MoE 的总参数量和激活参数量不是一回事? 高频
总参数量是所有专家参数之和——决定模型需要
要多少显存/内存装下它;
激活参数量是单个 token 实际参与运算的那部分参数——决定算力开销。
所以一个总参数 671B 的模型,单 token 激活可能只有 37B 量级,算力像小模型,容量像大模型,这就是它便宜的原因。
追问链
- 那显存能不能按激活参数量来估?
- 路由不均(专家负载倾斜)会带来什么工程问题?
MoE 和稠密模型分别适合什么场景?
MoE 适合:预算充足、追求单位算力下的质量、有大规模并发可以摊薄通信与调度开销、以及显存资源相对宽裕的服务端部署。
稠密模型适合:显存受限(端侧、单机小卡)、并发低且延迟敏感(MoE 的专家并行会引入额外通信延迟)、需要极简部署与稳定吞吐的场景。
换句话说:MoE 换来的是"用容量换质量",代价是显存占用、通信开销与调度复杂度。
MoE 的负载不均衡是什么问题?会怎么表现?
常规处理是加负载均衡损失(鼓励路由分布均匀)、设置专家容量上限与溢出丢弃策略、以及在工程侧做专家并行的重排布。对使用方的启示:同一个模型在不同任务分布下的实际吞吐可能差异很大,压测要用真实流量而不是随机文本。
客户要求「把 671B 的 MoE 模型部署到两台 80GB 的机器上」,你会怎么回应? 高频
正确回应是给出可选项:
- 换成激活量相近的稠密小模型;
- 用能跑下的量化版 MoE,并明确精度风险;
- 若一定要这份容量,接受多机多卡 + 专家并行带来的 All-to-All 通信开销,并说清延迟代价。
追问链
- 如果客户愿意把机器加到 16 台,还缺什么才能跑起来?
- 专家并行的 All-to-All 主要伤害吞吐还是延迟?
一个 256 专家、每 token top-8 的 MoE,把 top-8 改成 top-4,单 token 算力和显存下限各怎么变?
因为这两件事由不同口径决定:激活参数占比从
8/256 ≈ 3.1% 变成 4/256 ≈ 1.6%,砍掉的是每 token 的 FLOPs;但路由是运行时才决定的,你无法预知下一个 token 会走哪几个专家,所以全部 256 个专家的权重必须常驻显存。判据:被问「调 top-k 能省显存吗」,答案是不能;要省显存只能动总参数量或做量化。
追问链
- 那调小 top-k 会带来什么副作用?
- 如果只想省显存,有哪些可用手段?
MoE 省的 FLOPs 和 KV Cache 省的重复计算会叠加吗?叠加之后瓶颈会挪到哪里?
KV Cache 省的是重复计算(同样的前缀不再重算),MoE 省的是单位 token 的参数量(不激活全部专家);两者降低的都是「算多少」。但 MoE 同时引入两个新成本:显存下限由总参数量决定,以及跨设备搬运 token 的 All-to-All 通信。
于是高并发场景下,瓶颈常常从算力挪到显存容量与通信带宽;反过来,小 batch 时专家利用率低,MoE 的性价比优势会缩水甚至变成负担。
判据:把两项优化叠在一起之前,先确认新的瓶颈不是显存或通信。
追问链
- 多大的 batch 规模下,MoE 才开始划算?
- 如果 MoE 只在云端划算,本地化部署该怎么选型?
04 采样、温度与确定性 5 问
Temperature 和 top_p 分别在调什么?Agent 场景你会怎么设?
Agent 场景的经验是一条原则:凡是输出要被程序解析的地方(工具调用、结构化参数、JSON),尽量低温甚至贪婪解码;需要发散的地方(头脑风暴、候选方案生成)才提高温度。
要注意:即使 temperature = 0,由于并行归约的浮点非确定性、批处理组合变化等原因,输出也不保证逐字一致——所以兜底必须是校验和重试,而不是"假设它稳定"。
追问链
- 那参数校验失败了你怎么办?
- 为什么 temperature=0 仍然可能两次结果不同?
同一个问题问两次答案不同,这在 Agent 里会变成什么问题?
对应的工程手段是:结构化输出 + Schema 校验、解码参数按环节分级设置、把关键决策点做成确定性代码而不是交给模型自由发挥、评测时固定随机种子并多次重复取分布。
top_k 和 top_p 能同时用吗?会有什么问题?
更实用的建议是:固定一个主参数(OpenAI 系通常调 top_p,部分开源模型偏 top_k),另一个设为默认值,避免两个旋钮互相干扰导致调参不可解释。另外,把"温度"和"惩罚项"(presence / frequency penalty)混着调最容易出现"越调越怪"的情况。
用了约束解码(constrained decoding / response_format)之后,还需要再做 schema 校验吗?为什么? 高频
约束解码保证「语法合法」——每个位置只能取合法 token,所以几乎不会出现少括号、字段名拼错这类解析错误。
但它不保证「语义正确」:字段值可以是错的、枚举选错、数字超范围、必填项给空串,以及上下文被截断时 JSON 是否完整(取决于实现是否强收尾)。
判据:凡输出会被程序执行的调用,三层必须齐备——低温(概率上收敛)+ 约束解码(语法上强制)+ 本地 schema 与业务校验(语义上兜底)。少任何一层,线上都会以解析失败或错误执行的形式暴露。
追问链
- 约束解码会不会拖慢生成?
- 校验失败之后,你的重试策略是什么?
为了让评测可复现,固定 seed 够吗?还需要固定什么?
必须一起固定的还有:
- 推理框架与模型版本的精确标识(升级、换量化档位都会改变 logits 的微小差异);
- 批处理的拼法(同一批里别人多一个请求,你的结果就可能翻转);
- 采样参数与停止条件;
- 评测集本身与判分规则(规则也要版本化)。
判据:报告指标时给出重复次数与波动区间;跌幅小于波动区间的不叫回归。
追问链
- 你怎么给「采样噪声」和「真实回归」划线?
- 哪些指标天生不适合用来判定回归?
05 推理优化与成本杠杆 6 问
如果让你把推理成本砍一半,你会动哪几个杠杆? 高频
① 先量瓶颈:是显存不够(并发上不去)、还是首 token 延迟高、还是吞吐被批处理限制?三个瓶颈对应完全不同的杠杆。
② 缓存与上下文侧(几乎无质量损失,优先级最高):提升前缀缓存命中率、裁剪工具结果、压缩历史。
③ 调度侧:连续批处理提高批内利用率、分页管理 KV Cache 降低碎片。
④ 模型侧:量化(FP8/INT8)、分级路由(简单任务走小模型)。
⑤ 采样侧:投机解码用小模型起草、大模型验证。
顺序很关键:能在上下文层解决的问题,不要动到模型精度。
追问链
- 每一档的代价是什么?
- 怎么验证优化没有伤害质量?
量化的代价到底是什么?
① 精度损失,且不是均匀的——对数值敏感的环节(长链推理、精确算术、结构化输出)更容易先崩;
② 长尾能力退化,平均分可能只掉一点,但某些能力会明显下滑,所以必须看分项而不是看总分;
③ 工程复杂度,不同量化格式对推理引擎、算子支持、硬件的要求不同,实际部署时"能不能跑"和"跑得快不快"是两回事。
结论:量化必须配评测,用平均分判断量化是否可行是危险的。
投机解码(speculative decoding)为什么能加速?
因为大模型的一次前向是并行的,验证 k 个 token 的成本接近验证 1 个,所以只要草稿的接受率够高,就能在一次前向上推进多个 token,端到端提速。
前提条件:草稿模型的分布要与目标模型足够接近(否则接受率低、反而更慢),且任务可预测性较强(代码补全、格式化输出这类收益最明显,自由创作收益有限)。
PagedAttention 是必须上的优化吗?什么情况下收益最大、什么情况下几乎没用?
收益最大:长上下文 + 高并发 + 各请求长度差异大。传统实现要按最大长度预留一段连续显存,长度参差时浪费极重;分页把缓存切成固定块按需分配,可并发请求数能显著上升。
收益很小:单请求、短上下文、低并发、长度整齐——此时几乎没有碎片可消灭。
判据:先看显存利用率与可并发请求数,再决定要不要上分页;它不改 O(n²) 的注意力复杂度,指望它降算力是方向性错误。
追问链
- 它和连续批处理是什么关系?
- 如果碎片不严重但吞吐上不去,你会先查什么?
投机解码:草稿模型一次起草 k=4 个 token,接受率 r=0.7 大概能拿到多少加速?r 掉到 0.2 时还能上吗? 高频
1/(1 + k·r)。r=0.7、k=4 时约为
1/3.8 ≈ 26%,也就是大约 3~4 倍的搬运量节省;r=0.2、k=4 时只有 1/1.8 ≈ 56%,而且草稿模型自身的计算与调度开销还没算进去,实际很可能净亏损。判据:上线前先实测接受率;r 低于 0.5 左右就别上,或者先换一个与目标模型分布更接近的草稿模型。
加速比还强依赖任务类型——代码补全、格式化输出这类高可预测任务收益最大,自由创作收益有限。
追问链
- 接受率低是草稿模型的问题还是任务的问题?怎么区分?
- 除了另训一个草稿模型,还有别的「一次前向产出多个 token」的办法吗?
线上看到「吞吐上不去、GPU 利用率只有个位数」,你会先上量化还是先上连续批处理?
GPU 利用率只有个位数说明硬件在空转,根因是「一批请求要等最慢的那个结束才换下一批」;连续批处理让某个请求一结束就立刻补入新请求,直接填满空转,是性价比最高的一刀。
量化解决的是另一类问题——显存装不下或搬运量太大:它减少每次搬运的字节数,对 decode 的带宽瓶颈有效,但对「批内没填满」这种调度问题无能为力。
判据:先问瓶颈是「算」「搬」还是「排」——排队问题用调度解,搬运问题用量化解,算力问题用融合与分块解。
追问链
- 连续批处理会不会让单请求延迟变差?为什么?
- 如果显存也不够、利用率也低,这两件事能一起做吗?
01 Harness 是什么 6 问
Harness 的定义是什么?边界在哪? 高频
具体可以拆成七层:① 执行层(Agent Loop、终止条件、状态机);② 能力层(工具注册与契约、MCP 接入、工具执行与沙箱);③ 上下文层(预算分配、压缩、缓存友好组装、记忆);④ 编排层(规划、Subagent、多 Agent 通信);⑤ 治理层(权限、审计、提示注入防御、配额);⑥ 质量层(评测集、指标、trace、回归门禁);⑦ 适配层(多模型网关、参数 профиль、与训练团队的反馈回流)。
边界判断有个简单标准:如果是"让模型自己变强"的事,属于模型侧;如果是"让变强的模型能可靠地完成任务"的事,属于 Harness。
追问链
- 模型越来越强之后,Harness 会不会被吃掉?
- 这七层里你认为哪一层最难做?
为什么说 Harness 的难点不在"让它跑起来",而在"让它可评测、可回滚"?
一个只在开发机上跑通过的 Agent,缺三样东西就无法成为产品:① 可观测——出了问题你拿不到完整链路(每轮的 prompt、工具调用、耗时、token),只能靠猜;② 可复现——没有 trace 就没有 replay,同一个 bug 你复现不出来,也就无法验证修好了没;③ 可安全变更——prompt 和工具描述本质上就是代码,没有版本化、灰度和一键回滚,每次改动都是在赌。
所以成熟的 Harness 有个特征:prompt 变更有版本号、有对照评测、有灰度门禁,而不是直接改线上。
你怎么判断一个 Agent 产品做得好不好?
① 真实任务成功率——在用户的真实任务分布上,能独立完成的比例是多少;
② 人工介入成本——需要用户接管、确认、纠正的次数,这直接决定它是不是负担;
③ 可恢复性——跑偏之后能不能回退、能不能断点续跑、会不会把副作用做重;
④ 单位任务成本——token 与时间的消耗。
一个重要的判断信号是:好的 Agent 产品会把"不确定性"显式暴露给用户(比如告诉你它删除了哪些文件、改了哪些内容、依据是什么),而不是假装自己一直很确定。
同一份模型,A 团队的 Agent 能连续跑几十步交付一份带引用的调研报告,B 团队跑到第 8 步就散了。你会按什么顺序排查,每一步看什么数? 高频
① 上下文:把每一步的输入按四类成分切开数 token,看真实判断依据的占比。如果第 8 步时占比已经掉到 10% 上下,问题在压缩与排序,不在模型。
② 工具契约:把这一步真正调用的那几个工具的 description 打出来,检查四层是否齐全——做什么、什么时候用、什么时候该改用别的、参数范例与返回结构。只写一句「查询数据」的工具,模型只能靠猜。
③ 失败恢复:把 trace 里每一次工具报错列出来,看它是被分类后回喂继续跑,还是直接抛异常终止了整轮。8 步里只要有一次超时没人接住,任务就断在那里。
三条都查过仍然解释不了差异,再换模型做对照——这样换模型才是结论,而不是第一步的猜测。
追问链
- 你怎么量化「上下文里的判断依据占比」?给一个能落地的口径。
- 如果 trace 里只有结果、没有过程,你会先补什么?
给一个刚上线的 Agent 排改造优先级:工具调用错误率 15%、跑到第 20 轮的任务失败率 40%、单任务平均成本是预期的 3 倍。你先动哪一层,为什么?
① 成本 3 倍:先查前缀稳定性与状态外置,这一层改动最小、收益最大。把相邻两轮的请求体打印出来逐字节比对,第一个不同点若落在前 1% 以内,说明缓存基本全废;再把中间产物外部化,上下文只留指针与目录清单。
② 第 20 轮失败:查压缩触发点与终止条件。用量到 60% 就该触发阶段摘要,而不是等接口报错;确认预算耗尽时返回的是「部分结果 + 已完成步骤」,而不是一句失败。
③ 错误率 15%:最后补契约四层、schema 约束、执行前校验与错误分类回喂。
理由:成本与长任务失败是每天都在流血的事故,错误率是可以通过一轮契约改造集中偿还的工程债。
追问链
- 如果把顺序反过来、先修错误率,会有什么代价?
- 成本降下来之后,你怎么确认不是因为任务跑得更少而「看起来更便宜」?
有人说「模型越来越强,Harness 会越来越薄」。这句话哪一半对、哪一半是幻觉?
该薄的:为绕开旧模型弱点而加的补丁——强制模板化的输出格式、把答案空间裁成枚举、用反复重试掩盖一次判断失误。这些补丁在新模型上不但没用,还会压住模型的真实能力,必须主动识别并拆掉。
不会薄的:四件模型在结构上做不到的事——交付形态、可观测与审计、权限与不可逆操作的闸门、断点恢复。这些不是能力问题,是责任问题,模型再强也得由代码承担。
判据:一条 Harness 逻辑如果删掉之后模型正确率不变、账还能对上、能回滚、能追责,那它就是可以拆的补丁;删掉之后系统失去可追责性或不可恢复,它就必须留着。
追问链
- 你最近一次主动拆掉补丁是什么时候,怎么判断它已经没用了?
- 如果线上跑的还是老版本模型,这些补丁要不要拆?
02 Agent Loop 与终止条件 7 问
Agent Loop 的终止条件你会设计哪几类? 高频
① 显式完成——模型明确表示任务达成(要做好格式约束,不要靠正则猜自然语言);
② 资源用尽——最大轮数、token 预算上限、时间上限,三者都要有,因为不同任务会先撞到不同的墙;
③ 无进展检测——连续 N 轮动作或工具调用高度相似、或者没有产生新的有效信息,判定为原地打转并中断;
④ 循环检测——A→B→A 这类振荡模式;
⑤ 主动挂起——需要人工确认、缺少必要信息、或者触及高风险操作时,转 Human-in-the-loop 而不是硬着头皮往下走。
还要有一个兜底:异常终止也必须产出可读的中间结果,而不是把已经完成的工作丢掉。
追问链
- 如果只允许你保留一个条件,你留哪个?为什么?
- 无进展检测具体怎么实现?
模型开始重复同一个动作不收敛,你系统层面怎么发现? 高频
① 动作指纹去重——把每轮的工具名 + 规范化参数(排序后哈希)作为指纹,连续重复即判定打转;
② 结果熵检测——工具返回内容高度相似甚至完全一致,说明再调也拿不到新信息;
③ 目标相似度——对比相邻几轮的思考文本相似度,超过阈值说明在原地复述;
④ 进度信号——为任务维护"已完成子目标集合",若连续多轮集合不增长,即无进展。
检出之后的处理分三级:先注入提示纠偏(告诉它已经做过什么)→ 再强制换策略(禁用刚才那个工具)→ 最后中断并交出中间结果并说明卡在哪。
一次 loop 最多几轮?这个数怎么定?
简单查询型 3–5 轮(一次检索加一次总结足够);常规办事型 10–20 轮;代码修复类长任务可以放到 30–50 轮,但必须配预算上限兜底。
定这个数的依据是"分布 + 成本":看线上真实任务的轮数分布,取 P95 再留一点余量;同时算一下撞到上限时的最坏成本,确保可接受。
另外要区分软上限与硬上限:软上限触发时提示模型"轮数不多了,请收尾并给出当前结论",硬上限触发时直接中断。只设硬上限会让模型在最后一轮还去开一个新工具,交出一个半成品。
ReAct 和 Plan-and-Execute 该怎么选?
ReAct(边想边做)每轮根据最新观察决定下一步,适应性强、对信息不确定的任务友好,缺点是容易短视、可能反复试探、总轮数偏高。
Plan-and-Execute(先规划再执行)先生成步骤清单再逐步执行,优点是全局感强、可审计、可并行;缺点是计划一旦错误会一路错下去,且环境变化后计划失效。
实践中常见的组合是两层:外层用规划定大方向(3–6 步),内层用 ReAct 处理每一步的具体不确定性,并在关键节点重新规划。选择标准是:信息在开始时就基本齐备 → 偏规划;信息要边做边获得 → 偏 ReAct。
一次 loop 的 max_turns 设为 15,每轮新增输入约 4k token。如果模型在第 3 轮就该收尾却一直跑下去,最多浪费多少输入 token?这道题真正考的是什么? 高频
4k × (4+5+…+15) ≈ 45.6 万 token。真正考的是:只设了 max_turns、没有无进展检测与成本斜率的循环,刹车只作用于「一定会停」,不作用于「停在该停的地方」。轮数上限是安全阀,不是成本控制。
补一句会加分:这 45.6 万 token 在日志里全是正常的模型调用,没有任何异常记录——这就是为什么这类浪费能持续几个月不被发现,直到有人去画每轮的输入曲线。
追问链
- 加上「连续 3 轮调用签名重复且观察结果哈希不变就退出」之后,这个任务会在第几轮停?
- 你会用哪个指标在监控上盯住这类浪费?
把无进展检测的阈值从 3 调到 1,为什么任务完成率反而可能下降?
正确做法是把两个条件叠加:调用签名重复(同名同参数)且观察结果哈希连续多轮不变,两个条件同时成立才计为停滞,阈值取 3。单看哈希会被时间戳、随机 id 这类噪声骗到;单看调用次数又会误杀「换关键词继续检索」这种正常行为。
判据:把阈值调到 1 跑一遍回归集,逐条看被判定停滞的样本;只要其中存在「下一轮本来会成功」的样本,阈值就是设错了。
追问链
- 如果任务需要轮询外部状态直到它变化,你的停滞检测会误杀它,怎么改?
- 你用什么数据证明阈值从 1 改到 3 是对的?
任务跑到第 9 轮需要用户确认一次不可逆操作,用户 40 分钟后才回来。要让这 40 分钟不白等,需要满足哪几个条件?
① 状态持久化:上下文、前 8 步的结论、中间产物、待决策的问题必须落盘,进程重启也能接上。
② 等待不计入预算:轮数与时间上限的计时要把等待人工的时间排除,否则用户回来时任务已经因为时间上限被判预算耗尽。
③ 恢复后不重放副作用:已完成的有副作用步骤必须带幂等键,恢复时读回上次结果,而不是再执行一次。
验收方式:把进程直接杀掉再拉起来,任务从第 9 轮继续,且外部世界只被改了一次。顺带一提,确认信息本身也要能决策:不是问「是否继续」,而是给出影响范围与可选方案。
追问链
- 如果用户 3 天后才回来,保留状态的成本怎么控制?
- 恢复时怎么判断「这一步之前到底执行成功了没有」?
03 Tool Use 与工具契约 7 问
工具描述怎么写才算好? 高频
① 什么时候该用、什么时候不该用(最重要的,能显著减少误调用);
② 每个参数的业务含义与取值约束(枚举值、格式、范围,以及默认行为);
③ 典型调用示例(一到两个真实例子,最好包含常见错误写法);
④ 返回值结构(模型要能判断调用是否成功、结果里哪个字段才是它要的);
⑤ 失败与边界情况(什么输入会报错、报错长什么样、能不能重试)。
经验数据是:描述质量对调用准确率的影响,往往比换模型更大。所以我们把工具描述当一等公民维护,有版本、有评测。
追问链
- 那工具描述和 CLI 的 --help 是同一份吗?
- 怎么验证描述改好了?
模型调用工具失败了,你怎么处理?
① 参数错误(缺必填、类型不对、枚举越界)——可修复,把结构化错误回喂(哪个字段、错在哪里、合法取值集合是什么),允许重试 1–2 轮;
② 权限拒绝——不可自动修复,需要用户授权或换路径,应中断并说明;
③ 超时/限流——可重试,但要指数退避 + 上限,并考虑换通道;
④ 业务性错误(查无此人、条件不满足)——不该重试,这是有效信息,应该把"这个事实"告诉模型让它改变策略;
⑤ 工具自身 bug——不该让模型兜底,要告警并降级。
最容易犯的错是把"业务性错误"当异常重试,结果白白烧掉好几轮预算。
MCP 和直接写 Tools 有什么区别?什么时候用哪个? 高频
选型建议:
用 MCP——能力来自外部或第三方、需要生态复用、团队分工上由能力方自己维护、长尾能力多;
用内部 Tools——高频核心链路、需要强管控与极致性能、需要平台级统一配额与审计、参数要深度校验。
真实系统通常是两者并存:核心高频能力走内部工具,长尾与外部能力走 MCP,在模型看来它们是同一套工具抽象。
追问链
- MCP 的安全边界怎么处理?
- 两种工具在权限模型上要区别对待吗?
工具重试导致重复写库、重复发消息,怎么办?
① 只读查询——随便重试,无副作用;
② 幂等写——可以重试,依赖幂等键去重;
③ 非幂等副作用(发消息、转账、提交表单)——默认不自动重试,改由人工确认或状态查询后决定。
幂等键的做法是:在真正执行前,用「任务 ID + 工具名 + 参数规范化哈希」生成键,写入去重表(带 TTL),执行前先查、执行后标记。这样即便重试也只落地一次。
还要注意一个隐蔽问题:超时不代表没执行。超时后应该先查询执行状态,再决定重试,而不是直接重发。
同一个工具,A 版描述一句话,B 版四层齐全。团队决定「先上线,出问题再加提示词补」。这个决定错在哪,代价怎么算?
四层描述里至少有两层是可以变成结构强制的:枚举与范围写进 schema(
enum、minimum、maximum),非法输入在结构上不可能出现;「何时用、何时该改用别的」写进描述,消除相似工具之间的选择困难。用系统提示词补救有两个代价:① 它按概率生效,同一句约束在不同轮次、不同上下文长度下命中率不同;② 它占常驻 token 并且会动前缀——补丁每加一句,所有请求的头部都跟着变一次,前缀缓存的收益被吃掉一部分。
判据:任何准备「将来再加提示词」的信息,先问它能不能用 schema 表达;能,就不该留在提示词里。
追问链
- 哪些信息是 schema 表达不了、只能写在描述里的?
- 在很长的上下文里新增一条系统约束,你会怎么验证它真的生效了?
某个写操作超时了,重试 3 次之后发现数据被写了 4 次。问题出在哪几层? 高频
① 幂等键由 Harness 自己生成:如果键是时间戳或随机 UUID,每次重试都得到新键,服务端的去重表永远命中不了。键必须由调用方按「操作意图」生成——任务 ID + 步骤序号,或者用户请求 ID,这样重试时键不变。
② 超时没有被当成「可能已执行」:超时是最会骗人的错误,服务端可能已经执行完、只是响应在路上丢了。返回值里必须有
side_effect_done 这类字段,Harness 才知道「能不能安全重试」。验收方式:把进程杀在「请求发出后、响应返回前」,恢复执行后外部世界只能被改一次。另外,人工确认不能替代幂等——前者决定该不该做,后者决定会不会做两次。
追问链
- 幂等键的粒度按任务、按步骤还是按调用?各自的代价是什么?
- 如果下游服务不支持幂等键,你还有什么办法保证只执行一次?
团队要把 12 个内部工具接给 3 个不同的 Agent 产品使用。用 MCP 是对的还是错的,判断依据是什么?
12 个工具 × 3 个产品 = 36 份接入适配,而且上游接口每改一次就要改 36 处——这正是 MCP 要解决的问题:一次实现、多处接入,所以这个场景该用。
但要同时接受两个代价:① 多一层进程与协议开销,对实时补全这类极致低延迟的场景不合适;② MCP 不改善契约质量,描述含糊的工具接进来照样被误用,七要素一条都不能省。
反例:如果这份能力只服务一个产品、调用链又极短,引入 MCP 只会多一层开销,收益为负。所以决策问题只有一个:这份能力需不需要被第二个产品复用。
追问链
- MCP 工具与内部工具的权限模型要区别对待吗?
- 如果 3 个产品里只有一个对延迟敏感,你会怎么分层?
04 Context Engineering 7 问
Prompt Engineering 和 Context Engineering 的区别是什么? 高频
前者是措辞、格式、few-shot 的组织、角色与约束的表达;后者是决定模型的可见信息集合——召回哪些内容、裁剪掉哪些、什么时候注入记忆、历史压缩到什么粒度、静态与动态部分怎么排列。
工程上后者的权重更大,因为它决定了效果上限:提示词写得再好,如果关键信息根本没进上下文,模型只能猜。而且 Context Engineering 直接决定成本(token 量、缓存命中率)与延迟,是可量化、可优化的部分。
Schema 有几百个字段,你会全塞进 prompt 吗? 高频
分层做法:
① 常驻层——工具名、少量最高频字段、以及"如何获取字段清单"的元工具(让模型能主动查);
② 按需召回层——先用一次轻量检索(关键词或向量)从字段库里召回候选字段子集,再放进上下文;
③ 外置层——完整 schema 放在可查询的资源里,模型需要时通过工具查全量定义。
更稳的做法是两阶段:先让模型输出"我要用到哪些字段",程序校验后把对应 schema 注入,再让它生成最终条件。这样既省 token,也让每一步的生成空间可控、可校验。
追问链
- 那召回错了怎么办?
- 这个两阶段设计会多花一轮,成本上划算吗?
上下文快满了,你怎么知道?压缩策略是什么? 高频
压缩按"损伤从小到大"分三级:
① 裁剪——工具结果只保留关键字段,丢弃冗长的原始响应、日志、重复内容。这一级几乎无损,应该常态化执行;
② 摘要化——把早期历史替换成摘要,只保留决策与结论,丢掉推理过程;
③ 外置——把大块内容(长文档、大 JSON、已完成产物)落盘,上下文里只留指针(路径、ID、摘要),需要时通过工具回读。
关键设计是摘要里必须保留指针,否则信息真丢了。压缩要记日志、最好对用户可见,并且可回滚。
为什么上下文的排列顺序会影响成本?
稳定内容放前面(静态 system prompt、工具列表按固定顺序、few-shot 固定不变),动态内容放后面(当前时间、用户信息、本轮检索结果、新增历史)。
常见的反面写法很隐蔽:把当前时间戳放在 system prompt 开头、每次按使用频率重排工具列表、把召回片段按相关度排序(顺序每次不同)、在开头注入会话 ID。这些都会让整段缓存作废,成本可能差好几倍,而日志上完全看不出来——只能靠监控命中率发现。
任务跑到第 20 轮,上下文接近窗口上限,模型开始答非所问。你会先压缩历史还是先压缩知识?为什么? 高频
量法:把当前上下文按四类成分切开数 token。典型分布是知识只有几千 token,而二十轮的历史消息加工具返回值可以到 20 万 token 量级,指令与工具定义合计往往不到 10%。
压状态的三个动作:① 中间产物外置,上下文只留文件名清单与指针;② 阶段摘要,固定四段字段(目标 / 已完成 / 关键结论 / 待办),只丢过程不丢结论;③ 单条超长结果做头尾保留裁剪,超过窗口 10% 就裁,并标注省略了多少字符。
判据:压完之后重跑失败样本,完成率不掉,说明被删掉的内容本来就没被用到。
追问链
- 怎么判断一段历史属于「过程」还是「结论」?
- 摘要压三次之后开始丢任务目标,你怎么防?
同样的内容,只调整排列顺序,成本能差多少?给一个可以验证的判据。
判据是相邻两轮请求体的字节前缀:把第 N 轮与第 N+1 轮的请求体转成字节串,从第一位开始比对,找到第一个不同的偏移量。
偏移量落在前 1%(总长 100k 时即前 1k 以内)→ 缓存基本全废,每轮都在重算全部历史;偏移量落在 90% 之后 → 前面被复用,这一轮的输入成本约等于新增的那一段。
所以纪律是按变化频率排序:稳定的靠前(指令、工具定义、任务目标),每轮都变的放最后(用户输入、最新工具结果)。把时间戳、记忆片段、随机 id 放进头部,等于每轮主动把缓存清零。
附带的收益是:新信息在尾部离生成位置更近,相关性也更好——成本和效果在这里是同向的。
追问链
- 工具定义顺序不稳定会怎样?怎么保证序列化后字节稳定?
- 如果业务上必须在头部放用户名,有什么折中方案?
上下文窗口已经到 1M token,「把整个代码库塞进去」这件事还需要检索吗?
① 成本:注意力是平方复杂度,序列翻倍算力约翻四倍;一次任务发十五轮,就等于把整个代码库重复处理十五次。窗口变大不会让这件事变便宜。
② 信噪比:1M token 里与当前问题真正相关的可能不到 1%。真实判断依据的占比从 18% 被稀释到 10%,模型会「越跑越笨」——收得下不等于用得上。
③ 判断依据要可核对:检索来的片段能带来源与层级(fact / inference / opinion),全库直塞则没有任何可信度信息,模型只能一视同仁地采信。
所以窗口变大改变的是「检索可以少而精,还是可以多塞一点」,不改变「先检索再注入」这条结构。
追问链
- 要做「长上下文直塞」与「检索注入」的 A/B,你会怎么设计对照组?
- 什么样的任务确实更适合全量直塞?给一个判据。
05 Memory 记忆系统 6 问
长期记忆你会存什么?什么时候写? 高频
写入时机是这道题的关键:只在信号足够强的时候写——用户显式纠正("以后别用表格")、用户显式声明("我在做招聘")、或者同一偏好被重复观察到多次。绝不能把每一次会话里的临时要求都写进去,否则记忆区会变成噪声区,注入后反而干扰判断。
配套要求:写入带时间戳与来源,支持用户查看与删除,并设置 TTL 或衰减机制。
追问链
- 怎么防止把一次性偏好写进去?
- 记忆检索是走向量还是规则?
记忆和新事实冲突了怎么办?
① 先分类——是"偏好变化"还是"事实变化"?偏好变化(从喜欢表格改成喜欢列表)通常是覆盖;事实变化(换团队了)也是覆盖,但要保留历史区间。
② 带时间与置信度——每条记忆都有生效时间与置信度,冲突时高置信度优先;同等置信度则新的优先,但把旧的标记为 superseded 而不是删除。
③ 不可消解就暴露给用户——如果两条记忆指向矛盾结论(用户说"汇报要简洁",但历史反馈显示他常要求补充细节),不要自己赌,应该在输出时给出选择或直接询问。
核心原则是:记忆系统要能解释自己为什么这么判断,否则出错时无法排查。
怎么证明记忆让效果变好了,而不是让输出变得飘忽?
做法是 A/B:同一批任务分别跑「注入记忆」与「不注入记忆」两条链路,对比任务完成率、人工介入次数、以及目标风格的一致率。要特别关注负向信号:注入记忆后,模型是否开始在不相关场景里生搬硬套旧偏好(过拟合);是否出现"忘了任务本身要求,只记得风格要求"(注意力争夺)。
工程上还有两个必要设计:记忆可关闭(某个任务可以临时不使用历史偏好)和记忆可追溯(输出里能看出用了哪条记忆)。没有这两样,记忆出问题时你会连原因都定位不到。
设计一个写入触发器系统,你怎么决定一条信息「该不该写」进记忆? 高频
其中自动抽取噪音最大,必须设稳定性阈值加定期清理,且优先用显式指令触发。
答出「稳定性阈值 + 定期清理 + 显式指令优先」说明真做过,而不是背过。
追问链
- 自动抽取噪音占比超过多少就该告警?
- 显式指令写入后要不要回显确认?
两条记忆语义相反、且无时间差(真伪冲突),系统该怎么处理?
用户澄清后会产出一条高置信度新记忆,把冲突真正解决。
选边就是在假装自己知道答案,比明确的「不确定」危害更大。
追问链
- 如果用户一直不回应怎么办?
- 怎么把这次澄清沉淀成高置信记忆?
记忆去重为什么不能靠原始字符串相等判断?那该怎么判断?
正确做法是先归一化再取指纹:把同一实体归一到同一个 key、值做规范化(单位、大小写、空白),再对规范化后的内容取哈希做跨库去重;更新时改旧版本的 superseded_at,而不是新建一条。
判据:去重键必须是「实体 + 属性 + 规范化值」的指纹,光对原文取哈希只能挡住一字不差的重复。
追问链
- 归一化漏掉一种表述会怎样?
- 更新时是覆盖还是标记失效?
06 Subagent 与多智能体编排 6 问
为什么要用 Subagent,而不是一个长上下文 Agent 一直做下去? 高频
① 上下文隔离——如果所有子任务都塞进同一个上下文,会互相污染(无关信息干扰判断),而且上下文会迅速膨胀到需要频繁压缩,压缩就会丢信息。Subagent 各自持有干净上下文,只装载与自己任务相关的信息。
② 并行提速——互相独立的子任务可以并发执行,端到端时间从求和变成取最大值。
③ 权限与提示隔离——不同子任务需要的工具权限不同(读数据的和写数据库的不该有同样的能力),分 Agent 天然形成权限边界;同时每个 Subagent 可以有专门化的提示词,比一个"什么都会"的通用提示更稳。
但要多说一句:跨 Agent 传递只走结构化产物(文件、JSON 结果),不要用自然语言转述,否则会引入"传话失真",这是多 Agent 系统最常见的翻车方式。
追问链
- 部分子任务失败了怎么办?
- 结果汇总阶段会不会又变成一个长上下文问题?
多 Agent 怎么协作?有哪些组件?
① Orchestrator(调度与规划,负责拆任务、下发、汇总);
② Subagent Pool(执行单元,各自独立上下文与能力集);
③ 通信层(结构化消息:任务目标 + 约束 + 输入产物指针 + 期望输出 schema);
④ 结果汇总层(按 schema 校验、去重、冲突标注);
⑤ 失败隔离层(单个子任务失败不阻塞其他,可重试或降级,明确"部分成功"语义);
⑥ 可观测层(每个 Subagent 的 trace 挂到同一个任务链路下)。
模式上主要三种:Supervisor(集中调度,适合任务可明确分解)、Pipeline(固定阶段流水线,适合稳定流程)、去中心化(适合探索型、无明确分解方案)。
选型标准是任务可分解性 + 失败隔离需求——不是 Agent 越多越好。
多 Agent 系统的常见踩坑有哪些?
① 传话失真——用自然语言在 Agent 之间转述需求,每转一手丢一点信息。解法是只传结构化产物,且用 schema 强制约束。
② 上下文重复膨胀——为了"让子 Agent 有足够信息",把主上下文整个复制下去,结果每个子 Agent 都背着几十 K token,成本和延迟全部失控。解法是只下发该子任务的最小必要上下文,其余通过工具按需拉取。
③ 汇总变成新的长上下文——Oracle 把所有子结果原文拼起来再决策,又回到长上下文问题。解法是要求子 Agent 输出结构化摘要 + 产物指针,汇总层只读摘要,需要细节时回读产物。
④ 死锁与循环等待——A 等 B 的结论、B 等 A 的输入。解法是显式依赖图 + 超时 + 单向数据流。
把 12 万 token 的材料放进主上下文、任务还要迭代 5 轮,改成 3 个 Subagent 各读 4 万 token,两边输入量差多少? 高频
差约 4.9 倍,而且差距随轮数继续拉大——单 Agent 那一侧是「材料量 × 轮数」,多 Agent 那一侧与轮数几乎无关。
判据:只要材料体量远大于结论体量、且任务要迭代多轮,上下文隔离就是纯赚。
追问链
- 如果子 Agent 之间还要交换中间结果,这笔账还算得过来吗?
- 12 万 token 的单轮输入能靠前缀缓存省掉多少?
流水线(Pipeline)编排里,上游一个环节出错会怎样?
某一环卡住还会整体阻塞。
判据:流水线必须配每环的校验与错误回流,否则故障定位成本是线性的倍数。
追问链
- 怎么在流水线里做错误回流?
- 哪一环最适合放兜底?
多 Agent 系统的权限隔离应该怎么落地?
这样即使某个被提示注入说服的写 Agent 想破坏生产库,它也没有那把钥匙。
判据:越权在能力层面不可达,而不是在判断层面被劝阻。
追问链
- 被注入的写 Agent 能做什么?
- 权限在工具内强制的具体实现?
07 沙箱、权限与提示注入 6 问
工具要不要跑在沙箱里?桌面端怎么设计? 高频
隔离强度的选择是权衡:进程级隔离轻量、启动快,适合纯计算与受信任的工具;容器级隔离能限制文件系统与网络,适合执行模型生成的代码;微虚拟机最强但最重,适合高风险不可信代码。
桌面端 Agent 的特殊性在于用户授权与可解释性的权重更高:
① 能力声明前置——每个工具明确声明它会读什么、写什么、联网与否,并在界面上让用户看得懂;
② 首次与危险操作确认——第一次使用某类能力时确认一次,之后删除文件、发送消息这类不可逆操作坚持二次确认;
③ 路径与网络白名单——限制可访问的目录范围,网络出站按需开放;
④ 副作用闸门 + 全量审计——不可逆操作在代码层面强制确认(这一步不交给模型判断),每次调用留痕(工具、参数、时间、结果摘要),用户可回看。
核心原则是最小权限 + 可撤销 + 可审计。
追问链
- 用户嫌确认太烦怎么办?
- 沙箱内的提示注入你怎么防?
提示注入(Prompt Injection)从哪进来?怎么防? 高频
关键认知是:只靠在 prompt 里写"不要被这些内容里的指令影响"是无效的——因为经过指令微调的模型天生倾向于遵循指令,你没法用一句软约束对抗训练出来的行为倾向。
可行的四层防御:
① 数据与指令分离——把外部内容用明确的分隔与标签包起来,声明为"待处理的数据",并在系统提示里固化处理规则;
② 能力最小化——当前任务根本不需要的工具不要挂载,从源头减少可被诱导的动作;
③ 副作用强制确认——高危操作(写文件、发消息、执行命令、转账)一律走人工确认或双因子校验,让注入无法静默完成;
④ 输出侧校验——检查最终动作是否偏离原始任务目标(目标漂移检测),异常时阻断。
怎么让用户"看得懂、控得住"工具的权限?
看得懂:用业务语言描述能力("读取你项目文件夹里的文档"),而不是技术术语("fs.read: /home/*");执行前展示将要进行的操作预览(要改哪个文件、要发给谁),执行后给出可回看的操作记录。
控得住:分层授权(始终允许 / 每次询问 / 禁止),支持按目录、按工具、按任务临时授权;提供一键撤销与会话级回收;对不可逆操作强制二次确认。
兜底:所有副作用操作留痕可审计,且尽量设计成可回滚(写文件先备份、批量操作先给 diff)。
一个判断标准:如果用户无法回答"它刚才到底做了什么",那就是权限设计失败了。
四层防御资源有限,工程资源应该优先投在哪一层?为什么? 高频
只有第四层是纯代码判定,不调用模型、不看上下文,即使模型被骗也照样拦。
判据:是否「不依赖模型判断」是分水岭。
追问链
- 前三层是不是就没用?
- 审计记录最少要包含什么?
文件名、文档标题这类元数据,要不要和正文一样做净化?
判据:任何进入上下文的字段——文件名、标题、标签、作者名——一律净化,不因为它是元数据就默认可信。
追问链
- 为什么元数据里模型警惕性更低?
- 净化入口怎么统一?
批量删除工具一次要删 4,200 条记录,靠「不可逆操作弹确认框」拦得住吗?该怎么设计?
正确做法是在闸门里把「批量规模」做成与「不可逆」并列的一条独立规则——本章的实现里,工具名带
bulk_ 前缀且一次超过 100 条的调用直接拒绝,返回「需拆分或人工执行」,而不是给一个可以一键点掉的确认框。判据:批量上限与不可逆判定是两条独立规则——确认框管「要不要做」,规模上限管「一次能做多大」。
追问链
- 100 这个上限是怎么定出来的?
- 拆分之后的每条操作还要不要单独确认?
08 长任务与失败恢复 7 问
你做 Agent 的时候遇到过哪些工程挑战? 高频
① provider 侧不稳定——限流、超时、通道抖动,需要多通道抽象 + 健康探测 + 自动切换 + 切换后的结果一致性校验;
② 流式输出卡死——连接还在但不出 token,需要首 token 超时 + 空闲心跳超时 + 强制中断与重试;
③ 上下文溢出——主动计量、分级压缩、状态外置,并在触发时给用户可见提示;
④ 长任务中断恢复——进程被杀、机器重启,需要任务状态机 + 检查点 + 断点续跑;
⑤ 副作用重复——重试导致重复写库,需要幂等键与去重表;
⑥ 成本失控——预算上限、轮数上限、缓存友好前缀;
⑦ 变更风险——prompt 一改就翻车,需要版本化、灰度、自动回滚。
答完再补一句:这些问题的共同点是"模型没坏,是系统没兜住",这正是 Harness 存在的价值。
追问链
- 流式卡死具体怎么检测?阈值怎么定?
- 上下文自动压缩在架构上放在哪一层?
模型输出卡死(连接还在但不出 token)怎么发现、怎么恢复? 高频
① 首 token 超时——从发起请求到收到第一个 token 的时间上限。这能抓住"请求已受理但模型排队/卡住"的情况,阈值取实测 P99 再放宽,比如 30–60 秒。
② 空闲心跳超时——两个相邻 token 之间的最大间隔。这能抓住"已经开始输出但中途挂住"的情况,阈值可以比首 token 短得多,比如 10–20 秒。
③ 总时长上限——整个响应的时间上限,防止"一直缓慢吐字"把任务无限拖下去。
任一触发就主动中断连接(不要等对端),记录现场(已收到的部分内容、耗时、阶段),然后按策略恢复:同一通道重试 → 换通道重试 → 降级到非流式 → 报错并把中间结果交出。
判断"慢"还是"死"的关键是心跳:只要还在稳定吐字就不算卡死,所以不能只看总时长。
长任务跑到一半崩了怎么办?
状态机至少要覆盖:排队、运行、等待人工确认、暂停、成功、失败、重试中、已取消——每个状态有明确的进入/退出条件与持久化内容。
检查点要落盘四样东西:任务目标与约束、已完成步骤清单、每步的产物指针、下一步计划。落盘时机选在"每个子目标完成之后"而不是固定时间间隔,因为子目标边界才是真正的可恢复点。
恢复流程是:读出检查点 → 校验产物是否已存在(避免重复执行)→ 从下一个未完成步骤继续,并把"之前发生过什么"用摘要注入上下文。
还有一个容易被忽略的点:重试不能重复副作用,所以恢复时必须先查状态再决定是否执行,而不是无条件重放。
你的系统怎么区分"工具超时了"和"工具执行失败了"?
执行失败意味着服务明确返回了错误(4xx/5xx、业务异常),说明请求已被处理且结果是失败——通常不该原样重试,要么修参数,要么换方案。
超时意味着我们只是没等到回应,请求可能成功了、可能失败了、也可能还在执行中——这叫"结果未知",比失败更危险,直接重试可能造成重复副作用。
所以正确做法是:对可能产生副作用的工具,超时后先走状态查询(用幂等键或业务 ID 查这次调用到底有没有生效),确认未生效才重试;如果工具没有查询接口,就不该给它自动重试的权限,只能上报人工处理。
这也解释了为什么设计工具时就要把幂等键和查询能力作为契约的一部分,而不是事后补。
上下文窗口 128k、触发阈值 60%、单条工具结果上限取窗口的 10%。某工具一次返回约 4 万 token 的结果,压缩流程会先对它做什么? 高频
裁剪方式是头尾保留:留头部 60%、尾部 30%,中间约 10% 替换成「此处省略 N 字符」的显式标注。
判据:先裁单条、再摘要整体,且省略量必须显式写出——否则模型会以为看到的就是全部内容。
追问链
- 为什么尾部只留 30% 而头部留 60%?
- 省略标注为什么不能省掉?
上下文自动压缩能救回窗口,但它会改前缀——和 KV Cache 的命中率怎么权衡?
解法不是二选一,而是把压缩做成「少改头部、多动尾部」:不可压缩区(原始目标、用户约束、已确认结论)放在最前且只追加,压缩只作用于后面的过程性内容——这样头部前缀始终稳定,保住的是最贵的那一段。
判据:阈值要留足余量(本章实现里到 60% 就触发),一次压到位;比起窗口满到被迫压缩甚至报错,多付一次 prefill 的钱是划算的。
追问链
- 为什么头部比尾部更值得保?
- 如果把动态内容都放到头部会怎样?
为什么要把所有模型调用收敛到一个 provider 适配层?
判据:模型名、端点、能力差异都收口在适配层,业务代码不感知 provider。
追问链
- 不支持工具调用的模型怎么降级?
- 能力探测具体探测什么?
01 评测的第一性问题 6 问
你怎么知道一版改动真的让 Agent 变好了? 高频
① 固定的评测集——改动前后跑的是同一批题,否则数字不可比;
② 明确的基线——上一版的数据是什么,没有基线就没有"变好"这个概念;
③ 噪声估计——同一版本重复跑多次,看指标的波动区间。如果提升幅度落在波动区间内,那不能算改进。
实践上还要注意两点:看分布而不只看均值(平均分涨了但某些关键场景崩塌,这是净损失);区分"变好"和"变长"(轮数变多、token 变多往往能刷高完成率,但用户体验和成本都变差了,所以指标必须成组看)。
追问链
- 怎么估计噪声?
- 如果提升只有 2 个百分点,你上线吗?
为什么说"感觉这次好多了"不能作为工程结论?
① 样本偏差——你试的往往是自己熟悉的几个 case,而线上失败集中在长尾;
② 确认偏差——你刚改完,倾向于把符合预期的表现看成改进,把不符合的看成偶然;
③ 无基线——没有同时跑旧版本,等于没有对照,无法排除"这次任务本来就简单"。
不是说主观判断没价值,它的正确用途是发现"哪里不对"(产生假设),而不是判断"是否变好"(验证假设)。前者靠人,后者靠评测。
离线评测和线上指标的关系是什么?
离线评测回答"在受控条件下,这一版的正确性有没有退化"——可复现、可归因、能拦住回归,但它的任务分布是过去的,未必代表未来。
线上指标回答"在真实流量下,用户是否真的受益"——分布真实,但噪声大、混杂因素多(用户群变化、流量结构变化),归因困难。
正确的用法是用离线守回归底线,用线上看真实收益:离线不通过不上线;离线通过后灰度上线,用线上数据验证;线上出现新的 badcase,回流进离线评测集。离线评测集就是由线上 badcase 长出来的,这样两者才形成一个闭环而不是两套体系。
线上完成率从 78% 掉到 75%,你第一件事做什么? 高频
① 查历史波动:把同一版本连续跑多次的分数拿出来,看这个指标的波动带有多宽;如果它历史上本来就在 ±4 分之间抖动,3 个百分点落在带内,先记为噪声。
② 查口径有没有变:分子、分母、样本集、规范化规则的版本有没有动过——口径一改,数字立刻不可比,这类「假回归」比真回归更常见。
③ 查分层:整体掉 3 分,是均匀下降还是某一层崩了?如果对抗集掉了 15 个百分点,哪怕整体只掉 3 分也必须立刻查。
顺序很重要:先排除口径与噪声,再去动代码,否则你会在噪声上改出一个特判逻辑。
追问链
- 如果团队没有留存历史波动数据呢?
- 分层指标里,哪几层的跌幅你最不能容忍?
评测集只有 20 条,改动后通过数从 8 条变成 10 条(40% 到 50%)。这个改动能上吗?
n=20 时比例估计的 95% 置信区间宽度在 ±22 个百分点量级:40% 的区间大致是 20% 到 60%,50% 的区间大致是 30% 到 70%,两者大面积重叠。
要稳定分辨 5 到 10 个百分点的差异,样本量通常需要几百条量级;而且要看的是分层够不够,不是总数够不够。
正确动作有两个:① 先在保留池上验证提升是否复现;② 把这次改动涉及的场景抽 50 到 100 条补进评测集,再来判断。
追问链
- 要多大样本量才能分辨 5 个百分点?
- 如果保留池上的提升更大,你会怎么解释?
怎么用一句话检验你拆出来的两个评测维度是不是正交?
能构造出来,说明两维可以分别变化,是独立的;构造不出来,说明它们其实是同一件事,应该合并或重新拆。
举例:把「准确」和「有用」并列就不成立——不准确的答案很难有用,构造不出干净的反例,两者高度相关。而「方向相关性」和「可操作性」可以:一份方向完全正确、证据齐全,但通篇没有下一步动作的分析,就是真实存在的「方向满分、可操作零分」样本。
这条判据的工程价值在于:它把维度设计从文字游戏变成了可以做实验的事。
追问链
- 如果两个维度的相关系数是 0.9,你会怎么处理?
- 一票否决与加权求和,分别适合什么形状的维度关系?
02 评测集建设与防过拟合 6 问
你的评测集是怎么建起来的? 高频
① 采集——从线上失败案例(用户重试、纠错、放弃、人工介入的会话)中捞取原始输入与完整链路,这些是最有信息量的样本;
② 归因分类——把失败按原因打标(理解错意图 / 参数生成错 / 工具选择错 / 上下文缺失 / 表达问题),保证每个类别的样本数够,否则指标会被大类淹没;
③ 固化——整理成带期望输出的测试用例,人工确认标注正确后入库,并保留原始链路便于 replay。
另外要主动构造一部分边界与对抗样本:模糊表述、自相矛盾的输入、超长输入、以及"工具返回了恶意内容"的注入场景——这些线上出现频次低但破坏力大,靠等线上出现太被动。
追问链
- 多少条算够?
- 怎么保证评测集不过期?
评测集多少条才够用?
几十条的评测集只能发现"明显崩了"(掉了十几个百分点),无法判断"提升 2% 是不是真的";要稳定分辨几个百分点级别的差异,通常需要几百条量级,而且每个关键类别(而不是总数)都要有足够样本——因为指标是按类别看的。
更实用的建议是先建小而纯,再逐步扩充:30–50 条覆盖核心场景的"冒烟集",用来快速拦住大回归;300 条以上的"回归集",用来判断小改动是否有效。不要一开始就追求几千条,那会因为标注质量参差而变得不可信。
怎么防止系统把评测集"背下来"?
① 保留集(hold-out)——把评测集切成可见/不可见两部分。调优时只能看可见部分,最终验收用不可见部分。如果两者差距很大,说明过拟合了。
② 持续注入新样本——评测集不是一次建完的静态资产,线上新 badcase 要持续回流,让评测集不断变难。一个长期不更新的评测集,指标会逐渐失去区分度。
③ 生成式与参数化样本——对于可枚举的任务(查询条件生成、参数填充),用模板 + 参数组合自动生成大批样本,让"记住答案"在成本上不可行。
判断是否过拟合的信号很直接:评测集上稳步提升,但线上指标不动甚至下降。出现这个现象就要立刻检查评测集是否已经泄漏。
评测集三个月没更新,分数一直停在 96% 左右不动。这说明什么,你打算做什么? 高频
96% 的稳定高分意味着这套题已经覆盖不了当前线上会遇到的难点,剩下那 4% 是长期修不动的硬骨头。指标不再变化,就无法反映改动的效果,评测作为工具的价值归零。
动作有三步:① 加难度,从最近三个月的线上 trace 里抽失败与重试点,构造边界集与对抗集样本;② 检查配比,如果四层里对抗集是空的,那安全类问题根本没被覆盖,96% 只是简单题占比过高的产物;③ 轮换,把保留池里一部分旧样本下放到调试池,从新数据里补新样本进保留池。
判据:一个评测集如果连续两个季度波动不超过 1 个百分点,就该重建了。
追问链
- 怎么区分「系统真的稳定」和「评测集失效」?
- 轮换保留池时,怎么保证历史分数仍然可比?
调试池 92%、保留池 68%,你接下来怎么处理这 24 个百分点的差距?
① 排除划分噪声:确认两个池子是不是用同一份哈希规则划分的;如果保留池只有二三十条,先看它的置信区间有多宽。
② 定位差距来源:把两个池子按分层切开对比。如果差距集中在回归集,说明存在针对具体样本的特判;如果各层普遍偏低,说明能力本身没有泛化。
③ 检查最近的改动:有没有出现「针对某几条样本加的特判」「在提示词里写死的例子」。这类改动的特征就是调试池涨、保留池不动。
④ 处理:补新样本稀释调试池,把最近一轮改动回滚重做,并且不再看调试池的单条样本。
判据:24 个百分点已远超噪声,必须当结构性问题处理,而不是当成一次运气不好。
追问链
- 保留池样本量很少时,怎么判断这 24 个百分点是真的?
- 为什么说「看调试池的单条样本」本身就是过拟合的开始?
从线上一条 trace 到一条能进回归集的样本,中间哪一步最容易做错?
新手很自然地把当时正确的回答原文抄下来当标准答案,于是立刻出现两个问题:① 同一件事有无数种正确说法,换个措辞就被判失败,回归集天天报假警;② 无法自动判定,只能靠人读,样本一多就没人跑了。
正确做法是标注可判定的行为:应该调用哪个工具、关键参数应该是什么、是否应该拒绝、是否应该先追问澄清。
另一个高频错误是漏掉来源与原因,三个月后没人知道这条样本为什么在这里,于是谁也不敢删,回归集只涨不减。判据:缺
origin 或 reason 的样本一律拒收。追问链
- 哪些 badcase 不该进回归集?
- 脱敏之后还能保证可复现吗?
03 办事型 Agent 的硬指标 6 问
"参数生成准确性"具体怎么算? 高频
① 枚举类参数(状态、类型、操作符)——精确匹配。生成值必须在合法枚举集合内且与期望一致,错一个就是错。
② 数值类参数(阈值、数量、日期区间)——精确匹配或带明确容差的近似匹配,容差要事前写清楚(例如日期允许 ±0,金额允许 ±0.01)。
③ 自由文本参数(检索关键词、描述字段)——结构化逐项比对:先把期望拆成必含要素集合,再检查生成结果覆盖了哪些要素,得分是覆盖率;若有明确禁止项,命中即扣分。
④ 集合类参数(多选标签、字段列表)——用精确率/召回率或 Jaccard 相似度,而不是"差不多就行"。
还有两个必须明确的口径问题:分母是什么(所有调用,还是只统计"模型认为该调用工具"的那些);部分正确怎么算(4 个参数对 3 个,是算 0 还是 0.75——不同选择会得出完全不同的结论)。
追问链
- 分母你选哪个?为什么?
- 部分正确你怎么处理?
工具调用成功率这个指标有什么陷阱?
① 分母陷阱——如果把"模型压根没调工具"的情况排除在分母外,成功率会虚高,掩盖"该调不调"的问题。分母应该是所有本应调用工具的场景。
② 成功定义陷阱——HTTP 200 不等于任务成功。要区分"调用发出成功""参数正确""业务结果符合预期"三层,混在一起会看不出问题在哪。
③ 难度混同陷阱——把简单查询和复杂多步任务混在一个数字里,任何改动都会被大类淹没。应该按任务类型分层看。
④ 重试归因陷阱——经过重试才成功的算不算成功?我倾向于分开统计:一次成功率(反映模型质量)与最终成功率(反映系统兜底能力),两者同时看。只看最终成功率,会让"重试兜住一切"掩盖模型本身的问题。
任务完成率怎么定义?由谁判定?
① 自动化判定——任务有明确的可验证结果(生成了符合条件的文件、查询返回了非空结果、代码通过了测试),这是最可靠的,应当优先把任务设计成可自动验证的。
② 模型判定——用 LLM 对照 rubric 打分,适用于结果无法程序化验证的场景,必须配人工抽检校准。
③ 人工判定——最准但成本最高,用于校准前两者、以及构建金标准集。
工程上的目标是把尽可能多的任务转化为第 ① 类:给任务设计机器可验证的产出(结构化结果、断言、测试),这比提高打分模型的准确率更根本。
「不可解样本处理率」单独成指标之后,对模型的行为激励发生了什么变化? 高频
在只有「完成率」的世界里,面对信息不足的问题,最优策略是硬猜一个答案——猜对了算完成,猜错了也不比拒绝更差,而拒绝或追问会被算作没完成任务,直接拉低分数。系统因此被塑造成一台过度自信的答题机器。
单列「不可解处理率」之后,分母只算不可解样本,正确拒绝或追问澄清算通过。硬猜的收益变成负数,追问开始得分。
工程含义是:分子分母的设计会直接塑造系统行为。所以评测集里必须真的有一批不可解样本,否则这个指标分母为零,等于不存在。
追问链
- 怎么判断一条样本到底算不算不可解?
- 追问澄清的成功率怎么定义——追问一次就算成功,还是要追问到点上?
参数准确率的四种粒度里,哪一种最不容易被「碰巧写对」骗过?
结构级最容易被骗:JSON 能解析、字段齐全就算通过,语法对而语义全错也能拿分。字段级好一些,但仍可能「参数写对了,管道里还有别的 bug」。语义等价级贴近「能不能用」,可它判断的依然是参数。
结果级是唯一直接对准「这个查询有没有把用户要的数据取回来」的粒度:参数碰巧写成等价形式、或者查了别的东西却结果一致,概率都低得多。
代价是需要一个可执行环境,成本最高。所以实践中的组合是:字段级与语义级做日常快速回归,结果级做发版前的最终验收。
追问链
- 结果级判定下,「跑得通但结果为空」算通过吗?
- 如果环境不可执行,你会退回到哪一级,为什么?
规范化规则新增了一条同义词映射,参数准确率涨了 6 个百分点。这算改进吗?
同义词映射放宽了判定标准:原本判错的等价表达(比如「华东」与「east」)现在判对了。分数的上升来自评判的尺子变松,与系统行为无关。
正确做法:① 把规范化规则当代码管,改一次就打一个版本号;② 指标连同规则版本一起报,跨版本的分数禁止直接相减;③ 规则变更的那一版不要拿新旧数据做对比,要对比就用同一套新规则把历史结果重算一遍。
判据:任何一次改动只要碰了评分代码,就必须重跑基线,而不是直接拿新分数和旧分数比。
追问链
- 重算历史基线很贵,有没有更省的做法?
- 同义词表越加越宽,会带来什么风险?
04 洞察型评分与 LLM-as-Judge 6 问
洞察型 Agent 的"内容质量"怎么评? 高频
① 方向相关性——产出的分析是否落在问题上,有没有跑偏到无关角度;
② 证据充分性——结论是否有可溯源的数据支撑,还是只是合理推测;
③ 可操作性——是否给出了能落地的判断或建议,而不是正确的废话;
④ 表达清晰度——结构是否清楚、重点是否突出、有没有冗余。
每个维度用 3–5 级量表并写清每级的判定标准(rubric 的关键是让不同评分者得出接近的结果)。
最重要的设计是:维度分不是用来算总分的,而是用来做归因的——低分出现在"证据充分性",说明是检索没召回;出现在"表达清晰度",说明是提示或组织问题。只有能定位到环节,评分才有迭代价值。
追问链
- 维度之间高度相关怎么办?
- 怎么知道评分标准本身是合理的?
LLM-as-Judge 有哪些偏差?怎么控制? 高频
① 位置偏差——倾向给排在前面的答案更高分。对策:交换顺序各评一次,取一致结论;不一致就判为平局或人工介入。
② 长度偏差——倾向给更长、更"全面"的回答高分。对策:rubric 里显式区分"信息量"与"篇幅",加一条"冗余扣分";或对长度做归一化后再比较。
③ 自我偏好——偏爱自己(同族模型)生成的文本。对策:用不同模型评判,或至少做交叉验证;关键评测用人工校准。
④ 格式/表述偏差——被排版、markdown 结构、自信的语气影响。对策:rubric 明确只看内容不看形式,或统一后处理格式再评。
此外必须有人工抽检校准:定期抽一批让真人评,与机器评分比对,一致率下降就说明评判标准漂了,要回去修 rubric。
为什么不能只看平均分?
三种典型情况:① 平均分涨了但关键场景崩了(比如回答变得很长,平均分因信息量提升而上涨,但简短咨询类场景全部变糟);② 平均分不动但方差变大(一端显著变好、另一端显著变差,稳定性实际下降);
③ 高分样本挤占(某些原本满分的场景现在稳定扣一点分,被其他场景的涨幅掩盖)。
所以指标要成组看:均值 + 分位数(P5/P95)+ 关键场景单独看 + 最差类别。我在实践中会额外维护一份"绝不能退化的场景清单",无论平均分怎么涨,这些场景退化就是不能上线。
一份输出四维得分 4/4/1/4,另一份 3/3/3/3。你会怎么汇报这两份? 高频
4/4/1/4 的短板是可操作性只有 1 分:方向对、证据足、表达清楚,但通篇没有下一步动作,业务方拿到手里不知道要做什么,实质价值接近零。3/3/3/3 虽然没有任何一维突出,但每一项都合格,是可以读、可以执行的。
汇报要分两层:① 判定层,先应用一票否决规则(可操作性 ≤ 2 分即不合格),给出通过与不通过;② 归因层,再报四维明细,指出卡在哪一维、该去改哪个环节——可操作性低往往指向提示词里没有要求给出动作,而不是检索出了问题。
用平均分汇报的代价是:你会把一个不可交付的输出和一个合格输出并列。
追问链
- 一票否决的阈值定在 2 分还是 3 分,依据是什么?
- 如果四项都平均但都不高,你会怎么定位下一步?
用一次实验测出评审模型的位置偏差有多大,你会怎么设计?
取 30 到 50 对输出,对每一对跑两次评审:第一次把 X 放在 A 位、Y 放在 B 位,第二次交换。两次都指向同一个原始样本记「一致」,结论相反记「翻转」。翻转率就是位置偏差的强度。
三个设计要点:① 两次调用必须同参数、温度设 0,否则测到的是采样噪声;② 不要试图测出「偏移量」再校正,偏差是非线性的,正确用法是拿一致性做过滤——一致的才采信,不一致记平局;③ 顺便对比「能力差距悬殊」与「能力接近」两组,能力接近时翻转率明显更高,说明这套评测对微小改进本来就没有分辨力。
追问链
- 翻转率 20% 算高吗,多少算可接受?
- 平局占比很高的时候,这份评测还有用吗?
为什么「先用 A 模型生成洞察,再用 A 模型评审」得到的漂亮分数不能信?
同源模型有相同的表达习惯、相同的偏好、相同的盲区。A 生成的内容天生符合 A 的审美,A 评审自然打高分;换一批用户、换一个模型家族,这个分数会整体下降,而且排序也会变化——也就是说它对「谁更好」的判断不可迁移。
这套流程还有一层迷惑性:分数不但高,而且很稳。稳定性通常被当成评审可信的证据,但在这里它恰恰是自证的特征。
正确做法三条:评审模型与生成模型不同源;每轮评测抽 30 到 50 条人工打分,算人工与机器的同向率,低于 75% 时机器分数不得用于决策;把「用机器评审降低人工成本」和「用机器评审替代人工判断」严格分开。
追问链
- 换一个不同家族的模型评审后同向率仍然很低,问题可能出在哪?
- 人工校准要抽多少条、多久抽一次才够?
05 Trace、Replay 与线上闭环 6 问
Trace 你会记录哪些字段? 高频
任务级——任务 ID、用户、入口、目标与约束、开始/结束时间、最终状态、总 token 与成本。
轮次级——轮次编号、模型与参数、完整的 prompt 组成(含系统提示版本号、注入的上下文片段及其来源、裁剪了什么)、模型原始输出、解析后的工具调用、耗时、输入/输出 token、缓存命中情况。
工具级——工具名与版本、参数、执行耗时、返回结果摘要与原始结果指针、错误分类、是否重试。
变更级——本次运行使用的 prompt / 工具 / 模型配置版本号。
两个容易被漏掉但很关键的字段:prompt 的各段来源与版本(否则改了提示词就再也复现不了旧结果)、以及裁剪/压缩的日志(否则你不知道模型当时"没看到"什么)。
追问链
- 存原始 prompt 全文会不会太大?
- 怎么按任务链路把多 Agent 的 trace 串起来?
Replay 有什么用?
① 复现——线上失败很难在开发环境重现(输入随机、上下文巨大、依赖外部状态),replay 让你用当时的完整输入重跑,把不可复现变成可调试。
② 对比——在同一个测试用例上跑旧版本与新版本(A/B replay),直接看出行为差异,这是判断改动是否有效的核心手段。
③ 回归——把有代表性的 trace 固化成回归用例,每次改动自动重放这批用例,形成门禁。
实现要点是把"可重放"作为架构约束而不是事后补的功能:所有外部依赖(模型、工具、检索)都要能在 replay 模式下用录制结果替换(mock/replay 层),否则外部状态一变,重放就不成立。
从线上 badcase 到回归门禁,完整闭环怎么建?
① 发现——通过用户反馈信号(重试、纠错、放弃、点踩)与系统指标异常(成功率下降、超时率上升)自动捞取候选 badcase。
② 归因——按失败原因打标分类(意图理解 / 参数生成 / 工具选择 / 上下文缺失 / 表达 / 系统故障),并区分"模型问题"与"系统问题"。
③ 固化——把可复现的案例整理成评测用例入库,保留原始 trace。
④ 修复——针对原因改对应的层(提示 / 工具描述 / 上下文策略 / 代码逻辑),而不是一律改提示词。
⑤ 回归——在固定评测集上跑,既有全量指标也要看新用例;不能有回归才允许进入下一步。
⑥ 灰度与回滚——按用户或租户灰度,监控线上指标与失败率,劣化自动回滚,正常后放量。
这个闭环能持续运转的前提是第 ③ 步要自动化一部分,否则人工整理会成为瓶颈,闭环很快就断了。
PR 阶段的门禁要求跑 40 分钟全量评测,团队开始加 skip-eval 标签。你怎么改? 高频
① 本地提交前:只跑解析器与错误分类的单元测试,10 秒级;② PR 创建后:只跑冒烟集(10 到 20 条)加静态检查,控制在 2 分钟内,不通过就阻塞合并;③ 合并到主分支后:跑回归集与边界集,15 分钟级,失败产生告警并自动建 issue;④ 发版候选:跑全量(回归、边界、对抗、保留池),可以到 1 小时,不通过阻塞发布。
关键判断是:门禁的价值不是「跑得多」,而是「跑得久」——一个总被绕过的门禁,价值等于零。宁可让 PR 阶段只拦最粗的低级错误,也不要让它变成必须跳过的流程。
追问链
- 冒烟集只跑 10 到 20 条,会不会漏掉真正的回归?
- skip-eval 标签要不要允许存在?如果允许,怎么加约束?
系统 A:完成率 90%、用户重试率 30%;系统 B:完成率 85%、重试率 8%。你选哪个上线?
完成率是代理指标,重试率是真实结果。用户重试一次,等于对上一次输出投了一张反对票;30% 的重试率意味着三成请求没有被一次接受——这通常就是「答得像但不对」的那类失败,而它恰好是完成率最难捕捉的:系统给出一个看似合理的答案,评测算通过,用户不满意。
把两个数一起读:A 的「一次就满意」大约是 63%(90% 乘 70%),B 大约是 78%(85% 乘 92%),B 明显更好。
还有一个附带收益:所有重试请求的原始 trace 天然就是一批高质量 badcase,B 的改进闭环会转得更快。如果必须在两者间取舍,我会把重试率写进发版门禁,而不是只盯完成率。
追问链
- 完成率用的是哪个口径,会影响你的判断吗?
- 如果 A 的重试集中在少数几个场景,你会改变结论吗?
Trace 里最容易被漏掉、但重放时最致命的是哪一类字段?
大多数团队会记请求体、工具调用和耗时——这些能让你知道发生了什么,但不够让你复原为什么。最常见的三种无法重放是:① 提示词改过了,只存了最终渲染出来的字符串,没存版本号,旧 trace 无法判断当时用的哪一版;② 上下文是动态拼的,检索片段、记忆、用户画像每轮都不同,不存来源就只能看到一个巨大的字符串;③ 裁剪没有留痕,你只知道模型没答对,不知道它当时没看到哪一段。
判据很简单:拿一条三个月前的 trace 出来,不改一行代码跑一遍,能不能复现同样的失败?不能,缺的就是这一类字段。
追问链
- 存全量提示词体积很大,有什么工程上的折中?
- 合规要求不能存原文时,怎么保证可重放?
01 知识建模:实体、事实、推断 6 问
为什么要把知识拆成实体、事实、推断三层? 高频
实体层(人、项目、组织、产品)——可锚定的对象,有唯一标识,相对稳定,来自主数据,可信度最高。
事实层(参与了某项目、在某时间发生了某事)——可溯源的关系与事件,来自业务系统记录或结构化抽取,每条都能回指来源,可校验。
推断层(基于实体与事实得出的结论,如"该成员适配某类岗位")——由模型生成,必然带不确定性,必须标注依据链与置信度,且可被新事实推翻后重算。
分开的核心价值是:事实层可溯源,所以敢拿去支撑结论;推断层带依据,所以敢展示但知道要谨慎。如果把三者混成一个"知识库",你无法回答"这条结论到底站不站得住"。
追问链
- 推断层怎么保证质量?
- 实体对齐怎么做?
推断的质量怎么保证?
① 生成时强制给依据——要求推断必须附带它引用了哪些事实(事实 ID 列表),没有依据的推断直接丢弃。这既是质量控制,也是可解释性。
② 置信度与呈现策略——按依据数量、事实新鲜度、以及是否有冲突事实计算置信度;低置信度的推断不以结论性语气呈现,而是作为"可能的观察"提示,避免误导用户做出重要决策。
③ 抽样人审 + 回流——定期抽样人工核验,把误判案例回流入评测集与规则库。审的结果要反哺到生成策略(比如某类推断总是错,就要收紧触发条件)。
还要有失效机制:推断所依赖的事实发生变化时(人员转岗、项目结束),相关推断必须被标记为待重算而不是继续留着——"过期但看起来很确定"的推断比没有推断更危险。
实体对齐是什么?不做会怎样?
不做对齐有三类后果:
① 信息碎片化——同一个人被拆成多个实体,各自的记录都不完整,检索时召回不全,看起来像"知识缺失",实际是对齐没做。
② 事实冲突——同一个实体的属性在不同来源里被存成两份,取值不同且无法判断谁新谁旧。
③ 统计口径失真——"参与过几个项目"这类聚合会失真。
常用手段是用强标识优先(工号、唯一 ID)→ 弱标识兜底(姓名 + 部门 + 时间窗)→ 冲突时人工裁决,并且对齐结果要可回溯(记录合并了哪些来源),否则出错了无法拆开。
一条事实里如果缺了「口径版本」这个字段,最严重的后果是什么? 高频
例如 2025Q2 转化率 4.2%(含退款订单)与 2025Q4 转化率 3.1%(剔除退款),界面上看起来是「一年下滑 26%」,实际两个数字的分母定义不同,根本不可比。
缺来源则不可信,缺更新时间则不知时效,但只有缺口径版本会产生「看起来完全正常的错误结论」——系统不报错,用户据此排期、复盘、写进汇报。
判据:把两个数放进上下文,模型会不会主动算出下降幅度;会,就说明口径版本没有跟着事实进入上下文,或者提示词里没有写「口径不同的数值不可直接比较」。
追问链
- 历史数据已经按旧口径入库,怎么补口径版本?
- 口径变更时,引用过该指标的历史推断应该怎么处理?
两条知识冲突:一条是上个月生成的分析结论,一条是本周的事实记录。应该信哪个,为什么不能按时间裁决?
裁决顺序不能颠倒:先判层次(事实优先于推断),再判可比性(同指标、同口径版本、同维度),最后才轮到比时间。
按时间裁决会出错,因为推断的「新」只代表它被生成得晚,不代表它更可信——一条刚生成的分析完全可能建立在过时前提上。
正确处理:采用事实作为依据,并把该推断标记为「与最新事实不符,可能已过时」;如果它仍有视角价值,可以呈现,但必须标明它只是推断。
追问链
- 同一指标、同一口径、同一期出现两个不同的值,属于哪一类冲突?怎么处理?
- 「可溯源」是否足以让一条推断当作事实使用?
业务方说「华东区销售额」时,系统至少要能回答哪两个问题,聚合查询才不会算错?
二是层级范围:「华东区销售额」是否包含其下各城市的销售额,这由实体层的上下级定义决定。
缺别名归一会漏召回;缺层级定义会让聚合范围直接算错——而这类错误很难从结果里看出来,因为数字看起来很正常。
工程做法:实体表同时维护「标准名、别名列表、上级、层级深度」,并给每条别名加生效期;改别名不要删除,只标记失效时间。
追问链
- 别名表为什么不能只建一次?你用什么信号判断该补表了?
- 「转化率」在不同业务线含义不同,这属于实体层的哪类问题?
02 RAG 的链路与失效模式 6 问
RAG 的完整链路有哪几步? 高频
① 采集与清洗——把文档、表格、日志接进来,去重、去噪、处理编码与格式。
② 切分(Chunking)——决定检索的最小单位。切得太大召回不准且占 token,切得太小语义不完整。
③ 索引——为每个 chunk 建关键词索引与向量索引,并保留元数据(来源、时间、权限、层级结构)。
④ 召回——根据查询取回候选集(关键词 + 向量混合)。
⑤ 排序(Rerank)——对候选做精排,选出真正该进上下文的那几条。
⑥ 生成——把选中片段与问题一起交给模型,要求带引用作答。
最常见的误区是把 RAG 理解成"④ + ⑥",然后所有问题都往提示词上改。实际上大部分 RAG 故障发生在 ②③⑤,而这三步都在模型之外。
追问链
- 每一环的典型失效表现是什么?
- 怎么定位故障出在哪一环?
RAG 的典型失效模式有哪些?怎么定位?
① 切分破坏语义——把一张表格从中间切断、把一个流程分成两半,导致召回片段残缺。表现为"答案缺一半"或"细节对不上"。定位:直接看召回片段的原文。
② 召回失败——正确片段根本没进候选集。这是最隐蔽的,因为模型会基于错误材料自信作答。定位:把"正确片段是否在候选集里"单独作为指标统计(召回率),而不是只看最终答案正确率。
③ 排序失败——正确片段在候选集里但被挤到后面,最终没进上下文。定位:看 rerank 前后的排名变化。
④ 生成忽略——材料都在上下文里,模型却没用,或者用了却编造了细节。定位:要求输出引用并在评测里检查引用是否真实存在。
关键方法论是把链路分层评测:先保证召回,再保证排序,最后才谈生成——否则你会一直在错误的环节上优化。
切分(chunking)你会怎么定?
原则:① 尊重结构边界——按章节、段落、表格、列表项切,别把标题和它的正文分开;② 保留上下文——每个 chunk 带上标题路径(文档 > 章节 > 小节),让它在脱离原文时仍可被理解;③ 允许重叠——相邻 chunk 之间留 10%–20% 重叠,缓解边界信息丢失;④ 长度适配——大小要兼顾语义完整与检索粒度,通常几百 token;表格和代码这类结构化内容要整体保留,宁可超长。
还有一个常被忽略的点:要为不同类型的资料用不同的切分策略(政策文档按条款、会议记录按发言段落、指标字典按字典项),一刀切是精度损失的常见来源。
判断切分好坏的实用方法:随机抽 20 个 chunk 单独读,能不能看懂它在说什么——看不懂就是切坏了。
你的 RAG 系统在 10% 的查询上答错。给出一个能在十分钟内把问题区间砍成两半的排查方案。 高频
能答对,问题就在检索链路(查询理解、切分、索引、召回、重排);不能答对,问题在组装与生成,或者模型能力本身。
第二步:检查召回结果里有没有那个块(把 top-k 临时调到 100 再看)。有,是排序问题或 top-k 太小;没有,是切分或索引问题。
第三步:用原文里的关键词做一次全文检索。能找到,是语义召回的问题;找不到,是切分把答案切断了。
纪律:先定位、再动手。换嵌入模型通常只动几个百分点,而切分错误带来的是「这条直接得 0 分」,两者不是一个量级。
追问链
- 为什么这一步要「从后往前」做,而不是从查询理解开始?
- 统计完 10 个失败样本之后,你会优先改哪个环节,依据是什么?
top-20 的召回里 17 条来自旧版本文档,过滤之后只剩 3 条可用。问题出在哪,怎么改?
top-k 是额度:被过滤掉的 17 条占掉了名额,而真正相关的第 21 到 25 名从来没有进入候选池。
正确做法是把过滤条件下推到检索层,让向量库只在符合条件的子集里做近邻搜索——同样的查询、同样的 top-k,可用结果从 3 条变成 20 条。
判据:过滤后被丢掉的比例超过召回条数的一半,就必须下推。选型阶段先确认向量库支持带过滤的近邻查询。
追问链
- 两路混合检索时,为什么两路必须用同一套过滤条件?
- 如果向量库不支持带过滤的近邻搜索,有哪些替代方案?
同一份语料:把块调到 200 字,检索更准但答案变差;调到 1200 字,答案更全但召回变差。怎么解?
检索粒度(块越小语义越聚焦、匹配越准)与返回粒度(块越大上下文越全)本来就该分别取值。
做法是父子块:切成 200 到 400 字的子块用于嵌入与检索,命中后按 parent_id 返回其所属的 800 到 1500 字的父块,命中同一父块的多个子块只返回一次。
代价是要维护父子映射,并且膨胀之后总字符变多,必须按预算截断、并显式标注截断了多少。
另外相邻块保留 10% 到 20% 的重叠,降低答案被切在边界上的概率。
追问链
- 表格为什么不能按字符长度切?你会怎么处理表格?
- 每个块为什么要带上「文档 > 章节 > 小节」的层级路径?
03 Embedding 与向量检索 6 问
语义检索为什么会找错? 高频
四类具体错法:
① 语义相似但答案无关——查询"如何申请年假"召回《请假制度总则》的相似段落,但真正有用的是《年假实施细则》,两者语义高度接近。
② 精确标识失效——向量对数字、工号、型号、专有名词不敏感,"型号 A123" 和 "型号 A132" 在向量空间里几乎没区别,但答案完全不同。
③ 否定与条件丢失——"不含"、"除……之外"这类逻辑关系在稠密向量里表达很弱。
④ 频次与时效被稀释——出现 20 次的关键条款,可能比只出现 1 次的临时通知排在更前,但后者才是当前有效的版本。
所以纯向量检索在真实系统里几乎总是配合关键词检索(补精确匹配)+ 元数据过滤(补时效与权限)+ Rerank(补真实相关性)使用。
余弦相似度、点积、欧氏距离该怎么选?
向量已归一化(模长为 1)——余弦相似度与点积完全等价,此时用点积更快(省掉除法)。大多数现代 embedding 模型输出的向量本身就是归一化的,所以实践中常见"用点积近似余弦"。
向量未归一化——点积会把模长也计入相似度,如果向量模长本身有含义(例如代表置信度或频次),这可能是特性;如果没有含义,那就是噪声,应该先归一化。
欧氏距离——在归一化向量上,欧氏距离与余弦相似度是单调等价的(
d² = 2 − 2·cos),所以排序结果相同。它的好处是直觉上更好解释,坏处是对模长变化更敏感。工程上的建议是:跟你的向量库与索引实现保持一致——很多 ANN 库针对特定度量做了优化(比如内积),混用不同度量的预计算会导致结果与暴力检索不一致,这种 bug 很难发现。
向量检索的能力边界在哪?什么场景不该用它?
① 需要精确匹配——编号、单号、金额、日期范围、代码符号。这些必须走结构化查询或关键词精确匹配。
② 需要聚合与统计——"上个月有多少人入职"。向量检索只能找相似文本,不能做聚合,这本质上是数据库问题。
③ 需要严格权限与合规——向量检索没有天然的权限语义,必须在检索前做元数据过滤(pre-filter),而不是检索后再筛(否则会泄漏被过滤内容的存在性,也浪费召回额度)。
④ 需要多跳推理——"和 A 合作过项目的人,他们的共同上级是谁"。这是图查询擅长的事,向量检索只能拿到与 A 相关的文本片段。
一句话总结:向量检索擅长"找相似的说法",不擅长"精确匹配、聚合、关系推理、权限控制"——所以真实系统里它只是检索层的一个组件,而不是全部。
用户问「哪些功能不支持批量操作」,检索回来的却全是「支持批量操作」的文档。你会怎么修,为什么不建议先换嵌入模型? 高频
这是机制性局限,换任何通用嵌入模型都会遇到,所以要修的地方在向量之外:
- 查询理解阶段把否定改写成正向表述(不支持 → 缺少、未提供、不兼容);
- 再叠一路关键词检索,让「不支持」这个精确串能被直接匹配上。
经验上,改写之后这类查询会从「基本不命中」变成「命中一半以上」,是量级差别。
追问链
- 「同比增长 12%」与「同比下降 12%」属于哪一类失效?
- 精确标识符(订单号、错误码、函数名)应该怎么检索?
同一批向量、同一批候选,换成点积打分之后,长文档的名次普遍上升。原因是什么,怎么处理?
所以未归一化时用点积(或欧氏距离)会系统性偏好长文本。
处理分两步:确认嵌入模型训练时用的是哪个度量(查模型卡)并保持一致;如果模型走余弦,就把向量做 L2 归一化之后改用点积——两者等价,而且更快。
判据:一旦出现「长文档总是排得更高」或者「同一段话复制两遍分数变高」,先查归一化与训练度量这两项。
追问链
- L2 归一化除了省算力,真正的语义作用是什么?
- 欧氏距离在向量归一化之后,与余弦是什么关系?
团队想把嵌入模型从 384 维换成 1536 维,期望检索指标明显提升。作为评审你会问哪几个问题?
- 现在的失败样本里,有多少属于「语义该匹配但没匹配上」?如果失败集中在精确串、否定词、条件约束这三类,换维度完全无用——它们是机制性失效。
- 换模型意味着索引要全量重建,存储与延迟的预算给了吗?很多 384 或 768 维模型在同义匹配上并不输 1536 维,而索引体积与延迟差 2 到 4 倍。
- 相似度阈值有没有跟着重标?分数分布会随模型改变,旧阈值会失效。
追问链
- 换嵌入模型之后,哪些东西必须一起重建或重标?
- 如果失败样本集中在精确匹配类,你会先改哪一环?
04 混合检索、Rerank 与知识可信 7 问
混合检索怎么设计?关键词和向量怎么融合? 高频
① 并行召回——一路 BM25/倒排做关键词检索(擅长精确命中、专有名词、数字),一路向量检索(擅长同义改写、语义近似),各取 Top-K(比如各 50 条)。
② 分数融合——两种分数不可直接比较(量纲不同),常见做法是RRF(倒数排名融合):只用排名不用分数,
score = Σ 1/(k + rank),简单、鲁棒、不需要调权重;或者做分数归一化后加权求和,但要为不同数据源分别标定。③ 元数据过滤——在召回阶段就加权限、时效、类型过滤,而不是事后筛。
④ 精排——把融合后的前 50–100 条交给 Rerank 模型(cross-encoder),选出最终进上下文的 5–10 条。
这套结构的分工是:召回要宽(宁可多召回)→ 排序要准(决定最终质量)→ 上下文要省(只放最相关的几条)。
追问链
- RRF 的 k 一般取多少?
- Rerank 模型和 embedding 模型的区别是什么?
Rerank 为什么比向量检索准?代价是什么?
向量检索(bi-encoder)先把查询和文档各自独立编码成向量,再算相似度。好处是可以离线建索引、检索快(毫秒级),代价是查询和文档之间没有交互,细粒度的匹配关系表达不出来。
Rerank(cross-encoder)把查询和文档拼接后一起送进模型,让每个词之间都能相互作用,因此精度显著更高。代价是无法预计算——每个(查询,文档)对都要跑一次前向,成本随候选数线性增长,所以只能用在精排阶段、候选只有几十到上百条的时候。
这就是"粗排用双塔求快,精排用交叉编码器求准"的两阶段架构的根本原因。
补充一句工程考量:Rerank 的延迟通常几十到几百毫秒,如果对首字延迟极敏感,可以考虑异步 rerank + 先返回粗排结果再更新,或者只对 Top-N 做 rerank。
怎么让回答"有据可查"?
① 要求结构化引用——模型输出时对每个结论都要给出来源标识(chunk ID、文档 ID),而不是在正文里写一句"[1]"。
② 引用必须真实存在——后处理阶段校验:引用的 ID 是否真的在本次上下文中、引用的段落是否真的支持该结论。这一步能拦掉相当比例的"编造引用"。
③ 溯源到原文位置——chunk 要保留原文定位信息(文档链接 + 页码/段落),用户点开能看到原始上下文,而不是只看到片段。
④ 无据要能拒答——明确允许并鼓励"根据现有资料无法回答",并对这种情况监控比例。一个从不拒答的系统,其引用可信度必然很低。
⑤ 评测引用质量——把"引用支持率"(引用是否真的支撑结论)作为独立指标,而不是只看答案看起来对不对。
知识冲突(同一事实有多个版本的记录)怎么处理?
① 时效性冲突(旧版制度 vs 新版制度)——按生效时间处理:检索时优先返回当前生效版本,但保留历史版本可查(因为"当时适用什么"也是一个合法问题)。落地手段是元数据里带 effective_from / effective_to。
② 来源权威性冲突(正式文件 vs 内部聊天记录)——引入来源权重,正式发布的主数据优先;权重必须在检索与排序阶段生效,而不是最后让模型自己判断。
③ 真实矛盾(两处记录确实不一致,无法判断谁对)——不要静默选择其中一个。正确做法是把冲突显式暴露出来("系统中存在两种记录:A 系统显示 X,B 系统显示 Y"),这既诚实又让问题能被修复。
④ 数据质量冲突(空值、格式错误)——在采集清洗阶段解决,不应进入检索层。
核心原则是:知识引擎的第一职责是"不制造虚假确定性",冲突要么按明确规则消解,要么显式暴露。
两路召回融合时,为什么常说 RRF 比加权分数和更稳?给出量化判据。 高频
加权和要先归一化,而归一化用的 min / max 取决于这一批候选:换一批数据,同一篇文档的名次就会变,即使权重一点没动。
RRF 只看名次,用 1/(60 + rank) 求和,与分数尺度无关,也几乎不用调参;代价是丢掉分数幅度信息——第一名和第十名的差距被压平,k 的取值决定压平程度。
判据:两路分数的量级差在一个数量级以内,可以用加权和(归一化口径要固定成历史分位数);超过一个数量级,优先 RRF。
追问链
- RRF 里的 k 取 60 有什么讲究?调大调小分别影响什么?
- 如果坚持用加权分数和,归一化怎么做才稳定?
模型在回答里标注了 [E7],但证据清单里只有 E1 到 E5。列出三种处理方式,并说明哪一种做法是错的。
三种处理:重试生成;把该结论降级改写为「未找到依据」;标记该条为待人工核对。
错误做法:把 [E7] 替换成最接近的 E5(这是伪造引用),或者直接忽略、照常返回(这是掩盖问题)。
工程前提是两步:在上下文里给每个证据块一个短 ID,并要求模型用这些 ID 标注依据;生成之后跑一次后置校验,检查回答里出现的引用编号是否都真实存在。这是确定性的代码判断,不该指望在提示词里写一句「不要编引用」。
追问链
- 为什么说 L1「模糊引用」在用户侧等于没有引用?
- 后置校验发现「未被使用的证据」时,应该做什么?
有人提议跳过初排,直接对所有文档做 Rerank,反正交叉编码器更准。这个方案会在什么量级上崩?
参考量级:把 10000 句做两两打分需要约 5000 万次句对推理(数十小时量级),而双塔只需要算 10000 次嵌入(秒级)。
所以崩溃点在「候选规模从几十涨到上万」这个量级上:单次查询会从毫秒变成秒级,成本随文档量线性上升。
正确分工:初排把候选从百万级降到几十级(哪怕排得不够准),精排在这几十条里做准排序,最后截断到 4 到 8 条进上下文。「召回宁可宽、排序必须准」说的就是这条分工。
追问链
- 召回取 50 条,是不是就该把 50 条都送进模型?
- 两路召回结果冲突时,为什么不能选相似度更高的那条?
05 知识更新与时效性 3 问
一条知识过期了,是直接删掉还是标记失效?为什么? 高频
原因有三:① 可解释性——用户质疑「你为什么觉得口径是 X」时,你要能拿出「2025-03-12 由 A 提供、2025-09-01 被 B 取代」这条链,物理删除就断链了;② 可回滚——新版本可能是错的,标记失效才能随时回退到旧版本;③ 合规——软删除只是默认行为,用户行使「被遗忘权」时仍要能硬删除。
实现上是给每条知识加
superseded_at 字段,删除时只填它而不是从库里抹掉。一个反直觉的点:过期 ≠ 无用——过期知识仍可能含有可用的历史线索,召回时应降权而非直接丢弃,把时效判断权交给模型(给它 written_at 这个依据,而不是替它删掉)。
追问链
- 软删除和回滚是一回事吗?
- 什么情况下必须硬删除?
知识库体量大了以后,为什么全量重建不可行?增量更新难在哪?
增量更新便宜但难,难点是级联失效:一条事实变了,依赖它的推断也要跟着失效。
解法是把依赖关系显式记录(对应知识引擎的「事实层 / 推断层」分层):上游发变更事件,只重算受影响的条目,其余沿用。
核心判据:能不能靠静态知识永久成立——能就不需要 TTL,不能(价格、排期、余额)就一定要带
valid_until。工程折中是变更订阅 + 局部失效,而不是「改一条就全量重来」。
追问链
- 稳定事实和易变事实怎么区分?
- 级联失效如果不处理会怎样?
怎么判断一条召回的知识「还新不新鲜」?能不能只按写入时间倒序排?
正确做法是把新鲜度拆成一组可计算的信号:写入时间、来源的更新频率、是否命中 TTL 过期、被引用的新鲜程度。
召回时把这些信号交给排序层(Rerank)综合判断,而不是硬编码「新的就优先」——因为你无法替用户判断「一条稍旧但来源极权威的知识」和「一条很新但来源可疑的知识」哪个更该信。
本质:把「时效判断权交给模型,把判断依据交给系统——你提供 written_at / source_freshness / ttl_status 这些信号,不替它下结论。
追问链
- 为什么「写入晚」不等于「新鲜」?
- 过期知识直接删掉会丢什么?
结论先行(一句话给出取舍)→ 机制(为什么是这样,涉及哪条链路)→ 代价或边界(这么做放弃了什么)→ 你的实践或数字(真实场景里怎么落地)。 这套结构之所以有效,是因为它天然把「研究问题」和「工程问题」分开了:只有工程问题才配得上第三条和第四条。