CodeAct范式
在大模型agent领域,比较常见的是ReAct范式,它的核心思想是把推理(Reasoning)和行动(Acting,通常是工具调用)结合起来。LLM 一边输出“思考过程”,一边决定调用什么工具或采取什么行动,再根据观察结果继续推理。而CodeAct的核心思想是让 LLM 输出 可执行代码(而不是自然语言的行动指令),然后在安全环境里执行代码,执行结果再反馈给模型,进入下一轮。虽然CodeAct还有
rag系列文章目录
前言
在大模型agent领域,比较常见的是ReAct范式,它的核心思想是把推理(Reasoning)和行动(Acting,通常是工具调用)结合起来。LLM 一边输出“思考过程”,一边决定调用什么工具或采取什么行动,再根据观察结果继续推理。
而CodeAct的核心思想是让 LLM 输出 可执行代码(而不是自然语言的行动指令),然后在安全环境里执行代码,执行结果再反馈给模型,进入下一轮。
一、为什么需要CodeAct
之所以需要CodeAct,是因为大模型没法进行继续,或者大模型计算的准确度不高。比如文本中提到a和b,而c等于a加上b,让大模型输出c的值,大模型输出很可能不准确。
还有需要画图的时候,大模型没法直接画图,而写代码就很方便。
CodeAct主要适用于以下场景:
1、 复杂计算 / 数学推理
2、 数据处理 / 科学计算 / 可视化
3、 编程题(如 HumanEval、MBPP)
4、 高精度要求的场景(减少 LLM “口算” 出错)
二、存在的问题
CodeAct 虽然能提升 LLM 的推理能力,但它也带来了一些新的挑战。
-
正确性验证困难
• 问题:
LLM 生成的代码执行结果,未必和用户问题语义完全对齐。
如果代码逻辑有 bug,但运行能返回“貌似合理”的结果,用户可能难以察觉。
• 风险:
得到错误答案,但因为有“代码支撑”,用户会过度信任。
• 缓解思路:
增加冗余验证:同一任务用不同实现思路多跑几次,交叉对比结果。
引入“结果检查器”模型(Verifier)对输出进行二次验证。 -
代码执行的稳定性
• 问题:
代码可能包含致命错误(死循环、内存溢出、调用非法库等)。
代码注入攻击风险:用户或模型生成的代码可能试图访问敏感资源。
• 风险:
执行环境崩溃、资源耗尽、安全漏洞。
• 缓解思路:
沙箱执行(限制内存、CPU、磁盘、网络)。
设置超时和资源上限。
仅允许白名单库和函数。 -
调试与可解释性
• 问题:
当结果不对时,很难判断是 LLM 推理错误,还是代码实现错误。
调试成本高:需要人工检查 LLM 输出的多段代码。
• 风险:
难以快速定位问题,导致系统可靠性差。
• 缓解思路:
要求 LLM 输出代码+解释。
生成单元测试,自动验证关键函数。 -
性能与效率
• 问题:
LLM 可能生成冗长、低效的代码(如暴力算法)。
多轮执行反馈模式增加延迟。
• 风险:
响应慢,计算资源浪费。
• 缓解思路:
使用 Code Optimization Agent,对生成代码做优化。
预置高效工具库(避免 LLM 重复造轮子)。
三、实践
以下使用langgraph构建CodeAct工作图,如下所示:
代码如下:
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END, START
from langchain.schema import BaseOutputParser
from typing import TypedDict
from dotenv import load_dotenv
import traceback
import os
# Load environment variables
load_dotenv()
assert os.getenv("OPENAI_API_KEY"), "OPENAI_API_KEY not set in .env"
# Typed state with retry support
class AgentState(TypedDict, total=False):
instruction: str
code: str
output: str
error: str
traceback: str
retries: int
# Extract Python code from LLM response
class CodeExtractor(BaseOutputParser):
def parse(self, text: str) -> str:
import re
match = re.search(r"```python(.*?)```", text, re.DOTALL)
return match.group(1).strip() if match else text.strip()
# Step 1: Generate code
def generate_code(state: AgentState) -> AgentState:
llm = ChatOpenAI(temperature=0, model="gpt-4")
prompt = f"Write Python code to do the following task:\n\n{state['instruction']}"
response = llm.invoke(prompt)
code = CodeExtractor().parse(response.content)
return {
**state,
"code": code
}
# Step 2: Execute the code
def execute_code(state: AgentState) -> AgentState:
try:
local_vars = {}
exec(state["code"], {}, local_vars)
output = local_vars.get("result", "Execution completed. No `result` variable found.")
return {
**state,
"output": output,
"error": None,
"traceback": None
}
except Exception as e:
retries = state.get("retries", 0) + 1
return {
**state,
"error": str(e),
"traceback": traceback.format_exc(),
"retries": retries
}
# Branch logic: Retry if error and below max
MAX_RETRIES = 3
def error_handler(state: AgentState) -> str:
if "error" in state and state.get("retries", 0) < MAX_RETRIES:
return "generate_code"
return END
# Build LangGraph
builder = StateGraph(AgentState)
builder.add_node("generate_code", generate_code)
builder.add_node("execute_code", execute_code)
builder.add_edge(START, "generate_code")
builder.add_edge("generate_code", "execute_code")
builder.add_conditional_edges("execute_code", error_handler)
graph = builder.compile()
# Run the agent
if __name__ == "__main__":
user_input = "Plot a sine wave using matplotlib and numpy"
initial_state: AgentState = {"instruction": user_input, "retries": 0}
result = graph.invoke(initial_state)
print("\n--- Final Result ---")
if "output" in result:
print("Output:\n", result["output"])
else:
print("Error:\n", result.get("error", "Unknown error"))
print("Traceback:\n", result.get("traceback", "No traceback"))
生成的图片如下,该agent通过生成代码,并执行代码,获得了sin曲线。
总结
虽然CodeAct还有很多问题需要解决,但是随着大模型编程的能力越来越强,这些问题会大大缓解。CodeAct是一种新的方式,这种agent不仅仅会聊天,而且会主动code,深入思考,大大加强了agent处理复杂问题的能力。
参考文档: 1 2
更多推荐
所有评论(0)