找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3683

积分

0

好友

506

主题
发表于 6 天前 | 查看: 26| 回复: 0

用语言模型写代码、与数据库交互、运行自动化流程,这些操作如今已司空见惯。然而,当一个智能体(Agent)任务一多,它就容易丢三落四,甚至开始一本正经地胡说八道。

现代模型工具接入(如MCP)虽然方便,但也带来了 上下文腐化 的问题——随着输入的 Token 数量急剧增加,模型的性能会呈断崖式下跌。这迫使我们去思考,当任务复杂度超出模型原生处理能力时,如何另辟蹊径?答案或许藏在代码之中。今天,我们就来深入探讨两种截然不同但思路相通的代码驱动方案:CodeAct 与 RLM。

Claude 的内存结构拆解:窗口里到底塞了什么?

我们不妨先看看上下文窗口里到底被什么东西占满了。以 Claude 为例,其上下文窗口的典型分配大致如下:系统提示词约占 1.4%,系统工具(包括 MCP 工具)占 8.3%,而智能体上下文(如技能描述、工具说明、对话历史)则吃掉了约 70%。留给用户实际输入的空间反而非常有限。

Claude 上下文窗口分配示意图

根据 Anthropic 的研究,真正用于放置核心系统指令的部分仅有约 10%,其余空间都被对话历史、工具输出和各类中间结果填满。一旦总 Token 数膨胀到 20 万级别,模型就难以分辨重点,这是导致模型健忘和幻觉频发的根本原因之一。一个缓解思路是更智能地利用上下文窗口,而 CodeAct 正是这样一种方案。

CodeAct:用代码作为“动作”与外界交互

CodeAct 的核心思想非常直接:既然大语言模型(LLM)天生擅长写代码,为什么不直接让它用可执行的代码来与外部世界交互呢?简单来说,就是用代码块作为智能体的“动作空间”。

举个例子,假设你需要从一个学生数据库中查找 2025 年入学的所有记录。与其让模型在上下文里费力地“推理”和扫描,不如让它直接生成并执行一条 SQL:

SELECT * 
FROM students 
WHERE enrollment_year = 2025;

把检索工作交给专门的数据库引擎,这才是高效开发者的做法。CodeAct 的逻辑与此完全一致:与其将海量数据塞进上下文让模型去“理解”(顺便加剧上下文腐化),不如让模型写一段代码、执行它、然后观察结果。

CodeAct 处理流程示意

其工作流可以概括为: 问题 → 写代码 → 执行 → 迭代 → 最终答案。

CodeAct 多轮交互框架图

CodeAct 多轮交互框架(图源论文)

回到学生数据库的例子,CodeAct 的完整流程是:接收用户自然语言查询 -> LLM 理解意图并生成 Python 代码 -> 在编译器/环境中执行 -> 检查输出。如果结果满意就返回,不满意则基于错误反馈进行迭代修正。

1. 原子工具调用:CodeAct 表现持平或更优

在第一组实验中,研究者在 API-Bank 基准上测试了最简单的单 API 调用场景,对比了文本格式、JSON 格式和 CodeAct(Python 函数调用)三种方案。

原子 API 调用正确率对比表

即使在完全用不上控制流优势的简单场景下,CodeAct 在多数模型上的正确率都持平甚至更高。对于 GPT-4、Claude 等闭源模型,三种格式表现稳定;但开源模型从 CodeAct 中获益更大。一个合理的解释是:在预训练阶段见过大量代码的模型,用代码表达动作比用 JSON 更自然。

2. 复杂多工具任务:CodeAct 实现更高成功率

真正拉开差距的是多工具组合场景。在包含 82 个人工精选任务的 M3ToolEval 基准上,CodeAct 的优势明显——模型可以在一个代码块里组合多个工具,使用循环和条件语句控制流程,存储中间变量,跨步骤复用输出。

数据表明,最佳模型的绝对成功率提升了 20.7%,平均交互轮次减少了 2.1 轮。有趣的是,模型能力越强,从这种结构化的动作空间中获得的收益就越大。

多工具任务成功率对比图

M3ToolEval 完整结果表

3. 多轮自调试能力

CodeAct 带来了一个宝贵的能力:自调试。因为动作本身就是代码,执行出错会产生结构化的错误反馈(traceback),模型在下一轮就可以针对性地修复。论文展示了一个案例:CodeActAgent 使用 Pandas 下载数据、训练回归模型、进行可视化,过程中遇到 matplotlib 报错或数据缺失问题,都能自行修复。

CodeAct 多轮自调试交互示例图

