1 快速开始

1.1 框架介绍

01.框架定位
    a.核心理念
        a.功能说明
            AutoGen是微软研究院开发的一个功能强大的开源框架,旨在通过自动化多智能体对话来构建和简化下一代大型语言模型(LLM)应用。其核心理念是将复杂的任务分解,通过让多个具有不同角色、能力和定制化程度的AI智能体进行自动化对话来协同解决。它提供了一个统一且可扩展的抽象层,使得开发者可以轻松地编排、自动化和优化复杂的LLM工作流,从而最大化LLM的性能并弥补其单一模型的短板。
        b.代码示例
            ---
            # AutoGen的核心思想:通过智能体对话解决问题
            import os
            from autogen import AssistantAgent, UserProxyAgent

            # 配置LLM,例如使用OpenAI的GPT-4
            config_list = [{"model": "gpt-4", "api_key": os.environ.get("OPENAI_API_KEY")}]

            # 1. 创建一个AI助手智能体 (AssistantAgent),负责思考和生成代码
            assistant = AssistantAgent(
                name="assistant",
                llm_config={"config_list": config_list}
            )

            # 2. 创建一个用户代理智能体 (UserProxyAgent),负责执行代码和与用户交互
            user_proxy = UserProxyAgent(
                name="user_proxy",
                code_execution_config={"work_dir": "coding"} # 指定代码执行的工作目录
            )

            # 3. 发起一个对话,让两个智能体协作解决一个需要写代码的任务
            user_proxy.initiate_chat(
                assistant,
                message="今天星期几?今年以来,哪只科技大盘股的涨幅最大?涨了多少?"
            )
            ---
    b.技术架构
        a.功能说明
            AutoGen的架构核心是其可对话的智能体(Conversable Agents)。框架提供了一个通用的`ConversableAgent`基类,所有智能体都继承自该类,使其具备收发消息的能力。架构在此基础上派生出两种核心智能体:`AssistantAgent`和`UserProxyAgent`。`AssistantAgent`通常扮演AI助手的角色,负责生成代码和提供解决方案;而`UserProxyAgent`则作为人类的代理,负责执行代码、收集反馈,并可以在需要时征求人类的输入,从而实现人机协同。这种“思考者-执行者”的分离是AutoGen架构的关键所在。
        b.代码示例
            ---
            # 架构概念:AssistantAgent生成代码,UserProxyAgent执行代码

            # AssistantAgent 的典型回复(包含一个Python代码块)
            # """
            # To find the best performing stock, I will write a python script to fetch the stock data and calculate the year-to-date gain.
            # ```python
            # import yfinance as yf
            # from datetime import datetime
            #
            # stocks = [\"AAPL\", \"GOOGL\", \"MSFT\", \"AMZN\", \"NVDA\"]
            # start_date = f\"{datetime.now().year}-01-01\"
            # end_date = datetime.now().strftime(\"%Y-%m-%d\")
            # ... (代码省略)
            # ```
            # """

            # UserProxyAgent 接收到包含代码块的消息后,会自动执行(如果配置允许)
            # 并将代码的执行结果(例如 "NVIDIA has the largest gain of 50% YTD.")
            # 作为下一轮对话的消息,发送回给 AssistantAgent,形成一个闭环。
            ---

02.核心特性
    a.多样化对话模式
        a.功能说明
            AutoGen支持构建各种复杂的对话模式。除了基础的双智能体对话,它还支持多智能体群聊(Group Chat)、层级对话(Hierarchical Chat)以及自定义的对话拓扑。这使得开发者可以根据任务的复杂性,设计出如辩论、代码审查、多轮规划等高级协作流程。

    b.可定制与可对话
        a.功能说明
            框架中的所有智能体都是高度可定制的。开发者可以为其配置不同的LLM、设定独特的系统消息(System Message)来塑造其“个性”和专长、为其配备不同的工具集。同时,所有智能体都遵循统一的“可对话”接口,可以无缝地进行交互。

    c.人机协同
        a.功能说明
            AutoGen在自动化和人类监督之间取得了很好的平衡。通过`UserProxyAgent`,可以轻松地在流程中引入人类的智慧。你可以配置让系统在每一步都征求人类输入,或者只在特定条件下暂停以寻求指导,实现了从完全自主到强人机交互的平滑过渡。

1.2 安装配置

