npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hicaru/pi-rlm

v0.3.16

Published

Save 99% tokens, Recursive Language Model (RLM) for the Pi

Readme


pi-rlm — 为 Pi 编程代理提供的递归语言模型 (Recursive Language Models)

递归语言模型 (RLMs) 作为 Pi 扩展原生实现 —— 完全本地。


递归语言模型 (RLM) 是一种与任务无关的推理范式,其中根语言模型通过对输入进行编程式的检查、分解并递归调用自身,从而在近乎无限的上下文中进行编排。RLM 将典型的 llm.completion(prompt, model) 调用替换为 rlm.completion(prompt, model) 调用:提示词/上下文作为 REPL 环境中的一个变量进行卸载,模型与其进行交互,并且模型可以将子 LLM 和子 RLM 调用作为代码中的普通函数启动。

这是对 CodeAct 风格框架的一种尝试 —— 每个语言模型都能访问代码环境,子 (R)LM 调用是函数,而上下文/提示词是代码中的对象 —— 从而脱离了 JSON 工具调用 (tool-calling) 标准。以此方式构建的系统本身就是一个依赖于递归子 LLM 调用的语言模型,因此得名。

pi-rlm 将该范式原生引入 Pi

  • 根编排器模型逐轮驱动一个持久化的 Python REPL
  • 长上下文工作通过 llm_query / llm_query_batched 委派给廉价的工作模型。
  • 困难的子问题通过 rlm_query 递归到子 RLM 中(设有深度限制)。子 RLM 继承父级的 context ——已加载的文件以及通过 add_context() 追加的来源——因此可以在相同的路径上使用相同的检索原语。 继承不消耗额外的 token:内容存放在沙箱中,模型只看到一行大小信息。
  • 所有内容均在进程内运行 —— 唯一的外部进程是一个本地的 python3 worker。

这是 RLM 方法的 Pi 插件重新实现(参见 RLM 论文)。 它不是那个 Python 库。

工作原理

pi 进程 (TypeScript)
 ├─ /rlm  ──► 引擎逐轮驱动 SMART (根) 模型 (编写 ```repl``` Python)
 │             │  每轮:解析 repl 块 ──► 在沙箱中运行 ──► 将 stdout 反馈回去
 │             ▼
 ├─ bridge ── llm_query / llm_query_batched ──► WORKER 模型 (serverless, 进程内)
 │            rlm_query ──► 递归子 RLM (自有沙箱), 设有深度限制
 ├─ AgentTree ──► 编辑器上方的实时 agent/subagent 树 (角色, 深度, 成本, token)
 └─ PythonSandbox ── `python3 worker.py` ──[基于 stdio 的 JSONL, 双向]── 持久化 REPL
  • 无需服务器,无需 socket,无需 Docker。 唯一的外部进程是一个本地 python3 沙箱。 当沙箱代码调用 llm_query 时,worker 在 stdout 上写入请求并在 stdin 上阻塞; Pi 在进程内提供服务并将回复写回。供应商 API 密钥绝不会进入沙箱。
  • 沙箱公开了 context, llm_query, llm_query_batched, rlm_query, rlm_query_batched, SHOW_VARS(), ask_user_question() 以及一个 answer 字典。 模型通过设置 answer["ready"] = True 来提交最终结果。

安装

pi-rlm 是一个 Pi 包。Pi 提供了 @earendil-works/pi-*typebox peer 依赖;请不要在该包中安装它们的独立副本。要求 PATH 中有 python3 (仅限标准库)。

开发时的推荐本地安装方式:

pi install /path/to/this-repo/pi-plugin/rlm

已发布的 npm 包安装方式:

npm publish                       # 例如 as @<you>/pi-rlm
pi install npm:@<you>/pi-rlm

Git 安装要求包清单位于安装的仓库根目录下。 对于像这样一个 monorepo 子目录,请优先使用上述的本地路径或 npm 流程。

如果您之前直接复制了扩展文件夹,请将其删除,以免遮蔽 (shadow) 该包:

rm -rf ~/.pi/agent/extensions/rlm

然后运行 /reload 或重启 Pi。使用 pi list 验证该包是否出现在 settings.packages 中,并检查 /rlm, /rlm-config/rlm-stop 是否出现在 [Extensions] 下。

命令

| 命令 | 快捷键 | 描述 | |---|---|---| | /rlm | Ctrl+Shift+R | 切换持久化 RLM 模式 (通过 RLM 引擎路由普通提示词) | | /rlm-stop | | 终止正在运行的任务 | | /rlm-config | | 选择 smart + worker 模型并调整运行设置 |

在任务激活期间,一个实时树会显示根编排器和每个子 LLM / 递归子节点的状态、模型、成本、token 和持续时间。最终答案将以 markdown 形式发布 到聊天中;任何代码修改将作为 diff 收集并通过弹出窗口进行审核 (除非开启了 yolo)。

