datalink.ac

同一串字符,两个读者

人怎么读,agent 怎么读,为什么这种对称就是全部的机关。

图表从设计上只考虑一个读者,而且不是那个拿着 API key 的人。

做图的渲染器是为「人」优化的:它挑一个适合数据形状的类型、一套扛得住投影仪的配色、 一个放得下最长类目的字号。然后那个人用它做点什么——看出趋势、提出问题、 决定要不要去打开那个仪表盘。

而 agent 拿到的是这份优化的产物。它拿到的是像素。

这种不对称是有代价的

代价并不隐晦,也不免费:

一张图 数据
读者拿到的东西 为人眼挑选的渲染 精确的数字
精度 渲染器画到多少 测量到多少
对模型的代价 视觉 token,约每 750 平方像素 1 个 文本 token,约 4 字符 1 个
可核对 不可 可——它就是文本

拿一张 705×500 的图来说。作为图片大约是 470 个视觉 token; 同一张图的数据,作为 JSON 大约 40 个 token。这是一个数量级的差别, 但有意思的并不是这个差别。有意思的是图片根本没法告诉你的东西: 单位是多少、样本有多大、这个值是均值还是最大值、这条序列是不是在坐标轴上被截断了。

我们不是在拿有损格式和无损格式对比,然后说图片是个坏公民。 我们是在拿「碰巧为人类而做的格式」和「我们本来就应该为机器做的格式」对比, 然后发现后者对人一样够用。

两种读法,一串字符

解法不是给 agent 再造一套 API。而是意识到:一条 URL 可以有两种读法, 而且同一条 URL 可以同时被两种方式读。

GET /d?type=pie&labels=TS,Py,Go&values=4821,2312,980
  → image/svg+xml        (人打开它)
  → 原样的规格            (agent 解析它)

渲染器的输出里嵌着它绘制自的那份规格,就放在一个 <metadata> 节点中——纯文本, 就住在 SVG 里面。所以这张图永远可以被拆回原样。我们把这条不变量叫做无损, 也正是它让第二种读法成为可能,而不需要第二个事实来源。

数据视图不是碰巧多出来的一个端点。它就是同一条链接换了读者, 所以它永远不会和图片说法不一:因为它们描述的只有一件事。

agent 该拿它怎么办

一份很短的契约,其中一句话就承载了大部分:

取链接。读数据,不要读图。

具体来说:

  • 去取,不要去猜。 如果链接给你规格,规格就是答案。永远不要从像素里还原数值。
  • 不要给数字化妆。 不悄悄四舍五入,不换单位,不重排顺序。数据说是 4.18,那就是 4.18。
  • 改参数,不要改产物。 想要另一个切面,就改写链接再取一次。 不要去编辑一个渲染好的东西——它没什么可编辑的。
  • 把链接交回去。 你用的那条链接,就该是人打开的那条。 它是唯一一个对你们双方含义相同的产物。

最后这一条,就是人机协作——不是功能,是协议。 agent 的产出和人的输入,是同一串字符。

可以直接粘贴的那句话

如果你的 agent 给你的是它从图片里读来的图,修复也许只需要一句话:

画一张饼图,把我们的错误预算按服务拆开,然后把精确的数值给我。 从链接里读,不要从图片里读——我要的是数值,不是你看图得到的印象。 最后把链接发给我,我自己想改参数。

第一句要一张图。第二句禁止了有损的那一步。第三句交回的是一件工具,而不是一张图片。

← 回到博客