<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>Paweł Dubiel Tech Blog</title>
  <link>https://paweldubiel.com/zh</link>
  <atom:link href="https://paweldubiel.com/zh/rss.xml" rel="self" type="application/rss+xml" />
  <description>关于 AI、语言模型和软件工程的笔记。</description>
  <language>zh</language>
  <lastBuildDate>Mon, 12 Oct 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>我把 Amiga 软盘交给了 AI 智能体，一个晚上之后 Pirates! 就在 Unity 里跑起来了</title>
  <link>https://paweldubiel.com/zh/articles/pirates-amiga-unity-port</link>
  <guid isPermaLink="true">https://paweldubiel.com/zh/articles/pirates-amiga-unity-port</guid>
  <pubDate>Sun, 11 Oct 2026 22:37:00 GMT</pubDate>
  <dc:creator>Paweł Dubiel</dc:creator>
  <category>ai</category>
  <category>agents</category>
  <category>coding</category>
  <category>llm</category>
  <description>我把 1990 年 Amiga 版 Sid Meier&apos;s Pirates! 的四张软盘镜像交给一个编码智能体，请它把游戏移植到 Unity。</description>
  <content:encoded><![CDATA[<p>我把 1990 年 Amiga 版 Sid Meier's Pirates! 的四张软盘镜像交给一个编码智能体，请它把游戏移植到 Unity。干活的是 Claude Code 里的 Claude Opus 5.5。一个晚上之后，游戏已经可以从标题画面一路玩下去：决斗、城镇、在地图上航行，直到海战，用的都是原版的图像和声音。比速度更重要的是结果的检验方式：同一套决策脚本分别在 C# 移植版和运行于处理器模拟器中的原始机器码上执行。在 802 次运行、约 600 万行被比对的输出中，两个版本呈现给玩家的内容完全一致。</p>
<p>我在这里把这项工作的各个阶段依次写下来，因为它们合起来构成了一套方法，换一款游戏、换一个模型也能重复。文章最后我会展示按同一套流程完成的第二个项目：把 Centurion: Defender of Rome 从 DOS 移植到 JavaScript。两者都是用于学习的私人项目：原版游戏及其图像和声音仍受版权保护，我不会分发它们。</p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-title-screen.webp" alt="Unity 移植版中的 Pirates! 标题画面：夕阳下挂着海盗旗的盖伦帆船，用 1990 年的原版图像绘制。" loading="eager" decoding="async" width="1600" height="900"></p>
<p><em>Unity 中的标题画面。图像是在运行时从游戏的原始文件中解码出来的。</em></p>
<h2 id="从软盘镜像到反编译代码">从软盘镜像到反编译代码</h2>
<p>智能体先从辨认文件入手。Amiga 的软盘镜像（ADF）是扇区的原始拷贝，所以几十行 Python 就足以把内容解包出来。游戏程序原来是一个带覆盖模块（overlay）的文件：核心常驻内存，另外三个代码段按需从磁盘读入。免费的反编译器 Ghidra 并不内置对这种格式的支持。智能体写了一个脚本，把所有代码段按固定地址排布到同一个镜像里，并把 45 处指向覆盖模块的间接跳转改成普通调用。这样一来，反编译器就把约 630 个函数看成了一个完整的程序。</p>
<p>游戏数据带来了一个意外。扩展名为 <code>.rez</code> 的文件采用的是 Macintosh 电脑的资源布局，因为 Amiga 版本是从 Mac 移植过来的。识别出格式之后，智能体提取了 210 段文本、82 个字符串列表、六个时代的城镇数据、图像、动画、精灵图（sprite）和声音。事实证明，文本是最好的代码地图：传给“显示文本”例程的字符串编号，直接说明了某个函数负责游戏的哪个画面。</p>
<h2 id="十三个智能体读代码九个智能体重写代码">十三个智能体读代码，九个智能体重写代码</h2>
<p>反编译出来的代码接近 2.9 万行，函数和变量都没有名字。主智能体把它切成每段约 2000 行的片段，并把每一段连同同一份书面任务说明交给一个单独的智能体。每个智能体都要把自己那一段里所有函数的描述写进文件：精确的公式、常量、随机数范围、所显示文本的编号，以及读取和写入的全局变量。任务说明里有一句话，后来证明很关键：错误的公式比标明的空缺更糟糕。因此智能体要标出自己没能确定的地方，并到汇编里去核对含糊之处。反编译器在这里丢失了许多函数参数，因为 35 年前的编译器使用的是 16 位的 <code>int</code> 类型。</p>
<p>第二阶段沿用了同样的分工。九个智能体把游戏规则重写成 C#，每个负责各自的地址范围。最后得到约 1.6 万行代码，而游戏状态被放进一个字节数组，寻址方式与原版的内存完全相同。这看上去不太优雅，却消除了一整类错误。老代码会随意让结构体相互重叠，还会从数组起始位置的前一个字节开始读取。建立在内存镜像上的移植版可以逐行翻译并与汇编对照，常量表也留在代码去找它们的位置。绘图、声音和操控则被智能体换成了对一个接口的调用，由引擎另行实现。</p>
<h2 id="判定基准处理器模拟器里的原始代码">判定基准：处理器模拟器里的原始代码</h2>
<p>阅读反编译代码并不能证明移植版的行为与原版一致。于是智能体搭建了一个比对工具。Motorola 68000 处理器的原始机器码运行在 Unicorn 模拟器中。系统例程，也就是菜单、文本窗口、读取操控输入和绘图，被替换成了 Python 函数。这些函数按照一个简单的决策生成器回答游戏提出的每一个问题，并记录游戏显示的全部内容。C# 移植版则通过一个在 Unity 之外运行的“脚本玩家”得到完全相同的决策序列。最后把两份记录逐行比对。文本里包含金币、船员人数、日期和城镇名称，所以记录一致是对规则的有力检验。</p>
<p>第一次完整测量的结果是 802 次运行中有 800 次一致。两处偏差出自同一个原因：浮点运算。游戏使用的是一个软件实现的库，它的舍入方式与今天的处理器不同。它算出的 81 的平方根是 8.999999999999998，而游戏会把结果截断为整数，于是在某些金币与船员的比例下，移植版里的船员士气会高出一点。修正的办法是把这个库的例程逐条指令重写：1572 条指令、43 个例程，以及由原始代码算出的 21,701 个测试向量，没有任何差异。改完之后，全部 802 次运行都一致；另外还有 120 次运行，在决斗、航行以及海战和陆战中逐帧比对了游戏状态。</p>
<p>比对还暴露了 1990 年原版游戏自身的两个 bug：从斜向攻击城镇时通过空指针读取地图，以及船员降到零时的除零。在这些地方，移植版必须选定一种行为，而比对工具有一个开关，可以让原版走同一条路。结果也有它的边界。这个工具不比对绘图和声音，而一些少见的路径，比如结婚、集齐藏宝图或最高的头衔，测试得很少。</p>
<h2 id="呈现层以及-1990-年没有的新增功能">呈现层，以及 1990 年没有的新增功能</h2>
<p>玩家看得到的那一层，是智能体在 Unity 里用代码搭建的，没有使用现成的场景。图像和动画从原始资源解码，精灵图取用当前画面调色板里的颜色，音乐则通过模拟游戏的四通道音序器渲染成了音频文件。智能体从命令行操控正在运行的游戏，截取屏幕画面并查看它们。这样暴露出了几个任何规则测试都抓不到的错误，比如浏览器版本没有声音，原因是音频转换需要 ffmpeg 程序，而系统里没有装。</p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-world-map.webp" alt="Unity 移植版中的加勒比海地图：带有城镇的岛屿、带航向指示的玩家船只和风暴云。" loading="lazy" decoding="async" width="1600" height="900"></p>
<p><em>在地图上航行。背景由 160 乘 200 格的地形网格和原版图块生成。</em></p>
<p>第一轮试玩之后，我提了三项修改。关于宝藏船队抵达日期的提问，在原版中是防拷贝措施，需要纸质说明书；现在问答保留了下来，但“船长笔记”里会给出正确答案。城镇列表原先只显示城镇的数据，因为游戏默认玩家手里有印刷的地图；现在所选城镇会标在加勒比海地图上。决斗画面增加了一张表格，列出双方的兵力、士气和武器，排布方式与原版相同。这些新增功能可以关闭，比对测试是在关闭它们的情况下运行的，这样记录仍然与 1990 年的代码一致。</p>
<p><img src="https://paweldubiel.com/assets/pirates-amiga-original-duel-openretro.webp" alt="Amiga 原版游戏的截图：墙前的两名剑客，下方是决斗的标题以及 Force、Morale、Weapon 表格。" loading="lazy" decoding="async" width="640" height="400"></p>
<p><em>原版中的决斗。截图来源：OpenRetro Game Database。</em></p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-duel-panel.webp" alt="Unity 移植版中的决斗：船甲板上的剑客，下方是标题以及列出双方兵力、士气和武器的表格。" loading="lazy" decoding="async" width="1600" height="900"></p>
<p><em>移植版中的同一画面。表格里的数字是从决斗状态中实时读取的。</em></p>
<p><img src="https://paweldubiel.com/assets/pirates-unity-port-city-chart.webp" alt="加勒比海地图，上面标出了 Port-de-Paix 城、玩家的位置，以及带有城镇数据和法国旗帜的信息框。" loading="lazy" decoding="async" width="1600" height="900"></p>
<p><em>相对原版的新增功能：在加勒比海地图上标出所选城镇。</em></p>
<h2 id="centurion同一套流程换成-javascript并扩展了玩法">Centurion：同一套流程，换成 JavaScript，并扩展了玩法</h2>
<p>第二个项目是 Centurion: Defender of Rome，一款 1990 年的 DOS 游戏，被移植到了 JavaScript 和 Canvas 元素上，不借助模拟器。步骤是一样的，只是名字不同。可执行文件得先解包，因为它是用 EXEPACK 工具压缩过的。游戏的五个模块（陆战、角斗场、战车竞速、海战和片头）放在一个覆盖模块文件里，共用同一个数据段。战役状态运行在这个数据段 64 KB 的实时副本上，因为游戏引擎依赖 16 位溢出、整数除法和有符号字节，而 JavaScript 的浮点数本身并不会重现这些行为。存档与原版格式逐字节一致，这一点由测试来验证。</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-title-screen.webp" alt="浏览器移植版中的 Centurion 标题画面：地中海地图上方的 CENTURION 字样、制作人员名单面板，以及 Start Game、Difficulty 和 Game Options 按钮。" loading="lazy" decoding="async" width="1070" height="800"></p>
<p><em>浏览器中的 Centurion 标题画面，使用原版图像。</em></p>
<p>在这里，我比忠实移植走得更远。我加了一个扩展规则的开关，默认关闭：军团合并和同一行省驻扎多个军团、轻装的投矛兵（velites）、战象，以及从海上登陆。这个移植版的代码出自与 Pirates 不同的模型：最多的是 Gemini 3.8 Flash，还有一部分是通过 Codex 运行的 OpenAI 的 <code>gpt-6.1-sol</code>。这样选是因为手边正好有这些工具，而不是出于对模型的比较。</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-game-options.webp" alt="Centurion 移植版中的游戏选项菜单：Extra Features: OFF 一项、难度等级、存档和读档，旁边是写有头衔和国库状况的元老院委任状。" loading="lazy" decoding="async" width="1070" height="800"></p>
<p><em>选项菜单。第一项用来开启原版中没有的扩展规则。</em></p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-province-screen.webp" alt="Centurion 移植版中的 Italia 行省画面：城市景观、带有修建圆形剧场选项的竞技菜单，以及行省状态：民心、贡赋、军队。" loading="lazy" decoding="async" width="1086" height="818"></p>
<p><em>带有竞技菜单的行省画面。</em></p>
<h2 id="gemini-在-centurion-上遇到的问题">Gemini 在 Centurion 上遇到的问题</h2>
<p>最费时间的，是那些反编译代码或文件名所暗示的内容与游戏实际行为不符的地方。下面是项目笔记里的五个例子：</p>
<ul>
<li><strong>没有数据的覆盖模块。</strong> 游戏的五个模块放在同一个文件 <code>OVL0.OVL</code> 里，被加载到同一个地址，但它们全都使用共用的数据段。因此，单独在 Ghidra 里打开覆盖模块的代码，看不到任何字符串或表。脚本把每个覆盖模块与数据段拼接起来，生成五个合成的可执行文件，直到这时反编译器才把小游戏的代码与战役的数据结构关联起来。</li>
<li><strong>被征服行省的边界。</strong> 按照鼠标可点击区域的地图来勾勒行省，得到的是棱角分明的线条，与手绘地图不相称。代码揭示的是另一种机制：在地图图像里，每个行省都有一条宽度为一个像素的深色隐藏路径，而数据中的一张表为 27 个行省各给出一个起点。游戏从起点开始，把这条路径重新涂成帝国的颜色，移植版也照此办理。</li>
<li><strong>倒退的帧。</strong> 原版的游戏循环以 9–12 Hz 的频率运行，而浏览器每秒绘制 60 次。有三处，精灵图会瞬间倒退一帧。片头里的地球仪是靠在 10 步之内移动 14 种调色板颜色来旋转的，但表中第一步的值是零；如果每一步都移动调色板，大陆每转一圈就会顿挫一下。在步兵大队的行军和角斗士的突刺中，必须精确还原顺序：先是中间帧，然后才改变位置。</li>
<li><strong>有误导性的文件名。</strong> 位图 <code>BB1.CBM</code> 和 <code>BB2.CBM</code> 看上去像是战斗横幅，可是画在屏幕顶部之后，它们遮住了整个战场。代码只在电脑没有 VGA 显卡时才加载它们：这是给较老的 EGA 和 CGA 显卡准备的全屏背景。在同一个例程里还发现，战前部署分为两个阶段。选择阵型会替换可用战术的列表，而坎尼战术要在选了楔形阵之后才会出现。</li>
<li><strong>几乎听不见的音乐。</strong> 解码出 AdLib 声卡驱动的 17 首乐曲和 24 种乐器之后，旋律是对的，但播放的电平只有约 −55 dB。对驱动的反汇编表明，每奏一个音符，它都会从乐器中保存的衰减值里减去该音符音量的四分之一。一行代码找回了约 32 dB。第二个毛病出在浏览器这一边：音符非常短的时候，在 Web Audio API 中取消已排定的音量变化，会把仍在进行的起音抹掉，使音符变成无声。</li>
</ul>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-battle-tactics.webp" alt="Centurion 移植版中的陆战：楔形阵的五种战术列表，其中包括 Cannae Tactic，以及部署在战场上的部队。" loading="lazy" decoding="async" width="1086" height="818"></p>
<p><em>战前部署的第二阶段：楔形阵可用的战术。</em></p>
<p>Circus Maximus 里的战车竞速是另一项单独的工作。那里的战车并不是一张图。如果为三种战车等级、四种车手颜色、四种动作、十六种过弯倾斜程度和三帧奔跑动画的每一种组合都准备单独的位图，就会有 2300 多帧，所以游戏的作者在内存里构建了一棵由 16 字节节点组成的树。每个节点指向同一层的下一个元素和自己的第一个子节点，并带有帧索引、各动画帧的偏移表和可见性标志。根节点是四匹马。战车车厢有一个额外的水平偏移，过弯的物理计算会往里面写入 0 到 15 像素的倾斜量，而车手是车厢的子节点，继承了这个位置。所以在弯道上，车手会随车厢一起倾斜，而马匹仍沿着赛道的轴线继续奔跑。车轴断裂和残骸翻滚的分支一直都存在，只是可见性标志处于关闭状态。</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-chariot-sprite-tree.webp" alt="Centurion 中战车精灵图树的示意图：四匹马的节点、三种等级的车厢节点、事故状态节点、车手的四种动画，以及拼合后的战车在无倾斜和倾斜 12 像素时的样子。" loading="lazy" decoding="async" width="920" height="540"></p>
<p><em>根据游戏数据还原出的战车精灵图树。示意图是在项目中用解码后的原版资源制作的。</em></p>
<p>赛道同样不是用图块搭出来的。游戏把保存的 72 对坐标展开成 368 个控制点，并把赛道横向的位置分成 16 条车道。弯道中的安全速度取决于车道，按（车道编号 + 15）× 4 计算：贴着内墙时为 60，靠外侧护栏时为 116–120。内侧车道路程最短，但以高于这个阈值的速度进入掉头弯，会使车厢倾斜，把战车甩向外侧，并触发一次翻车判定，超出得越多，翻车的可能性越大。速度条上的红色标记向玩家标示的就是这个阈值。</p>
<p><img src="https://paweldubiel.com/assets/centurion-js-port-circus-track-physics.webp" alt="Circus Maximus 赛道的几何结构：在体育场图像上用颜色标出的直道、刹车区和掉头弯，以及安全速度从内侧车道的 60 上升到外侧车道的 120 的图表。" loading="lazy" decoding="async" width="880" height="500"></p>
<p><em>赛道的 368 个点，以及随车道变化的弯道安全速度。</em></p>
<h2 id="除了游戏之外这项工作还留下了什么">除了游戏之外，这项工作还留下了什么</h2>
<p>我把这套方法写成了一个 skill，也就是智能体在接到类似任务时加载的一组指令。它包含来自两个项目的三条原则。游戏规则要忠实移植，呈现层则用接口替换。移植版保留原版的内存布局。结果在通过与原始代码的比对之前不可信任。skill 里还收录了给分析智能体和移植智能体的任务说明，以及 Pirates 项目中的脚本。</p>
<p>最有意思的结论与玩家有关，而不是与智能体有关。谁有一款自己喜欢、却多年来总觉得缺点什么的游戏，如今不需要源代码，就能又快又便宜地按自己的想法把它改出来。在 Pirates 里，那道需要纸质手册才能回答的测验题现在会给出答案，还多了一张游戏原本没有的地图。在 Centurion 里，我加入了原版没有的规则：合并军团、战象和从海上登陆。游戏规则一旦变成了普通的 C# 或 JavaScript 代码，下一次改动就只是一次普通的代码修改，而不是给二进制文件打补丁。用同样的办法也可以把游戏搬到更快的引擎或别的平台上：Centurion 在浏览器里运行，Pirates 可以构建出 Linux 版和浏览器版。这套方法也并不只适用于老游戏。反编译器、处理器模拟器和记录比对对较新的程序同样有效；代码更多意味着工作量更大，而不是换一种做法。</p>
<h2 id="资料来源">资料来源</h2>
<ul>
<li>两个项目的自有材料：代码分析笔记、给智能体的任务说明、比对工具的报告（802 次运行、所发现差异的清单）、Centurion 移植版的说明及其规格文档。这些材料没有公开发布。</li>
<li>National Security Agency，<a href="https://github.com/NationalSecurityAgency/ghidra" rel="noopener noreferrer">Ghidra</a>，用于反编译两款游戏的逆向工程套件。</li>
<li><a href="https://www.unicorn-engine.org/" rel="noopener noreferrer">Unicorn Engine</a>，用于运行原始 68000 代码的处理器模拟器。</li>
<li>OpenRetro Game Database，<a href="https://openretro.org/amiga/pirates" rel="noopener noreferrer">Amiga 版 Pirates! 的游戏页面</a>，原版游戏截图的来源。</li>
</ul>]]></content:encoded>
</item>
<item>
  <title>METR 时间跨度变长，并不意味着任务按比例变难</title>
  <link>https://paweldubiel.com/zh/articles/a-longer-metr-horizon-does-not-mean-proportionally-harder-tasks</link>
  <guid isPermaLink="true">https://paweldubiel.com/zh/articles/a-longer-metr-horizon-does-not-mean-proportionally-harder-tasks</guid>
  <pubDate>Sun, 11 Oct 2026 15:03:00 GMT</pubDate>
  <dc:creator>Paweł Dubiel</dc:creator>
  <category>ai</category>
  <category>papers</category>
  <category>llm</category>
  <category>agents</category>
  <category>benchmarks</category>
  <description>一个团队想弄清楚，能不能把更长的编程任务交给智能体的下一个版本。于是他们比较基准测试的结果，而这些结果是用人类完成这项工作所需的时间来描述的。</description>
  <content:encoded><![CDATA[<p>一个团队想弄清楚，能不能把更长的编程任务交给智能体的下一个版本。于是他们比较基准测试的结果，而这些结果是用人类完成这项工作所需的时间来描述的。这样的结果很容易被当成一种提示：现在已经可以把多少工作交给智能体了。</p>
<p>不过，这种解读需要先检验一点：人类工作的时间更长，是否真的意味着任务对 AI 也相应地更难。如果在某个区间里，各项任务对智能体的难度相近，那么它的成功率稍有提高，结果就可能跨过一大段分钟数。</p>
<p>这时，在挑选智能体时我们还需要一项额外的信息：完成同一批任务的几率发生了怎样的变化。如果我们比较的恰好是基准测试中时间不太能区分难度的那一段，单看时间的倍数就可能高估两个版本之间的差别。</p>
<p><a href="https://metr.org/time-horizons/" rel="noopener noreferrer">METR 把这种测量称为</a> <a href="https://paweldubiel.com/zh/glossary/time-horizon">time horizon</a>。在阈值为 50% 的版本中，它指的是这样一个人类工作时间：拟合出的曲线预测智能体在此处有一半的尝试成功。这是对该耗时的任务取的平均，而不是对其中每一项任务的保证。这里测量的并不是 AI 自身的运行时间。</p>
<p>在预印本 <a href="https://arxiv.org/abs/2610.12466" rel="noopener noreferrer"><em>On the estimation and validity of AI time horizons—a statistical look at the METR plot</em></a> 中，Drew T. Nguyen 和 William Fithian 分析的正是从时间到难度的换算。这项研究属于 AI 评估与统计学领域，首次发表于 2026 年 10 月 8 日，它在 METR 的数据中指出，在人类工作时间 2 到 30 分钟之间有一段几乎平坦的区段。对所考察的智能体来说，这个区间里的任务平均难度相近。</p>
<h2 id="几率的小变化可以把阈值推得很远">几率的小变化可以把阈值推得很远</h2>
<p>下面的例子是自拟的教学简化，不是研究结果。我们有 A、B、C 三项任务，人类完成它们分别需要 3、10 和 30 分钟。两个智能体各自在相同的环境中把每项任务执行 100 次。我们记录成功或失败。</p>





























<table><thead><tr><th>任务</th><th>人类耗时</th><th>较旧智能体的成功次数</th><th>较新智能体的成功次数</th></tr></thead><tbody><tr><td>A</td><td>3 分钟</td><td>100 次中 50 次</td><td>100 次中 52 次</td></tr><tr><td>B</td><td>10 分钟</td><td>100 次中 49 次</td><td>100 次中 51 次</td></tr><tr><td>C</td><td>30 分钟</td><td>100 次中 48 次</td><td>100 次中 50 次</td></tr></tbody></table>
<p>为了看得清楚，我们把这些频率当作精确已知的几率，并用递减的曲线把各点连起来。较旧的智能体在 3 分钟处与 50% 相交，较新的在 30 分钟处。时间跨度增长到十倍，可每项任务上的成功率只提高了 2 个百分点。每个智能体的 300 次尝试中，成功次数从 147 变成了 153。</p>
<p>三项任务和所有的失败都留在测量之中。我们只是选取曲线与阈值相交的位置；既没有过滤什么，也没有奖励什么。这个假想测试的成本是 600 次完整的智能体尝试。在真实的实验中，这样的样本量不足以把 2 个百分点的差别看作确定无疑。必须拟合曲线并估计不确定性。</p>
<p>这个例子展示的是从一条几乎平坦的曲线上读取时间跨度的操作。在研究中，曲线的形状要先从许多任务和系统中确定下来。如果曲线在另一个区间下降得快得多，同样倍数的时间跨度就需要成功几率有更大的提高。因此，从 3 分钟到 30 分钟，与从 30 分钟到 5 小时，按定义并不是等量的进步。</p>
<h2 id="人类耗时需要与对-ai-的难度相匹配">人类耗时需要与对 AI 的难度相匹配</h2>
<p>出发点是一张结果表：某个智能体执行了哪项任务、执行了多少次、结果如何。我们还知道人类的耗时和任务所属的族。我们不知道的，是一个描述它对 AI 有多难的客观数字。</p>
<p>作者的基线假设，人类耗时每翻一倍，难度都增加同样的一步。它让所有智能体的曲线共用一个斜率；各条曲线的差别在于能力水平。这是一个比最初采用的、对每个系统单独回归更强的参照点。</p>
<p>第一个方案用一条学习得到的单调样条（spline）曲线取代固定的步长：它由平滑衔接的若干段组成，各段可以增长得快一些或慢一些。耗时更长仍然不会降低预测的难度，但增长不必是均匀的。</p>
<p>第二个方案在论文中称为 Model 2，它采用了 <a href="https://paweldubiel.com/zh/glossary/item-response-theory">item response theory, IRT</a>。它根据成功与失败的模式，同时估计智能体的能力和任务的难度。它还考虑了同属一个族的任务之间的相似性，以及各次尝试结果的额外差异。这样一来，同一对“智能体–任务”的多次重复，就不会被当成同样多条关于整个基准测试的全新而独立的信息。</p>
<p>基线与新方法出现分歧的第一步，就是从人类耗时到难度的换算。输入的智能体结果保持不变。因此，新的拟合可以在 AI 的回答一个都不变的情况下改变时间跨度。</p>
<h2 id="同样的-gpt-4o-结果给出了不同的时间跨度">同样的 GPT-4o 结果给出了不同的时间跨度</h2>
<p>作者重新分析了 METR Time Horizon 1.1 保存下来的结果：228 项任务和 26 个 AI 系统。在图 1 中，GPT-4o 的时间跨度按共用斜率的基线计算是 7.2 分钟，按 Model 2 计算是 4.4 分钟。这是由同一批尝试得出的两个估计，既不表示 GPT-4o 的表现变差了，也不是对它推理成本的比较。</p>
<p>更灵活的曲线也可能只是更好地拟合了噪声。所以作者检验了对拟合时未使用的整个任务族的结果预测。在五折验证中，他们划分的是 79 个族，而不是同一任务的单次尝试。在指标与结果加权方式的全部 12 种组合中，两种新方法的点估计都更好。这意味着预测成功的误差更小，而不是智能体本身的成功率提高了。<a href="https://arxiv.org/html/2610.12466v1#S2.SS5" rel="noopener noreferrer">§2.4–2.5 和图 2</a></p>
<p>优势的分布并不均匀。拟合改进最多的，是时间跨度穿过上述平坦区间的 GPT-4 时代的系统。对最强的系统来说，所比较的几条曲线几乎重合。针对单个系统的估计也远不如汇总结果那样具有决定性。<a href="https://arxiv.org/html/2610.12466v1#A1" rel="noopener noreferrer">附录 A</a></p>
<details>
<summary>实验细节</summary>
<p><strong>数据与设置</strong>。这是对 METR 公开结果的重新分析，不是一批新的智能体运行。任务涉及软件方面的工作，成功与否由自动评分判定。人类耗时通常是各次成功完成所用时间的几何平均；一部分数值来自专家的估计。AI 的推理时间不是所测时间跨度中的变量。</p>
<p><strong>模型和 checkpoint 的选择</strong>。作者没有训练新的 LLM，也没有挑选它们的最佳 checkpoint。他们使用的是 METR 以往评估保存下来的结果。GPT-4o 是一个参数量未公开的 API 模型。这项分析并不确定它内部选择权重的流程。统计拟合采用最大似然法；Model 2 使用 EM 算法和积分的数值近似。曲线形状的图使用全部数据，而上文所述的预测质量比较使用按族的划分。</p>
<p><strong>指标</strong>。这一组指标包括 marginal log score，也就是二元的 <a href="https://paweldubiel.com/glossary/cross-entropy" hreflang="pl">cross-entropy [Polski]</a>，Brier score，以及在 50% 和 80% 阈值附近的平滑误差指标。Cross-entropy 会严厉惩罚自信而错误的预测；Brier score 衡量的是几率与成功/失败结果之差的平方。数值越低越好。四项指标各在三种加权方式下计算：任务等权、族等权，以及 METR 采用的折中版本。我们不把它们加总成一个百分比的改进。</p>
<p><strong>成本与不确定性</strong>。新的分析需要进行统计拟合，各个验证划分也要单独拟合，但不需要额外调用被评估的 LLM。论文没有报告部署该估计方法所节省的时间或金钱。主要比较的不确定性区间是按任务族计算的。每项指标的点估计更好，并不意味着每一个单独的对比在统计上都具有决定性。</p>
</details>
<h2 id="更长的任务需要重新检验这把尺子">更长的任务需要重新检验这把尺子</h2>
<p>论文没有确定平坦区段的成因，也没有表明它会出现在每一个基准测试中。它同样没有证明 METR 的任务代表了程序员的全部工作。作者并不质疑观察到的指数式进步趋势；他们研究的是人类工作时间轴上的间距意味着什么。</p>
<p>实际的用法，是在时间跨度之外补上一张按固定任务区间绘制的成功几率图。这样就能看出，时间跨度的跃升是否对应着可靠性的明显变化。往自己的基准测试里加入更长的任务时，在延长现有曲线之前，值得先在留出的任务族上检验一下，它们的耗时是否仍能预测对智能体的难度。</p>
<h2 id="资料来源">资料来源</h2>
<ul>
<li>Drew T. Nguyen, William Fithian, <a href="https://arxiv.org/abs/2610.12466" rel="noopener noreferrer"><em>On the estimation and validity of AI time horizons—a statistical look at the METR plot</em></a>，预印本，2026 年，v1。arXiv:2610.12466；DOI: 10.48550/arXiv.2610.12466。<a href="https://arxiv.org/html/2610.12466v1" rel="noopener noreferrer">全文</a>。</li>
<li>METR，<a href="https://metr.org/time-horizons/" rel="noopener noreferrer"><em>Task-Completion Time Horizons of Frontier AI Models</em></a>，测量的定义、评估流程和局限。该页面注明，这张图已不再积极更新。</li>
</ul>]]></content:encoded>
</item>
<item>
  <title>SemiAnalysis 比较 AI 订阅的用量限额</title>
  <link>https://paweldubiel.com/zh/articles/semianalysis-compares-ai-subscription-limits</link>
  <guid isPermaLink="true">https://paweldubiel.com/zh/articles/semianalysis-compares-ai-subscription-limits</guid>
  <pubDate>Sat, 10 Oct 2026 11:06:52 GMT</pubDate>
  <dc:creator>Paweł Dubiel</dc:creator>
  <category>ai</category>
  <description>SemiAnalysis 在 2026 年 10 月 5 日的分析中比较了各家 AI 订阅的实际限额。</description>
  <content:encoded><![CDATA[<p>SemiAnalysis 在 <a href="https://newsletter.semianalysis.com/p/anthropic-subscriptions-offer-5x" rel="noopener noreferrer">2026 年 10 月 5 日的分析</a>中比较了各家 AI 订阅的实际限额。作者考察了不同类型的 <a href="https://paweldubiel.com/glossary/token" hreflang="pl">token [Polski]</a> 会让用量指示器走多少，再把可用的额度折算成通过 API 完成同样用量所需的费用。</p>
<p>按照他们的测量，在所假定的智能体工作 token 比例下，搭配 Opus 5.5 的 Claude 按 API 价目表计算所提供的价值，大约是所比较的、搭配 GPT-6.1 Sol 的 OpenAI 订阅的五倍。这衡量的是可用的用量；模型完成任务的效果并不在比较之列。</p>
<p>文章还展示了 OpenAI 新版 Pro 200 把 token 额度减半所带来的影响，并描述了他们发现的一次 A/B 测试：其中一个账户的限额低了约 20%。可见订阅的价值还取决于不断变化的用量计算规则。</p>
<p>最后对中间商服务的比较仅向付费订阅者开放。</p>]]></content:encoded>
</item>
</channel>
</rss>