01.环境准备
    a.安装AutoGen
        a.功能说明
            安装AutoGen是开始使用的第一步。官方推荐使用`pip`进行安装。为了获得最全面的功能,特别是代码执行和依赖管理,建议安装`pyautogen[blendsearch,docker,lmm,math,retrieve,teachable,tool,websurfer]`,它包含了大部分常用场景的依赖。
        b.代码示例
            ---
            # 推荐使用虚拟环境以避免包冲突
            python -m venv autogen-env
            source autogen-env/bin/activate  # Linux/macOS
            # .\autogen-env\Scripts\activate  # Windows

            # 安装核心包
            pip install pyautogen

            # 或者安装包含所有附加功能的版本
            pip install "pyautogen[blendsearch,docker,lmm,math,retrieve,teachable,tool,websurfer]"

            # 验证安装
            python -c "import autogen; print(autogen.__version__)"
            ---
    b.设置环境变量
        a.功能说明
            AutoGen的智能体需要与大型语言模型(LLM)进行交互,因此必须在环境中配置LLM的API密钥。最常见的配置是设置OpenAI的API密钥。你可以直接在代码中设置,或者更推荐的方式是将其保存在名为`OAI_CONFIG_LIST`的JSON文件中,AutoGen会自动加载。这种方式便于管理多个模型配置和密钥。
        b.代码示例
            ---
            # 方法一:在代码中直接设置(不推荐用于生产)
            import os
            os.environ["OPENAI_API_KEY"] = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

            # 方法二:创建OAI_CONFIG_LIST.json文件(推荐)
            # 在项目根目录下创建 OAI_CONFIG_LIST.json 文件
            # [
            #   {
            #     "model": "gpt-4-turbo",
            #     "api_key": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            #   },
            #   {
            #     "model": "gpt-3.5-turbo",
            #     "api_key": "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            #   }
            # ]

            # 在代码中加载配置
            from autogen import config_list_from_json
            config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")
            ---

02.代码执行环境
    a.本地执行
        a.功能说明
            默认情况下,`UserProxyAgent`会在其工作目录(通过`work_dir`参数指定)下的一个Python环境中执行代码。这对于简单的脚本和任务来说非常方便。但需要注意的是,这种方式执行的代码可能会影响到你的本地环境,存在一定的安全风险。
        b.代码示例
            ---
            # 配置在本地执行代码
            user_proxy_local = UserProxyAgent(
                name="user_proxy_local",
                code_execution_config={
                    "work_dir": "coding", # 指定代码文件和日志的存放目录
                    "use_docker": False   # 明确指定不使用Docker
                }
            )
            ---
    b.Docker执行
        a.功能说明
            为了安全和环境隔离,强烈推荐使用Docker来执行代码。当`use_docker`设置为`True`时,`UserProxyAgent`会在一个临时的Docker容器中执行代码。这可以防止代码对本地文件系统造成意外的修改,并确保代码在一个干净、一致的环境中运行。你需要确保本地已经安装并运行了Docker。
        b.代码示例
            ---
            # 配置在Docker中执行代码
            user_proxy_docker = UserProxyAgent(
                name="user_proxy_docker",
                code_execution_config={
                    "work_dir": "coding",
                    "use_docker": True # 启用Docker执行
                    # 可以指定要使用的Docker镜像,默认为autogen/python:3.11
                    # "docker_image": "python:3.11-slim"
                }
            )
            ---

1.3 快速开始

01.定义智能体
    a.创建助手智能体
        a.功能说明
            首先,我们定义一个“助手”智能体(`AssistantAgent`)。这个智能体的核心职责是理解任务、进行思考,并生成解决问题的Python代码。我们通过`system_message`参数为其设定了一个“Python专家”的角色,以引导其生成高质量的代码。`llm_config`则为其配置了所需的语言模型。
        b.代码示例
            ---
            from autogen import AssistantAgent, UserProxyAgent, config_list_from_json

            # 从配置文件加载LLM配置
            config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")

            # 创建一个助手智能体
            assistant = AssistantAgent(
                name="assistant",
                system_message="You are a helpful AI assistant. You write python code to solve tasks.",
                llm_config={"config_list": config_list}
            )
            ---
    b.创建用户代理智能体
        a.功能说明
            接下来,我们定义一个“用户代理”智能体(`UserProxyAgent`)。它的主要职责是执行由助手智能体生成的代码。我们通过`code_execution_config`参数配置了代码执行环境,例如,使用Docker来确保安全。`human_input_mode`设置为`TERMINATE`意味着当用户输入“exit”时,对话将结束,否则将自动执行代码,这实现了自动化与人类监督的结合。
        b.代码示例
            ---
            # 创建一个用户代理智能体
            user_proxy = UserProxyAgent(
                name="user_proxy",
                human_input_mode="TERMINATE", # 在用户输入'exit'或对话结束时终止
                max_consecutive_auto_reply=10,
                is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"),
                code_execution_config={
                    "work_dir": "web_scraping", # 代码执行的工作目录
                    "use_docker": True # 推荐使用Docker执行代码
                },
                llm_config={"config_list": config_list}
            )
            ---

02.发起对话
    a.启动双智能体对话
        a.功能说明
            定义好两个核心智能体后,我们就可以通过`user_proxy.initiate_chat()`方法来启动一次对话。`user_proxy`作为对话的发起者,将初始任务消息发送给`assistant`。之后,两个智能体将自动进行多轮对话:`assistant`生成代码,`user_proxy`执行代码并反馈结果,直到任务最终完成或达到终止条件。
        b.代码示例
            ---
            # 用户代理发起对话,请求助手编写一个网络爬虫
            chat_result = user_proxy.initiate_chat(
                assistant,
                message=(
                    "Write a python script to scrape the main headlines from Hacker News (https://news.ycombinator.com/). "
                    "The script should save the headlines to a file named \'headlines.txt\'."
                ),
            )
            ---

