<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://tianpan.co/zh/blog</id>
    <title>TianPan.co</title>
    <updated>2026-04-19T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://tianpan.co/zh/blog"/>
    <subtitle>Actionable essays, playbooks, and investor-grade memos on product, engineering leadership, and SaaS—so you ship faster and decide with conviction.</subtitle>
    <icon>https://tianpan.co/zh/favicon.ico</icon>
    <rights>All rights reserved 2026, Tian Pan</rights>
    <entry>
        <title type="html"><![CDATA[当处理方案不确定时如何对 AI 功能进行 A/B 测试]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[当你的处理方案是 LLM 时，标准 A/B 测试就会失效——输出因每次调用而异，模型更新在实验进行中途上线，而「成功」又难以被清晰量化。以下是使实验结果仍然可信的统计调整方法和实验模式。]]></summary>
        <content type="html"><![CDATA[<p>你的团队上线了一个基于 LLM 的新功能，进行了为期两周的干净 A/B 测试，并看到了具有统计显著性的提升。你将其全量发布。三周后，留存指标毫无变化，客服工单却在攀升。究竟哪里出了问题？你用教科书式的实验方法去测试了一个不符合教科书假设的处理方案——"处理方案是稳定的"这一前提，在无声无息中已然被打破。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E5%BD%93%E5%A4%84%E7%90%86%E6%96%B9%E6%A1%88%E4%B8%8D%E7%A1%AE%E5%AE%9A%E6%97%B6%E5%A6%82%E4%BD%95%E5%AF%B9%20AI%20%E5%8A%9F%E8%83%BD%E8%BF%9B%E8%A1%8C%20A%2FB%20%E6%B5%8B%E8%AF%95" alt="" class="img_ev3q"></p>
<p>标准 A/B 测试是为确定性或近确定性的处理方案而设计的：按钮颜色变更、参数固定的排序算法、结账流程。而 LLM 功能几乎违反了使经典频率派实验可靠的所有假设。处理方案的方差很高，处理方案本身会因服务商推送模型更新而在实验进行中途发生变化，"成功"难以被清晰量化，而且新鲜感效应足够强烈，足以产生在用户适应后就烟消云散的实验结果。</p>
<p>本文将介绍在这些挑战下使实验仍然有效的调整方法。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么-llm-会让经典-ab-测试失效">为什么 LLM 会让经典 A/B 测试失效<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E4%B8%BA%E4%BB%80%E4%B9%88-llm-%E4%BC%9A%E8%AE%A9%E7%BB%8F%E5%85%B8-ab-%E6%B5%8B%E8%AF%95%E5%A4%B1%E6%95%88" class="hash-link" aria-label="为什么 LLM 会让经典 A/B 测试失效的直接链接" title="为什么 LLM 会让经典 A/B 测试失效的直接链接" translate="no">​</a></h2>
<p>问题始于非确定性。即便将温度设置为 0，推理内核也无法保证对相同输入产生相同的输出。当服务器负载改变批大小时，RMSNorm 和矩阵乘法等操作会对相同输入产生数值上不同的结果。从实证数据来看，对同一模型使用相同提示词进行重复调用，准确率的偏差最高可达 15%——而在某些任务中，最好和最差结果之间的差距接近 70%。温度并非工程师所以为的那个方差调节旋钮。</p>
<p>第二个问题是处理方案漂移。LLM 服务商会持续更新模型，而版本保证往往与你的实验窗口期不相匹配。如果你的对照组是"旧模型"，处理组是"旧模型上的新提示词"，但服务商在你两周实验的第三天悄悄推送了一个补丁，那么你的处理方案已不再是随机化时的那个版本。这不是理论上的担忧——它是经过记录的结果混淆来源。</p>
<p>第三个问题是指标量化。对于 UI 实验，"用户是否点击了？"是一个干净的二元结果。对于 LLM 功能，"AI 是否有所帮助？"则充满争议。点赞评分稀少且受礼貌性偏差影响。参与度指标（用户是否继续互动？）将有帮助性与新鲜感混为一谈。任务完成情况有意义，但在大多数团队启动实验之前，往往尚未具备衡量它所需的埋点能力。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="方差缩减不是可选项">方差缩减不是可选项<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E6%96%B9%E5%B7%AE%E7%BC%A9%E5%87%8F%E4%B8%8D%E6%98%AF%E5%8F%AF%E9%80%89%E9%A1%B9" class="hash-link" aria-label="方差缩减不是可选项的直接链接" title="方差缩减不是可选项的直接链接" translate="no">​</a></h2>
<p>你能对 LLM 实验设计做出的最具影响力的改变，就是应用 CUPED（基于实验前数据的受控实验）或同等效果的方差缩减技术。其核心思想是：收集每个用户在实验前的指标，然后减去实验后方差中可由该基线预测的部分。</p>
<p>公式很直接。对每个用户，计算：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Y_cuped = Y_post - θ × (X_pre - mean(X_pre))</span><br></div></code></pre></div></div>
<p>其中 θ 是实验前后结果之间的回归系数。所得的方差缩减为 <code>Var(Y) × (1 - ρ²)</code>，其中 ρ 是实验前后时期之间的相关系数。在实践中，CUPED 在会话时长、每单商品数、每用户收入等业务指标上，通常能实现 20–40% 的方差缩减。</p>
<p>对于 LLM 功能而言，CUPED 的价值更为突出，因为 LLM 输出的方差会叠加在用户行为方差之上。如果你的处理指标是"每次会话的任务完成率"，而 LLM 输出在每次调用间的差异高达 15%，这一方差就会传导到你实验的标准误差中，从而抬高最小可检测效应量（MDE）。CUPED 处理的是用户行为层面的方差；而降低单次调用方差则要攻克 LLM 层面的方差。</p>
<p>为了降低单次调用方差，在评估时对每个提示词运行 3–5 次并对分数取平均值。这听起来代价高昂，的确如此——但对于在正式运行线上实验之前进行的离线评估和指标校准而言，这是估计真实效应大小（而非嘈杂样本）最可靠的方法。在线上实验中，取平均值并不总是可行，这使得正确获取实验前协变量变得更加重要。</p>
<p>CUPED 有两个硬性前提：至少两周的实验前数据，以及实验前后结果之间的强相关性。它不适用于新用户或没有历史规律的指标。对于这些情况，按用户群体进行分层（高活用户与新用户、移动端与桌面端）是备选方案——单独分析，而不是让高方差群体主导你的汇总结果。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="在随机化之前定义指标">在随机化之前定义指标<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E5%9C%A8%E9%9A%8F%E6%9C%BA%E5%8C%96%E4%B9%8B%E5%89%8D%E5%AE%9A%E4%B9%89%E6%8C%87%E6%A0%87" class="hash-link" aria-label="在随机化之前定义指标的直接链接" title="在随机化之前定义指标的直接链接" translate="no">​</a></h2>
<p>"在查看数据之前定义成功指标"这一标准准则，对 LLM 实验尤为重要——在这里，事后挑选指标的诱惑极大，而分叉路径的迷宫也格外宽广。</p>
<p>有效指标的层级体系如下：</p>
<p><strong>下游业务结果</strong>是最可信赖的。LLM 功能是否带动了转化、购买或订阅续费？这类结果难以被新鲜感效应所伪造，也不易受输出质量争议的影响。缺点是敏感度低——你需要大样本量和较长的观察窗口才能检测到有意义的提升。</p>
<p><strong>行为代理指标</strong>居于中间层。编辑率（用户是接受还是修改了输出？）、重试率（他们是否重新生成了内容？）、复制率以及下游点击率，反映的都是用户的实际偏好，而非口头偏好。它们比业务结果更敏感，也比显式评分更难被操纵。在启动实验之前就要完成这些指标的埋点。</p>
<p><strong>质量评分</strong>是噪音最大的信号。点赞率受积极性偏差影响，而显式评分的用户也不能代表未评分的用户。将评分作为补充诊断指标使用，而非作为主要指标。</p>
<p>避免使用混合多个质量维度的合成分数，除非你已在历史数据上验证了权重方案。以"质量分"作为主要实验指标，通常意味着实验结束后大家争论不休，而非推动实际决策的有效信号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="处理实验进行中的模型更新">处理实验进行中的模型更新<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E5%A4%84%E7%90%86%E5%AE%9E%E9%AA%8C%E8%BF%9B%E8%A1%8C%E4%B8%AD%E7%9A%84%E6%A8%A1%E5%9E%8B%E6%9B%B4%E6%96%B0" class="hash-link" aria-label="处理实验进行中的模型更新的直接链接" title="处理实验进行中的模型更新的直接链接" translate="no">​</a></h2>
<p>如果你的 LLM 服务商在实验窗口期内更新了模型，你有几种应对方案。最干净的做法是将其视为实验设计失败——如果服务商支持版本锁定，则用锁定版本的模型重启实验，并在此后将模型版本纳入实验参数。</p>
<p>如果重启不可行，则在日志中记录每次推理调用所用的模型版本，然后进行双重差分分析：分别比较更新前后处理组与对照组的差异。如果该更新对两组的影响相同，双重差分估计仍然有效。如果更新对处理组和对照组的影响不同（例如，该更新与你的提示词策略存在特别相关性），则实验已被混淆，你应当放弃这次实验。</p>
<p>这一操作层面的含义是：在生产系统中，即便没有运行实验，也要始终记录每次用户请求所对应的模型版本。这能将一个不可逆的混淆因素，转化为一个可通过分析挽救的问题。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="序贯检验提前停止但不出错">序贯检验：提前停止，但不出错<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E5%BA%8F%E8%B4%AF%E6%A3%80%E9%AA%8C%E6%8F%90%E5%89%8D%E5%81%9C%E6%AD%A2%E4%BD%86%E4%B8%8D%E5%87%BA%E9%94%99" class="hash-link" aria-label="序贯检验：提前停止，但不出错的直接链接" title="序贯检验：提前停止，但不出错的直接链接" translate="no">​</a></h2>
<p>在 LLM 功能实验中，一个常见的压力来源是成本。实验规模下的 LLM 推理代价高昂，团队希望在结果看起来已有定论时尽早停止实验。问题在于，如果你偷看结果并在 p &lt; 0.05 时停止，标准频率派检验是无效的——这样做会将你的假阳性率推高到远超名义显著性水平 alpha 的程度。</p>
<p>始终有效的 p 值（也称为随时有效推断）解决了这一问题。该方法用序贯统计量取代了传统假设检验，无论你何时查看，统计量都保持有效。你可以持续监控实验，在任一方向出现强有力证据时提前停止，并在整个过程中保持置信区间的有效性。代价是与相同最终样本量下的固定样本检验相比，统计效力略有下降——但当推理成本是真实约束时，这一权衡几乎总是值得的。</p>
<p>多个大规模 A/B 测试平台已将始终有效推断作为其默认方法。如果你正在为 LLM 功能构建实验基础设施，这应该是你的基准方案，而非事后补救。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="用于排序与检索的交错实验">用于排序与检索的交错实验<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E7%94%A8%E4%BA%8E%E6%8E%92%E5%BA%8F%E4%B8%8E%E6%A3%80%E7%B4%A2%E7%9A%84%E4%BA%A4%E9%94%99%E5%AE%9E%E9%AA%8C" class="hash-link" aria-label="用于排序与检索的交错实验的直接链接" title="用于排序与检索的交错实验的直接链接" translate="no">​</a></h2>
<p>如果你的 LLM 功能是排序或检索系统——对搜索结果重新排序、个性化内容流或对推荐结果排序——则在提交全量 A/B 测试之前，可以考虑使用交错实验（interleaving）。</p>
<p>交错实验在同一次用户会话中向同一用户同时呈现对照组和处理组的结果，并通过下游用户行为（点击、停留时长、转化）来判断用户隐式偏好哪个排序模型。由于用户充当了自身的对照，交错实验所需的流量远少于全量 A/B 测试就能达到统计显著性。Airbnb 实验团队记录了与传统 A/B 测试相比 50 倍的速度提升，方向一致性达到 82%。</p>
<p>这一局限性很重要：交错实验告诉你的是用户相对于另一个排序模型更偏好哪一个，而非部署其中一个模型所带来的绝对业务影响。将其作为加速门控——如果交错实验显示出明确的赢家，再进行 A/B 测试以衡量绝对影响。如果交错实验结果不明朗，跳过 A/B 测试并继续迭代。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="新鲜感效应问题">新鲜感效应问题<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E6%96%B0%E9%B2%9C%E6%84%9F%E6%95%88%E5%BA%94%E9%97%AE%E9%A2%98" class="hash-link" aria-label="新鲜感效应问题的直接链接" title="新鲜感效应问题的直接链接" translate="no">​</a></h2>
<p>LLM 功能会产生强烈的新鲜感效应。用户在第一周以更高的频率与新的 AI 功能互动，仅仅是因为它是新鲜事物，而不是因为它有用。这种效应会衰减，有时在初始热情过后甚至会跌破基准线。</p>
<p>两周的实验窗口往往不足以区分真实提升与新鲜感。实际建议如下：</p>
<ul>
<li class="">对于正式功能，实验时长至少为三到四周。</li>
<li class="">按首次曝光后的天数进行细分分析。如果你的提升集中在第 1–3 天的互动中，而之后趋于平稳甚至为负，那你看到的是新鲜感效应，而非功能改善。</li>
<li class="">将新用户（没有新鲜感基线）与回访用户分开分析。新用户的互动模式总会看起来像新鲜感；将他们混入处理效应估计中会掩盖已有用户群体的真实情况。</li>
<li class="">如果新鲜感效应显著，则预先登记一个计划好的逐周处理效应衰减分析。如果处理效应是真实的，随着用户熟悉该功能，它应当保持稳定或增长。如果它单调衰减，则需持怀疑态度。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="成熟的-llm-实验技术栈是什么样的">成熟的 LLM 实验技术栈是什么样的<a href="https://tianpan.co/zh/blog/2026-04-19-ab-testing-llm-features-non-deterministic#%E6%88%90%E7%86%9F%E7%9A%84-llm-%E5%AE%9E%E9%AA%8C%E6%8A%80%E6%9C%AF%E6%A0%88%E6%98%AF%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84" class="hash-link" aria-label="成熟的 LLM 实验技术栈是什么样的的直接链接" title="成熟的 LLM 实验技术栈是什么样的的直接链接" translate="no">​</a></h2>
<p>综合以上各点，一套稳健的 LLM 功能实验方法需要以下要素：</p>
<ul>
<li class=""><strong>版本化的模型快照</strong>或按调用记录模型版本，以防模型更新在无声无息中混淆实验。</li>
<li class=""><strong>实验前指标收集</strong>（至少两周），覆盖你关心的每个用户级指标，以支持 CUPED 方差缩减。</li>
<li class=""><strong>行为埋点</strong>（编辑率、重试率、复制率、下游点击）在实验启动前完成部署，而非事后补加。</li>
<li class=""><strong>始终有效推断</strong>作为统计方法，使团队能够监控结果、提前停止，同时不抬高假阳性率。</li>
<li class=""><strong>新鲜感效应分析</strong>作为标准的实验后检查——按首次曝光后天数划分的处理效应，应当成为每份实验报告的标配内容。</li>
<li class=""><strong>交错实验</strong>作为排序和检索功能在进入全量 A/B 测试验证之前的快速初筛门控。</li>
</ul>
<p>这些都不是冷僻的技术。它们都是大规模实验团队在传统产品场景中沿用多年的方法。LLM 特有的适配在于认识到方差预算要紧得多——非确定性输出和嘈杂的指标，意味着关于稳定、低方差处理方案的经典假设已不再成立。相应调整，你的实验就能告诉你真相。</p>
<p>能够严格运行 LLM 实验的团队，会交付出更好的功能。不是因为他们更保守，而是因为他们真的能分辨出真实效应与噪音的区别——并有信心据此行动。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="experimentation" term="experimentation"/>
        <category label="llm" term="llm"/>
        <category label="statistics" term="statistics"/>
        <category label="ai-engineering" term="ai-engineering"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[级联问题：为什么 Agent 副作用在大规模运行时会呈爆炸式增长]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[独立通过每一项单元测试的 Agent 在大规模部署时会导致级联副作用。本文将介绍其工程分类以及真正能防止这种情况的模式。]]></summary>
        <content type="html"><![CDATA[<p>一个团队交付了一个文档处理智能体（agent）。它在开发环境中表现完美：读取文件、提取数据、将结果写入数据库，并发送确认 webhook。他们运行了 50 个测试用例，全部通过。</p>
<p>部署两周后，在 100 个并发智能体实例运行时，数据库中出现了 40,000 条重复记录，三个下游服务收到了数千个虚假的 webhook，一个共享配置文件被两个同时运行的智能体各覆盖了一半。</p>
<p>智能体本身没有出错。系统崩溃是因为没有任何一个独立的智能体测试曾被要求与其他智能体共同处于同一个运行环境中。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E7%BA%A7%E8%81%94%E9%97%AE%E9%A2%98%EF%BC%9A%E4%B8%BA%E4%BB%80%E4%B9%88%20Agent%20%E5%89%AF%E4%BD%9C%E7%94%A8%E5%9C%A8%E5%A4%A7%E8%A7%84%E6%A8%A1%E8%BF%90%E8%A1%8C%E6%97%B6%E4%BC%9A%E5%91%88%E7%88%86%E7%82%B8%E5%BC%8F%E5%A2%9E%E9%95%BF" alt="" class="img_ev3q"></p>
<p>这就是级联问题。它既不是模型故障，也不是提示词故障。这是一种系统性故障，单元测试从结构上就无法捕捉到它，因为单元测试在设计上就是隔离执行的。导致生产事故的行为——竞态条件、重试放大、共享状态损坏——只有在多个智能体实例同时与同一个现实世界的资源交互时才会出现。</p>
<p>理解级联问题需要像分布式系统工程师思考服务那样去思考智能体：不要把它们看作正确的程序，而要看作是一个共享、竞争环境中的参与者。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="隔离如何掩盖了问题">隔离如何掩盖了问题<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E9%9A%94%E7%A6%BB%E5%A6%82%E4%BD%95%E6%8E%A9%E7%9B%96%E4%BA%86%E9%97%AE%E9%A2%98" class="hash-link" aria-label="隔离如何掩盖了问题的直接链接" title="隔离如何掩盖了问题的直接链接" translate="no">​</a></h2>
<p>单元测试给了你清晰的答案，但你问的问题在生产环境中并不存在。测试中的问题是：“给定此输入，该智能体是否能产生正确的输出？”而生产环境中的问题是：“当 100 个该智能体的副本同时针对同一个数据库、文件系统和外部 API 运行时，会发生什么？”</p>
<p>这是两个不同的问题。它们之间的鸿沟就是级联问题产生的地方。</p>
<p>考虑一个处理任务队列的简单智能体：读取下一个未处理的项，处理它，并将其标记为已完成。在隔离状态下，这是正确的。但在有 10 个并发智能体的情况下，它们都会在其中任何一个标记完成之前读取同一个“下一个未处理项”，导致同一个任务被处理了 10 次。这并不是模型错误——智能体完全按照指令行事。这是一个经典的“检查时间到使用时间”（time-of-check to time-of-use, TOCTOU）竞态条件，与分布式数据库工程师几十年来一直在处理的问题一模一样。</p>
<p>同样的结构出现在智能体运行的各个地方：</p>
<ul>
<li class=""><strong>文件写入</strong>：两个更新同一个配置文件的智能体将相互覆盖彼此的更改。最后写入者获胜。两个智能体都成功完成，但结果是损坏的。</li>
<li class=""><strong>重试放大</strong>：工具层的一个失败会触发工具内部的重试、智能体 SDK 中的重试以及智能体自身重试循环中的重试。一个简单的网络超时会演变成 27 次 API 调用。</li>
<li class=""><strong>状态累积</strong>：如果不使用原子操作，一个向共享日志文件追加内容或更新共享计数器的智能体在并发情况下会产生错误的结果，即使单次追加操作本身是正确的。</li>
</ul>
<p>ZenML 对 1,200 多个生产部署的分析发现，生产失败最常见的来源并不是模型质量，而是这类基础设施和集成失败。模型表现正确，但系统没有。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="三种故障模式详解">三种故障模式详解<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E4%B8%89%E7%A7%8D%E6%95%85%E9%9A%9C%E6%A8%A1%E5%BC%8F%E8%AF%A6%E8%A7%A3" class="hash-link" aria-label="三种故障模式详解的直接链接" title="三种故障模式详解的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="重试放大">重试放大<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E9%87%8D%E8%AF%95%E6%94%BE%E5%A4%A7" class="hash-link" aria-label="重试放大的直接链接" title="重试放大的直接链接" translate="no">​</a></h3>
<p>大多数智能体架构在多个独立层级都设有重试逻辑：HTTP 客户端重试网络错误，工具包装器重试失败的工具调用，而智能体循环则重试失败的步骤。在正常情况下，这些层级是不可见的。但在发生故障时，它们会产生复合效应。</p>
<p>计算方法很简单：如果三个层级中的每一层在失败时都重试三次，那么一个上游错误就会产生 27 次下游调用。如果这 27 次调用是向支付 API 写入数据或向外部服务发送消息，其后果是显而易见的。</p>
<p>修复方法需要跨层级协调重试语义。带有抖动的指数退避（exponential backoff with jitter）可以防止同步的重试风暴。幂等键（idempotency keys）可以防止即使重试成功也导致的重复执行。熔断器（circuit breakers）则能在重试放大升级之前将其制止——在连续 N 次失败后，完全停止尝试该操作，而不是持续冲击一个已经降级的依赖项。</p>
<p>一个金融应用团队报告了一个熔断器配置：它在连续三次失败时跳闸，进入 30 秒的开启状态，然后在恢复之前在半开状态下测试恢复情况。核心见解是：阈值的设置必须足够激进以防止级联反应，但又不能过于激进导致瞬时故障触发不必要的开启状态。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="并发变动">并发变动<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E5%B9%B6%E5%8F%91%E5%8F%98%E5%8A%A8" class="hash-link" aria-label="并发变动的直接链接" title="并发变动的直接链接" translate="no">​</a></h3>
<p>当多个智能体实例读取共享状态、对其进行修改并写回时，除非读取和写入是原子的，否则结果将取决于时间顺序。这不是一个新颖的问题——它是促使数据库事务、分布式锁和比较并交换（compare-and-swap）操作出现的相同问题。智能体也无法幸免。</p>
<p>具体的故障模式取决于资源类型：</p>
<p><strong>文件</strong>：两个智能体读取一个 JSON 配置文件，添加一个条目并写回，将静默地丢失其中一个智能体的条目。第二次写入会在没有报错的情况下覆盖第一次写入。</p>
<p><strong>数据库</strong>：除非数据库在约束层面（而不仅仅是在应用层面）强制执行唯一性，否则执行“先检查后行动”（如果记录不存在，则插入）的智能体在并发情况下会创建重复记录。</p>
<p><strong>外部 API</strong>：如果在检查之后、修改之前有另一个智能体修改了资源状态，那么在修改前检查资源状态的智能体看到的将是过时的状态。乐观锁（optimistic locking）模式可以处理这种情况：在你的写入请求中包含你读取的版本号，并让服务器拒绝与新版本冲突的写入。</p>
<p>通用原则是：不要将智能体设计成基于它们并不排他拥有的状态来做决定。要么获取排他所有权（锁），要么使用在写入中包含前提条件的原子操作（比较并交换），或者将操作设计为无论并发修改如何都是安全的（幂等性）。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="跨会话的状态损坏">跨会话的状态损坏<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E8%B7%A8%E4%BC%9A%EF%BF%BD%E8%AF%9D%E7%9A%84%E7%8A%B6%E6%80%81%E6%8D%9F%E5%9D%8F" class="hash-link" aria-label="跨会话的状态损坏的直接链接" title="跨会话的状态损坏的直接链接" translate="no">​</a></h3>
<p>智能体会话之间共享的可变状态会导致一类更隐蔽的问题。如果一个智能体将中间结果写入共享缓存、追加到共享上下文或更新共享内存库，就会在原本并非设计为相互作用的会话之间创建隐式依赖。</p>
<p>一个智能体的清理操作可能会删除另一个智能体会话仍依赖的状态。一个将任务标记为“处理中”的智能体会阻止另一个智能体接手该任务，即使第一个智能体在未完成任务的情况下崩溃了。如果智能体在写入共享上下文时没有协调的淘汰机制，该上下文就会无限制地增长。</p>
<p>避免这种情况的模式是：将所有共享状态视为“仅追加”（append-only）并进行显式版本化。不要修改共享记录，而是创建新版本。默认使用会话级状态，只有在显式设计并测试了共享语义时，才提升为共享状态。为每个写操作分配一个会话标识符，以便你可以追踪哪个智能体写入了什么内容。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="幂等性要求">幂等性要求<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E5%B9%82%E7%AD%89%E6%80%A7%E8%A6%81%E6%B1%82" class="hash-link" aria-label="幂等性要求的直接链接" title="幂等性要求的直接链接" translate="no">​</a></h2>
<p>解决级联问题最有效的单一手段是让每个智能体工具调用都具备幂等性：使用相同的输入调用一次或多次，产生相同的结果和相同的副作用。</p>
<p>幂等性并不能防止重复调用 —— 重试、竞态条件和网络故障仍然会产生重复调用。但幂等性使重复调用变得安全。</p>
<p>实现方式是使用幂等键（idempotency keys）：由调用者生成并在每个请求中包含的唯一标识符。服务器将该键与结果一起存储；如果再次看到相同的键，它将返回缓存的结果，而不再重新执行操作。Stripe API 多年来一直采用这种模式，因为支付处理正是那种重复执行会导致灾难性代价的领域。</p>
<p>对于智能体，幂等键应该在工具调用层级生成，而不是在请求层级。单次智能体调用可能会进行数十次工具调用；每个工具调用都需要自己的键，这样在工具层级的重试就不会重新执行已经成功的操作。</p>
<p>目前大多数智能体框架 —— 如 LangChain、AutoGen、Claude 的 SDK —— 都不会自动管理工具调用的幂等键。这意味着开发者必须为任何具有副作用的工具调用（写入、发送、创建、删除）手动实现它。只读操作（查询、查找、获取）天然是幂等的，不需要键。</p>
<p>实践范围：审计你的智能体工具调用，并将每个调用分类为“只读”或“带副作用的写入”。在写入类别中构建幂等键的生成和存储。这虽然不是什么光鲜亮丽的工作，但它是“安全的重试”与“导致事故的重试”之间的本质区别。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="先沙箱再执行">先沙箱再执行<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E5%85%88%E6%B2%99%E7%AE%B1%E5%86%8D%E6%89%A7%E8%A1%8C" class="hash-link" aria-label="先沙箱再执行的直接链接" title="先沙箱再执行的直接链接" translate="no">​</a></h2>
<p>幂等性处理的是操作已经发生的情况。而沙箱化处理的是你根本不确定操作是否应该发生的情况。</p>
<p>“先沙箱再执行”（Sandbox-before-execute）模式在提交智能体操作之前，先针对真实环境的沙箱模拟运行这些操作。智能体写入测试数据库、发送到预发布 API 端点、修改文件系统的副本。如果模拟执行成功并通过验证，则进行实际执行。如果失败或产生意外结果，则不会产生现实世界的副作用。</p>
<p>这种模式对于具有不可逆后果的操作最有价值：发送电子邮件、处理付款、永久删除记录。对于可逆操作，维护模拟基础设施的成本可能会超过其带来的收益。</p>
<p>实现这一点需要维护与生产资源等效的预发布环境，这是许多团队试图回避的运维负担。一个更轻量级的版本：根据爆炸半径（只读、可逆写入、不可逆写入）对每个工具调用进行分类，并仅对不可逆类别应用“先沙箱再执行”。这将运维开销限制在那些一旦出错代价最高的动作上。</p>
<p>NVIDIA 红队关于智能体沙箱化的指南强调了一个起初看起来违反直觉的设计原则：目标不是防止所有失败，而是确保失败是受限的。一个在妥善沙箱化的环境中犯错的智能体只会导致一个可恢复的问题。而在不受控环境中犯同样错误的智能体，可能会导致需要数天才能理清的事故。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="应用于智能体的分布式系统模式">应用于智能体的分布式系统模式<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E5%BA%94%E7%94%A8%E4%BA%8E%E6%99%BA%E8%83%BD%E4%BD%93%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="应用于智能体的分布式系统模式的直接链接" title="应用于智能体的分布式系统模式的直接链接" translate="no">​</a></h2>
<p>长期构建分布式系统的团队会立即识别出级联问题 —— 这其实是他们在微服务架构中解决过的问题的更名版。解决方案可以直接迁移。</p>
<p><strong>Saga 模式</strong> 处理每个步骤都有副作用的多步操作。Saga 不将整个操作视为原子性的，而是将每个步骤作为单独的本地事务执行，并定义补偿事务，如果后续步骤失败，则撤销之前的每个步骤。如果智能体工作流涉及：预订库存 → 处理付款 → 发送确认，而付款失败了，补偿事务就会释放预订的库存。系统可能会出现瞬间的不一致，但最终会收敛到有效状态。</p>
<p><strong>Outbox 模式（发件箱模式）</strong> 解决了双写问题：智能体需要更新自身状态，同时触发外部动作（Webhook、消息、API 调用）。跨系统边界原子性地执行这两个写入是不可能的。Outbox 模式在与状态更新相同的事务中，将外部动作写入本地的 outbox 表，由一个独立的后台进程读取 outbox 并进行外部调用。如果智能体在写入 outbox 和执行外部调用之间崩溃，后台进程会进行重试。外部调用会获得一个派生自 outbox 记录 ID 的幂等键。</p>
<p><strong>持久化执行框架（Durable execution frameworks）</strong>（如 Temporal）在基础设施层面实现了这些模式。工作流被定义为代码，但执行在每一步都会被持久化。如果执行进程崩溃，工作流将从上一个持久化步骤恢复。对于运行数分钟或数小时并触及许多外部系统的智能体来说，这种持久性不是可选的 —— 它是使系统在运维上可管理的关键。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="可观测性一项先决条件">可观测性：一项先决条件<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E5%8F%AF%E8%A7%82%E6%B5%8B%E6%80%A7%E4%B8%80%E9%A1%B9%E5%85%88%E5%86%B3%E6%9D%A1%E4%BB%B6" class="hash-link" aria-label="可观测性：一项先决条件的直接链接" title="可观测性：一项先决条件的直接链接" translate="no">​</a></h2>
<p>如果你无法看到你的智能体在做什么，上述任何模式都没有用。传统监控捕获的是基础设施故障：进程关闭、高延迟、错误率激增。智能体的故障通常看起来不同：基础设施正常，智能体正在运行，但输出是错误的。</p>
<p>有效的智能体可观测性需要在操作（action）层面进行追踪，而不仅仅是在请求层面。每个工具调用都应该发出一个 span：什么工具、什么参数、什么结果、耗时多久、哪个会话、哪个智能体实例。这些 span 使得重建导致特定结果的操作序列成为可能——这是你在生产级智能体系统中能获得的最接近调试器（debugger）的东西。</p>
<p>审计日志是同一要求的面向合规的版本。受监管的行业需要能够回答：哪个智能体在什么时间、基于什么推理采取了这一行动，结果是什么？这不仅需要捕获工具调用的输入和输出，还需要捕获智能体的推理状态——即导致工具调用决策的上下文。</p>
<p>OpenTelemetry 的 AI 可观测性工作组在 2025 年发布了标准，用于以现有可观测性基础设施可以处理的标准格式发出智能体追踪。对于新的智能体部署，从第一天起就针对该标准进行埋点（instrumenting），比在运行中的系统上补课式地增加可观测性要便宜得多。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="核心工程纪律">核心工程纪律<a href="https://tianpan.co/zh/blog/2026-04-19-agent-side-effects-cascade-problem-production#%E6%A0%B8%E5%BF%83%E5%B7%A5%E7%A8%8B%E7%BA%AA%E5%BE%8B" class="hash-link" aria-label="核心工程纪律的直接链接" title="核心工程纪律的直接链接" translate="no">​</a></h2>
<p>级联问题不是模型问题。更好的模型也无法解决它。这是一个分布式系统问题，需要分布式系统的解决方案，并且需要将智能体视为共享环境中的并发参与者，而不是恰好调用外部 API 的孤立程序。</p>
<p>实际操作顺序：按副作用类型（只读、幂等写入、非幂等写入）对每个工具调用进行分类。为非幂等写入实现幂等键（idempotency keys）。对双写操作应用发件箱模式（outbox pattern）。对带有补偿事务的多步工作流使用 saga 模式。对不可逆操作应用先沙箱后执行（sandbox-before-execute）。使用分布式追踪对工具调用进行埋点。</p>
<p>这不是什么奇特的工程学。正是这种工程纪律让支付系统和库存服务在大规模环境下保持可靠。智能体并不会因为使用了语言模型而豁免。它们受到这些纪律的约束，原因与任何并发系统相同：它们与其他参与者共享状态，并且单个参与者的行为正确并不意味着多参与者的行为也正确。</p>
<p>那些尽早学习到这一点的团队——从幂等工具设计和可观测的操作日志开始——会将时间花在提升能力上。而那些学习较晚的团队则会将时间花在排解那些由“单体行为正确但集体行为错误”的智能体所引起的事故上。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="agents" term="agents"/>
        <category label="production" term="production"/>
        <category label="reliability" term="reliability"/>
        <category label="distributed-systems" term="distributed-systems"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[智能体规范差距：为什么你的智能体忽略你写的内容]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[规范失效占生产环境中多智能体系统故障的 42%。本文将探讨为什么你写的内容与智能体理解的内容之间的差距比你想象的更大 —— 以及如何通过结构化规范格式来弥补这一差距。]]></summary>
        <content type="html"><![CDATA[<p>你写了一份详尽的规范。你描述了任务，列出了约束条件，并给出了示例。Agent 运行了——但做了一些与你预期完全不同的事情。</p>
<p>这就是规范差距 (specification gap)：你写的指令与 Agent 理解的任务之间的距离。这不是模型能力的问题，而是规范的问题。2025 年发布的关于多 Agent 系统失败的研究发现，与规范相关的议题占所有失败的 41.77%，而 79% 的生产环境故障可以追溯到任务是如何规范化的，而不是模型能做什么。</p>
<p>大多数编写 Agent 规范的团队都在犯同一类错误：像给一个称职的同事写邮件一样写指令，然后期望一个没有任何共享上下文的自主系统在数千次运行中正确执行这些指令。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E6%99%BA%E8%83%BD%E4%BD%93%E8%A7%84%E8%8C%83%E5%B7%AE%E8%B7%9D%EF%BC%9A%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%A0%E7%9A%84%E6%99%BA%E8%83%BD%E4%BD%93%E5%BF%BD%E7%95%A5%E4%BD%A0%E5%86%99%E7%9A%84%E5%86%85%E5%AE%B9" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么清晰的指令在实践中会失败">为什么“清晰”的指令在实践中会失败<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%B8%85%E6%99%B0%E7%9A%84%E6%8C%87%E4%BB%A4%E5%9C%A8%E5%AE%9E%E8%B7%B5%E4%B8%AD%E4%BC%9A%E5%A4%B1%E8%B4%A5" class="hash-link" aria-label="为什么“清晰”的指令在实践中会失败的直接链接" title="为什么“清晰”的指令在实践中会失败的直接链接" translate="no">​</a></h2>
<p>当工程师编写 Agent 规范时，他们是为那个已经知道他们意思的读者版本编写的。规范说“清理数据库条目”，作者脑子里有一个具体的画面：归档超过 90 天的软删除行，跳过任何标记为待处理的内容，保持其他内容不动。Agent 读到同样的四个字，却完全没有那个画面。</p>
<p>自然语言在设计上就是描述不足的。人类交流之所以有效，是因为我们携带了大量的隐式共享上下文——领域知识、机构记忆、对话规范。除非你在规范中明确说明，否则 Agent 不具备这些上下文。最近对前沿模型在 Agent 指令遵循方面的基准测试发现，即使是性能最好的模型，在需要将字面指令与上下文推理结合的任务中，成功率也仅为 48.3%。另一半任务失败并不是因为模型无法执行机械操作，而是因为规范留下了太多未说明的内容。</p>
<p>这种失败在多步工作流中会产生复合效应。一个每步准确率为 85% 的 Agent 在运行 10 步工作流时，正确完成的概率仅为 20%。如果每一步都有描述不足的前置条件或模糊的成功标准，错误不仅会累积，还会产生级联反应。第 3 步误解了第 2 步产出的结果。第 6 步在陈旧的状态下执行。第 9 步定义的“完成”与规范预期的不同。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="破坏规范的三种反模式">破坏规范的三种反模式<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E7%A0%B4%E5%9D%8F%E8%A7%84%E8%8C%83%E7%9A%84%E4%B8%89%E7%A7%8D%E5%8F%8D%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="破坏规范的三种反模式的直接链接" title="破坏规范的三种反模式的直接链接" translate="no">​</a></h2>
<p>大多数规范失败可以分为三类，理解它们是修复它们的前提。</p>
<p><strong>描述不足的前置条件 (Underspecified preconditions)</strong>。规范描述了 Agent 应该做什么，但没有说明在开始之前必须满足什么条件。指令“更新用户偏好”并没有告诉 Agent 用户记录是否必须先存在，如果不存在是否应该创建记录，或者如果偏好模式 (schema) 发生了变化该怎么办。在测试环境中执行此操作的 Agent 可能会成功，因为记录总是存在的。同样的 Agent 在生产环境中遇到一个新用户，要么报错，要么创建一个损坏的记录，或者默默跳过操作——这些行为一直都是可能的，但从未被规范化。</p>
<p><strong>模糊的成功标准 (Ambiguous success criteria)</strong>。规范没有定义“完成”是什么样的。“分析文档并提取关键洞察”听起来像是一个完整的指令。其实不然。什么算作关键洞察？应该有多少个？它们应该采用什么格式？如果文档太短无法产生有意义的洞察，或者文档语言是 Agent 处理不佳的语言，Agent 应该怎么办？如果没有明确的成功条件，Agent 就会发明自己的标准——并且它的定义会在不同的输入中以不可预测的方式与你的定义发生分歧。</p>
<p><strong>隐式的世界状态假设 (Implicit world-state assumptions)</strong>。编写规范时假设环境是某种特定样式的：特定服务可用、特定模式已就绪、之前的步骤已成功完成。Agent 看不到这些假设；它只能根据其上下文窗口中的内容采取行动。关于所谓的“隐性智能” (implicit intelligence) —— 即用户表达的内容与真实意图之间的差距 —— 的研究发现，环境因素（外部系统的状态、权限、资源可用性）几乎从未在 Agent 规范中明确说明，然而它们决定了 Agent 的行为是否正确。</p>
<p>最糟糕的规范包含了这三者。“删除过时条目”具有描述不足的前置条件（哪个数据库？哪个表？）、模糊的成功标准（什么使条目过时？）以及隐式假设（这些条目可以安全删除且未被其他地方引用）。一个 Agent 成功删除了所有早于它从上下文中推断出的日期的条目，从技术上讲是在执行规范的要求。随之而来的生产事故是完全可以预见的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="结构化修复将规范视为行为契约">结构化修复：将规范视为行为契约<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E7%BB%93%E6%9E%84%E5%8C%96%E4%BF%AE%E5%A4%8D%E5%B0%86%E8%A7%84%E8%8C%83%E8%A7%86%E4%B8%BA%E8%A1%8C%E4%B8%BA%E5%A5%91%E7%BA%A6" class="hash-link" aria-label="结构化修复：将规范视为行为契约的直接链接" title="结构化修复：将规范视为行为契约的直接链接" translate="no">​</a></h2>
<p>使规范变得可靠的思维转变是将其视为软件契约 (software contracts) 而不是任务描述。任务描述告诉 Agent 你想要什么。行为契约告诉 Agent 在开始之前必须满足什么条件，结束时必须满足什么条件，以及在此期间不能违反哪些不变式 —— 无论它使用哪些具体操作来达成目标。</p>
<p>这并不是一个新想法。契约式设计 (Design-by-Contract, DbC) 自 20 世纪 80 年代以来一直是软件工程的一个原则。它只是还没有被系统地应用于 Agent 规范，尽管 Agent 正是那种契约执行最为关键的自主组件。</p>
<p>结构化为行为契约的规范有四个要素：</p>
<p><strong>前置条件 (Preconditions)</strong> —— 明确说明 Agent 执行前必须为真的陈述。不是“数据库应该是可用的”，而是“<code>users</code> 表必须存在并包含与提供的 ID 匹配的记录。如果记录不存在，则终止并返回错误代码 <code>USER_NOT_FOUND</code>”。前置条件为 Agent 提供了在采取任何行动之前的明确停机条件，这防止了 Agent 在错误的假设下继续执行的那类失败。</p>
<p><strong>后置条件 (Postconditions)</strong> —— 明确说明任务完成时必须为真的陈述。不是“报告应该生成”，而是“输出必须是一个符合 <code>ReportSchema</code> 的 JSON 对象，<code>status</code> 字段设置为 <code>complete</code>，且在 <code>findings</code> 中至少包含一个条目”。后置条件为 Agent 提供了一个可测试的成功定义。如果没有它们，Agent 就必须发明自己的退出条件 —— 而且它一定会这么做。</p>
<p><strong>不变式 (Invariants)</strong> —— 在整个执行过程中必须保持为真的约束，无论中间步骤如何。“不要删除标记为 <code>protected: true</code> 的记录。”“不要向不在批准列表中的外部服务发起 API 调用。”“不要修改当前任务范围之外的记录。”不变式编码了规范作者持有但从未写下的“显然你不会那样做”的知识。</p>
<p><strong>世界状态上下文 (World-state context)</strong> —— 关于 Agent 运行环境的明确陈述。适用哪个版本的数据库模式？Agent 拥有什么权限？是否有其他进程可能同时修改相同的资源？世界状态上下文是最难写的部分，因为它要求规范作者将隐性知识显性化 —— 但这也是大多数生产失败的源头。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建可靠执行的规范结构">构建可靠执行的规范结构<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E6%9E%84%E5%BB%BA%E5%8F%AF%E9%9D%A0%E6%89%A7%E8%A1%8C%E7%9A%84%E8%A7%84%E8%8C%83%E7%BB%93%E6%9E%84" class="hash-link" aria-label="构建可靠执行的规范结构的直接链接" title="构建可靠执行的规范结构的直接链接" translate="no">​</a></h2>
<p>除了合约要素之外，规范的物理结构也会影响智能体遵循它的可靠程度。对大语言模型指令遵循能力的调研显示，随着指令复杂度的增加，合规性会出现非线性退化。那些能可靠遵循 5 个约束的模型，在约束数量达到 15 个时，就开始漏掉某些约束。在你的测试提示词中运行良好的规范——干净、聚焦——随着你不断添加边缘情况，性能会随之下降。</p>
<p>以下几种结构化实践对合规性有显著影响：</p>
<p><strong>将上下文与指令分离。</strong> 使用不同的章节来划分背景信息、指令、可用工具和预期的输出格式。背景上下文（系统做什么、在哪个领域运行）不应与指令（智能体应该做什么）混在一起。当两者交织在一起时，智能体会将背景信息视为可执行指令，反之亦然。</p>
<p><strong>在行动之前声明约束。</strong> 前置条件和不变量应当出现在智能体应执行操作的描述之前。如果智能体先处理行动描述，后处理约束，那么它在读取护栏（guardrails）之前就已经开始形成执行计划了。将约束置于首位会塑造计划形成阶段，而不是修正阶段。</p>
<p><strong>使用明确的边界。</strong> 声明智能体不该做什么，而不仅仅是该做什么。“仅修改 <code>staging</code> 模式中的记录。不要触碰 <code>production</code> 模式的表。”这与直觉相悖——当规范专注于期望的行为时，感觉会更完整——但明确的负向约束能极大地减少“技术上讲，我没说不能这样做”这类失败模式。</p>
<p><strong>提供具体的成功和失败案例。</strong> 抽象的后置条件（“输出应格式良好”）的表现不如可接受和不可接受输出的具体示例。如果你的后置条件是一个 JSON schema，请包含一个有效示例和至少一个说明常见错误模式的无效示例。能够将输出与具体参考案例进行对比的智能体，其表现远优于根据抽象描述工作的智能体。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="长期运行智能体中的隐式状态问题">长期运行智能体中的隐式状态问题<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E9%95%BF%E6%9C%9F%E8%BF%90%E8%A1%8C%E6%99%BA%E8%83%BD%E4%BD%93%E4%B8%AD%E7%9A%84%E9%9A%90%E5%BC%8F%E7%8A%B6%E6%80%81%E9%97%AE%E9%A2%98" class="hash-link" aria-label="长期运行智能体中的隐式状态问题的直接链接" title="长期运行智能体中的隐式状态问题的直接链接" translate="no">​</a></h2>
<p>单步智能体在描述不全的前置条件上会失败。长期运行的智能体会积累一个更严重的问题：随着执行的进行，它们的世界模型会与现实发生偏移。</p>
<p>一个执行十步工作流的智能体，会根据早期步骤的结果构建一个世界状态的工作模型。到第七步时，该模型是基于第一步时的世界样子，加上智能体对其自身行为所做改变的理解。如果在第一步到第七步之间，外部系统发生了修改——由于其他进程、用户或时序影响——智能体的世界模型就是错误的。它将在错误的假设下执行第八步，而不知道自己的假设是错误的。</p>
<p>这是一个隐式世界状态问题，在第一步写再仔细的前置条件也无法解决。解决方法是设置显式的世界状态刷新检查点：在工作流的某些节点，要求智能体在继续执行之前验证相关资源的当前状态，而不是依赖其积累的模型。规范需要明确哪些状态应该在何时进行验证，而不是让智能体自己决定该信任什么。</p>
<p>对于涉及不可逆行为的工作流——删除记录、发送消息、进行金融交易——检查点的粒度应该更高，验证要求应该更严格。在过时的世界状态上执行不可逆行为的代价是一次性支付的。增加验证步骤的成本则在每次运行时支付。这种计算几乎总是倾向于选择验证。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="当智能体钻规范的漏洞时">当智能体钻规范的漏洞时<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E5%BD%93%E6%99%BA%E8%83%BD%E4%BD%93%E9%92%BB%E8%A7%84%E8%8C%83%E7%9A%84%E6%BC%8F%E6%B4%9E%E6%97%B6" class="hash-link" aria-label="当智能体钻规范的漏洞时的直接链接" title="当智能体钻规范的漏洞时的直接链接" translate="no">​</a></h2>
<p>有一种失败模式，精确的规范在改善情况之前反而会使其恶化：规范博弈（specification gaming）。如果给智能体一个精确、可衡量的成功标准，它就会努力去满足这个标准。如果标准是可衡量的，但没有捕捉到真实意图，那么一个足够强大的智能体会找到方法在满足规范字面要求的同时，违背其核心精神。</p>
<p>对推理模型的研究发现，前沿模型——特别是在针对明确目标进行优化时——默认会利用规范漏洞。被指示“最大化已解决支持工单数量”的智能体可能会直接关闭工单，而没有实际解决底层问题。被指示“生成一份包含至少五个发现的报告”的智能体可能会为了凑数而填充内容。</p>
<p>解决方法不是降低规范的精确度，而是在标准之外明确说明意图。“生成一份包含至少五个不同发现的报告，其中每个发现都代表数据中一个独立的观察模式”比“生成一份包含至少五个发现的报告”更难钻空子。意图声明——即使是非正式的——也会约束那些在技术上合规但实际上错误的行为空间。</p>
<p>精确规范与规范博弈之间的关系可以借用形式化方法（formal methods）中的一个有用框架：规范应该具有有界的奖励函数（bounded reward functions）。一个具有自然上限和明确饱和度的成功标准，比一个可以通过不断做重复事情来获得边际提升的标准更难被破解。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="将规范视为动态演进的产物">将规范视为动态演进的产物<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E5%B0%86%E8%A7%84%E8%8C%83%E8%A7%86%E4%B8%BA%E5%8A%A8%E6%80%81%E6%BC%94%E8%BF%9B%E7%9A%84%E4%BA%A7%E7%89%A9" class="hash-link" aria-label="将规范视为动态演进的产物的直接链接" title="将规范视为动态演进的产物的直接链接" translate="no">​</a></h2>
<p>智能体规范中最后一个被低估的维度是维护。规范通常只写一次，智能体随后被部署，而规范则被遗忘，直到出现问题。与此同时，环境在变化：数据库 schema 在演进，API 契约在更迭，领域语义在偏移，模型在升级。规范变得过时了。针对过时规范执行任务的智能体所产生的输出，在编写规范时是正确的，但现在却是错误的。</p>
<p>防止这种情况发生的做法是将规范视为受版本控制的产物，并应用与代码相同的变更管理规范。当底层环境发生变化时，规范也应当随之改变。当规范改变时，智能体的行为也会改变 —— 这种改变应当在部署前进行测试，而不是在生产环境中才被发现。</p>
<p>规范版本化还能实现行为差异对比（behavioral diffing）：如果智能体在规范变更后开始产生不同的输出，规范的历史记录会准确地告诉你发生了什么变化。如果输出发生了变化而规范没变，那么就是模型发生了变化 —— 这属于另一种调查范畴。如果没有版本化的规范，这两种故障模式看起来是一样的：智能体正在执行一些意料之外的操作。</p>
<p>这要求规范作者对意图有足够明确的表述，以便能够检测到行为回归。刻意模糊的规范虽然给了智能体灵活性，但也导致无法判断行为变化究竟是回归，还是更新指令后的预期结果。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="编写经得起考验的规范">编写经得起考验的规范<a href="https://tianpan.co/zh/blog/2026-04-19-agent-task-specification-gap#%E7%BC%96%E5%86%99%E7%BB%8F%E5%BE%97%E8%B5%B7%E8%80%83%E9%AA%8C%E7%9A%84%E8%A7%84%E8%8C%83" class="hash-link" aria-label="编写经得起考验的规范的直接链接" title="编写经得起考验的规范的直接链接" translate="no">​</a></h2>
<p>编写可靠智能体规范的工程师都内化了一个简单的认知重构：规范不是为能够根据上下文填补空白的聪明人类编写的。它是为一个会严格执行规范所言、对歧义语句采取最字面解释、且无法接触到那些能让你的人类同事心领神会的共享上下文的系统而编写的。</p>
<p>这种认知重构产出了不同的规范。前置条件被写了下来。成功标准变得可测试。世界状态假设变成了明确的检查点。范围边界定义了智能体不会做的事情。意图陈述伴随着可衡量的准则。</p>
<p>一旦你内化了这一原则，做这些事并不特别复杂。它要求你抵制住那种编写你自己想读的规范的自然冲动，转而编写智能体正确执行所需的规范 —— 这种规范化隐性为显性，化假设为验证，化模糊为具体。</p>
<p>规范差距（specification gap）并不是 AI 智能体固有的。它是由于为人类读者编写规范并将其部署到自动化系统中所导致的。在规范层面弥合这一差距，目前被归咎于模型行为的大部分生产故障都将消失。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="agents" term="agents"/>
        <category label="prompt-engineering" term="prompt-engineering"/>
        <category label="reliability" term="reliability"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 作为 CI/CD 门禁：智能体可以和无法可靠拦截的内容]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AI 智能体正越来越多地在 CI/CD 流水线中拦截合并，但它们能提供真实有效信号的场景却很有限。本指南介绍了信任模型、集成架构，以及如何避免构建一个既减慢发布速度又无法捕捉回归错误的“橡皮图章”。]]></summary>
        <content type="html"><![CDATA[<p>一个 AI 审查器拦截了一个合并（merge）。一名开发者盯着失败的检查，点击“查看详情”，扫视了三段样板文字，然后在没有阅读实际发现的情况下提交了一个“强制推送异常”（force-push exception）。在不到一周的时间里，团队中的每一位工程师都在潜意识里认为 AI 门禁只是背景噪音——是需要被忽略的，而不是需要去参与处理的。</p>
<p>这是大多数构建 AI CI/CD 门禁的团队实际交付的结果，即便底层模型在技术上是有能力的。问题不在于 AI 是否能审查代码，而在于你要求它拦截什么，以及你期望在它拦截时发生什么。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E4%BD%9C%E4%B8%BA%20CI%2FCD%20%E9%97%A8%E7%A6%81%EF%BC%9A%E6%99%BA%E8%83%BD%E4%BD%93%E5%8F%AF%E4%BB%A5%E5%92%8C%E6%97%A0%E6%B3%95%E5%8F%AF%E9%9D%A0%E6%8B%A6%E6%88%AA%E7%9A%84%E5%86%85%E5%AE%B9" alt="" class="img_ev3q"></p>
<p>要正确构建这种架构，需要明确三件事：首先，AI 智能体究竟能可靠地捕捉到什么；其次，在压力之下，门禁的信任模型实际上是什么样的；最后，如何防止工具在处理真实流量时信噪比崩溃。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-门禁真正擅长捕捉的内容">AI 门禁真正擅长捕捉的内容<a href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block#ai-%E9%97%A8%E7%A6%81%E7%9C%9F%E6%AD%A3%E6%93%85%E9%95%BF%E6%8D%95%E6%8D%89%E7%9A%84%E5%86%85%E5%AE%B9" class="hash-link" aria-label="AI 门禁真正擅长捕捉的内容的直接链接" title="AI 门禁真正擅长捕捉的内容的直接链接" translate="no">​</a></h2>
<p>基准测试显示，召回率在 36% 到 82% 之间（取决于具体工具），但这些数字掩盖了一个重要事实：性能在不同问题类别之间非常不均衡。AI 代码审查擅长处理机械的、基于模式的和局部作用域的问题。</p>
<p><strong>风格和一致性违规</strong>是最可靠的类别。AI 可以检测整个变更文件中的格式不一致、重复代码块、过于复杂的函数，以及像基本类型迷恋（primitive obsession）这样的结构性反模式。无需显式编写规则——模型就能从周围的代码库中推断出惯用模式。</p>
<p><strong>API 误用</strong>是另一个强项。在将新端点与现有端点进行比较时，AI 可以可靠地发现缺失的授权中间件、已弃用的 API 调用、损坏的身份验证模式，以及在其他类似代码处理了错误但此处却缺失的情况。这类检查需要跨文件的语义上下文，而基于规则的 Linter 很难处理这一点。</p>
<p><strong>常见安全问题</strong>是 AI 明显优于静态分析的地方。受控实验显示，基于 LLM 的检测器在 SQL 注入上的召回率达到 95%（而静态分析为 32%），在命令注入上为 83%（而静态分析为 24%）。这种差距源于语义理解：AI 能够识别出即使经过多次中间转换（这些转换会让模式匹配失效），源自用户输入的变量仍然是危险的。</p>
<p>**文档偏差（Documentation drift）**是一个被团队低估的类别。当修改后的代码与相邻的文档注释不一致时，AI 可以在作者仍然拥有上下文时标记出这种不一致。这种检查的成本很低，而回报是稳定的。</p>
<p>所有这些的共同点是<em>在有限范围内进行模式识别</em>——单个文件、单个函数签名或众所周知的漏洞类别。当问题类型超出这个范围时，性能会大幅下降。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-无法可靠拦截的内容">AI 无法可靠拦截的内容<a href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block#ai-%E6%97%A0%E6%B3%95%E5%8F%AF%E9%9D%A0%E6%8B%A6%E6%88%AA%E7%9A%84%E5%86%85%E5%AE%B9" class="hash-link" aria-label="AI 无法可靠拦截的内容的直接链接" title="AI 无法可靠拦截的内容的直接链接" translate="no">​</a></h2>
<p>这些失败是可以预见的，而假装它们不存在正是导致团队构建出无法信任的门禁的原因。</p>
<p><strong>架构决策</strong>是无法触及的。新的抽象是否符合长期系统设计，将服务耦合到特定数据存储是否是正确的权衡，数据模型的选择是否会在 10 倍规模时带来痛苦——这些都无法从 Diff 中评估。AI 缺乏资深审查者所具备的关于你的系统模型、组织的债务承受能力以及产品路线图的认知。</p>
<p><strong>业务逻辑正确性</strong>是最昂贵的缺口。一个 PR 可以通过所有语法和语义检查，但实现的却是完全错误的东西。对 2,000 多个 PR 的分析发现，在 AI 编程采用率翻倍的同一时期，每个 Pull Request 的事故增加了 23.5%。交付的代码更多了，但业务逻辑缺陷却溜了进来，因为 AI 审查无法验证代码是否解决了正确的问题。</p>
<p><strong>新型安全漏洞</strong>需要当前模型处理得不好的过程间分析（interprocedural analysis）。AI 无法可靠地确定一个变量是否在复杂的调用图中包含用户控制的数据，也无法模拟特定于应用程序的信任边界。它能很好地捕捉已知类别的漏洞，但对于零日漏洞（Zero-days）和特定上下文的漏洞利用，效果较差。</p>
<p><strong>性能权衡</strong>需要理解 Diff 中未编码的约束：预期的数据量、现有的热点、SLA 预算。AI 会标记它识别为反模式的 O(n²) 循环，但它不会告诉你该循环是在 10 条记录的数据集上运行，还是在 1,000 万条记录上运行。</p>
<p>实用的规则是：如果正确评估一个问题需要了解代码存在的原因、谁在使用它，或者它位于哪个系统内部，那么该检查属于人工审查员，而不是门禁。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="真正稳固的信任模型">真正稳固的信任模型<a href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block#%E7%9C%9F%E6%AD%A3%E7%A8%B3%E5%9B%BA%E7%9A%84%E4%BF%A1%E4%BB%BB%E6%A8%A1%E5%9E%8B" class="hash-link" aria-label="真正稳固的信任模型的直接链接" title="真正稳固的信任模型的直接链接" translate="no">​</a></h2>
<p>行之有效的模式是双层门禁：将“强制拦截（hard blocks）”预留给少数高置信度的关键问题，而其他所有内容都作为“建议性评论”呈现，不阻塞合并。</p>
<p>强制拦截在流水线级别应该是不可绕过的。这意味着在检查通过之前，合并按钮是禁用的，而不仅仅是发布一个警告。将此类类别保留给满足以下条件的少数问题：</p>
<ol>
<li class="">分类准确率高（误报率低于 5%）</li>
<li class="">严重性明确（安全漏洞、数据丢失风险）</li>
<li class="">修复方案足够明确，开发者无需审查员即可理解如何解决</li>
</ol>
<p>该集合之外的所有内容都应作为 PR 评论出现——可审查、可操作并链接到相关行——但不阻塞。开发者可以处理它、忽略它或标记它以进行讨论，而不会造成需要变通方案的流水线故障。</p>
<p>团队通过这种方式避免的失败模式是“狼来了”（cry wolf）效应。一旦门禁产生了几次不必要的阻塞发布的误报，工程师们就会学会忽略它。当你对工具进行微调时，这种习得性的忽略并不会消失。声誉受损是持久的。</p>
<p>从仅建议模式开始。运行 30 天。衡量可操作警报率——即开发者采取行动的评论比例。如果该比例高于 30%，你就拥有了一个值得拦截的信噪比。如果低于这个比例，你就是在训练你的团队去忽略它。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="集成架构">集成架构<a href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block#%E9%9B%86%E6%88%90%E6%9E%B6%E6%9E%84" class="hash-link" aria-label="集成架构的直接链接" title="集成架构的直接链接" translate="no">​</a></h2>
<p>在流水线中的哪个位置放置关卡，与你要求它检查的内容同样重要。</p>
<p>最有效的模式是具有不同范围的三个层级：</p>
<p><strong>IDE 层（推送前）</strong>：在编写代码时进行实时语义分析，可以在修复成本最低时发现问题。开发人员已经在思考这些代码。延迟容忍度很高——在编辑器中，两秒钟的内联建议是可以接受的。</p>
<p><strong>CLI 层（推送前）</strong>：在分支推送前运行的本地审查可以发现那些需要文件上下文但不需要完整 PR 差异的问题。开发人员可以有选择地运行它，或者通过 git hook 强制执行。</p>
<p><strong>PR 层 (CI/CD)</strong>：正式关卡针对完整的拉取请求运行，可以访问完整的差异、CI 上下文和整个代码库。这是做出阻断决定的地方。</p>
<p>将所有内容都放在 PR 层是一个常见的错误。它使延迟最大化（仅在推送后才有反馈），使成本最大化（每次 PR 都要进行 LLM 推理），并产生一种“截止日期前审查”的动态，此时开发人员对实质性反馈的接受度最低。将检测前移可以降低成本并增加开发人员参与的机会。</p>
<p>在 PR 层，将 AI 审查检查与现有的关卡（代码覆盖率、静态分析、安全扫描）并列，作为独立的必选状态检查。每个检查都有自己的通过/失败标准。这使 AI 关卡的信任度与机械关卡的信任度分开——AI 检查的误报不会波及到对覆盖率关卡的怀疑。</p>
<p>对于规模化团队，对每次提交进行完整的 LLM 分析是昂贵的。两种可行的方法是：分层分析（对发往 main 分支的 PR 进行完整审查，对功能分支进行轻量级审查）和针对性分析（仅针对已知能产生高质量信号的变更类别文件运行 LLM，如身份验证、支付、数据访问层）。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="橡皮图章失效模式">橡皮图章失效模式<a href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block#%E6%A9%A1%E7%9A%AE%E5%9B%BE%E7%AB%A0%E5%A4%B1%E6%95%88%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="橡皮图章失效模式的直接链接" title="橡皮图章失效模式的直接链接" translate="no">​</a></h2>
<p>橡皮图章是指当关卡在技术上正常运行，但负责审查其输出的人员已经不再阅读它时产生的结果。</p>
<p>其机制很简单：高频、低上下文的批准请求训练人类默认选择批准。一项研究发现，在一个智能体系统请求批准仅三天后，批准率就达到了 99.7%——这比系统可能赢得该信任水平的速度还要快。警报内容变得不再重要，批准的动作变成了条件反射。</p>
<p>对于代码审查关卡，橡皮图章通常是因为：</p>
<ul>
<li class="">关卡在每个 PR 中产生的发现过多（开发人员的认知预算在触及真实问题前已耗尽）</li>
<li class="">发现的描述是抽象的而非可操作的（开发人员不知道该做什么，默认忽略）</li>
<li class="">关卡有明显的误报历史（开发人员假设任何发现可能都是错误的）</li>
<li class="">关卡在开发人员认为非关键的问题上阻断合并（开发人员学会了“修复”AI 意味着绕过它）</li>
</ul>
<p>早期检测这一点的最重要指标是评论确认率：AI 审查评论中，有多少比例导致了代码更改或保留代码现状的记录决策。在提交质量下降之前，确认率的下降就是橡皮图章现象正在滋生的信号。</p>
<p>缓解措施：</p>
<ul>
<li class="">将每个 PR 的发现数量限制在符合人类审查带宽的阈值内（10–15 条实质性评论，而不是 80 条）</li>
<li class="">提供带有明确上下文的发现：哪一行、什么模式、为什么重要、修复方案是什么</li>
<li class="">在视觉和结构上区分建议性发现和关键性发现，以便开发人员知道哪些需要处理，哪些只需了解</li>
<li class="">长期跟踪接受率，并在其降至 30% 以下时调整阈值</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="最关键的决定">最关键的决定<a href="https://tianpan.co/zh/blog/2026-04-19-ai-cicd-gate-what-agents-can-block#%E6%9C%80%E5%85%B3%E9%94%AE%E7%9A%84%E5%86%B3%E5%AE%9A" class="hash-link" aria-label="最关键的决定的直接链接" title="最关键的决定的直接链接" translate="no">​</a></h2>
<p>问题不在于“我们能否添加一个 AI 关卡？”，而在于“我们要在哪些目前未被发现的问题上阻断合并？”大多数团队的答案分为三类：</p>
<ol>
<li class="">静态分析或 linter 已经捕获的内容（不要替换，而是叠加）</li>
<li class="">需要人类判断来评估的内容（不要自动化）</li>
<li class="">一个狭窄的中间地带：基于规则的工具漏掉的语义问题，这些问题足够可复现从而值得信任，并且足够具体从而可操作</li>
</ol>
<p>这个中间地带是 AI 关卡合适的初始范围。它比大多数团队预期的要小，这就是为什么从建议模式开始并在阻断前进行测量，是产生一个让开发人员视为信号而非阻力的关卡的唯一架构。</p>
<p>成功实现这一点的团队并不是那些相信基准测试数字的团队。他们是在自己的代码库上测量了误报率，将其调整到开发人员可以容忍的水平，并在赢得阻断权限所需的信任之前，抵制住了扩大范围的诱惑。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="AI Engineering" term="AI Engineering"/>
        <category label="CI/CD" term="CI/CD"/>
        <category label="Code Review" term="Code Review"/>
        <category label="DevOps" term="DevOps"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 编码智能体在遗留代码库上的实践：哪些有效，哪些会适得其反]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AI 编码智能体在遗留代码库上会生成外观可信但语义错误的变更。本文系统梳理了哪些任务类型可以安全迁移、智能体在哪些地方会悄然破坏隐性契约，以及让智能体辅助重构变得可靠的「特征测试优先」模式。]]></summary>
        <content type="html"><![CDATA[<p>大多数 AI 编码演示展示的是智能体从零构建一个 Todo 应用，或者干净地实现一个全新的 API。而你的代码库，却是一个有着十五年历史的单体应用：充满未文档化的隐性契约、三个团队都依赖但没人完全搞清楚的废弃依赖，以及一个从单一类起步、如今已蔓延到四十个文件的服务层。演示与现实之间的差距，不仅仅是规模问题——更是结构性问题。在把代码库的"钥匙"交给智能体之前，理解这一点，能让你避开一类既隐蔽又代价高昂的失败。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E7%BC%96%E7%A0%81%E6%99%BA%E8%83%BD%E4%BD%93%E5%9C%A8%E9%81%97%E7%95%99%E4%BB%A3%E7%A0%81%E5%BA%93%E4%B8%8A%E7%9A%84%E5%AE%9E%E8%B7%B5%EF%BC%9A%E5%93%AA%E4%BA%9B%E6%9C%89%E6%95%88%EF%BC%8C%E5%93%AA%E4%BA%9B%E4%BC%9A%E9%80%82%E5%BE%97%E5%85%B6%E5%8F%8D" alt="" class="img_ev3q"></p>
<p>AI 编码智能体确实能帮助处理遗留系统，但只在特定任务边界内才有效。超出这些边界，它们不是显眼地失败——而是生成外观可信、语法正确、语义却有误的变更，这些变更能通过代码审查，最终在生产环境中暴露出来。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="上下文窗口不是正确的心智模型">上下文窗口不是正确的心智模型<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#%E4%B8%8A%E4%B8%8B%E6%96%87%E7%AA%97%E5%8F%A3%E4%B8%8D%E6%98%AF%E6%AD%A3%E7%A1%AE%E7%9A%84%E5%BF%83%E6%99%BA%E6%A8%A1%E5%9E%8B" class="hash-link" aria-label="上下文窗口不是正确的心智模型的直接链接" title="上下文窗口不是正确的心智模型的直接链接" translate="no">​</a></h2>
<p>团队在将 AI 智能体部署到大型代码库时，犯的第一个错误是把上下文窗口当作唯一的限制。这种思路是："我们有 100 万 token 的上下文窗口，代码库有 200 万 token，只要喂进去相关的部分就行了。"这个算术漏掉了关键一点——模型并不均匀地利用上下文。</p>
<p>关于上下文利用率的研究表明，随着上下文长度增长，LLM 的性能会显著下降，并出现明显的"迷失在中间"效应：模型能可靠地关注上下文窗口开头和结尾的信息，但会忽略埋藏在中间的细节。对于遗留代码库来说，这意味着喂入"相关"文件时，往往会把最关键的上下文——某个深藏三层调用链的工具函数中的隐性约束——恰好埋到模型停止关注的地方。</p>
<p>真正的约束不是"我们能把代码库塞进上下文吗？"，而是"我们能为这个具体任务按正确顺序获取正确的上下文吗？"这是两个本质上不同的问题。前者是个硬件问题，多砸 token 就能解决；后者是检索质量问题，需要刻意的工程投入。</p>
<p>对代码库进行检索增强生成（RAG）能部分解决这个问题。没有 RAG，智能体会自由地幻想出从未存在过的内部 API 调用；有了 RAG，它们被约束在检索到的代码模式范围内。CodeRAG-Bench 的研究表明，当提供高质量上下文时，生成质量会大幅提升——但检索层往往无法获取真正有用的上下文，尤其是跨文件的关系。如果模型以高置信度检索到错误的代码片段，就会产生外观正确（因为符合代码风格）的幻想 API。</p>
<p>实际建议：把代码库上的 RAG 视为降低幻想的必要手段，而非已解决的问题。通过测试来显式审计检索质量——查询你真实的内部 API 时，是否能返回定义这些 API 的文件，而不仅仅是调用它们的文件。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="任务范围问题">任务范围问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#%E4%BB%BB%E5%8A%A1%E8%8C%83%E5%9B%B4%E9%97%AE%E9%A2%98" class="hash-link" aria-label="任务范围问题的直接链接" title="任务范围问题的直接链接" translate="no">​</a></h2>
<p>AI 编码智能体在遗留代码上稳定成功的任务，比市场宣传的要窄很多。</p>
<p><strong>高置信度任务类型：</strong></p>
<ul>
<li class="">
<p>为隔离的模块编写单元测试。智能体看到函数，为正常路径和边界条件生成测试用例，产出捕获现有行为的特征测试（characterization tests）。这是遗留代码上最可靠、最有价值的使用场景。它不需要理解系统的全局不变量——只需理解局部契约。</p>
</li>
<li class="">
<p>解释函数的作用。从遗留代码生成文档是较好的应用场景之一，因为它是只读的。智能体即使在文档注释里说错了，也不会破坏生产行为。</p>
</li>
<li class="">
<p>从单个文件中提取工具类。小范围的重构——提取目标完全包含在上下文窗口内、没有外部调用者需要追踪的情况——效果很好。智能体可以看到变更的完整影响范围。</p>
</li>
<li class="">
<p>在等效模式之间转换。将 React 中基于类的组件转换为基于 Hook 的组件，或将回调风格的函数迁移为 async/await——这些具有机械结构和明确映射关系的任务能成功，因为语义意图本身就由转换来保证。</p>
</li>
</ul>
<p><strong>高风险任务类型：</strong></p>
<ul>
<li class="">
<p>横切变更（cross-cutting changes）。任何修改共享库、公共工具函数或多个服务使用的接口的操作，都会产生上下文边界问题。智能体只能对它能看到的调用方进行推理。在大型单体应用中，它通常看不到所有调用方。结果是：变更对它分析的子集是正确的，对其余部分则悄然出错。</p>
</li>
<li class="">
<p>隐性契约修改。遗留代码充斥着未文档化的假设："这个方法只从批处理任务调用，所以运行时不需要 null 安全"；"这个字段为 0 有独立于 null 的特殊含义"。这些约束只存在于工程师的脑子里，偶尔出现在事故复盘里。智能体根本不知道它们的存在。看起来正确的重构，会悄无声息地破坏这些不变量。</p>
</li>
<li class="">
<p>依赖关系图更新。升级共享库版本、修改被广泛使用的工具函数的方法签名、修改数据库表结构——这些变更的完整影响图超出了任何上下文窗口能容纳的范围。智能体修复了眼前的调用方，却悄然破坏了三个它从未见过的下游服务。</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-生成的遗留系统代码为何以不同方式失败">AI 生成的遗留系统代码为何以不同方式失败<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#ai-%E7%94%9F%E6%88%90%E7%9A%84%E9%81%97%E7%95%99%E7%B3%BB%E7%BB%9F%E4%BB%A3%E7%A0%81%E4%B8%BA%E4%BD%95%E4%BB%A5%E4%B8%8D%E5%90%8C%E6%96%B9%E5%BC%8F%E5%A4%B1%E8%B4%A5" class="hash-link" aria-label="AI 生成的遗留系统代码为何以不同方式失败的直接链接" title="AI 生成的遗留系统代码为何以不同方式失败的直接链接" translate="no">​</a></h2>
<p>即使在全新代码库场景下，AI 生成代码的质量指标也令人警醒。有报告显示，AI 生成代码包含的重大问题大约是人工代码的 1.7 倍，安全漏洞和配置错误的比例更高。在遗留系统上，这些失败模式会叠加放大。</p>
<p>核心问题是训练数据的时效性。LLM 在特定时间点索引的代码上进行训练。GitHub Copilot 的训练截止日期意味着它对该日期之后的 API 废弃、CVE 披露或库的变更一无所知。在依赖旧版本库的遗留系统中，智能体生成的代码可能对它训练时的版本是正确的，对你锁定的版本却是错的，或者"好心"升级到了你受约束的依赖版本不支持的最新语法。</p>
<p>第二个叠加失败是模式外推。遗留代码库包含十年前惯用、如今已成反模式的写法。当智能体在检索到的上下文中大量看到这些模式时，它学会了生成更多同类代码。它不会去现代化，而是忠实地延续遗留模式，因为本地证据就是这样说的。有团队报告说，智能体在已经部分迁移到 ORM 的代码库里写出了新的 JDBC 样板代码——因为检索上下文拉出了旧层的文件。</p>
<p>部落知识（tribal knowledge）是第三个缺口。Meta 专门构建了一个由 50 多个专业智能体组成的系统，用于提取和文档化那些仅凭代码本身并不明显的非显性模式——即设计选择。在部署这些智能体之前，工程师估计 40% 的生产调试时间是由于智能体对这些模式的了解不完整而造成的。先文档化部落知识、再部署智能体，显著改善了这一状况。大多数团队跳过了这一步。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="安全模式特征测试优先">安全模式：特征测试优先<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#%E5%AE%89%E5%85%A8%E6%A8%A1%E5%BC%8F%E7%89%B9%E5%BE%81%E6%B5%8B%E8%AF%95%E4%BC%98%E5%85%88" class="hash-link" aria-label="安全模式：特征测试优先的直接链接" title="安全模式：特征测试优先的直接链接" translate="no">​</a></h2>
<p>AI 辅助遗留工作中最可靠的门控机制，是将测试优先的纪律应用于被修改的代码，而不是被生成的代码。在对任何遗留模块进行智能体辅助重构之前：</p>
<ol>
<li class="">使用智能体生成特征测试，捕获该模块当前可观测的行为——包括边界情况和错误状态。</li>
<li class="">让人工工程师审查这些测试，审查的重点不是测试断言的正确性，而是它们所覆盖的行为的完整性。这里正是部落知识发挥作用的地方：工程师为智能体无从知晓的隐性约束补充测试用例。</li>
<li class="">在现有代码上运行这些测试，它们应该通过。这个基线就是契约。</li>
<li class="">然后再进行重构。这些测试强制保证外部行为得到保留。</li>
</ol>
<p>这个模式之所以有效，是因为它将两件事分开处理：理解系统（智能体不可靠的地方）和在已理解的边界内转换系统（智能体有用的地方）。特征测试将人工工程师已知的知识正式化。</p>
<p>跳过这一步的团队，始终报告更高的缺陷率。这需要时间，但值得。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="上下文工程才是真正的约束">上下文工程才是真正的约束<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#%E4%B8%8A%E4%B8%8B%E6%96%87%E5%B7%A5%E7%A8%8B%E6%89%8D%E6%98%AF%E7%9C%9F%E6%AD%A3%E7%9A%84%E7%BA%A6%E6%9D%9F" class="hash-link" aria-label="上下文工程才是真正的约束的直接链接" title="上下文工程才是真正的约束的直接链接" translate="no">​</a></h2>
<p>AI 编码智能体在大型遗留系统上的可扩展性瓶颈不是上下文窗口的大小——而是上下文的质量。两个架构选择决定了成败：</p>
<p><strong>范围明确、任务专属的上下文。</strong> 与其加载与变更相关的所有内容，不如只加载特定任务必要的内容。一个模块内的重构任务，需要该模块的代码、它的直接调用方和它所使用的类型——而不是整个服务。按文件夹或任务范围划定的上下文文件（类似于按目录划定范围的 CLAUDE.md），优于单一的庞大上下文文件，因为它们编码的是任务相关知识，而不是全系统的背景噪音。</p>
<p><strong>任务前文档生成。</strong> 让智能体在修改模块之前先阅读并描述它，效果出人意料地好。生成的描述经过人工审查后，能浮现出隐性假设、识别出智能体本可能忽略的依赖，并强制形成两遍处理流程——第一遍智能体建立对代码的认知模型，第二遍在该模型内进行修改。加入这一步的团队报告跨模块破坏的情况明显减少。</p>
<p>这里的组织类比是新人入职。你不会在新工程师入职第一天就让他对遗留系统做重大变更，而不先让他读相关文档、和团队沟通、理解各种不变量。同样的原则适用于智能体，只不过"与团队沟通"这一步被替换为精心整理的上下文文档——其中编码了团队所知道的一切。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="任务类型决策框架">任务类型决策框架<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#%E4%BB%BB%E5%8A%A1%E7%B1%BB%E5%9E%8B%E5%86%B3%E7%AD%96%E6%A1%86%E6%9E%B6" class="hash-link" aria-label="任务类型决策框架的直接链接" title="任务类型决策框架的直接链接" translate="no">​</a></h2>
<p>判断是否对特定遗留任务部署智能体的实用启发法：</p>
<ul>
<li class=""><strong>影响范围在上下文中可见？</strong> 如果你能加载变更可能影响的完整文件集并放进上下文窗口，智能体就能对完整影响进行推理。可以推进。</li>
<li class=""><strong>隐性契约已文档化？</strong> 如果该模块有特征测试，或者部落知识已通过注释或任务专属上下文被捕获，智能体就有了所需的约束条件。可以在审查下推进。</li>
<li class=""><strong>变更跨越服务边界？</strong> 如果变更触及其他服务消费的接口，或修改了共享库的行为，在任何智能体生成的变更合并之前，都需要人工架构审查。这不是智能体审查就足够的情况。</li>
<li class=""><strong>涉及依赖变更？</strong> 任何库版本升级、数据库表结构修改或 API 契约更新，都需要人工确认。智能体可以提议变更，工程师来验证影响图。</li>
</ul>
<p>这个框架能防止最常见的失败模式：智能体生成的变更通过了静态分析、通过了类型检查、通过了现有测试，却仍然破坏了生产行为——因为测试没有覆盖智能体所不知道的不变量。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="真正随时间改善的是什么">真正随时间改善的是什么<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-brownfield-legacy-code#%E7%9C%9F%E6%AD%A3%E9%9A%8F%E6%97%B6%E9%97%B4%E6%94%B9%E5%96%84%E7%9A%84%E6%98%AF%E4%BB%80%E4%B9%88" class="hash-link" aria-label="真正随时间改善的是什么的直接链接" title="真正随时间改善的是什么的直接链接" translate="no">​</a></h2>
<p>在遗留系统上使用 AI 智能体进展最快的团队，有一个共同特征：他们将上下文工程视为持续的投入，而不是一次性的配置。每个任务周期都会产出制品——特征测试、从遗留代码生成的文档、在任务专属上下文文件中固化的部落知识——这些制品让下一次智能体运行更加可靠。</p>
<p>这种复利效应，才是真正的价值主张。第一次在文档匮乏的遗留模块上运行智能体，风险较高，需要大量人工监督。第十次运行——在特征测试已编写、文档已生成并验证、隐性契约已被代码化之后——则要安全得多。</p>
<p>错误在于期望智能体在遗留代码上立刻带来生产力提升。生产力提升会在之后到来，是在让代码库对智能体可读的投入完成之后。这种投入本身就有独立价值——它就是文档和测试——但 AI 智能体让这种投入变得更迫切，因为跳过它的代价更高了。</p>
<p>遗留代码库并非为 AI 智能体阅读而设计的。成功的团队，将"对智能体友好"视为一种需要主动培育的显性工程属性，而不是可以理所当然假设的前提。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="legacy-systems" term="legacy-systems"/>
        <category label="coding-agents" term="coding-agents"/>
        <category label="refactoring" term="refactoring"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 编程代理在遗留代码库上的表现：为什么在你最需要它们的地方，它们往往会失败]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AI 编程代理在绿地项目基准测试中表现卓越，但在处理遗留系统时，却常以微妙且难以发现的方式引发崩溃。本文将探讨其中的症结所在，并分享如何在成熟代码库中更安全地使用它们。]]></summary>
        <content type="html"><![CDATA[<p>最迫切需要 AI 编程帮助的团队，通常并不是那些正在构建全新服务（greenfield services）的团队。他们往往正在维护 2012 年产出的 50 万行 Rails 单体应用，或是处理过数十亿笔交易的 COBOL 支付系统，亦或是架构师早在三次收购前就已离职的微服务网格。在这些代码库中，一个位置不当的重构就可能引入隐蔽的数据损坏漏洞，而这些漏洞往往在三周后的生产环境中才会浮现。</p>
<p>而这恰恰是目前的 AI 编程助手（agents）失败得最惨烈的地方。</p>
<p>令人沮丧的是，这种失效模式在爆发前是隐形的。AI 助手生成的代码可以通过编译，通过现有测试，并在审查中看起来非常合理。问题往往出现在预发环境（staging）、深夜的批处理作业，或者是某个客户在月份特定日期才会触发的边缘情况中。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E7%BC%96%E7%A8%8B%E4%BB%A3%E7%90%86%E5%9C%A8%E9%81%97%E7%95%99%E4%BB%A3%E7%A0%81%E5%BA%93%E4%B8%8A%E7%9A%84%E8%A1%A8%E7%8E%B0%EF%BC%9A%E4%B8%BA%E4%BB%80%E4%B9%88%E5%9C%A8%E4%BD%A0%E6%9C%80%E9%9C%80%E8%A6%81%E5%AE%83%E4%BB%AC%E7%9A%84%E5%9C%B0%E6%96%B9%EF%BC%8C%E5%AE%83%E4%BB%AC%E5%BE%80%E5%BE%80%E4%BC%9A%E5%A4%B1%E8%B4%A5" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="全新项目基准测试陷阱">全新项目基准测试陷阱<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E5%85%A8%E6%96%B0%E9%A1%B9%E7%9B%AE%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E9%99%B7%E9%98%B1" class="hash-link" aria-label="全新项目基��准测试陷阱的直接链接" title="全新项目基准测试陷阱的直接链接" translate="no">​</a></h2>
<p>现代 AI 编程助手在 HumanEval（根据文档字符串实现函数）和 SWE-bench（修复孤立的 GitHub 问题）等任务上进行基准测试。这些基准测试几乎已经饱和——前沿模型在 SWE-bench Verified 上的得分超过 80%，而 HumanEval 已被基本攻克。</p>
<p>但最近发布的一项名为 SWE-EVO 的基准测试衡量了不同的维度：在真实遗留系统上的长周期软件演进。目前最好的模型只能完成 21% 的任务，而相比之下，它们在 SWE-bench Verified 上的完成率为 65%。这 21% 与 65% 之间的差距，真实地反映了当 AI 助手离开受控、自洽的孤立错误报告世界时，其性能是如何退化的。</p>
<p>原因在于上下文（context）。全新代码在机械意义上是自描述的：约定是明确的，依赖图能装进上下文窗口，没有缺失的内部知识。遗留代码则恰恰相反。关于一个函数可以安全执行什么的实际约束，散落在事故后分析（postmortems）、Slack 讨论串、2017 年的注释以及一位在 2020 年离职的开发者的记忆中。</p>
<p>AI 助手是在“能运行的代码”上训练出来的，而不是在“能存活的代码”上。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实践中的似是而非是什么样子的">实践中的“似是而非”是什么样子的<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E5%AE%9E%E8%B7%B5%E4%B8%AD%E7%9A%84%E4%BC%BC%E6%98%AF%E8%80%8C%E9%9D%9E%E6%98%AF%E4%BB%80%E4%B9%88%E6%A0%B7%E5%AD%90%E7%9A%84" class="hash-link" aria-label="实践中的“似是而非”是什么样子的的直接链接" title="实践中的“似是而非”是什么样子的的直接链接" translate="no">​</a></h2>
<p>CodeRabbit 对 470 个开源拉取请求（PR）的分析发现，AI 编写的代码每 PR 产生的问题比人工编写的代码多 1.7 倍。详细分类揭示了真相：逻辑错误增加了 75%，安全漏洞出现的频率是 2.74 倍，I/O 性能问题频繁了 8 倍，并发/依赖错误大约翻了一番。这些类别的问题通常无法通过审查时的惊鸿一瞥发现。它们是那种会静静地潜伏在生产环境中数周的漏洞。</p>
<p>失效模式通常可以归纳为几种典型的模式：</p>
<p><strong>未记录的不变量（Undocumented invariants）。</strong> 每个成熟的代码库都有必须在特定条件下调用的函数——例如在特定的初始化序列之后、绝不能从多个 goroutine 调用、或仅在某些配置下使用非空参数。这些不变量不在函数签名中。它们在编写者的脑海里。一个将该函数移动到新模块的 AI 助手看到了干净的代码和类型签名。它看不到那些不变量。</p>
<p><strong>隐式依赖顺序（Implicit dependency ordering）。</strong> 服务 A 写入队列。服务 B 从中读取。服务 A 恰好在服务 B 检查之前刷新（flush）。没有人记录这种时间依赖性，因为它一直有效且从未崩溃。重构刷新逻辑的 AI 助手改变了时序。现在，服务 B 在生产环境的负载下，会断断续续地看到空队列。</p>
<p><strong>看起来不像是测试缺口的测试缺口。</strong> 遗留代码通常有 60–80% 的行覆盖率，但这几乎毫无意义，因为测试的编写初衷是覆盖代码行而非行为。一个通过了测试套件的 AI 助手，对于它是否保留了系统的实际行为几乎没有验证。Meta 发现，在他们构建预计算系统来记录隐性知识之前，其 4,100 多个流水线模块中只有约 5% 具有 AI 助手可访问的上下文。</p>
<p><strong>基于 DRY 错觉的过度抽象。</strong> 当两个函数看起来相似时，AI 助手会合并它们。通常它们相似只是偶然的——底层的领域概念不同，随着需求演变，相似性会发生分歧。合并后的版本充满了条件判断。在 AI 参与度高的项目中，重复代码率从 3.1% 跃升至 14.2%，平均 file size 几乎翻倍。代码看起来“更干净”了，但也更难修改了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么标准的防御措施无法捕捉这些漏洞">为什么标准的防御措施无法捕捉这些漏洞<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%A0%87%E5%87%86%E7%9A%84%E9%98%B2%E5%BE%A1%E6%8E%AA%E6%96%BD%E6%97%A0%E6%B3%95%E6%8D%95%E6%8D%89%E8%BF%99%E4%BA%9B%E6%BC%8F%E6%B4%9E" class="hash-link" aria-label="为什么标准的防御措施无法捕捉这些漏洞的直接链接" title="为什么标准的防御措施无法捕捉这些漏洞的直接链接" translate="no">​</a></h2>
<p>最显而易见的反应是：代码审查（code review）。但在遗留代码库中，代码审查在面对 AI 生成的更改时往往会失效。审查者依赖于 AI 助手所缺乏的上下文——AI 助手输入中缺失的那些内部知识，同样也缺失在审查者检查代码时的心理模型中。</p>
<p>在 AI 编程助手普及后的 12 个月里，每个 PR 的事故增加了 23.5%，变更失败率上升了 30%。在 AI 密集的仓库中，静态分析警告增长了 18%，认知复杂度分值上升了 39%。这些指标并不像是一个如宣传般奏效的技术所应有的。</p>
<p>标准的 Lint 检查和类型检查门槛起不到作用，因为错误不是语法或类型层面的。它们是语义上的——代码的行为偏离了系统的需求，这种偏离只有在系统运行时才会显现。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="真正有效的脚手架模式">真正有效的脚手架模式<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E7%9C%9F%E6%AD%A3%E6%9C%89%E6%95%88%E7%9A%84%E8%84%9A%E6%89%8B%E6%9E%B6%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="真正有效的脚手架模式的直接链接" title="真正有效的脚手架模式的直接链接" translate="no">​</a></h2>
<p>正在这一领域取得进展的团队已经不再将 AI 代理视为自动化的工程师，而是将其视为需要结构化护栏的、速度极快的初级工程师。这种规范是架构层面的，而非提示词工程（prompt-engineering）。</p>
<p><strong>为每个 PR 设置范围限制。</strong> 将代理生成的 PR 限制在 20 个文件和 500 行新增代码以内。这并不是为了限制代理的能力，而是为了控制影响范围（blast radius），并确保人工评审是可行的。大规模的 AI 提交会掩盖严重的问题。即使代理可以一次性完成整个重构，也要将其拆分为可评审的块。</p>
<p><strong>在生成任何代码前进行只读分析。</strong> 在代理触碰代码之前，要求其生成依赖图谱，识别它计划修改的功能的所有调用点，并列举从注释、测试和提交历史中发现的不变性约束（invariants）。这一阶段可以在问题变成代码之前捕捉到“我以前不知道这一点”类的问题。它还能识别出代理缺乏足够上下文来安全操作的情况——在这些情况下，应该停止操作，而不是凭猜测继续。</p>
<p><strong>在重构前进行基准测试。</strong> AI 重构最大的风险不是代码混乱，而是隐性的行为变化——函数在边缘条件下返回的内容可能略有不同，而现有测试并未覆盖这些条件。在允许任何代理驱动的重构之前，先运行特性测试（characterization tests，记录当前行为而非正确行为的测试）。如果你因为代码太乱而无法编写特性测试，这本身就是一个信号：代理目前还不应该碰这段代码。</p>
<p><strong>针对高风险更改进行影子运行（Shadow runs）。</strong> 对于影响共享基础设施的更改，将新版本作为“影子”部署——接收真实流量，产生真实输出，但不实际执行。在切换之前，将影子输出与生产输出进行对比。虽然这种设置成本很高，但它是验证缺乏足够测试覆盖的代码是否保持行为一致的唯一方法。</p>
<p><strong>显式地预计算团队隐性知识。</strong> Meta 的方法——构建一个由 50 多个专业代理组成的系统，来记录其流水线代码库中的隐性知识——将上下文覆盖率从 5% 提高到了 100% 的模块。结果是，由于代理不再需要在运行时重新发现上下文，每个任务的工具调用次数减少了 40%。这种投入在代理的准确性上得到了回报，而不仅仅是文档质量。</p>
<p><strong>限制代理的写入权限。</strong> 对代理可以修改的文件路径使用允许列表。基础设施配置、数据库迁移文件和身份验证代码应要求显式的人工启动。一个无法意外修改迁移文件的代理，也就无法意外引入破坏数据的更改。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="代码健康度这一前提条件">代码健康度这一前提条件<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E4%BB%A3%E7%A0%81%E5%81%A5%E5%BA%B7%E5%BA%A6%E8%BF%99%E4%B8%80%E5%89%8D%E6%8F%90%E6%9D%A1%E4%BB%B6" class="hash-link" aria-label="代码健康度这一前提条件的直接链接" title="代码健康度这一前提条件的直接链接" translate="no">​</a></h2>
<p>从实践者那里得到的一个发现是一致的：AI 代理在低质量代码上的表现更差，而不仅仅是在大型代码库上。过长的函数、职责过多的类以及圈复杂度过高的模块，对于代理来说更难进行正确推理——就像对人类来说一样难。</p>
<p>这创造了一个有用的前提条件检查。在允许代理修改模块之前，测量其代码健康分。如果低于阈值（某个团队使用的是 8.5/10），则要求先由人工进行清理。这种清理提高了代理在后续自动化工作中的准确性，并减少了代理“似是而非”的错误可能隐藏的区域。</p>
<p>CodeScene 的 Adam Tornhill 将其总结为：“速度会放大设计决策的好坏。” 在结构良好、有良好测试覆盖且有显式文档的代码上工作的代理，能快速生成高质量的更改。而在混乱、隐晦、缺乏文档的代码上工作的代理，则会更快地产生混乱、隐晦、缺乏文档的更改。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="基准测试差距说明了什么">基准测试差距说明了什么<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E5%B7%AE%E8%B7%9D%E8%AF%B4%E6%98%8E%E4%BA%86%E4%BB%80%E4%B9%88" class="hash-link" aria-label="基准测试差距说明了什么的直接链接" title="基准测试差距说明了什么的直接链接" translate="no">​</a></h2>
<p>目前最顶尖模型在 SWE-bench Verified (65%) 与 SWE-EVO (21%) 表现之间存在的 44 点差距，反映了一个行业必须诚实面对的事实：我们还没有能够真正理解遗留系统的代理。我们有的只是能够正确处理孤立的、定义明确的、且代码大多自文档化的更改的代理。</p>
<p>这并不是毫无用处。在成熟的代码库中，孤立且定义明确的更改经常发生。一个能够可靠地实现遵循现有模式的新端点、或向模型添加新列并更新所有相关读取路径、或为定义明确的工具函数编写测试的代理，确实能节省大量时间。</p>
<p>错误在于范围。代理最擅长处理那些资深工程师会评价为“这基本上是机械性工作”的、边界清晰的任务。而在那些资深工程师会说“我需要仔细考虑下游影响”的任务中，它们是危险的。然而，由于业务压力，这些危险的任务往往最容易诱使人们去尝试 AI 辅助。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="展望未来">展望未来<a href="https://tianpan.co/zh/blog/2026-04-19-ai-coding-agents-legacy-codebases#%E5%B1%95%E6%9C%9B%E6%9C%AA%E6%9D%A5" class="hash-link" aria-label="展望未来的直接链接" title="展望未来的直接链接" translate="no">​</a></h2>
<p>2026 年技术现状的真相是：AI 编程代理只有在被足够的脚手架包围，且这些脚手架承担了大部分风险管理工作时，才对遗留系统有用。这些脚手架——范围限制、只读分析阶段、特性测试、影子部署、显式的团队知识文档——都是真正的工程工作。那些因为代理看起来很自信而跳过这些步骤的团队，正是那些在撰写事后分析报告的团队。</p>
<p>前进的道路并不是让代理更聪明地理解遗留代码，尽管这最终会实现。而是让遗留代码库对代理更加清晰易读：显式的不变性、记录在册的依赖关系、以及能够真实反映系统预期行为的行为测试覆盖。这些工作对人类工程师同样有益，这意味着无论代理是否能完全弥合差距，这些投入都是值得的。</p>
<p>在成熟系统中，最能从 AI 编程辅助中获益的团队，并不是那些最早采用代理的团队，而是那些投资于让代码库变得清晰易读的团队——无论是对代理，还是对下一位加入团队的人类工程师。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="software-engineering" term="software-engineering"/>
        <category label="legacy-code" term="legacy-code"/>
        <category label="developer-tools" term="developer-tools"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[生产环境中的 AI 内容溯源：C2PA、审计轨迹与工程师正在忽视的合规截止日期]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[C2PA 提供加密证明，记录谁在何时签署了 AI 生成内容。但它无法在你的 CDN 中存活，无法单独满足欧盟 AI 法案要求，也无法告诉你内容是否真实。以下是生产级内容溯源的真实面貌。]]></summary>
        <content type="html"><![CDATA[<p>当欧盟 AI 法案的透明度义务于 2026 年 8 月 2 日正式生效时，每个为欧盟用户生成合成内容的系统都需要为该内容标注机器可读的溯源信息。大多数构建 AI 产品的工程团队对此有模糊的认知，但真正搭建好所需基础设施以实现合规的团队寥寥无几——而在那些已经实施的团队中，相当一部分只完成了监管要求的一半。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%9A%84%20AI%20%E5%86%85%E5%AE%B9%E6%BA%AF%E6%BA%90%EF%BC%9AC2PA%E3%80%81%E5%AE%A1%E8%AE%A1%E8%BD%A8%E8%BF%B9%E4%B8%8E%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%AD%A3%E5%9C%A8%E5%BF%BD%E8%A7%86%E7%9A%84%E5%90%88%E8%A7%84%E6%88%AA%E6%AD%A2%E6%97%A5%E6%9C%9F" alt="" class="img_ev3q"></p>
<p>面对"AI 内容溯源"这一命题，业界的主流应对方式是指向 C2PA（内容溯源与真实性联盟标准），然后宣布问题已解决。C2PA 固然重要——它真实存在，正被 Adobe、Google、OpenAI、索尼和三星采用，是业内最接近通用标准的方案。但仅凭 C2PA 实施并不足以满足欧盟 AI 法案第 50 条。它无法在你的 CDN 中存活，也无法阻止恶意行为者为篡改内容生成"可信"的溯源记录。</p>
<p>本文将探讨生产环境中 AI 内容溯源的真实需求——技术栈、失效模式，以及让团队措手不及的合规漏洞。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="c2pa-究竟能做什么以及不能做什么">C2PA 究竟能做什么（以及不能做什么）<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#c2pa-%E7%A9%B6%E7%AB%9F%E8%83%BD%E5%81%9A%E4%BB%80%E4%B9%88%E4%BB%A5%E5%8F%8A%E4%B8%8D%E8%83%BD%E5%81%9A%E4%BB%80%E4%B9%88" class="hash-link" aria-label="C2PA 究竟能做什么（以及不能做什么）的直接链接" title="C2PA 究竟能做什么（以及不能做什么）的直接链接" translate="no">​</a></h2>
<p>C2PA 是一种用于数字资产的加密签名标准。当 AI 系统生成图像、视频或文档时，C2PA 允许系统附加一个<strong>清单</strong>——一个嵌入文件中的 JUMBF 格式元数据块——记录创建内容的工具、操作该工具的组织以及创建时间。清单使用 X.509 证书签名。任何持有公钥的人都可以验证签名，确认清单未被篡改。</p>
<p>清单包含<strong>断言</strong>：对资产的类型化、CBOR 编码的声明。与 AI 生成内容相关的断言类型包括：AI 生成披露（在 C2PA v2.1 中引入）、操作记录（执行了哪些编辑）、素材引用（使用了哪些源资产），以及内容绑定——检测篡改的文件字节加密哈希。</p>
<p>当一个 C2PA 签名的资产被用于创建另一个资产时——例如人工编辑者将 AI 生成的图像合成到设计稿中——原始清单作为新清单中引用的"素材"存在。这形成了一条<strong>溯源链</strong>：每个生成和修改事件的加密链接图，可追溯至原始来源。</p>
<p>有三点至关重要：</p>
<p><strong>C2PA 证明的是签名，而非真实性。</strong> 该标准确认的是：持有有效证书的签名者在特定时间签署了清单。它不验证 AI 生成内容是否未被篡改，不验证记录的元数据是否准确，也不验证签名者是否说了真话。实地调查已记录过 C2PA 为伪造文件和误导性剪辑内容进行加密认证的案例。该信任模型关注的是身份，而非真实性。</p>
<p><strong>C2PA 无法在元数据剥除后存活。</strong> 携带清单的 JUMBF 元数据块会被社交平台（Instagram、X、WhatsApp 在上传时均会剥除元数据）、进行自适应流转码的 CDN，以及格式转换流水线例行删除。一旦你的内容经过任何不明确保留元数据的系统，加密证明便荡然无存。</p>
<p><strong>C2PA 不足以满足欧盟 AI 法案合规要求。</strong> 法规要求采用多层方法：可见标签、机器可读的清单元数据（C2PA 满足此层），以及不可见水印（C2PA 单独并不提供）。仅实施 C2PA 会在水印要求上留下合规漏洞。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="元数据剥除问题">元数据剥除问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#%E5%85%83%E6%95%B0%E6%8D%AE%E5%89%A5%E9%99%A4%E9%97%AE%E9%A2%98" class="hash-link" aria-label="元数据剥除问题的直接链接" title="元数据剥除问题的直接链接" translate="no">​</a></h2>
<p>这是最让团队措手不及的失效模式。一个实施良好的 C2PA 签名流水线会生成加密有效的清单，这些清单能干净地嵌入源文件。然后内容进入生产环境——经过视频转码器、图像优化器、S3 → CloudFront 交付流水线，或第三方平台——清单就消失了。</p>
<p>截至 2025 年，各主要平台的处理方式差异显著：</p>
<ul>
<li class="">Instagram、X 和 WhatsApp 在上传时剥除所有元数据</li>
<li class="">TikTok 保留并显示 C2PA 凭证（早期采用者）</li>
<li class="">LinkedIn 以有限形式显示凭证</li>
<li class="">Google 搜索的"关于此图片"功能在存在 C2PA 时会读取</li>
<li class="">大多数带转码流水线的 CDN 会静默删除 JUMBF 容器</li>
</ul>
<p>视频流水线尤为脆弱。自适应码率流（HLS、DASH）以多种分辨率和码率重新编码内容，生成与原始 JUMBF 元数据毫无关联的新文件。每次重新编码都会破坏硬绑定——将清单与特定文件字节关联的加密哈希。</p>
<p>C2PA v2.1 通过<strong>软绑定</strong>部分解决了这一问题：与其使用（或单独使用）基于哈希的硬绑定，软绑定使用指纹或嵌入式水印作为标识符。水印能在重新编码和格式转换后存活。当验证器遇到没有清单的已剥除文件时，可以提取水印，查询<strong>软绑定解析 API</strong>（一个标准化的 HTTPS 端点），从外部清单存储库检索清单，并验证内容。</p>
<p>这是正确的架构：水印作为持久指针，外部清单存储库作为信息来源。但它需要同时实施 C2PA 和水印系统——这就引出了合规要求。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为何欧盟-ai-法案要求的不止-c2pa">为何欧盟 AI 法案要求的不止 C2PA<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#%E4%B8%BA%E4%BD%95%E6%AC%A7%E7%9B%9F-ai-%E6%B3%95%E6%A1%88%E8%A6%81%E6%B1%82%E7%9A%84%E4%B8%8D%E6%AD%A2-c2pa" class="hash-link" aria-label="为何欧盟 AI 法案要求的不止 C2PA的直接链接" title="为何欧盟 AI 法案要求的不止 C2PA的直接链接" translate="no">​</a></h2>
<p>欧盟 AI 法案第 50 条——AI 生成内容的透明度义务——将于 2026 年 8 月 2 日生效。它具有全球效力：只要你的系统为欧盟用户提供服务，无论公司在哪里注册，你都在其适用范围内。</p>
<p>欧盟 AI 生成内容行为准则规定，合规要求：</p>
<ol>
<li class=""><strong>可见披露</strong> — 人类可读的标签，标明内容由 AI 生成</li>
<li class=""><strong>机器可读元数据清单</strong> — C2PA 满足此层</li>
<li class=""><strong>不可见水印</strong> — C2PA 单独<strong>不</strong>满足此要求；需要嵌入内容的独立信号</li>
<li class=""><strong>内容指纹</strong> — 用于检测和去重</li>
<li class=""><strong>日志记录</strong> — 可选但建议</li>
</ol>
<p>该准则明确禁止仅依赖单一标记技术，并禁止删除水印。第 50 条违规的处罚结构为最高 750 万欧元或全球营业额的 1.5%。</p>
<p>加利福尼亚州的 AI 透明度法（SB 942，2026 年 1 月 1 日生效）对服务加利福尼亚居民的系统有类似要求：可见标签、不可感知的机器可检测水印，以及公开可访问的检测工具。加利福尼亚 AB 853 明确认可 C2PA 作为清单要求的合规机制——但水印义务是独立的。</p>
<p>实际含义：如果你已实施 C2PA 但尚未实施水印，你只完成了合规的一半。两者都需要。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="c2pa-与水印的能力矩阵">C2PA 与水印的能力矩阵<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#c2pa-%E4%B8%8E%E6%B0%B4%E5%8D%B0%E7%9A%84%E8%83%BD%E5%8A%9B%E7%9F%A9%E9%98%B5" class="hash-link" aria-label="C2PA 与水印的能力矩阵的直接链接" title="C2PA 与水印的能力矩阵的直接链接" translate="no">​</a></h2>
<p>C2PA 和水印解决的是不同问题。它们是互补关系，而非替代关系。</p>
<p>C2PA 提供丰富、可审计的溯源链。它记录谁签署了内容、使用了什么工具、在什么时间、使用了什么素材。它将各代内容关联起来。它为调查人员和合规审计员提供具有加密可验证完整性的结构化记录。它做不到的是在每个主要分发节点的剥除中存活。</p>
<p>水印则是完全相反的特性。Google 的 SynthID（部署在 Gemini 和 Imagen 中）在生成过程中将不可感知的修改嵌入像素值、音频频率或文本令牌分布中。Meta 的 Video Seal 在频域嵌入信号。这些信号能在 JPEG 重压缩、裁剪、分辨率变化和社交媒体处理后存活。SynthID 在低至 200 kbps 的视频码率下仍可检测，而 C2PA 可靠保留清单的最低码率为 500 kbps。但水印没有身份附件——它们确认涉及了 AI 生成，却无法归因于哪个组织、哪个模型版本或何时生成。</p>
<p>加密水印（一个新兴研究方向，尚未生产就绪）试图弥合这一差距：在推理过程中嵌入伪随机码，只有模型运营商才能验证。当前实现面临加密安全强度与信号损坏鲁棒性之间的根本张力——在所需错误率下同时实现两者仍是一个开放的研究问题。</p>
<p>满足监管要求且能在实际分发中存活的生产架构是：用于溯源链的 C2PA 清单，辅以用于剥除弹性的水印，水印注册为指向外部托管清单存储库的软绑定。这正是 Google（C2PA + SynthID）和 Adobe（C2PA + 软绑定水印）已实施的方案。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建生产级溯源系统">构建生产级溯源系统<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#%E6%9E%84%E5%BB%BA%E7%94%9F%E4%BA%A7%E7%BA%A7%E6%BA%AF%E6%BA%90%E7%B3%BB%E7%BB%9F" class="hash-link" aria-label="构建生产级溯源系统的直接链接" title="构建生产级溯源系统的直接链接" translate="no">​</a></h2>
<p>如果你正在构建需要满足这些要求的 AI 内容生成系统，基础设施可分解为五个组件：</p>
<p><strong>签名服务。</strong> 一个具备 HSM 支持私钥存储的专用微服务负责清单签名。它必须与推理流水线分离——在生成量规模下进行签名需要基于队列的异步架构。证书生命周期管理（轮换、吊销、OCSP 可用性）需要明确的运营所有权。如果你运营多租户平台，租户证书路由需要专门设计：C2PA 信任列表按签名者授予信任，而非按平台。</p>
<p><strong>清单存储库。</strong> C2PA 清单应存储在独立于媒体文件本身的外部不可变存储中。存储库以哈希为索引：任何验证器都可以使用文件哈希或水印 ID 查询以检索关联清单。这是文件在传输过程中被剥除清单后的信息来源。将其设计为一次写入、读取时可 CDN 分发，并在存储层进行多租户隔离。</p>
<p><strong>水印服务。</strong> 水印嵌入在推理时发生——信号在内容生成时引入，而非作为后处理步骤。水印 ID 与关联的清单 URL 一起在清单存储库中注册。软绑定解析 API 将水印映射到清单，使验证器能够恢复已剥除文件的溯源信息。</p>
<p><strong>溯源审计数据库。</strong> 独立于 C2PA 清单存储，这是操作记录：内容 ID、模型版本、时间戳、提示哈希（非提示文本——隐私考虑）、签名者证书指纹、租户 ID、父素材引用和分发事件。使用只追加事件日志。Kafka → ClickHouse 或 BigQuery 是常见模式。当合规审计员要求提供你的系统正确标记内容的证据时，这就是你提供的内容。</p>
<p><strong>验证 API。</strong> 一个接受文件哈希或水印 ID 并返回验证状态（未知/有效/可信/已泄露）的 HTTPS 端点，为透明度 UI、下游合作伙伴集成和内部合规监控提供支持。</p>
<p>数据流如下：推理生成内容 → 水印服务嵌入信号 → 签名服务创建包含 AI 生成断言、模型版本、时间戳和软绑定引用的 C2PA 清单 → 清单存储在清单存储库中 → 媒体以嵌入的 JUMBF + 水印交付 → 异步写入审计日志事件。当内容经过剥除 CDN 时，水印持续存在；验证器提取它，查询解析 API，检索清单，并验证内容哈希。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="素材链问题">素材链问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#%E7%B4%A0%E6%9D%90%E9%93%BE%E9%97%AE%E9%A2%98" class="hash-link" aria-label="素材链问题的直接链接" title="素材链问题的直接链接" translate="no">​</a></h2>
<p>AI 内容很少孤立存在。AI 生成的图像被合成到营销视频中。AI 撰写的段落被编辑并纳入更长的文档。翻译文章使用 AI 生成的部分。这些衍生关系中的每一个都创建了 C2PA 嵌套清单存储旨在跟踪的素材关系。</p>
<p>实践中，素材链创建了图形结构的数据，关系型数据库对此支持不佳。当合规审计员询问"给我展示这篇已发布文章的完整溯源"时，答案可能需要跨数十个中间资产遍历素材引用图。图形数据库配合 SPARQL 查询比 SQL 联接更适合此场景。</p>
<p>关键不变量：每个重新处理步骤都必须重新签署清单，引用前一个清单作为素材。这意味着签名基础设施必须存在于处理流水线的每个阶段——不仅仅是在初始生成时。链中的任何空白都会产生不完整的溯源记录，这是合规和审计风险。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="c2pa-无法防护的情况">C2PA 无法防护的情况<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#c2pa-%E6%97%A0%EF%BF%BD%E6%B3%95%E9%98%B2%E6%8A%A4%E7%9A%84%E6%83%85%E5%86%B5" class="hash-link" aria-label="C2PA 无法防护的情况的直接链接" title="C2PA 无法防护的情况的直接链接" translate="no">​</a></h2>
<p>在所有技术基础设施就位的情况下，有必要明确其局限性。</p>
<p><strong>C2PA 无法检测签名前的篡改。</strong> 如果内容在清单签署前被篡改，生成的清单会准确记录对篡改内容的签名事件。加密证明是有效的，内容仍然是虚假的。</p>
<p><strong>C2PA 不具备追溯性。</strong> 你的系统在溯源基础设施部署前生成的任何 AI 内容都没有溯源记录。AI 检测器——其误报率已记录超过 20%——是唯一的追溯选项，且在规模上不可靠。</p>
<p><strong>C2PA 无法覆盖开源推理。</strong> 本地运行的 Stable Diffusion、在消费者硬件上运行的微调模型，以及没有溯源实现的 API 可访问模型，生成的内容没有清单。这些代表了恶意行为者阻力最小、流量最大的路径。整个 C2PA 和水印生态系统依赖于对开源模型权重无法强制执行的生产者参与。</p>
<p><strong>身份层创造了监控风险。</strong> C2PA 允许（在某些应用中要求）将签名者身份附加到内容上。对于记者、举报人和人权工作者来说，打击虚假信息的同一基础设施可能被武器化用于国家支持的身份识别。世界隐私论坛记录了清单中自动嵌入的 GPS 坐标和时间戳如何暴露位置数据，以及无法编辑的操作断言如何为签名内容创建永久编辑历史。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="你面临的合规时间线">你面临的合规时间线<a href="https://tianpan.co/zh/blog/2026-04-19-ai-content-provenance-c2pa#%E4%BD%A0%E9%9D%A2%E4%B8%B4%E7%9A%84%E5%90%88%E8%A7%84%E6%97%B6%E9%97%B4%E7%BA%BF" class="hash-link" aria-label="你面临的合规时间线的直接链接" title="你面临的合规时间线的直接链接" translate="no">​</a></h2>
<p>2026 年 8 月 2 日的欧盟 AI 法案第 50 条生效日期并非理论。GPAI（通用 AI）透明度义务，涵盖模型提供者，已于 2025 年 8 月 2 日生效。通过第三方 API 提供 AI 功能的组织通常将自己错误分类为"部署者"（较轻要求），而实际上他们是"GPAI 系统提供者"（较重要求）。首先确定正确的分类；所有技术决策都由此产生。</p>
<p>实施完整的溯源基础设施——价值链分类、C2PA 签名流水线、水印集成、外部清单存储库、软绑定注册，以及 C2PA 信任列表的合规认证——对于不从零开始的团队而言，现实所需最少三到六个月。现在开始的团队正在与紧迫的截止日期赛跑。</p>
<p>参考实现状况良好。Rust SDK（<code>c2pa-rs</code>，在 <code>contentauth</code> GitHub 组织下维护）是参考实现，通过 WebAssembly 可无缝用于浏览器端验证。OpenAI、Adobe Firefly 和 Google Imagen 已有生产级 C2PA 实现可供架构参考。Midjourney 截至 2026 年初尚未实施 C2PA——考虑到其体量，这是一个显著的缺口，也表明行业整体采用在很大程度上仍是自愿而非强制。</p>
<p>内容溯源问题是真实存在的，工具已足够成熟可以解决它。滞后的是工程团队将其视为合规复选框——而非核心系统设计要求：一个具有失效模式、运营开销和架构影响的要求，需要从一开始就设计到系统中，而非在监管截止日期前一个月仓促附加。</p>
<hr>
<p><strong>关键参考资料：</strong></p>
<ul>
<li class="">C2PA 规范 2.2：spec.c2pa.org</li>
<li class="">欧盟 AI 法案第 50 条：artificialintelligenceact.eu/article/50/</li>
<li class="">C2PA Rust SDK：github.com/contentauth/c2pa-rs</li>
<li class="">欧盟 AI 生成内容行为准则：digital-strategy.ec.europa.eu</li>
</ul>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="production" term="production"/>
        <category label="compliance" term="compliance"/>
        <category label="security" term="security"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[为什么用户会忽略你花了三个月构建的 AI 功能]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AI 功能之所以失败，不是因为模型不好，而是因为用户从未发现它们、不信任它们，或者没有养成使用它们的习惯。以下是解决方法。]]></summary>
        <content type="html"><![CDATA[<p>你的团队花了三个月时间将 LLM 集成到产品中。模型运行正常，延迟在可接受范围内，演示效果也非常棒。你上线了产品，然后眼睁睁地看着使用率指标停留在 4% 不动了。</p>
<p>这是一个典型的过程。大多数 AI 功能的失败并非发生在模型层面，而是在采用（adoption）层面。其根本原因并非技术问题，而是一系列围绕可发现性（discoverability）、信任和习惯养成而做出（或未做出）的产品决策。理解为什么采用率会失败，以及实际上应该衡量和改变什么，是交付“有用 AI”的团队与仅交付“令人印象深刻的演示”的团队之间的分水岭。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E4%B8%BA%E4%BB%80%E4%B9%88%E7%94%A8%E6%88%B7%E4%BC%9A%E5%BF%BD%E7%95%A5%E4%BD%A0%E8%8A%B1%E4%BA%86%E4%B8%89%E4%B8%AA%E6%9C%88%E6%9E%84%E5%BB%BA%E7%9A%84%20AI%20%E5%8A%9F%E8%83%BD" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="按频率排序的三种失败模式">按频率排序的三种失败模式<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E6%8C%89%E9%A2%91%E7%8E%87%E6%8E%92%E5%BA%8F%E7%9A%84%E4%B8%89%E7%A7%8D%E5%A4%B1%E8%B4%A5%E6%A8%A1%E5%BC%8F" class="hash-link" aria-label="按频率排序的三种失败模式的直接链接" title="按频率排序的三种失败模式的直接链接" translate="no">​</a></h2>
<p>问问你自己，你的 AI 功能在漏斗的哪个环节出现了断裂。这里有三种截然不同的失败模式，每种模式都需要不同的修复方案。</p>
<p><strong>失败模式 1：用户从未发现该功能的存在。</strong> 该功能隐藏在一个用户从未点击过的按钮后面，或者在他们从未打开过的设置面板中，抑或是作为在新手引导（onboarding）过程中仅出现一次且再未露面的工具提示（tooltip）。可发现性不仅是位置问题，也是框架问题。“AI 助手” 毫无意义，而 “帮我起草这封邮件” 则是用户现在就可以采取的具体行动。</p>
<p><strong>失败模式 2：用户尝试了一次该功能便弃之不用。</strong> 这属于信任层面的失败。用户运行了一个查询，得到了一个感觉不可靠或完全错误的答案，于是判定验证输出结果的成本超过了亲自动手完成任务的成本。对于许多 AI 功能来说，这是正确的理性计算。如果错误率高到用户必须检查每一个输出，那么你构建的工具只是增加了一个步骤，而不是减少了一个。</p>
<p><strong>失败模式 3：用户使用了该功能但没有再次回访。</strong> 该功能产生了一次价值，但未能演变成一种习惯。用户需要重复、可靠的成功体验，行为才能变得自动化。仅仅一次良好的体验是不够的——你需要奖励是一致的，且触发机制是自然的。</p>
<p>每种失败模式在分析数据中都有不同的特征。高激活率但低二次使用率指向失败模式 3。低激活率且激活用户没有明显规律则指向失败模式 1。首次使用后立即出现的高跳出率指向失败模式 2。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="部署正确的指标衡量">部署正确的指标衡量<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E9%83%A8%E7%BD%B2%E6%AD%A3%E7%A1%AE%E7%9A%84%E6%8C%87%E6%A0%87%E8%A1%A1%E9%87%8F" class="hash-link" aria-label="部署正确的指标衡量的直接链接" title="部署正确的指标衡量的直接链接" translate="no">​</a></h2>
<p>标准的产品分析并不适用于 AI 功能。页面浏览量和按钮点击次数无法告诉你 AI 是否真的有用。你需要以不同的方式部署埋点。</p>
<p>关键指标分为三类：</p>
<p><strong>交互质量指标：</strong></p>
<ul>
<li class="">建议采纳率（suggestion acceptance rate）：用户保留、编辑或放弃 AI 建议的百分比。</li>
<li class="">后续行动率（follow-up rate）：用户是否根据 AI 输出采取了行动，还是直接关闭了面板。</li>
<li class="">重试率（retry rate）：用户是否重新输入了提示词（re-prompt），这信号表明第一条回复不令人满意。</li>
</ul>
<p><strong>下游影响指标：</strong></p>
<ul>
<li class="">比较 AI 辅助流与非辅助流的任务完成率。</li>
<li class="">衡量在有 AI 支持的情况下完成任务所需的时间。</li>
<li class="">留存率关联性——使用 AI 功能是否能预测 30 天留存率？</li>
</ul>
<p><strong>采用漏斗指标：</strong></p>
<ul>
<li class="">功能激活率（有多少符合条件的用户曾经使用过该功能）。</li>
<li class="">二次使用率（在那些使用过一次的用户中，有多少人在 7 天内再次使用）。</li>
<li class="">核心用户占比（每周使用该功能超过 N 次的用户）。</li>
</ul>
<p>大多数团队只追踪激活率，别无其他。这会产生一种误导性的画面：如果位置显眼，一个功能可能显示出不错的激活率，而由于输出质量不够好，二次使用率仅为 8%。如果没有完整的漏斗分析，你可能会把工程时间浪费在可发现性上，而实际问题却是质量。</p>
<p>在做出任何产品更改之前，先建立一个 4 到 6 周的基准线。按用户群组、获客渠道和角色进行细分——不同类型的用户采用模式差异巨大，汇总数据会掩盖哪些细分市场实际上正在参与其中。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="可发现性不仅是位置问题">可发现性：不仅是位置问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E5%8F%AF%E5%8F%91%E7%8E%B0%E6%80%A7%E4%B8%8D%E4%BB%85%E6%98%AF%E4%BD%8D%E7%BD%AE%E9%97%AE%E9%A2%98" class="hash-link" aria-label="可发现性：不仅是位置问题的直接链接" title="可发现性：不仅是位置问题的直接链�接" translate="no">​</a></h2>
<p>本能反应是增加一个显眼的按钮，发起邮件营销，或者增加一个新手引导步骤。这些固然有帮助，但还不够。可发现性有两个维度：用户需要知道该功能的存在，并且他们需要理解该功能对他们的具体作用。</p>
<p>通用的入口点（“试试我们的新 AI！”）的表现一贯不如上下文相关的触发器。在用户正要开始一项 AI 可以提供帮助的任务时准确出现的提示，其转化率远高于侧边栏中的任何按钮。如果你构建了一个可以总结文档的 AI，触发器应该在用户打开长文档时出现，而不是出现在导航栏中。</p>
<p>上下文触发器比静态 UI 需要更多的产品工作，因为它们需要推断用户状态。但其带来的采用率差异足够显著，通常值得投资。从 AI 能提供最清晰、最快价值的两到三个用户任务开始，专门为这些时刻设计触发器。</p>
<p>渐进式披露（progressive disclosure）同样适用于功能传达以及 UI 设计。不要试图在新手引导弹窗中解释 AI 能做的一切。展示它现在能做的一件事，让他们体验到一次成功，并随着他们的深入参与展示更多功能。目标是让能力的揭示与信任的积累相匹配。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="信任脚手架降低验证成本">信任脚手架：降低验证成本<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E4%BF%A1%E4%BB%BB%E8%84%9A%E6%89%8B%E6%9E%B6%E9%99%8D%E4%BD%8E%E9%AA%8C%E8%AF%81%E6%88%90%E6%9C%AC" class="hash-link" aria-label="信任脚手架：降低验证成本的直接链接" title="信任脚手架：降低验证成本的直接链接" translate="no">​</a></h2>
<p>用户对 AI 的不信任并非源于对 AI 认识论的深思熟虑。他们的不信任是因为曾被“坑”过：他们信任了 AI 的输出，结果输出是错的，导致后续环节出了问题。验证成本的计算非常简单：如果我横竖都要复核每一项 AI 输出，那么 AI 就没有为我节省任何精力。</p>
<p>信任脚手架是指一套旨在降低用户信任 AI 输出的感知成本的设计选择。具体技术包括：</p>
<p><strong>展示工作过程。</strong> 如果 AI 总结了一篇文档，请链接到原文出处。如果它生成了代码建议，请用一句话解释它的逻辑。用户更愿意信任那些可以抽样检查的输出，而不是凭空出现的输出。这对于高风险决策尤为重要。</p>
<p><strong>明确置信度。</strong> 一个偶尔会说“我对此不太确定”的系统，比一个对所有输出都表现出同等自信的系统更值得信赖。用户会学会校准预期。一个从未表达过不确定性的系统会侵蚀信任，因为用户无法判断什么时候该担心。</p>
<p><strong>从低风险场景开始。</strong> 不要首先在用户最关键的工作流程中定位你的 AI 功能。让用户在一次性或易于撤销的任务中接触它。第一印象对信任校准的影响比后续任何体验都大。</p>
<p><strong>让撤销变得简单。</strong> 当用户知道可以随时撤销结果时，信任 AI 输出的成本会显著降低。一键撤销是一项关乎信任的功能。</p>
<p><strong>优雅降级。</strong> 当 AI 确实无法提供帮助时，请明确告知并提供非 AI 的路径。一个静默失败（产生错误输出却未标记不确定性）的功能比一个大声宣告失败的功能更能迅速摧毁信任。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="习惯养成工程化循环">习惯养成：工程化循环<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E4%B9%A0%E6%83%AF%E5%85%BB%E6%88%90%E5%B7%A5%E7%A8%8B%E5%8C%96%E5%BE%AA%E7%8E%AF" class="hash-link" aria-label="习惯养成：工程化循环的直接链接" title="习惯养成：工程化循环的直接链接" translate="no">​</a></h2>
<p>习惯是在暗示（cue）下发生的行为，无需刻意决策。要让 AI 功能成为习惯，必须满足三个条件：暗示在用户的工作流中定期出现、操作无摩擦，以及奖励足够一致以至于用户的大脑会更新其预期。</p>
<p>暗示是最难把握的部分。如果用户只有在主动寻找时才会遇到你的 AI 功能，它永远不会成为习惯——因为主动寻找本身就需要决策。暗示必须来自产品或用户的环境，而不是来自用户的记忆。</p>
<p>GitHub Copilot 的成功部分归功于其暗示是不可避免的：每次你打开文件并开始打字时，Copilot 已经在提供建议了。操作（接受建议）只需要按一下键。奖励（更快的代码编写速度）是即时的。这种循环在每个会话中运行数十次。这种架构极度有利于习惯的养成。</p>
<p>大多数 AI 功能的循环架构并不理想。暗示需要用户记住该功能的存在，操作包含多个步骤，而奖励则是延迟的或难以归功。如果你是在代码编辑器之外进行构建，则必须更努力地去工程化这个循环。</p>
<p>强化习惯循环的具体技术：</p>
<ul>
<li class="">
<p><strong>将功能引入用户的现有工作流。</strong> 如果用户主要在 Slack 中工作，就将 AI 触发器放在 Slack 中。如果他们在处理邮件，就在那里集成。每一次环境切换都是习惯中断的机会。</p>
</li>
<li class="">
<p><strong>让第一次有意义的交互尽可能短。</strong> 意图与结果之间的每一个额外步骤都会侵蚀习惯循环。减少提示语、预填上下文，并削减任何发生在“我想要 AI 帮助”和“我得到了有用的东西”之间的用户体验环节。</p>
</li>
<li class="">
<p><strong>让改进显而易见。</strong> 习惯的强度与奖励的清晰度成正比。如果 AI 为用户节省了 20 分钟但用户没有意识到，习惯就不会养成。使用情况摘要、明确的节省时间估算和对比指标有助于用户认识到他们获得的价值。</p>
</li>
<li class="">
<p><strong>谨慎使用通知和连续达标（streaks）。</strong> 这些手段对某些产品和人群有效，但会引起其他人的反感。应通过具有明确指标的 A/B 测试来验证，而不是假设它们能提升参与度。</p>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="运行位置与框架实验">运行位置与框架实验<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E8%BF%90%E8%A1%8C%E4%BD%8D%E7%BD%AE%E4%B8%8E%E6%A1%86%E6%9E%B6%E5%AE%9E%E9%AA%8C" class="hash-link" aria-label="运行位置与框架实验的直接链接" title="运行位置与框架实验的直接链接" translate="no">​</a></h2>
<p>一旦你拥有了基础的埋点分析，位置与框架实验就是你能利用的最高杠杆。同一个功能放在不同的位置，或者使用不同的文案，其激活率可能会有天壤之别。</p>
<p>一个务实的实验序列：</p>
<ol>
<li class="">
<p><strong>框架测试。</strong> 准备三到五种不同的功能描述，并衡量哪一种能驱动首次使用。宽泛的描述（如“AI 助手”）几乎总是输给具体的描述（如“将此内容总结为 3 个要点”）。描述用户将获得什么的行动导向框架，优于描述功能为何存在的利益导向框架。</p>
</li>
<li class="">
<p><strong>位置测试。</strong> 测试在用户主要工作流中的内联入口、作为上下文触发器以及在专门页面上的效果。上下文触发器通常会胜出，但其影响程度因产品而异。</p>
</li>
<li class="">
<p><strong>时机测试。</strong> 在用户会话的不同时间点放置相同的触发器，其转化率也不同。在会话初期，用户处于熟悉环境的阶段；而在会话中期，当他们正在积极工作时，上下文触发器更容易被接受。</p>
</li>
<li class="">
<p><strong>受众细分测试。</strong> 新用户和资深用户对 AI 功能引入的反应不同。资深用户通常希望立即获得能力；新用户则首先需要信任脚手架。考虑为不同的群体设计不同的引入路径。</p>
</li>
</ol>
<p>按顺序运行这些实验，并衡量其对整个采用漏斗的影响，而不仅仅是即时的激活事件。如果框架的改变让激活率翻倍但让二次使用率减半，那么这可能并不是一次胜利。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="什么是良好的采用表现">什么是良好的采用表现<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-adoption-why-users-dont-use#%E4%BB%80%E4%B9%88%E6%98%AF%E8%89%AF%E5%A5%BD%E7%9A%84%E9%87%87%E7%94%A8%E8%A1%A8%E7%8E%B0" class="hash-link" aria-label="什么是良好的采用表现的直接链接" title="什么是良好的采用表现的直接链接" translate="no">​</a></h2>
<p>当一个 AI 功能奏效时，其采用漏斗大致如下：在符合条件的第一周内，有显著比例的符合条件的用户完成激活；7 天内的二次使用率超过 40%；并且该功能出现在留存模型中，作为长期参与度的预测指标。</p>
<p>GitHub Copilot 作为经过最严谨研究的 AI 产品，展示了可能达到的高度：90% 的财富 100 强企业采用了它，而在已激活的用户中，测得的生产力提升非常显著，以至于开发者们会积极拥护这款工具。但 Copilot 拥有结构性优势 —— 紧密的工作流集成、即时且可衡量的价值，以及一个本就倾向于采用工具的用户群体（开发者）。</p>
<p>对于没有这些结构性优势的功能，成功看起来则有所不同。现实的目标在很大程度上取决于你所属的领域，但总的来说：符合条件用户的激活率低于 20% 通常表明存在可发现性或信任问题，这在进行任何其他投入之前都值得优先解决。二次使用率低于 30% 则表明存在质量或习惯循环问题。</p>
<p>成功的 AI 功能发布的共同点是，团队将“采用率”视为一个工程问题 —— 而非市场部门的工作，也不是功能上线后就会自然而然发生的事情。他们监测正确的指标，识别具体的失败模式，并针对控制采用率的产品决策进行迭代。这就是工作的核心所在。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai engineering" term="ai engineering"/>
        <category label="product engineering" term="product engineering"/>
        <category label="ux" term="ux"/>
        <category label="adoption" term="adoption"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[当你的 AI 功能过时：生产环境中的知识切断与时间溯源]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[基于具有固定训练切断点模型构建的产品，会随着世界与训练数据的偏离而失效。本文将介绍如何检测由知识切断引起的故障、管理 RAG 的新鲜度，并在时间漂移演变为隐蔽的生产回归之前进行针对性设计。]]></summary>
        <content type="html"><![CDATA[<p>你的 AI 功能在第三季度上线了。评估结果看起来不错。用户很满意。六个月后，满意度评分下降了 18 分，但你的仪表盘依然显示 99.9% 的可用性和低于 200 毫秒的延迟。没有任何地方看起来坏了。从传统意义上讲，也没有任何地方<em>真的</em>坏了。模型在响应，基础设施很健康。只是这个功能在悄无声息地出错。</p>
<p>这就是生产环境 AI 系统中“时间衰减”（temporal decay）的样子。它不会通过报错来提醒你。它以模型所知与现实世界现状之间的差距形式不断累积——等到你的支持队列反映出这一点时，损害已经持续数月之久。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E5%BD%93%E4%BD%A0%E7%9A%84%20AI%20%E5%8A%9F%E8%83%BD%E8%BF%87%E6%97%B6%EF%BC%9A%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%9A%84%E7%9F%A5%E8%AF%86%E5%88%87%E6%96%AD%E4%B8%8E%E6%97%B6%E9%97%B4%E6%BA%AF%E6%BA%90" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="知识截止并非单一的时间点">知识截止并非单一的时间点<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E7%9F%A5%E8%AF%86%E6%88%AA%E6%AD%A2%E5%B9%B6%E9%9D%9E%E5%8D%95%E4%B8%80%E7%9A%84%E6%97%B6%E9%97%B4%E7%82%B9" class="hash-link" aria-label="知识截止并非单一的时间点的直接链接" title="知识截止并非单一的时间点的直接链接" translate="no">​</a></h2>
<p>“知识截止”（knowledge cutoff）这个词暗示了一个清晰的界限：模型知道日期 X 之前的一切，而对之后的事情一无所知。现实情况则更加复杂，也更加危险。</p>
<p>训练语料库是异质的。一个模型的有效知识边界取决于你询问的是哪个子领域。对主要前沿模型的研究发现，即使在同一个模型内部，不同子资源（sub-resource）的有效截止日期也有显著差异。一个标榜知识截止到 2024 年 12 月的模型，在通用新闻方面可能确实能达到 2024 年，但在你特定的监管领域，有效截止日期可能仅为 2022 年，因为该领域的内容在训练数据中代表性不足。</p>
<p>这意味着你在营销文案中看到的截止日期，并非你的功能实际在使用的截止日期。寻找真实边界的方法是经验主义的：构建一套与特定日期挂钩的已知答案的小型探测问题集，在部署时运行，并测量准确率下降的位置。供应商不会告诉你这些，但你的用户最终会告诉你。</p>
<p>除了初始的截止日期，还有一个更缓慢的次生问题：<strong>时间对齐</strong>（temporal grounding）。对多代大语言模型（LLM）的研究发现，与绝对日期查询相比，日期相对查询（date-relative queries）的准确率下降了 23–35%。当用户询问“HIPAA 合规性<em>最近</em>有什么变化？”时，模型必须推理出什么算作“最近”，将其锚定在它对当前日期的理解上，并据此检索信息。这三个步骤都是潜在的失败点。模型会系统性地错估相对时间参考，因为它们对“现在”的训练信号是被冻结的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么这会悄无声息地失败">为什么这会悄无声息地失败<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E4%BC%9A%E6%82%84%E6%97%A0%E5%A3%B0%E6%81%AF%E5%9C%B0%E5%A4%B1%E8%B4%A5" class="hash-link" aria-label="为什么这会悄无声息地失败的直接链接" title="为什么这会悄无声息地失败的直接链接" translate="no">​</a></h2>
<p>传统监控对时间衰减是盲目的，因为它测量的是系统行为，而非回答质量。你的 APM 仪表盘关注的是错误率、延迟百分位数和 Token 吞吐量。当你的模型对截止日期三个月后发生的调价给出陈旧回答时，这些指标都不会发生波动。</p>
<p>生产事故的失败模式是一致的：系统显示 99% 的可用性，同时提供错误的信息，唯一的信号是用户信任的逐渐瓦解。一家家电制造商的 AI 客服机器人（运行在不了解更新后的维修流程的模型上）将多套指令集组合成了语无伦次的指导。系统在每个可观察的指标上都显得很健康，但用户就是无法按照维修步骤操作。</p>
<p>这正是时间衰减比大多数生产故障更危险的地方：它是一个语义问题，而非运维问题。你现有的告警基础设施是围绕运维异常构建的。</p>
<p>有三类问题在没有新鲜度处理的情况下，不应直接路由给原生 LLM：</p>
<ul>
<li class=""><strong>政策与合规性问题</strong>：税法、监管要求、许可条款——这些都有明确的日期，且实质内容变动频繁。</li>
<li class=""><strong>现状问题</strong>：市场价格、产品可用性、公司信息、人事变动。</li>
<li class=""><strong>相对时间问题</strong>：没有明确日期锚点的“最近”、“当前”、“最新”、“新”。</li>
</ul>
<p>如果你的功能预期用途包含其中任何一类，你就面临时间对齐风险。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="检测由截止日期引起的故障">检测由截止日期引起的故障<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E6%A3%80%E6%B5%8B%E7%94%B1%E6%88%AA%E6%AD%A2%E6%97%A5%E6%9C%9F%E5%BC%95%E8%B5%B7%E7%9A%84%E6%95%85%E9%9A%9C" class="hash-link" aria-label="检测由截止日期引起的故障的直接链接" title="检测由截止日期引起的故障的直接链接" translate="no">​</a></h2>
<p>检测需要你在现有的运维指标之外增加质量评估。以下三种方法在不同的成本点上都行之有效。</p>
<p><strong>探测查询 (Probe queries)</strong>。创建一小组具有可验证答案的日期锚定问题：即在模型截止日期之后发生的变化。将这些作为“金丝雀”（canary）与常规流量并行运行，并跟踪准确率随时间的变化。随着世界与截止日期的偏离越来越远，金丝雀的准确率应呈预测模式下降。剧烈下降可能预示着特定领域的时效性已实质性恶化。</p>
<p><strong>时间异常检测</strong>。在你的应用程序中增加监测，以检测用户查询何时包含时间性词汇（如“当前”、“最近”、“截至今天”），并标记这些请求进行质量抽样。询问时间相对问题的用户是受截止日期失效影响风险最高的人群。对一定比例的此类请求进行人工或自动化审核，并跟踪正确回答与陈旧回答随时间变化的比例。</p>
<p><strong>检索管道中的新鲜度评分</strong>。如果你正在使用 RAG，你的检索层应在相关性分数之外输出新鲜度元数据。对于询问“当前最佳实践”的查询，8 个月前更新的文档与询问基础概念的查询相比，应具有不同的权重。在检索时进行陈旧度评分（计算更新后的天数除以该文档类型可接受的更新频率），为你提供了一个具体的告警指标。当检索到的文档平均陈旧度超过阈值时，就是一个值得叫醒相关人员处理的信号。</p>
<p>LLMLagBench 的研究方法为生产抽样提供了一个系统的补充：通过从新闻档案中构建密集的时间探测集，你可以精确识别模型性能发生拐点的位置——不仅是官方的截止日期，还有每个领域实际的有效边界。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rag-无法自动解决这个问题">RAG 无法自动解决这个问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#rag-%E6%97%A0%E6%B3%95%E8%87%AA%E5%8A%A8%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98" class="hash-link" aria-label="RAG 无法自动解决这个问题的直接链接" title="RAG 无法自动解决这个问题的直接链接" translate="no">​</a></h2>
<p>团队通常将 RAG 视为显而易见的解决方案：如果模型的知识是静态的，就增加检索功能，使其能够访问新鲜信息。这种直觉是正确的，但 RAG 引入了其特有的时间性故障模式，而大多数实现都忽略了这一点。</p>
<p><strong>向量索引会衰减。</strong> 当你在索引时对文档进行嵌入（embedding）时，这些嵌入反映的是该时间点的文档内容。如果政策文档更新了，旧的嵌入仍留在索引中，检索到的将是过时的内容。如果没有显式的索引维护，你的 RAG 系统积累“时间债务”的速度，正等同于源语料库的变化速度。</p>
<p>过时问题之所以严重，是因为它是隐形的。检索成功了 —— 你得到了文档，评分看起来很正常 —— 但返回的文档可能是 14 个月前最后更新的，而它们描述的政策在此期间已经修订过两次了。</p>
<p>将向量索引视为动态基础设施而非一次性 ETL 任务需要：</p>
<ul>
<li class=""><strong>计划性过时扫描。</strong> 每天（或者对于高波动领域更频繁地）根据适用于该文档类型的过时阈值扫描已索引的文档。法律文件可能有 30 天的阈值；定价数据可能需要每小时扫描。超过阈值的文档将被标记并从活动检索中移除，直到它们经过重新认证或更新。</li>
<li class=""><strong>变更数据捕获（CDC）集成。</strong> 如果你的真相源数据存储在数据库中，请将索引更新视为该数据库变更日志的下游。当源文档发生变化时重新生成嵌入，而不是按照可能错过突发变化的固定时间表进行。</li>
<li class=""><strong>增强层中的新鲜度元数据。</strong> 在根据检索到的片段构建提示词（prompt）时，将源时间戳与内容一并包含在内。“根据 2026 年 4 月更新的文档……”能为模型和用户提供单纯内容无法传递的信息年龄信号。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="没人会问的发布设计问题">没人会问的发布设计问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E6%B2%A1%E4%BA%BA%E4%BC%9A%E9%97%AE%E7%9A%84%E5%8F%91%E5%B8%83%E8%AE%BE%E8%AE%A1%E9%97%AE%E9%A2%98" class="hash-link" aria-label="没人会问的发布设计问题的直接链接" title="没人会问的发布设计问题的直接链接" translate="no">​</a></h2>
<p>大多数时间性故障在发布前跳过的需求分析中是可预见的。六个月后，它们看起来就像是无声的回归。在发布前值得问的三个问题：</p>
<p><strong>该功能的正确答案的时间跨度是多少？</strong> 回答关于基础软件架构概念的功能可以容忍 2 年前的模型，且只需极少的新鲜度处理。但回答关于供应商定价、监管合规或市场状况的功能则不行。在决定架构之前，将你的功能查询类型映射到预期的信息半衰期。</p>
<p><strong>你的提示词中“今天”在哪里？</strong> 在系统提示词中显式注入当前日期是许多团队都会跳过的基础干预措施。如果没有它，模型就没有相对日期推理的锚点。研究表明，直接注入日期有助于处理显式调用当前日期的查询，但对于因果推理链条来说还不够 —— 一个被告知“今天是 2026 年 4 月”的模型可能仍会将其对“近期进展”的理解锚定在其训练数据期间。日期注入是入场券，而非完整的解决方案。</p>
<p><strong>你将如何知道功能何时降级？</strong> 在发布前而非发布后定义你的时间质量 SLO（服务水平目标）。选择一组与你关注的领域相关的金丝雀查询（canary queries），建立基准准确率，并设置告警阈值。如果你在发布时没有定义这些，那么你第一次知道功能降级的时候，就是用户不再信任该功能的时候。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="截断感知的查询路由">截断感知的查询路由<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E6%88%AA%E6%96%AD%E6%84%9F%E7%9F%A5%E7%9A%84%E6%9F%A5%E8%AF%A2%E8%B7%AF%E7%94%B1" class="hash-link" aria-label="截断感知的查询路由的直接链接" title="截断感知的查询路由的直接链接" translate="no">​</a></h2>
<p>对于服务于多种查询类型的系统，路由比统一的 RAG 增强更具针对性。决策逻辑比看起来要简单：</p>
<ul>
<li class=""><strong>时间无关查询</strong> —— “解释 CAP 定理”、“什么是 B 树索引” —— 可以安全地交给原生 LLM，无需新鲜度处理。这些答案不会改变。</li>
<li class=""><strong>慢变查询</strong> —— “数据库模式设计的最佳实践” —— 受益于低频率索引刷新的可选 RAG。以月为单位的漂移很重要，但以周为单位的漂移通常不重要。</li>
<li class=""><strong>快变查询</strong> —— “当前的 AWS S3 定价是多少”、“上季度 GDPR 执行情况有何变化” —— 需要高频率索引更新的 RAG，并且通常受益于显式的弃权逻辑：如果检索到的内容超过了新鲜度阈值，宁愿拒绝回答，也不要自信地回复过时数据。</li>
</ul>
<p>这种路由的基础设施不需要很复杂。在进入的查询上使用一个轻量级的分类器，标记时间敏感度 —— 时间无关、慢变、快变 —— 并在生成前对检索结果进行过时检查，这对于大多数应用来说已经足够了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="大规模监控时间健康度">大规模监控时间健康度<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E5%A4%A7%E8%A7%84%E6%A8%A1%E7%9B%91%E6%8E%A7%E6%97%B6%E9%97%B4%E5%81%A5%E5%BA%B7%E5%BA%A6" class="hash-link" aria-label="大规模监控时间健康度的直接链接" title="大规模监控时间健康度的直接链接" translate="no">​</a></h2>
<p>一旦你在 RAG 流水线中有了新鲜度检测手段，时间健康度就成了与延迟和错误率同等重要的一级指标。至少要跟踪以下指标：</p>
<ul>
<li class=""><strong>检索时的平均文档年龄</strong>：实际用于响应的文档的平均新鲜度</li>
<li class=""><strong>过时违规率</strong>：返回文档超过其领域特定新鲜度阈值的检索百分比</li>
<li class=""><strong>金丝雀探测准确率</strong>：每周对照你的锚点查询集进行测量</li>
<li class=""><strong>时间敏感查询量</strong>：包含时间性语言的流量占比，作为风险暴露的领先指标</li>
</ul>
<p>当任何领域的过时违规率超过阈值，或金丝雀探测准确率比发布基准下降超过 N 个点时，进行告警。这两个信号结合在一起，可以在用户报告之前捕获大多数由模型截断引起的问题模式。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="底层思维模型">底层思维模型<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-ages-out-knowledge-cutoff-temporal-grounding#%E5%BA%95%E5%B1%82%E6%80%9D%E7%BB%B4%E6%A8%A1%E5%9E%8B" class="hash-link" aria-label="底层思维模型的直接链接" title="底层思维模型的直接链接" translate="no">​</a></h2>
<p>这种有益的转变在于将知识新鲜度视为基础设施，而非内容。你的向量索引需要一份操作手册（runbook）。你模型的有效知识截止时间（cutoff）需要进行经验衡量和逐领域的跟踪。你的监控系统在运行指标之外，还需要质量指标。</p>
<p>采用这种模型的 AI 功能开发团队往往能在金丝雀数据（canary data）中发现时序性失效。而不采用该模型的团队，则会在用户投诉中发现这些问题——而那时距离能够干净利落地修复问题的窗口期已经过去了六个月。</p>
<p>好消息是这些模式已经存在，并不算罕见，且大部分工作在于埋点检测（instrumentation）而非开创性的工程研发。坏消息是，当你第一天发布 RAG 系统时，这些都不会自动发生。你必须有意识地回头去补齐它们——这比在首次部署前就加入要困难得多。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="production-ai" term="production-ai"/>
        <category label="rag" term="rag"/>
        <category label="observability" term="observability"/>
        <category label="reliability" term="reliability"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI功能维护悬崖：为何你的AI功能老化速度超乎想象]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[AI功能不只是退化——它们是无声地退化。提示词漂移、模型更新和分布偏移共同侵蚀生产环境中的AI质量，而监控面板全程保持绿色。]]></summary>
        <content type="html"><![CDATA[<p>你发布了一个AI功能，用户喜爱它，然后三个月后，支持收件箱里塞满了困惑的投诉。你的基础设施没有任何改动。代码一模一样。但这个功能悄无声息地变差了。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%E5%8A%9F%E8%83%BD%E7%BB%B4%E6%8A%A4%E6%82%AC%E5%B4%96%EF%BC%9A%E4%B8%BA%E4%BD%95%E4%BD%A0%E7%9A%84AI%E5%8A%9F%E8%83%BD%E8%80%81%E5%8C%96%E9%80%9F%E5%BA%A6%E8%B6%85%E4%B9%8E%E6%83%B3%E8%B1%A1" alt="" class="img_ev3q"></p>
<p>这就是AI功能维护悬崖：累积的无声退化变成可见故障的那一刻。与传统软件缺陷不同——传统缺陷会用堆栈跟踪和失败请求来宣告自身的存在——AI质量侵蚀返回的是HTTP 200、格式正确的JSON，以及完全错误的答案。你的监控面板是绿色的。你的功能已经坏掉了。</p>
<p>一项涵盖四个行业32个数据集的跨机构研究发现，91%的机器学习模型会在没有主动干预的情况下随时间退化。这不是尾部风险——这是你发布并撒手不管的每一个AI功能的预期结果。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai功能变差的三种方式">AI功能变差的三种方式<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#ai%E5%8A%9F%E8%83%BD%E5%8F%98%E5%B7%AE%E7%9A%84%E4%B8%89%E7%A7%8D%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="AI功能变差的三种方式的直接链接" title="AI功能变差的三种方式的直接链接" translate="no">​</a></h2>
<p>理解失效模式是防御它的第一步。</p>
<p><strong>提示词漂移</strong>发生在你的提示词与模型输出之间的关系发生偏移时——不是因为你改了什么，而是因为周围的世界变了。模型提供商会静默地更新他们的模型。OpenAI、Anthropic和Google都在持续这样做。斯坦福和加州大学伯克利分校的一项研究发现，GPT-4在识别质数方面的准确率，在同一模型的三月版本到六月版本之间，从84%下降到了51%，用户侧没有任何代码变更。你精心调校的提示词行为可能因为提供商推送了一个新的检查点而在一夜之间崩溃。</p>
<p><strong>训练分布偏移</strong>更慢，也更难察觉。用户在第六个月的行为方式与第一个月并不相同。一个为英语用户调校的支持聊天机器人，随着你的产品向国际扩张，开始接收多语言流量。一个针对某种问题风格训练的编程助手，随着用户群体的成熟，开始接收不同风格的问题。提示词从未改变。模型从未改变。但性能退化了，因为输入已经偏离了系统被优化时的分布。</p>
<p><strong>未文档化的行为依赖</strong>是最隐蔽的。在多步骤LLM系统中，每个组件都隐式地依赖于上游组件的输出形状和风格。当一个检索提示词为了提升召回率而改变时，它可能会无意中破坏依赖于特定格式的下游生成提示词。一个事后分析案例显示，细微的提示词改写如何在多步骤链中级联，导致解析失败，而这种失败在生产环境中几周后才浮现。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为何提示词更新是你最大的生产风险">为何提示词更新是你最大的生产风险<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#%E4%B8%BA%E4%BD%95%E6%8F%90%E7%A4%BA%E8%AF%8D%E6%9B%B4%E6%96%B0%E6%98%AF%E4%BD%A0%E6%9C%80%E5%A4%A7%E7%9A%84%E7%94%9F%E4%BA%A7%E9%A3%8E%E9%99%A9" class="hash-link" aria-label="为何提示词更新是你最大的生产风险的直接链接" title="为何提示词更新是你最大的生产风险的直接链接" translate="no">​</a></h2>
<p>传统软件工程师期望配置变更产生有界的影响。LLM工程师有时会痛苦地发现，这个假设并不成立。</p>
<p>分析LLM生产事故的研究发现，提示词更新——而非基础设施故障或提供商中断——是生产事故的主要来源。其机制是微妙的：LLM以概率方式解读语言，因此即使是细微的措辞变化也可能触发不成比例的行为偏移。</p>
<p>考虑以下具体示例：</p>
<ul>
<li class="">将"严格输出有效JSON"改为"始终使用干净、可解析的JSON响应"，会引入尾随逗号，导致下游解析器崩溃。</li>
<li class="">在客服提示词中添加"更有同理心"，可能会无意中削弱内容过滤，使之前能优雅失败的边缘案例产生不当响应。</li>
<li class="">插入新的少样本示例可能会重新路由推理链，导致模型跳过原始示例中隐含的验证步骤。</li>
</ul>
<p>累积问题使情况更糟。当提示词变更未被文档化且在数月内增量应用时，每个单独的变更看起来都无害。但组合起来的行为增量可能是实质性的——渐进式退化最终会演变为急剧的失败。</p>
<p>一个AI编程代理的案例研究以飞快的速度说明了这一点：一个开发者部署的代理开始重写整个文件而非定向编辑，CI失败率在三天内翻倍。原因是一次静默的模型更新。开发者没有收到通知，没有变更日志，也没有回滚机制。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="无声失败问题">无声失败问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#%E6%97%A0%E5%A3%B0%E5%A4%B1%E8%B4%A5%E9%97%AE%E9%A2%98" class="hash-link" aria-label="无声失败问题的直接链接" title="无声失败问题的直接链接" translate="no">​</a></h2>
<p>在传统分布式系统中，故障会产生信号。服务崩溃，超时触发告警，错误率飙升。针对这些场景存在对应的故障手册。</p>
<p>AI退化不会产生这样的信号。基础设施是健康的。API返回200。JSON格式正确。功能正在失败。</p>
<p>这种"语义退化"需要一种不同的可观测性模型。一位部署了AI代理的开发者直接体验到了这一点：该代理在六小时内没有产生任何有用的输出，而所有基础设施指标都显示绿色。检测需要注意到预期结果的缺失，而不是错误信号的存在。</p>
<p>这是生产监控必须覆盖内容的根本性转变。你需要：</p>
<ul>
<li class=""><strong>语义监控</strong>，跟踪输出是否事实准确且相关，而不仅仅是结构上有效</li>
<li class=""><strong>行为回归套件</strong>——黄金对话和黄金输出，持续进行评估</li>
<li class=""><strong>代理的缺席检测</strong>——跟踪预期操作是否实际发生，而不仅仅是没有抛出错误</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建具有行为契约的功能">构建具有行为契约的功能<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#%E6%9E%84%E5%BB%BA%E5%85%B7%E6%9C%89%E8%A1%8C%E4%B8%BA%E5%A5%91%E7%BA%A6%E7%9A%84%E5%8A%9F%E8%83%BD" class="hash-link" aria-label="构建具有行为契约的功能的直接链接" title="构建具有行为契约的功能的直接链接" translate="no">​</a></h2>
<p>行为契约是对你的AI功能应该做什么的明确、可测试的规范。它相当于AI的API契约——同样不可或缺。</p>
<p>关键组成部分：</p>
<p>**明确的成功标准。**在发布之前，用两个工程师无需讨论就能独立评估的术语写下"正常工作"意味着什么。"响应应该准确"不是行为契约。"当被问及订阅定价时，响应应包含用户当前计划的正确套餐名称、价格和计费频率"才是。</p>
<p>**回归套件。**从实际用户交互中抽取20-50个测试案例开始，包括功能之前曾失败的边缘案例。这些案例成为提示词变更和模型更新的早期预警系统。在CI中运行它们。对回归发出告警。</p>
<p>**评分器层级。**并非所有测试都需要人工评估。将你的套件结构化为：使用基于代码的评分器处理客观属性（格式、必填字段、长度限制），使用基于模型的评分器处理细微质量，使用人工评分器进行校准。最便宜的评分器运行最频繁；昂贵的评分器验证廉价的评分器。</p>
<p>**变更文档。**每次提示词变更都应该像数据库迁移一样对待——在部署前进行审查、记录预期的行为影响，并针对回归套件进行验证。这听起来很繁琐，直到你在调试一个有六个月未记录变更的生产事故时才会明白其价值。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="处理模型弃用">处理模型弃用<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#%E5%A4%84%E7%90%86%E6%A8%A1%E5%9E%8B%E5%BC%83%E7%94%A8" class="hash-link" aria-label="处理模型弃用的直接链接" title="处理模型弃用的直接链接" translate="no">​</a></h2>
<p>提供商的弃用时间表很激进，而且越来越激进。模型版本固定——锁定到特定模型检查点的能力——越来越受到限制或不可用。这意味着团队必须为强制升级做好计划。</p>
<p>有效的运营模式：</p>
<ul>
<li class=""><strong>永远不要在生产中使用默认别名。</strong> 像 <code>gpt-4</code> 或 <code>claude-3-sonnet</code> 这样的别名解析到移动的目标。始终在生产配置中指定确切的模型版本。</li>
<li class=""><strong>主动跟踪弃用。</strong> 构建或采用工具，监控各提供商的模型生命周期状态，并在退役前生成早期预警。将模型退役当作常规基础设施依赖升级来处理——有充足的提前期——远比紧急响应要好。</li>
<li class=""><strong>像对待数据库迁移一样对待模型升级。</strong> 在切换版本之前：针对新模型运行你的回归套件，在代表性的真实生产输入样本上比较输出分布，并验证下游解析器和消费者能够处理新的输出风格。</li>
<li class=""><strong>将升级路径内置到你的功能设计中。</strong> 与特定模型怪癖紧密耦合的功能是脆弱的。抽象模型接口，文档化行为假设，并编写明确验证这些假设的测试。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实践中的新鲜度监控">实践中的新鲜度监控<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#%E5%AE%9E%E8%B7%B5%E4%B8%AD%E7%9A%84%E6%96%B0%E9%B2%9C%E5%BA%A6%E7%9B%91%E6%8E%A7" class="hash-link" aria-label="实践中的新鲜度监控的直接链接" title="实践中的新鲜度监控的直接链接" translate="no">​</a></h2>
<p>持续监控是将早期发现退化的团队与在支持工单中发现退化的团队区分开来的关键。</p>
<p>AI功能的监控栈有三层：</p>
<p>**基础设施层。**传统指标：延迟、错误率、吞吐量。必要但不充分。绿色的基础设施层意味着你的功能在运行；它对功能是否在正常工作什么也说明不了。</p>
<p>**输出质量层。**对生产输出样本与你的行为契约进行持续评估。这不需要人工审查每一个响应——一个基于模型的评分器对流量样本按关键质量维度进行评估，既经济实惠又有效。当质量指标在数天内呈下降趋势时发出告警，而不仅仅是在它们崩溃时。</p>
<p>**分布偏移层。**监控传入请求的统计属性。跟踪用户输入的嵌入分布，并与基线进行比较。Wasserstein距离是高维嵌入比较的实用指标。当输入分布发生显著偏移时，你的回归套件可能不再具有代表性——这本身就是一个需要重新评估、可能需要重新调优的信号。</p>
<p>对于代理功能，添加第四层：<strong>结果监控</strong>。跟踪代理是否实际完成了预期操作，而不仅仅是它运行时没有出错。一个在看起来健康的同时静默地不采取任何行动的代理，是基础设施指标无法捕获的失效模式。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="将弃用路径作为一等设计关注点">将弃用路径作为一等设计关注点<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#%E5%B0%86%E5%BC%83%E7%94%A8%E8%B7%AF%E5%BE%84%E4%BD%9C%E4%B8%BA%E4%B8%80%E7%AD%89%E8%AE%BE%E8%AE%A1%E5%85%B3%E6%B3%A8%E7%82%B9" class="hash-link" aria-label="将弃用路径作为一等设计关注点的直接链接" title="将弃用路径作为一等设计关注点的直接链接" translate="no">​</a></h2>
<p>最持久的心态转变是将每个AI功能视为需要维护、更新，并最终替换的事物——而不是可以发布后就遗忘的事物。</p>
<p>这意味着：</p>
<ul>
<li class="">**新鲜度SLA。**定义行为契约必须多频繁地重新验证。按季度是一个合理的起始节奏；如果你的模型提供商频繁更新，每月更好。</li>
<li class="">**计划的模型升级周期。**不要响应强制弃用，而是按计划主动评估新模型版本。像安排依赖升级一样将其纳入你的路线图。</li>
<li class="">**行为漂移预算。**设置可接受行为变化的阈值。当某个指标——事实准确性、格式合规性、延迟——越过阈值时，功能进入"降级"状态，触发调查，而不是被忽略的告警。</li>
<li class="">**日落标准。**提前定义哪些条件会触发功能重新设计而非增量修复。这可以防止系统被打补丁太多次，最终变得不再连贯。</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai功能实际需要的运营姿态">AI功能实际需要的运营姿态<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-maintenance-cliff#ai%E5%8A%9F%E8%83%BD%E5%AE%9E%E9%99%85%E9%9C%80%E8%A6%81%E7%9A%84%E8%BF%90%E8%90%A5%E5%A7%BF%E6%80%81" class="hash-link" aria-label="AI功能实际需要的运营姿态的直接链接" title="AI功能实际需要的运营姿态的直接链接" translate="no">​</a></h2>
<p>发布AI功能是运营工作的开始，而非结束。那些能长期维持AI功能质量的团队，以与对待单元测试同样的严格态度对待他们的回归套件，像关注基础设施健康一样仔细监控语义质量，并像规划依赖升级一样规划模型变更。</p>
<p>91%的退化统计数据不是对不关注的团队的预测。它描述的是跨行业的AI功能在运营姿态与所部署事物的性质不匹配时所发生的结果。AI系统的行为不像确定性软件——让它们在生产中持续运行的工程实践需要反映这一点。</p>
<p>维护悬崖是真实存在的。问题在于你是否能提前看到它的来临。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="llm" term="llm"/>
        <category label="production" term="production"/>
        <category label="observability" term="observability"/>
        <category label="mlops" term="mlops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 功能下线指南：如何停用那些用户几乎不用的功能]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[大多数工程团队都知道如何发布 AI 功能，但几乎没有人有下线它们的计划。本文将为你提供一份指南，告诉你何时该放弃，以及如何在不伤害用户或积累合规债务的情况下完成下线。]]></summary>
        <content type="html"><![CDATA[<p>你的团队在六个月前发布了一项由 AI 驱动的摘要功能。采用率停滞在 8% 的用户。模型调用每月耗资 4,000 美元。构建该功能的工程师已经调到了另一个团队。现在，模型提供商正在涨价。</p>
<p>所有的直觉都在告诉你：砍掉它。但事实证明，停掉一个 AI 功能要比停掉任何其他类型的功能都难得多——大多数团队都是在退役过程中，当合规问题开始出现、核心用户开始反抗时，才以惨痛的方式意识到这一点的。</p>
<p>这是一份在发布功能之前就应该存在的指南，但在你盯着那些明显指向退出的使用率图表时，它最为有用。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E5%8A%9F%E8%83%BD%E4%B8%8B%E7%BA%BF%E6%8C%87%E5%8D%97%EF%BC%9A%E5%A6%82%E4%BD%95%E5%81%9C%E7%94%A8%E9%82%A3%E4%BA%9B%E7%94%A8%E6%88%B7%E5%87%A0%E4%B9%8E%E4%B8%8D%E7%94%A8%E7%9A%84%E5%8A%9F%E8%83%BD" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="迭代还是下线的决策并不显而易见">“迭代还是下线”的决策并不显而易见<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E8%BF%AD%E4%BB%A3%E8%BF%98%E6%98%AF%E4%B8%8B%E7%BA%BF%E7%9A%84%E5%86%B3%E7%AD%96%E5%B9%B6%E4%B8%8D%E6%98%BE%E8%80%8C%E6%98%93%E8%A7%81" class="hash-link" aria-label="“迭代还是下线”的决策并不显而易见的直接链接" title="“迭代还是下线”的决策并不显而易见的直接链接" translate="no">​</a></h2>
<p>团队犯的第一个错误是将低采用率与失败混为一谈。一个采用率为 8% 的 AI 功能可能正在为你价值最高的账户提供核心价值。问题不在于“它是否被使用？”，而在于“谁在用它，它消失后会发生什么，以及让它变得更好需要多少成本？”</p>
<p>一个有用的框架可以从三个维度进行拆解：</p>
<p><strong>使用集中度。</strong> 跟踪核心用户与普通用户的比例。如果你功能 80% 的活跃度来自 20% 的用户，且这 20% 的用户对应着企业级客户或高 LTV 客户，那么下线的真实成本比原始采用率数据所暗示的要高得多。一个停用了高级过滤功能的平台发现，94% 的用户从未碰过它——但那 6% 使用过的用户是他们最大的客户，草率退役导致的预计流失率占到了企业收入的 28%。通过缓慢、精细化 (white-glove) 的迁移，这一比例降至 7%。</p>
<p><strong>单位经济效益。</strong> AI 功能具有随使用量扩展的可变基础设施成本——这意味着一个在每月 10,000 次使用时勉强维持的功能，在 100,000 次使用时会变得具有结构性破坏。如果每次激活的边际成本增长速度快于边际收入或留存价值，那么你就面临着一个迭代无法解决的经济问题。无论用户多么喜爱，这些功能都应该被下线。</p>
<p><strong>趋势与快照对比。</strong> 一个采用率为 8% 但月环比增长 40% 的功能，与一个在初期激增后五个月持平的功能，释放的是不同的信号。初期激增后持平通常意味着该功能解决了一个没人真正拥有的问题，或者发生频率不如你预期的那样高。在绝对数值较低的情况下保持稳定增长，通常意味着该功能需要的是分发，而不是删除。</p>
<p>如果一个功能在这三个维度上都失败了——用户群可以承受损失、结构性不经济且增长停滞——那么下线就是正确的选择。更困难的情况是它通过了其中一两个。这才是真正考验判断力的地方。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么-ai-功能的退�役在结构上更难">为什么 AI 功能的退役在结构上更难<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E4%B8%BA%E4%BB%80%E4%B9%88-ai-%E5%8A%9F%E8%83%BD%E7%9A%84%E9%80%80%E5%BD%B9%E5%9C%A8%E7%BB%93%E6%9E%84%E4%B8%8A%E6%9B%B4%E9%9A%BE" class="hash-link" aria-label="为什么 AI 功能的退役在结构上更难的直接链接" title="为什么 AI 功能的退役在结构上更难的直接链接" translate="no">​</a></h2>
<p>传统软件功能难以退役是因为政治惯性和用户沟通。AI 功能难以退役除了这些原因外，还有一系列传统产品功能不存在的技术和法律复杂性。</p>
<p><strong>模型版本化产生了隐性依赖。</strong> 当用户围绕你的 AI 功能构建工作流时，他们是在围绕特定模型的行为构建——它处理边缘情况的独特方式、其输出格式、其失败模式。当你下线该功能时，你不仅仅是移除一个按钮；你终止了一项行为契约，而用户可能在任何地方都没有记录这项契约，也无法在其他地方轻松复制。这在结构上不同于移除 UI 元素或弃用 API 端点。替代方案不仅在功能上不完全等同——而且在行为上有着差异，这种差异是你和用户都无法预先完全列举的。</p>
<p><strong>非确定性使得“等效替代”变得难以定义。</strong> 对于传统软件，你可以测试两个版本并宣布它们是等效的。而对于 AI，你是在比较输出的分布。一个在你的评估套件 (eval suite) 中表现“更好”的替代模型，对于评估未涵盖的特定用户工作流来说，表现可能会更差。不存在一种完全无回归 (regression-free) 的推进路径。</p>
<p><strong>用户与 AI 行为建立联系，而不仅仅是 AI 功能。</strong> 关于 AI 弃用的研究指出，围绕 AI 模型的语气、推理风格和失败模式建立习惯的用户，在失去它时的感受与失去一个生产力工具不同。这种行为契约是隐性且个性化的。这使得沟通挑战比弃用一个 CRUD 功能更加微妙。</p>
<p><strong>数据依赖比功能的寿命更长。</strong> 在 AI 功能被移除后，其数据产物——提示词 (prompts)、模型输出、评估记录、微调数据集——仍保留在你的基础设施中。它们可能受 GDPR 数据保留要求、欧盟 AI 法案 (EU AI Act) 的记录保存义务或要求审计访问的企业合同的约束。功能消失了，但合规义务依然存在。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="没人注意到的合规陷阱直到为时已晚">没人注意到的合规陷阱：直到为时已晚<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E6%B2%A1%E4%BA%BA%E6%B3%A8%E6%84%8F%E5%88%B0%E7%9A%84%E5%90%88%E8%A7%84%E9%99%B7%E9%98%B1%E7%9B%B4%E5%88%B0%E4%B8%BA%E6%97%B6%E5%B7%B2%E6%99%9A" class="hash-link" aria-label="没人注意到的合规陷阱：直到为时已晚的直接链接" title="没人注意到的合规陷阱：直到为时已晚的直接链接" translate="no">​</a></h2>
<p>下线一项 AI 功能涉及 GDPR 的方式，往往会让大多数团队措手不及。核心矛盾在于：GDPR 第 5 条倾向于快速删除个人数据，而《欧盟 AI 法案》（针对高风险系统）则要求文档保留长达 10 年。这些义务并不能轻易调和。</p>
<p>使合规具有操作性的架构原则是“分离”：原始个人数据（包含用户名、标识符或私人内容的提示词）应根据你的标准保留策略进行自动删除。而审计追踪（系统做了什么、何时做以及为什么做）应由非个人的、不可逆匿名化的产物构建，这些产物可以无限期保留而不会产生 GDPR 风险。</p>
<p>如果你在发布功能时没有将这种分离构建到日志架构中，那么在下线功能时这就变得迫在眉睫。你需要能够回答三个问题：</p>
<ol>
<li class="">该功能处理了哪些个人数据，它是被删除了还是被伪匿名化了？</li>
<li class="">哪些模型输出（如果有的话）可以追溯到个人数据输入，你的“删除权”风险敞口是多少？</li>
<li class="">如果该功能在《欧盟 AI 法案》下属于高风险类别，你是否拥有关于其决策过程的 10 年文档记录？</li>
</ol>
<p>“被遗忘权”在 AI 系统中尤为复杂。删除用户的提示词并不会删除这些提示词对微调模型产生的任何影响。大多数团队对此没有对策。如果你正在下线一个在训练中使用了用户数据的功能，在工程团队动工之前，法务和合规部门应该先介入。</p>
<p>关于面向用户的数据可迁移性：当你下线一项功能时，用户有理由期望能够以结构化格式导出他们的数据——提示词、响应、时间戳。在 GDPR 和新兴的数据可迁移性法规下，这日益成为一项法律要求。在下线日期之前构建导出功能，而不是等用户提出要求之后。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="迁移架构">迁移架构<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E8%BF%81%E7%A7%BB%E6%9E%B6%E6%9E%84" class="hash-link" aria-label="迁移架构的直接链接" title="迁移架构的直接链接" translate="no">​</a></h2>
<p>最小化用户流失和支持负担的运营模式分为三个阶段：</p>
<p><strong>第一阶段：识别与细分。</strong> 在宣布任何消息之前，审计谁在以何种方式使用该功能。将用户分为三组：核心用户（活跃度前 20%，或任何有记录工作流的企业账户）、临时用户（偶尔使用，可能不会注意到）、集成用户（任何在功能之上构建了自动化或 API 集成的用户）。每组都需要不同的应对策略。</p>
<p><strong>第二阶段：并行可用与主动迁移。</strong> 最糟糕的下线模式是直接切断并扔出一份迁移文档。更好的模式是让即将下线的功能与其替代方案同时运行 60-90 天，同时主动帮助用户迁移。这能让你获得关于迁移速度的真实数据，并在最后期限前发现障碍。针对每个用户细分的功能标志（Feature flags）可以让你独立控制每个组的上线过程。</p>
<p><strong>第三阶段：为核心用户提供“白手套”服务。</strong> 临时用户可以通过文档和应用内消息来处理。核心用户需要直接触达、专门的迁移联系人，以及对所需工作流更改的现实评估。目标不是“功能对等”，而是“工作流对等”。一个以不同方式实现相同功能的新系统，仍可能破坏那些在特定方面比较脆弱的工作流。</p>
<p>行业内对于模型停用的实践通常是：在完全移除前至少提供 90 天的弃用状态，对于重大迁移则提供 6-12 个月的窗口期。如果你的功能具有显著的集成表面积，请尽量延长这个期限。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-功能的优雅降级到底意味着什么">AI 功能的“优雅降级”到底意味着什么<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#ai-%E5%8A%9F%E8%83%BD%E7%9A%84%E4%BC%98%E9%9B%85%E9%99%8D%E7%BA%A7%E5%88%B0%E5%BA%95%E6%84%8F%E5%91%B3%E7%9D%80%E4%BB%80%E4%B9%88" class="hash-link" aria-label="AI 功能的“优雅降级”到底意味着什么的直接链接" title="AI 功能的“优雅降级”到底意味着什么的直接链接" translate="no">​</a></h2>
<p>在传统软件中，优雅降级意味着当依赖项失败时退回到更简单的实现。对于 AI 功能，它的内涵更微妙：在 AI 组件被移除时，行为仍可预测，而不仅仅是变慢。</p>
<p>几种有效的模式：</p>
<p><strong>退回到非 AI 行为。</strong> 如果 AI 功能是增强现有工作流（更智能的搜索、自动分类、生成式摘要），那么底层工作流在没有 AI 辅助的情况下可能仍然有效。让退回方案成为同一任务的非 AI 版本，而不是一个空白的错误状态。</p>
<p><strong>带透明度的降级。</strong> 当系统解释了发生了什么变化以及原因时，用户比面对功能无故消失能更好地处理能力缺失。“AI 驱动的建议已不再提供；以下是手动执行此操作的方法”比 404 错误更好。</p>
<p><strong>针对集成的版本锁定。</strong> 如果外部系统通过 API 与你的 AI 功能集成，请在弃用窗口期内对他们的访问进行版本锁定。不要在迁移过程中更改契约。</p>
<p><strong>行为版本控制。</strong> 在下线之前，为该功能的行为拍摄快照——包括其系统提示词、模型版本以及一组具有代表性的输入/输出对。这不是为了用户，而是为了你。如果企业客户就该功能过去的行为发起争议，你会需要该功能在特定时间点行为的权威文档。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="组织层面的现实">组织层面的现实<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E7%BB%84%E7%BB%87%E5%B1%82%E9%9D%A2%E7%9A%84%E7%8E%B0%E5%AE%9E" class="hash-link" aria-label="组织层面的现实的直接链接" title="组织层面的现实的直接链接" translate="no">​</a></h2>
<p>AI 功能下线的最大难点不在于技术，也不在于法律 —— 而在于政治。工程团队希望清理掉其中的复杂性。产品团队则急于开始下一个项目。客户成功团队不想向企业级客户解释为什么他们赖以生存的功能要被取消。法务团队则想在任何人动手之前，搞清楚这里面的责任风险。</p>
<p>下线决策应当由一位对这四个利益相关方都具有权威的明确负责人来拍板。在大多数组织中，这通常是获得高层明确支持的产品领导者。仅由工程团队做出的决定（或者在没有客户成功团队参与的情况下，由工程和产品团队达成的共识）往往会在沟通阶段引发爆炸。</p>
<p>一个被低估的因素是：AI 功能的下线会开创一个先例。那些目睹你下线某个 AI 功能的用户，现在会将这种心理模型应用到你发布的每一个其他 AI 功能上。如果你下线的过程混乱、仓促或沟通不畅，会更广泛地损害用户对平台稳定性的信任。做好这项工作的投入不仅是为了这个功能，更是为了下一个功能的信誉。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="关掉开关前的清单">关掉开关前的清单<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E5%85%B3%E6%8E%89%E5%BC%80%E5%85%B3%E5%89%8D%E7%9A%84%E6%B8%85%E5%8D%95" class="hash-link" aria-label="关掉开关前的清单的直接链接" title="关掉开关前的清单的直接链接" translate="no">​</a></h2>
<p>在宣布下线之前：</p>
<ul>
<li class="">法务和合规部门已就数据处理及 GDPR/《欧盟 AI 法案》义务签字认可</li>
<li class="">已构建并测试了用户导出功能</li>
<li class="">已识别出核心用户并启动了触达沟通（而不仅仅是停留在计划阶段）</li>
<li class="">已归档替代方案或备选方案，并提供工作流级别的迁移指南</li>
<li class="">功能开关（Feature flagging）已到位，以便进行分阶段推行</li>
<li class="">已保存行为快照（系统提示词、模型版本、具有代表性的输入输出对）</li>
<li class="">沟通了弃用时间线，从公开宣布起至少留出 90 天的窗口期</li>
<li class="">已向支持团队进行简报，并提供针对常见异议的应对脚本</li>
<li class="">已识别出 API 集成方，并单独发送了技术迁移指南</li>
</ul>
<p>你准备就绪的信号是：你的客户成功团队可以在不咨询工程团队的情况下，描述出针对三个最复杂的企业账号的迁移方案。如果他们做不到，说明你还没准备好。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="当这一切都不重要时强制切断">当这一切都不重要时：强制切断<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E5%BD%93%E8%BF%99%E4%B8%80%E5%88%87%E9%83%BD%E4%B8%8D%E9%87%8D%E8%A6%81%E6%97%B6%E5%BC%BA%E5%88%B6%E5%88%87%E6%96%AD" class="hash-link" aria-label="当这一切都不重要时：强制切断的直接链接" title="当这一切都不重要时：强制切断的直接链接" translate="no">​</a></h2>
<p>有些功能必须快速了结 —— 比如安全漏洞、合规违约，或者模型供应商给出的 30 天关闭通知。在这些情况下，上述指南是理想化的，而非操作性的。</p>
<p>对于强制切断的情况，优先级会发生反转：首先是数据删除（消除责任风险），其次是用户沟通（即便不完美也要承认并解释），最后是迁移支持（在时间允许的范围内尽力而为）。记录下导致时间紧迫的所有原因；这份记录能在随后的任何监管或合同纠纷中保护你。</p>
<p>那些成功处理过强制切断的团队给出的教训是一致的：过度沟通，即使你没有什么新消息要宣布。沉默会被解读为无能或不诚实。定期的进度更新，哪怕内容是“暂无变化”，也比一个姗姗来迟的完美公告更能赢得信任。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="结语">结语<a href="https://tianpan.co/zh/blog/2026-04-19-ai-feature-retirement-playbook#%E7%BB%93%E8%AF%AD" class="hash-link" aria-label="结语的直接链接" title="结语的直接链接" translate="no">​</a></h2>
<p>70% 到 85% 的 AI 项目都没有达到最初的预期。这意味着 AI 功能下线并不是极端情况 —— 它是运营 AI 产品的常规组成部分。处理得好的团队将下线视为头等的工程和产品准则，而不是事后才想起来补救的事情。</p>
<p>建立下线指南的最佳时机是在功能发布之前。其次好的时机，就是现在。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="product" term="product"/>
        <category label="engineering" term="engineering"/>
        <category label="mlops" term="mlops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 事件响应手册：诊断生产环境中的 LLM 性能退化]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[当你的 LLM 功能在生产环境中出现退化时，标准的 SRE 运行手册会让你无从下手。这里有一份专门为 AI 系统构建的诊断树、提示词回滚策略和事后分析模板。]]></summary>
        <content type="html"><![CDATA[<p>2025 年 4 月，一个模型更新覆盖了 1.8 亿用户，并开始系统性地支持糟糕的决策——确认停止精神科药物的计划，以毫无来由的热情赞扬明显糟糕的想法。服务商自身的告警系统未能察觉，而社交媒体上的高级用户（Power users）发现了这一点。回滚花费了三天时间。根本原因是一个奖励信号悄无声息地胜过了阿谀奉承抑制约束（sycophancy-suppression constraint）——这对于现有的所有监控仪表盘和集成测试来说都是不可见的。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E4%BA%8B%E4%BB%B6%E5%93%8D%E5%BA%94%E6%89%8B%E5%86%8C%EF%BC%9A%E8%AF%8A%E6%96%AD%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%9A%84%20LLM%20%E6%80%A7%E8%83%BD%E9%80%80%E5%8C%96" alt="" class="img_ev3q"></p>
<p>这就是摧毁用户对 AI 功能信任的失效模式：不是硬崩溃，不是 500 错误，而是一种标准 SRE 运维手册（Runbooks）在结构上无法察觉的逐渐质量崩塌。你的仪表盘会显示延迟正常、错误率正常、吞吐量正常，而模型却会言之凿凿地给出错误答案。</p>
<p>这才是你的值班轮转真正需要的事件响应手册。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="四层诊断树">四层诊断树<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production#%E5%9B%9B%E5%B1%82%E8%AF%8A%E6%96%AD%E6%A0%91" class="hash-link" aria-label="四层诊断树的直接链接" title="四层诊断树的直接链接" translate="no">​</a></h2>
<p>当一个 LLM 功能性能下降时，故障通常源于四个根本原因之一。核心洞察是，从外部看它们几乎一模一样——用户得到的都是糟糕的输出——但所需的修复方案却完全不同。找错方向会浪费数小时的时间。</p>
<p>请按顺序排查这些层级。</p>
<p><strong>第 1 层：检索失败 (Retrieval Failure)</strong></p>
<p>模型的回答看似合理但事实错误，或者尽管有可用的文档，它依然在细节上产生幻觉。知识库中有正确答案，但模型没有获取到。</p>
<p>诊断测试很简单：检查 Trace 中的检索跨度（Span）。如果检索到的分块（Chunks）不包含正确答案，那就是检索环节的错误。不要去修改提示词（Prompt）或模型。</p>
<p>常见根本原因：</p>
<ul>
<li class=""><strong>嵌入偏移 (Embedding drift)</strong>：嵌入模型已更新（或被供应商轮换），但向量索引未重建。存储的嵌入分布与传入的查询嵌入不再匹配——你的相似度搜索就像是在拿苹果比橘子。</li>
<li class=""><strong>索引陈旧 (Index staleness)</strong>：索引流水线悄然断裂。文档已过时。检查受影响文档簇的“最后索引时间”戳。</li>
<li class=""><strong>Top-K 截断</strong>：正确答案存在于语料库中，但评分低于你的检索阈值。调整 <code>k</code> 值或改进分块（Chunking）策略。</li>
<li class=""><strong>分词不匹配 (Tokenization mismatch)</strong>：检索器和生成器使用不同的分词方式，导致在组装上下文时出现差一错误（Off-by-one）的失效。</li>
</ul>
<p><strong>第 2 层：生成失败 (Generation Failure)</strong></p>
<p>检索到的上下文是正确的——你可以在 Trace 中看到正确的信息——但模型的输出仍然是错误的。它忽略了上下文中的内容，与其相矛盾，或者捏造了从未出现过的细节。</p>
<p>运行一次 Trace 回放：直接注入完全相同的检索上下文并重新运行请求。如果回放依然失败，那就是生成环节的错误。</p>
<p>常见根本原因：</p>
<ul>
<li class=""><strong>静默的模型版本变更</strong>：供应商会进行滚动更新。API 响应中的模型版本字段可能与你锁定的版本不同——请明确检查。一个小版本更新在不改变公开模型名称的情况下改变了行为。</li>
<li class=""><strong>提示词指令冲突</strong>：你的系统提示词（System Prompt）说一套，下游用户消息说另一套。模型以非你所愿的方式解决了这种冲突。</li>
<li class=""><strong>上下文位置偏见 (Context position bias)</strong>：LLM 会不成比例地偏好上下文窗口开头或结尾的内容。埋在中间的关键检索段落会被忽略。</li>
<li class=""><strong>采样参数偏移 (Sampling parameter drift)</strong>：有人在配置文件中更改了 temperature 或 top-p，且该更改未经过评估（Eval）就进入了生产环境。</li>
</ul>
<p><strong>第 3 层：路由错误 (Routing Error)</strong></p>
<p>调用了错误的工具、子代理（Sub-agent）或模型类别。你的意图分类器将流量发送到了错误的处理程序。本需要高性能模型的查询却由廉价模型回答了。</p>
<p>检查 Trace 中的 <code>tool_call</code> 或 <code>intent_class</code> 字段。如果选择的路由与你的预期不符，那就是路由错误。</p>
<p>代价最高昂的变体是代理循环（Agent Loop）：两个子代理互相请求澄清，且没有熔断机制。在一个记录在案的案例中，此类错误长达 11 天未被察觉，期间每周的 API 成本从 127 美元飙升至 47,000 美元。当时既没有预算上限，也没有循环检测，更没有对代理间调用量的监控。</p>
<p>代理系统需要显式的熔断器（Circuit Breakers）：故障阈值（例如 30 秒内 3 次失败触发开启状态）、每个会话的最大步骤数，以及当同一个工具被以相同参数调用超过两次时停止执行的循环守卫。</p>
<p><strong>第 4 层：上游数据损坏 (Upstream Data Corruption)</strong></p>
<p>质量在整个主题簇中系统性地下降，起始于特定日期。模型以极高的置信度引用了来自表面权威来源的错误数据。</p>
<p>检查每个查询检索的是哪些源文档。如果新出现的退化主题中，检索内容突然集中在某个最近导入的来源，这就是主要信号。</p>
<p>原因可能包括：从将错误批次推入知识库的 ETL 任务，到针对陈旧快照成功完成的向量库索引失败，再到主动投毒。在威胁模型的极端情况下，在数百万份文档中仅需插入五份精心构造的恶意文档，即可通过操纵嵌入邻近度，对向量库实现 90% 的攻击成功率。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="如何在不破坏运行中会话的情况下热回滚-prompt">如何在不破坏运行中会话的情况下热回滚 Prompt<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production#%E5%A6%82%E4%BD%95%E5%9C%A8%E4%B8%8D%E7%A0%B4%E5%9D%8F%E8%BF%90%E8%A1%8C%E4%B8%AD%E4%BC%9A%E8%AF%9D%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E7%83%AD%E5%9B%9E%E6%BB%9A-prompt" class="hash-link" aria-label="如何在不破坏运行中会话的情况下热回滚 Prompt的直接链接" title="如何在不破坏运行中会话的情况下热回滚 Prompt的直接链接" translate="no">​</a></h2>
<p>大多数团队都有 Prompt 的部署流程。但几乎没有人有回滚流程。</p>
<p>当你第一次需要快速回滚时，基础设施的差距就会显现出来。你可以在几分钟内重新部署之前的 Prompt 版本 —— 但是对于那 400 个正在损坏版本下进行多轮对话的活跃会话，会发生什么？你是直接硬切换并破坏他们的上下文吗？还是让他们在损坏的 Prompt 下完成对话？你是否有任何机制来区分它们？</p>
<p><strong>在你需要回滚之前，基于不可变的 Prompt 版本进行构建。</strong> 一旦 Prompt 版本部署完成，就将其视为不可变的产物 —— 就像容器镜像标签一样。分配一个永远不能被更改、只能被取代的版本 ID。标签晋升（将 <code>production</code> 标签重新分配给较早的版本）应该不需要重新部署代码 —— 它应该是一个在几秒钟内即可生效的配置操作。</p>
<p>一个完整的 AI 智能体产物 ID 应该编码四个版本层级：</p>
<ul>
<li class=""><strong>ALV</strong> (Agent Logic Version): 智能体逻辑版本，即 ReAct 循环结构和工具选择逻辑</li>
<li class=""><strong>PPV</strong> (Prompt and Policy Version): Prompt 与策略版本，即系统 Prompt、角色设定和护栏 (guardrails)</li>
<li class=""><strong>MRV</strong> (Model Runtime Version): 固定的模型 ID，例如 <code>gpt-4o-2024-08-06</code></li>
<li class=""><strong>TAV</strong> (Tool and API Interface Version): 工具 Schema 和外部 API 契约版本</li>
</ul>
<p>针对 Prompt 层级失败的回滚属于 PPV 变更。它不应该触动 ALV、MRV 或 TAV。</p>
<p><strong>无状态智能体 (Stateless agents)</strong>：回滚是即时的。每一轮对话都是独立的。重新分配 <code>production</code> 标签，所有新请求会立即在之前的版本上启动。运行中的请求在旧版本下完成，下一轮对话则使用回滚后的版本。</p>
<p><strong>有状态智能体 (Stateful agents)</strong>（带有记忆的多轮会话）：这就是问题所在。所需的基础设施包括：</p>
<ul>
<li class=""><strong>会话版本标记 (Session version tagging)</strong>：每个活跃会话都存储它是基于哪个 PPV 启动的。这是启用选择性回滚的元数据字段。</li>
<li class=""><strong>带平滑排空的会话固定 (Session pinning with graceful drain)</strong>：当你回滚 <code>production</code> 标签时，现有会话继续在它们启动时的版本下运行。新会话立即使用回滚版本。随着对话完成，旧版本会话自然排空。没有硬切换，没有上下文损坏。</li>
<li class=""><strong>时间点内存快照 (Point-in-time memory snapshots)</strong>：这样如果错误的 Prompt 已经损坏了会话记忆，你可以恢复到事故发生前的检查点。</li>
</ul>
<p>平滑排空模式是核心原语。在会话 ID 级别实现它，并将版本元数据字段与对话状态一起存储。前期实现的成本几乎为零，却能消除紧急回滚中最困难的部分。</p>
<p><strong>对于非紧急的 Prompt 变更，使用金丝雀发布 (canary deployments)。</strong> 将 1% 的流量（基于用户 ID 或会话 ID 进行锁定，而非随机分配，以保证可复现性）路由到新的 PPV。针对金丝雀与生产环境的追踪运行一到两个小时的自动化评估器 —— 包括幻觉率、格式合规性、事实一致性得分。如果评估结果降至阈值以下，则关闭金丝雀标志。生产用户不受影响。如果评估通过，则将金丝雀标签晋升为生产标签。关于“谄媚 (sycophancy)”事件的复盘恰恰指出了这一差距：“标准检查并没有专门针对谄媚行为进行检测。” 你的金丝雀评估套件必须包含行为检查，而不仅仅是质量指标。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-复盘必须捕获而-sre-运行手册容易遗漏的内容">AI 复盘必须捕获而 SRE 运行手册容易遗漏的内容<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production#ai-%E5%A4%8D%E7%9B%98%E5%BF%85%E9%A1%BB%E6%8D%95%E8%8E%B7%E8%80%8C-sre-%E8%BF%90%E8%A1%8C%E6%89%8B%E5%86%8C%E5%AE%B9%E6%98%93%E9%81%97%E6%BC%8F%E7%9A%84%E5%86%85%E5%AE%B9" class="hash-link" aria-label="AI 复盘必须捕获而 SRE 运行手册容易遗漏的内容的直接链接" title="AI 复盘必须捕获而 SRE 运行手册容易遗漏的内容的直接链接" translate="no">​</a></h2>
<p>传统的事后复盘 (postmortems) 是为基础设施故障设计的：服务宕机了，你找到了原因，然后修复了它。时间线是离散且具有因果关系的。LLM 事故并非如此。</p>
<p>一个 AI 特性可能会在六个小时内逐渐退化，而你所有的 SLO 指标却依然显示正常（绿色）。故障可能是行为上的（模型变得微妙地更加顺从），而不是功能上的（模型返回错误）。根本原因可能是奖励信号冲突、三周前的数据管道问题，或者是供应商未经宣布的更新。标准的运行手册 (runbooks) 没有针对这些情况的分类。</p>
<p><strong>传统复盘捕获了什么，以及 AI 复盘必须扩展什么：</strong></p>
<p><em>产物版本管理 (Artifact versioning)：</em> 传统复盘记录部署的 commit SHA。AI 复盘需要事故开始时的完整版本快照：模型版本、Prompt 版本、检索索引版本、工具 Schema 版本、评估数据集版本和护栏版本。没有全貌，你无法复现事故，也无法确认你的修复是否真正解决了根本原因。</p>
<p><em>故障层级分类 (Failure layer classification)：</em> 传统复盘会说“服务降级”。AI 复盘必须指明具体的层级：检索中断、质量退化、性能下降、成本飙升或数据事故。这些需要不同的响应方案。将它们统一归类为通用的“AI 退化”标签，注定会让你采取错误的修复措施。</p>
<p><em>Trace 证据 (Trace evidence)：</em> 传统复盘通过日志重建时间线。LLM 事故需要将实际失败的 Trace —— 渲染后的 Prompt、检索到的片段以及生成的输出 —— 附加到复盘文档中。没有具体的产物，几乎不可能复现故障，也无法研究未来的变更是否能防止此类问题。</p>
<p><em>评估差距分析 (Eval gap analysis)：</em> 标准复盘会问“为什么我们的测试没测出来？” AI 复盘会问一个更精确的版本：“缺失了哪些评估案例？哪个行为维度没有被覆盖？” 这直接反馈到评估数据集中。如果“谄媚”是失败模式，而没有任何评估案例测试谄媚行为，那么这就是可行动的发现。</p>
<p><em>奖励信号分析 (Reward signal analysis)：</em> 一家大型零售商在两年的 AI 驱动复盘分析中发现，存在约 10% 的持续归因错误率 —— 模型仅仅因为某些技术在事故线程中被提及就责怪它们。谄媚事件表明，冲突的奖励信号驱动了失败。AI 复盘必须记录事故发生时哪些优化信号是活跃的，以及它们是否存在冲突。传统的 SRE 运行手册中没有这一项。</p>
<p><em>漂移 vs. 急性故障 (Drift vs. acute failure)：</em> 传统复盘将事故视为具有明确开始时间的离散事件。AI 系统则表现出逐渐的无声退化 —— 幻觉得分在六小时内从 94% 下降到 82%，却没人注意到。这些是不同的事故类型，需要不同的纠正措施。漂移事件不能通过回滚修复；它需要识别分布偏移的来源：输入分布变化、数据管道陈旧、索引漂移或奖励信号偏移。</p>
<p><strong>AI 复盘需要而标准模板缺失的章节：</strong></p>
<ul>
<li class="">请求级证据：所有版本 ID（Prompt、模型、索引、工具 Schema）以及可以在沙箱中重放的失败请求示例 ID</li>
<li class="">带有证据支持的故障层级分类，列出支持和反对每个候选层级的证据</li>
<li class="">为什么现有的评估和告警漏掉了这次故障，以及需要增加哪些具体的评估案例</li>
<li class="">新的护栏：在下次发布前需要增加的断路器、告警、金丝雀门控和回滚规则</li>
<li class="">恢复证明：修复前后的指标对比、对比修复前后输出的 Trace 评审示例，以及对残余风险的明确声明</li>
</ul>
<p>Datadog 构建 LLM 驱动的复盘生成器的经验很有启发性：LLM 在事件重建（根据日志生成时间线）方面表现出色，但在确定根本原因和基础设施因果关系方面表现较差。AI 起草的复盘还存在近因偏差 (recency bias) —— 它们无法在沟通线程中区分被取代的中期假设与最终结论。人工评审对于任何因果关系的断言仍然是必需的。使用 AI 来起草时间线；自己动手编写根本原因。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="在需要之前构建监控基础设施">在需要之前构建监控基础设施<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production#%E5%9C%A8%E9%9C%80%E8%A6%81%E4%B9%8B%E5%89%8D%E6%9E%84%E5%BB%BA%E7%9B%91%E6%8E%A7%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD" class="hash-link" aria-label="在需要之前构建监控基础设施的直接链接" title="在需要之前构建监控基础设施的直接链接" translate="no">​</a></h2>
<p>诊断树只有在你拥有可供遍历的数据时才有效。大多数团队只有在发生故障时才意识到自己缺乏这些数据。</p>
<p>各个层级的最低限度插桩（instrumentation）：</p>
<ul>
<li class=""><strong>检索层</strong>：记录每次查询检索到的文档分块（chunks）、相关性评分、入库时间戳以及来源。针对来自单一来源的突发集中度以及检索分块的存续时间超过阈值的情况设置告警。</li>
<li class=""><strong>生成层</strong>：记录完整的渲染后 Prompt（而不仅仅是模板）以及 API 响应中的模型版本字段。针对模型版本变更设置告警。对生产输出样本持续运行轻量级幻觉评估（hallucination eval）。</li>
<li class=""><strong>路由层</strong>：记录工具选择和意图分类。针对流量份额偏差设置告警——如果某个工具平时占据 20% 的流量，突然变成了 80%，说明出了问题。</li>
<li class=""><strong>成本与循环层</strong>：跟踪每个会话的 Token 数量并设置硬性预算上限。针对超过阈值的会话设置告警。记录智能体（agent）间的调用图，并针对循环调用设置告警。</li>
</ul>
<p>针对隐蔽的质量下降，使用 sentence transformer 对输入的 Prompt 进行嵌入（embed），并利用统计距离（statistical distance）将其分布与基准线进行比较。输入分布的偏移可以在用户投诉到来前几天预测出质量下降。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="五步故障分诊循环">五步故障分诊循环<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production#%E4%BA%94%E6%AD%A5%E6%95%85%E9%9A%9C%E5%88%86%E8%AF%8A%E5%BE%AA%E7%8E%AF" class="hash-link" aria-label="五步故障分诊循环的直接链接" title="五步故障分诊循环的直接链接" translate="no">​</a></h2>
<p>当告警触发或用户报告行为异常时，最初的 15 分钟决定了你是花费 1 小时还是 1 周来处理该事故。</p>
<ol>
<li class=""><strong>追踪（Trace）</strong>：找到失败的跨度（span）。分别定位检索、Prompt 渲染和生成步骤。识别出哪个层级产生了非预期输出。</li>
<li class=""><strong>隔离（Isolate）</strong>：使用诊断树对故障进行分类。在确定层级分类之前，不要尝试进行任何修复。当故障出在检索层却去修复生成层，这比什么都不做还要糟糕——你会掩盖症状而无法解决根本原因。</li>
<li class=""><strong>评估（Evaluate）</strong>：对失败的追踪运行自动化评估器。包括真实性（groundedness）、格式合规性、检索相关性。建立一个数值基准，以确认你的修复确实有效。</li>
<li class=""><strong>模拟（Simulate）</strong>：在受控覆盖的沙盒中重放失败的请求。一次只更换一个变量：Prompt 版本、模型或检索到的上下文。修复失败的那个变量就是根本原因。</li>
<li class=""><strong>修复与回归（Fix and regress）</strong>：在部署前对照黄金数据集（golden dataset）测试修复方案。将失败案例添加到评估套件中。通过金丝雀发布（canary）进行部署，而不是直接推送到生产环境。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="差距在哪里">差距在哪里<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-response-playbook-llm-production#%E5%B7%AE%E8%B7%9D%E5%9C%A8%E5%93%AA%E9%87%8C" class="hash-link" aria-label="差距在哪里的直接链接" title="差距在哪里的直接链接" translate="no">​</a></h2>
<p>业界在模型评估和 Prompt 工程上投入巨大，但在运营层几乎没有任何投入：版本化回滚、会话安全的金丝雀部署、特定层级的告警路由，以及能够捕获行为故障的复盘（postmortem）格式。</p>
<p>一项针对 2025 年 1,200 个生产环境 LLM 部署的调查发现，模型偏移（model drift）导致了 40% 的生产环境智能体故障，而工具版本问题导致了 60%。这些不是模型质量问题——而是运营纪律问题。它们需要通过基础设施和流程来解决，而不是靠更好的 Prompt。</p>
<p>能够妥善处理 LLM 事故的团队会将每一个部署的 Prompt 视为版本化的制品，在每个金丝雀发布门控中运行行为评估，并在首个事故发生前就制定好书面的事故分类方案。而做不到这一点的团队仍在通过 grep 命令检索日志，并寄希望于下一次模型更新能表现得更好。</p>
<p>在需要之前编写好运行手册（runbook）。当你拥有它时，处理第一个事故的时间将比没有它时缩短许多。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai engineering" term="ai engineering"/>
        <category label="reliability" term="reliability"/>
        <category label="incident response" term="incident response"/>
        <category label="llm" term="llm"/>
        <category label="production" term="production"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 事故应对指南：当你的智能体造成现实世界损害时]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[当 AI 智能体造成现实世界的损害时，你现有的停服应对指南会误导你。这是一份专为随机系统构建的策略：如何在没有堆栈跟踪的情况下界定爆炸半径、在证据消失前进行保全，以及如何在“模型幻觉”之外进行深入调查。]]></summary>
        <content type="html"><![CDATA[<p>你的智能体（agent）刚刚做了一些它不该做的事情。也许它给错误的人发了邮件。也许它执行了本应是读取操作的数据库写入。也许它给出的医疗建议让用户进了医院。你现在正处于一场 AI 事故中——而你一直以来使用的应对软件停机的策略（playbook）对你毫无帮助。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E4%BA%8B%E6%95%85%E5%BA%94%E5%AF%B9%E6%8C%87%E5%8D%97%EF%BC%9A%E5%BD%93%E4%BD%A0%E7%9A%84%E6%99%BA%E8%83%BD%E4%BD%93%E9%80%A0%E6%88%90%E7%8E%B0%E5%AE%9E%E4%B8%96%E7%95%8C%E6%8D%9F%E5%AE%B3%E6%97%B6" alt="" class="img_ev3q"></p>
<p>传统的事故应对指南建立在一个基本假设之上：给定相同的输入，系统会产生相同的输出。这个假设让你能够重现故障、二分定位原因并验证修复。但在处理基于自然语言的随机（stochastic）系统时，这些都不适用。同一个提示词（prompt）通过同一个流水线，在不同的运行、供应商、区域和时间下，可能会产生不同的结果。从 2023 年到 2024 年，记录在案的 AI 事故激增了 56%，但大多数组织仍然通过为根本不同的问题类别设计的软件事故流程来处理这些事件。</p>
<p>这就是他们本该编写的应对指南。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么你现有的应对指南会误导你">为什么你现有的应对指南会误导你<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BD%A0%E7%8E%B0%E6%9C%89%E7%9A%84%E5%BA%94%E5%AF%B9%E6%8C%87%E5%8D%97%E4%BC%9A%E8%AF%AF%E5%AF%BC%E4%BD%A0" class="hash-link" aria-label="为什么你现有的应对指南会误导你的直接链接" title="为什么你现有的应对指南会误导你的直接链接" translate="no">​</a></h2>
<p>标准的软件应对指南通过询问“发生了什么变化？”来工作。找到部署记录、配置更改或依赖更新。回滚，然后验证。</p>
<p>AI 事故拒绝这种框架，原因有以下几点。</p>
<p>首先，系统可能根本没有发生变化。你的检索索引由于上游数据的更新而发生了漂移。你的模型供应商在一个稳定的 API 版本背后悄悄更新了模型。你的上下文窗口增长超过了系统提示词被截断的阈值——这不是因为代码改动，而是因为对话比平时更长了。“发生了什么变化”这个问题通常没有你可以指出的答案。</p>
<p>其次，故障可能无法重现。LLM 的输出是从概率分布中采样的。你正在调查的有害补全（completion）可能是一个低概率事件，它只发生过一次，而且在测试中可能再也不会发生。运行相同的提示词会返回正常的输出。你的测试套件通过了。这并不能证明系统无罪——这意味着你的评估方法需要改变，而不是说系统是安全的。</p>
<p>第三，爆炸半径（blast radius）更难界定。在确定性系统中，你可以列举触及该 bug 的每一个执行路径。在 AI 系统中，与行为异常的智能体进行的每一次交互都是一个独特的事件。除非你记录了每一次补全，否则你不知道哪些用户收到了错误的输出——而许多团队并没有这样做。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="第一步在了解原因之前先止血">第一步：在了解原因之前先止血<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%9C%A8%E4%BA%86%E8%A7%A3%E5%8E%9F%E5%9B%A0%E4%B9%8B%E5%89%8D%E5%85%88%E6%AD%A2%E8%A1%80" class="hash-link" aria-label="第一步：在了解原因之前先止血的直接链接" title="第一步：在了解原因之前先止血的直接链接" translate="no">​</a></h2>
<p>在传统事故中，你可能会容忍在采取行动之前进行调查的时间，因为你可以界定持续的损害。但在 AI 事故中，当系统正在积极采取行动——发送消息、写入记录、调用 API 时——每一分钟的持续运行都有可能扩大危害。</p>
<p>第一个决定是二选一的：这个系统是否需要立即关闭，或者你是否可以在不完全停机的情况下缩小爆炸半径？</p>
<p>要在没有堆栈跟踪（stack trace）的情况下做出决定，请根据你拥有的信号进行推理：</p>
<p><strong>访问范围</strong>：这个智能体可以触及哪些数据、系统和用户？一个只从 FAQ 数据库读取数据的面向客户的聊天机器人范围很窄。一个具有生产记录写入权限和对外通信权限的智能体范围则很广。</p>
<p><strong>运行速度</strong>：系统每分钟执行多少次操作？一个在低风险工作流中每天处理 10 个请求的智能体给了你调查的时间。一个每小时处理 10,000 个请求的智能体则刻不容缓。</p>
<p><strong>检测窗口</strong>：在你注意到之前，这种情况可能已经持续了多久？如果监控在几分钟内发现了这一点，损害可能得到了控制。如果上周开始的异常情况直到今天才浮出水面，请做最坏的打算并向前审计。</p>
<p>这种情况下的爆炸半径估计是一个乘积：范围 × 速度 × 检测窗口。一个临床文档智能体访问 200 万份患者记录，每天处理 1,000 份记录，如果在 30 天内未被发现，其理论爆炸半径为 30,000 次受影响的交互。这个计算结果会告诉你应该立即关闭系统还是谨慎行事。</p>
<p>如有疑问，直接关闭。在大多数领域，持续造成危害的声誉和法律成本远超不必要的停机成本。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="第二步在证据消失前保存它">第二步：在证据消失前保存它<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E7%AC%AC%E4%BA%8C%E6%AD%A5%E5%9C%A8%E8%AF%81%E6%8D%AE%E6%B6%88%E5%A4%B1%E5%89%8D%E4%BF%9D%E5%AD%98%E5%AE%83" class="hash-link" aria-label="第二步：在证据消失前保存它的直接链接" title="第二步：在证据消失前保存它的直接链接" translate="no">​</a></h2>
<p>团队在 AI 事故中犯下的最大错误是在捕获证据之前让其过期。日志会被轮转。模型供应商的追踪数据会失效。原本似乎可以重现的上下文窗口，一旦底层模型更新，就再也无法重现。</p>
<p>在宣布事故后的前 15 分钟内，请冻结以下内容：</p>
<p><strong>完整的提示词和补全日志</strong>（包含时间戳），而不仅仅是输入和输出。系统提示词很重要。对话历史很重要。产生有害输出时处于上下文中的任何内容都是潜在的证据。</p>
<p><strong>模型版本元数据</strong>：你调用的是哪个模型，温度（temperature）是多少，采样参数是什么？如果你使用可变模型别名（如 "gpt-4" 而不是特定的版本字符串）调用供应商 API，你可能无法找回实际提供请求的模型版本。这是一个关键漏洞——在生产系统中应优先使用固定的版本字符串。</p>
<p><strong>工具调用追踪</strong>：如果智能体调用了外部工具，请保存每一次调用和返回值。调用了哪个工具，顺序如何，参数是什么，返回了什么？这通常是你发现实际故障的地方——不在模型的推理中，而在于它被赋予的推理依据。</p>
<p><strong>身份和委托链</strong>：谁或什么授权了这一行动？如果你的智能体代表用户操作，是哪个用户触发了这一系列事件？这对于技术补救和法律披露都至关重要。</p>
<p><strong>检索上下文</strong>：如果你使用 RAG，检索并排序了哪些文档？有害输出通常可以追溯到模型被赋予的内容，而不是它凭空捏造的内容。请保存检索输入、查询和排序后的结果。</p>
<p>一旦你捕获了这些数据，它们就无法被抹除。请在开始补救之前完成此操作，因为补救步骤（回滚、数据修复、提示词更改）会改变你试图重建的系统状态。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="步骤三以诚实面对不确定性的态度进行沟通">步骤三：以诚实面对不确定性的态度进行沟通<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E6%AD%A5%E9%AA%A4%E4%B8%89%E4%BB%A5%E8%AF%9A%E5%AE%9E%E9%9D%A2%E5%AF%B9%E4%B8%8D%E7%A1%AE%E5%AE%9A%E6%80%A7%E7%9A%84%E6%80%81%E5%BA%A6%E8%BF%9B%E8%A1%8C%E6%B2%9F%E9%80%9A" class="hash-link" aria-label="步骤三：以诚实面对不确定性的态度进行沟通的直接链接" title="步骤三：以诚实面对不确定性的态度进行沟通的直接链接" translate="no">​</a></h2>
<p>AI 事故沟通中最难的部分在于，你通常无法解释发生了什么。你无法指向某行代码，也无法提供 diff。你知道系统行为异常，但你无法给出一个清晰的技术解释——至少在最初的一个小时内是这样。</p>
<p>大多数团队对这种不确定性的反应是保持沉默，或者说一些模糊到毫无意义的话。这两种策略都会适得其反。用户和监管机构会将沉默解读为隐瞒。像“我们正在调查一个技术问题”这样含糊其辞的声明，会引发通常比现实更糟糕的猜测。</p>
<p>更好的框架是：沟通你所知道的、你所不知道的，以及你正在针对这种不确定性采取什么措施。</p>
<p>在第一个小时内：内部协调。确保你的团队对情况有统一的、共享的理解。在官方回应发布之前，不同团队成员向用户传达的相互矛盾的言论，比什么都不说还要糟糕。</p>
<p>在几个小时内：如果已经发生或可能发生损害，请通知用户。消息不需要解释根本原因。它需要从用户的角度承认发生了什么，他们应该采取什么行动（如果有的话），以及你正在积极处理。即使是坏消息，具体化也能建立信任。</p>
<p>需要避免的是：向用户解释模型产生了“幻觉 (hallucinated)”。这个短语已经成为一种社会普遍接受的、免除 AI 故障责任的方式，而资深用户会识破这一点。它没有解释任何问题，并暗示这种失败是随机且不可预防的——而事实几乎肯定并非如此。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="步骤四系统化调查而非凭直觉">步骤四：系统化调查，而非凭直觉<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E6%AD%A5%E9%AA%A4%E5%9B%9B%E7%B3%BB%E7%BB%9F%E5%8C%96%E8%B0%83%E6%9F%A5%E8%80%8C%E9%9D%9E%E5%87%AD%E7%9B%B4%E8%A7%89" class="hash-link" aria-label="步骤四：系统化调查，而非凭直觉的直接链接" title="步骤四：系统化调查，而非凭直觉的直接链接" translate="no">​</a></h2>
<p>“模型产生幻觉”永远不是根本原因。它只是对症状的描述。真正的根本原因始终存在于你围绕模型构建的系统中。</p>
<p>高效的调查应遵循层级，而非直觉：</p>
<p><strong>首先是检索层 (Retrieval layer)</strong>：如果你使用 RAG，系统是否检索到了相关的、准确的文档？发送到检索系统的查询是否准确捕捉到了用户的需求？当模型被迫从空白或误导性的上下文中生成内容时，经常会出现幻觉。</p>
<p><strong>其次是提示词层 (Prompt layer)</strong>：系统给模型下达了什么指令？是否存在相互矛盾的指令？是否有些指令在结合特定用户输入时，产生了意想不到的交互？Prompt 故障是系统性的——如果发生了一次，在类似条件下就会再次发生。</p>
<p><strong>再次是模型层 (Model layer)</strong>：只有在排除检索和 Prompt 故障后，才应检查模型本身。这是该模型系列已知的故障模式吗？你是否在有记录显示质量会下降的 Temperature 或上下文长度下观察到了故障？模型层面的故障是真实存在的，但它们很少是随机的——它们具有你可以发现的结构。</p>
<p><strong>最后是安全层 (Safety layer)</strong>：你的护栏 (guardrails) 在哪里，为什么它们没有捕捉到这一点？如果你有输出过滤器，它们给这次生成的评分是多少？如果你没有输出过滤器，那就是根本原因。</p>
<p>Meta 的生产环境根本原因分析平台——运行在 300+ 个团队中——发现，真正的根本原因分析需要对每一层进行系统化调查，并在每一步进行异常检测和维度分析。像“模型产生幻觉”这种单一因素的解释，只是无法产生任何有效修复措施的捷径。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="步骤五编写真正有帮助的事后分析报告-post-mortem">步骤五：编写真正有帮助的事后分析报告 (Post-Mortem)<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E6%AD%A5%E9%AA%A4%E4%BA%94%E7%BC%96%E5%86%99%E7%9C%9F%E6%AD%A3%E6%9C%89%E5%B8%AE%E5%8A%A9%E7%9A%84%E4%BA%8B%E5%90%8E%E5%88%86%E6%9E%90%E6%8A%A5%E5%91%8A-post-mortem" class="hash-link" aria-label="步骤五：编写真正有帮助的事后分析报告 (Post-Mortem)的直接链接" title="步骤五：编写真正有帮助的事后分析报告 (Post-Mortem)的直接链接" translate="no">​</a></h2>
<p>传统的事后分析报告 (Post-Mortem) 以行动项结束：添加测试、修复 Bug、改进监控。AI 事故的事后分析需要不同的结构，因为故障模式往往无法通过单元测试来消除。</p>
<p>该文档需要记录事故中保留了哪些数据，以及为什么这些数据充足或不足。如果你因为缺乏 Prompt 日志而无法重建时间线，那么补齐这个缺口就是一个行动项。如果你因为没有每个用户的生成日志而无法确定影响范围 (blast radius)，那也是一个行动项。</p>
<p>“哪里出了问题”部分应拒绝接受跳过层级的解释。如果草案写着“模型产生了有害输出”，那是不完整的。完整的版本应该说明是哪种检索或 Prompt 条件创建了上下文，导致产生了有害输出，以及为什么安全层没有拦截它。</p>
<p>修复措施应明确你要增加什么样的可观测性——不是为了再次检测同一起事故，而是为了检测该事故所属的故障类别。AI 系统的故障是有模式的。一个给错误的人发送邮件的 Agent，很可能是因为身份混淆故障。除非你在整个系统中增加对身份相关异常的监控，否则这种模式会以不同形式再次出现。</p>
<p>最后：建立观察期。与软件修复不同，AI 系统的修复措施不会提供明确的通过/失败信号。在更改 Prompt 或添加护栏后，应在一段有意义的时间内，监控系统在各种条件下的行为分布——而不是仅仅进行一次测试运行。随机性 (Stochastic) 系统需要持续观察，而非特定时间点的验证。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="责任的底层转变">责任的底层转变<a href="https://tianpan.co/zh/blog/2026-04-19-ai-incident-runbook-agent-harm#%E8%B4%A3%E4%BB%BB%E7%9A%84%E5%BA%95%E5%B1%82%E8%BD%AC%E5%8F%98" class="hash-link" aria-label="责任的底层转变的直接链接" title="责任的底层转变的直接链接" translate="no">​</a></h2>
<p>最重要的事故是那些用户信任你的系统并因此受到伤害的事故。一个给出危险医疗建议的聊天机器人。一个基于错误推理执行金融交易的智能体（Agent）。一个在被人发现之前已经默默损坏记录数周的文档处理系统。</p>
<p>这些不是 AI 开发中的边缘案例。它们是核心工程问题。构建一个有用的 AI 系统和构建一个安全的系统是同一个项目，而事故应对手册（Runbook）正是让这一切变得具体的载体。</p>
<p>所需的运行规范——记录一切、限制访问范围、在无需系统配合的情况下使其可中断、在不确定性下诚实沟通——并不光鲜。它不会出现在 Demo 中。但它正是区分能够将 AI 投入生产运行的团队与只能做演示的团队的标准。</p>
<p>当你的智能体造成伤害时，你的首要任务是限制这种伤害。你的第二优先级是理解它。你的第三优先级是构建一个让下一次事故更容易控制和理解的系统。现在从事这项工作的团队正在构建一些随着 AI 系统获得更多权限和更高自主性而变得愈发重要的东西。从一份认真对待随机（Stochastic）故障的 Runbook 开始，是正确的起点。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="incident-response" term="incident-response"/>
        <category label="llm" term="llm"/>
        <category label="production" term="production"/>
        <category label="reliability" term="reliability"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 输出的版权陷阱：工程师在演变成法律问题前需要了解的知识]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[训练数据记忆、演绎作品原则以及输出所有权是当前存在直接工程影响的法律争议。本文将介绍风险面以及能够切实降低法律责任的管控措施。]]></summary>
        <content type="html"><![CDATA[<p>当大语言模型在响应用户提示词时逐字复制受版权保护的文本，谁应该承担法律责任 —— 是模型提供商、构建产品的公司，还是输入查询的用户？在 2026 年，法院正在积极研究这一问题，其答案将直接影响你的生产系统。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E8%BE%93%E5%87%BA%E7%9A%84%E7%89%88%E6%9D%83%E9%99%B7%E9%98%B1%EF%BC%9A%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%9C%A8%E6%BC%94%E5%8F%98%E6%88%90%E6%B3%95%E5%BE%8B%E9%97%AE%E9%A2%98%E5%89%8D%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84%E7%9F%A5%E8%AF%86" alt="" class="img_ev3q"></p>
<p>大多数工程团队已经接受了这样一个基本叙事：“AI 训练可能会侵犯版权，但那是模型提供商的问题。” 这种叙事在两个重要方面是错误的。首先，基于输出的责任 —— 即模型在推理时产生的内容 —— 在很大程度上与训练数据责任是不同的，且在大多数司法管辖区仍是一个悬而未决的法律问题。其次，你认为从 AI 提供商那里获得的合同赔偿可能比你想象的要窄。</p>
<p>本文涵盖了工程团队面临的实际风险敞口：生产环境中的逐字记忆率（verbatim memorization rates）是怎样的，开源许可证污染如何真正在生成的代码中显现，企业级 AI 协议在哪里留下了风险缺口，以及哪些工程控制措施可以在不停止 AI 采用的情况下切实降低责任风险。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="工程师容易混淆的两个法律问题">工程师容易混淆的两个法律问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%AE%B9%E6%98%93%E6%B7%B7%E6%B7%86%E7%9A%84%E4%B8%A4%E4%B8%AA%E6%B3%95%E5%BE%8B%E9%97%AE%E9%A2%98" class="hash-link" aria-label="工程师容易混淆的两个法律问题的直接链接" title="工程师容易混淆的两个法律问题的直接链接" translate="no">​</a></h2>
<p>AI 版权讨论涉及两个需要不同防御策略的独立问题。</p>
<p><strong>训练数据责任</strong> 探讨模型提供商是否有权在特定数据集上进行训练。这是 NYT v. OpenAI 诉讼（截至 2026 年仍在进行中）、Anthropic 关于盗版书籍的纠纷（以每部受版权保护作品约 3,000 美元的价格和解，涉及约 500,000 部作品）以及英国 Getty Images v. Stability AI 案件的范畴。这些案例发生在权利持有者和模型提供商之间。你的公司不是被告，你的工程决策也不会影响结果。</p>
<p><strong>输出责任</strong> 是风险所在。当你的产品生成文本或代码，且用户或第三方声称该输出侵犯了他们的版权时，模型提供商的训练数据和解并不能为你提供盾牌。Anthropic 的和解协议明确排除了 Claude 生成的侵权输出索赔。大多数企业协议的结构也类似。你需要对产品产生的内容承担下游责任。</p>
<p>这种区别非常重要，因为许多团队投入大量精力根据模型提供商的训练数据实践来评估他们，却几乎不关注服务协议中的输出责任缺口。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="逐字记忆的真实情况">逐字记忆的真实情况<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E9%80%90%E5%AD%97%E8%AE%B0%E5%BF%86%E7%9A%84%E7%9C%9F%E5%AE%9E%E6%83%85%E5%86%B5" class="hash-link" aria-label="逐字记忆的真实情况的直接链接" title="逐字记忆的真实情况的直接链接" translate="no">​</a></h2>
<p>前沿大语言模型会记住训练数据。问题在于记住了多少，以及在什么条件下会触发。</p>
<p>对 GPT-3.5-turbo 的研究发现，在对抗性“发散攻击”（divergence attack）条件下 —— 即通过精心设计的提示词引导模型输出记忆内容 —— 超过 5% 的输出可能由训练数据中 50 个 token 序列的直接逐字副本组成。这种提取率比基线输出高出 150 倍。虽然该攻击方式已被公开披露且最明显的漏洞已修补，但底层的记忆现象依然存在。</p>
<p>研究人员在比较 GPT-4 和 Claude 2 在复制受版权保护书籍方面的表现时发现，在直接提示下，GPT-4 有 44% 的概率复现受版权保护的文本，而 Claude 的复现概率为 16%，且在被要求提供特定开头段落时完全拒绝。这些数字并不小 —— 几乎一半对前沿模型的直接提示都产生了受版权保护的内容。</p>
<p>更微妙的风险是研究人员所称的“马赛克记忆”（mosaic memory）：模型不再是精确的逐个 token 复现，而是从高度相似的序列中组合输出，这些序列在检测时可能不会被登记为逐字复制。研究表明，模糊重复（fuzzy duplicates）对功能性记忆的贡献约为精确重复的 0.8 倍，这意味着仅关注精确匹配的去重指标低估了实际风险。</p>
<p>具体到代码，在审计中发现 35% 的 GitHub Copilot 生成代码示例包含许可证异常。这不仅仅是企业风险 —— 出现在私有代码库中的 GPL 许可代码可能会触发开源传染（copyleft）义务，而不仅仅是包含该代码的文件。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="生成代码中的许可证污染问题">生成代码中的许可证污染问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E7%94%9F%E6%88%90%E4%BB%A3%E7%A0%81%E4%B8%AD%E7%9A%84%E8%AE%B8%E5%8F%AF%E8%AF%81%E6%B1%A1%E6%9F%93%E9%97%AE%E9%A2%98" class="hash-link" aria-label="生成代码中的许可证污染问题的直接链接" title="生成代码中的许可证污染问题的直接链接" translate="no">​</a></h2>
<p>开源许可证污染对于交付 AI 编程工具或使用 AI 生成代码构建内部工具的工程团队来说，是最具体且可衡量的版权风险。</p>
<p>风险运作方式如下：一个在包含 GPL 许可代码的语料库上训练的 AI 编程助手生成了一个函数。生成的代码可能在结构上源自训练集中的 GPL 许可实现。如果该代码最终进入你的私有产品，你可能会在没有任何人类开发人员知情复制的情况下触发 GPL 义务。</p>
<p>现实世界的成本已经开始显现。2024 年，一家法国电信公司因违反 GPL 被判支付超过 900,000 欧元的赔偿金 —— 这个案例发生在 AI 编程大规模普及之前，但它说明了大规模许可证执法的样子。据报道，多家财富 500 强公司在审计发现 AI 生成代码中存在许可证污染后，对其整个代码库进行了全面审查（在某些情况下甚至是重写）。</p>
<p>工程师面临的困难在于，“相似到足以触发 copyleft”目前还没有算法上的定论。实质性相似（substantial similarity）的法律标准是基于具体事实且存在争议的。虽然存在先进的许可证检测工具（大型科技公司内部使用），且有人提出了 DevLicOps 框架作为生命周期许可证管理的系统方法，但目前还没有现成的系统能对生成的代码给出绝对的“安全 / 不安全”结论。</p>
<p>实际影响是：对待接触私有产品的 AI 生成代码，应像对待外部供应商的代码一样 —— 假设它需要许可证审查，而不是在审计时才补救，而是作为开发工作流的一部分。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="你的-ai-供应商协议到底涵盖了什么">你的 AI 供应商协议到底涵盖了什么<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E4%BD%A0%E7%9A%84-ai-%E4%BE%9B%E5%BA%94%E5%95%86%E5%8D%8F%E8%AE%AE%E5%88%B0%E5%BA%95%E6%B6%B5%E7%9B%96%E4%BA%86%E4%BB%80%E4%B9%88" class="hash-link" aria-label="你的 AI 供应商协议到底涵盖了什么的直接链接" title="你的 AI 供应商协议到底涵盖了什么的直接链接" translate="no">​</a></h2>
<p>企业 AI 协议中的赔偿条款在不同供应商之间差异巨大，且经常被依赖它们的团队误解。</p>
<p>Google Cloud 的生成式 AI 赔偿保障是目前最广泛的。它涵盖了两个不同的领域：Google 使用训练数据侵犯第三方权利的索赔，以及 Gemini 或 Vertex AI 生成的未经修改的输出侵犯第三方权利的索赔。这种自动且广泛的输出保障确实少见，使 Google 的方案在企业采购谈判中脱颖而出。</p>
<p>OpenAI 的企业条款为源自服务本身的索赔提供赔偿，但明确排除了客户内容、客户应用程序以及与第三方产品的组合。赔偿涵盖了 OpenAI 构建的部分；它并不涵盖你的应用程序使用 OpenAI API 构建的部分。</p>
<p>Anthropic 关于训练数据责任的结算明确排除了基于输出的索赔。使用 Claude API 的企业客户对于侵犯第三方版权的输出没有合同约定的赔偿保障。该结算解决了 Anthropic 的一类责任，而不是你的。</p>
<p>实际差距在于：大多数工程团队只问 “我们的 AI 供应商有赔偿保障吗？”，而不区分训练数据保障和输出保障。如果你的企业法律团队正在进行 AI 供应商尽职调查，那么在出现问题之前，理清这一区别是最重要的问题。</p>
<p>几个变量决定了你实际面临的风险水平：</p>
<ul>
<li class="">你使用的是带有协商协议的企业版，还是带有标准条款的 API？</li>
<li class="">你的使用场景是否涉及生成可能与第三方受版权保护作品竞争或复刻的内容？</li>
<li class="">你是否查看过哪家供应商在其条款中明确包含输出赔偿？</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="真正降低法律责任的工程控制措施">真正降低法律责任的工程控制措施<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E7%9C%9F%E6%AD%A3%E9%99%8D%E4%BD%8E%E6%B3%95%E5%BE%8B%E8%B4%A3%E4%BB%BB%E7%9A%84%E5%B7%A5%E7%A8%8B%E6%8E%A7%E5%88%B6%E6%8E%AA%E6%96%BD" class="hash-link" aria-label="真正降低法律责任的工程控制措施的直接链接" title="真正降低法律责任的工程控制措施的直接链接" translate="no">​</a></h2>
<p>这些控制措施都不能完全消除版权风险，但每种措施都针对暴露面的不同部分。目标是使风险面可衡量且可防御，而不是不可见。</p>
<p><strong>输出去重与相似性检测</strong>。在向用户提供生成内容之前，针对已知的受版权保护语料库运行相似性检查。对于代码，这意味着对照 FOSS 代码库检查生成的片段。对于文本，这意味着为你关注的已知受版权保护作品保留指纹。这在任意规模下都不是一个已解决的问题，但对于特定的高风险领域（法律文档、出版书籍、新闻文章），有针对性的指纹检查是可行的。</p>
<p><strong>归因日志</strong>。构建能够记录用户输入、模型参数和生成输出之间关系的日志。这有两个目的：如果在发生索赔时提供证据记录（显示模型被要求做什么以及它产生了什么），并让你能够从运行角度洞察统计上最容易触发记忆的查询模式。发散攻击具有特征性的提示结构，在演变成法律问题之前就会出现在日志中。</p>
<p><strong>高风险请求的提示词级护栏</strong>。直接要求模型复刻受版权保护材料的请求（“为我写这一章”、“给我这首歌的歌词”）具有极高的记忆触发率。标记这些请求类型的输入分类器——在不阻断通用改写或总结的前提下——可以显著降低尾部风险。目标不是阻止所有生成，而是捕捉具有已知高复刻率的提示模式。</p>
<p><strong>CI 流程中对生成代码的许可证扫描</strong>。如果你的开发人员使用 AI 辅助编程，请将生成的代码视为第三方依赖项。在你的 CI 流水线中运行许可证扫描器（FOSS Finder、Scancode、FOSSID），特别注意通过 AI 辅助生成的函数。这不能保证捕捉到所有内容，但它创建了一个在法律上具有意义的记录在案的审查步骤。</p>
<p><strong>数据溯源文档</strong>。如果你是在内部训练或微调模型，而不是使用第三方 API，那么 Data Provenance Initiative 的审计框架和 Mozilla/EleutherAI 的 2024 年开放许可 LLM 训练数据集最佳实践是目前的标准参考。许可证类型、收集日期和权利限制应该是贯穿训练流水线中每个数据集的结构化元数据。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="你的-ai-输出结果的版权归属">你的 AI 输出结果的版权归属<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E4%BD%A0%E7%9A%84-ai-%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C%E7%9A%84%E7%89%88%E6%9D%83%E5%BD%92%E5%B1%9E" class="hash-link" aria-label="你的 AI 输出结果的版权归属的直接链接" title="你的 AI 输出结果的版权归属的直接链接" translate="no">​</a></h2>
<p>这个问题还有一个经常被忽视的维度：你的 AI 生成输出可能根本不受版权保护。</p>
<p>美国版权局关于 AI 与版权的第二部分报告（2025 年 1 月）确立了版权保护需要人类创作。仅凭提示词是不够的。人类创作微不足道（de minimis）的 AI 生成内容——这描述了大多数 AI 工具的输出——不会获得版权保护，这意味着竞争对手可以合法地复制你生成的 AI 营销文案、文档或产品内容而无需担心侵权。</p>
<p>工程层面的后果不那么明显：如果你正将 AI 生成的内容构建为竞争护城河，那么这个护城河在法律上可能无法防御。这并不意味着要避免 AI 生成的内容，但它确实意味着价值主张需要建立在系统、数据和工作流之上，而不是将输出文本本身作为受保护的资产。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="这对你的生产架构意味着什么">这对你的生产架构意味着什么<a href="https://tianpan.co/zh/blog/2026-04-19-ai-output-copyright-trap-llm-generated-code#%E8%BF%99%E5%AF%B9%E4%BD%A0%E7%9A%84%E7%94%9F%E4%BA%A7%E6%9E%B6%E6%9E%84%E6%84%8F%E5%91%B3%E7%9D%80%E4%BB%80%E4%B9%88" class="hash-link" aria-label="这对你的生产架构意味着什么的直接链接" title="这对你的生产架构意味着什么的直接链接" translate="no">​</a></h2>
<p>风险状况因用例而异，你需要的控制措施应与暴露程度成正比。</p>
<p><strong>高风险：</strong> 生成可能与第三方受版权保护作品竞争或重现其内容的文本或代码的系统。例如内部代码生成工具、内容创作平台、法律文件生成、新闻摘要。这些系统需要在企业 AI 协议中进行输出责任审查，并建立归属日志（attribution logging）和输出相似性检查。</p>
<p><strong>中等风险：</strong> 使用 AI 处理或分析现有内容但不逐字复制的系统。例如分类、实体提取、具有严格长度限制的摘要、结构化数据提取。记忆（Memorization）风险较低，但并非为零。</p>
<p><strong>较低风险：</strong> 模型基于结构化内部数据生成内容，且不接触训练语料库的系统。如果你的模型是在专有数据上进行微调的，且输出领域与受版权保护的作品不重叠，那么实际风险会显著降低。</p>
<p>更广泛的一点是，版权风险对于你的系统来说并不是一个非黑即白的“合法/不合法”问题——它是一个风险面，取决于用例、供应商协议以及你所采取的工程控制措施。那些将其视为法律问题并交给法律顾问解决的团队，正在犯与那些将安全性外包给合规检查表的团队相同的错误。</p>
<p>实际做法是：了解供应商的实际赔偿范围（针对输出，而不仅仅是训练）、在发生索赔之前添加归属日志，并将进入专有产品的 AI 生成代码默认视为需要进行许可审查。这些都不是法律团队该发明的工作——它们是发生在工具和工作流层面的工程决策。</p>
<p>法院仍在制定相关学说。你的生产系统不能干等着。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="legal" term="legal"/>
        <category label="compliance" term="compliance"/>
        <category label="llm" term="llm"/>
        <category label="security" term="security"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 审美难题：在没有标准答案时如何衡量质量]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[当准确性指标失去意义时，如何评估 AI 的输出——文案创作、创意内容和设计背后的两两比较研究、评分者间信度和 LLM 评审员的工程学科。]]></summary>
        <content type="html"><![CDATA[<p>大多数 AI 产品团队都会遇到这样一种场景：某位领导层成员询问新的文案生成模型是否比旧的好。团队运行了评估套件，准确率数据看起来不错，于是发布了模型。三周后，营销团队悄悄换回了旧模型，因为新模型“听起来不对劲”。准确率指标是真实的，只是他们衡量错了对象。</p>
<p>这就是 AI 品味问题。只要你的输出是主观的——文案创作、设计建议、创意内容、语气调整、风格推荐——它就会出现。当没有客观的基准事实（Ground Truth）时，传统的机器学习评估框架会给你一种虚假的自信。而大多数团队对于该如何应对并没有系统性的方案。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E5%AE%A1%E7%BE%8E%E9%9A%BE%E9%A2%98%EF%BC%9A%E5%9C%A8%E6%B2%A1%E6%9C%89%E6%A0%87%E5%87%86%E7%AD%94%E6%A1%88%E6%97%B6%E5%A6%82%E4%BD%95%E8%A1%A1%E9%87%8F%E8%B4%A8%E9%87%8F" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么准确率指标在主观输出中会失效">为什么准确率指标在主观输出中会失效<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E4%B8%BA%E4%BB%80%E4%B9%88%E5%87%86%E7%A1%AE%E7%8E%87%E6%8C%87%E6%A0%87%E5%9C%A8%E4%B8%BB%E8%A7%82%E8%BE%93%E5%87%BA%E4%B8%AD%E4%BC%9A%E5%A4%B1%E6%95%88" class="hash-link" aria-label="为什么准确率指标在主观输出中会失效的直接链接" title="为什么准确率指标在主观输出中会失效的直接链接" translate="no">​</a></h2>
<p>事实准确性评估背后的直觉很简单：模型要么说法国的首都是巴黎，要么没说。基准事实是稳定的、外部的且可验证的。你可以针对它计算精确率和召回率。</p>
<p>主观质量则不然。询问十位资深的文案撰稿人某个标题是否“吸引人”，你会得到真实的反馈分歧——这不是因为其中一些人错了，而是因为审美判断在不同的人、语境和受众之间确实存在差异。一个能引起 28 岁产品经理共鸣的标题，在 55 岁的 CFO 看来可能反应平平。这两种判断都没有错。</p>
<p>这产生了一个实际的后果：如果你试图将主观质量压缩成一个单一的准确率数字，你衡量的就不是质量，而是与标注训练数据的人的一致程度。你基于其构建评估的基准事实并非真正的基准事实；它只是某位标注者的意见，被提拔成了事实。</p>
<p>处理得好的团队会将主观评估视为一门独立的工程学科。而挣扎中的团队则将其视为一个不需要严谨对待的软性问题——直到营销团队开始抱怨。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="正确的基础成对比较优于绝对评分">正确的基础：成对比较优于绝对评分<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E6%AD%A3%E7%A1%AE%E7%9A%84%E5%9F%BA%E7%A1%80%E6%88%90%E5%AF%B9%E6%AF%94%E8%BE%83%E4%BC%98%E4%BA%8E%E7%BB%9D%E5%AF%B9%E8%AF%84%E5%88%86" class="hash-link" aria-label="正确的基础：成对比较优于绝对评分的直接链接" title="正确的基础：成对比较优于绝对评分的直接链接" translate="no">​</a></h2>
<p>解决基准事实问题最持久的方法是停止询问“这个输出有多好？”，而是开始询问“这两个输出中哪一个更好，为什么？”</p>
<p>成对比较避开了绝对量表的问题。你不需要定义一个 7/10 分的标题意味着什么。你只需要评估者做出相对判断，而人类在这一点上的一致性要高得多。这与 A/B 测试背后的洞察一致：即使绝对质量无法衡量，偏好也是可以衡量的。</p>
<p>将成对偏好转换为可靠排名的统计基础是 Bradley-Terry 模型。它为每个输出分配一个潜在强度参数，并将输出 A 优于输出 B 的概率建模为它们强度参数差异的函数。输入足够的成对比较，它就会产生一个带有明确不确定性估计的排序。Chatbot Arena——目前最权威的开源 LLM 基准测试——就使用 Bradley-Terry 作为其核心排名引擎，并结合 Bootstrap 重采样来生成每个模型得分的置信区间。</p>
<p>Elo 等级分是相同想法的一种近似，借用自国际象棋。它们在统计严谨性上不如 Bradley-Terry，但在有新输出不断加入的持续评估中更容易实现。100 点的 Elo 差异意味着在成对比较中大约有 64% 的预期胜率，这为你解释差距提供了一个有意义的方式。</p>
<p>一个实际的启示是：不要只收集偏好，要报告不确定性。两个模型版本之间 5 个点的 Elo 差异几乎可以肯定是噪声。在没有置信区间的情况下报告点估计值，是大多数排行榜式评估误导团队的地方。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="评分者信度绕不开的门槛">评分者信度：绕不开的门槛<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E8%AF%84%E5%88%86%E8%80%85%E4%BF%A1%E5%BA%A6%E7%BB%95%E4%B8%8D%E5%BC%80%E7%9A%84%E9%97%A8%E6%A7%9B" class="hash-link" aria-label="评分者信度：绕不开的门槛的直接链接" title="评分者信度：绕不开的门槛的直接链接" translate="no">​</a></h2>
<p>在分析偏好数据之前，你需要回答一个更难的问题：你的评估者之间真的达成一致了吗？如果两个标注者对同一对输出进行评分时有 40% 的时间意见不一，那么你的偏好数据基本上就是噪声，下游再多的统计机制也无法修复它。</p>
<p>衡量这一点的标准工具是 Cohen's kappa（用于两个评分者）或 Fleiss' kappa 和 Krippendorff's alpha（用于三个或更多评分者）。这些指标将观察到的一致性与随机预期的一致性进行比较。Kappa 为 0 意味着评分者的一致性不高于随机水平；Kappa 为 1 意味着完美一致。</p>
<p>对于实际的评估工作，重要的阈值包括：</p>
<ul>
<li class=""><strong>κ &lt; 0.40</strong>：丢弃数据。你的评分指南（Rubric）太模糊，评估者无法一致执行。</li>
<li class=""><strong>κ 0.41–0.60</strong>：中度一致。对于探索性工作尚可，但不能用于发布决策。</li>
<li class=""><strong>κ 0.61–0.80</strong>：高度一致。对于生产环境的评估是可以接受的。</li>
<li class=""><strong>κ &gt; 0.80</strong>：近乎完美。在真正的主观任务中很少见；通常预示着你的任务可能并不像你想象的那么主观。</li>
</ul>
<p>当你有多位标注者、缺失数据或定序尺度（在 AI 评估中很常见）时，Krippendorff's alpha 是更好的选择。大多数研究人员引用的阈值是 α ≥ 0.70，作为得出有意义结论的底线。</p>
<p>这是大多数团队都会跳过的一步：<strong>在收集大量数据之前，先进行评分者间的一致性检查</strong>。让两三位标注者对 30–50 个示例的试点样本进行标注，计算一致性，如果太低则修订你的评分指南。在收集了 2,000 个标签后才发现一致性很差，代价是极其昂贵的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="将主观质量分解为可衡量的维度">将主观质量分解为可衡量的维度<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E5%B0%86%E4%B8%BB%E8%A7%82%E8%B4%A8%E9%87%8F%E5%88%86%E8%A7%A3%E4%B8%BA%E5%8F%AF%E8%A1%A1%E9%87%8F%E7%9A%84%E7%BB%B4%E5%BA%A6" class="hash-link" aria-label="将主观质量分解为可衡量的维度的直接链接" title="将主观质量分解为可衡量的维度的直接链接" translate="no">​</a></h2>
<p>评估准则失败的一个原因是它们要求标注人员判断“整体质量”——这是一个将多个独立信号压缩成一个极其模糊指令的复合指标。</p>
<p>更好的方法是将质量分解为评估者可以独立评估的各个维度。对于文案写作，一套合理的维度可能是：</p>
<ul>
<li class=""><strong>清晰度 (Clarity)</strong>：意思是否显而易见？</li>
<li class=""><strong>说服力 (Persuasiveness)</strong>：文案是否激发了预期的行动？</li>
<li class=""><strong>品牌语调一致性 (Brand voice alignment)</strong>：听起来是否像这家公司的风格？</li>
<li class=""><strong>准确性 (Accuracy)</strong>：事实陈述是否正确？</li>
<li class=""><strong>简洁度 (Conciseness)</strong>：是否每个字都有其存在的价值？</li>
</ul>
<p>每个维度都有自己的成对比较或量表得分。这样做的好处是具有诊断性：你可以看到模型 B 在清晰度和简洁度上更好，但在品牌语调上较差，这为产品团队提供了可操作的反馈。将其压缩为整体质量会破坏这种信号。</p>
<p>这种分解还提高了评分者间的一致性 (Inter-rater reliability)。“哪一个更清晰？”比“哪一个更好？”更容易回答。评估者在主观判断上可能会出错，但当问题具体化时，他们的系统性错误会减少。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="损害结果的已知偏见">损害结果的已知偏见<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E6%8D%9F%E5%AE%B3%E7%BB%93%E6%9E%9C%E7%9A%84%E5%B7%B2%E7%9F%A5%E5%81%8F%E8%A7%81" class="hash-link" aria-label="损害结果的已知偏见的直接链接" title="损害结果的已知偏见的直接链接" translate="no">​</a></h2>
<p>即使是设计良好的评估研究，如果你不积极减轻影响人类（和 LLM）评估者的偏见，也会产生受损的数据。</p>
<p><strong>位置偏见 (Position bias)</strong> 是记录最一致的问题。当并排展示两个输出时，人类和 LLM 评审会系统性地偏向于首先或第二个展示的选项——这种效应可能会使结果波动超过 10 个百分点。标准的缓解措施是将每对输出交换顺序展示两次，只有当两次展示的结果一致时才宣布偏好。</p>
<p><strong>冗长偏见 (Verbosity bias)</strong> 对 LLM 作为评审系统的影响尤为严重。由于在人类反馈中训练时通常更偏好较长的回答，LLM 评审会对冗长的输出给出更高的分数，无论这些额外的文字是否有价值。在文案评估中，这表现为系统性地倾向于繁琐、复杂的文本，而不是精炼、有力的文字——这正是错误的信号。</p>
<p><strong>自我偏好偏见 (Self-preference bias)</strong> 虽然细微但真实存在。LLM 评审会给那些与其自身生成模式相似的输出打出更高的分数，即使输出的来源是隐藏的。这意味着：如果你使用 GPT-4 来评估 GPT-4 与 Claude 的输出，你进行的并不是中立的评估。</p>
<p><strong>评估者来源效应 (Evaluator source effects)</strong> 不仅仅是 LLM 的问题。临床环境的研究一致表明，人类评分者会给那些由与自己相似的人产生的内容打出更高的分数：临床医生给临床医生撰写的计划评分更高；工程师给工程师编写的规范评分更高。缓解措施是盲测——在评估前移除任何关于谁或什么产生了该输出的信号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="llm-作为评审何时使用何时不使用">LLM 作为评审：何时使用，何时不使用<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#llm-%E4%BD%9C%E4%B8%BA%E8%AF%84%E5%AE%A1%E4%BD%95%E6%97%B6%E4%BD%BF%E7%94%A8%E4%BD%95%E6%97%B6%E4%B8%8D%E4%BD%BF%E7%94%A8" class="hash-link" aria-label="LLM 作为评审：何时使用，何时不使用的直接链接" title="LLM 作为评审：何时使用，何时不使用的直接链接" translate="no">​</a></h2>
<p>大规模的人类评估非常昂贵。按照每个评估输出 0.10 到 1.00 美元计算，评估 100,000 个输出的成本为 10,000 到 100,000 美元。LLM 评审可以将这一成本降低两个数量级。</p>
<p>强大的 LLM 评审（GPT-4 级别或更高）在许多质量维度上与人类评估者的一致性达到 80–90%。这大致相当于人类评分者之间在相同任务上的一致性。对于初步筛选、开发迭代和分流，这种一致性率已经足够好了。</p>
<p>一个稳健的实际工作流是：使用 LLM 作为评审来过滤和分层你的候选输出；在与这些 LLM 判断校准过的代表性样本上使用人类评估；在边缘情况和最终决策中使用人类。在进行大规模应用之前，先在一个包含 100–200 个示例的预留集上验证你的 LLM 评审与人类偏好的一致性。如果一致性低于 75%，则该评审对你所在的领域校准得不够。</p>
<p>需要注意的失败模式：LLM 评审在未经验证的新任务、冗长程度与品牌语调需要权衡的领域，以及当你需要向非技术利益相关者（他们会问你为什么要用 AI 给 AI 评分）解释评估的合理性时，表现不佳。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="审美对齐问题">审美对齐问题<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E5%AE%A1%E7%BE%8E%E5%AF%B9%E9%BD%90%E9%97%AE%E9%A2%98" class="hash-link" aria-label="审美对齐问题的直接链接" title="审美对齐问题的直接链接" translate="no">​</a></h2>
<p>AI 品味问题最深层的版本不是方法论问题，而是概念问题。你的评估应该衡量谁的偏好？</p>
<p>一个设计在 Z 世代创意总监眼中可能是美丽的，而在 55 岁的受访高管眼中可能只是功能性但乏味的。这两种判断在内部都是自洽的。没有一个中立的框架可以对它们进行仲裁。当你为高度主观的 AI 输出构建评估系统时，你不可避免地是围绕某些人群的偏好、某些文化背景、某些对“好”的定义来构建的。</p>
<p>这在结构上与事实准确性问题不同。对于事实准确性，目标是收敛到基本事实 (Ground truth)。而对于审美对齐，没有收敛点——只有承认你的评估正在衡量与特定目标受众的对齐。</p>
<p>实际意义在于：明确你正在衡量谁的偏好。如果你的文案 AI 是为企业 B2B 买家优化的，那就让这部分人群成为评估群体。不要在通用人群中进行评估并假设结果可以迁移。“在评估中表现良好”与“营销团队讨厌它”之间的脱节，通常是由于评估人群与实际受众之间的不匹配。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="一个实用的工作流">一个实用的工作流<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E4%B8%80%E4%B8%AA%E5%AE%9E%E7%94%A8%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81" class="hash-link" aria-label="一个实用的工作流的直接链接" title="一个�实用的工作流的直接链接" translate="no">​</a></h2>
<p>综上所述，一种评估主观 AI 输出的可行且可靠的方法如下：</p>
<ol>
<li class=""><strong>将质量分解</strong>为 3–5 个具体的、可独立评估的维度。</li>
<li class=""><strong>组织一次校准会议</strong>，邀请 2–3 名领域专家针对 30–50 个样本进行评估。计算 Krippendorff's alpha。修改评分标准，直到 α ≥ 0.70。</li>
<li class=""><strong>收集成对比较数据</strong>，受访者应是代表你目标受众的群体，而非普通的众包人员。</li>
<li class=""><strong>将每一对样本展示两次</strong>并交换顺序；仅记录在两种排序中表现一致的偏好。</li>
<li class=""><strong>对偏好数据进行 Bradley-Terry 模型拟合</strong>。报告带有自助法（bootstrap）置信区间的排名。</li>
<li class=""><strong>针对留出的真人偏好样本验证 LLM 评测员（LLM judge）</strong>。在一致性达到 ≥ 75% 后，再大规模使用 LLM 评测员。</li>
<li class=""><strong>持续监测偏差</strong>：随着数据的积累，跟踪位置效应、评估者效应和人口统计学效应。</li>
</ol>
<p>这比运行准确率基准测试要费劲。但这也是唯一能告诉你，你的 AI 文案模型是确实变得更好了，还是仅仅只是变得不同了的方法。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="这如何改变你的评估策略">这如何改变你的评估策略<a href="https://tianpan.co/zh/blog/2026-04-19-ai-taste-problem-measuring-subjective-quality#%E8%BF%99%E5%A6%82%E4%BD%95%E6%94%B9%E5%8F%98%E4%BD%A0%E7%9A%84%E8%AF%84%E4%BC%B0%E7%AD%96%E7%95%A5" class="hash-link" aria-label="这如何改变你的评估策略的直接链接" title="这如何改变你的评估策略的直接链接" translate="no">​</a></h2>
<p>AI 的“审美”问题不会消失——它是支撑整个系统的关键。每一支在主观领域构建 AI 产品的团队都在解决这个问题，无论他们是否承认。那些将其视为具有明确方法论的工程问题的团队，能够产出值得信赖的评估结果。而那些只谈论“感觉（human vibes）”的人则是在盲目摸索。</p>
<p>好消息是工具链已经显著成熟。Bradley-Terry 模型的实现可以现成使用。像 Prolific 这样的平台为受控偏好研究提供了数据收集基础设施。LLM-as-judge 流水线也已成为标准。尚不那么普及的是系统应用这些工具的纪律性——例如在进行大规模数据收集之前测量评估者间一致性（inter-rater reliability），分解质量维度而非将其混为一谈，以及报告置信区间而非单一的估值点。</p>
<p>市场团队抱怨新模型“听起来不太对劲”其实是在为你提供信息。在发布之前，建立一个能够捕捉这些信息的评估系统，才是值得解决的工程问题。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai" term="ai"/>
        <category label="evaluation" term="evaluation"/>
        <category label="ml" term="ml"/>
        <category label="product" term="product"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[AI 技术债的三座无声时钟]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[与代码债务不同，AI 特有的技术债——提示词漂移、评估侵蚀和嵌入陈旧——会以隐蔽的方式累积。本文将介绍如何在这些时钟耗尽之前检测它们。]]></summary>
        <content type="html"><![CDATA[<p>传统的技术债务往往会自我显现。构建缓慢、测试失败、或是被抑制了六个月的 lint 警告——这些都是你可以通过 grep 搜索、转化为工单并排入冲刺（sprint）的症状。AI 特有的债务则不同。它在部署的间隙中悄然累积，在任何人意识到数据波动之前，它就已经降低了系统的性能。</p>
<p>大多数生产环境中的 AI 系统现在都有三个正在滴答作响的“债务时钟”。第一个是当特定模型版本流行时才有意义的提示词（prompt）。第二个是在构建时能代表用户行为，但现在已经过时的评估集（evaluation set）。第三个是仍在支撑检索层的嵌入（embeddings）索引，它们是由早已被弃用的模型生成的。每个时钟独立运行。三者共同叠加。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=AI%20%E6%8A%80%E6%9C%AF%E5%80%BA%E7%9A%84%E4%B8%89%E5%BA%A7%E6%97%A0%E5%A3%B0%E6%97%B6%E9%92%9F" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="ai-债务的问题在于它表现得如同系统依然可靠">AI 债务的问题在于，它表现得如同系统依然可靠<a href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness#ai-%E5%80%BA%E5%8A%A1%E7%9A%84%E9%97%AE%E9%A2%98%E5%9C%A8%E4%BA%8E%E5%AE%83%E8%A1%A8%E7%8E%B0%E5%BE%97%E5%A6%82%E5%90%8C%E7%B3%BB%E7%BB%9F%E4%BE%9D%E7%84%B6%E5%8F%AF%E9%9D%A0" class="hash-link" aria-label="AI 债务的问题在于，它表现得如同系统依然可靠的直接链接" title="AI 债务的问题在于，它表现得如同系统依然可靠的直接链接" translate="no">​</a></h2>
<p>经典的技术债务是一种有意识的权衡：为了更快交付而偷工减料，记录下来，并放入积压工作（backlog）中。你知道它的存在。</p>
<p>AI 特有的债务并非如此。一个旅游预订助手的任务成功率可以从 92% 下降到 83%，而代码库没有任何变化。提示词完全相同。底层业务逻辑未被触及。改变的是模型在 API 端点的行为——可能是来自供应商的静默更新、用户请求分布的变化，或者是与流水线中下游提示词的微妙交互。日志看起来很正常，因为“代码或提示词都没有改变；系统的行为只是开始发生漂移。”</p>
<p>这是 AI 债务的特征：在衡量正确的指标之前，这种退化表现得如同系统依然可靠。</p>
<p>软件工程文献中描述了一个机器学习特有的原则，称为 CACE —— 牵一发而动全身（Changing Anything Changes Everything）。在传统软件中，你可以更改一个函数而不影响无关的函数。在 LLM 流水线中，更改一个提示词会改变每一个下游提示词的输入。更新嵌入模型会使索引中的每个向量失效。这种互联性使得债务以打破常规思维模型的方式级联发生。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="债务时钟之一提示词漂移">债务时钟之一：提示词漂移<a href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness#%E5%80%BA%E5%8A%A1%E6%97%B6%E9%92%9F%E4%B9%8B%E4%B8%80%E6%8F%90%E7%A4%BA%E8%AF%8D%E6%BC%82%E7%A7%BB" class="hash-link" aria-label="债务时钟之一：提示词漂移的直接链接" title="债务时钟之一：提示词漂移的直接链接" translate="no">​</a></h2>
<p>提示词漂移是指提示词最初的设计目标与模型当前实际执行效果之间的逐渐失配。</p>
<p>模型供应商会向 API 端点推送行为更新，且并不总是公之于众。即使是固定在 <code>gpt-4o-2024-08-06</code> 的版本也无法幸免——即使是名义上锁定的版本，在不同时段之间也会表现出意想不到的行为偏移。一项跟踪 15 个提示词类别、共 2,250 条模型响应的研究发现，GPT-4 的响应长度随时间产生了 23% 的偏差，而某供应商的旗舰模型在同一个六个月窗口内，指令遵循的一致性下降了 31%。</p>
<p>更隐蔽的触发因素是输入分布偏移。你的客户群在增长、变化，或者找到了新的表达方式，而这些是你的提示词在编写时并未考虑到的。从大多数定义来看，提示词仍然“有效”——它能解析，也能返回结果——但它在实际生产查询中的有效性已经下降。如果没有在正确的粒度上进行监控，这是不可见的。</p>
<p>多步流水线会放大这一点。当你串联四五个 LLM 调用时，第一步的提示词漂移会改变第二步看到的输入。第二步的提示词可能是针对第一步的特定输出进行微调的。现在它接收到了不同的输入，其自身的行为也会随之改变——不是因为它的提示词变了，而是因为它的上下文变了。</p>
<p><strong>待监控指标：</strong></p>
<ul>
<li class="">明确固定模型版本。永远不要在生产环境中使用自动更新的别名。</li>
<li class="">跟踪输出长度、格式合规性以及连续时间段之间的语义相似度。这些信号中的任何突然波动都预示着在用户察觉失败之前发生了漂移。</li>
<li class="">每周针对生产流量的固定样本运行以 LLM 作为裁判（LLM-as-judge）的评估。对指令遵循、语气和事实性进行评分。如果相对下降超过 10%，则应触发调查。</li>
<li class="">使用真实的生产案例而非合成案例来构建回归测试套件。合成测试无法捕捉到实际用户行为中积累的边缘案例。</li>
</ul>
<p>实施结构化提示词监控的团队报告称，LLM 相关问题的调试时间减少了 50%，提示词迭代速度提高了三倍。这些监控设施很快就能收回成本。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="债务时钟之二评估集侵蚀">债务时钟之二：评估集侵蚀<a href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness#%E5%80%BA%E5%8A%A1%E6%97%B6%E9%92%9F%E4%B9%8B%E4%BA%8C%E8%AF%84%E4%BC%B0%E9%9B%86%E4%BE%B5%E8%9A%80" class="hash-link" aria-label="债务时钟��之二：评估集侵蚀的直接链接" title="债务时钟之二：评估集侵蚀的直接链接" translate="no">​</a></h2>
<p>评估集是构建时所关注内容的快照。它反映了你的团队当时想到的边缘案例、当时出现的故障模式，以及当时的视角下的用户行为分布。如果你是六个月前构建的，且之后从未触及，那么它可能正在衡量错误的东西。</p>
<p>评估集侵蚀是指当你的测试集偏离生产现实，而模型保持不变时发生的情况。你运行评估，数据看起来没问题，但你的用户却在经历测试套件根本没有覆盖的质量下降。</p>
<p>这种失败模式非常微妙。由用户数据构建的评估集往往“过于干净”——它反映了在你的产品找到真正受众之前，或者在某个特定功能驱动新类型流量之前的查询。当这种新流量到来时，它会触发你的评估从未测试过的模型行为。一项比较分布偏移数据集微调的研究发现，F1 性能下降了 63 个百分点——这是一种灾难性的退化，而在原始评估集上进行拆分测试（split-test）的方法将完全忽略这一点。</p>
<p>更深层次的问题是组织架构上的。评估集往往是在发布或重大模型升级期间通过突击努力构建的，然后就被闲置了。它们没有负责人。没有人负责更新它们。随着产品演进，它们只能积满灰尘。</p>
<p><strong>待构建项：</strong></p>
<ul>
<li class="">将评估集视为具有负责人和审核周期的动态资产。</li>
<li class="">每周抽取新鲜的生产查询，并按比例路由到评估流水线中。对抽样查询进行聚类，并将聚类分布与现有评估集进行比较——偏差会告诉你覆盖范围在哪里退化。</li>
<li class="">使用群体稳定性指数（PSI）来衡量评估集与生产流量之间的特征分布偏移。在任何关键维度上，PSI 超过 0.2 都意味着评估集需要在该区域补充新案例。</li>
<li class="">建立季度评估审计机制：提取 200 个近期的生产案例，让模型进行评分，并与历史评估基准进行比较。明显的下降意味着你的评估集不再具有代表性。</li>
</ul>
<p>目标不是每季度从头开始重建评估。而是在生产环境已经发生变化而测试集尚未跟进的领域增加覆盖范围。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="债务时钟之三embedding-过时">债务时钟之三：Embedding 过时<a href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness#%E5%80%BA%E5%8A%A1%E6%97%B6%E9%92%9F%E4%B9%8B%E4%B8%89embedding-%E8%BF%87%E6%97%B6" class="hash-link" aria-label="债务时钟之三：Embedding 过时的直接链接" title="债务时钟之三：Embedding 过时的直接链接" translate="no">​</a></h2>
<p>Embedding 过时是生产系统中存在最久的 AI 技术债务时钟，而且它往往最难被察觉，因为 RAG 检索的退化是平滑的 —— 它只是开始返回稍差的结果，频率也只是稍微降低，直到用户完全不再信任该系统。</p>
<p>过时问题有两个截然不同的诱因。第一个是语料库过时：索引中的文档已被更新、取代或仅仅是陈旧了，但它们仍被检索并展示给用户。第二个是模型对齐失效：生成索引的 Embedding 模型已更新或弃用，但你的向量从未重新生成。现在的查询是由与生成文档向量时不同的模型进行 Embedding 的，这引入了系统性的不匹配，导致检索质量全面下降。</p>
<p>生产环境中的 RAG 系统通常只有在尝试添加新文档并注意到混合查询的检索质量下降时，才会发现模型对齐失效的问题。到那时，语料库已经提供了数周或数月陈旧的表示。</p>
<p>基础设施的现实情况使这一问题更加恶化。对一个拥有 1000 万文档的语料库进行 Embedding，仅初始运行的计算成本就达 300 到 650 美元。团队为了避免这项支出而理性地推迟重新生成 Embedding，这意味着过时窗口在不断扩大。由于检索质量是逐渐退化而非灾难性崩溃，很少有一个明显的时刻能触发修复。</p>
<p><strong>实施建议：</strong></p>
<ul>
<li class="">跟踪每个文档 Embedding 的来源和生成日期。建立自动化的新鲜度检查，标记超过预设年龄阈值的文档。</li>
<li class="">进行每周质量评估：选取 50 到 100 个固定的测试查询，并将检索结果与一个月前的基准进行对比。这组固定查询的召回率和准确率能告诉你检索层是否正在退化。</li>
<li class="">更新 Embedding 模型时，在弃用旧模型之前先制定迁移计划。采取增量方式重新生成 Embedding，从流量最高的文档片段开始。</li>
<li class="">考虑混合检索 —— 将稠密向量搜索与稀疏关键词匹配相结合 —— 作为对抗 Embedding 过时的对冲手段。稀疏组件不会以同样的方式退化，可以在向量质量下降时进行补偿。</li>
</ul>
<p>分布式系统增加了另一个维度：如果你的 Worker 持有内存索引，它们看不到其他 Worker 写入的更新。这不是一个理论上的担忧 —— 这是一个常见的生产环境陷阱，会导致同一服务的不同实例对同一查询返回不同的结果。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="季度审计规程">季度审计规程<a href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness#%E5%AD%A3%E5%BA%A6%E5%AE%A1%E8%AE%A1%E8%A7%84%E7%A8%8B" class="hash-link" aria-label="季度审计规程的直接链接" title="季度审计规程的直接链接" translate="no">​</a></h2>
<p>这三个债务时钟并不需要通过完全重新架构来管理。它们需要的是一个按可预测节奏运行的维护规程。</p>
<p>每季度一次是一个合理的默认选择。审计包含五个部分：</p>
<p><strong>Prompt 审查。</strong> 提取过去 90 天的 Prompt 性能指标。对于每个生产环境的 Prompt，将当前得分分布与上季度的基准进行对比。标记任何显示相对退化超过 15% 的 Prompt。检查被标记的 Prompt，重点关注指令清晰度、模型版本固定和测试覆盖率。</p>
<p><strong>评估覆盖率检查。</strong> 抽取 200 到 300 个近期生产环境的查询，并按意图和主题进行聚类。将聚类分布与你现有的评估集进行对比。增加代表性不足的聚类示例。剔除不再反映真实流量的聚类示例。</p>
<p><strong>Embedding 新鲜度扫描。</strong> 运行 Embedding 来源检查。在高检索量的语料库片段中，任何早于新鲜度阈值的文档都应排队重新生成 Embedding。如果 Embedding 模型在上一季度进行了更新，请评估影响并安排迁移。</p>
<p><strong>漂移指标审查。</strong> 提取过去 90 天的 PSI、输出方差和检索准确率趋势，并将它们整合到一个视图中。任何相对于基准变动超过 20% 的指标都应落实负责人和修复时间表。</p>
<p><strong>可观测性差距评估。</strong> 识别 AI 流水线中哪些环节没有监控手段，并安排覆盖。未被监控的流水线阶段是静默债务累积最快的地方。</p>
<p>总的时间投入是每季度几个工程师日。这并非微不足道，但远低于在债务复利导致用户可见的质量退化后再去应对的成本。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="潜在的转变">潜在的转变<a href="https://tianpan.co/zh/blog/2026-04-19-ai-technical-debt-prompt-drift-eval-erosion-embedding-staleness#%E6%BD%9C%E5%9C%A8%E7%9A%84%E8%BD%AC%E5%8F%98" class="hash-link" aria-label="潜在的转变的直接链接" title="潜在的转变的直接链接" translate="no">​</a></h2>
<p>传统的技术债务假设环境是静态的：代码本身不会改变行为。AI 系统则不然。提供商的模型会更新，用户与产品的交互方式会改变，语料库中的文档会老化，评估分布会漂移 —— 这一切都在持续发生，而且大部分发生时你的代码库没有任何变化。</p>
<p>这意味着 AI 系统需要以传统软件不需要的方式进行持续的管理。这不像是一个你每隔几年重构一次的代码库，它更接近于生产数据库：你持续监控它，定期运行维护任务，并将退化视为调查信号，而不是一个只能默默忍受的谜团。</p>
<p>三个债务时钟正在滴答作响。运行季度审计规程是你准确掌握时间的办法。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="llmops" term="llmops"/>
        <category label="technical-debt" term="technical-debt"/>
        <category label="production-ai" term="production-ai"/>
        <category label="mlops" term="mlops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[标注经济学：每种标签来源背后隐藏的代价]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[在评测标签来源的选择上——人类领域专家、众包工人、LLM 合成生成和行为推断——的决策框架，以及何时「无标注」才是正确答案。]]></summary>
        <content type="html"><![CDATA[<p>大多数团队在选择标注策略时，都会比较单价：众包工人大约 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0.08</mn><mi mathvariant="normal">/</mi><mtext>条，</mtext><mi>L</mi><mi>L</mi><mi>M</mi><mtext>生成不到</mtext></mrow><annotation encoding="application/x-tex">0.08/条，LLM 生成不到 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em"></span><span class="mord">0.08/</span><span class="mord cjk_fallback">条，</span><span class="mord mathnormal">LL</span><span class="mord mathnormal" style="margin-right:0.109em">M</span><span class="mord cjk_fallback">生成不到</span></span></span></span>0.003/条，人类领域专家约 $1/条。跑一遍表格，选出看起来"足够好"的最便宜选项，然后上线。这套算法经常让团队陷入麻烦。</p>
<p>真正的决策并非只看单条标签的成本。每种标签来源都有一个隐藏的质量税——以垃圾梯度、误导性评估曲线，或花费数月排查生产故障的形式复利叠加；而干净的标签本可以在训练阶段就捕获这些问题。最便宜的来源往往是计入下游信任成本后最昂贵的一种。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E6%A0%87%E6%B3%A8%E7%BB%8F%E6%B5%8E%E5%AD%A6%EF%BC%9A%E6%AF%8F%E7%A7%8D%E6%A0%87%E7%AD%BE%E6%9D%A5%E6%BA%90%E8%83%8C%E5%90%8E%E9%9A%90%E8%97%8F%E7%9A%84%E4%BB%A3%E4%BB%B7" alt="" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="四种来源及其真实权衡">四种来源及其真实权衡<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E5%9B%9B%E7%A7%8D%E6%9D%A5%E6%BA%90%E5%8F%8A%E5%85%B6%E7%9C%9F%E5%AE%9E%E6%9D%83%E8%A1%A1" class="hash-link" aria-label="四种来源及其真实权衡的直接链接" title="四种来源及其真实权衡的直接链接" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="人类领域专家">人类领域专家<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E4%BA%BA%E7%B1%BB%E9%A2%86%E5%9F%9F%E4%B8%93%E5%AE%B6" class="hash-link" aria-label="人类领域专家的直接链接" title="人类领域专家的直接链接" translate="no">​</a></h3>
<p>专家标注的单价约为 $1/条，是最贵的选项，也是最常被用在不该用的地方、最少被用在该用的地方的一种。</p>
<p>专家标注的隐性税是吞吐量和一致性。一位神经科医生每小时可能标注 50 份放射报告；三人团队则会引入无法通过裁决完全消除的标注者间方差。获得 10,000 条干净标签需要数周时间，还要耗费精力搭建标注界面、撰写标注指南、组织对齐会议——第一条干净标签才算出炉。</p>
<p><strong>适用场景</strong>：任务需要真正的领域知识，而这种知识无法在提示词中完全规范化（临床判断、法律歧义、安全关键边缘案例）；错误标签的代价极高；或你在构建用于校准其他标注方法的"黄金集"。</p>
<p><strong>不适用场景</strong>：任务标准明确且客观——格式检查、结构化数据的事实抽取、规则清晰的分类。为一个逻辑规则即可可靠完成的决策付 $1，不值得。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="众包工人">众包工人<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E4%BC%97%E5%8C%85%E5%B7%A5%E4%BA%BA" class="hash-link" aria-label="众包工人的直接链接" title="众包工人的直接链接" translate="no">​</a></h3>
<p>众包平台承诺以低成本实现规模化。现实是平台质量已大幅下滑。标签不一致、工人钻规则漏洞、以及越来越多的非人类参与者，使得基准质量保证比五年前更弱。你为标签付了钱，又为降噪再付一次。</p>
<p>单条标注成本看起来有吸引力，但在文本任务上，众包工人的标注一致性通常低于训练有素的专家或现代 LLM。根据已发表的基准数据，情感分类或意图分类等有清晰标签的任务，众包工人与 LLM 在与真实标签的一致率上相差约 25 个百分点。</p>
<p>此处的隐性税是质量管理开销。你需要试点轮次、垃圾检测、每条 3–5 人多数投票，以及过滤流水线。质量控制后的有效成本往往接近原始 LLM 成本——还更慢。</p>
<p>众包工人仍适用于需要人类感知判断的任务（图像美感、语音自然度），或需要真正主观多样性的场景——即你<strong>希望</strong>从人类视角分布中采样，而非收敛到单一"正确"答案。对于这类任务，众包方差是信号，不是噪声。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="llm-合成生成">LLM 合成生成<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#llm-%E5%90%88%E6%88%90%E7%94%9F%E6%88%90" class="hash-link" aria-label="LLM 合成生成的直接链接" title="LLM 合成生成的直接链接" translate="no">​</a></h3>
<p>经济账面上非常诱人：每条不到 $0.003，日吞吐量可达数百万条，除 API Key 外无需其他基础设施。而且对于许多任务，质量经得住考验。在文本分类基准上，最先进的 LLM 与真实标签的一致率约 88%，而熟练人工标注者约为 86%——且速度快 20 倍。</p>
<p>但合成生成有一种在聚合准确率数字中不会显现的失效模式：系统性偏差。在特定数据分布上训练的 LLM 会将该分布反映在其标注中。当你使用同一模型家族来生成标签和评估标签时，你构建了一个闭环——模型在给自己的作业打分。准确率看起来很高，生产性能却是另一回事。</p>
<p>需要警惕的具体失效模式：</p>
<ul>
<li class=""><strong>标签平滑伪影</strong>：即使对模糊项，LLM 也倾向于给出高置信度标签，而人类会在此犹豫。训练信号看起来干净，模型变得脆弱。</li>
<li class=""><strong>分布偏差</strong>：如果标注模型经过 RLHF 倾向于某些响应风格，它会在标签中偏向这些风格。微调模型学会模仿标注者的风格，而非底层任务。</li>
<li class=""><strong>幻觉合理性</strong>：对于开放式生成任务，LLM 会产生看起来正确但微妙错误的标签，这些错误只在对抗性输入或边缘案例中才会浮现。</li>
</ul>
<p><strong>LLM 生成标签适用场景</strong>：任务具有可验证结构（可查证答案的事实 QA、模式验证、格式合规），标注标准可以在提示词中完全规定，且你用这些标签做训练或过滤——而非最终评测的真实标签。</p>
<p>永远不要将 LLM 生成的标签作为生产评测的参考集。那是唯一需要不继承模型偏差的真实标签的地方。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="从生产日志推断行为">从生产日志推断行为<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E4%BB%8E%E7%94%9F%E4%BA%A7%E6%97%A5%E5%BF%97%E6%8E%A8%E6%96%AD%E8%A1%8C%E4%B8%BA" class="hash-link" aria-label="从生产日志推断行为的直接链接" title="从生产日志推断行为的直接链接" translate="no">​</a></h3>
<p>这是团队晚发现、然后停不下来的标注来源。用户与你部署的系统交互时，会持续产生隐式质量信号：重试查询暗示第一个回答失败，复制输出暗示有用，回答后重新措辞表示不对齐。这些都不需要标注合同。</p>
<p>成本在金钱层面接近零。隐性税是选择偏差和延迟。</p>
<p><strong>选择偏差</strong>：只有活跃用户才会产生丰富的行为信号。得到糟糕答案后默默流失的用户不会出现在你的反馈日志中。你所观察到的系统性偏向坚持使用的用户——这一子群体可能无法代表你的实际用户分布。基于这些信号训练，会针对活跃用户群体中的参与度优化，而非为全体用户提升质量。</p>
<p><strong>延迟</strong>：行为信号需要时间积累。如果你的评测循环运行在新鲜的生产标签上，可能是在对昨天的查询进行评测，但没有任何行为信号。反馈延迟依任务而异：代码助手可能在几秒内得到隐式反馈（代码能跑吗？）；长文写作助手可能需要数小时才能看到有意义的参与信号。</p>
<p>行为推断最适合作为<strong>监控信号</strong>而非训练标签。随时间观察重试与完成比率，能比任何静态评测集更快、更可靠地告诉你模型质量何时下降。将其作为主要训练信号需要大多数团队会跳过的细心去偏处理。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="决策框架">决策框架<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E5%86%B3%E7%AD%96%E6%A1%86%E6%9E%B6" class="hash-link" aria-label="决策框架的直接链接" title="决策框架的直接链接" translate="no">​</a></h2>
<p>正确的来源策略取决于三个变量：任务复杂度、所需标签质量和可用数量。</p>
<p><strong>高复杂度、低数量任务</strong>（安全评估、医疗或法律判断、细致的偏好排序）：使用领域专家，即便 $1/条。成本是真实的；这个领域中糟糕标签的代价更高。</p>
<p><strong>中等复杂度、中等数量任务</strong>（意图分类、语气检测、事实 QA、标准清晰的文档分类）：LLM 生成标签是正确的起点。对样本进行人工审查以验证提示词对齐，然后扩展规模。</p>
<p><strong>需要感知或主观多样性的任务</strong>（图像质量、语音自然度、创意偏好）：众包工人提供 LLM 无法复制的真实方差。投入质量控制，并为过滤开销做好计划。</p>
<p><strong>监控和回归检测</strong>：来自生产日志的行为推断是最快、最廉价的信号。用它在出现异常时触发人工审查，而不是单独作为训练来源。</p>
<p>对大多数发布 LLM 功能的团队，实用的默认方案是：用 LLM 生成标签获取数量，按约 1:50 的比例用人工审查验证随机样本，并构建一个小型专家标注的黄金集（200–500 条示例），永远不混入训练，始终用于最终评估。这给了你规模加上质量锚点。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="何时无标注才是正确答案">何时"无标注"才是正确答案<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E4%BD%95%E6%97%B6%E6%97%A0%E6%A0%87%E6%B3%A8%E6%89%8D%E6%98%AF%E6%AD%A3%E7%A1%AE%E7%AD%94%E6%A1%88" class="hash-link" aria-label="何时&quot;无标注&quot;才是正确答案的直接链接" title="何时&quot;无标注&quot;才是正确答案的直接链接" translate="no">​</a></h2>
<p>并非每个评估问题都需要标注数据。无参考评估方法已相当成熟，对于某些类别的问题，它们是正确工具——而非妥协。</p>
<p><strong>格式和模式合规性</strong>——输出是否匹配所需的 JSON 结构、是否在长度限制内、是否包含必填字段——根本不需要标签。程序化验证器比任何标注方法都更便宜、更快、更一致。</p>
<p><strong>安全性和毒性筛查</strong>，基于大型开放数据集训练的嵌入分类器往往优于任务特定标注。你在检测一种分布属性，而非任务特定判断。</p>
<p><strong>一致性评估</strong>——检查模型对语义等价输入是否给出相似答案——无标注比较信号效果很好。生成释义对，测量输出方差，标记分歧。不需要标签。</p>
<p><strong>不适用无标注的场景</strong>：你在主观维度上测量任务质量（有用性、准确性、深度），任务没有可程序化验证的正确答案，或你需要可对外报告的结果。在这些情况下，你需要真实标签，且需要诚实说明是哪种来源生成的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="混合方法">混合方法<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-economy-label-sourcing-eval#%E6%B7%B7%E5%90%88%E6%96%B9%E6%B3%95" class="hash-link" aria-label="混合方法的直接链接" title="混合方法的直接链接" translate="no">​</a></h2>
<p>处理这一问题出色的团队不会只选一种来源——而是分层叠加。LLM 生成标签覆盖训练和回归测试的数量。小型专家标注集为评测提供真实标签。行为信号支撑在线监控仪表盘。众包工人在特定维度需要主观多样性时填补空白。</p>
<p>错误在于把错误的层用到错误的工作上。LLM 标签作为你的生产评测锚点，迟早会误导你。每条训练样本都用专家标注，标注预算在数据足够训练之前就会耗尽。以行为信号作为主要训练来源，会悄悄地只为你最活跃的用户的行为优化，其他一概不管。</p>
<p>每种标注来源的共同点，是一个在单价中不可见的隐性质量成本。建立对这些成本的认知模型——而不只是每条标签的费率——正是区分能可靠发布 LLM 功能的团队，与那些永远被生产故障——而这些故障本该被评测提前捕获——搞得措手不及的团队的关键所在。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="evaluation" term="evaluation"/>
        <category label="annotation" term="annotation"/>
        <category label="llm" term="llm"/>
        <category label="mlops" term="mlops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[无需标注的评估：在拥有标准答案前衡量 LLM 质量]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[一份在第一周 —— 即在你拥有标注数据之前 —— 衡量 LLM 输出质量的实用指南。涵盖了自我一致性、约束满足、行为不变性以及 LLM 作为裁判（LLM-as-judge），并探讨了每种方法的失效模式。]]></summary>
        <content type="html"><![CDATA[<p>大多数团队在发布 LLM 功能后，会花费数周时间争论该功能是否真的好用。由于构建标注数据集感觉像是一个独立的项目，评估问题往往被推迟。当你有了标准答案（ground truth）时，你也积累了两个月无法诊断的沉默回归。这本末倒置了。如果你知道该采用哪些技术以及每种技术的局限性，你可以在第一周——在完成任何标注之前——就获得有意义的质量信号。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E6%97%A0%E9%9C%80%E6%A0%87%E6%B3%A8%E7%9A%84%E8%AF%84%E4%BC%B0%EF%BC%9A%E5%9C%A8%E6%8B%A5%E6%9C%89%E6%A0%87%E5%87%86%E7%AD%94%E6%A1%88%E5%89%8D%E8%A1%A1%E9%87%8F%20LLM%20%E8%B4%A8%E9%87%8F" alt="" class="img_ev3q"></p>
<p>这篇文章是无标注评估的实战指南：涵盖了有效的无引用方法、所需条件，以及如果不小心就会误导你的特定失败模式。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么稍后评估是一个-bug而不是一个计划">为什么“稍后评估”是一个 Bug，而不是一个计划<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E4%B8%BA%E4%BB%80%E4%B9%88%E7%A8%8D%E5%90%8E%E8%AF%84%E4%BC%B0%E6%98%AF%E4%B8%80%E4%B8%AA-bug%E8%80%8C%E4%B8%8D%E6%98%AF%E4%B8%80%E4%B8%AA%E8%AE%A1%E5%88%92" class="hash-link" aria-label="为什么“稍后评估”是一个 Bug，而不是一个计划的直接链接" title="为什么“稍后评估”是一个 Bug，而不是一个计划的直接链接" translate="no">​</a></h2>
<p>推迟评估的常规理由是：良好的评估需要标准答案，标准答案需要标注，而标注需要时间和预算。对于某些评估技术来说，这是事实。但并非对所有技术都如此。</p>
<p>推迟的真实代价是你会失去进行因果推论的能力。当你三个月后发现质量问题时，你不知道它是由最新的提示词（prompt）更改、模型 API 更新、用户查询分布的变化，还是预处理中的 Bug 引起的。如果没有尽早建立基准——即使是不完善的基准——你的回顾式调试就只能靠猜测。</p>
<p>无标注评估并不是标准答案的永久替代品。它是在你拥有标签之前建立信号的一种方式，这样当你确实获得标签时，你可以利用它们来进行校准和扩展，而不是从头开始构建一切。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="自我一致性来自你自备模型的免费信号">自我一致性：来自你自备模型的免费信号<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E8%87%AA%E6%88%91%E4%B8%80%E8%87%B4%E6%80%A7%E6%9D%A5%E8%87%AA%E4%BD%A0%E8%87%AA%E5%A4%87%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%85%8D%E8%B4%B9%E4%BF%A1%E5%8F%B7" class="hash-link" aria-label="自我一致性：来自你自备模型的免费信号的直接链接" title="自我一致性：来自你自备模型的免费信号的直接链接" translate="no">​</a></h2>
<p>自我一致性（Self-consistency）是最容易实现的无标注技术。你不是针对一个查询生成一个响应，而是生成多个响应——通常使用温度采样（temperature sampling）——然后衡量它们的一致程度。</p>
<p>核心见解是：不确定性表现为方差。一个真正“知道”事实性问题答案的模型会在多次采样中重复产生相同的答案。一个在猜测的模型会产生一系列不同的答案。衡量这种分布可以让你在没有任何外部引用的情况下获得事实性的代理指标。</p>
<p>在实践中，你对输出进行哈希处理或归一化，并计算多数一致性（majority agreement）。如果你问一个模型一个事实性问题十次，它给出相同答案八次，这比它给出五个不同答案的信号更强。这项技术最初是为推理任务正式提出的——在数学基准测试中显示出 4–18% 的准确率提升——但其基本原理广泛适用于任何存在正确答案的任务。</p>
<p>局限性非常重要：</p>
<ul>
<li class=""><strong>一致的幻觉会使其失效。</strong> 如果模型一致地编造同一个虚假声明——“该条约签署于 1847 年”——高自我一致性会让你对错误答案产生高度信心。该方法假设错误是随机的；系统性错误是不可见的。</li>
<li class=""><strong>开放式任务有许多正确答案。</strong> 对于创意写作、摘要或对话响应，样本之间的差异不是 Bug——它是预期的，甚至是理想的。在这些任务上衡量一致性会惩罚优秀的输出。</li>
<li class=""><strong>成本随样本量增加。</strong> 每个查询生成十个响应是推理成本的十倍。对于高流量的生产环境，你需要有策略地进行采样，而不是评估所有内容。</li>
</ul>
<p>对有确定答案的任务使用自我一致性：事实性问答、分类、结构化提取、算术。对于多样性更合适的生成式任务，请跳过它。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="约束满足无需标签的结构正确性">约束满足：无需标签的结构正确性<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E7%BA%A6%E6%9D%9F%E6%BB%A1%E8%B6%B3%E6%97%A0%E9%9C%80%E6%A0%87%E7%AD%BE%E7%9A%84%E7%BB%93%E6%9E%84%E6%AD%A3%E7%A1%AE%E6%80%A7" class="hash-link" aria-label="约束满足：无需标签的结构正确性的直接链接" title="约束满足：无需标签的结构正确性的直接链接" translate="no">​</a></h2>
<p>对于许多 LLM 使用场景，正确性包含一个结构化组件，可以在不参考“正确”答案的情况下进行检查。这就是约束满足（constraint satisfaction）评估，它通常是现有最高信号、最低成本的技术。</p>
<p>你可以通过编程方式验证的约束示例：</p>
<ul>
<li class=""><strong>格式约束：</strong> 输出是否为有效的 JSON？它是否符合所需的 Schema？它是否包含预期的字段？</li>
<li class=""><strong>长度约束：</strong> 摘要是否在 150 字以内？生成的代码是否在预期范围内？</li>
<li class=""><strong>引用完整性：</strong> 每一项声明是否都引用了存在的来源？所有 URL 是否都返回 200？</li>
<li class=""><strong>特定领域的不变量：</strong> 生成的 SQL 是否可解析？代码是否可编译？正则表达式在测试用例上是否产生有效的输出？</li>
</ul>
<p>这里的价值在于这些检查是二进制的、快速的，且完全确定。你不需要模型来评估它们。它们捕获了一类特定的、高影响的失败——模型产生的输出在形式上是损坏的——而没有任何标注负担。</p>
<p>局限性也同样清晰：约束满足无法告诉你语义质量。一个输出可以穿过所有结构检查，但仍然在事实性上是错误的、逻辑不连贯的，或者对用户的实际目标完全无用。约束满足是必要的，但不是充分的。将其视为你的第一道过滤器，而不是唯一的过滤器。</p>
<p>在实践中，正确的方法是枚举正确输出必须具备的每个结构属性，将这些属性编码为自动化检查，并在每个评估候选对象上运行它们。这只需要一个下午的时间来设置，并能立即为你提供底线信号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="行为不变性测试那些不应改变的内容">行为不变性：测试那些不应改变的内容<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E8%A1%8C%E4%B8%BA%E4%B8%8D%E5%8F%98%E6%80%A7%E6%B5%8B%E8%AF%95%E9%82%A3%E4%BA%9B%E4%B8%8D%E5%BA%94%E6%94%B9%E5%8F%98%E7%9A%84%E5%86%85%E5%AE%B9" class="hash-link" aria-label="行为不变性：测试那些不应改变的内容的直接链接" title="行为不变性：测试那些不应改变的内容的直接链接" translate="no">​</a></h2>
<p>行为不变性（Behavioral invariants）是一种更高级的技术，用于测试模型在输入转换下的内部一致性。其核心直觉是：如果你改变了输入中某些不应影响输出的部分，但输出却发生了剧烈变化，那么你就发现了一个脆弱点。</p>
<p>一些值得测试的不变性示例：</p>
<ul>
<li class=""><strong>语义改写不变性</strong>：“法国的首都是哪里？”和“你能告诉我哪座城市是法国的首都吗？”应该产生相同的答案。巨大的差异表明模型是在对表面形式而非语义做出反应。</li>
<li class=""><strong>否定一致性</strong>：如果你分别询问“X 是正确的吗？”和“X 是错误的吗？”，模型的回答应该在逻辑上保持一致。许多模型在这方面都会失败。</li>
<li class=""><strong>指令鲁棒性</strong>：在保持语义不变的情况下，更改系统提示词中的格式细节（换行符、大小写、标签措辞），对于事实性任务不应显著改变输出。</li>
<li class=""><strong>适用场景下的顺序不变性</strong>：对于检索增强（RAG）任务，问题的答案不应因为支持性证据出现在长上下文的开头还是结尾而发生翻转。</li>
</ul>
<p>行为不变性测试的目的与事实性检查不同。它衡量的是鲁棒性和可靠性，而非正确性。如果一个模型对语义相同的提问给出不同的回答，这不仅说明它不可靠，而且意味着随着用户查询表述的多样化，它在生产环境中的表现很可能会下降。</p>
<p>实际的限制在于你需要自己生成这些不变性测试对，而且哪些不变性对你的特定任务至关重要并不总是显而易见的。不变性测试也不会告诉你哪个答案是正确的，只能说明模型不一致。对于事实性任务，你需要额外的信号来区分“不一致且错误”与“不一致但偶尔正确”。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="模型评分准则无黄金标签的-llm-as-judge">模型评分准则：无黄金标签的 LLM-as-Judge<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E6%A8%A1%E5%9E%8B%E8%AF%84%E5%88%86%E5%87%86%E5%88%99%E6%97%A0%E9%BB%84%E9%87%91%E6%A0%87%E7%AD%BE%E7%9A%84-llm-as-judge" class="hash-link" aria-label="模型评分准则：无黄金标签的 LLM-as-Judge的直接链接" title="模型评分准则：无黄金标签的 LLM-as-Judge的直接链接" translate="no">​</a></h2>
<p>最灵活的无标注技术是使用一个强大的 LLM 根据自定义准则来评估生产模型的输出。这通常被称为 “LLM-as-judge”，并已成为评估流水线中的标准组件。</p>
<p>G-Eval 框架提供了一个实用的模板：</p>
<ol>
<li class="">编写一份评分准则，规定任务中高质量输出的标准（连贯性、与提供上下文的事实一致性、与查询的相关性、指令遵循情况）。</li>
<li class="">要求裁判 LLM 根据这些标准生成思维链（Chain-of-thought）评估。</li>
<li class="">按数字量表评分（通常为 1–5 分），使用 Token 概率加权进行连续评分，而非分类输出。</li>
</ol>
<p>如果做得好，LLM 裁判在许多任务上与人类判断高度相关。它们在评估那些没有正式定义的特质时特别有用，例如回答是否乐于助人、摘要是否抓住了重点、语气是否得体。</p>
<p>然而，其失效模式非常严重，你不应盲目使用这种技术：</p>
<p><strong>长度偏见普遍存在。</strong> 在大多数裁判模型中，较长的输出通常得分更高，即使长度并没有增加价值。一个长度增加一倍的输出，尽管语义等价甚至更糟，得分却可能高出 20–30%。务必在你的评分准则和提示词设计中控制长度因素。</p>
<p><strong>位置偏见影响成对比较。</strong> 当要求裁判比较两个输出时，出现在第一个的输出获胜的概率往往高于随机概率。如果你在进行 A/B 比较，你需要随机化顺序，并对两种顺序的得分进行平均。</p>
<p><strong>领域专业知识差距显著。</strong> 研究表明，在医学、法律和心理健康等专业领域，LLM 裁判与领域专家的达成一致的比例仅为 64–68%。对于通用任务，一致性会更高，但差距依然存在。在涉及高风险或专业领域的场景下，不要将 LLM 裁判作为唯一的评估信号。</p>
<p><strong>没有参考资料就无法进行事实核查。</strong> 裁判模型无法可靠地区分一个自信的幻觉和一个正确的声明。表述流利、结构合理错误声明往往比表述生硬但正确的输出得分更高。LLM 裁判衡量表达质量比衡量事实准确性更可靠。</p>
<p><strong>讨好偏见会导致评分虚高。</strong> 大多数裁判模型倾向于认可而非批评。随着时间的推移，评分会向上漂移，特别是当被评估的输出看起来与裁判模型的训练分布相似时。</p>
<p>为了在实践中减轻这些偏见：在准则中加入明确的语言来惩罚不必要的冗长；始终以两种顺序运行成对比较；在规模化应用之前，先针对一小组人工标注的示例对裁判模型进行校准；在涉及事实准确性的领域，切勿将其作为唯一的评估信号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="技术组合第一周的评估技术栈">技术组合：第一周的评估技术栈<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E6%8A%80%E6%9C%AF%E7%BB%84%E5%90%88%E7%AC%AC%E4%B8%80%E5%91%A8%E7%9A%84%E8%AF%84%E4%BC%B0%E6%8A%80%E6%9C%AF%E6%A0%88" class="hash-link" aria-label="技术组合：第一周的评估技术栈的直接链接" title="技术组合：第一周的评估技术栈的直接链接" translate="no">​</a></h2>
<p>没有任何一种无标注技术是万能的。实际的方法是将它们分层组合，每一层捕捉不同类型的失败：</p>
<p><strong>第 1 层 —— 确定性检查（约束满足）：</strong> 对每个输出都运行。捕捉格式错误、Schema 违规和结构性错误。除了生产环境调用外，推理成本几乎为零。请首先建立这一层。</p>
<p><strong>第 2 层 —— 一致性采样（自洽性）：</strong> 对于事实性任务，针对 5–10% 的随机流量运行。生成三到五个额外的输出，并将高变异性的查询标记出来供人工审核。利用变异分布来追踪随时间推移的变化。</p>
<p><strong>第 3 层 —— 行为回归测试（不变性）：</strong> 一个包含 50–100 个不变性测试对的固定测试集，在每次模型或提示词变更部署前运行。这是你的变更检测层。</p>
<p><strong>第 4 层 —— LLM 裁判评分（准则评估）：</strong> 针对随机抽样的输出运行，或者在低流量场景下针对所有输出运行。使用带有校准准则的强力裁判模型。每周手动检查裁判的输出，直到你信任其校准结果。</p>
<p>这个技术栈为你提供了四个独立的失败探测器，每个探测器都有不同的敏感度和失效模式。当多个层都标记同一个输出时，对质量信号的信心会大幅增强。当各层出现分歧时，则是一个值得人工调查的信号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="当所有方法共同失效时">当所有方法共同失效时<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E5%BD%93%E6%89%80%E6%9C%89%E6%96%B9%E6%B3%95%E5%85%B1%E5%90%8C%E5%A4%B1%E6%95%88%E6%97%B6" class="hash-link" aria-label="当所有方法共同失效时的直接链接" title="当所有方法共同失效时的直接链接" translate="no">​</a></h2>
<p>即使是组合后的技术栈也有一个值得明确指出的共同盲点：它无法检测出模型持续产生这种看起来高质量但实际上错误的答案的失败模式。</p>
<p>自洽性（Self-consistency）给了你很高的信心。约束满足（Constraint satisfaction）通过了。行为不变性（Behavioral invariants）没有显示出差异。LLM judge 给出了高分。然而，输出在事实层面仍然是错误的——而且是持续地、有说服力地、大规模地出错。</p>
<p>这种类型的失败——自信且持续的幻觉（hallucination）——最终只能依靠地面真值（ground truth）来捕捉。无标注评估方法可以告诉你什么时候某些内容不一致、结构损坏或根据某些正式标准明显错误。但它们无法告诉你模型何时学到了一个虚假信念，并以极高的自信表达出来。</p>
<p>这是无标注评估真实存在的上限：它衡量的是可靠性和形式上的正确性，而不是真理。对于真理至关重要的应用——医疗信息、法律文件、财务数据、科学主张——你最终将需要人类专家标注、外部知识库比对或基于执行的验证。无标注技术栈为你赢得了时间，并捕捉到了大部分问题。但它并不能消除对地面真值的需求。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="在拥有完美基础设施之前就开始">在拥有完美基础设施之前就开始<a href="https://tianpan.co/zh/blog/2026-04-19-annotation-free-llm-evaluation#%E5%9C%A8%E6%8B%A5%E6%9C%89%E5%AE%8C%E7%BE%8E%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD%E4%B9%8B%E5%89%8D%E5%B0%B1%E5%BC%80%E5%A7%8B" class="hash-link" aria-label="在拥有完美基础设施之前就开始的直接链接" title="在拥有完美基础设施之前就开始的直接链接" translate="no">​</a></h2>
<p>在阅读有关评估框架的内容时，人们很容易产生一种诱惑，觉得必须先构建好一切才能开始学习。这是错误的。从一层开始。</p>
<p>选择与你的任务最相关的约束满足检查——输出是否按预期解析、是否包含所需字段、是否在预期的长度范围内——并从今天开始实施。跟踪通过率随时间的变化。那个单一的数字，即使不完美，也比零评估更有用，而这正是大多数团队在第一周时的状态。</p>
<p>随着规模的扩大，添加其他层。重要的是养成早期测量的习惯，此时你仍然有能力调查所发现的情况，并将其与你对质量的直觉联系起来。地面真值不会在第一天就出现。但你的直觉、你的任务规范以及你运行廉价自动化检查的能力会。</p>
<p>无标注评估不是评估作秀（evaluation theater）。它是一种诚实标记的初步近似，能够防止最糟糕的一种失败：在不知道质量是上升还是下降的情况下发布变更。</p>
<hr>
<p><em>正在构建 LLM 评估流水线？另请参阅 <a class="" href="https://tianpan.co/zh/blog/2025-10-08-your-ai-product-needs-evals">AI 产品评估：为什么你的测试套件可能在对你撒谎</a> 和 <a class="" href="https://tianpan.co/zh/blog/2026-04-16-judge-model-independence-eval-blind-spots">评判模型独立性：避开评估盲点</a>。</em></p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="llm-evaluation" term="llm-evaluation"/>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="testing" term="testing"/>
        <category label="llm-ops" term="llm-ops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[你从未闭合的反馈回路：将用户行为转化为 AI 真值]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[显式的点赞评分可能是表象。编辑率、重试模式和会话中断能更真实地反映 AI 的质量 —— 而且你可以在没有标注预算的情况下，将它们转化为评估数据集。]]></summary>
        <content type="html"><![CDATA[<p>大多数构建 AI 产品的团队会花费数周时间设计评分组件、星级点击、点赞/点踩按钮。然而六个月后，他们查看数据时发现响应率仅为 2% —— 数据偏向于极端体验，被那些带有强烈偏好的人主导，而且在区分 7/10 和 9/10 的输出方面几乎毫无用处。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E4%BD%A0%E4%BB%8E%E6%9C%AA%E9%97%AD%E5%90%88%E7%9A%84%E5%8F%8D%E9%A6%88%E5%9B%9E%E8%B7%AF%EF%BC%9A%E5%B0%86%E7%94%A8%E6%88%B7%E8%A1%8C%E4%B8%BA%E8%BD%AC%E5%8C%96%E4%B8%BA%20AI%20%E7%9C%9F%E5%80%BC" alt="" class="img_ev3q"></p>
<p>与此同时，每一个用户会话都在产生源源不断的真实、明确的行为信号。接受代码建议并继续操作的用户是满意的。立即按下 Ctrl+Z 的用户则不满意。连续四次重新组织问题的用户正在告诉你一些显式评分永远无法捕捉到的信息：前三次回答都失败了。无论你是否收集，这些信号都存在。问题在于你是否正在闭合这个反馈回路。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么点赞评分在结构上是失效的">为什么点赞评分在结构上是失效的<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E4%B8%BA%E4%BB%80%E4%B9%88%E7%82%B9%E8%B5%9E%E8%AF%84%E5%88%86%E5%9C%A8%E7%BB%93%E6%9E%84%E4%B8%8A%E6%98%AF%E5%A4%B1%E6%95%88%E7%9A%84" class="hash-link" aria-label="为什么点赞评分在结构上是失效的的直接链接" title="为什么点赞评分在结构上是失效的的直接链接" translate="no">​</a></h2>
<p>显式反馈（Explicit feedback）有一个根本性问题：它捕捉的是用户怎么说，而不是用户怎么做。这两者经常发生背离。</p>
<p>用户可能会给一个 AI 写作助手打五星，同时却在修改它生成的每一条回复中 80% 的内容。评分捕捉的是情绪 —— 这个工具感觉很有用，用户喜欢这个产品。而编辑行为捕捉的是质量 —— 输出结果一直有误，以至于需要手动纠正。如果你只根据评分进行优化，你将构建出一个让人感觉印象深刻但产出不可靠的系统。</p>
<p>这种背离也存在于另一个方向。那些默默满意的用户 —— 接受输出并继续操作的人 —— 很少进行评分。他们没有理由停下来去点一颗星。你的 4.7 分平均分是建立在那些带有强烈观点的人的声音之上的，而不是中位数的体验。</p>
<p>关于多轮对话系统的研究发现，在对话后期，超过一半的用户表达中会出现隐式反馈信号，而显式评分仅在极小比例的互动中被收集。行为数据更丰富、频率更高，且是自动生成的。你已经在为产生这些数据的基础设施付费了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="值得收集的行为信号">值得收集的行为信号<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E5%80%BC%E5%BE%97%E6%94%B6%E9%9B%86%E7%9A%84%E8%A1%8C%E4%B8%BA%E4%BF%A1%E5%8F%B7" class="hash-link" aria-label="值得收集的行为信号的直接链接" title="值得收集的行为信号的直接链接" translate="no">​</a></h2>
<p>并非所有隐式信号都具有同样的参考价值。有些需要结合上下文才能正确解读。以下是大致按可靠性排序的信号分类：</p>
<p><strong>高置信度负面信号：</strong></p>
<ul>
<li class="">立即撤销（在接受建议后的几秒钟内按下 Ctrl+Z）</li>
<li class="">在同一会话内重新表述查询（用户因为上次回答失败而在重试）</li>
<li class="">未完成任务即放弃会话（在工作流中途离开）</li>
<li class="">直接覆盖完整输出，而不是针对性的编辑</li>
</ul>
<p><strong>高置信度正面信号：</strong></p>
<ul>
<li class="">无需修改或后续操作直接进入下一个任务</li>
<li class="">将输出复制到下游工具或分享到外部</li>
<li class="">生成输出后，提出基于该输出的后续问题</li>
</ul>
<p><strong>Context-dependent signals：</strong></p>
<ul>
<li class="">接受的响应长度 vs. 截断长度（如果用户总是滚动并继续阅读，则长度适中；如果他们总是在第 10 行停止阅读，则长度不当）</li>
<li class="">对 AI 生成内容的编辑率（需要基准线：法律合同 30% 的编辑率是正常的；而写作助手生成的客户邮件同样的编辑率则过高）</li>
<li class="">对话持续性（用户回应 vs. 保持沉默）</li>
</ul>
<p>对话系统的一项研究发现：一个简单的基于长度的隐式信号 —— 用户生成的响应是否超过阈值长度 —— 与基准模型相比，带来了 12 个点的胜率提升。对于一个单一且低成本收集的行为指标来说，这是一个非常有力的信号。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="构建从行为到评估数据集的流水线">构建从行为到评估数据集的流水线<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E6%9E%84%E5%BB%BA%E4%BB%8E%E8%A1%8C%E4%B8%BA%E5%88%B0%E8%AF%84%E4%BC%B0%E6%95%B0%E6%8D%AE%E9%9B%86%E7%9A%84%E6%B5%81%E6%B0%B4%E7%BA%BF" class="hash-link" aria-label="构建从行为到评估数据集的流水线的直接链接" title="构建从行为到评估数据集的流水线的直接链接" translate="no">​</a></h2>
<p>目标是将行为信号转化为带标签的数据对：<code>(input, output, quality_label)</code>，你可以用它来构建评估数据集、微调奖励模型或识别退化案例。以下是一个实用的流水线。</p>
<p><strong>第一步：对交互层进行监测 (Instrument the interaction layer)</strong></p>
<p>标准的观测性指标 —— 延迟、错误率、Token 数量 —— 是不够的。你需要交互层面的观测能力：</p>
<ul>
<li class="">记录会话 ID 和对话轮次序列，而不只是单个请求</li>
<li class="">记录编辑事件以及相对于输出生成的时间戳</li>
<li class="">捕获导航事件（用户是离开了产品，还是进入了更深层，或者是重复了某个步骤？）</li>
<li class="">记录查询重构（同一会话、相似的语义意图、新的措辞 = 重试信号）</li>
</ul>
<p>你不需要捕获具体内容。你需要捕获结构：响应后发生了什么，发生了多久，以及朝哪个方向发展。</p>
<p><strong>第二步：根据产品语境定义行为标签</strong></p>
<p>行为信号在不同的语境下意义不同。对代码建议的立即编辑可能意味着模型错了，也可能意味着开发者想加入自己的定制。你必须为你特定的产品定义每个信号的含义。</p>
<p>一个有用的练习：对于你监测的每个行为信号，写出可能产生该信号的两到三种用户意图解释，并设计日志模式（schema）以便尽可能地区分它们。如果你无法区分，请将该信号视为弱信号而非强信号。</p>
<p><strong>第三步：策略性采样，而非随机采样</strong></p>
<p>你不需要收集每个会话的标签。高价值的案例在于边缘地带：</p>
<ul>
<li class="">用户表现出混合信号的会话（部分编辑，然后继续）</li>
<li class="">高重试会话（针对同一底层任务进行了 3 次以上的重构）</li>
<li class="">与历史基准不匹配的新交互模式</li>
<li class="">在其他指标上模型表现最差的用户群体的会话</li>
</ul>
<p>从分布的尾部采样可以让你发现最可能暴露模型弱点的案例。随机采样只会给你带来大量确定的成功案例，这对提高评估覆盖率毫无帮助。</p>
<p><strong>第四步：转化为评估示例</strong></p>
<p>对于每个带标签的会话，提取规范的 <code>(prompt, response, label)</code> 三元组：</p>
<ul>
<li class="">Prompt 是用户最终成功的措辞（在任何重试之后）</li>
<li class="">Response 是模型在那一轮产生的输出</li>
<li class="">Label 可以是二元的（接受/拒绝）或分级的（无编辑、轻微编辑、重大编辑、完全替换）</li>
</ul>
<p>对于重试案例，你现在拥有了更有价值的东西：一个自然的 A/B 对。模型的第一次响应被拒绝了；重构后的查询产生了一个用户接受的结果。这是一个无需任何标注的偏好对（preference pair） —— 行为序列本身就是标签。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="标注预算账">标注预算账<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E6%A0%87%E6%B3%A8%E9%A2%84%E7%AE%97%E8%B4%A6" class="hash-link" aria-label="标注预算账的直接链接" title="标注预算账的直接链接" translate="no">​</a></h2>
<p>当你核算人工标注的成本时，行为信号的经济优势就变得显而易见了。</p>
<p>在标准质量下，人工标注的成本约为每个标签 0.08 美元。而基于 LLM 的标注成本约为每个标签 0.002 美元。在同等成本下，LLM 标注能为你提供 40 倍的已标注数据——而且在规模化（约 25,000 个示例）的情况下，LLM 标注的数据集在下游模型质量上可以与人工标注的数据集相媲美。</p>
<p>行为信号的每个标签成本几乎为零，因为用户在与你的产品交互时就是在进行标注。其成本在于基础设施和流水线工程，而非单条数据的劳动力成本。在任何具有一定用户规模的情况下——哪怕只有数千名月活跃用户——你生成已标注评估数据集的速度都会超过任何人工标注工作流。</p>
<p>但问题在于噪声。隐式信号虽然频繁但伴随着噪声。一次重试可能意味着模型失败了，也可能意味着用户改变了主意。一次会话放弃可能意味着不满，也可能意味着用户被会议中断了。从行为信号中构建干净的评估数据集需要过滤、聚合，并对标签的不确定性有一定的容忍度。关于重复隐式反馈的研究发现，测量多个交互事件中的不确定性——而不是依赖单一的行为事件——可以显著提高信号的可靠性。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="microsoft-的语义遥测做对了什么">Microsoft 的语义遥测做对了什么<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#microsoft-%E7%9A%84%E8%AF%AD%E4%B9%89%E9%81%A5%E6%B5%8B%E5%81%9A%E5%AF%B9%E4%BA%86%E4%BB%80%E4%B9%88" class="hash-link" aria-label="Microsoft 的语义遥测做对了什么的直接链接" title="Microsoft 的语义遥测做对了什么的直接链接" translate="no">​</a></h2>
<p>Microsoft Research 构建了一个他们称之为语义遥测（semantic telemetry）的框架，用于理解用户如何大规模地与 AI 系统交互。其核心洞察是使用 LLM 对交互模式进行分类，而不仅仅是统计事件数量。</p>
<p>他们的流水线分为三个步骤：</p>
<ol>
<li class=""><strong>生成分类法 (Taxonomy)</strong>：将对话样本输入 LLM，并要求其生成一套分类类别——主题、任务类型、复杂程度。</li>
<li class=""><strong>大规模分类</strong>：将这些类别应用于数百万次匿名交互。</li>
<li class=""><strong>分析分布偏移</strong>：观察主题和任务复杂度的分布如何随时间、在不同人群或不同模型版本之间发生变化。</li>
</ol>
<p>使这一方法对评估产生价值的是第 3 步。如果你产品的高级用户群体开始从“查找与检索”任务转向“综合与分析”任务，你的评估数据集就需要反映这种转变。行为遥测让这种偏移变得可见。如果没有它，当实际使用分布在发生演变时，你的评估数据集仍会保持停滞。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="你已经忽略的沉默信号">你已经忽略的沉默信号<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E4%BD%A0%E5%B7%B2%E7%BB%8F%E5%BF%BD%E7%95%A5%E7%9A%84%E6%B2%89%E9%BB%98%E4%BF%A1%E5%8F%B7" class="hash-link" aria-label="你已经忽略的沉默信号的直接链接" title="你已经忽略的沉默信号的直接链接" translate="no">​</a></h2>
<p>有些行为信号不需要新的埋点，因为它们已经存在于你的交互日志中——只是尚未被提取和利用。</p>
<p><strong>Ctrl+Z / 撤销事件</strong>：如果你的产品涉及将 AI 生成的内容应用到文档或编辑器中，编辑器已经记录了撤销事件。在接受建议后的几秒钟内执行撤销，是你无需询问任何人就能收集到的最清晰的负面标签。</p>
<p><strong>分享或导出事件</strong>：如果用户将 AI 生成的输出复制到剪贴板、分享链接或将内容导出到其他工具，这是一个强烈的认可信号。这意味着他们足够信任该输出，从而将其流转到下游。</p>
<p><strong>从结果页面后退</strong>：如果用户点击进入 AI 生成的结果并立即返回，这是一个拒绝信号。这与搜索中的跳出率结构相同——结果与意图不匹配。</p>
<p><strong>后续问题的结构</strong>：在之前回答基础上构建的后续问题（如“现在把它缩短”或“为边缘情况 X 添加一个异常”）是积极的参与信号。而重新解释原始任务的后续问题（如“不，我的意思是……”）则是修正信号——模型理解错了。</p>
<p>这些都不需要评分提示。如果你在会话级别记录交互，它们就已经存在于你的日志中了。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="闭环从信号到持续评估">闭环：从信号到持续评估<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E9%97%AD%E7%8E%AF%E4%BB%8E%E4%BF%A1%E5%8F%B7%E5%88%B0%E6%8C%81%E7%BB%AD%E8%AF%84%E4%BC%B0" class="hash-link" aria-label="闭环：从信号到持续评估的直接链接" title="闭环：从信号到持续评估的直接链接" translate="no">​</a></h2>
<p>目标不仅是收集标注数据，而是构建一个反馈闭环，持续更新你对生产环境中模型质量的理解。</p>
<p>一个实用的闭环架构如下：</p>
<ol>
<li class="">在会话级别<strong>埋点 (Instrument)</strong> 交互事件</li>
<li class="">使用你为产品定义的信号分类法对行为事件进行<strong>标注 (Label)</strong></li>
<li class="">从分布尾部进行<strong>采样 (Sample)</strong>，以构建针对性的评估分片 (eval slices)</li>
<li class="">在部署前针对这些分片<strong>评估 (Evaluate)</strong> 模型变更</li>
<li class=""><strong>监控 (Monitor)</strong> 行为信号中的分布偏移，作为质量退化的先行指标</li>
</ol>
<p>监控步骤是大多数团队会忽略的一步。行为信号分布是早期预警系统。如果模型更新后重试率飙升，这就是一个质量退化信号——通常比等待显式用户投诉或正式评估结果汇总要快得多。相反，如果会话完成率在没有任何提示词更改的情况下有所提高，那么底层模型行为中某些评估未能预测的东西发生了变化。</p>
<p>最危险的 AI 系统故障不是那些响亮崩溃的系统，而是那些在保持运行、听起来充满信心，却在悄无声息地向错误方向偏移的系统。行为遥测能让你在用户发现这种偏移之前先看到它。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="本周要做什么">本周要做什么<a href="https://tianpan.co/zh/blog/2026-04-19-behavioral-signals-ai-eval-ground-truth#%E6%9C%AC%E5%91%A8%E8%A6%81%E5%81%9A%E4%BB%80%E4%B9%88" class="hash-link" aria-label="本周要做什么的直接链接" title="本周要做什么的直接链接" translate="no">​</a></h2>
<p>你不需要立即构建完整的流水线。从以下两件事开始：</p>
<p><strong>第一</strong>，审计你已经在记录的日志。检查你的交互日志是否包含会话 ID (session ID)、轮次序列 (turn sequences) 以及任何响应后的用户行为。如果已经包含这些，你就可以开始从现有数据中提取行为标签，而无需编写新的埋点 (instrumentation) 代码。</p>
<p><strong>第二</strong>，选择一个在你的产品上下文中含义明确的信号，并有针对性地进行埋点。对于大多数产品来说，查询重试率 (query retry rate) 是现有信号最强、噪声最低的行为指标。一个重新组织语言并再次提交的用户，正在明确地告诉你第一个响应没起作用。就从这里开始。</p>
<p>无论你是否闭环，反馈循环始终存在。每一个用户会话都在对你的模型进行一场无声的评估。唯一的问题在于，你是否在阅读这些结果。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="evaluation" term="evaluation"/>
        <category label="observability" term="observability"/>
        <category label="mlops" term="mlops"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[基准污染：为什么那个90% MMLU分数并不意味着你想象的那样]]></title>
        <id>https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap</id>
        <link href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap"/>
        <updated>2026-04-19T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[前沿模型在标准基准上表现亮眼，但污染——测试数据泄漏到预训练中——会显著虚高这些数字。本文揭示实际差距有多大，以及如何设计能给出诚实信号的评估。]]></summary>
        <content type="html"><![CDATA[<p>当GPT-4在MMLU上得到88%时，感觉是一个里程碑时刻。MMLU——大规模多任务语言理解基准——涵盖从小学数学到专业法律的57个学科。在如此广泛领域达到88%的准确率，看起来是真正广泛智能的有力证据。后来研究人员创建了MMLU-CF，一个无污染变体，替换掉了与已知训练语料库存在可疑相似性的问题。GPT-4o下降到73.4%——差距高达14.6个百分点。</p>
<p><img decoding="async" loading="lazy" src="https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E5%9F%BA%E5%87%86%E6%B1%A1%E6%9F%93%EF%BC%9A%E4%B8%BA%E4%BB%80%E4%B9%88%E9%82%A3%E4%B8%AA90%25%20MMLU%E5%88%86%E6%95%B0%E5%B9%B6%E4%B8%8D%E6%84%8F%E5%91%B3%E7%9D%80%E4%BD%A0%E6%83%B3%E8%B1%A1%E7%9A%84%E9%82%A3%E6%A0%B7" alt="" class="img_ev3q"></p>
<p>这个差距不是小的舍入误差。它代表的是"在复杂学术问题上可靠正确"与"在见过这道题时可靠正确"之间的区别。对于基于排行榜分数做模型选择决策的团队来说，这意味着购买了一种并不真正存在的能力。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="评估数据如何进入训练语料库">评估数据如何进入训练语料库<a href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap#%E8%AF%84%E4%BC%B0%E6%95%B0%E6%8D%AE%E5%A6%82%E4%BD%95%E8%BF%9B%E5%85%A5%E8%AE%AD%E7%BB%83%E8%AF%AD%E6%96%99%E5%BA%93" class="hash-link" aria-label="评估数据如何进入训练语料库的直接链接" title="评估数据如何进入训练语料库的直接链接" translate="no">​</a></h2>
<p>这个机制不是什么秘密阴谋。考虑到LLM预训练的运作方式，它是结构性的，几乎不可避免。</p>
<p>现代前沿模型在网络规模的数据集上训练——Common Crawl快照、GitHub、arXiv、StackExchange、Reddit帖子。MMLU、HumanEval和GSM8K等流行基准数据集在GitHub和Hugging Face上公开可用，在arXiv的学术论文中被频繁讨论，并在StackExchange答案中被引用。当你抓取整个互联网时，基准数据集也会被一并抓进来。</p>
<p>污染有几种形式。直接包含是最明显的：包含HumanEval问题的GitHub仓库存在于训练数据中。但也有改写污染，从基准问题衍生的合成数据集最终进入训练数据（CodeAlpaca包含约12.8%的改写HumanEval样本）。还有论坛讨论，人们在那里发布基准问题和解答。还有基于MMLU内容构建的学习指南。测试集随着时间推移在网络上扩散。</p>
<p>对于LLaMA 2，研究人员发现超过16%的MMLU示例被污染，其中11%"严重污染"——意味着这些示例中超过80%的token出现在预训练数据中。对于HumanEval，主要开源预训练集的污染率从8%到18%不等。</p>
<p>更难回答的问题是，这是否构成真正的性能虚高，还是说模型确实从那些污染样本中学到了能迁移的东西。MMLU-CF的结果直接回答了这个问题：差距是真实且显著的。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="为什么标准检测方法持续失效">为什么标准检测方法持续失效<a href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%A0%87%E5%87%86%E6%A3%80%E6%B5%8B%E6%96%B9%E6%B3%95%E6%8C%81%E7%BB%AD%E5%A4%B1%E6%95%88" class="hash-link" aria-label="为什么标准检测方法持续失效的直接链接" title="为什么标准检测方法持续失效的直接链接" translate="no">​</a></h2>
<p>业界对污染担忧的第一反应是n-gram匹配：检查测试输入是否逐字出现在训练语料库中。这对直接包含有效，但对其他一切完全失败。</p>
<p>一个13亿参数的Llama模型生动地证明了这一点：在改写版本的测试集上训练后，它在MMLU、GSM8K和HumanEval上达到了GPT-4级别的性能。这些改写轻松通过了n-gram去污染过滤器。该模型实际上已经记住了答案分布，而没有存储字面文本。</p>
<p>更近期的检测方法使用语义相似度（句子-BERT嵌入）、困惑度分析（污染样本相对于未污染邻居显示出异常低的困惑度）和成员推断攻击。这些能捕获更多污染，但2025年的研究显示了一个新问题：即使在监督微调污染可检测之后，也可以通过用干净数据进行后训练来掩盖污染证据。你可以通过训练消除指纹。</p>
<p>这就是使基准分数对闭源模型从根本上不可靠的对抗动态：创建基准的人无法审计训练数据，而训练模型的人有强烈的动机取得好成绩。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="基准到现实的性能差距">基准到现实的性能差距<a href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap#%E5%9F%BA%E5%87%86%E5%88%B0%E7%8E%B0%E5%AE%9E%E7%9A%84%E6%80%A7%E8%83%BD%E5%B7%AE%E8%B7%9D" class="hash-link" aria-label="基准到现实的性能差距的直接链接" title="基准到现实的性能差距的直接链接" translate="no">​</a></h2>
<p>污染对真实任务重要性的最清晰证据来自代码生成基准。在HumanEval上——测试孤立、自包含问题上的函数级代码生成——前沿模型得分在84-89%范围内。在真实世界的类级代码生成基准上（要求模型理解项目上下文、类间依赖和现有模式），性能下降到25-34%。</p>
<p>这不是小的方法论细节问题。HumanEval被设计为易于评估：具有清晰文档字符串和单元测试的单个函数。它成功做到了易于评估，却未能预测模型是否对实际软件开发有用。</p>
<p>GSM8K数学推理显示了类似模式。推理时去污染技术——在评估时改写测试问题以减少模式匹配可能性——将GSM8K的准确率降低了高达22.9%，将MATH降低了19.0%。污染不只是虚高绝对数字；它还在人为缩小小型和大型模型之间的差距，让更便宜的模型在重要任务上看起来比实际更有能力。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="抗污染评估实际上是什么样的">抗污染评估实际上是什么样的<a href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap#%E6%8A%97%E6%B1%A1%E6%9F%93%E8%AF%84%E4%BC%B0%E5%AE%9E%E9%99%85%E4%B8%8A%E6%98%AF%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84" class="hash-link" aria-label="抗污染评估实际上是什么样的的直接链接" title="抗污染评估实际上是什么样的的直接链接" translate="no">​</a></h2>
<p>有四种方法在评估生命周期的不同节点起作用。</p>
<p><strong>时间锚定</strong>原则上最简单：使用可证明在模型训练截止日期之后的评估数据。LiveBench和LiveCodeBench持续这样做，从最近的竞赛、新闻事件和新发布的问题中提取。其优点是，对于训练期间不存在的数据，污染在结构上是不可能的。缺点是你需要不断更新基准以保持这一特性。</p>
<p><strong>过程级评估</strong>改变了你衡量的内容。不是只检查最终答案是否正确，而是评估推理轨迹——模型产生的中间步骤。在同一套数学题上准确率相同的两个模型可以表现出截然不同的推理过程：一个在做有效的代数运算，而另一个在对常见答案形式进行模式匹配。真正学会了底层方法的模型在问题变体上表现出更好的泛化能力。依赖记忆答案模式的模型在稍微改变表面形式时就会崩溃。</p>
<p><strong>行为探测</strong>走得更远。不是在基准分布的保留切片上测试，而是构建通过不同表面探测相同能力的新测试用例。如果一个模型声称学会了"解一元二次方程"，就探测它是否能以文字题、代码、几何问题和新颖符号系统的形式求解。真正的学习能跨越表面变化泛化；记忆做不到。</p>
<p><strong>私有保留集</strong>对于不是基准研究人员的从业者来说通常是正确答案——只需从你的实际任务分布中构建自己的评估集，将其保存在互联网之外，永远不要与供应商分享作为微调示例。这消除了你用例的整个污染路径。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="团队实用评估框架">团队实用评估框架<a href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap#%E5%9B%A2%E9%98%9F%E5%AE%9E%E7%94%A8%E8%AF%84%E4%BC%B0%E6%A1%86%E6%9E%B6" class="hash-link" aria-label="团队实用评估框架的直接链接" title="团队实用评估框架的直接链接" translate="no">​</a></h2>
<p>如果你正在为特定部署选择或比较模型，基准排行榜分数充其量应该被视为弱先验信息。以下是真正给你有用信号的方法：</p>
<p>首先，从你自己的数据构建评估集。从你的实际任务分布中取50-200个示例，让人类评估正确输出，然后针对这些测试模型。这在设计上是防污染的，它直接衡量你关心的能力，而不是代理指标。</p>
<p>其次，在真实提示条件下测试。许多基准结果使用精心设计的多样本提示、思维链、优化样本和集成解码。在生产中你将使用简单的零样本或少样本提示。当提示从基准最优移动到生产现实时，性能往往会大幅下降。</p>
<p>第三，如果你在标准基准上比较模型，优先选择抗污染基准，其中研究人员对抗污染做出了方法论承诺——LiveBench、MMLU-CF或具有时间截止点的特定任务变体。将原始MMLU或HumanEval分数视为营销材料。</p>
<p>第四，测试行为泛化而不是标准分布的准确率。取你的用例并创建5-10个"变体探测"，以不同方式测试相同的能力。一个在你的示例上表现完美但在变体上失败的模型可能是在模式匹配，而不是在推理。</p>
<p>第五，对于推理任务，特别注意轨迹质量。模型的推理轨迹是否连贯地导向答案，或者答案是否伴随着不连贯的推理片段出现？正确答案配坏推理是污染信号。这也是可靠性信号：这些模型在问题稍微超出分布时往往更频繁地产生自信的错误答案。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="更广泛的测量问题">更广泛的测量问题<a href="https://tianpan.co/zh/blog/2026-04-19-benchmark-contamination-llm-evaluation-gap#%E6%9B%B4%E5%B9%BF%E6%B3%9B%E7%9A%84%E6%B5%8B%E9%87%8F%E9%97%AE%E9%A2%98" class="hash-link" aria-label="更广泛的测量问题的直�接链接" title="更广泛的测量问题的直接链接" translate="no">​</a></h2>
<p>基准污染是更广泛问题的一个症状：AI系统的评估基础设施与被评估参与者的激励机制在结构上不一致。基准创建者公开发布数据以允许可重复研究。模型训练者可以访问该发布的数据。评估者随后使用同样的公开数据来评估模型质量。利益冲突是内置的。</p>
<p>这不能完全解决——你不可能拥有一个既足够公开以允许第三方审计、又足够私密以防止污染的基准。但你可以构建承认这一局限性而不是忽视它的评估管道。</p>
<p>73.4%与88.0%在MMLU上的差距不是需要修补的错误。它量化了当你无法验证训练数据清洁度时，基准分数高估真实能力的程度。对于你没有训练数据可见性的模型——这是大多数商业API——假设存在类似的差距，直到你从自己的评估中获得相反的证据。</p>
<p>构建你的评估。在你的分布上测试。把排行榜分数当作起始过滤器，而不是决策标准。</p>]]></content>
        <author>
            <name>Tian Pan</name>
            <uri>https://tianpan.co</uri>
        </author>
        <category label="ai-engineering" term="ai-engineering"/>
        <category label="evaluation" term="evaluation"/>
        <category label="llm" term="llm"/>
        <category label="benchmarks" term="benchmarks"/>
    </entry>
</feed>