AI Agent实战:构建安全可靠的代码生成与执行系统

最近在筹备一个面向2026年的技术峰会项目,团队内部讨论最热烈的议题之一就是如何利用AI Agent技术,打造一个能实时生成、演示甚至交互的“代码秀”环节。这不仅仅是简单的代码补全或片段展示,而是希望构建一个能理解需求、自主编码、解释逻辑并应对现场提问的智能体。在这个过程中,我们深入调研了包括Amazon Bedrock在内的多个平台,踩了不少坑,也积累了一套从概念到落地的完整方案。

本文将系统性地拆解“AI驱动的代码秀”这一概念,分享如何利用现有的大模型与Agent框架,构建一个能够进行动态代码演示与讲解的智能系统。无论你是对AI应用开发感兴趣的初学者,还是正在寻找技术峰会创新亮点的团队负责人,都能从中获得从环境搭建、核心原理到实战部署的全流程指导。

1. 背景与核心概念:什么是“AI代码秀”?

传统的技术演讲或代码展示,通常是演讲者预先编写好代码,在台上逐行讲解。这种方式虽然经典,但互动性有限,且难以应对观众即兴提出的、偏离预设路径的问题。

“AI代码秀”旨在改变这一模式。其核心是构建一个或多个AI智能体(Agent),它们能够:

  1. 理解自然语言需求:接收来自主持人或观众的、用自然语言描述的编程任务(例如:“请用Python写一个快速排序算法,并可视化每一步的过程”)。
  2. 规划与执行:将复杂任务拆解为规划、编码、测试、调试等子步骤,并自主调用代码解释器、文件系统等工具来执行。
  3. 生成与演示:实时生成可运行的代码,并在一个安全的沙箱环境中执行,将结果(控制台输出、图表、Web界面等)展示出来。
  4. 解释与交互:不仅展示代码,还能用通俗的语言解释关键算法、设计思路,并回答关于代码性能、可替代方案等后续问题。

这背后的关键技术支撑正是AI Agent。它不是单一的大模型,而是一个具备感知、规划、决策和执行能力的系统。一个典型的代码生成Agent可能包含以下模块:

  • 大脑(LLM):如GPT-4、Claude 3或通过Amazon Bedrock访问的各种大模型,负责理解、规划和推理。
  • 规划器:将用户目标分解为可执行的任务序列。
  • 工具集:如代码解释器、命令行、浏览器、绘图库等,是Agent与外界交互的“手和脚”。
  • 记忆模块:保存对话历史、执行上下文,确保在多轮交互中保持一致。
  • 安全沙箱:一个隔离的环境,用于安全地执行Agent生成的代码,防止对主机系统造成破坏。

2. 环境准备与版本说明

为了构建一个原型系统,我们需要搭建一个融合了大模型API、Agent框架和代码执行环境的开发栈。以下是一个基于Python的推荐环境,它平衡了能力与易用性。

核心环境:

  • 操作系统:Ubuntu 20.04+/macOS Monterey+/Windows 10+ (WSL2推荐)
  • Python版本:3.9 或 3.10(许多AI库对3.11+的兼容性仍在完善中)
  • 包管理工具:pip 或 poetry

关键依赖库及版本建议:构建一个基础的代码生成Agent,你可能需要以下库。请注意,AI生态迭代迅速,版本号请根据实际情况调整。

# requirements.txt 示例 langchain==0.1.0 # Agent框架,提供高阶抽象 langchain-community==0.0.10 # 社区工具和集成 openai==1.6.1 # 如需使用OpenAI API anthropic==0.18.0 # 如需使用Claude API boto3==1.34.0 # AWS SDK,用于访问Amazon Bedrock docker==6.1.3 # 用于管理代码执行沙箱容器 jupyter==1.0.0 # 可选,用于交互式开发和演示 streamlit==1.28.0 # 可选,用于快速构建演示Web界面

