📚 文档 | 💡 在线演示 | 💡 示例 | 🤝 参与贡献 | 📝 引用论文 | 💬 加入 Discord | 🏛️ AG2 Classic
[!IMPORTANT]
正在寻找ConversableAgent、GroupChat或import autogen?那就是 AG2 Classic。自 AG2 v1.0 起,基于协议驱动(protocol-driven)的框架已成为顶级包,导入方式为
ag2。经典框架已迁移至独立仓库 — ag2ai/ag2-classic,文档见 classic.docs.ag2.ai。该框架仍在维护且可安装;您已有的构建不会失效。本仓库(
pip install ag2)不再提供autogen导入名称或经典代理类。
AG2 是一个开源编程框架,用于构建 AI 代理并促进多代理之间的协作以解决任务。AG2 旨在简化代理式 AI 的开发与研究。它提供了诸如代理之间交互、支持多种大型语言模型(LLM)、工具使用、自主和人类参与的工作流、以及多代理对话模式等功能。
该项目目前由来自多个组织的志愿者团队维护。如果您有兴趣成为维护者,请通过 support@ag2.ai 联系项目管理员 Chi Wang 和 Qingyun Wu。
autogen.* 命名空间)autogen.* 命名空间)AG2 Classic 是源自 AutoGen 的原始框架:包括 autogen.* 导入命名空间及其代理类 — ConversableAgent、AssistantAgent、UserProxyAgent、GroupChat / GroupChatManager、群组(swarms)、register_function、LLMConfig / OAI_CONFIG_LIST,以及嵌套和顺序聊天模式。
它现已迁移至独立仓库并拥有独立的文档站点:
| AG2 Classic | AG2(本仓库) | |
|---|---|---|
| 代码仓库 | ag2ai/ag2-classic | ag2ai/ag2 |
| 文档 | classic.docs.ag2.ai | docs.ag2.ai |
| 导入 | import autogen |
import ag2 |
| 核心代理 | ConversableAgent |
Agent |
| 多代理 | GroupChat、群组、嵌套聊天 |
网络(枢纽 + 通道) |
如果您代码中出现以下任何内容,那么您使用的是 Classic — 请继续使用它,并参考 classic.docs.ag2.ai:
import autogen # autogen.* 命名空间
from autogen import ConversableAgent, GroupChat # 经典代理类
from autogen import AssistantAgent, UserProxyAgent
Classic 仍在维护且可安装。您现有的代码不会失效 — 请固定安装 classic 发行版,而不是 ag2>=1.0:
pip install ag2-classic
[!NOTE]
AG2 v1.0(pip install ag2)不是 Classic 的直接升级版。代理模型、编排方式和导入方式均发生了改变。请参阅群聊迁移指南。
本 README 其余部分介绍 AG2 v1.0(import ag2)。
有关 AG2 概念和代码的分步介绍,请参阅我们文档中的快速入门。
AG2 需要 Python 版本 >= 3.10。AG2 在 PyPI 上以 ag2 名称提供。
Windows/Linux:
pip install ag2[openai]
Mac:
pip install 'ag2[openai]'
默认安装最小依赖。请安装与您的模型提供商匹配的额外依赖 — ag2[openai]、ag2[anthropic]、ag2[gemini]、ag2[ollama] 等。
每个提供商的配置都会读取其标准环境变量,因此密钥无需硬编码或提交到仓库:
export OPENAI_API_KEY="<your-api-key>" # 或 ANTHROPIC_API_KEY、GEMINI_API_KEY 等
您也可以使用 OpenAIConfig(model="gpt-4o-mini", api_key=...) 显式传递密钥 — 这在每次请求自带密钥时非常有用。
AG2 全程异步。Agent.ask(...) 启动一轮对话并返回一个 AgentReply;文本内容位于 reply.body。
import asyncio
from ag2 import Agent
from ag2.config import OpenAIConfig
agent = Agent(
"assistant",
prompt="你是一个乐于助人的助手。",
config=OpenAIConfig(model="gpt-4o-mini"),
)
async def main() -> None:
reply = await agent.ask("总结 Python 列表和元组之间的主要区别。")
print(reply.body)
asyncio.run(main())
我们维护了一个在线演示环境和一个包含多种应用场景的专用仓库,帮助您快速上手,此外文档中还提供了一系列可运行的代码示例。
AG2 提供了多种代理概念来帮助您构建 AI 代理。这里介绍最常见的一些。
Agent 是核心构建块 — 它与模型提供商通信、调用工具并返回回复。@tool 装饰的普通 Python 函数,代理可以调用这些函数。Agent 是 AG2 的基本构建块。ask() 运行一轮对话;对返回的回复调用 ask() 将继续同一对话,保留其历史记录。
import asyncio
from ag2 import Agent
from ag2.config import OpenAIConfig
reviewer = Agent(
"reviewer",
prompt=(
"你是一名代码审查员。分析提供的代码并提出改进建议。"
"不要生成代码,只提出改进建议。"
),
config=OpenAIConfig(model="gpt-4o-mini"),
)
async def main() -> None:
reply = await reviewer.ask("def fib(n): return n if n < 2 else fib(n-1) + fib(n-2)")
print(reply.body)
# 继续同一对话 — 之前的轮次仍在上下文中。
follow_up = await reply.ask("对于较大的 n,哪个改进最重要?")
print(follow_up.body)
asyncio.run(main())
代理通过工具获得强大的能力,工具扩展了它们访问外部数据、API 或函数的能力。使用 @tool 装饰一个 Python 函数并将其传递给代理 — AG2 会运行完整的工具调用循环:模型决定何时调用,AG2 执行它,并将结果反馈给模型。
import asyncio
from datetime import datetime
from ag2 import Agent, tool
from ag2.config import OpenAIConfig
@tool
async def get_weekday(date_string: str) -> str:
"""返回给定日期(格式为 YYYY-MM-DD)对应的星期几。"""
return datetime.strptime(date_string, "%Y-%m-%d").strftime("%A")
date_agent = Agent(
"date_agent",
prompt="你负责查找给定日期对应的星期几。",
config=OpenAIConfig(model="gpt-4o-mini"),
tools=[get_weekday],
)
async def main() -> None:
reply = await date_agent.ask("我出生于 1995-03-25,那天是星期几?")
print(reply.body)
asyncio.run(main())
人工监督对于验证或引导 AI 输出通常至关重要。在工具内部调用 context.input(...) 可以暂停运行并向人类提问 — 您的 hitl_hook 决定该问题如何得到回答(命令行提示、Web 界面、队列等)。
import asyncio
from ag2 import Agent, Context, tool
from ag2.config import OpenAIConfig
from ag2.events import HumanInputRequest, HumanMessage
@tool
async def publish_lesson_plan(context: Context, plan: str) -> str:
"""在教育工作者批准后发布教案。"""
answer = await context.input(f"批准此教案吗?\n\n{plan}")
if answer.strip().lower().startswith("y"):
return "已发布。"
return f"已被教育工作者拒绝:{answer}"
def hitl_hook(event: HumanInputRequest) -> HumanMessage:
# 在此处阻塞等待真实输入 — 命令行提示、Web 界面、队列等。
return HumanMessage(content=input(f"{event.content}\n> "))
teacher = Agent(
"teacher",
prompt=(
"起草一份简短的教案,然后调用 publish_lesson_plan 工具进行发布。"
"批准过程由工具收集 — 切勿以纯文本形式请求批准。"
),
config=OpenAIConfig(model="gpt-4o-mini"),
tools=[publish_lesson_plan],
hitl_hook=hitl_hook,
)
async def main() -> None:
reply = await teacher.ask("让我们向孩子们介绍太阳系。")
print(reply.body)
asyncio.run(main())
当两个或多个代理需要协作时,AG2 使用 网络(Network):一个 Hub 拥有注册表、预写日志(write-ahead log)和审计追踪,代理通过类型化通道(channels)进行通信。这取代了经典的 GroupChat / 群组(swarm)/ 嵌套聊天模式。
以下示例中,一个 conversation 通道 — 一种任意一方可随时发言的自由形式的两方会话 — 连接了一个规划者(planner)和一个审查者(reviewer):
import asyncio
from ag2 import Agent
from ag2.config import OpenAIConfig
from ag2.knowledge import MemoryKnowledgeStore
from ag2.network import EV_TEXT, Hub
MAX_MESSAGES = 4
async def wait_for_messages(hub: Hub, channel_id: str, expected: int, timeout: float = 120.0) -> None:
"""轮询枢纽的预写日志,直到交换了 `expected` 条消息。"""
deadline = asyncio.get_event_loop().time() + timeout
while asyncio.get_event_loop().time() < deadline:
wal = await hub.read_wal(channel_id)
if sum(1 for e in wal if e.event_type == EV_TEXT) >= expected:
return
await asyncio.sleep(0.05)
raise TimeoutError(f"在超时前仅达到 {expected} 条消息")
async def main() -> None:
config = OpenAIConfig(model="gpt-4o-mini")
hub = await Hub.open(MemoryKnowledgeStore(), ttl_sweep_interval=0)
planner = await hub.register(
Agent("planner", prompt="你负责规划学校课程。用一句简短的话回复。", config=config),
)
reviewer = await hub.register(
Agent("reviewer", prompt="你负责批评教案。用一句简短的话回复。", config=config),
)
# 自由形式的两方通道:任何一方都可以随时发言。
channel = await planner.open(type="conversation", target="reviewer")
await channel.send("四年级太阳系课程应该以什么内容开头?", audience=[reviewer.agent_id])
# 双方的默认处理器都会回复每条入站消息,因此对话会自动推进。
# `conversation` 永远不会自动关闭 — 我们对其设置了上限并关闭它。
await wait_for_messages(hub, channel.channel_id, expected=MAX_MESSAGES)
await channel.close()
# 从枢纽的预写日志中重放对话。
names = {planner.agent_id: "planner", reviewer.agent_id: "reviewer"}
for envelope in await hub.read_wal(channel.channel_id):
if envelope.event_type == EV_TEXT:
print(f"{names[envelope.sender_id]}: {envelope.event_data['text']}")
await hub.close()
asyncio.run(main())
通道有多种形态 — conversation(自由形式、两方)、consulting(严格的一问一答、自动关闭)、discussion(N 个代理之间轮流发言),以及 workflow(声明式的 TransitionGraph 用于条件交接,最接近经典的 GroupChat)。请参阅网络指南。
一个裸 Agent 只是一个模型循环。框架(harness) 是您可以在其上组合的一组可选原语。其中两个最为有用:
knowledge= — 代理可以读写的一个 KnowledgeStore,使其能够在多次运行之间保留记忆。compact= — 一种限制历史增长的策略。SummarizeCompact 将丢弃的轮次折叠成摘要,而不是直接丢弃。将存储与 assembly= 中的 WorkingMemoryPolicy 配对使用,代理的记忆会在每一轮对话中被注入系统提示词 — 回忆不再依赖于模型选择去查记录。
import asyncio
from pathlib import Path
from ag2 import Agent, KnowledgeConfig, MemoryStream
from ag2.compact import CompactTrigger, SummarizeCompact
from ag2.config import OpenAIConfig
from ag2.events import CompactionCompleted, CompactionFailed
from ag2.knowledge import DiskKnowledgeStore
from ag2.policies import WorkingMemoryPolicy
config = OpenAIConfig(model="gpt-4o-mini")
# 磁盘持久化,因此代理记住的任何内容在进程退出后仍然存在。
STORE_DIR = Path("./knowledge_demo")
store = DiskKnowledgeStore(STORE_DIR)
agent = Agent(
"tutor",
prompt=(
"你是一名四年级教师的科学辅导员。"
"每当您了解到关于教师或班级的持久性事实时,请使用知识工具 `read` "
"`memory/working.md`,然后 `write` 回并追加一个新事实作为项目符号。"
"不要删除已存在的事实。"
"每个回复保持在一两句话。"
),
config=config,
knowledge=KnowledgeConfig(
store=store,
# 将丢弃的历史总结而不是直接遗忘。
compact=SummarizeCompact(target=4, config=config),
compact_trigger=CompactTrigger(max_events=8),
),
# 在每一轮对话中将 memory/working.md 注入到系统提示词中,因此回忆不依赖于模型选择调用知识工具。
assembly=[WorkingMemoryPolicy()],
)
stream = MemoryStream()
# 订阅两种结果 — 只关注 Completed 会掩盖失败的策略。
@stream.where(CompactionCompleted).subscribe()
async def on_compacted(event: CompactionCompleted) -> None:
print(f" [已压缩: {event.events_before} -> {event.events_after} 个事件,通过 {event.strategy}]")
@stream.where(CompactionFailed).subscribe()
async def on_compaction_failed(event: CompactionFailed) -> None:
print(f" [压缩失败: {event.strategy}]")
async def main() -> None:
# 返回的会话:没有任何对话历史,因此代理在此处回忆到的任何内容
# 都来自磁盘,通过知识存储。
if STORE_DIR.exists():
reply = await agent.ask("你还记得关于我和我班级的什么信息?", stream=stream)
print(f"tutor: {reply.body}")
return
reply = await agent.ask("我是 Dana。我在 Rosewood 小学教四年级,有 26 名学生。", stream=stream)
print(f"tutor: {reply.body}")
for turn in ["我的班级最困惑的是为什么会有季节。", "为这个问题建议一个动手演示。"]:
reply = await reply.ask(turn)
print(f"tutor: {reply.body}")
asyncio.run(main())
运行两次。第一次运行会填充 memory/working.md 并触发压缩;第二次运行从空历史开始,仍然知道 Dana 是谁:
[已压缩: 18 -> 3 个事件,通过 SummarizeCompact]
tutor: 我记得您是 Dana,在 Rosewood 小学教四年级,有 26 名学生,
您的班级最困惑的是理解为什么会有季节。
有关 assembly=、tasks=、聚合和完整轮次生命周期的更多信息,请参阅代理框架指南。
AG2 支持更高级的概念来帮助您构建 AI 代理工作流。更多信息请参阅文档。
本项目使用 prek 钩子来维护代码质量。在贡献之前:
pip install prek
prek install
prek run --all-files
如需了解 AG2(原 AutoGen)背后的研究,请参阅以下论文:
如果您在研究中使用了 AG2,请引用以下论文:
@software{ag2,
author = {AG2 Contributors},
title = {AG2: Open-Source AgentOS for AI Agents},
year = {2024},
url = {https://github.com/ag2ai/ag2}
}
或参考我们的论文:
@article{wu2023autogen,
title={AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation},
author={Wu, Qingyun and Bansal, Gagan and Zhang, Jieyu and Wu, Yiran and Li, Beibin and Zhu, Erkang and Jiang, Li and Zhang, Xiaoyun and Zhang, Shaokun and Liu, Jiale and others},
journal={arXiv preprint arXiv:2308.08155},
year={2023}
}
本项目基于 Apache License, Version 2.0 (Apache-2.0) 许可。
我们已记录这些更改,以确保对用户和贡献者社区的透明度。有关详细信息,请参阅 NOTICE 文件。