03.执行与结果
    a.自动化协作流程
        a.功能说明
            对话启动后,整个流程将自动进行。`assistant`会回复一段包含Python代码的消息,用于抓取Hacker News的头条。`user_proxy`接收到消息后,会检测到代码块,并因为`human_input_mode`不是`ALWAYS`,它会直接在配置好的环境(Docker容器)中执行该代码。代码执行成功后,会生成`headlines.txt`文件。
        b.代码示例
            ---
            # Assistant的典型回复(在后台自动发生)
            # """
            # ```python
            # import requests
            # from bs4 import BeautifulSoup
            #
            # url = \"https://news.ycombinator.com/\"
            # response = requests.get(url)
            # soup = BeautifulSoup(response.text, \"html.parser\")
            # headlines = [a.text for a in soup.select(\".titleline > a\")]
            #
            # with open(\"headlines.txt\", \"w\") as f:
            #     for headline in headlines:
            #         f.write(f\"{headline}\n\")
            # print(\"Headlines saved to headlines.txt\")
            # ```
            # """
            ---
    b.获取最终产出
        a.功能说明
            对话结束后,你可以在`user_proxy`指定的工作目录(`web_scraping`)中找到任务的最终产出物,即`headlines.txt`文件。`initiate_chat`方法返回的`chat_result`对象中也包含了完整的对话历史、成本信息和最终的总结,可用于分析和调试。
        b.代码示例
            ---
            # 检查生成的文件
            # 在./web_scraping/headlines.txt 文件中可以看到抓取到的新闻标题

            # 打印对话摘要和成本
            print(chat_result.summary)
            print(chat_result.cost)
            ---

2 智能体

2.1 核心详解

01.ConversableAgent
    a.智能体基类
        a.功能说明
            `ConversableAgent`是AutoGen中所有智能体的基石。它定义了智能体间通信的基本接口,使其能够发送和接收消息。这个基类本身不执行具体任务,但提供了注册回复函数(`register_reply`)的能力,允许开发者自定义智能体的行为逻辑,从而实现高度灵活和可扩展的多智能体交互模式。
        b.代码示例
            ---
            from autogen import ConversableAgent

            # 创建一个基础的可对话智能体
            base_agent = ConversableAgent(
                name="base_agent",
                llm_config=False, # 默认不使用LLM
                human_input_mode="NEVER" # 从不征求人类输入
            )

            # 可以为其注册自定义的回复逻辑
            def my_reply_func(messages, sender, config):
                return "This is my custom reply."

            base_agent.register_reply(trigger=ConversableAgent, reply_func=my_reply_func)
            ---

02.AssistantAgent
    a.AI助手角色
        a.功能说明
            `AssistantAgent`是扮演AI助手的核心角色。它默认配置了LLM(如GPT-4),负责理解任务、生成思考过程和编写解决问题的代码。它是一个纯粹的“思考者”和“规划者”,自身不执行代码,而是将生成的代码块放在回复中,期望由其他智能体(通常是`UserProxyAgent`)来执行。
        b.代码示例
            ---
            from autogen import AssistantAgent

            # 创建一个专注于编写Python代码的AI助手
            python_coder = AssistantAgent(
                name="python_coder",
                system_message="You are a senior Python developer. You write clean, efficient, and correct Python code.",
                llm_config={"config_list": config_list}
            )
            ---

03.UserProxyAgent
    a.人类代理与执行者
        a.功能说明
            `UserProxyAgent`是人类用户的代理,同时也是一个强大的“执行者”。它的核心职责是执行从其他智能体接收到的代码块。此外,它还负责人机交互,可以通过`human_input_mode`参数配置何时征求人类输入(例如,`ALWAYS`表示总是需要人类确认,`TERMINATE`表示在人类输入"exit"时终止对话)。这种设计使得AutoGen可以在完全自主和人机协同两种模式间无缝切换。
        b.代码示例
            ---
            from autogen import UserProxyAgent

            # 创建一个需要人类参与的用户代理
            human_in_the_loop_proxy = UserProxyAgent(
                name="human_in_the_loop_proxy",
                human_input_mode="ALWAYS", # 每次执行前都征求人类同意
                code_execution_config=False # 在此模式下通常禁用自动代码执行
            )
            ---

04.GroupChatManager
    a.群聊协调者
        a.功能说明
            `GroupChatManager`是一种特殊的智能体,它本身不直接解决问题,而是作为群聊的协调者。当一个对话被发起给`GroupChatManager`时,它负责管理群聊中的对话流程,根据预设的规则或LLM的判断,在每一步选择最合适的智能体发言。这使得构建复杂的多智能体协作(如辩论、咨询、多角色项目组)成为可能。
        b.代码示例
            ---
            from autogen import GroupChat, GroupChatManager

            # 假设已创建 coder, product_manager, qa_engineer 三个智能体
            group_chat = GroupChat(
                agents=[coder, product_manager, qa_engineer],
                messages=[],
                max_round=12
            )

            # 创建群聊管理器,它也是一个ConversableAgent
            manager = GroupChatManager(
                groupchat=group_chat,
                llm_config={"config_list": config_list}
            )

            # 对话被发起给manager,由它来协调整个群聊
            user_proxy.initiate_chat(
                manager, 
                message="开发一个新功能:用户登录。请完成设计、开发和测试。"
            )
            ---