大模型API选择(三选一或组合):

  1. OpenAI GPT系列:生态最成熟,工具调用(Function Calling)能力强大,适合快速原型验证。
  2. Anthropic Claude系列:在代码和长上下文理解上表现优异,安全性设计较好。
  3. Amazon Bedrock:这是一个托管服务,提供了通过统一API访问多个顶尖模型(如Claude、Llama、Titan)的能力。优势在于企业级的安全、合规和成本管理,适合生产环境。你需要一个AWS账户并启用Bedrock服务。

Agent框架选择:

  • LangChain/LangGraph:目前最流行的Agent框架之一,模块化设计,工具链丰富,社区活跃。本文示例将主要基于LangChain。
  • AutoGen:由微软推出,擅长多Agent协作,适合构建复杂的对话和任务分解场景。
  • Semantic Kernel:微软另一个框架,深度集成.NET生态,但同样支持Python。

对于“代码秀”场景,我们首先需要一个能可靠执行代码的安全沙箱。这里推荐使用Docker容器作为隔离环境。

3. 核心原理与架构拆解

一个能够进行“代码秀”的AI Agent,其工作流程可以简化为以下核心循环:

用户输入自然语言任务 ↓ Agent(LLM核心)进行任务规划与拆解 ↓ Agent选择并调用工具(如:Python解释器、文件写入) ↓ 工具在Docker沙箱中执行代码并返回结果(输出、错误、图表文件) ↓ Agent分析结果,决定下一步(继续执行、修正错误、返回答案) ↓ 将最终代码、结果和解释返回给用户

3.1 关键组件详解

1. 工具(Tools)工具是Agent能力的延伸。对于代码秀,最重要的工具是代码执行工具

# 示例:一个简单的基于Docker的Python代码执行工具(概念模型) import docker import subprocess import tempfile import os class DockerPythonExecutor: def __init__(self): self.client = docker.from_env() self.image_name = "python:3.9-slim" # 使用官方轻量级Python镜像 # 确保镜像存在 try: self.client.images.get(self.image_name) except docker.errors.ImageNotFound: print(f"拉取镜像 {self.image_name}...") self.client.images.pull(self.image_name) def execute(self, code: str, timeout: int = 10) -> dict: """ 在Docker容器中执行Python代码。 返回包含输出、错误和执行状态的字典。 """ # 使用临时目录挂载代码文件(更安全可控) with tempfile.TemporaryDirectory() as tmpdir: code_path = os.path.join(tmpdir, "script.py") with open(code_path, 'w') as f: f.write(code) # 运行容器,将临时目录挂载到容器内 container = self.client.containers.run( self.image_name, command=f"python /mnt/script.py", volumes={tmpdir: {'bind': '/mnt', 'mode': 'ro'}}, # 只读挂载 working_dir='/mnt', detach=True, stdout=True, stderr=True, mem_limit='100m', # 内存限制 pids_limit=50, # 进程数限制 network_mode='none' # 禁用网络,更安全 ) try: # 等待容器执行完成,并获取输出 result = container.wait(timeout=timeout) logs = container.logs(stdout=True, stderr=True).decode('utf-8') container.remove(force=True) # 清理容器 exit_code = result['StatusCode'] if exit_code == 0: return {"status": "success", "output": logs, "error": ""} else: # 通常执行错误也会输出到stderr,但这里通过logs获取 return {"status": "error", "output": "", "error": logs} except subprocess.TimeoutExpired: container.kill() container.remove(force=True) return {"status": "timeout", "output": "", "error": "Execution timed out."}

2. Agent与LLM的集成LangChain将工具、记忆和LLM封装成AgentExecutor。我们需要定义工具,并告诉LLM如何使用它们。

