【AI测试智能体】为什么传统测试方法对智能体失效?

引子

上周我在公司跑一组智能体回归测试,同一个任务跑了 30 遍,通过率 67%。

同事看了一眼说:"那这智能体到底行不行?"

我答不上来。

在传统软件测试里,"行不行"是个非黑即白的问题。同一个输入,跑 100 遍,结果应该一模一样。assert add(2, 3) <span class="wx-em-red"> 5,这个测试要么 pass,要么 fail,没有中间状态。

但智能体不是这样的。同一个任务,temperature 不同,输出的文本可能不同。同一组 30 次运行,可能出现多种不同的输出文本,但其中大部分都算"答对了"。

这不是智能体的问题。这是测试方法的问题。

我们用确定性测试的尺子,去量一个概率性的东西,量出来的数据没有决策价值。

这篇文章不讨论智能体本身,只讨论一件事:传统测试方法为什么对智能体失效,以及失效之后该怎么调整思路。

传统测试的三个假设

所有传统软件测试方法论都建立在三个前提上。这三个前提在智能体场景下全部不成立。

假设一:相同输入产生相同输出

这是测试可重复性的基础。一个 bug 能复现,说明输入和输出之间有确定的因果关系。测试工程师写用例、造数据、跑脚本,核心逻辑就是控制变量、观察输出。

智能体打破了这个假设。同样的任务描述,同一个模型,同样的 API 调用,输出可能不同。原因有三:

  1. temperature 参数:控制生成的随机性。temperature > 0 时,每次采样路径不同。
  2. 上下文窗口截断:对话历史超过窗口限制时,早期信息被丢弃。同样的任务,在第 3 轮和第 13 轮跑,上下文不同,输出不同。
  3. 外部依赖波动:工具调用(API、数据库、网页抓取)的响应时间和返回内容可能有微小差异,这些差异会进入 LLM 的下一轮推理,放大成不同的输出。

假设二:预期结果可以精确描述

传统测试用例的标准格式是:

输入 预期输出 实际输出 结果
add(2, 3) 5 5 pass

预期输出是精确的、可比较的。assert expected </span> actual,一行代码搞定。

智能体的输出不是这样的。"分析这份销售数据"------什么叫分析对了?

  • 智能体 A 输出了 3 个图表 + 一段文字总结,得 78 分
  • 智能体 B 输出了 5 个图表 + 三段文字总结,得 72 分
  • 智能体 C 只输了一段文字,但指出了关键趋势,得 85 分

三个输出格式完全不同,但质量有高低。"预期输出"无法用精确值描述,只能用评分标准来衡量。

评分代替断言之后,新问题来了:谁来评?怎么评?评的标准一致吗?这些是后面几篇要展开的内容,这里只点出问题。

假设三:缺陷可以精确复现

传统测试发现 bug 后,第一步是复现。复现不了,开发不认。

智能体的缺陷复现困难。一个任务在第 7 次运行时失败了,第 8 次用同样的参数跑,可能又成功了。不是 bug 修了,是随机性导致的波动。

这导致三个后果:

  1. 缺陷报告质量下降:无法提供稳定的复现步骤,开发无法定位根因。
  2. 回归判断失真:改了一行代码,跑测试发现通过率从 67% 变成 65%,不知道是代码改坏了还是随机波动。
  3. 根因定位靠猜:输出错误时,不知道是 Prompt 问题、工具问题、模型问题、还是上下文问题。

失效的五个环节

传统测试流程有五个核心环节。智能体场景下,每个环节都需要改造。

环节一:用例设计

传统方式:写精确的预期输出。

智能体场景:预期输出是模糊的。需要改为写"成功标准"而非"预期值"。

比如,"计算 25 * 4 + 100 / 5"这个任务:

  • 传统测试:预期输出 = "120"
  • 智能体测试:成功标准 = 输出中包含数字 120,且没有明显的计算错误

再比如,"分析销售数据生成周报":

  • 传统测试:无法写用例(输出不固定)
  • 智能体测试:成功标准 = 包含至少 3 个分析维度 + 有明确的结论 + 数据引用正确

环节二:环境控制

传统方式:固定测试环境,控制所有变量。

智能体场景:需要控制的是 LLM 相关的变量:

  • temperature:测试时建议固定,避免随机性干扰
  • seed:如果模型支持,固定随机种子提高可重复性
  • 模型版本:锁定具体版本(如 qwen-plus-0813),避免模型升级导致行为漂移
  • 工具状态:Mock 外部依赖,避免网络波动影响测试结果

环节三:执行策略

传统方式:每个用例跑一次,pass 或 fail。

智能体场景:需要多次运行,统计分布。

复制代码
单次运行 → 统计 30 次运行的成功率
单次断言 → 统计分布(P50、P90、通过率)