2.2 对话模式

01.双智能体对话
    a.基础协作模式
        a.功能说明
            双智能体对话是AutoGen最基础也是最核心的协作模式。通常由一个`AssistantAgent`(思考者/规划者)和一个`UserProxyAgent`(执行者/反馈者)组成。对话由`UserProxyAgent`通过调用`initiate_chat`方法发起,并传入初始任务。之后,两个智能体将自动进行多轮对话,`AssistantAgent`生成解决方案和代码,`UserProxyAgent`执行代码并反馈结果,直至任务完成。
        b.代码示例
            ---
            # 承接 34.3 中的 assistant 和 user_proxy 实例

            # UserProxyAgent 发起对话
            chat_result = user_proxy.initiate_chat(
                assistant, # 对话的另一方
                message="绘制一张NVDA和TSLA从2024年初至今的股价走势对比图,并保存为png文件。",
                summary_method="last_msg" # 定义如何总结对话
            )

            # 对话结束后,可以获取总结或最后的消息
            print(chat_result.summary)
            ---

02.群组对话 (GroupChat)
    a.多智能体协作
        a.功能说明
            当任务需要两个以上智能体协作时,AutoGen提供了`GroupChat`机制。`GroupChat`允许多个智能体加入一个对话组,并通过一个`GroupChatManager`来协调对话流程。管理器负责决定在每一轮对话中由哪个智能体发言,从而实现更复杂的协作模式。
        b.代码示例
            ---
            from autogen import GroupChat, GroupChatManager

            # 假设已创建了 coder, product_manager, qa_engineer 三个智能体

            # 创建一个群聊实例
            group_chat = GroupChat(
                agents=[coder, product_manager, qa_engineer],
                messages=[],
                max_round=12
            )

            # 创建群聊管理器
            manager = GroupChatManager(
                groupchat=group_chat,
                llm_config={"config_list": config_list}
            )

            # 由用户代理发起与群聊的对话
            user_proxy.initiate_chat(
                manager, 
                message="开发一个新功能:用户登录。请完成设计、开发和测试。"
            )
            ---
    b.发言人选择
        a.功能说明
            在`GroupChat`中,发言人的选择是一个关键环节。默认情况下,管理器会轮流选择智能体发言。但更常用的是让LLM来动态决定下一个发言者。通过在`GroupChatManager`中配置`llm_config`,管理器会在每一步分析对话历史,并选择最适合继续对话的智能体。还可以通过`speaker_selection_method`参数进行更精细的控制。
        b.代码示例
            ---
            # 默认是轮流发言("round_robin")
            # 如果GroupChatManager配置了llm_config,则默认为"auto",由LLM决定

            # 示例:自定义发言人选择逻辑
            def custom_speaker_selection(last_speaker, groupchat):
                # ... 自定义逻辑 ...
                if last_speaker is product_manager:
                    return coder
                else:
                    return product_manager

            custom_manager = GroupChatManager(
                groupchat=group_chat,
                speaker_selection_method=custom_speaker_selection
            )
            ---

03.层级对话
    a.智能体嵌套
        a.功能说明
            AutoGen还支持更复杂的层级对话结构,即一个智能体(通常是一个管理者或协调者)的回复可以是发起另一个独立的、由一组子智能体参与的对话。这种“智能体嵌套”或“对话中的对话”模式,使得构建具有分层管理结构的大型多智能体系统成为可能。例如,一个“CEO”智能体可以将任务委派给“技术部”和“市场部”两个子群聊,并等待它们各自的结论。
        b.代码示例
            ---
            # 概念示例:通过注册回复函数实现层级对话

            # 1. 创建技术部和市场部两个子群聊管理器
            tech_manager = GroupChatManager(...) 
            marketing_manager = GroupChatManager(...)

            # 2. 创建CEO智能体
            ceo = AssistantAgent(name="CEO", ...)

            # 3. 定义一个函数,让CEO可以调用子群聊
            def run_sub_chat(message, manager):
                ceo.initiate_chat(manager, message=message)

            # 4. 将这个函数注册为CEO的工具,或通过其他方式触发
            # 这样CEO就可以在它的对话中,决定何时启动一个子对话流程
            ---

2.3 代码执行

