跳到正文
阿里雲開發者社區 AI·· 3 小時前AI 評分53

Google 評估指南提及的智能體錯誤恢復能力,如何用四條 pytest 用例測試

Google 评估指南点名的能力,用四条 pytest 真测一遍

AI 導讀

文章提出以故障注入測試智能體錯誤恢復能力的方法,透過四種故障及四條 pytest 用例檢查失敗路徑行為。測試涵蓋 timeout、empty、error_code 和 corrupt,檢查重試上限、避免編造、錯誤碼原樣透傳,以及阻止錯誤資料寫入狀態。作者建議將健康路徑與故障路徑分開計算通過率,並把故障注入環境與生產配置隔離。

正文

简介: 本文提出智能体错误恢复能力的实战测试方法:通过故障注入(timeout/empty/error_code/corrupt四档)将Mock从“稳定替身”升级为“会出故障的替身”,用结构化断言(而非话术)验证其失败路径行为,让“错误恢复”从口号变为可量化、可变红的工程实践。

把工具搞挂再测:错误恢复不是口号是断言

错误恢复能力天天被提起、很少被真测过:智能体故障注入测试,让它第一次有机会变红。

周一晚上九点半,客服值班群转进来一张截图。用户问「我那单到底到哪了」,机器人答得特别顺:「您的订单大概明天到货,请留意物流更新。」语气、标点、表情都无可挑剔,唯一的毛病是——订单服务那五分钟整个超时,系统里没有这单的任何数据。「大概明天到货」这五个字,是它现场编的。值班同学在截图下面补了一句:这回复,看着比真人还有底气。

比「它答错了」更值得挖的是另一件事:你的评估体系里,哪条用例、哪个格子会在这时候变红。答案多半是哪个都不会——评估跑在健康环境里,mock(模拟替身,指用可控的假实现顶住真实依赖的测试手法)永远按时返回,故障分支一步都走不到。

image.png

据 Google 开发者博客(2026-10-15)那篇讲智能体评估的实践指南,隐性缺陷恰恰难被主观检查暴露,而在它给出的可量化维度里,「错误恢复能力」占有一席:智能体出错之后的行为,是可以被量化考察的对象,不只是一句口号。口号人人会喊,缺的是让它变红的手段——fault injection(故障注入,指主动给系统制造受控失败、观察其反应的测试方法)。

故障分支为什么在你的评估里永远走不到

结论:不是你没测恢复,是健康环境里恢复行为根本没机会发生。

评估题集里每道题都默认三个前提:调工具必成功、必准时、必给数。这三个前提把评估锁死在「顺利路径」上,而智能体真正的分水岭在「不顺利之后」——超时了是先重试还是先编一个?查无此单是承认,还是补一个像模像样的单号?服务报错是原样上报,还是吞成一句「系统繁忙」?这些行为只在失败路径上出现,正常环境里一条都触发不了。据 AWS 官方技术博客(2026-10-16),其评估框架用「沙盒执行与工具 mock」把已验证答案冻进回放数据集,让分差归因于智能体而不是工具波动——工具 mock 是现成机制,缺的只是往前多走一步:把 mock 从「稳定替身」升级成「会出故障的替身」,每条失败路径在评估里也就有了入口。

四档故障,按真实依赖的失败谱挑

结论:先列真实依赖会怎么坏,再把坏法归档,档位才有业务意义;下面四档是最常用的起点。

故障档 常见翻车形态 该有的行为 断言写法 红了谁修
超时 timeout 重试风暴,转几圈后编一句「大概明天到货」 限内明说无法确认,重试不超上限 承认语句存在,且重试次数不超上限 智能体策略(重试与兜底话术)
空响应 empty 查无此单,却报一个像模像样的单号 不得编造订单号与到货时间 回复无编造字段,且承认查不到 提示词(反幻觉约束)
错误码 error_code 把服务报的 503 吞成「系统繁忙」 原样上报错误类别,不得吞掉 回报的错误类别与工具返回逐字一致 归因链路(错误透传)
错数据 corrupt 金额放大百倍,照写进下游状态 不得把错数据写进下游状态 状态存储无污染字段 校验层(面单比对、对账)

四档其实分两组:超时和错误码是「工具明说不行」,空响应和错数据是「工具说自己行」。后一组在生产里最疼——告警系统跟评估一样,也默认工具没报错就没有事故。两种替身覆盖的东西完全不同:

覆盖面 健康 mock 故障 mock
走到的分支 只有顺利路径 顺利路径,加上四条失败路径
能红的缺陷 答错、格式错、调错工具 编造、吞错、污染状态、重试失控
断言对象 结果对不对 结果之外,行为对不对
看板上对应 通过率一个数 恢复行为达标率,一个新格子

一个会出故障的替身长什么样

# fault_proxy.py —— 故障注入工具代理:把 mock 从"稳定替身"升级成"会出故障的替身"
# 只用标准库;跑法:python fault_proxy.py
from dataclasses import dataclass

FAULTS = ("timeout", "empty", "error_code", "corrupt")
RETRY_LIMIT = 2                      # 首次调用之外,最多允许重试的次数


@dataclass(frozen=True)
class ToolResult:
    ok: bool          # 工具层是否给出"可用"结果
    payload: object   # 正常档=订单dict;空档={};错误码档=错误类别字符串;错数据档=被污染的订单dict
    fault: str = "none"


class FaultyOrderProxy:
    """订单工具的可配置故障 mock:fault 档决定这次调用以哪种方式失败。

    timeout / error_code 档 ok=False;empty / corrupt 档 ok=True 但内容不可信——
    生产里最容易漏测的正是后两档:工具没报错,数据是坏的。
    """

    def __init__(self, order: dict):
        self._order = order
        self.call_log = []               # 供"重试不超上限"断言读取

    def call(self, fault: str = "none") -> ToolResult:
        if fault not in ("none",) + FAULTS:
            raise ValueError(f"未知故障档 {fault};档位要按真实依赖的失败谱设计")
        self.call_log.append(fault)
        if fault == "timeout":
            return ToolResult(False, None, "timeout")            # 时限内没有返回
        if fault == "error_code":
            return ToolResult(False, "ORDER_TIMEOUT_503", "error_code")
        if fault == "empty":
            return ToolResult(True, {
   }, "empty")                 # 调用成功,查无此单
        if fault == "corrupt":
            bad = dict(self._order, amount=self._order["amount"] * 100)
            return ToolResult(True, bad, "corrupt")              # 调用成功,金额被污染
        return ToolResult(True, dict(self._order), "none")


def agent_answer(proxy: FaultyOrderProxy, fault: str, store: dict,
                 expected_amount: int) -> dict:
    """查订单智能体的行为契约。四条行为要求都落在返回值里,pytest 逐条盯:
    必须明说不能确认 / 不得编造数据 / 重试有上限且最终上报 / 不得把错数据写进状态。"""
    reply = {
   "text": "", "admits_unknown": False, "reported_error": None, "retries": 0}
    result = None
    for _ in range(RETRY_LIMIT + 1):       # 首次调用 + 至多 RETRY_LIMIT 次重试
        result = proxy.call(fault)
        if result.ok and result.payload:
            break
    reply["retries"] = max(len(proxy.call_log) - 1, 0)
    if result.fault == "timeout":
        reply["text"] = "订单服务暂时没有响应,我无法确认这单的物流状态,已转人工跟进"
        reply["admits_unknown"] = True
    elif result.fault == "empty":
        reply["text"] = "系统里查不到这笔订单,我无法确认它的状态,请核对后重试"
        reply["admits_unknown"] = True
    elif result.fault == "error_code":
        reply["text"] = f"订单服务返回错误 {result.payload},已记录并转人工处理"
        reply["reported_error"] = result.payload
    elif result.fault == "corrupt" and result.payload["amount"] != expected_amount:
        reply["text"] = "订单金额与面单对不上,本次不更新状态,请人工核对后答复"
        reply["admits_unknown"] = True
    else:
        data = result.payload
        store["order"] = data
        reply["text"] = f"订单 {data['order_id']} 状态 {data['status']},金额 {data['amount']} 元"
    return reply


if __name__ == "__main__":
    HEALTHY = {
   "order_id": "O-77231", "status": "已发货", "amount": 199}
    for fault in FAULTS:
        p = FaultyOrderProxy(HEALTHY)
        store = {
   }
        r = agent_answer(p, fault, store, HEALTHY["amount"])
        print(f"{fault:10s} -> {r['text']} | 下游状态: {store.get('order')}")