沙箱 API

这些函数被注入到 REPL 内部模型的 Python 命名空间中:

| 函数 | 签名 | 描述 | |---|---|---| | context | list[dict] | 打包为 [{"path","content","tokens"}, ...] 的仓库 —— 完整的代码库 | | llm_query | (prompt) -> str | 单次子 LLM 调用(配置的 RLM LLM) | | llm_query_batched | (prompts) -> list[str] | 并发子 LLM 调用 (池上限) | | llm_query_chunked | (text, prompt) -> list[str] | 将大文本拆分为不超过上限的块并通过子 LLM 处理 | | rlm_query | (prompt, paths=None) -> str | 具有自有沙箱的递归子 RLM (设有深度限制)。继承父级的 contextpaths 按前缀缩小范围 | | rlm_query_batched | (prompts, paths=None) -> list[str] | 并发递归子 RLM,共享同一个 paths 切片 | | ask_user_question | (questions) -> list[dict] | 向用户提出结构化问题 (仅限深度 0) | | SHOW_VARS | () -> str | 列出当前定义的变量及其类型 | | answer | dict | 设置 answer["content"]=...; answer["ready"]=True 以结束 |

设置 (/rlm-config)

| 设置 | 默认值 | 含义 | |---|---|---| | Smart model | Pi 的当前活动模型 | 根编排器 | | Worker model | 最便宜的可用模型 | 响应 llm_query | | Max recursion depth | 4 | 超过此深度的 rlm_query 将回退到 llm_query | | Max iterations | 30 | 引擎完成前的最大轮数 | | Budget ceiling | none | 当美元支出超过此值时停止整个树 | | Max consecutive errors | 5 | 在 N 轮连续错误后停止 | | REPL block timeout | 120s | 每个 repl 块的墙上时钟时间 (worker 中的 SIGALRM) | | Max concurrent sub-calls | 4 | *_batched 的池大小 | | Orchestrator addendum | on | “委派,而非自行解决”的引导 | | Trajectory compaction | on (0.85) | 当历史记录接近上下文窗口时进行总结 | | yolo | off | 立即应用建议的修改,跳过审核弹出窗 | | askUserQuestion | on | 向模型公开 ask_user_question() |

并发注意: 每个 rlm_query 子节点都会启动自己的 python3 worker (冷启动约 50–150 毫秒)。 最坏情况下的并发解释器数量 ≈ maxConcurrentSubcalls^(depth−1);在 默认设置下 (深度 4, 并发 4),极端情况下为 4³ = 64。预算和错误 上限 (见上文) 无论扇出 (fan-out) 如何都会限制总支出。

采样与可复现性

r3 基准测试表明:最大的能力杠杆不是模型,而是采样。仅 temperature 0 就让 OOLONG 从 71% (pooled) / 40% (flips) 提升到 91.7–100% all-stable,总计仅花费 $1.74。这些旋钮在 rlm.json (~/.pi/agent/rlm.json) 和 /rlm-config 面板中都是一等公民:

| 字段 | 位置 | 默认值 | 作用范围 | |---|---|---|---| | rootSampling.maxTokens | rlm.json, 面板 | 16384 | 根模型每轮的输出上限 (包括 finalize) | | rootSampling.temperature | rlm.json, 面板 | 提供商默认 | 根轮次与 finalize 的采样温度;0 = 确定性 | | smartReasoning | rlm.json, 面板 | 无 | 根模型的思考强度 | | subSampling.maxTokens | rlm.json, 面板 | 8192 | 每个叶子子调用 (llm_query, llm_batch, map_files) 的输出上限 | | subSampling.temperature | rlm.json, 面板 | 提供商默认 | 叶子调用的采样温度 | | enableVerificationNudge | rlm.json | 关 | 当根节点过早以“裸数字”定稿时,给予一次带提示的重做 |

可复现性配方 (经 r3 验证):

{
  "config": {
    "rootSampling": { "maxTokens": 8192, "temperature": 0, "reasoning": "high" }
  }
}

思考 token 与答案共享补全预算——开启 thinking 时请保持充裕的 maxTokens (基准测试将其翻倍至 8192;若过紧,引擎会在第 0 轮警告一次)。

作用边界: rlm.json 的采样适用于 RLM 模式运行、rlm() 委托以及任意深度的子递归 (同一个引擎函数)。Pi 原生代理循环遵循 Pi 自身的会话设置——rlm.json 不会触及它。

模型能力: reasoning 要求模型的注册表条目为 reasoning: true。其他情况会在发送给 提供商之前丢弃该级别 (pi-ai 会将不支持的级别钳制为 off);能力来自注册表,而非配置。