01.执行环境
    a.本地执行
        a.功能说明
            默认情况下,`UserProxyAgent`会在其工作目录(通过`work_dir`参数指定)下的一个Python环境中执行代码。这对于简单的脚本和任务来说非常方便。但需要注意的是,这种方式执行的代码可能会影响到你的本地环境,存在一定的安全风险。
        b.代码示例
            ---
            # 配置在本地执行代码
            user_proxy_local = UserProxyAgent(
                name="user_proxy_local",
                code_execution_config={
                    "work_dir": "coding", # 指定代码文件和日志的存放目录
                    "use_docker": False   # 明确指定不使用Docker
                }
            )
            ---
    b.Docker执行
        a.功能说明
            为了安全和环境隔离,强烈推荐使用Docker来执行代码。当`use_docker`设置为`True`时,`UserProxyAgent`会在一个临时的Docker容器中执行代码。这可以防止代码对本地文件系统造成意外的修改,并确保代码在一个干净、一致的环境中运行。你需要确保本地已经安装并运行了Docker。
        b.代码示例
            ---
            # 配置在Docker中执行代码
            user_proxy_docker = UserProxyAgent(
                name="user_proxy_docker",
                code_execution_config={
                    "work_dir": "coding",
                    "use_docker": True # 启用Docker执行
                    # 可以指定要使用的Docker镜像,默认为autogen/python:3.11
                    # "docker_image": "python:3.11-slim"
                }
            )
            ---

02.代码提取与执行
    a.自动提取
        a.功能说明
            `UserProxyAgent`能够自动从接收到的消息中检测和提取代码块(通常是Markdown格式的Python代码块)。一旦检测到可执行的代码,它就会根据`code_execution_config`的配置来执行它。这个过程是完全自动的,是实现AutoGen自动化工作流的关键。
        b.代码示例
            ---
            # AssistantAgent发送的消息中包含代码块
            message_with_code = """
            Here is the python code to solve the problem:
            ```python
            print("Hello, AutoGen!")
            ```
            """

            # UserProxyAgent接收到此消息后,会自动提取并执行 print("Hello, AutoGen!")
            ---
    b.执行结果返回
        a.功能说明
            代码执行后,其输出(stdout)、错误(stderr)以及最终的退出码都会被`UserProxyAgent`捕获。然后,这些执行结果会被格式化成一条新的消息,发送回给之前的发言者(通常是`AssistantAgent`)。这使得`AssistantAgent`能够知道代码的执行情况,并根据结果进行下一步的思考,例如修复代码中的错误或基于代码输出继续任务。
        b.代码示例
            ---
            # 代码执行后的典型返回消息
            # """
            # exitcode: 0
            # Hello, AutoGen!
            # """

            # 如果代码出错,返回消息会包含错误信息
            # """
            # exitcode: 1
            # Traceback (most recent call last):
            #   File "<stdin>", line 1, in <module>
            # NameError: name \'prnt\' is not defined
            # """
            ---

03.Jupyter内核执行
    a.交互式执行
        a.功能说明
            除了执行脚本文件,AutoGen还支持通过Jupyter内核来执行代码。这允许智能体进行更具交互性的、探索性的数据分析。代码可以逐个单元格(cell)执行,并且可以保持变量和状态。这对于数据科学任务尤其有用。
        b.代码示例
            ---
            from autogen.coding import JupyterCodeExecutor

            # 创建一个Jupyter代码执行器
            jupyter_executor = JupyterCodeExecutor(
                kernel_name="python3",
                output_dir=".",
            )

            # 在UserProxyAgent中配置使用Jupyter执行器
            user_proxy_jupyter = UserProxyAgent(
                name="user_proxy_jupyter",
                code_execution_config={"executor": jupyter_executor}
            )
            ---

2.4 工具与函数调用

01.函数调用基础
    a.注册函数
        a.功能说明
            AutoGen允许为智能体注册自定义的Python函数作为其可以调用的“工具”。通过`register_function`方法,你可以将一个或多个函数以及它们的签名(函数名、参数、描述)提供给智能体。智能体(特别是配置了支持函数调用的LLM的`AssistantAgent`)在对话中可以决定调用这些函数来完成特定任务。
        b.代码示例
            ---
            # 1. 定义一个或多个工具函数
            def get_current_weather(location: str) -> str:
                """获取指定地点的当前天气。"""
                # ... (此处为调用天气API的逻辑)
                return f"{location}现在是晴天,25摄氏度。"

            def get_stock_price(symbol: str) -> float:
                """获取指定股票代码的当前价格。"""
                # ... (此处为调用股票API的逻辑)
                return 150.75

            # 2. 为UserProxyAgent注册这些函数
            user_proxy.register_function(
                function_map={
                    "get_current_weather": get_current_weather,
                    "get_stock_price": get_stock_price,
                }
            )
            ---
    b.自动调用与执行
        a.功能说明
            一旦函数被注册,`AssistantAgent`在需要时会生成一个特殊的函数调用指令(遵循OpenAI的函数调用格式)。`UserProxyAgent`接收到这个指令后,会自动执行对应的Python函数,并将函数的返回值作为结果,在下一轮对话中发送回给`AssistantAgent`。整个过程无缝衔接,极大地扩展了智能体的能力边界。
        b.代码示例
            ---
            # 用户发起一个需要调用工具的任务
            user_proxy.initiate_chat(
                assistant,
                message="北京今天天气怎么样?苹果公司的股价是多少?"
            )

            # AssistantAgent的回复(在后台自动发生)会是一个函数调用指令
            # [ 
            #   {"type": "tool_code", "function": {"name": "get_current_weather", "arguments": "{\"location\": \"北京\"}"}},
            #   {"type": "tool_code", "function": {"name": "get_stock_price", "arguments": "{\"symbol\": \"AAPL\"}"}}
            # ]

            # UserProxyAgent会自动执行这两个函数,并将结果返回
            ---