4. 微调进一步释放性能

研究者构建了包含约 7k 条多轮轨迹的 CodeActInstruct 数据集,并在此基础上微调出 CodeActAgent。相比基础的 LLaMA-2 和 Mistral,微调后的模型性能有大幅提升,在 MINT 等任务上表现突出,与更大规模的模型相比也颇具竞争力。

CodeActAgent 评估结果表

综上所述,CodeAct 不仅仅是格式上的改进。它重构了智能体的动作空间,为模型赋予了控制流、数据流、可复用变量和自动反馈循环。工具使用不再是一个接一个地调用 API,而是变成了可编程的推理过程。

CodeAct 简易实现

(注:以下为实验性原型,生产环境建议使用隔离沙箱。)

导入依赖:

import os 
import re 
import io 
import contextlib 
from openai import OpenAI 
from google.colab import userdata 

os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY") 
client = OpenAI()

定义工具函数:提取并执行 Python 代码。

def extract_python_code(text: str): 
    pattern = r"```python(.*?)```" 
    match = re.search(pattern, text, re.S | re.I) 
    return match.group(1).strip() if match else None 

def run_python(code: str): 
    buf = io.StringIO() 
    try: 
        with contextlib.redirect_stdout(buf): 
            exec(code, {}) 
        return buf.getvalue() 
    except Exception as e: 
        return f"Execution error: {e}"

核心的 CodeAct 循环:

SYSTEM_PROMPT = """ 
You are a CodeAct agent. 
Always solve using Python code. 
Return ONLY a python code block. 
Do not explain in text. 
"""

def codeact_run(user_problem, max_iters=3): 

    messages = [ 
        {"role": "system", "content": SYSTEM_PROMPT}, 
        {"role": "user", "content": user_problem} 
    ] 

    for step in range(max_iters): 

        resp = client.chat.completions.create( 
            model="gpt-4o-mini", 
            messages=messages 
        ) 

        text = resp.choices[0].message.content 

        print("\n===== MODEL OUTPUT =====\n") 
        print(text) 

        code = extract_python_code(text) 

        if not code: 
            print("\n No code block — retrying\n") 
            messages.append({ 
                "role": "user", 
                "content": "Return python code block only." 
            }) 
            continue 

        print("\n EXECUTING PYTHON:\n") 
        print(code) 

        output = run_python(code) 

        print("\n PYTHON OUTPUT:\n") 
        print(output) 

        return output 

    print("Failed to obtain executable code.") 
    return None

运行一个物理问题示例:

problem = """ 
A batter hits a baseball at 45.847 m/s at 23.474 degrees. 
Outfielder throws it back at 24.12 m/s at 39.12 degrees. 
Find final distance from batter. 
Assume no air resistance and g = 9.8. 
"""

codeact_run(problem)

模型成功生成并执行了计算抛体运动的代码,得出了最终距离。这说明 CodeAct 确实让 LLM 拥有了“编程的手”,能动手解决问题。

但 CodeAct 仍有其局限:如果输入本身极其庞大,比如几百页的报告或整个代码仓库,单次前向传播仍然无法消化。那么,能否让代码不只是调用外部工具,而是用来组织模型自身的推理过程呢?这就是 递归语言模型 要解决的问题。

简单来说,CodeAct 是“代码作为动作接口”,而 RLM 是“代码作为推理控制器”。

RLM:递归语言模型

RLM 的工作方式可以用伪代码概括:

超长文档 
→ 拆分成块 
→ 模型分析每个块 
→ 递归调用模型汇总 
→ 聚合结果 
→ 最终答案

RLM 工作流程示意

论文给出的正式定义是:“一种通用推理策略,将长提示词视为外部环境的一部分,允许 LLM 以编程方式检查、分解并递归地在提示词片段上调用自身。”

RLM 处理长书籍的架构图

RLM 处理整本书的架构(图源论文)

如图所示,RLM 不会把完整文本硬塞进模型,而是将其视为外部环境。根模型(depth=0)通过代码执行将文本拆分成块,发起递归子调用(depth=1)来分析相关部分,最后聚合所有子结果形成最终响应。

1. 长上下文下的性能表现

RLM 的核心价值在于将推理能力扩展到模型固定上下文窗口之外。实验数据表明,在 S-NIAH、OOLONG 等基准上,随着输入长度增加,基础模型的表现快速下降,而 RLM 的表现则保持稳定——即使输入规模达到百万 Token 量级,远超模型原生窗口。

RLM 与基础模型在不同长度下的性能对比图

2. 信息密集型任务的优势