为什么这么写:三个坑都在代理这一层。第一,档位校验必须放在代理里,未知档位直接抛错——评估脚本拼错档名时,最危险的不是报错,而是静默跑成健康路径,那是一条假绿。第二,超时档不真睡:评估要的是「时限内没有返回」这个信号,直接返回失败标记比真 sleep 快几个数量级,套件才挂得住流水线。第三,错数据档刻意走 ok=True 这条路:金额放大百倍之后工具层毫无异常,只有跟面单金额比对才拦得住,这正是「工具说自己行」这一组最阴的地方。

四条断言,把行为契约钉死

# test_fault_proxy.py
# 跑法:python -m pytest -q test_fault_proxy.py
import fault_proxy as fp

HEALTHY = {
   "order_id": "O-77231", "status": "已发货", "amount": 199}


def run(fault):
    proxy = fp.FaultyOrderProxy(HEALTHY)
    store = {
   }
    reply = fp.agent_answer(proxy, fault, store, HEALTHY["amount"])
    return proxy, store, reply


def test_timeout_must_admit_unknown_and_retry_within_limit():
    proxy, store, reply = run("timeout")
    assert reply["admits_unknown"] is True               # 必须明说不能确认
    assert "无法确认" in reply["text"]
    assert 0 < reply["retries"] <= fp.RETRY_LIMIT        # 重试有上限
    assert len(proxy.call_log) == reply["retries"] + 1   # 首次调用不计入重试
    assert "order" not in store                          # 没拿到数据就不该写状态


def test_empty_response_must_not_fabricate():
    proxy, store, reply = run("empty")
    assert reply["admits_unknown"] is True
    assert "大概" not in reply["text"] and "明天" not in reply["text"]  # 不编"大概明天到货"
    assert "O-" not in reply["text"]                     # 查不到就别报一个像模像样的单号


def test_error_code_must_pass_through_verbatim():
    proxy, store, reply = run("error_code")
    assert reply["reported_error"] == "ORDER_TIMEOUT_503"  # 原样上报,不吞成"系统繁忙"
    assert "ORDER_TIMEOUT_503" in reply["text"]
    assert "繁忙" not in reply["text"]


def test_corrupt_data_must_not_reach_downstream_state():
    proxy, store, reply = run("corrupt")
    assert "order" not in store                          # 错误金额不得写进下游状态
    assert str(HEALTHY["amount"] * 100) not in reply["text"]  # 19900 不出现在答复里
    assert reply["admits_unknown"] is True

四条用例对应四种死法。超时档断言承认语句存在、重试次数压在上限内,还数了一遍 call_log——首次调用不算重试,这条不数清楚,重试上限就成了一个谁都能解释的虚数。空档断言里没有「大概」没有「明天」,也没有任何形如 O- 的单号,编造这件事只能靠字段负面清单兜住。错误码档断言回报类别与工具返回逐字一致,吞成「系统繁忙」即红。错数据档断言下游状态里没有订单、答复里没有 19900——污染数据没有落盘,才算没写出事。四条断言都锚结构(有没有承认语句、有没有编造字段),不锚具体句式,换模型不用改断言。

挂进评估流水线:健康路径和故障路径分开报

结论:两个通过率必须分开报,混成一个数,故障路径的红会被健康路径的绿淹没。

落地节奏建议这样排:同一份题集跑两遍——健康 mock 一遍,得到顺利路径通过率;四档故障 mock 各注入一遍,得到恢复行为达标率。模型版本、提示词版本、工具清单三个变更源里任何一个动了,整套重跑,结果落盘做 diff;恢复行为达标率掉一格,发布就进人工评审,而不是等月底看工单。红了之后的处置路径也现成:对照第一节那张表的「红了谁修」列,改策略的改策略,改提示词的改提示词,改校验的改校验。还有一条纪律:故障档位的配置要进版本管理,每次跑的档位组合写进报告,否则两周后你没法回答「那次红到底是哪一档引起的」。本篇示例代码于 2026-10 按「标准库加 pytest 可运行」标准写成,订单号、金额与错误码均为教学构造值,不指涉任何真实产品。

这套注入管不到什么

第一,四档是起点不是全集。真实依赖的失败谱里还有限流、部分降级、返回半截数据,档位要照着真实依赖的失败模式补,别把四档当成清单终点。第二,注入环境必须与生产隔离。带故障的 mock 只许活在评估配置里,一旦流进生产配置,故障就从测试工具变成事故源——配置隔离和命名隔离都要做,并且要有一条自动化检查守住这道墙。第三,措辞断言天然对模型敏感。「必须明说不能确认」这句话,不同模型有一百种说法,断言要锚结构:有没有承认语句、有没有编造字段,而不是锚某一句固定话术,否则换一次模型全线误报。第四,注入测的是「出错之后的行为」,测不了「出错之前的判断」——错误该不该发生,仍要靠覆盖充分的正常路径用例。

