为什么大模型测试和传统软件测试完全不同
本章导读
如果你带着传统测试的思维去做大模型测试,一定会碰得头破血流。
本章会深入剖析传统测试的底层逻辑与大模型的核心差异,并帮你建立“评估能力边界”的新思维。
读完本章,你将理解:
-
为什么等价类、边界值、断言在 LLM 测试中大面积失效
-
大模型测试的本质是什么
-
如何从“验证正确性”转向“评估能力边界”
1.1 传统软件测试的底层逻辑
在讨论差异之前,我们先回顾传统软件测试的基石——确定性系统。
1.1.1 确定性系统的定义
传统软件(Web 应用、移动 App、后端服务、嵌入式系统等)本质上是确定性系统:给定相同的输入,系统总是输出相同的结果。
【图1-1:确定性系统示意图】

基于这个确定性,我们发展出了一整套成熟的测试方法论:
| 方法 | 核心思想 | 示例 |
|---|---|---|
| 等价类划分 | 将输入域划分为若干等价类,每个类取一个代表值 | 年龄输入框:有效类 1-100,无效类 <1,无效类 >100 |
| 边界值分析 | 重点关注等价类边界的值 | 边界值:0、1、100、101 |
| 判定表 | 描述输入条件组合与输出结果的关系 | 会员等级 + 消费金额 → 折扣率 |
| 状态转换 | 测试系统在不同状态间的迁移 | 订单状态:待支付 → 已支付 → 已发货 → 已完成 |
这些方法的共同特点是:我们可以穷举或近似穷举输入空间,并明确知道每个输入对应的预期输出。
1.1.2 传统测试的核心假设
传统测试建立在三个核心假设之上:
-
可预测性:给定输入,输出是确定的
-
可复现性:缺陷可以在相同条件下复现
-
可判定性:存在明确的“正确/错误”判定标准
经验提示
这三个假设在大模型测试中全部被打破。如果你在转行时仍然固守这些假设,你会发现自己寸步难行
1.2 大模型:非确定性系统
1.2.1 什么是非确定性
大语言模型是一个概率生成模型。它的每一次输出,都是从概率分布中采样的结果。
【代码1-1:大模型的非确定性】
import openai
from openai import OpenAI
# 初始化客户端
client = OpenAI(api_key="your-api-key-here")
def test_non_deterministic(prompt: str, n_calls: int = 3, temperature: float = 0.7):
print(f"{'='*50}")
print(f"Prompt: {prompt}")
print(f"Temperature: {temperature}")
print(f"{'='*50}\n")
responses = []
for i in range(n_calls):
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}],
temperature=temperature
)
answer = response.choices[0].message.content
responses.append(answer)
print(f"【第 {i+1} 次调用】")
print(f"{answer}\n")
print("-" * 50)
return responses
# 测试示例
if __name__ == "__main__":
prompt = "用一句话解释什么是人工智能"
test_non_deterministic(prompt, n_calls=3, temperature=0.7)
即使将 temperature 设为 0,由于浮点数精度、并行计算、GPU 内核的不确定性,结果仍然可能产生微小波动。对于生成任务,这种波动可能导致完全不同的输出。
1.2.2 非确定性带来的根本挑战
挑战1:没有“标准答案”
传统测试中,我们可以写出这样的断言:
assert calculator.add(1, 1) == 2
但在大模型测试中,你问“什么是人工智能”,模型可能给出以下任意一种回答:
-
“人工智能是让机器模拟人类智能的技术”
-
“AI is the simulation of human intelligence in machines”(中文提问下模型有时会输出英文)
-
一段 500 字的详细解释
-
一个反问:“你指的是强人工智能还是弱人工智能?”
这些回答可能都是合理的,也可能部分合理。你无法用简单的等值判断。
挑战2:测试用例无法“固化”
传统测试中,一个测试用例是一个固定的 (输入, 预期输出) 对。
在大模型测试中,同样的输入对应无限种合理输出。你无法穷举“预期输出”,只能通过评测标准动态判断。
挑战3:缺陷难以复现(幽灵 Bug)
作者在使用目前市面上的一些大模型产品时发现,这种情况并不少见,大模型“一本正经”的在输出结果,但是这些结果乍一看没有问题,但是实际采纳就会发现存在BUG。
例如:在配置spring项目多数据源时,有别于经常使用的MySQL数据库,笔者使用postgresql数据库时,基于mybatis-plus,大模型在yml文件中推荐的写法中,url参数输出结果为“jdbcurl”,导致mapper相关错误。排查代码逻辑很容易忽略配置相关信息。
1.3 传统测试方法为何失效——具体分析
本节用具体例子说明,为什么等价类、边界值、断言等方法无法直接应用于大模型测试。
1.3.1 等价类划分的失效
场景:测试一个电商客服大模型,用户问题按业务类型分为“退款”“物流”“产品咨询”“投诉”四类。
传统思路:每类取 3-5 个典型问题,构成测试集。
问题所在:
-
同一个业务类内部,问题的语义差异远大于传统等价类的差异。“退款需要多久”和“退款被拒绝了怎么办”虽然都属于“退款”类,但模型处理逻辑完全不同。
-
模型的表现不仅取决于问题类别,还取决于措辞、语气、上下文长度、对话历史等变量。等价类划分无法覆盖这些维度。
1.3.2 边界值分析的失效
场景:测试模型对输入长度的处理。模型的上下文窗口为 4096 个 token。
传统思路:测试长度为 4095、4096、4097 token 的输入。
问题所在:
-
长度边界确实需要测试,但大模型真正的“边界”往往是语义边界。例如:
-
当输入接近上下文窗口上限时,模型是否会遗忘开头的内容?
-
在长文本中插入关键信息,模型能否正确提取?
-
跨越多个段落的指代消解是否仍然准确?
-
-
这些语义边界无法用简单的数值边界覆盖。
1.3.3 自动化断言的失效
场景:自动化测试中,需要判断模型回答是否包含正确答案。
传统写法:
assert "北京" in model_response # 判断回答中是否包含“北京”
问题:
-
模型可能回答“中国的首都是 Beijing”,你的断言会失败(大小写/中英文)
-
模型可能回答“北京,也就是北平”,断言通过但语义不完整
-
模型可能回答“上海”,断言失败,但“上海”本身也是一个合理的城市名
更严重的问题:你无法为每个测试用例手写复杂的语义匹配规则。业界实践是用模型评估模型——但这引入了新的不确定性(评估模型本身也会犯错)。
【表1-1:传统断言 vs LLM评测方法对比】
| 维度 | 传统断言 | LLM 评测方法 |
|---|---|---|
| 判定依据 | 字符串/数值精确匹配 | 语义相似度、LLM-as-Judge |
| 预期输出 | 固定值 | 可接受范围/参考集 |
| 通过标准 | 100% 精确 | 统计阈值(如相似度 > 0.8) |
| 可维护性 | 低(随业务变化频繁修改) | 中(需要持续校准评估器) |
1.4 大模型测试的新范式
1.4.1 核心转变:从“验证正确性”到“评估能力边界”
基于上述分析,我提出大模型测试的新定义:
大模型测试的本质,不是验证模型在某个输入下是否输出正确答案,而是系统性地评估模型的能力边界——它擅长什么、不擅长什么、在什么条件下会失败、安全底线在哪里。
这个定义带来了三个核心转变:
转变一:从“断言”到“评测体系”
我们不再写死预期,而是建立多维度的量化指标。常见的评测维度包括:
| 维度 | 定义 | 量化方式示例 |
|---|---|---|
| 准确性 | 事实性错误的比例 | 人工标注错误率 / 事实一致性得分 |
| 完整性 | 回答是否覆盖用户问题的所有要点 | 要点覆盖率(0-100%) |
| 有用性 | 回答是否解决用户实际需求 | 人工评分(1-5分)/ 点赞率 |
| 安全性 | 是否输出有害内容 | 违规率 / 红线用例通过率 |
| 流畅性 | 语言是否通顺自然 | 困惑度(PPL)/ 人工评分 |
|
风格一致性 |
是否符合预设的语气和风格 | 风格分类器得分 |
| 结果满意程度 | 对于测试结果符合预期的程度 | 语义、结果的匹配程度 |
转变二:从“单点测试”到“统计测试”
由于大模型的非确定性,单次测试结果没有意义。你必须在统计层面评估模型表现。
操作示例:评估模型在某个 Prompt 上的稳定性
#发出问题的
user_argent = ConversableAgent(
name="数据分析师",
llm_config=llm_config,
system_message="""你是数据分析专家。根据用户要求,必须使用工具来解决问题。
工具如下:
- get_weather(city): 查询城市天气
- calculate(expression):计算数学表达式
根据用户的问题,正确选择工具。
""",
function_map={
"get_weather": get_weather,
"calculate": calculate,
}
)
工具调用成功率>95%,返回结果正确性符合预期,响应时间<300ms。
转变三:从“功能验证”到“持续监控”
传统测试通常在上线前完成。但大模型是动态演化的:
-
外部 API 会悄悄升级(OpenAI、Claude 等)
-
Prompt 会被频繁修改
-
用户的使用模式会变化
-
模型的输出分布可能发生漂移
因此,测试必须左移(在开发/微调阶段介入)且右移(持续线上监控)。
1.5 结尾总结
-
传统软件测试基于确定性系统,依赖可预测性、可复现性、可判定性三大假设。
-
大模型是非确定性概率生成模型,打破了上述所有假设。
-
传统方法(等价类、边界值、断言)在大模型测试中大面积失效,原因是无法处理语义多样性、统计波动和评估主观性。
-
大模型测试的新范式是:从验证正确性转向评估能力边界,具体包含三个转变:
-
从“断言”到“评测体系”
-
从“单点测试”到“统计测试”
-
从“功能验证”到“持续监控”
-
更多推荐




所有评论(0)