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 的推理能力,但它也带来了一些新的挑战。

  1. 正确性验证困难
    • 问题:
    LLM 生成的代码执行结果,未必和用户问题语义完全对齐。
    如果代码逻辑有 bug,但运行能返回“貌似合理”的结果,用户可能难以察觉。
    • 风险:
    得到错误答案,但因为有“代码支撑”,用户会过度信任。
    • 缓解思路:
    增加冗余验证:同一任务用不同实现思路多跑几次,交叉对比结果。
    引入“结果检查器”模型(Verifier)对输出进行二次验证。

  2. 代码执行的稳定性
    • 问题:
    代码可能包含致命错误(死循环、内存溢出、调用非法库等)。
    代码注入攻击风险:用户或模型生成的代码可能试图访问敏感资源。
    • 风险:
    执行环境崩溃、资源耗尽、安全漏洞。
    • 缓解思路:
    沙箱执行(限制内存、CPU、磁盘、网络)。
    设置超时和资源上限。
    仅允许白名单库和函数。

  3. 调试与可解释性
    • 问题:
    当结果不对时,很难判断是 LLM 推理错误,还是代码实现错误。
    调试成本高:需要人工检查 LLM 输出的多段代码。
    • 风险:
    难以快速定位问题,导致系统可靠性差。
    • 缓解思路:
    要求 LLM 输出代码+解释。
    生成单元测试,自动验证关键函数。

  4. 性能与效率
    • 问题:
    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

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