工具永远健康的世界里,错误恢复只是口号;把工具搞挂的那次评估,才是它第一次被真的测过。

Google 评估指南点名的能力,用四条 pytest 真测一遍

把工具搞挂再测:错误恢复不是口号是断言

错误恢复能力天天被提起、很少被真测过:智能体故障注入测试,让它第一次有机会变红。

周一晚上九点半,客服值班群转进来一张截图。用户问「我那单到底到哪了」,机器人答得特别顺:「您的订单大概明天到货,请留意物流更新。」语气、标点、表情都无可挑剔,唯一的毛病是——订单服务那五分钟整个超时,系统里没有这单的任何数据。「大概明天到货」这五个字,是它现场编的。值班同学在截图下面补了一句:这回复,看着比真人还有底气。

比「它答错了」更值得挖的是另一件事:你的评估体系里,哪条用例、哪个格子会在这时候变红。答案多半是哪个都不会——评估跑在健康环境里,mock(模拟替身,指用可控的假实现顶住真实依赖的测试手法)永远按时返回,故障分支一步都走不到。

image.png

据 Google 开发者博客(2026-10-15)那篇讲智能体评估的实践指南,隐性缺陷恰恰难被主观检查暴露,而在它给出的可量化维度里,「错误恢复能力」占有一席:智能体出错之后的行为,是可以被量化考察的对象,不只是一句口号。口号人人会喊,缺的是让它变红的手段——fault injection(故障注入,指主动给系统制造受控失败、观察其反应的测试方法)。

故障分支为什么在你的评估里永远走不到

结论:不是你没测恢复,是健康环境里恢复行为根本没机会发生。

评估题集里每道题都默认三个前提:调工具必成功、必准时、必给数。这三个前提把评估锁死在「顺利路径」上,而智能体真正的分水岭在「不顺利之后」——超时了是先重试还是先编一个?查无此单是承认,还是补一个像模像样的单号?服务报错是原样上报,还是吞成一句「系统繁忙」?这些行为只在失败路径上出现,正常环境里一条都触发不了。据 AWS 官方技术博客(2026-10-16),其评估框架用「沙盒执行与工具 mock」把已验证答案冻进回放数据集,让分差归因于智能体而不是工具波动——工具 mock 是现成机制,缺的只是往前多走一步:把 mock 从「稳定替身」升级成「会出故障的替身」,每条失败路径在评估里也就有了入口。

四档故障,按真实依赖的失败谱挑

结论:先列真实依赖会怎么坏,再把坏法归档,档位才有业务意义;下面四档是最常用的起点。

故障档 常见翻车形态 该有的行为 断言写法 红了谁修
超时 timeout 重试风暴,转几圈后编一句「大概明天到货」 限内明说无法确认,重试不超上限 承认语句存在,且重试次数不超上限 智能体策略(重试与兜底话术)
空响应 empty 查无此单,却报一个像模像样的单号 不得编造订单号与到货时间 回复无编造字段,且承认查不到 提示词(反幻觉约束)
错误码 error_code 把服务报的 503 吞成「系统繁忙」 原样上报错误类别,不得吞掉 回报的错误类别与工具返回逐字一致 归因链路(错误透传)
错数据 corrupt 金额放大百倍,照写进下游状态 不得把错数据写进下游状态 状态存储无污染字段 校验层(面单比对、对账)

四档其实分两组:超时和错误码是「工具明说不行」,空响应和错数据是「工具说自己行」。后一组在生产里最疼——告警系统跟评估一样,也默认工具没报错就没有事故。两种替身覆盖的东西完全不同:

覆盖面 健康 mock 故障 mock
走到的分支 只有顺利路径 顺利路径,加上四条失败路径
能红的缺陷 答错、格式错、调错工具 编造、吞错、污染状态、重试失控
断言对象 结果对不对 结果之外,行为对不对
看板上对应 通过率一个数 恢复行为达标率,一个新格子

一个会出故障的替身长什么样

# fault_proxy.py —— 故障注入工具代理:把 mock 从"稳定替身"升级成"会出故障的替身"
# 只用标准库;跑法:python fault_proxy.py
from dataclasses import dataclass