这不是"多跑几次"那么简单。需要定义:

  • 运行次数:30 次是经验值(中心极限定理,n≥30 时样本均值近似正态分布)
  • 通过阈值:成功率 ≥ 70% 算通过,还是 ≥ 80%?这取决于业务场景
  • 波动容忍度:P50 和 P90 的差异超过多少需要告警?

环节四:缺陷定位

传统方式:看日志、看堆栈、看输入输出差异。

智能体场景:智能体的执行过程是黑盒的。需要额外的可测性设计:

  • 结构化日志:每个阶段(规划、执行、反思、总结)输出标准化日志
  • 状态暴露:暴露当前阶段、已执行子任务、失败原因
  • 检查点机制:关键节点输出检查点,支持断点验证

这些是第 6 篇的内容,这里只提结论:不可测的系统无法自动化,智能体需要主动暴露内部状态。

环节五:回归判断

传统方式:跑测试,对比 pass/fail 数量。

智能体场景:需要对比的是分布,不是单次结果。

复制代码
旧版本:30 次运行,通过率 67%,平均 token 消耗 4200
新版本:30 次运行,通过率 65%,平均 token 消耗 4500

结论:通过率下降 2%,token 消耗增加 7%。需要判断:
1. 2% 的下降是统计显著还是随机波动?
2. 7% 的 token 增加是否在预算范围内?
3. 哪些用例从 pass 变成了 fail?

这需要版本对比工具,不是简单的 diff。这是第 15 篇的内容。

代码:温度对稳定性的影响

理论讲完了,看数据。

下面这个脚本,用同一个智能体、同一个任务、不同 temperature 各跑 30 次,统计成功率和输出一致性。

复制代码
#!/usr/bin/env python3
"""
温度对智能体稳定性的影响实验

对比 temperature=0.3/0.7/1.0 三种设置下,
同一任务跑 30 次的成功率和输出一致性。

注:CustomAgent 是你项目中的封装,实际使用时替换为你的 Agent 类。
核心逻辑:固定 temperature,多次运行,统计分布。
"""

import os
import statistics
import requests
from collections import Counter

# 你的 API Key,从环境变量读取
API_KEY = os.getenv("DASHSCOPE_API_KEY")
API_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
MODEL = "qwen-plus"

TASK = "计算 25 * 4 + 100 / 5,把结果存储到记忆中"
EXPECTED_ANSWER = "120"
N_RUNS = 30
TEMPERATURES = [0.3, 0.7, 1.0]


def call_llm(temperature: float) -> dict:
    """调用 LLM API"""
    resp = requests.post(API_URL, headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    }, json={
        "model": MODEL,
        "messages": [{"role": "user", "content": TASK}],
        "max_tokens": 2048,
        "temperature": temperature,
    }, timeout=60)
    
    if resp.status_code <span class="wx-em-red"> 200:
        result = resp.json()
        return {
            "success": True,
            "content": result["choices"][0]["message"]["content"],
            "tokens": result.get("usage", {}).get("total_tokens", 0),
        }
    return {"success": False, "error": resp.text[:200]}


def check_success(result: dict) -> bool:
    """检查任务是否成功(输出包含正确答案)"""
    if not result.get("success"):
        return False
    return EXPECTED_ANSWER in result.get("content", "")


def check_output_consistency(results: list) -> float:
    """检查输出一致性:最高频输出占总成功数的比例"""
    outputs = [r.get("content", "").strip() for r in results if r.get("success")]
    if not outputs:
        return 0.0
    counts = Counter(outputs)
    most_common_count = counts.most_common(1)[0][1]
    return most_common_count / len(outputs)


def run_experiment():
    print(f"任务: {TASK}")
    print(f"运行次数: {N_RUNS} 次/温度")
    print(f"模型: {MODEL}")
    print()

    for temp in TEMPERATURES:
        results = []
        for i in range(N_RUNS):
            result = call_llm(temp)
            results.append(result)

        # 统计
        success_count = sum(1 for r in results if check_success(r))
        success_rate = success_count / N_RUNS
        consistency = check_output_consistency(results)

        tokens = [r.get("tokens", 0) for r in results if r.get("success")]
        avg_tokens = statistics.mean(tokens) if tokens else 0

        print(f"temperature={temp}: 成功率={success_rate:.0%}, "
              f"一致性={consistency:.0%}, 平均Token={avg_tokens:.0f}")


if __name__ </span> "__main__":
    run_experiment()

数据是 2026-05-08 真实跑的,模型 qwen-plus,每个温度跑 30 次:

temperature 成功率 输出一致性 唯一输出数 平均 Token P50 Token 平均耗时
0.3 100% 50% 6 167 165 3.6s
0.7 100% 50% 7 165 165 3.7s
1.0 100% 67% 9 156 151 3.5s

