多轮对话 Agent 怎么测?确定性与不确定性分离的四层测试金字塔
一次多轮 Agent 的测试工程实践把状态机、分类器、话术、接线四种性质完全不同的东西拆开用四种方法各测各的每种都配一套能回归的资产。技术栈LangGraph · pytest · hypothesis · Langfuse · LLM-as-Judge。文末附四层 × 现成框架的选型对比表可直接抄。你改了一句提示词想修AI 追问太多、像中介查户口的毛病。改完和它聊了十分钟感觉顺多了发版。第二天用户反馈AI 是不追问了可它也不推房了——你那句少问点问题把它引导用户去看房源的桥接语一起压没了。你再改。推荐是修好了但一个更隐蔽的问题浮出来用户对着刚推给他的房源说了句这套还行AI 把这句好评当成了再给我换一套又推了一套新的把上一套顶掉了。用户一脸问号。三个回合下来你会撞上一个让所有做 Agent 的人心里发凉的事实每次改动你只验证了自己盯着的那一个场景而 Agent 的真实行为空间比你能聊到的大好几个数量级。跟它聊聊看根本不是测试是抽查——而且是最坏的那种抽查跑不全、不稳定、出了问题还说不清是哪儿坏的。这篇文章想回答一个被很多团队糊弄过去的问题**一个多轮对话 Agent到底该怎么测**下面每一层我都会把真实项目里的代码骨架摆出来——因为方法论听着都对能不能落地全看那几十行测试长什么样。我会用我们做的一个产品当例子——一个租房场景的 AI 找房助手。它每收到用户一条消息只干一件事决定这一轮该做什么。新用户来了先聊五个问题建立找房偏好预算、通勤、户型、生活方式、绝对不要什么老用户闲聊时顺着话头把需求挖深攒推荐素材用户想看房就推荐但每天最多三套免得刷到决策疲劳用户说了危险的话安全兜底话术接住剩下的正常聊。一条消息进来走的是这么一条流水线图 1 · 一条消息的旅程 —— 实线块 纯代码确定虚线块 AI 判断不确定看着不复杂对吧一层分发没有嵌套。可就是这么一张扁平的图坑我们坑得最狠。复杂度不在流程图里在你看不见的状态流程图只有一层但每一轮决策背后有一大堆状态在暗处参与运算用户此刻在哪个阶段日常闲聊、首次建档、补充偏好、修改偏好建档聊到第几轮、五个问题问到第几个用户连续答非所问几次了连着三次才该体面地退出别死缠AI 连续追问几轮了问到第三轮就该还用户一句不带问号的话别像查户口今天推荐名额还剩几套、有没有待确认的偏好草稿。把这些一乘五种意图 × 四种阶段 × 几个计数器 × 有没有画像草稿名额……上万条路径。你和它聊一下午连百分之一都盖不住。这就是为什么端到端聊天测一切是最差的选项。它同时犯了三宗罪跑不完上万条路径人力聊天杯水车薪不稳定同一句话模型这次判成闲聊、下次判成需求状态就跑偏测试时红时绿说不清一条 case 挂了你分不清是意图判错了、还是状态记错了、还是话术差了于是所有人默认都去改提示词补丁越摞越厚最后谁都不敢动那坨提示词。但这张图里藏着一个救命的好消息它是整套方法论的地基——确定的和不确定的本就该分开盯着那张流程图再看一眼AI 只出现在三个地方——判断安全、判断意图、生成话术。而这三个 AI 判断口之间所有的记账、状态转移、选路全是纯代码不调模型、不碰数据库同样的输入永远给同样的输出。把这条分界线画到真实的图拓扑上长这样图 2 · 真实图拓扑 —— 准备上下文、两处条件路由是纯代码安全闸门、意图分类是分类口而扇出后每个动作节点内部还各自藏着生成/抽取口这张图比第一张多暴露了两件要命的事。其一选路那一下全是纯代码安全闸门判完拒还是过是纯函数条件意图判完进哪个动作节点也是纯函数条件硬规则 意图 兜底。其二也是新手最容易栽的——LLM 口不只在两端动作节点内部还散着一堆收集建档一个节点里就有抽取、合成、生成三个 LLM 调用。记住这张图右边那块第四层会回来找它算账。这条分界线一旦画出来测试策略几乎是自动成立的**不同性质的东西用不同的方法测。**你不会用秤去量体温也不该用聊天去测一段纯代码的状态转移。而且这条线的意义远不止测试。它反过来是一条架构纪律如果你的 Agent 画不出这条线——模型调用和业务逻辑搅成一团、状态转移散落在各个提示词的字里行间——那你遇到的其实不是测试难题是架构债。**好的可测性是设计出来的不是事后补出来的。**所以我们把LLM 只许出现在分类和生成两端中间必须是纯函数直接写进了 Agent 的开发规范让每个新 Agent 从第一天起就天然可测。动手之前先把测一条用例这句话说清楚很多团队的测试讨论卡在一个特别朴素的地方两个人都说写条用例测一下脑子里想的却是两种完全不同的东西——一个想的是直接调那个函数另一个想的是把整个对话跑一遍。不先统一这件事后面所有分工都是鸡同鸭讲。对一个用图来编排的 Agent比如 LangGraph 这类测试其实只有三种基本姿势区别就在喂它什么、看它什么第一种单看一条规则。绕开整张图把某一条业务规矩单独拎出来验技术上就是直接调那个决策函数喂它一个意图加几个状态字段看返回值对不对。它能证明这条规矩本身对——最快、零成本、能全部验一遍但证明不了这条规矩有没有被接到正确的地方。第二种走一整段对话。把完整的图当黑盒从头到尾跑一遍——喂一份完整的会话状态阶段、轮次、各种计数器、有没有画像草稿名额和一段对话历史同时把所有 AI 判断都换成写死的标准答案只看跑完后状态怎么变、经过了哪些环节。它测的恰恰是第一种够不着的东西——环节之间接得对不对、多轮怎么演化代价是准备一份完整状态比准备几个字段贵得多。第三种单考一次 AI。把安全判断、意图判断、或者话术生成单独拎出来考——喂一段对话看它判成了哪一类、话说得合不合格。因为考的是概率模型判据必须是一整套题的正确率而不是某一条的对错。这三种姿势没有高下之分真正的区别在于维护成本从哪来单看一条规则的用例极便宜坏了改一行就行走一整段对话的用例贵在那份完整状态所以得用统一的剧本格式来写初始状态、每轮发生什么、每轮该验什么让一份剧本能长期复用单考 AI 的用例是一套题库贵在标注所以必须能沉淀、能跨版本反复重考。把这层窗户纸捅破下面四道质检关卡就各就各位了一条规则单独验一整段对话整个走一次 AI 判断拎出来考。图 3 · 三种姿势各管一段 —— 一条规则单独验一整段对话整个走一次 AI 判断拎出来考第一层把产品决策焊死成表格先纠正一个会把人带偏的叫法。这一层技术上叫状态机测试但它测的东西根本不是什么技术细节而是产品设计决策本身。看几条我们真实的规则以及它们背后的产品理由规则为什么这么定用户答非所问要连续三次才退出建档建档是核心转化。租客聊着聊着吐槽两句工作太正常了一跑题就放弃建档完成率会崩——所以给三次冗余先把人拉回来用户一旦明说要看房立刻退出建档去推荐主动要看房是最强的意愿信号此刻还死守建档流程等于拦着用户要的东西建档的五个问题游标只前进不回头用户最烦被问第二遍预算。哪怕这轮答得含糊也宁可往下走绝不回头重问每天最多推三套房源推荐是稀缺感商品一天塞十套用户直接麻木AI 连问三轮必须还一句不带问号的话收集偏好是长期生意查户口的感觉会把人问跑——先给予再索取**每一行都是一次产品讨论拍下来的结论。**而把这些结论翻译成测试长得就跟决策表本身一模一样——一行一条规则喂进去起始状态和意图断言状态怎么变# 业务规则层不调模型、不碰 DB同输入永远同输出。一行 一次产品拍板。pytest.mark.parametrize(stage, intent, expect, [ # 建档中答非所问 → 计数1留在建档给三次冗余别一跑题就放人走 (ONBOARDINGofftopic0, CHAT, {off_topic: 1}), # 连续第三次跑题 → 这一步必须退出建档转化率的兜底硬线 (ONBOARDINGofftopic2, CHAT, {stage: IDLE}), # 建档中明说要看房 → 立刻退出建档去推荐最强意愿信号不许再拦 (ONBOARDING, RECOMMEND, {stage: IDLE, route: recommend}), # 建档中正常补充 → 游标只前进绝不回头重问预算 (ONBOARDINGtopic1, COLLECT_ONLY, {cursor: 2}),])def test_stage_transition(stage, intent, expect): assert derive_stage(intent, parse(stage)) expect光有逐条用例还不够再加几条无论如何都必须成立的铁律——它们不是抽查几个例子而是跑遍所有阶段 × 意图组合都得成立given(stagestages(), intentintents()) # 阶段 × 意图 全笛卡尔积穷举def test_invariants(stage, intent): out derive_stage(intent, stage) assert out.off_topic OFF_TOPIC_EXIT_THRESHOLD # 计数到 3 必退不会卡在 4、5 assert out.cursor stage.cursor # 游标只进不退问过的不再问 assert out.route in VALID_NODES # 路由是全函数任何输入不抛错**为什么它是性价比之王**因为不调 AI、不连数据库几百条用例十秒跑完。更妙的是用户的那些乱输入在这一层根本不存在——乱七八糟的自然语言早在上游被分类器压成了有限的几个枚举值。有限枚举意味着可以穷举意味着可以彻底焊死。我们给自己的状态机铺这层测试的那天第一遍就抓到一条已经静默失败了好几个星期的旧测试。之前一次规则调整改了代码游标推进逻辑从原地改成了至少进一位漏更了一条断言它就那么一直红着没人发现——因为根本没人天天跑它。翻译成人话**产品规则被人悄悄改了而规则的契约没有任何人在守。**这层测试就是那个守约的人。它锁死的不是代码是当初会议室里拍板的那些产品决策。一个真实踩过的坑顺手说清上面derive_stage只认已经解析好的意图枚举。用户点的那些快捷按钮“看房”“改偏好”带的是原始 action 字段必须先过一层 shortcut 解析才变成意图——你要是图省事直接把 action 喂进路由函数它会默默落到闲聊兜底。所以这类接线依赖我们专门写了护栏用例故意喂错层的输入断言它确实会误路由把契约钉死在测试里免得下一个人重新踩。第二层把分类器当成一个 ML 模型来考安全判断和意图判断这两个 AI 口判得准不准是另一码事得用另一种考法。别给它写单元测试——它是个概率模型不是确定性函数。正确的做法是像考核一个机器学习模型那样建一套标注题库每改一次提示词就把整套题重考一遍看的是每一类的准确率和错题分布也就是混淆矩阵说白了就是一张把 A 类判成 B 类各几次的错题统计表。题库里的题分三种缺一种就会漏掉一整类事故。而题该长什么样这件事最好直接看题——注意后两道用户输入几乎一样正解却相反区别全在 AI 上一句做了什么## 单轮题一句裸话考基本盘id: recommend.explicit.001 · label: RECOMMENDuser: 帮我找套房## 前情题 AAI 只是提议还没真推 → 用户好啊是接受该去推id: recommend.boundary.offer_confirm.001 · label: RECOMMENDassistant: 要不要我找几套合适的房源给你看看user: 好啊## 前情题 BAI 已经把房源摆出来了 → 用户这套还行是好评不该再推id: chat.boundary.shown_match.001 · label: COLLECT_AND_GUIDEassistant: 〔已展示房源卡两居 / 近地铁 / 6k〕user: 这套还行一字不差的好啊/这套还行前情不同正解相反——分类器是读上下文来判断的题目就必须把上下文带上。我们真翻过的那次车好评被当成再换一套就是 B 这类。所以我们的题库里边界题占了过半。题库写成人能读的 markdown脚本编译后推到评估平台跑分 runner 支持传提示词版本同一套题分别跑当前版和候选版输出逐类准确率和混淆矩阵的差异。判据永远是全集的逐类准确率绝不看单条随机输出——理由下面这份真实跑分说得很清楚。我们给意图分类器建了一套66 道题的题库边界题占了过半35 道拿线上版本连考两轮考出来的数字很说明问题[v10] 66 题 · 连考两轮 · 温度0 run1 run2overall 93.9% 90.9% ← 同一套提示词两轮仍差 3 个百分点overall 95% 置信区间[86.6%, 95.8%] ← 版本对比要看两版区间是否重叠别给噪音颁奖gold\pred REC CAG CO GO CHAT ← 混淆矩阵错判被吸进哪个类一目了然REC 12 1 0 0 0 ← REC→CAG ×1CAG 0 23 0 0 0 宽兜底类自己 100% 不丢CO 0 2 7 0 0 ← CO→CAG ×2稳定弱点簇就在这GO 0 0 0 9 0CHAT 0 0 1 0 11 ← CHAT→CO ×1连续成功率两轮全对 60/66 90.9% ← 生产真正要的口径至少一次成功率 62/66 93.9% ← 能力上限只能看潜力稳定错判两轮同错 4 条全是边界题 ← 真弱点见下文抖动题时对时错 2 条 ≈ 3% ← 噪音不是弱点别去修它**两轮总分是 93.9% 和 90.9%。**同一套提示词、温度调到零两次考试还是差了 3 个百分点。有一道题的原话甚至就写在提示词的示例里一轮判错、一轮才对。这就是盯着单条输出调提示词会被反复折腾最硬的实锤——**66 道题里就有 2 道在时对时错3% 上下的天然抖动意味着你看到的任何单条好坏都可能只是噪音。**谁再拿一张截图跟你说你看这条又坏了把这个数字甩给他。而这 3 个百分点的差距恰好逼出一个容易被跳过的严谨问题**它到底是真变化还是随机波动**只跑一轮、看总分涨了就宣布提升很可能是在给噪音颁奖。所以版本对比不能只盯单点分数得给关键指标配上置信区间上面那行 95% CI 就是干这个的纯数学算得出不依赖任何库——两版的区间不重叠差异才算真的超过了统计噪声。我们干脆给最小可感知变化提前定了个阈值涨跌幅度不到这个数一律不作为发布依据。抖动还牵出另一个更贴近生产的视角。同一道题跑 N 次“至少对一次和每次都对是两码事前者说明能力上限够得着适合看潜力后者才是生产真正要的——**用户不会接受多试几次总有一次成功”他们要的是每次都稳。**退款、支付、合规这类场景该盯的是连续成功率。看那两行数字至少一次成功率 93.9%听着还行可换成连续两轮全对立刻掉到 90.9%——同一套东西换个更严的口径就缩水一截要是要求连着五轮全对实际可用性还得再打折。真正有价值的是两轮都错、而且错得一模一样的那 4 道题全是边界题。它们才是真弱点而且集中成一个簇“换个区域继续找这种带修改的接受被当成了边收集边引导”先不用了回头再说这种软拒绝没能压住默认分支又不想被推荐、又嫌问题多的双重拒绝只识别出了一半。回头看那张混淆矩阵——4 道错判里 3 道全栽进了同一个宽兜底类CAG一格CO→CAG ×2就是这个簇的指纹。**所以下一版提示词就精确瞄准这几个句式补规则别去动那个兜底类本身别的一个字不动。**因为你有整套题守着任何补了这里、崩了那里都会当场现形。还有个额外收获之前修过的那个好评复推的坑AI 已展示房源后、用户的好评被误判成求推荐相关的边界题这次两轮全过——混淆矩阵里那个 100% 不丢的 CAG 类就有它们的功劳。这是那次修复第一次拿到了回归证据而不是我感觉修好了。第三层能用规则查的就别请 AI话术层测的是 AI 说出来的话像不像话——专业、有温度、不油腻、不查户口、不乱承诺。诀窍是先把要求分成两堆。能用规则机械检查的坚决不动用 AI——这些又快、又免费、永远不抖# 硬约束 普通函数正则/计数就够一次跑完不花一分钱、不抖一下defrule_give_back_no_question(reply: str) - bool: return?notin reply andnotin reply # 给予回合零问号defrule_one_question_per_turn(reply: str) - bool: return reply.count(?) reply.count() 1 # 建档一次只问一个defrule_no_reco_when_refused(reply: str, ctx) - bool: # 用户明说不要推荐 returnnot (ctx.user_refused_reco and hits_reco_template(reply)) # 那就一句推荐话术都不许有剩下机械查不了的软质量——温度够不够、上下文接得顺不顺、人设有没有跑偏——才请另一个 AI 当评委按评分卡打分取平均# 机检不了的才请评委按评分卡打分1-5 星取均值永远看分布不看单条judge_rubric: 暖度: 像懂行的朋友不是查户口的中介 主题衔接: 接住用户上一句不跳步、不自说自话 人设边界: 红娘/管家口吻不越界给法律金融建议# 评委必须输出打分理由低分样本人工复核后沉淀回题库有人立刻会问评委自己也会判错那它打的分还能信吗能靠三招兜住第一能机检的先被上面那几个函数分流走了评委只负责它真正擅长的软性判断第二永远看均值和分布不看单条——评委的抖动会被平均掉第三评委的评分卡本身也用一套标注集去校准低分样本人工抽核。评委不是真理是一台被校准过、且只在合适场景使用的仪器。第四层把 AI 全钉死跑一遍全流程回归前三层各管一段但还有个东西没测接线——分类结果进来之后状态记账对不对、路由对不对、该发偏好清单卡的那一轮到底发没发。测法就是用测试替身test double跑全流程把所有 AI 判断口全换成写死的脚本然后驱动真实的那张图多轮跑完整场剧本只断言状态轨迹和节点序列绝不断言 AI 说了什么那是第三层的活。这层的第一步也是最容易翻车的一步——把图里每个 LLM 口都对上一个 mock 目标# 还记得图 2 右边那块吗动作节点内部还藏着抽取/合成口——漏钉一个剧本就打真模型MOCK_SEAMS { intent.classify_intent: seq([COLLECT_ONLY, RECOMMEND]), # 每轮钉死一个意图 safety.classify_safety: const(SAFE), collect.extract_interests: const(Interests(likes[安静])), # ← 动作节点内部的口① collect.synthesize_draft: const({budget: 6k}), # ← 内部的口②最常被漏 reply.generate: fake_reply, # ← 内部的口③}缝钉全了剧本就干净了。剧本本身是一份声明式的东西——初始状态、每轮注入什么分类结果、每轮断言什么只看状态和路由不看话术scenario: 建档中途明说要看房→应立刻退出建档、直奔推荐initial_state: {stage:ONBOARDING, collect_round:2, cursor:1}turns:-inject_intent:RECOMMEND expect_route:recommend # 走对了节点 expect_state: {stage:IDLE} # 且真的退出了建档不是嘴上说说有人会问最终话术都对何必揪着中间状态不放因为结果对不等于过程对。一条 case 最后那句房源推荐读起来挺顺可它要是在本该建档的阶段抢跑推的、或者绕过了每日三套的名额校验——这次侥幸没出事换个用户、换个时点就是事故。这种答案看着通过、路径其实带病的假阳性是 Agent 最阴险的一类 bug它在只看最终输出的测试里永远是绿的直到某天在生产里爆开。第四层专测过程、不测话术防的就是它。AI 全被钉死之后这层零抖动、秒级完成能塞进 CI 每次提交都拦一道。那真实的端到端测试还要不要要但降级成冒烟留两三条每天夜里跑一次验证提示词和真实模型的集成没烂掉。它是烟雾报警器不是质检产线——这个定位一旦摆错你就又滑回聊天测一切的老路了。出了 bad case让 AI 先破案一条线上 bad case 报上来它只可能坏在三个地方**分类判错了、规则走错了、话说得不好。**传统流程是工程师打开观测平台人肉翻十几屏 JSON 找线索——慢而且翻着翻着就凭直觉去改提示词了又回到补丁摞补丁的老路。我们正在把这一步交给 AI 自动破案图 4 · AI 自动归因管线 —— bad case 导出诊断包 → 编程 Agent 归因 → 裁决坏在哪层并给修法 → 人拍板复测那一层关键是那个诊断包把一轮对话的全链路过程数据抽出来、去掉噪音、压成一页纸的结构化摘要。这份摘要人能十秒看懂AI 更能# 诊断包 · 一页纸只留 diff、不留全量对话历史只留末 2~3 轮不带 prompt 全文turn: {session, turn_id, prompt_version:v10}input: {query:这套还行, is_first:false}judges: {safety:SAFE, intent:RECOMMEND} # ← 疑点好评被判成了求推荐state_diff: {daily_rec:2→3, 发卡:false} # 状态只留变化项route: [prepare, safety, intent, recommend] # 途经节点确实走进了推荐output: {speech:给你换一套…, cards:1}links: {trace_url, annotation_id} # 深链回观测平台看原始细节而且现象本身就是路标——房源在建档没做完时就被推了这种描述天然指向路由和规则层根本不用去翻话术提示词话说得没温度才落到话术层。维护一张问题现象 → 候选层的小映射表破案一上来就把范围收敛到一两个模块。把这份摘要连同现象标签一起丢给编程 Agent让它按先查分类、再查规则、后查话术的顺序破案并给出建议是该在流程里加一条确定性约束改代码还是该增强提示词改分类或话术以及修完之后该复测哪一层的哪套题。人的角色就此从翻日志的侦探变成了看裁决书的法官。而且这些过程数据本来就都躺在那儿——调试台早就记录了每一轮的状态快照和节点轨迹唯一缺的只是把它导出成诊断包的那一个按钮。让每一条 bad case变成一道永久考题绝大多数团队的现状是调试时发现的问题截个图发到群里修完就散了。三个月后同一个问题换身马甲回来再修一遍。正确的姿势是造一个数据飞轮图 5 · 数据飞轮 —— bad case → 打标 → AI 归因 → 导出考题 → 永久回归每转一圈就少一类复发这里的关键洞察是打标的那一刻一条测试用例需要的所有信息其实都已经在场了——用户输入、当时的完整状态、AI 的判断链。缺的从来不是采集能力而是把它导出成一道考题的最后一步。把这一步做成一个按钮飞轮就转起来了一条被标错的 case按它坏在哪层自动落成对应层的用例——归分类的落成第二层的一道题对话窗口 纠正后的标签归接线的落成第四层的一段剧本当时的状态快照 意图序列归规则的落成第一层的一行参数。冷启动也不难。很多人一听建题库就头大其实题从三个地方来一天就能凑齐第一批历史上修过的每一个 bad case修过的误判本身就是现成的边界题、设计文档里的规则表直接翻译成用例、以及调试台持续流进来的标注。我们那套意图题近一半就来自前两个存量来源。飞轮转起来之后还得防它跑偏成两种毛病。一是别把每条失败都无差别塞回题库——那样用例库迟早膨胀到没人敢跑。入库得有门槛能复现、期望行为写得清、根因标签明确、能代表一类问题而不是一次环境抖动、且已脱敏。二是别把 bad case 当成一条条孤立的账来记。同一个根因、同一个场景的失败该自动聚成一簇——一份好报告不该是列出 100 条 bad case而该是某场景下 Agent 二十多次跳过同一道校验集中在某一版提示词。前者让你逐条救火后者直接把手指按在了病根上。飞轮转不转全看调试台顺不顺手。我们把它收敛成五块必备能力缺一块流程就断对话回放区像用户一样重看这场对话每条 AI 消息旁边就是打标入口状态透视板当前阶段、各个计数器、画像草稿名额一眼全览节点轨迹时间线这一轮走了哪些节点、各花多久、每个 AI 口判成了什么——正是诊断包的可视化形态一键闭环按钮把打标、AI 归因、导出考题连成一条流水线版本 AB 复现锁定某一轮换一版提示词原地重跑两版输出并排比——这是改提示词前后到底有没有变好最直接的证据。而且这五块能力不该是某个调试页的私产得做成通用组件正式产品的聊天界面里一个快捷键就能唤出同一套面板内测同学随手就能打标。数据飞轮的进料口越多越好。至于观测平台——我们用的是已经全量开源的 Langfuse——它什么都能存但它端给你看的是 JSON。一条用例里嵌着完整会话状态展开三屏没人读得下去。我们的取舍很简单跑分归平台看懂归自己。题库存储、多版本对比、评委打分、标注队列用平台现成的别手搓评估引擎而这条用例是什么场景、状态怎么流转、错在哪一步这种业务语义的阅读体验自己建薄薄一层按业务字段渲染再深链回平台看原始细节。两边各干各擅长的别强求什么 all-in-one。让测试真的在跑测试的价值不在写出来在每次改动都拦一道。我们那条静默失败了几周的测试就是最好的反面教材——写了但没人跑等于没写。所以每一层挂在什么时机得说死时机跑哪一层成本每次提交代码第一层秒级、零 AI 成本忽略不计每次合并之前第一层 第四层全流程回归秒级改了分类提示词第二层对应题库新旧版本对比考一两百次最便宜模型调用改了话术提示词第三层硬约束 评委几十次调用每天夜里端到端冒烟两三条 全量二三层基线分钟级数量上它应该是一座金字塔规则用例几百条 ≫ 全流程剧本几十条 ≫ 每个分类器题库百来题 ≈ 话术评审几十条 ≫ 端到端冒烟个位数。如果哪天你发现自己的端到端测试反而最多那这座金字塔就是倒的——你在用最贵、最抖、最说不清的方式去测那些本该最便宜、最稳定的东西。图 6 · 测试金字塔 —— 形状同构内容换血实线层确定、虚线层是 AI这座金字塔和传统软件的测试金字塔形状同构内容却换了血单元测试的位置换成了业务规则表集成测试的位置换成了钉死 AI 的全流程回归端到端的位置换成了真模型冒烟。而新增出来的那两层——概率组件的统计化考试、和 LLM 评委——是传统金字塔里没有的它们是 AI 系统特有的质检工序。认清这一点你就不会再拿我们有单元测试覆盖率来自我安慰了那套指标压根没覆盖 Agent 最容易翻车的地方。还得补最后一句把这座金字塔全跑绿也只是拿到了离线通过这一张票而离线提升不等于线上变好。发布时得让离线门禁和线上灰度接上同时盯三类信号——离线质量核心场景通过率、P0 风险数、线上体验转人工率、重复追问率、投诉率、业务结果转化、任务完成率。哪天离线分涨了、线上关键信号却在恶化别犹豫回滚——那说明你的题库漏掉了真实世界正在发生的事该回去补题而不是硬发。落地工具箱每一层该用什么框架方法论讲完程序员最实在的问题是这四层社区有现成的框架吗我该用哪个答案是——每一层都有趁手的工具但没有任何一个框架能一口气盖住四层。谁跟你说 all-in-one谁就没真测过多步 Agent。层测什么现成框架我们的取舍① 业务规则纯函数转移 / 不变量pytest.parametrize、hypothesisproperty-based直接用零额外依赖。表驱动穷举 hypothesis 兜不变量② 分类器逐类准确率 / 混淆矩阵 / 版本对比Langfuse、LangSmith、DeepEval、Promptfoo、OpenAI Evals、Ragas偏 RAG题库 / 多版本 / judge 走Langfuse混淆矩阵这类业务判据自写薄 runner③ 话术硬约束 软质量硬断言裸 pytestjudgeDeepEval / Promptfoo / Langfuse LLM-as-judge硬约束自写正则 evaluator免费不抖软质量挂 judge评分卡自定义④ 全流程回归状态轨迹 / 路由接线没有专门框架LangGraphInMemorySaver pytestmonkeypatch编译期塞 checkpointer 多轮驱动monkeypatch 钉死每个 LLM 口归因 / 飞轮bad case → 考题标注可用 Langfuse annotation queue自建诊断包 编程 Agent 归因标注沉淀回 Langfuse dataset三条取舍逻辑比表格更值得记评估平台我们选 Langfuse不选 LangSmith。不是谁功能更强是开源可自托管——评测数据真实对话不出内网MIT 协议dataset / experiment / score 三件套原生齐全。LangSmith 是 LangChain 官方的闭源 SaaS功能也够但数据要上人家云、还把你绑在一家。选型先问数据能不能出内网再问功能。DeepEval、Promptfoo 这类LLM 评估框架擅长的是第二三层不是第四层。它们把喂一个 prompt、评一次输出做得很顺断言式、YAML 声明式、红队分类器考试和话术评审直接能用。但你要测的是整个多步 Agent 跑完之后、内部的状态转移对不对——这些框架没有跑完读 LangGraph 内部 state 做断言的原生能力。第四层只能靠 LangGraph 自己的 checkpointer 你自己写的 runner。这就是通用评估框架的边界它们测一次 LLM 调用测不了一台状态机。第一层反而最不需要框架。pytest hypothesis 就是全部——因为这层被你亲手从 AI 里剥出来了它就是纯函数用测普通代码的方式测就行。反过来说一个 Agent 里不靠 LLM 评估框架就能测的部分越大说明你的架构分层越干净。尾声四条经验和一个越用越便宜的循环我们踩过的那些坑——好评被当成复推、同一个问题被问两遍、提示词补丁越摞越厚、坏测试静默好几周——大概率你也正在踩、或者即将踩。方法论其实一点都不新全是软件工程攒了几十年的老套路表驱动测试、题库考核、评分卡、测试替身、错题本。新的只是把它们对号入座地放进了 Agent 的分层里然后让 AI 把其中的体力活给干了。如果只让我留四句话**先画那条确定性与不确定性的分界线再谈测试。**线画出来每一块用哪种姿势测是自动成立的画不出来那不是测试问题是架构问题先去重构。**要是只做一件事先铺业务规则那一层。**一天就能铺满它锁死的是产品决策不只是代码。它还是最诚实的文档——文档会撒谎穷举测试不会。**把分类器当模型考、把话术当作文批、把接线当全流程跑一遍。**三种东西三种考法混在一起考你只会得到感觉还行这种没法回归的结论。让 AI 进测试流水线打工而不只是被测。这套体系里AI 有三重身份它是被测者分类和话术、是质检工评委打分、用户模拟器对聊也是质量工程师自动归因、从标注生成考题甚至连怎么生成测试用例这件事本身我们都沉淀成了编程 Agent 能直接执行的规程。人只需要做两件事定标准拍板。正因如此这套体系的边际成本会随着 AI 参与度的提高而持续下降——它是那种越用越便宜的东西。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】