↓ 跳过正文
  1. Posts/

为什么模型准确率达到 99.9%,AI Agent 仍然可能不安全?

·6928 字·14 分钟

起因
#

过去几篇笔记一直在 Lecture 6 的范围里打转。Distribution Shift 那篇让我意识到离线测试集的 98% 准确率没法平移到生产环境,Algorithmic Bias 那篇又告诉我总体准确率可以掩盖群体间的巨大差异,对抗攻击那篇则让我看到泛化好的模型仍然可以被微小扰动骗过。

这三件事都指向同一个结论:模型在离线评测上拿高分,不等于它在真实世界里可靠。

但当我继续看 MIT 6.S191 的 Lecture 7(The Three Laws of AI,主讲人 Douglas Blank)时,发现课程提出了一个比"模型可靠性"更大的问题——

当模型不再只是返回一个预测值,而是被嵌入一个 Agent 系统、拥有了调用工具甚至修改生产数据的能力时,我们应该怎么评估它、观测它、约束它?

这跟过去几篇讨论的问题层级不同。以前我关心的是"模型输出的预测结果对不对",现在的问题变成了"模型驱动的 Agent 做出的决策和行动,是否安全"。

做 ML Infra 这些年,我对系统指标很熟悉。P99 延迟、QPS、可用性、数值一致性——这些是我日常盯的东西。但 Lecture 7 让我停下来想了想:一个 Agent 可以同时满足以下所有条件——

  • HTTP 返回 200
  • API 成功率 100%
  • P99 延迟正常
  • Trace 完整无异常
  • 没有任何 Exception

但它给用户生成的财务报告里,把一个关键数字搞错了。

API Success 不等于 Task Success。

更进一步,哪怕模型在离线测试集上达到了 99.9% 的正确率,这个数字也不能直接回答"这个 Agent 上线后是否安全"。

做一个简单的思想实验。假设一个财报分析 Agent 在 10,000 次测试任务中,正确完成了 9,990 次,错了 10 次。99.9% 看起来很高。但这 10 次错误可能只是把报告标题的日期格式弄错了,也可能是在没有 WHERE 条件的情况下对生产数据库执行了 UPDATE。这两种错误的后果差了几个数量级。

(以上是为了说明问题构造的假设场景,不是实际生产事故。)

这篇文章想把我在 Lecture 7 中形成的几个认识记下来。课程围绕三个核心能力展开讨论——Evaluation(评测)、Observability(可观测性)和 Agent Safety(Agent 安全性)。我会沿着这三条线走,同时把自己从 ML Infra 角度的延伸思考穿插进去。

LLM 的"正确"怎么衡量
#

过去做传统 ML 的时候,Evaluation 这件事相对直接。分类任务看 Accuracy / Precision / Recall / F1,回归任务看 MSE / MAE,排序任务看 AUC / NDCG。指标选好、测试集留好、跑一遍就出数字。

到了 LLM Agent,情况变复杂了。

还是拿那个财报分析 Agent 举例。假设用户要求它"提取某公司 2025 年 Q3 财报中的营收数据,生成一段分析摘要"。这个任务至少包含几个不同性质的子问题:

  1. 营收金额是否正确提取?(120.5 亿元,不是 120.5 万元)
  2. 货币单位是否正确?(人民币,不是美元)
  3. 财报时间范围是否对应 2025 Q3?(不是 Q2)
  4. 生成的分析摘要是否准确反映了数据含义?
  5. 如果 Agent 有数据库写入权限,它写入的数据是否与提取结果一致?

前三个子问题有明确的正确答案,可以用确定性的程序规则去核查——拿 Agent 的输出跟原始财报做字段级比对就行。第四个问题是开放式的自然语言评价,没有标准答案可供精确匹配。第五个涉及操作正确性,需要单独验证。

MIT 6.S191 Lecture 7 在讲 Evaluation 时提出了一个框架:围绕 Evaluation Dataset(评测数据集)、Metric(评测指标)和 Experiment(评测实验)来组织离线评测流程。这个框架本身不复杂,但它提醒了我一件事——不同类型的子任务不应该用同一把尺子去量。

对于有确定答案的子任务(金额、单位、日期),最可靠的做法是写确定性的校验逻辑。LLM 在这里的角色是信息提取,校验不需要也不应该依赖另一个 LLM。

对于开放式的文本质量评价,业界目前常用的方案是 LLM-as-a-Judge——让另一个 LLM 按照预定义的评分标准对输出打分。Lecture 7 也提到了这种方法。它在实践中确实有用,尤其是在人工标注成本很高的时候。但我觉得需要对它保持清醒:另一个 LLM 的判断不是绝对真值。 它本身也可能出错,也可能有偏见,也可能在某些边界情况下给出不一致的评分。用 LLM 评价 LLM,相当于引入了一个新的不确定性来源。在高风险场景下,人工抽检仍然不可替代。