几个观察:

  1. 简单任务下 temperature 影响有限:计算题对所有 temperature 都 100% 正确。temperature 的差异在更复杂的任务(如创意写作、推理)中会更明显。

  2. 输出一致性不是单调的:temperature=1.0 时一致性反而更高(67% vs 50%)。这说明一致性不仅受 temperature 影响,还和采样路径、任务类型有关。

  3. Token 消耗没有随 temperature 单调变化:temperature=1.0 时平均 token 反而更少(156 vs 167)。temperature 控制的是概率分布的平滑度,不是输出长度。这个实验说明,至少在数学计算这类确定性任务上,temperature 对 token 消耗的影响不大。至于创意写作或推理任务,需要单独验证。

  4. 耗时差异不大:3.5s vs 3.6s,在误差范围内。

这个实验说明一件事:temperature 对简单任务影响有限,但对复杂任务(推理、创意、安全)的影响需要单独评估。测试时固定 temperature 是为了保证可比性,不是因为 temperature 一定会导致"失败"。

补充说明:这个实验用的是 qwen-plus 模型,任务类型是数学计算。不同模型、不同任务类型的 temperature 敏感度可能完全不同。下一篇我们会测创意写作和推理任务,数据会更有趣。

交付物:智能体测试 vs 传统测试对比清单

下面这个清单,列出了 12 个关键差异点。每个差异点都对应一个需要改造的环节。

# 对比维度 传统软件测试 智能体测试 改造方向
1 输出确定性 相同输入 → 相同输出 相同输入 → 不同输出 从断言改为统计分布
2 预期描述 精确值(expected == actual 模糊标准(评分) 从 assert 改为评分机制
3 缺陷复现 可精确复现 概率性出现 多次运行 + 日志追踪
4 用例设计 输入 + 预期输出 输入 + 成功标准 从精确值改为条件判断
5 执行次数 1 次 ≥30 次 统计显著性
6 环境控制 固定 OS/依赖/配置 固定 temperature/seed/模型版本 控制 LLM 相关变量
7 失败判断 pass/fail 成功率/质量分 从二元判断改为连续评分
8 回归对比 diff 输出 对比分布 版本间统计检验
9 根因定位 日志 + 堆栈 结构化日志 + 检查点 可测性改造
10 性能指标 响应时间/吞吐量 延迟/Token 消耗/成功率 增加 LLM 特有指标
11 测试数据 边界值/等价类 梯度难度/对抗样本 增加模糊测试
12 报告输出 pass/fail 统计 多维度得分 + 趋势 从表格改为雷达图

温度设置建议

基于上面的实验,给出测试场景的温度设置建议:

测试阶段 建议 temperature 理由
单元测试 0.1-0.3 最大化可重复性,快速定位问题
集成测试 0.3 平衡稳定性和真实性
回归测试 0.3 版本间可比,减少随机波动干扰
探索性测试 0.7-1.0 发现边界 case,测试多样性
生产环境 按业务场景定 客服场景低温度(稳定),创意场景高温度(多样)

核心原则:测试时温度要低,生产时温度按需求定。测试的目的是发现问题,不是模拟生产。生产环境的 temperature 由业务需求决定,但测试环境必须固定,否则数据不可比。

总结

传统测试方法对智能体失效,不是"不太好使",是"根本不对"。确定性测试的尺子量不了概率性的东西。

需要改造的不是一两个环节,是从用例设计到回归判断的全链路。这篇文章列出了 12 个差异点,给出了温度设置建议。但具体怎么改造------测试数据怎么设计、评分机制怎么做、可测性怎么加------后面逐篇展开。

下一篇讲智能体测试的 6 维能力模型。单一分数没有决策价值,需要按业务场景设计权重。

相关推荐
dfdfadffa1 小时前
如何用模块化方案组织一个可扩展的前端组件库项目
jvm·数据库·python
2301_812539671 小时前
SQL中如何高效实现分组数据的批量更新_利用窗口函数与JOIN
jvm·数据库·python
RSTJ_16252 小时前
PYTHON+AI LLM DAY THREETY-NINE
开发语言·人工智能·python
2501_901200532 小时前
如何实现SQL存储过程存储过程参数标准化_统一命名规范
jvm·数据库·python
怕浪猫2 小时前
荒岛原始无工业、无电力、无设备,从零搭建最基础计算机体系
人工智能·设计模式·面试
2601_949499942 小时前
金价涨、光模块跌?不,它们之间存在更复杂的四重关联
人工智能·区块链
tanis_20772 小时前
Deepseek V4 Pro 新手极速上手指南
人工智能·语言模型
AI袋鼠帝2 小时前
阿里最强视频模型!千问App首发灰测 HappyHorse 1.0
人工智能
运气好好的2 小时前
Golang怎么用embed嵌入SQL文件_Golang如何将SQL迁移文件嵌入Go程序统一管理【技巧】
jvm·数据库·python