我卖 LLM 记忆 API,也在做记忆基准测试:如何尽量不给自己放水

原文:https://dev.to/woochan/i-sell-memory-apis-im-also-building-the-benchmark-heres-how-im-trying-not-to-rig-it-481e(作者 @woochan)

这次我来讲讲这个基准测试是怎么开始的,以及它的核心到底是怎么搭建的。

这个项目始于读各种抱怨,而不是源于一个点子。同样的话反复出现:厂商发布的数字和别人实测的数字对不上;换掉做评分的模型,对结果的影响比被比较系统之间的差距还大;也正因为如此,基本上没人真用公开发布的数字。大家会拿自己的数据测两个方案,然后留下那个让他们烦得少一点的。我在 Wontopos 工作,公司卖记忆 API,所以我没法指着这些问题耸耸肩不管。

下面所有数字都来自当前构建版本。一切都还没定稿,所以等你读到这篇文章时,其中一些数字可能已经变了。

公平优先,因为你没有理由信任我

我知道,一个记忆公司的人说“我做了个公平的基准测试”听起来是什么味道。所以我不会承诺什么,而是把仓库里写的内容原样摆出来。

Wontopos 托管这个项目并负责运行,仅此而已。我们同时也在做记忆基础设施,意味着我们要在自己管理的这套东西里参与竞争,所以限制被白纸黑字写下来,而不是靠口头承诺:

  • 我们的提交和其他人走同样的审批流程。我们不会自己合入自己的提交。
  • 我们不决定谁能被接收,规则决定。
  • 我们的成绩和其他人用同样的方式核验。
  • Wontopos 在新版本发布后十四天内不公布任何成绩。
  • 如果有其他记忆公司想共同管理,这比我们单独管理更好,这个邀请一直有效。

几条提交规则也朝同一个方向使劲:

  • 发布逐题记录。 任何人都能据此重新算出结果。汇总只是断言,逐题记录才是证据。
  • 读取器、评分模型和提示词由版本决定。 提交者不能自己选。
  • 评测框架必须是客户能直接用的那种。 一个只有作者本人能跑通的路径产生的数字,不是别人也能拿到的数字。

以上所有内容都是 Apache 2.0 协议,所以如果我们哪天成了问题,整套东西可以被拿走、到别处运行,不用问我们。

全都在这里:[github.com/wontopos/glasshouse](https://github.com/wontopos/glasshouse)。先提醒你里面现在有什么:基准测试本体还没放进去,submissions/ 是空的。规则是先放上来的,我们自己也都还没有提交。

语料

用约 17 个月的对话讲述的一个人的人生,你需要记住的事实就埋在里面。103,572 轮对话、1,991 个会话、约 190 万个 token。

它在四种干草堆规模下运行,从一小块核心到完整语料。真正包含答案的那 1,882 轮对话,在四个版本里逐字完全相同。变化的是包裹在它们周围的无关注话量。这样你能看到一个系统随着干草堆变大而逐步退化,而不是只得到一个分数、完全不知道它意味着什么。

维度

完整规模下共 14 个维度、1,547 道题。大多数是普通回忆:说过的话能不能取回来;换个说法提问还能不能找到;能不能说出事情发生的时间;能不能把两条事实组合起来。

下面这四个维度才是我做这件事的原因。

过期事实。某个值发生了变化。新值存在,但我故意让它在语料里变得难找。结果是三选一,而不是二选一:

  • 新值:1.0
  • “我不知道”:0.5
  • 旧值并把它当作当前值:0.0

中间那一行才是整个设计的重点。把“我不知道”和“自信地给一个过期值”放进同一个类别,你就把生产环境里真正有害的东西藏了起来——这两种表现,是你花钱买服务时差别极大的两种结果。

矛盾。对话里对同一个事实给出了两个不同的值,没人纠正,也没有任何线索告诉你哪个是对的。不存在正确答案。笃定地选其中一个是错的;说“这两个对不上”才是对的。

表面矛盾。这是上一项的镜像。两句话看起来冲突,但在不同条件下都成立,所以两者都为真。这道题要测的核心就是能不能把它和真正的矛盾区分开。

弃答。问的是从未提到过的事。空答案拿满分,编造一个得零分。此外还有 500 个虚假记忆探针,它们在问题本身里植入一件从未说过的事,看系统会不会顺着话头接下去。

图片

对话里共享了 50 张照片,配 150 道关于照片的题。每道题都锚定到一个日期:“在 2026 年 4 月 14 日的那张照片里,沙发上是什么?”

这样设计是因为有 50 张照片时,像“笔记本电脑开着吗?”这种问题会同时指向两张照片。放在对话流里没问题,但把问题单独抽出来,或者翻译成另一种语言,就变得无法正确回答了。日期能把目标限定到唯一一张照片,同时也不会泄漏答案,因为没有任何问题在问事情是什么时候发生的。

语言

语料包含 10 种语言,每种 10 个会话,共 100 个会话,混在其余内容里。800 道题针对这部分,双向测试:

  • 一条事实只以另一种语言存储,然后用英语提问。
  • 一条事实以英语存储,然后用另一种语言提问。

两个方向都很重要,因为它们的失败方式不同。前者测的是到底有没有任何信息能跨过语言边界,后者测的是提问那一侧能不能跨过去。

速度,以及为什么这样来测

速度当然重要,但公平地测量它比看上去要难得多,这也是我改动最多的部分。

问题出在地理上。 裸延迟本身就包含着光速带来的传输成本。从首尔去测一台美国服务器,服务器还没来得及处理任何请求,190ms 就已经没了。原样报出这个数字,你排出来的是服务器所在的位置,而不是它本身的好坏。

所以网络底限会被单独测量,再从中减掉。剩下的部分我称之为「延迟减去往返时间」,而不是「纯计算延迟」——因为响应传输的时间无法完全减干净,叫「纯计算」会高估它。

有两个条件能减小剩余误差,而且两者都是测试流程的一部分:

  1. 先预热连接。 TCP 是慢启动的,速率会逐步爬升。不预热的话,一个超过 14KB 的响应会额外多出一个往返,而 3,700 token 的响应正好卡在这条边界上。
  2. 记录响应体积。 剩余误差会随响应体积同步增大,把它记下来,读者才能判断这个数字里留有多少余量。

预算。 从人的感知来说,对话一旦超过 1,000ms,就不再像「自然流畅的交流」。其中 LLM 首个 token 的生成本身就占掉约 500ms,那么记忆部分分到的是剩下的 500ms——这就是目标值。比目标值快一倍得 +1 分,慢四倍得 -1 分,中间按对数尺度插值,因为 200ms 和 400ms 之间的差异,比 3s 和 3.2s 之间的差异更有意义。

按题计分,且有上下限。 每道题得分在 -1 到 +1 之间,最终结果取平均而非累加。如果改成累加惩罚,题目越多总分就越往下沉,分数从此不再能描述这套系统本身。

速度会和准确率并列呈现,不会悄悄折进准确率里,权重也会明确写出。如果某个系统上测不了速度,对应项会被移除而不是记 0——测不了本身不该是一种惩罚。

目前还没有跑出任何分数,在没有数据之前,我不会引用任何数字。

一个问题,留给你

如果你打算跑一个类似的东西,里面必须具备什么,你才会相信测试结果?如果你看过某个已发布的记忆基准测试得分、心里闪过一句「这不靠谱」,是什么出卖了它?

原文:https://dev.to/woochan/i-sell-memory-apis-im-also-building-the-benchmark-heres-how-im-trying-not-to-rig-it-481e(作者 @woochan)

发布评论
全部评论(0)