# 示例:使用LangChain和OpenAI API创建代码执行Agent from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_openai import ChatOpenAI from langchain.tools import Tool from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder # 1. 初始化LLM llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0) # temperature设为0使输出更确定 # 2. 将我们的执行器包装成LangChain Tool executor = DockerPythonExecutor() code_tool = Tool( name="python_code_executor", func=executor.execute, description="""A tool to execute Python code in a secure sandbox. Input should be a string containing valid Python code. Returns the output of the execution or an error message.""" ) # 3. 定义Agent提示词 prompt = ChatPromptTemplate.from_messages([ ("system", """You are a helpful AI programming assistant that can write and execute code. When asked to perform a coding task: 1. Think step by step. 2. Write the complete Python code to solve the problem. 3. Use the `python_code_executor` tool to run the code. 4. Analyze the output. If there's an error, fix the code and try again. 5. Finally, explain the code and the result in a clear way. """), MessagesPlaceholder(variable_name="chat_history"), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) # 4. 创建Agent tools = [code_tool] agent = create_openai_tools_agent(llm, tools, prompt) # 5. 创建执行器,并开启verbose模式以便观察Agent思考过程 agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True) # 6. 运行Agent result = agent_executor.invoke({"input": "Write a Python function to calculate the nth Fibonacci number, then compute the 10th number."}) print(result["output"])

4. 完整实战案例:构建一个终端代码秀助手

让我们构建一个本地的命令行程序,它接受用户提出的编程问题,然后由AI Agent完成编码、执行和解释。

4.1 项目结构

ai_code_show/ ├── requirements.txt ├── sandbox/ │ └── docker_executor.py # 封装的Docker代码执行器 ├── agent/ │ ├── __init__.py │ └── code_agent.py # LangChain Agent核心逻辑 ├── config.py # 配置文件(API密钥等) └── main.py # 主程序入口

4.2 编写安全沙箱执行器

我们将完善之前的DockerPythonExecutor,增加更多安全控制和资源限制。

# sandbox/docker_executor.py import docker import tempfile import os import logging from typing import Dict, Optional logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class SecurePythonSandbox: def __init__(self, image: str = "python:3.9-slim", timeout: int = 15): self.client = docker.from_env() self.image = image self.timeout = timeout self._ensure_image() def _ensure_image(self): try: self.client.images.get(self.image) logger.info(f"镜像 {self.image} 已存在。") except docker.errors.ImageNotFound: logger.info(f"拉取镜像 {self.image}...") self.client.images.pull(self.image) def run_code(self, code: str, input_data: Optional[str] = None) -> Dict: """ 执行代码,并可选择传入标准输入。 """ with tempfile.TemporaryDirectory() as tmpdir: # 写入代码文件 code_path = os.path.join(tmpdir, "main.py") with open(code_path, 'w', encoding='utf-8') as f: f.write(code) # 如果需要输入,写入一个输入文件 stdin_path = None if input_data: stdin_path = os.path.join(tmpdir, "input.txt") with open(stdin_path, 'w', encoding='utf-8') as f: f.write(input_data) # 准备Docker运行命令和挂载 cmd = ["python", "/workspace/main.py"] volumes = {tmpdir: {'bind': '/workspace', 'mode': 'ro'}} container = None try: container = self.client.containers.run( image=self.image, command=cmd, volumes=volumes, working_dir='/workspace', detach=True, stdout=True, stderr=True, mem_limit='256m', # 内存限制 cpuset_cpus='0-0', # 限制使用1个CPU核心 pids_limit=100, network_mode='none', # 无网络访问 read_only=True, # 容器根文件系统只读 # 设置用户为非root,增加安全性 user='1000:1000', ) # 等待执行完成 wait_result = container.wait(timeout=self.timeout) exit_code = wait_result['StatusCode'] logs = container.logs(stdout=True, stderr=True).decode('utf-8', errors='ignore') # 区分stdout和stderr(简单处理,实际日志混合了) # 更复杂的处理可以分别捕获,这里为简化返回统一日志 if exit_code == 0: return { "success": True, "exit_code": exit_code, "output": logs, "error": "" } else: return { "success": False, "exit_code": exit_code, "output": "", "error": logs } except docker.errors.ContainerError as e: logger.error(f"容器执行错误: {e}") return {"success": False, "exit_code": -1, "output": "", "error": str(e)} except Exception as e: logger.error(f"未知错误: {e}") return {"success": False, "exit_code": -1, "output": "", "error": str(e)} finally: if container: try: container.remove(force=True) except: pass # 单例实例,避免频繁创建连接 _sandbox_instance = None def get_sandbox(): global _sandbox_instance if _sandbox_instance is None: _sandbox_instance = SecurePythonSandbox() return _sandbox_instance