对于涉及权限和操作正确性的子任务,评测手段又不一样了——这更接近传统安全测试的思路,需要独立的规则验证和权限审计,后面 Agent Safety 那节会展开。

我从这里带走的一个认识是:对 LLM Agent 做 Evaluation,不能只报一个总体正确率。 不同类型的子任务需要不同的评测手段,而且这些评测手段的可信度本身也不一样。

输出错了,怎么知道错在哪里
#

Evaluation 回答的是"结果对不对",但即使我们知道结果错了,还需要知道"错在哪里"。

继续用那个财报分析 Agent 的例子。假设整个工作流是这样的:

  1. Planning:LLM 分解用户请求,决定需要哪些步骤
  2. Search:调用搜索工具查找目标财报文档
  3. Extract:从文档中提取营收数据
  4. Generate:基于提取结果生成分析摘要
  5. Write:将结果写入报告系统(假设有授权)

最终输出的报告里,营收数字是"120.5 万元",但原始财报中的数字是"120.5 亿元"。

财报分析 Agent 的 Trace 示意

如果没有任何中间过程的记录,我只能看到最终结果是错的,但不知道错误发生在哪一步。是 Search 找到了错误的文档?是 Extract 在解析数字时把"亿"读成了"万"?还是 Generate 在重新表述时搞混了单位?

MIT 6.S191 Lecture 7 花了相当篇幅讲 LLM Observability,核心概念是 Trace 和 Span。一个 Trace 对应一次完整的 Agent 执行过程,由多个 Span 组成,每个 Span 记录一个步骤的输入、输出、调用的工具、耗时等信息。

有了 Trace,上面那个问题就可以追查了。回溯每个 Span 的输入输出:如果 Search Span 返回了正确的文档,Extract Span 的输入也是正确的文档,但 Extract Span 的输出变成了"120.5 万元"——问题就定位到了 Extract 这一步。

这跟做后端服务的分布式追踪思路一脉相承。但有一个区别需要注意。

传统微服务的 Trace 记录的是确定性的函数调用链——输入什么、调了哪个下游服务、返回什么。每个节点的行为是可预测的。但在 LLM Agent 的 Trace 里,LLM 本身的推理过程是一个黑盒。Trace 能记录 LLM 的输入 Prompt 和输出文本,但不能解释模型内部为什么做出了这个决策。

换句话说,Observability 提供的是执行过程的诊断证据,不是模型决策机制的完整解释。 这跟之前聊可解释性时讨论的 Interpretability 是两个层面的事情。Trace 告诉我"Extract 步骤输出了错误的数字",但不能告诉我"模型为什么把亿读成了万"。后者可能需要 SHAP、attention 分析等可解释性方法,也可能根本说不清楚。

不过在工程实践中,Trace 提供的信息通常已经足够定位大部分问题了。知道哪个步骤出错,就可以针对性地修改 Prompt、更换工具、或者加入校验逻辑。

修一次 Bug 还不够
#

定位到问题之后呢?

最直接的反应是修 Prompt。比如在 Extract 步骤的 Prompt 里加一条规则:“提取金额时必须同时保留数值和单位(亿/万/千),不得擅自转换。”

改完之后跑一遍,发现这个 case 过了。修完收工?

我一开始也觉得可以。但 Lecture 7 接下来讲的一个思路让我意识到这样做远远不够。

假设一个月后,模型从 v1 升级到 v2。v2 在总体评测上表现更好,各项指标都有提升。于是我们把新模型部署上去。结果——那个"亿变万"的老 Bug 又出现了。

为什么?因为 v2 是一个全新的模型,它没有见过我们当时针对 v1 调的那条 Prompt 规则所"修复"的行为模式。或者更准确地说,v2 的参数完全不同,同一条 Prompt 对不同模型的约束效果也不同。

这件事的本质跟传统软件工程里的 Regression Test(回归测试)是一回事:修复一个 Bug 之后,必须把这个 Bug 变成一个持久的测试用例,确保未来的每次变更都不会让它复现。

从生产失败到回归测试的闭环

Lecture 7 把这个思路叫作持续记录失败案例、扩充测试集并在未来模型版本发布前进行回归评测。我觉得这跟传统软件的 regression suite 在精神上完全相通,只不过 LLM 场景有几个额外的麻烦:

第一,不能只保存导致失败的那一个样本。 那个"亿变万"的 case 可能只是数字单位错误的一种表现形式。还有"千变百"、“美元变人民币”、“季度错位"等等。一个真正有用的回归测试集,需要围绕同一类失败模式补充多种边界条件。

