open-interpreter — 本课题摘录
读了哪几篇: 01-harness-emulation(外壳仿真:为什么、枚举、路由)、02-harness-shaping(请求塑形与响应回译)。
其余几篇本轮没读。
这一家提出了一个别处没有的概念,而且它直接影响本课题第一和第二个决定。
它对本课题回答了什么
一个新说法:一副"外壳"= 系统提示 + 工具定义格式 + 走哪个接口协议
同一个模型,套上 A 工 具的外壳和套上 B 工具的外壳,收到的提示和工具说明是两份不同的东西。
为什么要伪装:开源/低价模型是在各自厂商命令行工具的提示与工具格式上做过对齐调优的。
- 某家的模型见惯的是某套工具名和提示口吻;
- 另一家在某种风格的塑形下表现最好;
- 第三家熟悉第三套。
直接塞进另一套原生格式,它们会"水土不服"——工具调用格式错、指令跟不住、效果掉一截。 (依据:Agent 库 · Open Interpreter (Rust) · Harness 仿真:为什么、Harness 枚举、路由矩阵 —— 开源/低价模型是在各自厂商 CLI 的提示与工具格式上做过对齐调优的,直接塞进 Codex 原生格式会水土不服,所以按 (WireApi × Harness) 两维路由把请求塑形成模型最熟悉的那个 harness 的样子)
策略一句话:按模型,把请求塑形成它最熟悉的那副外壳。模型以为自己还在原来的工具里跑,于是发挥出训练时的水平。
这条对本课题很重要,因为它推翻了一个默认假设: "一轮的输入怎么拼"和"工具怎么描述"是我们自己的设计自由。
不完全是。模型对某些格式有肌肉记忆,顺着它的记忆写,效果更好。
前面已经三次撞上这条:
- aider:用模型最熟悉的文本格式,出错率最低;
- oh-my-pi:有的模型被训练成在文本里用特定标记喊工具,走结构化通道反而绕远;
- open-interpreter:整套外壳都要照着它熟悉的来。
三家的说法一次比一次强。可以写成一条定则:格式的选择要顺着模型的训练分布,而不是顺着我们的审美。
决定二(结构):塑形与回译是一对翻译器
引擎只认自己的内部格式;外壳就是夹在引擎和真实模型接口之间的一对翻译器。
引擎的内部格式(历史 + 工具清单)
↓ 塑形:换系统提示、压平历史、编码工具
某工具原生的请求体 →(发给真实模型)→ 返回流式输出或纯文本
↓ 回译:纯文本 → 合成的工具调用
引擎认得的事件流
(依据:Agent 库 · Open Interpreter (Rust) · 一个 harness 到底改了什么:请求塑形与响应回译 —— 一个 harness = build_request 把请求塑成某工具原生的样子 + postprocess 把 模型的纯文本回译成合成的 function_call,两端夹着同一台引擎)
塑形三件套(任何一种外壳都在改的三样):换系统提示、压平历史、编码工具。
这个结构跟 oh-my-pi 的"方言层"几乎是同一个东西,但视角不同:
- oh-my-pi 的方言层只管"工具调用怎么编解码";
- open-interpreter 的外壳把系统提示和历史格式也算进去。
后者的范围更大,而且更接近真相:模型熟悉的不只是工具格式,还有提示的口吻和历史的排布。
没有原生工具调用的外壳,靠回译把模型吐出来的一段纯文本变成引擎能执行的工具调用。
引擎因此完全不知道差别——它只看到自己认得的事件流。
这跟 oh-my-pi 的"上层完全看不出区别"是同一条设计不变量,值得写进讲义: "怎么认出模型要调工具"这件事应该被一层完全吸收,循环不该知道下面走的是哪条路。
外壳一共十五个具名变体加一个兜底。 路由是两维的:走哪个接口协议 × 用哪副外壳。
它没回答什么
- 循环骨架本身——它继承自另一个项目的引擎,这两篇没讲循环。
- 历史怎么压——"压平历史"是塑形的一部分,但这两篇没讲压缩策略。
- 什么时候停——不在这两篇。
坑与代价
- 十五副外壳意味着十五套塑形与回译要维护。 而且模型厂商更新了自己的工具,这一层就滞后了。
- "伪装"依赖一个假设:模型确实在那套格式上调优过。 这个假设没法直接验证,只能靠效果反推。
判断(无锚): 对我们的最小原型,这一整套是过度设计。但那条底层观察要记住:换模型时,别只换模型名,还要问"它熟悉什么格式"。 如果错,会错在: 如果我们只用一两家旗舰闭源模型,它们对格式的宽容度很高,这条观察的价值就接近零。
- 回译出来的是"合成的"工具调用,不是模型真的走了结构化通道。 一旦回译错了,错误发生在循环之外,循环侧看不到任何异常。