4.3 构建LangChain Agent

# agent/code_agent.py from langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_openai import ChatOpenAI from langchain.tools import Tool from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.memory import ConversationBufferMemory from sandbox.docker_executor import get_sandbox import os # 从环境变量或配置文件读取API密钥 from config import OPENAI_API_KEY def create_code_execution_tool(): """创建代码执行工具""" sandbox = get_sandbox() def execute_python_code(code: str) -> str: """执行Python代码并返回结果字符串""" result = sandbox.run_code(code) if result["success"]: return f"执行成功:\n{result['output']}" else: return f"执行失败 (退出码 {result['exit_code']}):\n{result['error']}" return Tool( name="execute_python", func=execute_python_code, description="""Use this tool to run Python code and see the output. Input must be a complete, valid Python program as a string. The code will run in a secure sandbox with limited resources. Always use this tool to test your code before finalizing the answer.""" ) def build_code_show_agent(): """构建并返回一个配置好的Agent执行器""" llm = ChatOpenAI( model="gpt-4-turbo-preview", api_key=OPENAI_API_KEY, temperature=0.1, # 较低的温度保证代码生成的稳定性 max_tokens=2000 ) # 工具列表 tools = [create_code_execution_tool()] # 系统提示词 - 这是指导Agent行为的关键 system_prompt = """You are CodeShow AI, an expert programming assistant for live demonstrations. Your goal is to help users by writing, executing, and explaining Python code. **CRITICAL RULES:** 1. ALWAYS write the FULL, RUNNABLE Python code to solve the user's request. 2. ALWAYS use the `execute_python` tool to run your code and verify it works. 3. If the code fails, analyze the error, fix it, and try again. 4. After successful execution, provide: - A concise explanation of the solution. - The key lines of code and their purpose. - The output of the program. 5. Keep your explanations engaging and suitable for a live audience. 6. For complex tasks, break them down step-by-step in your reasoning. Example Interaction: User: "Show me how to read a CSV file and plot a bar chart." You: Thought: I need to write Python code that uses pandas and matplotlib. Action: Use `execute_python` tool with the code. ... (execution happens) ... Observation: The code ran successfully and saved a plot.png file. Final Answer: Here's the code that reads 'data.csv' and creates a bar chart... """ prompt = ChatPromptTemplate.from_messages([ ("system", system_prompt), MessagesPlaceholder(variable_name="chat_history"), ("human", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad"), ]) # 记忆功能,让Agent能记住对话上下文 memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) # 创建Agent agent = create_openai_tools_agent(llm, tools, prompt) agent_executor = AgentExecutor( agent=agent, tools=tools, memory=memory, verbose=True, # 设为True可以看到Agent的“思考过程”,非常适合演示 handle_parsing_errors=True, max_iterations=5, # 防止Agent陷入死循环 early_stopping_method="generate" ) return agent_executor

4.4 主程序与交互

# main.py from agent.code_agent import build_code_show_agent import sys def main(): print("🚀 AI代码秀助手已启动!") print("输入你的编程问题(例如:'用Python实现二分查找'),输入 'quit' 退出。") print("-" * 50) agent = build_code_show_agent() while True: try: user_input = input("\n>>> 问题: ").strip() if user_input.lower() in ['quit', 'exit', 'q']: print("再见!") break if not user_input: continue print("\n🤖 AI正在思考并编码...\n") # 调用Agent result = agent.invoke({"input": user_input}) print("\n" + "="*50) print("📝 最终答案:") print(result["output"]) print("="*50) except KeyboardInterrupt: print("\n\n程序被中断。") break except Exception as e: print(f"\n❌ 发生错误: {e}") # 可以选择继续或退出 # break if __name__ == "__main__": main()