02.可学习的智能体 (TeachableAgent)
    a.动态学习新技能
        a.功能说明
            `TeachableAgent`是AutoGen中一个非常强大的高级智能体。它可以在对话过程中向用户学习新的技能(即新的函数)。当用户告诉它一个新的事实或如何完成一项新任务时,`TeachableAgent`可以自动地将这些新知识转化为一个新的Python函数,并将其添加到自己的工具集中,以便在未来使用。这使得智能体具有了动态成长的能力。
        b.代码示例
            ---
            from autogen.agentchat.contrib.teachable_agent import TeachableAgent

            # 创建一个可学习的智能体
            teachable_agent = TeachableAgent(
                name="teachable_agent",
                llm_config={"config_list": config_list}
            )

            # 用户教给它一个新技能
            user_proxy.initiate_chat(
                teachable_agent,
                message="你好,我教你一个新技能。要问候一个人,你应该说\"你好,[名字]!\"。请记住这个技能,函数名叫greet。"
            )

            # 在后续的对话中,teachable_agent就可以使用这个新技能了
            user_proxy.initiate_chat(
                teachable_agent,
                message="请问候张三。"
            )
            # teachable_agent会调用它自己创建的greet("张三")函数
            ---

3 相关信息

3.1 高级特性

01.增强推理 (Enhanced Inference)
    a.多LLM配置
        a.功能说明
            AutoGen允许为单个智能体配置多个LLM。在`llm_config`中,`config_list`可以包含多个模型配置。AutoGen会自动处理API调用时的重试和故障转移。例如,如果对GPT-4的调用失败,它可以自动切换到GPT-3.5或另一个备用模型。这大大提高了应用的健壮性。
        b.代码示例
            ---
            # 配置多个LLM,实现故障转移
            config_list_with_fallback = [
                {
                    "model": "gpt-4-turbo",
                    "api_key": "YOUR_OPENAI_API_KEY",
                },
                {
                    "model": "gpt-3.5-turbo",
                    "api_key": "YOUR_OPENAI_API_KEY",
                },
                {
                    "model": "llama3",
                    "api_key": "YOUR_GROQ_API_KEY",
                    "base_url": "https://api.groq.com/openai/v1"
                }
            ]

            assistant_robust = AssistantAgent(
                name="assistant_robust",
                llm_config={"config_list": config_list_with_fallback}
            )
            ---
    b.缓存 (Caching)
        a.功能说明
            为了降低成本和提高响应速度,AutoGen内置了对LLM调用的缓存机制。通过在`llm_config`中设置`cache_seed`,可以将相同请求的LLM响应缓存起来。当再次遇到完全相同的请求时,AutoGen会直接从缓存中返回结果,而不会再次调用API。将`cache_seed`设置为`None`可以禁用缓存。
        b.代码示例
            ---
            # 启用LLM响应缓存
            assistant_cached = AssistantAgent(
                name="assistant_cached",
                llm_config={
                    "config_list": config_list,
                    "cache_seed": 42  # 使用一个固定的种子来启用缓存
                    # "cache_seed": None # 禁用缓存
                }
            )
            ---

02.检索增强生成 (RAG)
    a.RetrieveUserProxyAgent
        a.功能说明
            AutoGen通过`RetrieveUserProxyAgent`简化了检索增强生成(RAG)应用的构建。这个特殊的`UserProxyAgent`可以被配置为从一组文档中检索相关信息,并将其作为上下文提供给`AssistantAgent`。这使得`AssistantAgent`能够基于你提供的私有知识库来回答问题或完成任务。
        b.代码示例
            ---
            from autogen.agentchat.contrib.retrieve_assistant_agent import RetrieveAssistantAgent
            from autogen.agentchat.contrib.retrieve_user_proxy_agent import RetrieveUserProxyAgent

            # 1. 创建一个用于RAG的助手智能体
            assistant_rag = RetrieveAssistantAgent(
                name="assistant_rag",
                llm_config={"config_list": config_list}
            )

            # 2. 创建一个RAG用户代理,并加载文档
            rag_proxy = RetrieveUserProxyAgent(
                name="rag_proxy",
                human_input_mode="NEVER",
                retrieve_config={
                    "task": "qa",
                    "docs_path": "./my_documents" # 指定文档目录
                }
            )

            # 3. 发起对话
            rag_proxy.initiate_chat(assistant_rag, problem="根据文档,AutoGen的缓存机制是如何工作的?")
            ---

03.智能体可观测性
    a.Agent Observability
        a.功能说明
            随着多智能体系统变得越来越复杂,理解它们的内部工作状态和决策过程变得至关重要。AutoGen正在积极开发“智能体可观测性”功能,旨在提供更好的工具来监控、记录和可视化智能体之间的交互、工具调用和状态变化。这对于调试、性能优化和理解复杂系统的行为至关重要。
        b.代码示例
            ---
            # 这是一个正在开发中的功能,API可能会发生变化
            # 概念示例:使用回调函数来记录事件
            def log_agent_event(agent, event_name, **kwargs):
                print(f"Agent: {agent.name}, Event: {event_name}, Details: {kwargs}")

            # 在未来版本中,可能会有类似这样的API来注册回调
            # autogen.register_event_callback(log_agent_event)
            ---