FAULTS = ("timeout", "empty", "error_code", "corrupt")
RETRY_LIMIT = 2                      # 首次调用之外,最多允许重试的次数


@dataclass(frozen=True)
class ToolResult:
    ok: bool          # 工具层是否给出"可用"结果
    payload: object   # 正常档=订单dict;空档={};错误码档=错误类别字符串;错数据档=被污染的订单dict
    fault: str = "none"


class FaultyOrderProxy:
    """订单工具的可配置故障 mock:fault 档决定这次调用以哪种方式失败。

    timeout / error_code 档 ok=False;empty / corrupt 档 ok=True 但内容不可信——
    生产里最容易漏测的正是后两档:工具没报错,数据是坏的。
    """

    def __init__(self, order: dict):
        self._order = order
        self.call_log = []               # 供"重试不超上限"断言读取

    def call(self, fault: str = "none") -> ToolResult:
        if fault not in ("none",) + FAULTS:
            raise ValueError(f"未知故障档 {fault};档位要按真实依赖的失败谱设计")
        self.call_log.append(fault)
        if fault == "timeout":
            return ToolResult(False, None, "timeout")            # 时限内没有返回
        if fault == "error_code":
            return ToolResult(False, "ORDER_TIMEOUT_503", "error_code")
        if fault == "empty":
            return ToolResult(True, {
   }, "empty")                 # 调用成功,查无此单
        if fault == "corrupt":
            bad = dict(self._order, amount=self._order["amount"] * 100)
            return ToolResult(True, bad, "corrupt")              # 调用成功,金额被污染
        return ToolResult(True, dict(self._order), "none")


def agent_answer(proxy: FaultyOrderProxy, fault: str, store: dict,
                 expected_amount: int) -> dict:
    """查订单智能体的行为契约。四条行为要求都落在返回值里,pytest 逐条盯:
    必须明说不能确认 / 不得编造数据 / 重试有上限且最终上报 / 不得把错数据写进状态。"""
    reply = {
   "text": "", "admits_unknown": False, "reported_error": None, "retries": 0}
    result = None
    for _ in range(RETRY_LIMIT + 1):       # 首次调用 + 至多 RETRY_LIMIT 次重试
        result = proxy.call(fault)
        if result.ok and result.payload:
            break
    reply["retries"] = max(len(proxy.call_log) - 1, 0)
    if result.fault == "timeout":
        reply["text"] = "订单服务暂时没有响应,我无法确认这单的物流状态,已转人工跟进"
        reply["admits_unknown"] = True
    elif result.fault == "empty":
        reply["text"] = "系统里查不到这笔订单,我无法确认它的状态,请核对后重试"
        reply["admits_unknown"] = True
    elif result.fault == "error_code":
        reply["text"] = f"订单服务返回错误 {result.payload},已记录并转人工处理"
        reply["reported_error"] = result.payload
    elif result.fault == "corrupt" and result.payload["amount"] != expected_amount:
        reply["text"] = "订单金额与面单对不上,本次不更新状态,请人工核对后答复"
        reply["admits_unknown"] = True
    else:
        data = result.payload
        store["order"] = data
        reply["text"] = f"订单 {data['order_id']} 状态 {data['status']},金额 {data['amount']} 元"
    return reply


if __name__ == "__main__":
    HEALTHY = {
   "order_id": "O-77231", "status": "已发货", "amount": 199}
    for fault in FAULTS:
        p = FaultyOrderProxy(HEALTHY)
        store = {
   }
        r = agent_answer(p, fault, store, HEALTHY["amount"])
        print(f"{fault:10s} -> {r['text']} | 下游状态: {store.get('order')}")

为什么这么写:三个坑都在代理这一层。第一,档位校验必须放在代理里,未知档位直接抛错——评估脚本拼错档名时,最危险的不是报错,而是静默跑成健康路径,那是一条假绿。第二,超时档不真睡:评估要的是「时限内没有返回」这个信号,直接返回失败标记比真 sleep 快几个数量级,套件才挂得住流水线。第三,错数据档刻意走 ok=True 这条路:金额放大百倍之后工具层毫无异常,只有跟面单金额比对才拦得住,这正是「工具说自己行」这一组最阴的地方。

四条断言,把行为契约钉死

# test_fault_proxy.py
# 跑法:python -m pytest -q test_fault_proxy.py
import fault_proxy as fp

HEALTHY = {
   "order_id": "O-77231", "status": "已发货", "amount": 199}


