跳转到内容

04 — RLM 子系统:持久化 REPL 与辅助函数体系

RLM 子系统:持久化 REPL 与辅助函数体系

学习目标

理解 CodeWhale 的 RLM(Recursive Language Model)子系统:持久化 Python REPL 设计、辅助函数体系与四种处理模式(CHUNK/BATCH/SEQUENCE/单查询)。

前置知识

下文假设你已理解上述概念,直接聚焦 CodeWhale 的具体实现。

项目实践

生命周期

四个核心工具:

  • rlm_open — 打开命名 REPL 会话,加载源数据
  • rlm_eval — 执行 Python 代码,返回结果
  • rlm_configure — 调整 REPL 反馈设置
  • rlm_close — 关闭完成的会话

源数据加载

rlm_open 可以加载多种源:

  • 文件内容(大文件 > 50K tokens)
  • 长文本(日志、转记、语料)
  • session:// 引用(v0.8.45 引入:加载当前提示、历史和会话数据)

加载的源在 REPL 内作为 _context 可用,_ctxcontent 是兼容别名。

REPL 内辅助函数体系

函数用途处理模式
peek有界检查(开头/结尾/摘要)所有模式
search语义搜索CHUNK/BATCH
chunk分块处理CHUNK
context_meta元数据提取所有模式
sub_query单个子查询SEQUENCE
sub_query_batch并行批量查询(需声明 independence)BATCH
sub_query_sequence顺序依赖查询SEQUENCE
sub_query_map映射式查询BATCH
sub_query_sequence序列式查询SEQUENCE
sub_rlm嵌套 RLM 调用所有模式
finalize最终合成所有模式
evaluate_progress进度评估所有模式

四种处理模式

CHUNK — 真正的超大输入(整个文件 > 50K tokens、长转记、多文档语料)。分块处理,每块独立处理,最后合成。

BATCH — 多个独立项需要 LLM 关注(分类 20 个条目、从 30 个文档提取字段、评分 15 个候选)。使用 sub_query_batch(..., dependency_mode="independent") 并行执行——它 fan-out 到同一个 DeepSeek 客户端,在一轮中完成 15 次顺序读取的工作量。批量助手拒绝运行,除非显式声明独立性。

SEQUENCE — 数据依赖工作,其中 A 的输出是 B 的输入。使用 sub_query_sequence(...) 或显式 Python for 循环。中间状态存储在变量中,每步检查结果再继续下一步。

符号状态设计

RLM 的核心设计是符号状态

  • 长输入和中间值留在 REPL 环境中
  • 不复制到根模型上下文
  • 用有界切片检查(peek),不用全量输出
  • 用 Python 变换,不用语言描述
  • 大中间字符串存储在变量或 var_handle
  • 不要将整个 body 粘贴回 prompt 中

var_handle 输出支持

当 RLM 返回大对象时,不直接返回完整内容,而是返回 var_handle

  • 父 Agent 通过 handle_read 按需查询
  • 支持切片、行范围、JSONPath 投影
  • 保持父上下文精简,但不丢失对细节的访问

问题与规避

陷阱:BATCH 模式用于依赖工作

如果项之间有依赖关系(B 依赖 A 的输出),使用 sub_query_batch 会导致错误结果。

规避:批量助手拒绝运行,除非显式声明 dependency_mode="independent"。对于依赖工作,使用 SEQUENCE 模式或 Python 显式 for 循环。

陷阱:RLM 返回大对象膨胀父上下文

RLM 处理的结果可能很大(如分类 100 个条目的完整结果)。如果直接返回,会膨胀父上下文。

规避:使用 var_handle 返回大对象。父 Agent 通过 handle_read 按需读取关键部分。

陷阱:REPL 状态泄漏

关闭 RLM 会话后,REPL 环境中的变量和状态可能被新会话误用。

规避:每个 rlm_open 创建新的独立 REPL 环境。rlm_close 清理环境。会话之间不共享状态。

设计取舍

为什么选择 Python REPL

  • Python 是数据处理的通用语言——大部分文本处理、JSON 操作、统计分析都可以用 Python 单行完成
  • REPL 提供了交互式探索的能力——先 peek 了解数据结构,再决定处理策略
  • Python 的标准库足以处理大多数上下文操作,不需要额外依赖

RLM vs 上下文压缩

维度RLM上下文压缩
目的处理超出窗口的长文本释放上下文空间
方法Python REPL + 辅助函数摘要/截断
保留信息按需查询(完整保留)有损(摘要丢失细节)
适用场景需要精确分析大文件长对话需要腾出空间
成本RLM 子调用成本压缩调用成本

两者互补:RLM 处理数据,压缩释放空间。

为什么批量助手需要独立性声明

这是安全设计——防止模型无意中将依赖任务并行化导致竞争条件或错误结果。显式声明 dependency_mode="independent" 强制模型思考任务之间的依赖关系。

参考来源

  • crates/tui/src/tools/rlm.rs — RLM 工具实现
  • prompts/base.md 中 “RLM — How to Use It” 章节
  • v0.8.45 CHANGELOG: RLM session objects