在要求模型聚合几乎所有输入信息的 OOLONG-Pairs 任务上,基础模型的 F1 分数近乎为零,而配置了 GPT-5 的 RLM 则拿到了 58% 的 F1 分数。这表明 RLM 改变的不仅仅是信息访问量,更是推理的执行方式。

RLM 在不同任务上的性能对比表

3. 效率与成本分析

你可能会担心递归推理成本高昂,但数据并非如此:RLM 的平均 API 成本与基础模型相当,有时甚至更低。因为它通过代码有选择地探测相关部分,避免了处理全量上下文中的无效 Token。

RLM 成本分位数分布图

本质上,RLM 将长上下文推理从一个内存瓶颈问题,转变为一个可编程的搜索与聚合问题。

RLM 实战:分析超长文档

我们以亚瑟·柯南·道尔的《福尔摩斯探案集》(TXT 格式)为例,该文档字符数超过 650 万。

文档字数统计截图

按 OpenAI 的估算规则,这大约对应 162.5 万 Token,远超任何商用模型的上下文窗口。

任务:提取文档中出现频率最高的前 20 个大写实体,并总结 3 个核心主题。

安装 rlms 包并初始化环境:

pip install -qU rlms
import os 
from rlm import RLM 
from rlm.logger import RLMLogger 
from google.colab import userdata 
api_key = userdata.get('OPENAI_API_KEY')

with open("big.txt", "r", encoding="utf-8") as f: 
    large_document = f.read() 

logger = RLMLogger(log_dir="./logs")

rlm = RLM( 
    backend="openai", 
    backend_kwargs={ 
        "model_name": "gpt-4o-mini",
        "api_key": api_key, 
    }, 
    environment="local", 
    environment_kwargs={}, 
    max_depth=1,
    logger=logger, 
    verbose=True, 
)

prompt = f""" 
You are analyzing a large document. 
Return ONLY valid JSON. 
TASK: 
Extract the top 20 most frequent capitalized entities 
and summarize 3 major themes. 
Document: 
{large_document} 
""" 

result = rlm.completion(prompt) 
print(result)

RLM 经过 25 轮迭代,耗时约 400 秒,处理了约 202 万输入 Token,输出了约 9.8 万 Token,最终成功返回了实体列表和主题摘要。虽然与严格的词法计数存在轻微偏差,但它准确识别了语料的核心叙事主题,完成了对超长文档的语义理解。

RLM 估计值与真实计数对比图

总结:动作与推理,选择正确的范式

大语言模型正从单纯的文本生成器演变为可编程的系统。CodeAct 与 RLM 是这条进化路径上两个方向互补的范式。它们都让 LLM 的推理过程变得透明、可观察、可控制。

  • CodeAct 把 LLM 变成了执行引擎,适合需要“动手做事”的任务:

    • 工具调用与 API 编排
    • 数据库查询与数据处理
    • 需要通过执行验证的自动化流程
  • RLM 让 LLM 用代码组织自己的推理,适合处理“规模过大”的任务:

    • 超长文档分析与摘要
    • 跨多文档的信息聚合与推理
    • 信息密集型分析任务

两者并非互斥。在生产系统中,完全可以组合使用——由 RLM 负责在海量信息中完成复杂推理和决策,再由 CodeAct 负责将决策转化为具体动作,与外部系统交互。

真正的范式转移在于:与其不计成本地扩大上下文窗口,不如去重构计算本身。无论是 CodeAct 的“执行循环”还是 RLM 的“递归分解”,LLM 系统的未来不在于能“吃下”多少 Token,而在于如何更智能地“控制”推理与行动。对这类 人工智能 前沿技术范式的持续探索与分享,正是像 云栈社区 这样的技术社区的价值所在。


引用

  1. https://research.trychroma.com/context-rot
  2. https://arxiv.org/abs/2402.01030
  3. https://github.com/langchain-ai/langgraph-codeact
  4. https://arxiv.org/abs/2512.24601v1
  5. https://github.com/dscape/spell/blob/master/test/resources/big.txt
  6. https://platform.openai.com/tokenizer
  7. https://developers.openai.com/api/docs/models/gpt-5.2-pro
  8. https://github.com/alexzhang13/rlm
  9. https://github.com/shreyanshjain05/RLM-Implementation
  10. https://dspy.ai/api/modules/RLM/



上一篇:底层逻辑构建方法论:掌握动态立体思维模型,提升认知与问题解决能力
下一篇:两天深度解析 OpenClaw 源码:AI Agent 的理想架构与工程实践启示
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 09:01 , Processed in 0.668137 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表