第九章:AutoGen - 基于对话的多 Agent 协作与安全代码执行

章节引导:单 Agent 的能力终究有限。许多复杂任务,如软件开发、科学研究、数据分析报告撰写,往往需要不同角色、不同能力的“专家”协同完成。本章我们将正式进入激动人心的多 Agent 系统的世界,首先学习由微软研究院推出的 AutoGen 框架。AutoGen 以其灵活的、基于对话的 Agent 协作机制和强大的代码执行能力而备受关注。与 LangGraph 精确控制单 Agent 流程不同,AutoGen 更侧重于模拟多个自主 Agent 如何通过自然语言对话进行交流、分工与协作。我们将深入其核心架构,重点掌握如何安全地让 Agent 执行代码(这是 AutoGen 的一大亮点),如何定制 Agent 行为与对话模式,并通过构建一个代码审查与自动修复系统的实例,亲身体验多 Agent 协作完成复杂任务的威力。

重要提示:相关库与版本
AutoGen 是一个独立的库 (pip install pyautogen)。本章示例基于 AutoGen 的较新版本,请确保你的环境已安装。同时,与 LLM 的交互通常需要安装相应的 SDK(如 openai)并配置 API Key。

9.1 AutoGen 架构:对话驱动的协作

AutoGen 的核心设计理念是对话驱动。Agent 之间的协作主要通过相互发送和接收消息来实现。理解其架构的关键在于掌握核心 Agent 类型和它们之间的通信及协作机制。
在这里插入图片描述

核心 Agent 类型详解

AutoGen 提供了一些内置的 Agent 类,它们都继承自 ConversableAgent 这个定义了基本对话能力的基类:

  • ConversableAgent: 所有能参与对话的 Agent 的基类。定义了核心交互方法,如 send(), receive(), generate_reply()。可继承以创建自定义 Agent。
  • AssistantAgent: 最常用的类型之一,代表一个标准的、基于 LLM 的对话 Agent。接收消息历史,调用配置好的 LLM 生成回复。通过设置 system_message 来赋予其不同角色和能力。
  • UserProxyAgent: (极其关键) 代表用户或用户的代理人。核心特点:
    1. 能发起对话: 通常是任务的发起者。
    2. 能请求人类输入: 可配置在需要时暂停并请求用户指令 (human_input_mode)。
    3. 能执行代码/函数: 其最强大的能力,可以执行 Python 代码块(在沙箱中)或调用预注册的函数。
      在这里插入图片描述

通信机制

Agent 通过发送和接收消息进行通信(通常是包含 contentrole 的字典)。

  • send(message, recipient): 发送消息。
  • receive(message, sender): 接收消息。
  • generate_reply(messages, sender): 生成回复的核心逻辑。

多 Agent 交互核心

在这里插入图片描述

AutoGen 支持多种交互模式:

  1. 两 Agent 对话: UserProxyAgentAssistantAgent 轮流对话,直至满足终止条件。
    # user_proxy.initiate_chat(assistant, message="Initial task")
    
  2. GroupChatGroupChatManager: (核心机制) 实现多个 Agent (>=3) 协作的关键。
    • GroupChat: 定义一个包含多个 Agent 的“聊天室”,维护共享消息历史。
    • GroupChatManager: 特殊的 ConversableAgent,负责管理 GroupChat 中的对话流程,根据 speaker_selection_method 选择下一个发言者。
      • "round_robin": 轮流。
      • "auto": (默认) LLM 决定谁最适合发言(需要 Manager 配置 LLM)。
      • "manual": 人类用户选择。
      • 自定义函数。
    • 通常由 UserProxyAgentGroupChatManager 发起群聊。
    # user_proxy = UserProxyAgent(...)
    # agent1 = AssistantAgent(name="Coder", ...)
    # agent2 = AssistantAgent(name="Tester", ...)
    # groupchat = GroupChat(agents=[user_proxy, agent1, agent2], ...)
    # manager = GroupChatManager(groupchat=groupchat, llm_config=...)
    # user_proxy.initiate_chat(manager, message="Task for the group")
    

9.2 安全的代码执行:UserProxyAgent 与沙箱

AutoGen 的一大特色是 UserProxyAgent 能够执行代码,这赋予了 Agent 强大的自动化能力。

为何需要 Agent 执行代码? 自动化任务、数据分析、工具使用、软件开发等。

UserProxyAgent 的代码执行能力配置:

通过 code_execution_config 参数启用和控制:

from autogen import UserProxyAgent

