news 2026/9/9 21:11:47

如何用 DockerCommandLineCodeExecutor 让 AutoGen 智能体在 Docker 容器中执行代码?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用 DockerCommandLineCodeExecutor 让 AutoGen 智能体在 Docker 容器中执行代码?

如何用 DockerCommandLineCodeExecutor 让 AutoGen 智能体在 Docker 容器中执行代码?

【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen

在 AutoGen(autogen)里开发智能体应用时,一个常见需求是让 LLM 生成代码并实际执行:用LocalCommandLineCodeExecutor直接在宿主机上跑 LLM 生成的代码风险较高,官方文档明确不推荐。推荐做法是使用DockerCommandLineCodeExecutor——它会创建一个 Docker 容器,把所有命令都放进这个容器里执行,宿主机环境不受影响。

本文基于仓库中两篇官方文档 Command Line Code Executors 和 Code Execution,走一遍完整路径:安装依赖、单独用执行器在容器里跑一段代码、再把「写代码的 Assistant 智能体 + 执行代码的 Executor 智能体」接入 AutoGen 运行时。适用环境:Python 3.10 或更高版本,宿主机已安装并正在运行 Docker。

准备工作:安装包并确认 Docker 可用

建议先建一个虚拟环境,把 AutoGen 的依赖与系统隔离:

python3 -m venv .venv source .venv/bin/activate

(Windows 下激活命令是.venv\Scripts\activate.bat。)

然后按 安装文档 安装核心包与扩展:

pip install "autogen-core" pip install "autogen-ext[docker]"
  • autogen-core提供智能体运行时和CodeBlock等基础类型,要求 Python 3.10 或更高。
  • autogen-extdockerextra 是DockerCommandLineCodeExecutor的前置条件,见 扩展安装文档。

如果要用 OpenAI 模型客户端驱动智能体,还需要:

pip install "autogen-ext[openai]"

最后确认 Docker 已安装并且守护进程正在运行。DockerCommandLineCodeExecutor通过dockerPython 库连接本地 Docker;连不上时源码会抛出Failed to connect to Docker. Please ensure Docker is installed and running.(见 执行器源码),所以 Docker 没启动是第一个要排除的问题。

单独让执行器在容器里跑代码

DockerCommandLineCodeExecutor的工作方式:把每个代码块保存为work_dir下的文件,再在容器内执行该文件,也就是说每个代码块都在一个新进程中执行。它启动时从镜像创建一个容器,默认镜像是python:3-slim,可以通过构造函数的image参数换成自定义镜像;镜像本地不存在时会自动尝试拉取。文档指出,镜像与执行器兼容的唯一要求是安装了shpython,因此把系统依赖预装进自定义镜像是保证依赖可用的直接办法。

最小示例(与文档示例一致):

from pathlib import Path from autogen_core import CancellationToken from autogen_core.code_executor import CodeBlock from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor work_dir = Path("coding") work_dir.mkdir(exist_ok=True) async with DockerCommandLineCodeExecutor(work_dir=work_dir) as executor: # type: ignore print( await executor.execute_code_blocks( code_blocks=[ CodeBlock(language="python", code="print('Hello, World!')"), ], cancellation_token=CancellationToken(), ) )

文档给出的示例输出为:

CommandLineCodeResult(exit_code=0, output='Hello, World!\n', code_file='coding/tmp_code_07da107bb575cc4e02b0e1d6d99cc204.python')

判断执行是否成功看CommandLineCodeResultexit_code是否为 0,以及output里是否出现代码应打印的内容。code_file指向宿主机work_dir中保存的代码文件;在容器内部,work_dir被挂载为工作目录/workspace(后文示例的 traceback 路径/workspace/tmp_code_...可以佐证这一点)。

几个影响容器行为的参数:

  • 默认用上下文管理器(async with)结束时,或程序退出时通过atexit钩子停止容器。如果想在 AutoGen 用完容器后保留容器以便检查内部状态,创建执行器时把auto_remove设为Falsestop_container设为False可以进一步避免执行结束时停止容器。
  • timeout(默认 60 秒,对应单次执行超时)和支持的语言列表(python,以及bash/shell/sh/pwsh/powershell/ps1)见 执行器源码的类文档。

接入 AutoGen 智能体:Assistant 写代码,Executor 执行

