对话靠谁驱动?不是你写个 while 循环手动搬消息,而是 initiate_chat 在背后接管了"一轮接一轮"的接力。这一节我们把驱动机制拆开,看它怎么决定下一步轮到谁、什么时候停。
你调 initiate_chat(recipient, message=...),框架做三件事:把 message 作为首条发给 recipient;等 recipient 回复;再把回复发回给你(发起方);然后默认继续——除非达到终止条件。这个"继续"就是对话能被驱动起来的原因。
from autogen import ConversableAgent cfg = {"model": "gpt-4o-mini", "api_key": "YOUR_KEY"} a = ConversableAgent("a", llm_config=cfg, system_message="你简短回应。") b = ConversableAgent("b", llm_config=cfg, system_message="你简短回应。") # a 发起,b 接,b 回 a,a 再回 b……直到 max_turns 用尽 result = a.initiate_chat(b, message="开始。", max_turns=4) print("总轮数:", len(result.chat_history)) # 预期 4 条左右
initiate_chat 有几个停止开关:max_turns(最大轮数)、silent(一方连续沉默)、以及自定义的 is_termination_msg(某条消息满足就停)。我们建议:调试期把 max_turns 设小(比如 4),确认逻辑对再放大,避免烧钱闲聊。
我们主张:能用隐式就别显式,把"为什么转"交给对话涌现;只有涉安全或强约束时才显式写死。
# 显式驱动示例:规定 a 收到"转给b"就交给 b from autogen import ConversableAgent cfg = {"model": "gpt-4o-mini", "api_key": "YOUR_KEY"} a = ConversableAgent("a", llm_config=cfg, system_message="你决定转交。") b = ConversableAgent("b", llm_config=cfg, system_message="你收尾。") def route(recipient, messages, sender, config): if "转给b" in str(messages[-1].get("content","")): b.send(messages[-1], a) # 手动把消息推给 b return True, "已转交" return False, None a.register_reply(trigger=ConversableAgent, reply_func=route, position=0)
当不止两个 Agent,谁先说谁后说由 GroupChatManager 决定(第四章详讲)。但原理和你看到的双 Agent 接力一致:都是"拿到消息→决定回复者→发送→判断是否终止"。
每轮对话会更新 Agent 的记忆(历史)。这意味着"下一轮说什么"依赖于前面所有轮次——状态是隐式累积的。好处是上下文连贯,坏处是一旦前面某轮出错,后面全歪。所以第四章强调终止条件和人工兜底。
隐式驱动写起来少,但出 bug 时你不知道下一轮会转向哪;显式驱动可控,但你要维护路由逻辑,复杂度回到"手写流程"的老路。我们的经验法则:当任务路径基本固定(比如固定流水线),用显式更省心;当路径依赖中间结果、难提前写死,用隐式让对话涌现。
# 显式路由的另一种写法:用 is_termination_msg 在 A 说"结束"时停 from autogen import ConversableAgent import os cfg = {"model": "gpt-4o-mini", "api_key": os.environ.get("OPENAI_API_KEY")} a = ConversableAgent("a", llm_config=cfg, system_message="你说完说结束。") b = ConversableAgent("b", llm_config=cfg, system_message="你接话。") def stop(msg): return "结束" in str(msg.get("content","")) chat = a.initiate_chat(b, message="开始聊。", max_turns=6, is_termination_msg=stop) # 当 a 说出含"结束"的话,对话即停,无需固定轮数
如果两个 Agent 都设了 human_input_mode=NEVER 又没终止条件,它们会一直你一句我一句直到 max_turns。更隐蔽的失控是"假终止"——模型说了"我完成了"但实际没做,对话停了但活没干。所以终止条件不能只看关键词,重要任务要加评估 Agent 验证(见 4.4)。
驱动机制理解透后,你会发现"对话即编排"不是一个比喻,而是字面事实:框架的确是用消息接力当控制流。这和你手写 while 循环本质等价,只是决策权交给了对话内容。接受这点,后面群聊的"不可控"就不再神秘,而是可设计的特性。
⚠️ max_turns 不设或设太大,模型可能聊到账单爆炸;上线前务必给上限。
💡 驱动机制本身就是"对话即编排"的引擎盖——你点火,框架按对话内容决定走向。