4.5 运行与演示

  1. 安装依赖
    pip install -r requirements.txt
  2. 配置API密钥:在config.py中设置你的OPENAI_API_KEY,或通过环境变量OPENAI_API_KEY设置。
  3. 确保Docker服务运行:在终端中运行docker --version确认Docker已安装并运行。
  4. 启动程序
    python main.py
  5. 进行交互
    🚀 AI代码秀助手已启动! 输入你的编程问题(例如:'用Python实现二分查找'),输入 'quit' 退出。 -------------------------------------------------- >>> 问题: 写一个函数,判断一个字符串是不是回文,并测试几个例子。 🤖 AI正在思考并编码... > 进入新的Agent执行链... 思考:用户想要一个回文判断函数和测试。我需要写一个Python函数,它接受一个字符串,移除空格并转为小写后检查是否与反转字符串相同。然后写几个测试用例。 行动:使用`execute_python`工具,输入代码。 观察:执行成功:测试通过!输出显示'racecar'是回文,'hello'不是。 思考:代码运行成功,测试结果符合预期。现在我需要解释代码。 最终答案:这是一个判断字符串是否为回文的Python函数。它首先清理字符串(移除非字母数字字符并转为小写),然后与自身的反转进行比较。以下是代码和测试输出... ================================================== 📝 最终答案: 这是一个判断字符串是否为回文的Python函数... ==================================================

5. 进阶:集成Amazon Bedrock与多模态展示

对于企业级或峰会演示,你可能希望使用更稳定、支持多模型的Amazon Bedrock,并增加可视化输出。

5.1 切换到Amazon Bedrock

首先,安装boto3并配置AWS凭证。

# 修改 agent/code_agent.py 中的LLM初始化部分 from langchain_aws import ChatBedrock # 需要安装 langchain-aws def build_bedrock_agent(): import boto3 from langchain_aws import ChatBedrock # 初始化Bedrock客户端 bedrock_runtime = boto3.client( service_name='bedrock-runtime', region_name='us-east-1' # 替换为你的区域 ) llm = ChatBedrock( client=bedrock_runtime, model_id="anthropic.claude-3-sonnet-20240229-v1:0", # 使用Claude 3 Sonnet model_kwargs={ "max_tokens": 2000, "temperature": 0.1, "top_p": 0.9, } ) # ... 后续创建Agent的代码与之前相同 ...

使用Bedrock的优势在于可以轻松切换模型(如Claude、Llama 2),并且享有AWS的安全、监控和成本管理特性。

5.2 增强演示效果:生成图表与Web界面

让Agent不仅能输出文本,还能生成图片或启动一个简单的Web服务器来展示结果。

1. 增强工具集:生成图表修改沙箱工具,使其能返回图像文件。我们可以在沙箱中安装matplotlib,让代码生成图表并保存,然后由Agent读取并返回图像路径或Base64编码。

2. 使用Streamlit构建Web演示界面这是一个快速将你的Agent变成Web应用的方法。

# app.py import streamlit as st from agent.code_agent import build_code_show_agent st.set_page_config(page_title="AI Live Code Show", page_icon="🚀") st.title("🚀 AI Live Code Show") st.caption("输入自然语言描述,观看AI实时编写、执行并解释代码。") agent = build_code_show_agent() if "messages" not in st.session_state: st.session_state.messages = [] for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if prompt := st.chat_input("你的编程挑战是什么?"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) with st.chat_message("assistant"): message_placeholder = st.empty() full_response = "" # 这里可以优化为流式输出,简化起见先一次性输出 result = agent.invoke({"input": prompt}) response = result["output"] message_placeholder.markdown(response) st.session_state.messages.append({"role": "assistant", "content": response})

运行streamlit run app.py,你就拥有了一个具有聊天界面的代码秀Web应用。

6. 常见问题与排查思路

在开发和运行此类AI Agent系统时,你会遇到一些典型问题。