第二,新模型总体准确率提高,不代表可以容忍关键场景退化。 假设 v2 在 1,000 个测试样本上的总体正确率从 98.5% 提升到 99.9%,但在我们标记为"关键安全场景"的 50 个样本上,通过率从 100% 降到了 96%。这种退化应该被 Release Gate 拦住。总体指标和关键场景指标不能简单地加权平均。

第三,反复针对同一组测试样本调 Prompt,可能导致评测集过拟合。 这跟训练数据的过拟合在概念上是类似的——如果你不断调整 Prompt 直到某一组固定的 case 全部通过,你并没有真正提升模型的能力,只是让它在这组特定输入上表现更好。因此需要保留一个独立的验证集,用来评估 Prompt 调整后的真实泛化效果。

从这里我形成的一个认识是:生产中发现的失败案例不只是 Bug,更应该成为长期积累的测试资产。 每修一次错,测试集就应该增长一点。这个闭环——生产失败 → Trace 分析 → 根因定位 → 扩充回归数据集 → 新版本发布前回归评测 → 上线后继续监控——才是一个可持续的质量保障机制。

模型没换,行为为什么会变
#

上面讨论的 Regression Test 场景是模型版本更新引起的问题。但 Lecture 7 还提到了一个更微妙的情况:模型权重完全没有变化,行为却发生了变化。

课件里把这种现象叫 Safety Drift。

这件事乍一看有点反直觉。模型参数 \(\theta\) 固定了,同一个输入不应该给出同一个输出吗?

但 LLM 是自回归模型。每一步生成的概率分布取决于当前的 context:

$$ P_\theta(\text{next token} \mid \text{context}) $$

在单轮对话中,context 基本就是 System Prompt + 用户输入,变化不大。但在多轮对话中,context 会随着对话历史不断增长和演化。前面 10 轮对话的内容会成为第 11 轮的 context 的一部分。

\(\theta\) 没变,但 context 变了,所以条件概率分布也变了。

这意味着一个 Agent 在第 1 轮对话中严格遵守安全规则(比如拒绝执行未授权的数据库写入),到了第 20 轮对话时,由于 context 的累积变化,可能会表现出不同的行为倾向。

这跟Distribution Shift 那篇讨论的问题有一定关联——在 Distribution Shift 中,是外部环境的数据分布发生了变化;在 Safety Drift 中,是模型自身对话过程中 context 的"分布"发生了变化。但两者不完全相同。Distribution Shift 通常讨论的是训练分布与部署分布之间的差异,而 Safety Drift 描述的是同一次部署内、同一个会话内的行为漂移。

需要说明的是,这不意味着安全违规的概率一定会随着对话轮数增加而单调上升。实际行为取决于具体的对话内容和 context 构成。但这提醒了一件事:单轮对话测试通过,不能保证多轮对话下行为始终一致。

一个直接的工程含义是:如果要评测 Agent 的安全行为,不能只做单轮测试。需要设计多轮、长对话的测试场景,检查安全约束在对话演进过程中是否保持稳定。

为什么 Prompt 不能充当安全边界
#

这是我在 Lecture 7 中想得最多的部分。

假设我们有一个具有生产数据库写入权限的 Agent,System Prompt 里明确写了:“禁止执行任何不带 WHERE 条件的 UPDATE 或 DELETE 语句。”

现在模型生成了这样一条 SQL:

1UPDATE financial_reports SET status = 'reviewed'

没有 WHERE 条件。如果直接执行,整张表的所有记录都会被修改。

System Prompt 说了不允许这么做,但模型还是生成了。这里有一个我在学习中形成的很明确的认识:

System Prompt 更多是在表达对模型行为的期望,而不是提供系统层面的强制保证。

通俗点说,只依赖 Prompt 来防止危险操作,有点像在"许愿”。

但我得补充一点,免得这个说法被误读:Prompt 不是完全没用的。在大多数正常情况下,一条写得好的 System Prompt 确实能有效引导模型行为。问题在于它不能作为安全边界——在那些最关键的、后果最严重的场景下,它没有强制执行的能力。模型可能因为 context 变化、输入边界情况、或者能力局限,绕过 Prompt 中的指示。

那换一种方案:让另一个 LLM 来审核第一个 LLM 生成的 SQL,判断它是否安全?

这比纯 Prompt 约束多了一层,但本质上仍然引入了另一个不确定性来源。第二个 LLM 也可能判断错误。在"是否执行一条可能影响整个数据库的 SQL"这种决策上,“大概率安全"跟"确定安全"之间的差距可能是灾难性的。

Agent 操作的独立授权边界

Lecture 7 在讨论 Agent 安全性时,强调了部署透明性和安全约束的重要性。从工程角度延伸,我觉得核心原则可以归纳为一句话:模型的判断与系统的授权必须分离。

