同一个接口每次返回都不一样?大模型输出的可靠断言怎么写

简介: 本文以电商客服故障为切入点,详解AI测试开发中“如何为不确定性输出做自动化测试”。提出断言四层模型:L1请求约束、L2格式硬断言、L3语义软断言(LLM-as-Judge)、L4稳定性率验证,破除“temperature=0即确定”的误区,强调工程化可复现性。

AI 测试开发面试高频题:"大模型的输出是不确定的,你怎么做自动化测试?"
这篇用一个真实线上故障,完整还原 AI 测试开发工程师的处理过程:怎么定位、怎么写代码、最后沉淀成什么方法。

一、真实故障:断言天天红,后来有人把它关了

某电商公司的智能客服项目,测试工程师小周给"订单状态查询"这个 LLM 接口写了自动化用例,断言写得很传统:

assert response.text == "您的订单 TEST-1001 已发货,预计3天内送达"

上线第一周,这条用例在 CI 里天天红。同样的输入,模型今天回"已发货,预计3天送达",明天回"您好,包裹已在路上啦~",后天直接换成 markdown 列表。小周先是把断言放宽成 assert "发货" in response.text,折腾几轮后烦了,直接把用例禁用,备注写了句:"LLM 输出随机,断言没意义"。

三周后,半夜告警:订单查询功能整体不可用。排查发现,模型输出悄悄变成了"带 markdown 代码块的 JSON"——内容其实没错,但下游服务直接 json.loads(),遇到 ``` 包裹就抛异常。致命的是,这条用例早就被禁用了,发布前没有任何拦截,故障持续了 40 分钟。

复盘时团队才意识到:不是大模型不能测,而是用精确匹配的旧思路去测,一定会经历"天天误报 → 麻痹放弃 → 故障裸奔"这个死亡循环。

二、先破除一个误区:temperature=0 也不保证逐字相同

面试里很多人第一反应是:"把 temperature 设成 0,输出不就固定了吗?"

不够。temperature=0 只是让采样退化为取最大概率 token,但服务端的 continuous batching、浮点累加顺序、并行解码等实现细节,仍然可能让同一输入产生细微的措辞差异。这在 OpenAI 官方论坛和 GitHub issue 里是被反复讨论过的已知现象。

所以正确的目标不是"逐字相等",而是把断言分层:机器能稳定的部分用硬断言锁死,语言天然漂移的部分用软断言兜住。

三、核心代码:四层断言策略

第 1 层:请求侧先约束输出

能结构化的绝不自由发挥。temperature=0 + 结构化输出,把 80% 的不确定性在源头掐掉:

import json
from openai import OpenAI

client = OpenAI()

def ask_order_status(order_id: str) -> str:
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        temperature=0,
        response_format={
   "type": "json_object"},   # 强制 JSON 输出
        messages=[
            {
   "role": "system", "content": (
                "你是客服助手,只返回 JSON:"
                '{"status": "shipped|pending|refunding", "summary": "不超过30字"}'
            )},
            {
   "role": "user", "content": f"查询订单 {order_id} 的状态"},
        ],
    )
    return resp.choices[0].message.content

第 2、3 层:格式硬断言 + 语义软断言(LLM-as-Judge)

格式、字段、枚举值这些"机器契约",必须硬断言,一个字符都不能让;语义措辞交给裁判模型判断:

JUDGE_PROMPT = """你是严格的测试评审员。
参考答案:{expected}
模型实际输出:{actual}
判断实际输出与参考答案语义是否一致,且不含事实错误。
只返回 JSON:{
   {"pass": true/false, "reason": "..."}}"""

def assert_llm_output(actual: str, expected: str):
    # —— 第2层:格式硬断言(复现故障的关键防线)——
    data = json.loads(actual)                      # 不是合法 JSON 直接失败
    assert {
   "status", "summary"} <= set(data), "缺少必需字段"
    assert data["status"] in {
   "shipped", "pending", "refunding"}, "枚举值非法"

    # —— 第3层:语义软断言(LLM-as-Judge)——
    verdict = client.chat.completions.create(
        model="gpt-4o", temperature=0,
        messages=[{
   "role": "user",
                   "content": JUDGE_PROMPT.format(expected=expected, actual=actual)}],
    )
    result = json.loads(verdict.choices[0].message.content)
    assert result["pass"], f"语义断言失败:{result['reason']}"

注意裁判模型要选比被测模型更强的型号,并且裁判的提示词、温度都要固定——裁判本身也要"可复现"。

第 4 层:稳定性测试,用"一致性率"替代单次判定

单次通过不算通过。同样的输入跑 N 次,格式一致性必须是 100%,语义一致性给一个可接受的阈值:

def test_output_stability(n=10):
    results = []
    for _ in range(n):
        raw = ask_order_status("TEST-1001")
        json.loads(raw)                    # 任何一次格式失败都算不通过
        results.append(json.loads(raw))

    semantic_ok = sum(r["status"] == "shipped" for r in results)
    rate = semantic_ok / n
    assert rate >= 0.9, f"语义一致性率 {rate:.0%},低于阈值 90%"

这条用例就是小周团队复盘后补上的:它不管模型怎么措辞,只要 10 次里有 1 次格式不对,CI 立刻红——故障里那种"格式漂移"从此不可能静默上线。

四、沉淀成方法:AI 测试开发的断言四层模型

层级 断言对象 方式 容忍度
L1 请求侧约束 输出格式 temperature=0、response_format、严格 schema 从源头减少漂移
L2 格式硬断言 JSON 结构、字段、枚举 代码断言 零容忍
L3 语义软断言 内容正确性 LLM-as-Judge / G-Eval 阈值制(如 ≥0.8)
L4 稳定性断言 一致性率 多次采样统计 格式 100%,语义 ≥90%

配套两条工程纪律:一是禁止禁用失败用例,LLM 用例红了要么修断言要么修模型,不许关掉;二是裁判提示词纳入版本管理,裁判变更也要走回归。开源社区的 DeepEval(G-Eval 指标)、OpenAI Evals 都是这套思路的成熟实现,可以直接复用,不必从零造。

五、面试追问,你答得上来吗

  1. LLM-as-Judge 自己也会出错、也会漂移,怎么办?——答:固定裁判模型与提示词版本、温度设 0、定期用人工标注集校准裁判的准确率(裁判的准确率本身也是一个被测指标)。
  2. 为什么不直接用余弦相似度做语义断言?——答:相似度对措辞敏感、对事实不敏感,"3 天送达"和"5 天送达"相似度很高但都是错的;语义判断交给更强的裁判模型更可靠,相似度只适合做粗筛。
  3. 稳定性测试跑 10 次成本高、CI 慢,怎么权衡?——答:分层执行——格式断言每次 PR 跑;语义与稳定性测试每晚定时跑全量,发布前跑冒烟子集。

下一篇预告:《RAG 上线后为什么总"答非所问"?——黄金数据集与检索质量评测》

相关文章
|
7天前
|
存储 弹性计算 缓存
阿里云服务器租赁费用:新版租赁收费标准及活动报价参考
本文更新了2026年阿里云全系列云服务器租赁活动报价,所有特惠资源均可前往阿里云活动中心选购,整体覆盖从个人入门到企业级高性能场景的全梯度需求。其中轻量应用服务器主打极致性价比,2核2G峰值200M带宽配置每日10点、15点限时抢购价仅38元/年,2核4G配置379元/年起;高性价比的经济型e实例、通用算力型u2i实例覆盖2核4G至4核32G全档位,适配开发测试与中小型企业业务;搭载英特尔至强6处理器的第九代c9i企业级实例算力较上代提升20%,支撑高并发生产环境,不同实例规格价差清晰,用户可根据自身业务负载与预算灵活选型。
1746 117
|
8天前
|
人工智能 程序员 API
Codex 接入 DeepSeek-V4-Flash:还能补上识图,提供两套方案
Codex 接入 DeepSeek-V4-Flash 怎么配?本文覆盖 CLI 与桌面端,再用 qwen3-vl-flash 补识图,两套方案可直接照做
1251 9
|
14天前
|
云安全 人工智能 运维
阿里云联动百位企业安全专家,共识Agent防御最佳实践
当Agent成为新员工,你的安全边界在哪里?
1956 9
阿里云联动百位企业安全专家,共识Agent防御最佳实践
|
8天前
|
编解码 人工智能 安全
2核4G/4核8G/8核16G阿里云服务器如何选择实例?经济型e、通用算力型u2i与计算型c9i选哪个?
本文介绍了阿里云2核4G、4核8G、8核16G三档主流配置下经济型e、通用算力型u2i和计算型c9i三种实例的最新活动价格与适用场景。同配置下三者价差显著,以2核4G为例,经济型e低至599.93元/年,计算型c9i则高达1742.08元/年。文章详细解析了各实例的性能定位:经济型e适合轻负载入门场景,u2i兼顾稳定算力与性价比,c9i凭借第9代至强处理器与芯片级安全能力支撑高性能业务。同时提示用户可叠加满减优惠券享受折上折,建议根据业务负载与预算综合决策。
543 112
缓存 安全 IDE
959 2
|
20天前
|
人工智能 前端开发 Linux
Codex 桌面版安装 + CC Switch 接入第三方 API 完整教程(2026 最新)
2026最新教程:手把手教你安装Codex桌面版,通过CC Switch v3.17.0一键接入Fenno等国产API(兼容OpenAI Responses格式),跳过账号登录,完整启用代码审查、多步任务与上下文感知功能。零基础友好,全程图文实操。(239字)
2942 4
|
8天前
|
人工智能 JSON Shell
2026AI漫剧本地全开源方案(附各个软件模型链接),8G显卡也能流畅运行
这是一套完全本地化部署的AI漫剧生成技术链路:涵盖LLM剧本分镜生成、FLUX文生图(IP-Adapter人脸锁定)、StoryDiffusion时序连贯控制、LTX-2.3唇形同步视频生成,及ComfyUI全流程调度。零云端费用,仅耗硬件算力,单集2–4小时可产出竖屏短视频,适配抖音/B站分发。
|
5天前
|
编解码 弹性计算 云计算
MiniMax-H3 视频生成模型 — 一键部署与使用指南
MiniMax-H3是MiniMax开源的33B全模态视频生成模型,支持文生视频、图生视频、参考生视频三种模式,原生输出2K/15秒带立体声音频视频,已原生适配ComfyUI,并可通过阿里云计算巢一键部署。(239字)
|
12天前
|
存储 人工智能 关系型数据库
阿里云AI产品与云产品最新组合套餐:Token Plan、AI coding及云服务器和建站等组合优惠价
阿里云推出全新“算力+模型+应用”一站式云与AI组合套餐活动,覆盖从个人开发者到中大型企业的全场景需求。核心亮点为分三档定价的Token Plan订阅服务,支持Qwen3.8-Max-Preview大模型调用,错峰时段最低可享0.2折优惠。活动同步推出AI Coding、智能体部署、云电脑托管、0代码建站等十余类场景化组合,搭配99元/年的普惠云服务器、88元/年的入门数据库等经典特惠产品,还为企业提供1V1定制化AI转型方案,大幅降低了不同用户群体拥抱AI的技术门槛与采购成本。
748 111