Rust 版 Pi 工作基本完成了,记录下性能对比

1,890 字#Rust #Pi

最近做了一个 Rust 项目:pi-rust。把 TypeScript 版的 Pi 编码助手用 Rust 重写,命令叫 rpi。

先把测试结果放出来。

先看数据对比

对比版本是 rpi 0.3.6 和 Pi 0.87.1

指标Rust 版 rpiTypeScript 版 Pi
打印版本号 --version17.5 ms169.5 ms
启动到能够响应状态请求17.7 ms189.5 ms
刚就绪时的常驻内存 RSS12.0 MiB91.5 MiB
安装体积21.8 MiB约 385 MiB

启动时间相差约 10.7 倍,rpi 的就绪内存约为 Pi 的 13%。安装体积这一项,Pi 还没有算上 Node 运行时。

为什么要用 Rust 重写?

1. 学习 Rust

首先就是想学 Rust。

我想找一个能持续写下去的项目。Agent 涉及异步请求、流式输出、文件操作和状态管理,后面还有终端界面和插件。这些需求会逼着我把 Rust 用起来:共享状态怎么处理,错误怎么往上传,异步任务怎么取消,接口怎么拆。

选 Pi 来重写,也有一个好处:有现成的项目可以参考。遇到一个功能,可以先看原版怎么做,再考虑在 Rust 里怎么实现。写完以后还有东西可以对照,不至于只凭自己的想象判断是否合理。

2. 想弄明白一个 Agent 是怎么工作的

平时用 AI 编码工具,看到的是输入需求、等它改代码。自己实现一次,就得处理那些界面上看不见的细节。

模型返回一个工具调用以后,谁去执行?工具出错了,要把什么结果交给模型?流式消息还没结束,用户取消了怎么办?程序中断后,下一次启动看到的历史应该是什么?

这些问题在调一次聊天 API 时未必会遇到,做完整 Agent 就绕不过去。

核心循环其实不长:请求模型,发现工具调用,执行工具,回传结果,再请求模型。周围的错误处理、取消、会话保存,才是需要花心思的地方。

3. 想把它做成一个能复用的库

我希望 rpi 除了能在终端里运行,也能直接嵌进自己的 Rust 程序。应用调用接口、订阅事件,就能使用 Agent 的能力。

所以项目用了 Cargo workspace,把模型适配、Agent 循环、工具执行和会话管理拆开。CLI 再把它们组合起来。

最小的 Agent 不需要终端界面,也不一定需要持久化。需要文件工具,就加工具层;需要保存会话和压缩上下文,再接 Harness。这样不同应用能各取所需。

4. 看看原生程序能省下多少开销

终端工具最后能交付一个可执行文件,安装时少管理一套 Node 和 npm 依赖,我觉得值得试。

启动和内存上的收益,前面的测试已经给了一组结果。代价也有:Rust 的异步接口、共享状态和动态插件都需要仔细处理。把原版代码逐行翻译过来,很多地方并不好用,接口也得跟着重新整理。

现在到哪一步了

已经有 CLI、TUI 和 SDK,不只是一个调用模型的 demo。当前工作区版本是 0.3.14;发布状态以仓库 Releases 和 crates.io 为准。

模型侧有 Anthropic 和 OpenAI 兼容接口,也支持通过配置接自定义网关。Agent 能处理流式响应、工具调用和取消,配有文件读写、编辑和命令执行等工具。

会话用 JSONL 保存,支持分支、上下文压缩和中断恢复。这里也一直在修实际问题。比如 CHANGELOG 里记录过:会话中断时,工具调用已经保存,结果还没保存,恢复后的消息就可能被模型服务拒绝。现在会补上表示中断的错误结果,让上下文可以继续使用,而不会直接重跑那个工具。

扩展方面已经有动态库插件 SDK 和加载器。远程模式也有了,可以在一台机器上跑 Agent,另一端用终端连接。

这些功能对应九个产品 crate。主要几层如下:

crate做什么
rpi-ai模型适配、消息类型和流式响应
rpi-agentAgent 循环、工具调用、事件和取消
rpi-tools内置工具和执行环境
rpi-harness会话、持久化、恢复和上下文压缩
rpi-cli配置、CLI、TUI 和远程模式

想从代码看起,可以先跑两个例子:

cargo run -p minimal
cargo run -p tools-example

它们用模拟 Provider,不需要模型密钥。第二个例子会驱动真实工具,在临时目录写文件,再读取并验证内容。这样可以先检查 Agent 的执行流程,不受真实模型输出影响。目前还有不少需要打磨的地方。

有没有后续的扩展计划

有,接下来想继续做的主要是这些方向。

扩展更容易写和安装。 插件接口和加载器已经有了,但还需要更顺手的模板、版本兼容说明,以及能直接拿来用的扩展。先把开发和使用的流程理顺,比单纯增加插件数量更有用。

继续补模型适配。 现有 Provider 接口可以复用,后面会根据使用需求考虑 Gemini、Bedrock 等适配器。每接一种协议,都要检查流式事件、工具调用和错误处理,不能只验证普通聊天能返回文字。

把性能测试往长任务上补。 下一步值得测的是长会话内存增长、工具循环吞吐、上下文压缩和 TUI 渲染。启动数据已经有了,我也想知道连续用上几个小时以后是什么表现。

更往后的方向包括执行隔离、编辑器集成,以及是否把多 Agent 编排放进核心运行时。这些需要继续设计,暂时没有确定的交付时间。

项目地址:bigfish1913/pi-rust。如果你也在学 Rust,或者想拆开看看 Agent 的实现,可以从两个离线示例开始。