3.2 人机协同

01.人类输入模式
    a.ALWAYS模式
        a.功能说明
            当`UserProxyAgent`的`human_input_mode`设置为`ALWAYS`时,系统会在每次准备自动回复(特别是执行代码或调用工具)之前暂停,并强制要求人类用户进行确认。用户可以审查智能体将要执行的操作,然后选择批准(直接按回车)、拒绝或提供修改意见。这种模式提供了最高级别的控制,适用于需要严格监督的关键任务。
        b.代码示例
            ---
            # 创建一个始终需要人类确认的用户代理
            supervised_proxy = UserProxyAgent(
                name="supervised_proxy",
                human_input_mode="ALWAYS",
                code_execution_config={"work_dir": "supervised_code"}
            )

            # 在对话中,每当助手生成代码,系统都会打印代码并等待用户输入
            # """
            # >>> PROPOSED CODE:
            # print("Executing critical task...")
            # >>> YOUR INPUT (or press Enter to execute):
            # """
            ---
    b.TERMINATE模式
        a.功能说明
            `TERMINATE`是默认且最常用的模式。在这种模式下,`UserProxyAgent`会自主地执行代码或回复,但用户可以在任何需要输入的提示下,通过输入`exit`来立即终止整个对话流程。这在自动化和人类控制之间提供了一个很好的平衡点,允许任务自主运行,同时保留了随时干预和停止的能力。
        b.代码示例
            ---
            # 创建一个使用TERMINATE模式的用户代理(默认行为)
            default_proxy = UserProxyAgent(
                name="default_proxy",
                human_input_mode="TERMINATE",
                code_execution_config={"work_dir": "coding"}
            )
            ---
    c.NEVER模式
        a.功能说明
            当`human_input_mode`设置为`NEVER`时,`UserProxyAgent`将变成一个完全自主的执行者。它永远不会征求人类的输入,即使在没有代码或工具可执行的情况下,它也会尝试使用自己的LLM来生成回复(如果配置了`llm_config`)。这种模式适用于构建完全自动化的、无需任何人工干预的后台工作流。
        b.代码示例
            ---
            # 创建一个完全自主的用户代理
            autonomous_proxy = UserProxyAgent(
                name="autonomous_proxy",
                human_input_mode="NEVER",
                code_execution_config={"work_dir": "auto_code"}
            )
            ---

02.动态请求人类反馈
    a.is_termination_msg
        a.功能说明
            除了固定的输入模式,`UserProxyAgent`还允许通过`is_termination_msg`参数提供一个自定义函数。这个函数会在每条消息之后被调用,用于判断该消息是否应该触发对话的终止。这使得开发者可以实现更复杂的、基于对话内容的终止逻辑,例如,当智能体明确表示任务已完成或无法继续时自动停止。
        b.代码示例
            ---
            # 自定义终止逻辑:当助手的回复中包含"任务完成"时,终止对话
            def custom_termination_logic(message):
                content = message.get("content", "").lower()
                return "任务完成" in content

            smart_proxy = UserProxyAgent(
                name="smart_proxy",
                is_termination_msg=custom_termination_logic,
                code_execution_config={"work_dir": "coding"}
            )
            ---

3.3 实战案例

01.自动化研究与报告生成
    a.案例描述
        a.功能说明
            这是一个经典的双智能体协作案例。目标是让AI自动完成“研究一个主题并撰写报告”的任务。我们使用一个`AssistantAgent`作为研究员和作者,一个`UserProxyAgent`作为代码执行者和文件保存者。`AssistantAgent`会生成Python代码来搜索网络、抓取信息,然后整理这些信息并撰写报告。`UserProxyAgent`负责执行这些代码,并将最终的报告保存到本地文件。
        b.代码示例
            ---
            # 概念代码结构
            # 1. Agents: 
            #    - researcher_agent = AssistantAgent(...) # 负责生成研究和写作代码
            #    - executor_proxy = UserProxyAgent(...) # 负责执行代码
            # 2. Task:
            #    - executor_proxy.initiate_chat(
            #        researcher_agent, 
            #        message="研究特斯拉最新的自动驾驶技术,并生成一份Markdown格式的报告保存到tesla_report.md。"
            #      )
            ---

02.交互式数据分析
    a.案例描述
        a.功能说明
            这个案例展示了AutoGen在数据科学领域的应用。我们创建一个`AssistantAgent`作为数据科学家,一个`UserProxyAgent`作为人类分析师的代理。分析师提供一个数据集(例如CSV文件)和分析目标。数据科学家智能体会生成Pandas或Matplotlib代码来加载、清洗、分析数据并进行可视化。`UserProxyAgent`在Jupyter内核中执行这些代码,并将图表和分析结果展示给人类分析师,分析师可以根据结果提出进一步的分析要求,进行多轮探索性分析。
        b.代码示例
            ---
            # 概念代码结构
            # 1. Agents:
            #    - data_scientist = AssistantAgent(...) # 生成Pandas/Matplotlib代码
            #    - analyst_proxy = UserProxyAgent(human_input_mode="ALWAYS", code_execution_config={"executor": jupyter_executor})
            # 2. Task:
            #    - analyst_proxy.initiate_chat(
            #        data_scientist,
            #        message="请分析附件中的sales_data.csv文件,找出销售额最高的月份,并绘制月度销售额的条形图。"
            #      )
            ---