user_proxy_with_code = UserProxyAgent(
   name="Executor",
   human_input_mode="NEVER",
   code_execution_config={
       "work_dir": "coding_sandbox", # 执行目录
       "use_docker": True,        # <---- 强烈推荐使用 Docker!
       # "use_docker": "python:3.11-slim", # 可指定镜像
       # "timeout": 120,           # 超时时间 (秒)
   },
   # ... 其他参数 ...
)

核心风险:安全!

警告: 直接在本地执行由 LLM 生成或来自不可信 Agent 的代码是极其危险的行为! 潜在风险包括文件删除、数据泄露、恶意软件安装等。绝不能直接信任!

深度实践:代码执行沙箱

必须使用沙箱 (Sandbox) 环境隔离代码执行:
在这里插入图片描述

  1. Docker 沙箱 (强烈推荐):
    • 配置: code_execution_config={"use_docker": True, ...}
    • 原理: AutoGen 在隔离的 Docker 容器内执行代码,保护宿主系统。
    • 依赖: 可通过自定义镜像或 work_dir 下的 requirements.txt 管理。
    • 要求: 本地需安装并运行 Docker。
  2. E2B (e2b.dev) 云沙箱 (推荐):
    • 配置: 需安装 e2b 包并配置 API Key(详见 AutoGen/E2B 文档)。
    • 原理: 在安全的云端沙箱执行代码。
    • 优点: 无需本地 Docker,方便快捷。
    • 缺点: 依赖第三方服务,可能有费用。
  3. 本地执行 (use_docker=False, 不推荐):
    • 风险: 代码直接在本地执行,work_dir 隔离有限,极不安全请勿在生产或处理不可信代码时使用。

安全最佳实践:

  • 强制使用沙箱: 始终优先 Docker 或 E2B。
  • 代码审查/限制: 对关键代码进行审查,或限制可用库/函数。
  • 管理沙箱依赖: 确保沙箱环境包含所需库。
  • 资源限制: 配置 Docker/E2B 限制 CPU、内存、网络。
  • 用户确认: 对高风险操作启用 human_input_mode 进行确认。

安全永远是第一位的!

9.3 定制 Agent 与对话模式

可以通过多种方式定制 AutoGen Agent 的行为和对话流:

1. 修改 Prompt/System Message:

最简单的方式,通过 system_message 赋予 AssistantAgent 不同的角色、指令和个性。

coder = AssistantAgent(
    name="PythonCoder",
    system_message="You are a senior Python programmer...",
    llm_config=llm_config
)
reviewer = AssistantAgent(
    name="CodeReviewer",
    system_message="You are a meticulous code reviewer...",
    llm_config=llm_config
)

2. 继承与重写方法:

通过继承 ConversableAgent 并重写 generate_reply 等方法,实现深度定制逻辑(如加入特定知识、记忆、状态管理)。

3. 注册自定义函数 (UserProxyAgent):

UserProxyAgent 调用预定义的、安全的 Python 函数,而不是执行任意代码。

import autogen
from autogen import UserProxyAgent, AssistantAgent
from dotenv import load_dotenv
import os

load_dotenv()

# 配置 LLM (假设已完成)
config_list = autogen.config_list_from_json(...)
llm_config = {"config_list": config_list, ...}

# 定义安全函数
def get_stock_price(symbol: str) -> float:
    """Gets the (simulated) stock price for a given symbol."""
    print(f"--- Called function get_stock_price for {symbol} ---")
    if isinstance(symbol, str) and symbol.upper() == "MSFT": return 300.0
    if isinstance(symbol, str) and symbol.upper() == "GOOG": return 150.0
    return 0.0

# 创建 UserProxyAgent 并注册函数
user_proxy_func = UserProxyAgent(
    name="FunctionExecutor",
    human_input_mode="NEVER",
    # code_execution_config=False, # 显式禁用代码执行
)
user_proxy_func.register_function(
    function_map={
        "get_stock_price_tool": get_stock_price # 映射工具名到函数
    }
)

# 创建 Assistant Agent 并告知它可以使用的工具
assistant_func_caller = AssistantAgent(
    name="AssistantFuncCaller",
    system_message="You can use tools. Use the get_stock_price_tool for stock prices.",
    llm_config={
        "config_list": config_list,
        "tools": [ # **关键:向 LLM 描述可用工具**
            {
                "type": "function",
                "function": {
                    "name": "get_stock_price_tool", # 必须与 register_function 中的键匹配
                    "description": "Gets the current stock price for a given symbol.",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "symbol": {"type": "string", "description": "Stock ticker (e.g., MSFT)"}
                        },
                        "required": ["symbol"],
                    },
                },
            }
        ],
    }
)