Code Execution 一节的示例实现两个轻量自定义智能体:Assistant负责生成代码,Executor负责从回复里抽出 markdown 代码块并交给执行器,用「绘制 NVIDIA 与 Tesla 2024 年至今累计收益曲线」作为任务。先定义消息类型与两个智能体(与文档代码一致):

import re from dataclasses import dataclass from typing import List from autogen_core import DefaultTopicId, MessageContext, RoutedAgent, default_subscription, message_handler from autogen_core.code_executor import CodeBlock, CodeExecutor from autogen_core.models import ( AssistantMessage, ChatCompletionClient, LLMMessage, SystemMessage, UserMessage, ) @dataclass class Message: content: str @default_subscription class Assistant(RoutedAgent): def __init__(self, model_client: ChatCompletionClient) -> None: super().__init__("An assistant agent.") self._model_client = model_client self._chat_history: List[LLMMessage] = [ SystemMessage( content="""Write Python script in markdown block, and it will be executed. Always save figures to file in the current directory. Do not use plt.show(). All code required to complete this task must be contained within a single response.""", ) ] @message_handler async def handle_message(self, message: Message, ctx: MessageContext) -> None: self._chat_history.append(UserMessage(content=message.content, source="user")) result = await self._model_client.create(self._chat_history) print(f"\n{'-'*80}\nAssistant:\n{result.content}") self._chat_history.append(AssistantMessage(content=result.content, source="assistant")) # type: ignore await self.publish_message(Message(content=result.content), DefaultTopicId()) # type: ignore def extract_markdown_code_blocks(markdown_text: str) -> List[CodeBlock]: pattern = re.compile(r"```\s*([\w\+\-]+)?\n([\s\S]*?)```") matches = pattern.findall(markdown_text) code_blocks: List[CodeBlock] = [] for match in matches: language = match[0].strip() if match[0] else "" code_content = match[1] code_blocks.append(CodeBlock(code=code_content, language=language)) return code_blocks @default_subscription class Executor(RoutedAgent): def __init__(self, code_executor: CodeExecutor) -> None: super().__init__("An executor agent.") self._code_executor = code_executor @message_handler async def handle_message(self, message: Message, ctx: MessageContext) -> None: code_blocks = extract_markdown_code_blocks(message.content) if code_blocks: result = await self._code_executor.execute_code_blocks( code_blocks, cancellation_token=ctx.cancellation_token ) print(f"\n{'-'*80}\nExecutor:\n{result.output}") await self.publish_message(Message(content=result.output), DefaultTopicId())

再注册智能体、启动运行时并发起任务:

import tempfile from autogen_core import SingleThreadedAgentRuntime from autogen_ext.code_executors.docker import DockerCommandLineCodeExecutor from autogen_ext.models.openai import OpenAIChatCompletionClient work_dir = tempfile.mkdtemp() # 创建本地内嵌运行时。 runtime = SingleThreadedAgentRuntime() async with DockerCommandLineCodeExecutor(work_dir=work_dir) as executor: # type: ignore[syntax] model_client = OpenAIChatCompletionClient( model="gpt-4o", # 文档示例中该参数被注释为 api_key="YOUR_API_KEY", # 实际运行需要填入你自己的 OpenAI API key。 ) await Assistant.register( runtime, "assistant", lambda: Assistant(model_client=model_client), ) await Executor.register(runtime, "executor", lambda: Executor(executor)) # 启动运行时并向 assistant 发布一条消息。 runtime.start() await runtime.publish_message( Message("Create a plot of NVIDA vs TSLA stock returns YTD from 2024-01-01."), DefaultTopicId() ) # 等待运行时空闲后停止。 await runtime.stop_when_idle() await model_client.close()

注意extract_markdown_code_blocks里的正则:文档原代码为r"```(?:\s*([\w\+\-]+))?\n([\s\S]*?)```",上面按原义保留了非捕获分组写法(若直接复制文档原文,请使用文档中的r"```\s*([\w\+\-]+)?\n([\s\S]*?)```"变体即可,两者匹配逻辑相同)。

这套流程能跑通的关键在Assistant的系统提示:要求把 Python 脚本写在 markdown 代码块里、图形必须保存为当前目录的文件、不使用plt.show()Executor收到消息后只抽取其中的代码块执行,把执行输出作为新的Message发回默认主题,于是Assistant可以看到执行结果并决定是否继续修正——消息投递由SingleThreadedAgentRuntime负责,智能体只负责自身逻辑。

验证执行结果与处理缺依赖

