Skip to content

Commit 2eca00b

Browse files
committed
feat: 添加 agent teams
1 parent bceb1cb commit 2eca00b

14 files changed

Lines changed: 392 additions & 321 deletions

File tree

docs/tutorials/agent/agent.md

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@ def get_instruction(name: str):
3636

3737
agent = Agent(llm=llm,
3838
instruction=get_instruction,
39-
instruction_args={'name': '张三'})
39+
instruction_args={'name': 'Mike'})
4040
```
4141

42+
> [!TIP]
43+
> `instruction` 参数也可以是一个文本文件路径, 文件内容将作为指令。
44+
4245
## 创建一个控制器
4346

4447
```python
@@ -51,12 +54,12 @@ controller = Controller(max_turns=10)
5154
## 启动智能体
5255

5356
```python
54-
_, resp = controller.run_sync(agent=translator, message="请帮我翻译蛋白质。")
57+
resp = controller.run_sync(agent=translator, message="请帮我翻译蛋白质。")
5558
```
5659

5760
其中 `message` 参数代表用户的具体指令或者是用户与智能体对话的开始。
5861

59-
`controller.run_sync` 方法返回两个值, 其中第一个值代表最后响应的 `Agent` 对象 (暂时还用不到), 第二个值代表智能体最后的相应内容。在这个例子中, `resp` 的值应该是智能体翻译的结果 (不排除其中包含一些提示语)
62+
`controller.run_sync` 方法返回一个 `ControllerResponse` 对象, 其中 `agent` 代表最后响应的 `Agent` 对象 (暂时还用不到), `message` 代表智能体最后的相应内容, `turns` 代表智能体运行的轮数
6063

6164
## 使用外部工具
6265

@@ -179,14 +182,23 @@ assistant.add_tools(get_weather_tool)
179182

180183
- 字符串: 字符串一般表示函数的执行结果, 例如天气查询的返回值, 此返回值会交还给智能体。
181184