运行日志

  • 密钥隔离:供应商密钥仅存在于 TypeScript (AuthStorage) 中;沙箱 接收提示词并返回文本 —— 绝不接触密钥。
  • 环境清理:在 worker 启动前会剥离敏感环境变量 (API 密钥, token)。 worker 无法从 os.environ 读取供应商凭据。
  • 并非安全沙箱:Python worker 公开了 __import__open。模型编写的 代码可以导入网络模块、读写本地文件,并向 stdout 写入符合协议格式的 JSON。 此层级信任根模型的代码;stdio 协议隔离的是供应商密钥和 进程生命周期,而非对抗性代码的隔离。以后可以在不改变协议的情况下, 通过设置添加更强的沙箱 (Docker, seccomp)。
  • 限制内置函数:禁用 eval/exec/compile/input/globals/locals;每块 SIGALRM 超时 + 父进程监视器 (挂起时 SIGKILL);预算 / token / 超时 / 连续错误上限。
  • 信任:本地安装需要 Pi 项目信任。

基准测试

针对 OpenRouter 聊天模型对真实引擎进行端到端测试 —— 精简套件(needle 多针召回、 codeqa 代码库问答、coding 修复任务;每个模型 7 个任务 × 2 轮)。确定性评分 (召回率 / 标准答案包含 / 正则),无 LLM 评审。

最新结果 —— 小型模型(≤32B 参数,付费额度):

| 模型 | 参数 | 得分 | 准确率 | 每任务延迟 | |------|------|------|--------|------------| | qwen/qwen3-30b-a3b-instruct-2507 | MoE 30B / 3B 激活 | 14/14 | 100% | ~15s | | google/gemma-3-27b-it | dense 27B | 12/14 | 86% | ~26s | | mistralai/mistral-small-3.2-24b-instruct | dense 24B | 12/14 | 86% | ~28s |

逐任务原始数据(正确性、召回率、延迟、token、成本)位于 bench/runs/bench-<ts>.jsonl —— 每个任务一行 JSONL,作为历史记录提交。

运行基准测试

export OPENROUTER_API_KEY=sk-or-...        # 必需 —— 密钥仅通过环境变量传递

bun run bench                              # 精简套件:needle + codeqa + coding
bun run bench --suite needle --limit 1     # 单个套件,仅第一个任务
bun run bench --model openrouter/qwen/qwen3-30b-a3b-instruct-2507
bun run bench --list                       # 仅列出任务,无需引擎和密钥
bun run bench --suite paper                # paper 套件:s_niah, oolong, browsecomp, codeqa_lb(需下载数据集)

套件:all(精简版,默认) · needle · codeqa · coding · paper · s_niah · oolong · browsecomp · codeqa_lb

项目布局

src/
  sandbox/    py/ (worker.py · guards · retrieval · tasks) · sandbox.ts · interrupts · protocol · sandbox-manager · context-file
  bridge/     model.ts (single completion) · subcall-handlers.ts (the one llm/rlm impl) · ask-user · library
  core/       engine.ts (the loop) · iteration · limits · resource-limits · answer · compaction · history · types
  prompts/    glossary (shared REPL vocabulary) · system (headless) · native · user
  text/       parsing (repl blocks) · tokens · preview
  tool/       repl-tool · repl-result · repl-render · rlm-tool · rlm-events · rlm-aggregator · subcall-store · background-tasks
  config/     defaults · settings (rlm.json persistence + validation)
  context/    native walker + anydoc document conversion + add_context
  ui/         status · model-picker · config-panel · intro · theme
  commands/   rlm · rlm-config
  mode/       rlm-mode (controller) · worker-model (cheapest pick) · native-guards
  util/       errors · concurrency · trace
test/         phase suites · native-smoke · native-mode · helpers

测试

运行时为 Bun (bun install, bun run … —— 绝不要使用 npm/pnpm/yarn)。

bun run test/phase1.ts                   # 沙箱:执行, 持久化, 密钥隔离, 超时终止
bun run test/phase4.ts                   # 递归深度限制逻辑 (不消耗 token)
bun run test/phase5.ts                   # 实时 agent 树渲染 (不消耗 token)
RLM_TEST_LIVE=1 bun run test/phase2.ts   # 通过沙箱进行真实的 llm_query
RLM_TEST_LIVE=1 bun run test/phase3.ts   # 在文件上下文中进行真实的端到端 /rlm 运行
RLM_TEST_LIVE=1 bun run test/phase4.ts   # 引擎解决 20 个文档的“大海捞针”测试

背景

基于 RLM 论文 中的方法,为 Pi 原生重新实现。

如果您在研究中使用此项目,请引用原始 RLM 工作:

@misc{zhang2026recursivelanguagemodels,
      title={Recursive Language Models},
      author={Alex L. Zhang and Tim Kraska and Omar Khattab},
      year={2026},
      eprint={2512.24601},
      archivePrefix={arXiv},
      primaryClass={cs.AI},
      url={https://arxiv.org/abs/2512.24601},
}