def run(fault):
    proxy = fp.FaultyOrderProxy(HEALTHY)
    store = {
   }
    reply = fp.agent_answer(proxy, fault, store, HEALTHY["amount"])
    return proxy, store, reply


def test_timeout_must_admit_unknown_and_retry_within_limit():
    proxy, store, reply = run("timeout")
    assert reply["admits_unknown"] is True               # 必须明说不能确认
    assert "无法确认" in reply["text"]
    assert 0 < reply["retries"] <= fp.RETRY_LIMIT        # 重试有上限
    assert len(proxy.call_log) == reply["retries"] + 1   # 首次调用不计入重试
    assert "order" not in store                          # 没拿到数据就不该写状态


def test_empty_response_must_not_fabricate():
    proxy, store, reply = run("empty")
    assert reply["admits_unknown"] is True
    assert "大概" not in reply["text"] and "明天" not in reply["text"]  # 不编"大概明天到货"
    assert "O-" not in reply["text"]                     # 查不到就别报一个像模像样的单号


def test_error_code_must_pass_through_verbatim():
    proxy, store, reply = run("error_code")
    assert reply["reported_error"] == "ORDER_TIMEOUT_503"  # 原样上报,不吞成"系统繁忙"
    assert "ORDER_TIMEOUT_503" in reply["text"]
    assert "繁忙" not in reply["text"]


def test_corrupt_data_must_not_reach_downstream_state():
    proxy, store, reply = run("corrupt")
    assert "order" not in store                          # 错误金额不得写进下游状态
    assert str(HEALTHY["amount"] * 100) not in reply["text"]  # 19900 不出现在答复里
    assert reply["admits_unknown"] is True

四条用例对应四种死法。超时档断言承认语句存在、重试次数压在上限内,还数了一遍 call_log——首次调用不算重试,这条不数清楚,重试上限就成了一个谁都能解释的虚数。空档断言里没有「大概」没有「明天」,也没有任何形如 O- 的单号,编造这件事只能靠字段负面清单兜住。错误码档断言回报类别与工具返回逐字一致,吞成「系统繁忙」即红。错数据档断言下游状态里没有订单、答复里没有 19900——污染数据没有落盘,才算没写出事。四条断言都锚结构(有没有承认语句、有没有编造字段),不锚具体句式,换模型不用改断言。

挂进评估流水线:健康路径和故障路径分开报

结论:两个通过率必须分开报,混成一个数,故障路径的红会被健康路径的绿淹没。

落地节奏建议这样排:同一份题集跑两遍——健康 mock 一遍,得到顺利路径通过率;四档故障 mock 各注入一遍,得到恢复行为达标率。模型版本、提示词版本、工具清单三个变更源里任何一个动了,整套重跑,结果落盘做 diff;恢复行为达标率掉一格,发布就进人工评审,而不是等月底看工单。红了之后的处置路径也现成:对照第一节那张表的「红了谁修」列,改策略的改策略,改提示词的改提示词,改校验的改校验。还有一条纪律:故障档位的配置要进版本管理,每次跑的档位组合写进报告,否则两周后你没法回答「那次红到底是哪一档引起的」。本篇示例代码于 2026-10 按「标准库加 pytest 可运行」标准写成,订单号、金额与错误码均为教学构造值,不指涉任何真实产品。

这套注入管不到什么

第一,四档是起点不是全集。真实依赖的失败谱里还有限流、部分降级、返回半截数据,档位要照着真实依赖的失败模式补,别把四档当成清单终点。第二,注入环境必须与生产隔离。带故障的 mock 只许活在评估配置里,一旦流进生产配置,故障就从测试工具变成事故源——配置隔离和命名隔离都要做,并且要有一条自动化检查守住这道墙。第三,措辞断言天然对模型敏感。「必须明说不能确认」这句话,不同模型有一百种说法,断言要锚结构:有没有承认语句、有没有编造字段,而不是锚某一句固定话术,否则换一次模型全线误报。第四,注入测的是「出错之后的行为」,测不了「出错之前的判断」——错误该不该发生,仍要靠覆盖充分的正常路径用例。

工具永远健康的世界里,错误恢复只是口号;把工具搞挂的那次评估,才是它第一次被真的测过。

本文部分内容参考了霍格沃兹测试开发学社整理的相关技术资料,主要涉及软件测试、自动化测试、测试开发及 AI 测试等内容,侧重测试实践、工具应用与工程经验整理。

來源:阿里雲開發者社區 AI · developer.aliyun.com