构建安全的 AI 代码助手与自动化脚本系统

前言

代码生成是 LLM 最强大的能力之一。然而,仅仅生成代码是不够的,真正的 AI 助手需要能够执行代码、验证结果并根据错误进行自我修复。本文将探讨如何构建一个安全、可靠的代码生成与执行系统。


代码生成最佳实践

1. 结构化提示词

为了获得高质量的代码,提示词应包含:

  • 任务描述:明确要实现的功能。
  • 技术栈:指定语言、库和版本。
  • 约束条件:性能要求、异常处理、编码规范。
  • 输出格式:要求只输出代码块,不含解释。

2. 示例引导 (Few-shot)

提供高质量的代码示例可以显著提升生成代码的风格一致性。

prompt = """
你是一个高级 Python 工程师。请根据要求编写函数。

示例:
要求:计算列表的平均值,处理空列表。
代码:
def calculate_average(numbers: list[float]) -> float:
    if not numbers:
        return 0.0
    return sum(numbers) / len(numbers)

要求:{user_request}
代码:
"""

代码解析与提取

LLM 通常返回 Markdown 格式的代码块。我们需要可靠地提取这些代码。

import re

def extract_code(text: str, language: str = "python") -> str:
    """从 Markdown 文本中提取代码块"""
    pattern = rf"```{language}\n(.*?)\n```"
    match = re.search(pattern, text, re.DOTALL)
    if match:
        return match.group(1).strip()
    
    # 如果没有 Markdown 标记,尝试直接返回
    if "def " in text or "import " in text:
        return text.strip()
    
    return ""

安全的沙箱执行

绝对不要在本地环境直接运行 LLM 生成的代码。 必须使用隔离的沙箱环境。

方案对比

方案 安全性 性能 复杂度 适用场景
Docker 通用后端执行
E2B / Bearly 极高 云端托管沙箱
Piston 快速多语言执行
Pyodide (WASM) 浏览器端执行

进阶实战:持久化沙箱会话 (Persistent Sessions)

在复杂的任务中,我们需要在多个对话回合中保持代码执行的状态(变量、文件、导入等),类似于 Jupyter Notebook。

1. 使用 E2B 维护持久化状态

from e2b_code_interpreter import CodeInterpreter

def run_with_e2b(code: str):
    with CodeInterpreter() as sandbox:
        # 执行代码
        execution = sandbox.notebook.exec_cell(code)
        
        # 处理输出(文本、图表、错误)
        if execution.error:
            print(f"执行错误: {execution.error.name}: {execution.error.value}")
            return None, execution.error.value
            
        # 如果生成了图表,E2B 会返回 base64 编码的图片
        for result in execution.results:
            if result.png:
                save_chart(result.png)
                
        return execution.text, None

---

#### 核心技术:自我修复循环 (Self-Correction Loop)

这是 AI 程序员 Devin  OpenDevin的核心逻辑

#### 流程
1.  **生成**LLM 生成代码
2.  **执行**在沙箱中运行代码
3.  **反馈**如果报错 **错误堆栈 (Traceback)**  **原始代码** 发回给 LLM
4.  **修复**LLM 分析错误并生成修复后的版本
5.  **循环**重复上述步骤直到代码运行成功或达到最大重试次数

```python
def autonomous_coder(task: str, max_retries: int = 3):
    code = generate_initial_code(task)
    
    for i in range(max_retries):
        output, error = run_in_sandbox(code)
        if not error:
            return code, output
            
        print(f"尝试 {i+1} 失败,正在修复...")
        code = generate_fix(code, error)
        
    raise Exception("无法修复代码")

沙箱安全深度防御

即使在 Docker 中运行,也需要多层防护:

  1. 网络隔离:禁用沙箱的外部网络访问,防止代码将你的 API Key 或敏感数据发送到黑客服务器(防止数据外泄)。
  2. 资源限制 (cgroups):限制 CPU 使用率为 10%,内存限制为 128MB,防止恶意代码(如死循环或内存炸弹)耗尽宿主机资源。
  3. 只读文件系统:除了 /tmp 目录外,其他目录设为只读。
  4. 超时控制:强制执行时间不得超过 30 秒。

行业应用:AI 数据分析师

结合代码执行,LLM 可以变成一个强大的数据分析师。

  • 输入:一个 CSV 文件和问题(“分析去年的销售趋势”)。
  • 过程:LLM 编写 Python 代码(使用 Pandas 和 Matplotlib),在沙箱中读取 CSV,生成分析报告和可视化图表。
  • 输出:文字结论 + 统计图表。

总结

代码执行赋予了 LLM “行动”的能力。

  • 安全性是底线:永远使用隔离沙箱(推荐 E2B)。
  • 鲁棒性是关键:建立自我修复循环
  • 状态保持是进阶:使用持久化会话处理复杂任务。

通过构建这套系统,你不仅是在做一个“会说话”的 AI,而是在做一个真正能“干活”的 AI 助手。

class PersistentSandbox: def init(self): # 创建一个持久化的沙箱实例 self.sandbox = CodeInterpreter()

def run_step(self, code: str):
    """执行代码并保持状态"""
    print(f"正在执行代码块...")
    execution = self.sandbox.notebook.exec_cell(code)
    
    if execution.error:
        return {"status": "error", "msg": execution.error.traceback}
    
    # 获取标准输出和结果
    return {
        "status": "success",
        "stdout": execution.logs.stdout,
        "results": [r.to_dict() for r in execution.results]
    }

def close(self):
    self.sandbox.close()

示例:第一步定义变量,第二步使用变量

ps = PersistentSandbox() ps.run_step(“x = 10”) result = ps.run_step(“print(x * 2)”) # 输出: 20


#### 2. 多文件项目管理

如果任务涉及多个文件(如 Web 爬虫或小型应用),我们可以在沙箱中动态创建文件结构。

```python
def setup_project(sandbox: CodeInterpreter):
    # 在沙箱中创建目录和文件
    sandbox.filesystem.make_dir("src")
    sandbox.filesystem.write("src/utils.py", "def add(a, b): return a + b")
    sandbox.filesystem.write("main.py", "from src.utils import add\nprint(add(1, 2))")
    
    # 执行主程序
    execution = sandbox.process.start("python3 main.py")
    return execution.wait().stdout