具体来说,几个必要的工程措施:

  • 最小权限(Least Privilege):Agent 只应该拥有完成任务所必需的最小权限集。一个做财报分析的 Agent 不需要 DROP TABLE 权限。
  • 工具白名单(Tool Allowlist):Agent 能调用哪些工具、每个工具接受哪些参数范围,应该在系统层面定义和强制执行,而不是靠 Prompt 约束。
  • 参数校验:模型生成的 SQL 在执行前必须经过独立的语法和安全规则检查——比如检测是否缺少 WHERE 条件、是否包含 DDL 语句、影响行数是否超过阈值。
  • 操作影响范围限制:即使 SQL 语法合法,也应该限制单次操作影响的最大行数或数据范围。
  • Human Approval(人工审批):高风险操作在执行前需要人工确认。
  • 审计记录:所有工具调用和数据变更都应该有完整的审计日志。

这里需要区分两种不同的场景。第一种是模型尝试执行危险操作,但被授权层拦截了——这是模型行为问题,授权机制正常工作。第二种是危险操作绕过了所有检查并成功执行——这不仅是模型行为问题,还暴露了系统安全边界本身的缺陷。

在第一种场景下,我们需要改进模型或 Prompt,减少危险操作的生成频率。在第二种场景下,需要先修补授权机制的漏洞,因为无论模型多好,系统层面的防线不能有缺口。

这也是为什么我觉得简单的字符串检测(比如正则匹配 SQL 关键词)或者让 LLM 做自我评估,不应该被当作可靠的生产授权机制。它们可以作为辅助手段,但不能替代数据库层面的权限控制、事务隔离和操作审批流程。

三种能力怎么组织到一起
#

回到文章开头的问题:模型准确率 99.9%,为什么 Agent 仍然可能不安全?

现在可以更完整地回答了。准确率衡量的是模型在特定测试集上的正确率,但它没有告诉我们:

  • 模型出错时,错误的后果有多严重(不同错误不能等价计量)
  • 模型执行过程中哪个环节出了问题(没有可观测性就无法诊断)
  • 模型的错误决策是否会直接导致不可逆的生产操作(没有独立授权层就没有安全兜底)

Lecture 7 提出的三种能力——Evaluation、Observability、Agent Safety——分别回应这三个问题:

能力回答的核心问题
Evaluation做得对不对?
Observability做了什么、错在哪里?
Agent Safety出错后能否限制后果?

再加上前面讨论的 Failure-driven Evaluation 闭环,这三种能力不是孤立的,它们形成一个持续改进的循环:Evaluation 发现错误 → Observability 定位根因 → 修复并扩充回归测试集 → Agent Safety 确保在修复生效之前,错误不会造成严重后果 → 新版本通过回归评测后上线 → 继续监控。

如果要给一个 LLM Agent 做上线前的检查,我觉得至少需要问自己这几个问题:

  1. 有没有可重复执行的质量评测,覆盖关键子任务?
  2. 有没有从历史失败中积累的回归测试集,覆盖已知的关键失败模式?
  3. 有没有足够的 Trace 信息,在出错时能定位到具体步骤?
  4. 有没有独立于 LLM 的权限控制和操作约束?
  5. 有没有针对多轮交互的安全行为测试?
  6. 已知的高风险失败模式,是否作为 Release Gate 在部署前拦截?

这不是什么复杂的架构设计,更像是一份基础的工程检查清单。但我发现,在 LLM Agent 快速落地的氛围下,这些看似基础的问题反而容易被跳过。

回头看 Lecture 6 和 Lecture 7 的关系:Lecture 6 那几篇回答的是"模型好不等于公平”、“泛化好不等于鲁棒”,Lecture 7 回答的是"模型好不等于安全"。它们共同指向一个更底层的认识:模型质量是系统质量的必要条件,但远不是充分条件。

写在最后
#

学 Lecture 7 之前,我对 LLM Agent 安全性的理解大致停留在"提高模型正确率"这个层面。觉得只要模型足够好、Prompt 写得足够细致,系统就应该是可靠的。

学完之后,认知发生了几个变化:

模型正确率高不等于安全风险低。不同错误的后果差异巨大,99.9% 的正确率在特定场景下可能仍然不够。

发现错误和限制错误后果是两种不同的工程能力。Evaluation 和 Observability 帮助发现和定位问题,但只有独立于模型的安全机制才能在模型出错时兜底。

Prompt 有用,但不是安全边界。它是软约束,表达期望而非强制保证。关键安全决策必须依赖系统层面的权限控制。

模型升级不等于系统升级。一个新模型可能在总体指标上更好,但在特定关键场景上可能退化。需要有针对关键失败模式的回归测试作为 Release Gate。

可靠的 AI 系统,不能只追求模型更少犯错,还必须确保模型出错时,系统不会失去控制。

参考资料
#

相关文章