03.多智能体代码审查
    a.案例描述
        a.功能说明
            这是一个使用`GroupChat`的复杂协作案例。我们创建一个包含“程序员”、“代码审查员”和“测试工程师”三个智能体的群聊。程序员负责根据需求编写代码。代码完成后,代码审查员会分析代码的风格、可读性和潜在问题。测试工程师则会为代码生成单元测试并执行。`GroupChatManager`负责协调整个流程,确保每个角色按顺序发言和行动,模拟一个真实的敏捷开发团队的代码审查会议。
        b.代码示例
            ---
            # 概念代码结构
            # 1. Agents: programmer, reviewer, tester
            # 2. GroupChat: group_chat = GroupChat(agents=[programmer, reviewer, tester], ...)
            # 3. Manager: manager = GroupChatManager(groupchat=group_chat, ...)
            # 4. Task:
            #    - user_proxy.initiate_chat(
            #        manager,
            #        message="请为用户登录模块实现一个新的密码重置功能。程序员先写代码,然后审查员审查,最后测试员测试。"
            #      )
            ---

3.4 生产部署

01.API服务化
    a.使用FastAPI或Flask
        a.功能说明
            将AutoGen应用部署为生产服务的标准方法是将其封装在一个Web API中。使用像FastAPI或Flask这样的Python Web框架,你可以创建一个API端点,该端点接收任务输入,启动一个或多个智能体对话,并在任务完成后返回结果。这种方式将AutoGen的复杂交互逻辑与外部客户端解耦,使其可以被任何Web应用、移动应用或其他服务调用。
        b.代码示例
            ---
            # main.py (使用FastAPI)
            from fastapi import FastAPI
            from pydantic import BaseModel
            import autogen

            app = FastAPI()

            class TaskRequest(BaseModel):
                message: str

            @app.post("/run_autogen_task")
            async def run_task(request: TaskRequest):
                config_list = autogen.config_list_from_json("OAI_CONFIG_LIST")
                assistant = autogen.AssistantAgent("assistant", llm_config={"config_list": config_list})
                user_proxy = autogen.UserProxyAgent("user_proxy", code_execution_config={"work_dir": "coding"})
                
                chat_result = user_proxy.initiate_chat(
                    assistant,
                    message=request.message
                )
                return {"summary": chat_result.summary, "cost": chat_result.cost}

            # 运行: uvicorn main:app --reload
            ---

02.容器化
    a.创建Dockerfile
        a.功能说明
            为了确保部署环境的一致性和可移植性,强烈建议使用Docker将AutoGen应用容器化。你需要创建一个`Dockerfile`来定义应用的基础镜像(如`python:3.11`)、安装所有Python依赖(`pyautogen`等)、复制你的应用代码,并指定启动命令(例如,`uvicorn`)。
        b.代码示例
            ---
            # Dockerfile
            FROM python:3.11-slim

            # 安装Docker CLI,因为AutoGen的Docker执行器需要它
            RUN apt-get update && apt-get install -y docker.io

            WORKDIR /app

            COPY requirements.txt .
            RUN pip install -r requirements.txt

            COPY . .

            EXPOSE 8000
            CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
            ---
    b.构建与运行
        a.功能说明
            有了`Dockerfile`后,你可以使用`docker build`命令构建镜像,并使用`docker run`来启动你的应用容器。这确保了你的应用在一个隔离、可复现的环境中运行,便于管理和扩展。
        b.代码示例
            ---
            # 构建镜像
            docker build -t autogen-app .

            # 运行容器
            docker run -d -p 8000:8000 --name autogen-service -v /var/run/docker.sock:/var/run/docker.sock --env-file .env autogen-app
            # 注意:挂载docker.sock允许容器内的AutoGen与宿主机的Docker守护进程通信,以便创建新的代码执行容器
            ---

03.注意事项
    a.状态管理
        a.功能说明
            在生产环境中,特别是对于需要处理多轮交互或长时间运行的任务,你需要考虑状态管理。无状态的API端点对于一次性任务很方便,但对于需要记忆的对话,你可能需要一个外部存储(如Redis或数据库)来保存和恢复对话历史。AutoGen本身不直接提供持久化层,需要开发者自行实现。

    b.安全
        a.功能说明
            安全是生产部署中的重中之重。由于AutoGen的核心功能之一是执行代码,因此必须采取严格的安全措施。始终优先使用Docker执行代码(`use_docker=True`),以将代码执行限制在隔离的容器中。避免在生产环境中使用本地执行模式。同时,要对API端点进行身份验证和授权,防止未经授权的访问和滥用。