核心进阶:代码自我修复循环 (Self-Healing)

通过将执行错误反馈给 LLM,可以实现代码的自动纠错。

async def self_healing_code_gen(task: str, max_rounds: int = 3):
    code = await llm.generate(f"任务: {task}")
    
    for _ in range(max_rounds):
        result = sandbox.execute(code)
        if result.success:
            return result.output
        
        # 将错误信息喂回给 LLM
        code = await llm.generate(f"代码执行失败,错误如下:{result.error}\n请修复代码。")
    
    return "无法修复代码"

构建代码解释器 (Code Interpreter)

一个完整的代码解释器循环包括:生成 -> 执行 -> 报错 -> 修复。

class AICodeAssistant:
    def __init__(self):
        self.llm = ChatOpenAI(model="gpt-4o")
        self.max_retries = 3

    def solve_task(self, task: str):
        current_task = task
        for i in range(self.max_retries):
            # 1. 生成代码
            code_response = self.llm.invoke(f"编写 Python 代码完成任务:{current_task}。只输出代码。")
            code = extract_code(code_response.content)
            
            print(f"尝试 {i+1}: 执行代码...")
            
            # 2. 执行代码
            result = execute_ai_code(code)
            
            if result["success"]:
                print("✅ 执行成功!")
                return result
            else:
                print(f"❌ 执行失败: {result['error']}")
                # 3. 自我修复:将错误反馈给 LLM
                current_task = f"""
                之前的代码执行失败了。
                任务:{task}
                错误类型:{result['error']}
                错误详情:{result['traceback']}
                请修复代码并重新提供。
                """
        
        return {"success": False, "message": "达到最大重试次数"}

数据可视化支持

代码执行不仅是计算,还包括生成图表。

def execute_and_get_charts(code: str):
    with CodeInterpreter() as sandbox:
        execution = sandbox.notebook.exec_cell(code)
        
        # E2B 会自动捕获 matplotlib/plotly 的输出
        charts = []
        for result in execution.results:
            if result.png:
                charts.append(result.png) # Base64 编码的图片
        
        return charts

安全性深度防御

即使在沙箱中,也需要限制资源:

  1. 网络限制:默认禁用网络访问,除非任务需要。
  2. 超时控制:设置硬性超时(如 30 秒),防止死循环。
  3. 内存限制:限制进程可用内存(如 512MB)。
  4. 文件系统隔离:只允许读写特定的临时目录。
  5. 敏感词过滤:在执行前检查代码中是否包含 os.environ, rm -rf / 等关键词。
def security_check(code: str) -> bool:
    forbidden_patterns = [
        r"import\s+os",
        r"import\s+subprocess",
        r"open\(",
        r"eval\(",
        r"exec\("
    ]
    for pattern in forbidden_patterns:
        if re.search(pattern, code):
            return False
    return True

单元测试生成

为了确保生成的代码逻辑正确,可以让 LLM 同时生成单元测试。

test_prompt = f"""
针对以下函数编写 3 个 pytest 测试用例:
{generated_code}

要求:
1. 覆盖正常情况和边界情况。
2. 使用 assert 语句。
"""

总结

代码生成与执行是构建强大 AI Agent 的基石。通过结合结构化提示词安全沙箱(如 E2B)以及错误反馈循环,我们可以构建出能够自主解决复杂计算和数据分析任务的智能系统。


参考资源

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 LLM应用开发——代码生成与沙箱执行 》

本文链接:http://localhost:3015/ai/%E4%BB%A3%E7%A0%81%E7%94%9F%E6%88%90%E4%B8%8E%E6%89%A7%E8%A1%8C.html

本文最后一次更新为 天前,文章中的某些内容可能已过时!