CrewAI 多智能体¶
用纯 Python 实现一个极简的多智能体协作框架,演示 CrewAI 的核心概念: Agent(角色)、Task(任务)、Crew(编队)、Process(执行模式)。 支持顺序(sequential)与层级(hierarchical,含委派)两种执行模式。 LLM 以可注入回调形式提供,便于离线测试。真实场景可替换为 CrewAI 库。 对应教程:第9卷《多智能体》第2章 协作与通信、第3章 分工与协调。
文件路径: examples/volume-09-multi-agent\crewai_demo.py
源代码¶
"""多智能体协作示例(CrewAI 概念实现)。
用纯 Python 实现一个极简的多智能体协作框架,演示 CrewAI 的核心概念:
**Agent(角色)**、**Task(任务)**、**Crew(编队)**、**Process(执行模式)**。
支持顺序(sequential)与层级(hierarchical,含委派)两种执行模式。
LLM 以可注入回调形式提供,便于离线测试。真实场景可替换为 CrewAI 库。
对应教程:第9卷《多智能体》第2章 协作与通信、第3章 分工与协调。
"""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass, field
from typing import Any
# LLM 回调:接收 prompt 返回输出
LLMCallable = Callable[[str], str]
def _default_llm(prompt: str) -> str:
"""默认(无外部 LLM 时)的占位响应。"""
return f"[规则引擎] 已处理:{prompt[:40]}..."
@dataclass
class Agent:
"""智能体。
Attributes:
role: 角色名(如"研究员")。
goal: 目标。
backstory: 背景描述。
llm: 可注入的 LLM 回调。
allow_delegation: 是否允许委派任务给其他智能体。
"""
role: str
goal: str
backstory: str = ""
llm: LLMCallable = _default_llm
allow_delegation: bool = False
def perform(self, task_description: str, context: str = "") -> str:
"""执行一项任务。
Args:
task_description: 任务描述。
context: 上游传递的上下文。
Returns:
执行结果文本。
"""
prompt = (
f"角色:{self.role}\n目标:{self.goal}\n"
f"任务:{task_description}\n上下文:{context or '(无)'}\n请输出结果。"
)
return self.llm(prompt)
@dataclass
class Task:
"""任务。
Attributes:
description: 任务描述。
agent: 负责的智能体。
expected_output: 期望输出说明。
context_from: 依赖的前序任务索引列表(用于拼接上下文)。
"""
description: str
agent: Agent
expected_output: str = ""
context_from: list[int] = field(default_factory=list)
@dataclass
class CrewResult:
"""编队执行结果。
Attributes:
tasks: 每个任务的输出列表。
final: 最终汇总输出。
"""
tasks: list[str]
final: str
@dataclass
class Crew:
"""智能体编队。
Attributes:
agents: 成员智能体列表。
tasks: 任务列表(按顺序执行)。
process: 执行模式,``sequential`` 或 ``hierarchical``。
manager: 层级模式下的管理者智能体。
"""
agents: list[Agent]
tasks: list[Task]
process: str = "sequential"
manager: Agent | None = None
def __post_init__(self) -> None:
if self.process not in ("sequential", "hierarchical"):
raise ValueError(f"未知 process: {self.process}")
if self.process == "hierarchical" and self.manager is None:
raise ValueError("层级模式需要指定 manager")
def _gather_context(self, task_index: int, outputs: list[str]) -> str:
"""收集指定任务依赖的上下文。"""
parts: list[str] = []
for dep in self.tasks[task_index].context_from:
if 0 <= dep < len(outputs):
parts.append(outputs[dep])
return "\n---\n".join(parts)
def kickoff(self, initial_context: str = "") -> CrewResult:
"""启动编队执行。
Args:
initial_context: 初始上下文。
Returns:
``CrewResult``。
"""
if self.process == "sequential":
return self._run_sequential(initial_context)
return self._run_hierarchical(initial_context)
def _run_sequential(self, initial_context: str) -> CrewResult:
outputs: list[str] = []
for i, task in enumerate(self.tasks):
ctx = initial_context if i == 0 else self._gather_context(i, outputs)
if i > 0 and not task.context_from:
# 默认接上一任务输出
ctx = outputs[i - 1]
outputs.append(task.agent.perform(task.description, ctx))
final = outputs[-1] if outputs else ""
return CrewResult(tasks=outputs, final=final)
def _run_hierarchical(self, initial_context: str) -> CrewResult:
"""层级模式:manager 统筹,逐个把任务委派给对应 agent。"""
assert self.manager is not None
outputs: list[str] = []
plan_prompt = (
f"角色:{self.manager.role}\n"
f"目标:制定执行计划并委派任务。\n"
f"任务数:{len(self.tasks)}\n上下文:{initial_context or '(无)'}"
)
plan = self.manager.llm(plan_prompt)
outputs.append(plan)
for i, task in enumerate(self.tasks):
ctx = self._gather_context(i, outputs) or plan
delegated = (
task.agent.perform(task.description, ctx)
if task.agent.allow_delegation or task.agent is not self.manager
else self.manager.perform(task.description, ctx)
)
outputs.append(delegated)
final = self.manager.llm(
f"角色:{self.manager.role}\n请汇总以下结果并给出最终答案:\n" + "\n---\n".join(outputs)
)
return CrewResult(tasks=outputs, final=final)
def build_research_crew(llm: LLMCallable | None = None) -> Crew:
"""构建一个研究-写作的示例编队(顺序模式)。
Args:
llm: 可选的共享 LLM 回调。
Returns:
``Crew``。
"""
shared = llm or _default_llm
researcher = Agent("研究员", "收集并整理资料", llm=shared)
writer = Agent("撰稿人", "把资料写成通俗文章", llm=shared)
tasks = [
Task(description="调研 AI Agent 的核心能力", agent=researcher, expected_output="要点列表"),
Task(
description="撰写一段科普短文", agent=writer, expected_output="短文", context_from=[0]
),
]
return Crew(agents=[researcher, writer], tasks=tasks, process="sequential")
def main() -> None:
"""演示多智能体协作。"""
# 用脚本化 LLM 让输出可预测
script = iter(
[
"[研究] Agent 具备感知、决策、行动能力。",
"[撰稿] AI Agent 就像能自己思考并动手的智能助手。",
]
)
crew = build_research_crew(llm=lambda _p: next(script))
result = crew.kickoff("主题:AI Agent")
print("各任务输出:")
for i, t in enumerate(result.tasks):
print(f" [{i}] {t}")
print(f"\n最终:{result.final}")
if __name__ == "__main__":
main()