182-
- `Agent` 对象: 表示要切换到新的智能体上继续执行任务。详细见 [多智能体编排](#多智能体编排)
185+
- `Agent` 对象: 表示要切换到新的智能体上继续执行任务。这种情况下工具函数一般被视为 **智能体转移函数**<a id='transfer-function'></a>
183186

184187
- `ContextVariables` 对象: 表示要更新的上下文变量。详细见 [上下文变量](#上下文变量)
185188

186189
- `Result` 对象: 以上三种类型的组合类。
187190

188191
除此之外的返回值都将会被忽略, 其隐藏含义是只关心函数的副作用而不关心函数的返回值。
189192

193+
另外, 我们通常使用历史对话传递消息, 在智能体切换的时候, 之前智能体的与用户的对话或是工具函数调用的结果都会被保存起来, 但是这种方式容易造成历史对话过长。如果你明确不需要这种传递机制, 可以在 `Result` 对象中设置 `message` 字段为 `False` 来实现转换智能体但并不携带历史对话。
194+
195+
```python
196+
result = Result(agent=assistant, message=False)
197+
```
198+
> [!TIP]
199+
> 在这种情况下你可以使用上下文变量或 `add_assistant_message` 方法实现信息的传递。
200+
201+
190202
## 上下文变量
191203

192204
智能体拥有短期记忆和长期记忆, 在这里我们将短期记忆定义为对话的历史记录, 而使用上下文变量实现长期记忆。
@@ -332,8 +344,8 @@ async def main():
332344
mcp_server=[mcp_server]
333345
)
334346
controller = Controller()
335-
_, resp = await controller.run(agent, "帮我查询南京今天的天气")
336-
print(resp)
347+
resp = await controller.run(agent, "帮我查询南京今天的天气")
348+
print(resp.message)
337349

338350
if __name__ == '__main__':
339351
asyncio.run(main())
@@ -369,38 +381,66 @@ controller = Controller(trace_callback=pprint)
369381
- `CONTEXT_UPDATE`: 上下文变量更新
370382
- `MCP_TOOL_CALL`: MCP 工具调用
371383

372-
## 多智能体编排
384+
## 多智能协作
373385

374-
[这里](https://github.com/wangtao2001/CourseGraph/blob/dev/examples/agent/agent_orchestration.py) 展示了一个典型的多智能体编排的场景
386+
除了让智能体使用 <a href='#transfer-function'>转移函数</a> 自行决定接下来被激活的智能体外,也提供了一些固定的协作范式,称之为团队
375387

376-
`core_agent` 负责选择不同的智能体执行相应的任务, 其中的 `transfer_to` 函数通过返回一个 `Agent` 对象来实现身份的转换。
388+
### 团队
377389

378-
对于具体执行任务的智能体来说, 当任务执行完成后, 返回了一个 `Result` 对象, 其中包含了工具函数的调用结果, 并且将身份再转回到 `core_agent`
390+
`RoundTeam` 为例,团队中每个 `Agent` 对象会依次被激活,所有 `Agent` 以广播的方式共享相同的上下文
379391

380-
这里我们并没有使用上下文变量, 而是通过历史对话消息在不同的智能体间传递信息。
392+
#### 创建团队
381393

382-
## 工作流编排
394+
直接使用 `RoundTeam` 类创建一个团队:
383395

384-
[这里](https://github.com/wangtao2001/CourseGraph/blob/dev/examples/agent/workflow_orchestration.py) 展示了一个典型的工作流编排场景。
396+
```python
397+
team = RoundTeam([agent1, agent2, agent3])
398+
```
385399

386-
其中包含了两个工作: 中文的新闻稿撰写和英文的新闻稿撰写。两个工作是并行执行的。
400+
或者使用 `|` 操作符:
387401

388-
在每个工作的内部, 我们手动控制智能体的执行顺序并更新上下文变量。比较特殊的是, 我们将指令直接写在了 `instruction` 中。在这种编排方式下, 智能体不再主动进行任务的规划, 只负责执行具体的指令。
402+
```python
403+
team: RoundTeam = agent1 | agent2 | agent3
404+
```
389405

390-
## 几种编排方式的对比
406+
#### 添加任务
391407

392-
1. **单智能体**:所有的任务都由一个智能体负责,自动规划任务、选择工具调用并进行结果的总结。优点是简单, 用户只需要配置工具下发指令即可。缺点是无法控制智能体的行为, 当任务过于复杂时, 单智能体的压力可能过大, 这种现象在小模型上更加明显。
408+
团队中所有 `Agent` 都将围绕这个任务进行协作:
393409

394-
2. **多智能体**:这种情况下通常用拥有一个核心智能体, 负责将任务拆分成多个任务,每个任务由一个智能体负责,智能体之间通过历史消息传递进行沟通。优点是子任务更加简单智能体处理更加轻松, 但缺点是缺乏稳定性。
410+
```python
411+
team.add_task("请创作一首关于春天的七律诗。")
412+
```
395413

396-
3. **工作流**: 当用户明确知道解决任务的具体步骤时工作流是更加合适的选择。智能体之间不再发生联系, 每个智能体的工作结果也通常保存到上下文变量中。
414+
#### 添加终止器
397415

398-
在具体的实践中, 我们可以将多种编排方式结合起来。将一个任务拆解成多个子任务, 每个子任务可以由多智能体规划具体的执行策略。这样就实现了人工拆解和智能体规划的平衡。
416+
团队中可以设置一个终止器,当满足终止条件时,团队将停止运行:
399417

400-
这里有一个细节需要注意: 在多智能体编排中, 我们通常使用历史对话传递消息, 在智能体切换的时候, 之前智能体的与用户的对话或是工具函数调用的结果都会被保存起来, 但是这种方式容易造成历史对话过长。如果你明确不需要这种传递机制, 可以在 `Result` 对象中设置 `message` 字段为 `False` 来实现转换智能体但并不携带历史对话。
418+
```python
419+
team.terminator = MaxTurnsTerminator(max_turns=10)
420+
```
421+
422+
终止器包含以下类型:
423+
424+
- `MaxTurnsTerminator`: 最大轮数终止, 包含每个 `Agent` 调用工具的次数。
425+
- `MaxActiveTerminator`: 最大激活次数终止, 表示团队中能够激活 `Agent` 的最大次数。
426+
- `TextTerminator`: 当团队中任意一个 `Agent` 的响应中包含指定的文本时,团队将停止运行。
427+
- `TimeOutTerminator`: 超时终止,表示整个团队运行的最长时长。
428+
429+
所有终止器都支持 `&``|` 操作符来组合使用。
430+
431+
#### 运行团队
432+
433+
使用 `run_sync``run` 方法运行团队:
401434

402435
```python
403-
result = Result(agent=assistant, message=False)
436+
team.run_sync()
404437
```
405-
> [!TIP]
406-
> 在这种情况下你可以使用上下文变量实现信息的传递。
438+
439+
不提供返回值,你可以使用 `team.global_messages` 获取团队中所有 `Agent` 的对话历史或者 `add_trace_callback` 方法添加一个回调函数来获取内部流程。
440+
441+
### 团队类型
442+
443+
444+
445+
446+

examples/agent/agents.py

Lines changed: 0 additions & 90 deletions
This file was deleted.

examples/agent/mcp_server.py

Lines changed: 0 additions & 34 deletions
This file was deleted.

examples/agent/use_mcp.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

examples/agent/workflow.py

Lines changed: 0 additions & 73 deletions
This file was deleted.

src/course_graph/agent/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
# File Name: course_graph/agent/__init__.py
55
# Description: agent 相关
66

7-
from .tool import Tool
87
from .agent import Agent
98
from .controller import Controller
10-
from .types import Result, ContextVariables
9+
from .types import Result, ContextVariables, Tool
1110
from .mcp import MCPServer, STDIO, SSE
1211
from .trace import TraceEvent
12+
from .utils import trace_callback
13+
from .teams import Team, RoundTeam, Terminator, TextTerminator, MaxTurnsTerminator

0 commit comments

Comments
 (0)