# 发起对话 (示例)
# user_proxy_func.initiate_chat(
#     assistant_func_caller,
#     message="What's the stock price for MSFT?"
# )

触发机制说明: AssistantAgent 要调用注册的函数,其 llm_config 必须包含 tools 描述。当 LLM 决定使用该工具时,它会生成特定的工具调用请求。UserProxyAgent 收到此请求后,会自动查找 function_map 并执行对应的 Python 函数,将结果返回。

设计复杂对话模式:

  • 利用 GroupChatManagerspeaker_selection_method 控制发言顺序。
  • 通过精心设计的 Agent system_message 或内部逻辑引导对话流向。
  • 探索 AutoGen 的高级功能或社区扩展以实现更复杂的交互模式。

9.4 动手实验:构建代码审查与自动修复的多 Agent 系统

目标:实践定义不同角色的 Agent,利用 AutoGen 的对话机制进行协作,并安全地执行代码(如运行测试、应用修复)。
在这里插入图片描述

场景: 用户提出函数需求 -> Coder 编写 -> Reviewer 审查 -> (循环修改) -> UserProxy 执行测试 -> 完成。

角色定义:

  • user_proxy (UserProxyAgent): 发起任务,批准,执行测试代码 (沙箱)
  • coder (AssistantAgent): 编写/修改代码。
  • reviewer (AssistantAgent): 审查代码。

协作流程设计 (简化版):

  1. UserProxy -> Coder: “编写函数 X”
  2. Coder -> Reviewer: "python ... "
  3. Reviewer -> Coder: “修改意见…” 或 “Approved”
  4. (循环 2-3)
  5. Coder -> UserProxy: “python ... (Approved)”
  6. UserProxy: (提取代码块) -> 执行测试 -> GroupChat: “测试结果…”

代码实现 (关键部分):

import os
import autogen
from autogen import AssistantAgent, UserProxyAgent, GroupChat, GroupChatManager
from dotenv import load_dotenv

load_dotenv()

# 配置 LLM (同 9.3 示例)
config_list = autogen.config_list_from_json("OAI_CONFIG_LIST", filter_dict={"model": ["gpt-4o"]})
llm_config = {"config_list": config_list, "cache_seed": 42}

# --- Agent 定义 ---
user_proxy = UserProxyAgent(
    name="UserProxy",
    system_message="Represents the user. Initiate the task. Execute Python code blocks for testing when received after approval. Report test results.",
    human_input_mode="TERMINATE", # Allow human intervention on termination/error
    max_consecutive_auto_reply=8, # Limit consecutive replies for safety
    # Use 'ALWAYS' to require human approval before code execution for extra safety
    # human_input_mode="ALWAYS",
    code_execution_config={
        "work_dir": "code_review_project",
        "use_docker": True, # CRITICAL: Enforce Docker sandbox
    },
    # Automatically execute code blocks received
    # This relies on the default behavior. More robust: check sender/context.
)

coder = AssistantAgent(
    name="Coder",
    system_message='''Python programmer. Write Python code based on requests.
    Receive feedback from CodeReviewer and revise.
    Enclose final code in ```python ... ```.
    Reply TERMINATE only when code is approved and you are done.''',
    llm_config=llm_config,
)

reviewer = AssistantAgent(
    name="CodeReviewer",
    system_message='''Code reviewer. Review Python code from Coder for correctness, clarity, bugs.
    Provide specific feedback or reply "Approved" if it looks good.
    Do not write code yourself.''',
    llm_config=llm_config,
)

# --- GroupChat 设置 ---
agents = [user_proxy, coder, reviewer]
groupchat = GroupChat(
    agents=agents,
    messages=[],
    max_round=12 # Limit conversation length
)

# GroupChatManager (使用 LLM 自动选择)
manager_llm_config = {"config_list": config_list, "cache_seed": 43}
manager = GroupChatManager(
    groupchat=groupchat,
    llm_config=manager_llm_config,
    # Guiding the manager
    system_message="Coordinate coding and reviewing. Ensure feedback is addressed. The UserProxy executes approved code for testing."
)

# --- 发起聊天 ---
initial_task = """
1. Coder: Write a Python function `calculate_rectangle_area(length: float, width: float) -> float` that calculates the area of a rectangle. Include a docstring.
2. Reviewer: Review the code.
3. UserProxy: After approval, test the function with length=5, width=10 and report the execution result.
"""

