
这两年带智能客服和知识助手项目我最常跟人讲的一句话是如果一条 prompt 不会因为改动而上线前自动跑一遍回归那你还没开始认真做提示工程。听上去有点像测试同学在宣示主权但作为长期做系统架构的人我恰恰认为这件事最先应该由架构师拉起来。因为提示词已经不再是一个“话术优化”问题它决定了系统边界、成本模型、安全闸门和可维护性属于典型的架构问题。我见过太多团队把注意力放在把模型从 A 换到 B或者微调一个更强的底座上却忽略了真正让线上效果崩塌的往往是一句措辞微调。半年多前我们一条线上智能客服 prompt 因为把“帮助用户确认订单”改写成了“按规范确认订单”导致整个客服话术变得僵硬投诉率明显上升。这种问题传统 UI 自动化测不到接口自动化也测不到但提示工程自动化测试可以。它解决的问题不是“模型聪明不聪明”而是“提示词在持续迭代中行为和效果有没有变坏”。这篇文章想聊的就是我作为架构师视角下如何搭建提示词回归测试体系从测试维度设计、用例集构造、框架落地到线上事故复盘再到多模态和 Agent 场景怎么迁移。适合正在做 AI 应用落地、需要建设可测试 AI 系统的架构师、测试开发和大模型应用工程师。不需要你是算法专家只要写过 API 调用、知道 pytest 怎么写就能把大部分内容用起来。1. 为什么提示工程自动化测试会成为架构师的核心战场1.1 提示词在系统里扮演的角色已经变了很多团队对提示词的认知还停留在“产品经理写一段话开发贴到代码里”。两三年前这种玩法勉强能跑因为那时候 prompt 的功能简单错了顶多回答不贴题。但现在不是了。一条线上 prompt 承担的是多轮状态管理、工具调用策略、格式控制、情绪策略、知识引用和安全防线的综合体。它已经悄悄长成了业务逻辑的一部分。拿我们客服系统举例同一套 prompt 模板根据用户意图走不同分支不同分支又带不同的 few-shot 示例。这已经不是“一段提示词”而是“一份可运行的决策配置”。既然它是系统资产就必须用软件工程的纪律来管。我常说一句话UI 自动化是给界面做回归接口自动化是给服务做回归提示工程自动化测试是给模型行为做回归。这三者缺一不可。更要命的是大模型是概率系统不像传统函数那样“输入相同输出就相同”。同样一句话换一个标点可能就会改变结果。这种不确定性如果不靠自动化手段进行系统性观测只靠人肉点几次根本看不出来。尤其是提示词改得越来越频繁的团队你的“测试能力”决定了你能跑多快。反过来看这正是架构师介入的最佳时机把提示词从口头经验变成可测试、可版本化、可回滚的基础设施。1.2 架构师视角这事本质上是质量属性设计我参加过多次架构评审很多人画完系统框图就收工从不谈模型输入输出的“非功能属性”。但作为系统架构师软考里反复强调的那些质量属性——可维护性、可测试性、性能、成本和安全放在提示工程里一个都跑不掉。如果你只在 Controller 里拼接 prompt 字符串那么每个业务方都能随时改改了也不留痕迹。架构师要做的首先是给模型调用层加一个“适配器”所有 prompt 不允许散落在业务代码里必须从配置中心或模板仓库读取并且带版本号。这是一切自动化测试的前提。没有这个前提后面所有测试脚本都是对着空气打拳。然后才是测试策略设计。我会把 prompt 测试当成一个独立的子架构来画从测试用例仓库出发经过执行调度层进到模型网关再把结果送到评估层最后汇总成质量报告并触发门禁。这种结构很像传统软件里的“管道-过滤器”。好处是每一层都可以替换例如把测试模型从 GPT 换成开源模型或者把评估器从规则判分升级成大模型裁判都不影响整体框架。也就是说架构师绝不是去替代测试工程师写几段断言代码而是要承担更高一层的责任定义“什么是好的模型行为”搭起一套可度量、可回归、可追溯的框架。这恰好我理解的核心竞争力——在模型能力越来越趋同的时候团队和团队之间的距离往往就差在这些“测试基础设施”上。2. 从测试维度和评测集开始把“感觉”翻译成可度量指标2.1 先建评分三元组正确性、格式遵循、风险/成本很多团队一上来就想写自动化回归第一步就问“怎么断言模型回答对不对”。问得太早。你应该先回答更基础的问题对你们业务来说什么算“对”我建议起步阶段只抓三个维度正确性、格式遵循、风险与成本。至于句子通不通顺、语气人情味这些初期可以用后续加的“风格一致性”来补充不用第一天就铺满十几个指标。正确性不等于参考答案完全一样它可以是核心实体匹配、要点覆盖度、逻辑无矛盾。比如客服查账单场景只要回答里包含“本月应还金额”“还款日”“逾期影响”这几个核心信息就认为要点覆盖达标。格式遵循则比较刚性如果 prompt 要求输出 JSON那么回答必须能被 json.loads 且字段齐全否则直接判失败。风险维度和成本维度容易被忽略却往往最致命。你有没有给 prompt 加“不透露系统提示词”这类约束有没有出现让用户去走违规操作的建议判断方法可以借助内容审核服务加关键词规则再加人工抽样。三个维度组合起来自然会形成一张评分表。举个例子维度典型判定方式推荐门槛内容正确性核心实体匹配、LLM裁判打分不低于 90%格式遵循JSON Schema / 标记解析100% 必须通过风险安全关键词、审核 API、对抗样本0 严重违规成本/时延Token 统计、首字耗时、总耗时不超预算阈值表格里的数字不是拍脑袋而是先用历史运行 3 天形成 baseline再做门禁。后面改 prompt只要任何一项跌破门槛就必须人工确认而不是自动放过去。2.2 评测集不要迷信“全量”要设计成金字塔第二个常见误区是不断堆积测试用例认为覆盖越多越安全。结果跑一次要花几千块维护成本也高最后没人愿意更新。我用的方法是把评测集做成金字塔底层是烟雾用例中间是业务场景用例顶层是长尾困难用例。不同层级的运行频率不一样。底层烟雾用例数量最少但价值最高。重点是验证 prompt 没有被写坏到连基本功能都跑不通。比如我们系统就放十条用例覆盖“查账单、报故障、转人工、投诉、闲聊”几个主干路径每次 PR 合并前必须跑。中间层是核心业务场景会刻意加入多轮对话、上下文变化和同义改写通常有几百条每天凌晨定时跑。顶层则是困难样本包括安全攻击、诱导越狱、情绪极端的用户输入、长文本和未知领域问题每星期跑一次用它来发现指标体系照顾不到的边缘故障。评测集的素材来源也很关键。不要只靠测试人员凭空编要接入线上日志、用户投诉工单、客服人工标记的 badcase。凡是线上出过事的输入格式化后先扔进困难样本池加上人工标注的预期行为。产品在进化、用户在变异所以评测集必须每周有人维护。我给团队立了条规矩新增一个评测用例必须带上“发现者、关联场景、期望行为、最近一次验证时间”不然三个月后没人知道这条用例在保护什么。3. 一套最小可落地的提示词回归测试框架搭建实录3.1 选型定调pytest YAML 统一模型调用层市面上有很多现成的 LLM 评测平台有的确实很强。但如果你正处在从 0 到 1 的阶段我建议先不要上重平台而是用一套轻量脚本跑起来。原因很简单早期你的评测标准天天在变平台的重模板和权限配置会拖慢迭代不是技术输不起是心态输不起。我们自己用的组合是 pytest YAML 用例文件 一个统一的模型调用封装层。选 pytest 是因为团队里本来就做过接口自动化测试报告、失败重跑、插件生态都成熟。YAML 用来描述每一条用例的输入输出期望和断言方式可读性比 Excel 好太多也方便进 Git 做 diff。模型调用封装层是最重要的一层上游接真实模型网关和测试专用的沙箱环境不让测试请求污染生产数据。目录结构大致长这样prompt_test_repo/ ├── cases/ │ ├── smoke_cases.yaml │ ├── business_cases.yaml │ └── hard_cases.yaml ├── evaluators/ │ ├── rule_based.py │ ├── schema_check.py │ └── llm_judge.py ├── runners/ │ ├── model_client.py │ └── executor.py ├── reports/ │ └── latest_result.json └── conftest.py这个结构的好处是职责清楚cases 里只放测试描述evaluators 里只放判定逻辑runners 里只放执行细节。以后某个环节想替换不会伤筋动骨。跟你维护传统测试框架的道理一模一样。3.2 核心模块一测试用例装载器YAML 用例长什么样我拿一个简单的客服场景举例。每条用例包含 id、用户输入、期望判定、可选参数等字段。id: cs_bill_query_base meta: level: smoke owner: customer_service_team model: provider: openai_compatible model_name: gpt-4o-mini temperature: 0 inputs: messages: - role: system content: type: template name: after_sales_prompt version: 2025.03.01 - role: user content: 我这个月话费账单是多少 assertions: check_points: - type: contain_keywords keywords: [账单, 金额] - type: no_negative_keywords keywords: [无法查询, 系统维护] required_format: plain_text装载器要做的事情很简单读取目录下所有 YAML解析成测试用例对象同时做一些基础校验防止写错字段。很多团队会在这一步埋坑——一个 YAML 写错关键字后面整批失败还找不到原因。所以我在用例加载后一定会打印“共加载 X 条用例失败 Y 条”Y 必须为 0。3.3 核心模块二执行器和重试策略真正跑测试的时候最容易出问题的是重试。模型接口偶尔超时、限流不代表你的 prompt 有问题。如果测试一遇到超时就失败误报率会高到让人放弃。我的经验是给执行器加三层控制超时时间、失败重试次数、退避策略。比如超时设为 30 秒失败重试两次每次退避 2 秒重试。但如果模型已经返回 200 成功内容却不符合断言这种失败不能重试因为大概率是语义问题而不是网络问题。所以代码里要区分“基础设施失败”和“断言失败”两者走不同的处理路径。并发也很考验架构。对模型 API 的并发必须控制在一个合理范围否则线上业务会被测试流量挤垮。可以把并发数设置在线上峰值的 5% 以内并且写进执行器的配置。实际跑一批三百条的用例并发 5 的时候大概需要几分钟完全能接受。要的是稳定和可重复不是测试跑得越快越好。3.4 核心模块三评估器与门禁评估器是整个测试框架里最需要花心思的部分。我习惯把判断拆成两层先做硬性规则再做语义评估。硬性规则包括是否包含关键词、是否可解析 JSON、是否命中禁用词、长度是否超限。这类规则执行快、成本低、结果稳定适合做第一层筛子。只有硬性规则通过了才轮到语义评估。语义评估初期可以用文本相似度。比如参考答案已经标注了“应该包含还款日”但模型说“您最后还款日是每月15日”通过词向量相似度能判断意思接近。等团队成熟以后再引入大模型裁判。用法是给裁判模型一套打分卡让它按 0-5 分给输出打分然后只保留低分样本让人工复核。这样做的好处是不用人工看全部结果成本可控。当所有用例跑完我会在 pytest 的 teardown 里汇总结果并和 GitLab CI/Jenkins 的门禁关联。比如“烟雾用例通过率必须 100%业务用例关键词命中率不得低于 95%禁止出现安全违规”任何一条不满足合并请求直接打回。这里有个小提示门禁阈值先别定太严先跑一周看历史数据取 P90 作为门禁值比拍脑袋可靠得多。4. 真实的智能客服案例一次 Prompt 改动引发的线上事故复盘4.1 事故背景一句话让客服从“亲近”变“机械”有一段时间客服系统质检反馈“机器人回答太啰嗦用户问 A 它总是扯到 B”。产品经理就优化了 prompt新增了一句“如果用户只问当前问题不要主动额外介绍其他业务”。从语义上看完全没毛病上线的确让篇幅变短了。但随后投诉量开始涨用户反复说“机器人态度很差像在应付”。我们一开始怀疑是模型服务升级导致的因为那两天确实改了模型版本号。后来对照日志发现模型升级前后 24 小时风格突变的高峰恰好发生在 prompt 变更后的 2 小时。再仔细看新版本 prompt问题变得非常明显新增的“不要主动额外介绍其他业务”被模型理解成了“不需要共情不要多说”。在用户表达不满时客服回复变得冰冷。为什么这种问题没在测试阶段发现因为当时只有人工点几个常见问题没人用“用户已愤怒”这类情绪输入去跑回归。如果当时有自动化测试评测集里放上个“被多收费后投诉”的 case结果会立刻暴露。4.2 当时我怎么排查的先用同一批 case 跑新旧版本事故发生后我带着测试同学做了一次对照实验。把所有线上真实会话里形态比较完整的 200 条输入整理出来分别跑线上旧版本提示词和准备回滚的新版本提示词。为了排除模型差异两个版本都指向同一个模型版本然后把温度参数也调成 0。结果很有意思正常查询类场景通过率几乎没变化但是情绪类场景比如“你们乱扣费”“我要投诉到消协”新版本通过率比旧版本低了快三十个百分点。模型回答普遍出现“抱歉给您带来不便但我需要先确认……”这种机械表达。再用文本 diff 逐句消解最终定位到那新增句子和原有“先共情再解决问题”指令存在歧义。模型在指令冲突时选了更明确的“不要做额外事”而没有遵守抽象层级的“共情优先”。那次之后我明确了一个原则凡是涉及情绪、安全、风险控制的 prompt 修改必须走完整的情绪场景回归而且不能只看通过率还要看失败案例的具体输出。自动化不只是告诉你有问题更可以帮你做问题定位。对照实验就是最好的调试手段。4.3 后来怎么用回归测试拦住同类问题事故后我们立马补建了一条“强制回归”流程。只要有人改了系统级 prompt 模板就必须至少跑一百条固定业务用例并且必须包含以下几类普通问询、多轮追问、情绪投诉、调戏攻击、超长输入。每类都有硬性指标。第一次跑的时候光是“情绪投诉”这块就产生了 23 个失败用例全被拦下来人工逐条改。我还让测试团队把线上曾经出事故的输入都沉到评测集里形成“事故案例池”。以后任何 prompt 上线前都会自动把历史事故案例跑一遍。项目组开始还觉得这套流程太重但连续两次拦住可能导致线上事故的改动后所有人都没意见了。有时候体系的价值不需要长期证明一次事故止损就够了。5. 六个高频问题和排查技巧每一条都是踩坑踩出来的5.1 分数随机波动太大怎么区分模型噪声和真实退化这是刚上线最容易让人崩溃的问题。同一组 prompt、同一批用例上下午跑出来的通过率差几个点你很难判断这到底是 model provider 悄悄换了权重还是只是随机采样变化。我给团队的做法是把 temperature 在测试环境固定为 0同时每个用例跑 3 次取多数投票结果。如果团队预算紧张至少对失败用例重跑一次确认不是一次性抖动。更稳妥的做法是记录每一次运行的模型名称、模型版本、服务端参数、响应耗时以及每一条用例的输出。就算当前无法解释某个波动以后模型方升级了你能通过历史 trace 反查。没有 trace 的大模型测试就像没有日志的微服务出了问题只能靠猜。5.2 大模型当裁判自己也开始胡说了用 LLM 评估 LLM 是热门方案但裁判本身不稳定。我们踩过一次给裁判提示“请判断回答是否礼貌”结果它把带“亲”字的话全部判高分把偏书面但更专业的回答判低分因为裁判被字面带偏了。后来我改成结构化评判卡给裁判模型列清楚各项打分维度和锚点案例。比如 5 分必须“包含完整解决方案且语气温和”3 分必须“未解决问题但语气礼貌”1 分则“出现负面表达、敷衍或错误信息”。有了锚点之后裁判打分和人工复核的一致性从七十多分提升到九十左右。如果对某一条用例的裁判结果没有信心我还会开双评委两个不同模型各打分意见不一致时由人工或者第三个模型仲裁。5.3 测试次数越多成本越高怎么控制预算评测集如果每周全量跑账单会很难看。我的成本策略是分层调度每条 prompt 的 PR 阶段只跑烟雾用例数量控制在二十条以内每天凌晨跑核心业务用例大约两三百条长尾困难用例和裁判模型评估每周跑一次并且只对关注的高风险场景启用 LLM 裁判。普通的中阶梯用规则判分成本几乎可以忽略。另一个省钱技巧是增加“相同输入缓存”。当 prompt 没有变更时相同输入不重复调用模型直接把上次结果拿出来对比只有 prompt 有变更时才真正发起请求。这个逻辑很像接口测试里的响应缓存节省效果非常明显两周下来成本大概少了四成。代价是报告要维护好每次运行的 commit 和 prompt 版本不然缓存会张冠李戴。5.4 不同模型对同一个 prompt 的行为差异很大我们在项目里会同时评估几个商用和开源模型同一个 prompt 在 A 模型上表现很好换到 B 模型就可能输出破格式。这不算模型“变笨”而是 prompt 天然带有模型偏好。架构上模型网关层要把模型名称和 prompt 模板做绑定不能让上游业务传一个模型名就自动套一套模板。自动化的视角下我要求同一个评测集对每个模型单独跑一份报告并计算“模型差异度”。如果某类 prompt 只在某一个模型上失败要么该 prompt 里写了对该模型不友好的符号要么该模型官方版本做了行为调整。对差异特别大的模型不要追求完美统一项目可以在网关层做降级策略A 类 prompt 走模型甲B 类 prompt 走模型乙。这些都需要测试数据支撑而不是拍脑袋决定。5.5 用户输入长度分布变化也会让 prompt 意外失效我们曾遇到线上回答准确率下滑但手工测试怎么都复现不了。后来分析线上请求发现那天某营销活动让用户输入变得特别长都是大段大段的诉求描述。prompt 模板把长输入塞到上下文里模型处理长文本时的注意力被稀释回答风格明显飘了。从那以后我在评测集里专门增加了长度边界用例。每个 prompt 至少要有短、中、长、超长四档输入超长档可以直接切到上下文上限的 80%。同时还要检查输入是否被截断如果模板拼接后超过模型上下文窗口很多实现会选择直接报错或者静默截断。这类问题在传统接口测试里很难遇到但在大模型场景是家常便饭需要你专门设计。5.6 回归用例维护累人人都想偷懒最理想的状态是每个用例都有 owner业务变了用例就跟着更新。但现实是业务方提了新需求没人回来更新测试数据。我试过几个办法最有用的一个是“失效用例自动通知负责人”。当某条用例连续两周失败且没有人工标记为预期变化就把这条用例的 owner 加进企业微信群提醒并升级给架构组。更长期的做法是引入“线上舆情反馈回流”。把客服聊天里的“不满意”按钮、转人工原因、差评文本定期捞出来聚类成新的测试用例。真正常青的评测集不该靠人天天手动想而应该从真实反馈长出来。架构师要做的就是搭好这条数据回流管道让它自动跑起来。6. 多模态和 Agent 时代架构师如何把这套方法论迁移出去6.1 文生图、视频生成场景的提示词测试思路很多人觉得提示工程测试只是文本模型才需要其实文生图、视频生成领域的提示词早已在吃同样的苦。现在是多模型时代兼容 SDXL、Flux、Seedance 这类生成模型的团队越来越多。文生视频里常听到的提示词技巧比如“情绪靠肌肉手部靠结构接触靠阴影真实靠受力”本质上就是在用自然语言约束模型的输出结构。这类口诀很有价值但没有测试体系你没法知道换一个模型版本后它还能不能遵守这些约束。多模态场景的自动化会更难因为传统断言规则已经失效。你是没法用关键词判断一张图片是否正确画出“手部结构”的。我们目前的做法有两层第一是用视觉语言模型对生成图片的局部结构做检测比如手部关键点是否完整、人体关节是否有反折第二是建立负面 checklist把常见模型翻车点写成固定问题让多模态评测模型逐项打分。比如“图中是否有六根手指”“接触面阴影是否突兀”“人物肌肉是否违背运动逻辑”。这些评测项沉淀下来之后其实就是一套新的“提示词回归测试集”。在这个方向上架构师要解决的是测试编排和结果存储问题。生成一段视频的成本比文本高一个量级所以测试用例必须按“静态帧抽取、关键动作检测、多片段离线评测”来设计。并且要确保同一测试集可以平行跑多个模型方便对比某个模型升级后对 prompt 遵循度的变化。没有这套东西团队很难回答“为什么这个月的画面质量突然下降了”。6.2 Agent 工具调用链路的回归测试看的是行为而不是话术Agent 应用和普通 Chat 的最大区别是模型不再只输出文字它还可能输出工具调用指令。提示词测试因此从“看回答像不像”变成“看它有没有做正确的事”。比如用户说“帮我查一下上个月的账单并且发邮件给我”Agent 应该先调用账单查询接口拿到结果后再调用邮件发送工具。如果 prompt 改动导致模型直接跳到邮件发送却没先查询这就是行为级回归错误。我的做法是把 Agent 的工具调用序列当作断言对象。每一步动作都要有预期 tool_name、预期参数部分匹配、以及最终答案里的引用是否来自查询结果。测试框架里需要额外记录 model 的 tool_calls 数组而不是只看字符串输出。你可以理解为过去接口自动化测的是 HTTP 请求和响应Agent 自动化测的是模型对工具的选择权和参数组装能力。这种测试对架构设计提出了更高要求模型调用层必须把工具定义做成可配置、可版本化的 schema。工具 schema 一变prompt 里的 function description 也要变如果没有统一的 schema 管理中心很容易出现工具更新了但模型还在按旧描述调用。等到 Agent 真出错了又得翻半天代码。6.3 与 RAG 检索、模型微调的测试怎么衔接最后说一下容易混淆的部分。热词很多RGA 检索增强生成、模型微调、Agent 工具调用经常被混在一起。但在测试体系里这三层必须解耦。提示词回归只测“在给定上下文的前提下模型行为有没有变化”。如果系统用了 RAG那么测试应该把检索出来的候选文档先固定成一份快照再作为变量输入 prompt。否则你会分不清效果下滑是因为提示词写坏还是因为检索改写算法变了。模型微调之后也要重新跑一遍全部提示词回归用例。我见过最典型的场景是团队微调了底座模型LLM 对指令的服从性提升但原有 prompt 里的负面防绕过约束不再生效。你不跑全套回归很难自己发现。所以架构上我会把这三层测试做成三个独立流水线再在最上层汇总成一个“AI 应用质量报告”检索命中率多少、提示词通过率多少、微调模型对比差异多少。只有分层清晰问题定位才能快速。7. 最后分享三点个人体会7.1 先观测后自动化别急着上平台我见过最可惜的团队花两个月搭了一个提示词评测平台搭完之后发现连模型调用的统一日志都没有。再好看的报表底层数据不准就没有意义。我自己的顺序永远是先做观测把所有线上请求的 prompt 模板、模板版本、模型版本、上下文 token 数、响应时延、输出长度全部记录下来。有了这些基础日志自动化测试的链路才是有源之水。7.2 提示词版本管理要从第一天开始如果你做 AI 应用超过一个月应该尽快把提示词搬出代码放到带版本管理的配置中心。别说什么“现在项目小不用管”提示词一旦散落在代码里后面做自动化测试时你会发现根本无法关联“线上跑的是哪一版”。版本管理不是资产管理同学的洁癖它是自动化测试能够追溯效果的前提。7.3 最容易低估的是“失效定位”成本测试没过如果只是告诉你“这条案例失败了”开发人员仍然不知道怎么改。所以我坚持测试报告里必须附上输入、输出、期望结果、失败原因标签和相邻相似案例对比。尤其是失败原因尽量用规则或模型预判打标比如“格式错误”“关键信息缺失”“存在敏感词”。宁可让测试报告多花一点时间生成也要让一线解决问题的人拿到可以动手的信息。提示工程自动化测试做了大半年我自己最大的变化是不再迷信某个大模型的“聪明程度”而是更在意手里的评测集能不能覆盖真实用户门禁能不能在模型和提示词变化时守住底线。架构师的核心竞争力从来不是会画几张架构图而是你愿不愿意把最不稳定、最主观、最容易随口的提示词也当成一辈子的系统工件去打磨。这套方法初期投入一定不小但等你被一条 prompt 在线上坑过一次就会明白这一切都值得。