问题现象可能原因排查与解决思路
Agent陷入循环,不断重试1. 提示词指令不清晰。
2. 工具执行结果解析失败。
3.max_iterations设置过高。
1. 检查系统提示词,确保有明确的停止条件(如“Final Answer”)。
2. 确保工具返回的字符串格式稳定。
3. 降低max_iterations(如设为5),并启用early_stopping
Docker容器执行超时或被杀死1. 代码包含死循环。
2. 资源(内存/CPU)不足。
3. 网络拉取镜像慢。
1. 在沙箱代码中设置更严格的超时和资源限制(如PIDs limit)。
2. 确保基础镜像已提前拉取到本地。
3. 考虑使用更轻量的镜像(如python:3.9-alpine)。
LLM不调用工具,直接输出代码1. 工具描述(description)不清晰。
2. 提示词未强调必须使用工具。
3. 模型温度(temperature)过高。
1. 优化工具描述,明确其用途和输入格式。
2. 在系统提示词中用大写、加粗强调“ALWAYS use the tool”。
3. 将temperature调低至0.1-0.3。
生成的代码有语法错误或逻辑错误1. 模型本身局限性。
2. 任务过于复杂。
1. 使用更强的模型(如GPT-4、Claude 3 Opus)。
2. 要求Agent“逐步思考”(Chain-of-Thought),并在提示词中提供优秀代码示例。
3. 实现一个“代码审查”步骤,让Agent在执行前先自我检查。
API调用费用高昂或速率受限1. 迭代次数过多。
2. 未做缓存。
1. 优化提示词和工具,减少不必要的LLM调用轮次。
2. 对相同的用户查询实现结果缓存。
3. 使用Bedrock等提供更细粒度成本控制的服务。
安全问题:用户输入恶意代码1. 沙箱隔离不彻底。
2. 资源限制不足。
1. Docker容器使用network_mode='none',read_only=True,user非root。
2. 严格限制内存、CPU、进程数、运行时间。
3.绝对禁止执行涉及文件删除、系统调用、网络访问的高风险代码。可预先对用户输入进行关键词过滤。

7. 最佳实践与工程建议

要将“AI代码秀”从原型推向峰会现场或生产环境,需要考虑以下工程化实践:

1. 安全第一

  • 深度防御:Docker沙箱是基础,但还可考虑gVisor、Firecracker等更强隔离的运行时。
  • 输入净化:对用户输入进行预处理,过滤明显危险的系统调用、无限循环模式等。
  • 资源配额:为每个会话设置严格的超时、内存和CPU限制,并实现全局熔断机制。
  • 审计日志:记录所有生成的代码、执行结果和用户交互,便于事后审查和问题排查。

2. 提升演示可靠性

  • 预热与缓存:针对常见演示场景(排序、可视化、API调用),可预先让Agent生成并验证代码,将结果缓存。现场演示时直接调用缓存,避免网络或模型波动。
  • 备用方案:准备几个手动验证过的、效果稳定的代码脚本作为后备,以防AI现场“发挥失常”。
  • 渐进式揭示:不要让AI一次性输出所有代码。可以设计成让AI一步步解释、编写、运行,增加戏剧性和观众理解度。

3. 优化性能与成本

  • 模型选择:对于代码生成,Claude 3 Sonnet/Haiku、GPT-4 Turbo是不错的选择。简单任务可尝试更经济的模型。
  • 提示词工程:精心设计的提示词能大幅减少无效轮次。使用少样本学习(Few-shot),在提示词中提供几个完美的输入输出示例。
  • 会话管理:长时间演示时,定期清理记忆上下文,防止token数无限增长。

4. 设计交互体验

  • 为现场优化:输出格式要醒目。考虑使用语法高亮显示代码,用不同颜色区分成功输出和错误信息。
  • 处理不确定性:设计友好的中间状态提示,如“我正在思考...”、“正在编写代码...”、“运行测试中...”,让观众感知进度。
  • 设置边界:明确告知观众和AI互动的范围(如“仅限Python基础算法和数据处理”),避免提出超出系统能力的问题导致冷场。

构建一个用于现场演示的AI代码秀系统,是AI Agent技术一个非常直观和有趣的应用。它不仅仅是一个工具,更是一个融合了软件工程、提示词工程、安全运维和交互设计的综合项目。从简单的命令行工具开始,逐步加入安全沙箱、Web界面、多模型支持,最终你可以打造出一个足够稳健、能够应对技术峰会复杂环境的智能演示伙伴。