print("\n--- Starting Code Review Group Chat ---")
try:
    user_proxy.initiate_chat(
        manager,
        message=initial_task,
    )
except Exception as e:
    print(f"An error occurred during the chat: {e}")

print("\n--- Code Review Group Chat Finished ---")

逐步代码讲解与分析:

  • 定义了具有明确角色的三个 Agent。
  • UserProxyAgent 配置了 Docker 沙箱进行代码执行。
  • 设置了 GroupChatGroupChatManager
  • UserProxy 发起了包含编码和测试指令的任务。
  • 观察对话流: Agent 间通过消息传递代码和评审意见。
  • 代码执行触发 (说明):
    • 当对话流进行到 UserProxy 接收到经 Reviewer “Approved” 的代码块时,由于 code_execution_config 已启用,UserProxyAgent自动查找并提取最近消息中的 ` ```python … ````代码块。
    • 它会将代码写入沙箱(Docker 容器内)的文件中。
    • 然后,它在沙箱内执行该文件。
    • 捕获执行的标准输出/错误
    • 将执行结果(成功输出或错误信息)作为新消息发送回群聊。
    • (注意:更复杂的测试场景可能需要更精细的逻辑来生成和执行测试用例。)

9.5 AutoGen 落地应用与挑战

典型应用场景: 自动化编码、数据分析、研究助理、多智能体仿真、创意写作等。

面临的挑战:

  • 对话可控性差: 可能陷入无效循环、偏离目标。
  • 结果稳定性: 多次运行结果可能不同。
  • 成本控制: 多轮对话可能导致大量 LLM 调用。
  • 复杂状态管理: 跟踪共享状态困难。
  • 调试难度: 追踪多 Agent 对话流复杂。

9.6 章节总结与框架对比

本章我们深入了 AutoGen 框架,掌握了其多 Agent 系统的核心方法。

  • 核心优势总结: AutoGen 的核心竞争力在于其灵活的、基于对话的协作机制,以及内置的、强调安全的代码执行能力。

  • 关键技术回顾: 学习了核心 Agent 类型、GroupChat/Manager 机制、安全代码执行配置与实践。

  • 对比:

    • LangGraph (Ch8) 对比:
      • LangGraph: 强于单 Agent 复杂流程的精确控制、显式状态管理。
      • AutoGen: 强于多 Agent 间基于对话的灵活协作和代码执行。
    • 与 CrewAI (Ch10 预告) 对比:
      • AutoGen: 对话更自由、动态
      • CrewAI: 提供更结构化、面向流程的协作框架(角色、任务、流程)。
  • 引出思考: AutoGen 的自由对话带来了灵活性,但也牺牲了部分可控性。对于需要明确角色分工和结构化流程的多 Agent 任务,下一章的 CrewAI 提供了另一种解决方案。


内容同步在我的公众号:智语Bot

autogen框架旨在简化大规模语言模型(LLM)交互的工作流程,通过Python库pyautogen实现高效的集成和应用开发。为了正确配置和使用autogen框架,开发者首先需要准备环境并安装必要的Python库。可以通过执行`pip install pyautogen`命令来安装pyautogen库,确保安装的是autogen框架相关的库,而不是其他项目。 参考资源链接:[autogen:大模型应用开发的创新框架](https://wenku.csdn.net/doc/5ve5e11hk3) 接下来,需要准备相应的LLM模型。如果选择使用OpenAI的Qwen系列模型,比如Qwen-72b,可以从开放源代码库下载并部署。对于不具备部署条件的开发者,可以利用阿里云提供的千问API接口进行接入,虽然这需要支付一定的费用,但通常会有一个免费额度。 在配置LLM时,开发者需要设置`llm_config`字典,包含模型名称(如`qwen-72b`)、API基础URL和访问密钥等。如果需要直接LLM交互而不使用缓存,应将`cache_seed`设置为`None`。 以下是一个使用autogen框架的示例代码,展示了如何配置环境和API接口: ```python import pyautogen as ag # 配置LLM参数 llm_config = { 'model_name': 'qwen-72b', # 模型名称 'api_base': '***', # API基础URL 'api_key': 'your_api_key', # 访问密钥 'cache_seed': None # 不使用缓存 } # 初始化agent agent = ag.Agent(config=llm_config) # 发起函数调用 response = agent.function_call( 参考资源链接:[autogen:大模型应用开发的创新框架](https://wenku.csdn.net/doc/5ve5e11hk3)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

(initial)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值