文档示例中这段程序的实际输出展示了完整的「失败—修复—成功」过程(以下为文档示例,非固定预期):

  1. Assistant第一版脚本用到pandasmatplotlibyfinance
  2. Executor在容器内执行,因为python:3-slim镜像里没有这些库,输出ModuleNotFoundError: No module named 'pandas'
  3. Assistant回复了一个 bash 代码块pip install pandas matplotlib yfinance
  4. Executor在同一个容器里执行该命令,安装完成后重新执行绘图脚本,Assistant确认曲线图已保存。

成功时绘图文件落在work_dir下(示例中为nvidia_vs_tesla_ytd_returns.png),文档用下面的方式查看产物:

from IPython.display import Image Image(filename=f"{work_dir}/nvidia_vs_tesla_ytd_returns.png")

所以核对结果有两层:执行层看CommandLineCodeResult.exit_code == 0与输出内容;任务层看work_dir里是否生成了系统提示要求的产物文件。

排查与限制

  • 缺模块不是宿主机问题:依赖装在容器里。文档示例的做法是让智能体输出 bash 代码块在容器内pip install;如果想一步到位,用image参数换成预装好依赖的自定义镜像即可(镜像里只要有shpython即可与执行器兼容)。
  • Docker 没运行:执行器连接失败时会提示Failed to connect to Docker. Please ensure Docker is installed and running.,先确认 Docker 守护进程在跑。
  • 不要用本地执行器替代:Command Line Code Executors 文档明确提示,LocalCommandLineCodeExecutor会在本机执行代码,谨慎使用;在 LLM 生成代码的场景下官方示例选择 Docker 执行器正是出于这个考虑。
  • 每个代码块都是新进程:命令行列执行器的语义是「保存代码块到文件、每个代码块在新进程中执行」,不要依赖块之间共享内存状态;状态要落在文件里。

可选分支:应用本身也跑在 Docker 容器里

如果你的 AutoGen 应用要打包进容器,又想让它再创建执行容器,文档推荐「Docker out of Docker」:把宿主机 Docker socket 挂载进应用容器,让它在宿主机上派生「兄弟」容器,而不是在容器里再跑一个 Docker 守护进程。做法是在docker run命令中追加:

-v /var/run/docker.sock:/var/run/docker.sock

同时,若工作目录属于宿主机,用bind_dir参数指定该宿主机目录,它会被绑定到派生出来的执行容器上,供其访问文件;不指定bind_dir时会回退使用work_dir

下一步

示例结尾指向 AutoGen 核心用户指南中 Agent Runtime、消息通信、消息处理与订阅的后续章节,想了解分布式运行时(跨进程、跨机器托管智能体)时可以从那里继续。

【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 21:10:08

论文写作软件怎么选?虎贲等考AI全流程实测与避坑指南

写论文软件哪个好?这个问题我每年都会被问几十次。尤其是最近两年,AI 写作工具扎堆冒出来,打开搜索框一片"实测""爆款""神器",真正能帮你把一篇论文从头到尾写完的却不多。多数工具要么只会生成一段…

作者头像 李华
网站建设 2026/9/9 21:07:22

线性回归全解析:从最小二乘到梯度下降的优化之旅

1. 为什么线性回归是所有机器学习入门的第一道坎很多人第一次接触机器学习,是从"房价预测"或者"成绩预测"这类例子开始的。你有一堆数据:房子面积、卧室数量、地段评分,要预测房价;或者复习时长、历史成绩&am…

作者头像 李华
网站建设 2026/9/9 21:04:51

WonderTrader依赖库配置实战:从vcpkg到CMake的C++编译避坑指南

简介:在 Ubuntu 22.04 环境、gcc 11.4.0 工具链下编译 WonderTrader 的 C 开发者,可借助这份预编译的依赖库集合,跳过 Boost 等第三方依赖的下载、版本匹配与 include 路径配置等繁琐过程。压缩包采用 tgz 格式,共 2000 个文件&am…

作者头像 李华
网站建设 2026/9/9 21:03:08

Android歌词渐变:用LinearGradient实现卡拉OK式进度高亮

简介:一份Android自定义View源码,实现歌词风格的文字颜色渐变效果,面向需要为TextView添加动态渐变文字的移动开发者。项目通过GradientTextView对文本着色,以两种颜色平滑过渡,适合音乐播放器歌词、字幕强调等场景&am…

作者头像 李华