mirror of
https://github.com/OpenBMB/ChatDev.git
synced 2026-04-25 11:18:06 +00:00
277 lines
7.4 KiB
Markdown
Executable File
277 lines
7.4 KiB
Markdown
Executable File
# Dynamic 执行模式指南
|
||
|
||
Dynamic 执行模式允许在边级别定义并行处理行为,支持 Map(扇出)和 Tree(扇出+归约)两种模式。当消息通过配置了 `dynamic` 的边传递时,目标节点会根据拆分结果动态扩展为多个并行实例。
|
||
|
||
## 1. 概述
|
||
|
||
| 模式 | 描述 | 输出 | 适用场景 |
|
||
|------|------|------|----------|
|
||
| **Map** | 扇出执行,将消息拆分为多个单元并行处理 | `List[Message]`(打平结果) | 批量处理、并行查询 |
|
||
| **Tree** | 扇出+归约,并行处理后按组递归合并 | 单个 `Message` | 长文本摘要、层级聚合 |
|
||
|
||
## 2. 配置结构
|
||
|
||
Dynamic 配置定义在**边**上,而非节点:
|
||
|
||
```yaml
|
||
edges:
|
||
- from: Source Node
|
||
to: Target Node
|
||
trigger: true
|
||
carry_data: true
|
||
dynamic: # 边级动态执行配置
|
||
type: map # map 或 tree
|
||
split: # 消息拆分策略
|
||
type: message # message | regex | json_path
|
||
# pattern: "..." # regex 模式必填
|
||
# json_path: "..." # json_path 模式必填
|
||
config: # 模式特定配置
|
||
max_parallel: 5 # 最大并发数
|
||
```
|
||
|
||
### 2.1 核心概念
|
||
|
||
- **动态边**:配置了 `dynamic` 的边,其传递的消息会触发目标节点的动态扩展
|
||
- **静态边**:未配置 `dynamic` 的边,其传递的消息会**复制**到所有动态扩展实例
|
||
- **目标节点扩展**:目标节点根据 split 结果被"虚拟"扩展为多个并行实例
|
||
|
||
### 2.2 多入边一致性规则
|
||
|
||
> [!IMPORTANT]
|
||
> 当一个节点有多条入边配置了 `dynamic` 时,所有动态边的配置**必须完全一致**(type、split、config),否则执行时会报错。
|
||
|
||
## 3. Split 拆分策略
|
||
|
||
Split 定义如何将通过边的消息拆分为并行执行单元。
|
||
|
||
### 3.1 message 模式(默认)
|
||
|
||
每条通过边的消息作为独立执行单元。这是最常用的模式。
|
||
|
||
```yaml
|
||
split:
|
||
type: message
|
||
```
|
||
|
||
**执行行为**:
|
||
- 源节点输出 4 条消息通过动态边
|
||
- 拆分为 4 个并行单元,目标节点执行 4 次
|
||
|
||
### 3.2 regex 模式
|
||
|
||
使用正则表达式从文本内容中提取匹配项。
|
||
|
||
```yaml
|
||
split:
|
||
type: regex
|
||
pattern: "(?s).{1,2000}(?:\\s|$)" # 每 2000 字符切分
|
||
```
|
||
|
||
**典型用例**:
|
||
- 按段落拆分:`pattern: "\\n\\n"`
|
||
- 按行拆分:`pattern: ".+"`
|
||
- 按固定长度:`pattern: "(?s).{1,N}"`
|
||
|
||
### 3.3 json_path 模式
|
||
|
||
从 JSON 格式输出中按路径提取数组元素。
|
||
|
||
```yaml
|
||
split:
|
||
type: json_path
|
||
json_path: "$.items[*]" # JSONPath 表达式
|
||
```
|
||
|
||
## 4. Map 模式详解
|
||
|
||
Map 模式将消息拆分后并行执行目标节点,输出结果打平为 `List[Message]`。
|
||
|
||
### 4.1 配置项
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `max_parallel` | int | 10 | 最大并发执行数 |
|
||
|
||
### 4.2 执行流程
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
Source["源节点输出"] --> Edge["动态边 (map)"]
|
||
Edge --> Split["拆分"]
|
||
Split --> U1["单元 1"]
|
||
Split --> U2["单元 2"]
|
||
Split --> U3["单元 N"]
|
||
U1 --> P1["目标节点 #1"]
|
||
U2 --> P2["目标节点 #2"]
|
||
U3 --> P3["目标节点 #N"]
|
||
P1 --> Merge["合并结果"]
|
||
P2 --> Merge
|
||
P3 --> Merge
|
||
Merge --> Output["List[Message]"]
|
||
```
|
||
|
||
## 5. Tree 模式详解
|
||
|
||
Tree 模式在 Map 基础上增加归约层,将并行结果按组递归合并,最终输出单个结果。
|
||
|
||
### 5.1 配置项
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `group_size` | int | 3 | 每组归约的元素数量,最小为 2 |
|
||
| `max_parallel` | int | 10 | 每层最大并发执行数 |
|
||
|
||
### 5.2 执行流程
|
||
|
||
```mermaid
|
||
flowchart TB
|
||
subgraph Layer1["第一层:并行执行"]
|
||
I1["单元 1"] --> R1["结果 1"]
|
||
I2["单元 2"] --> R2["结果 2"]
|
||
I3["单元 3"] --> R3["结果 3"]
|
||
I4["单元 4"] --> R4["结果 4"]
|
||
I5["单元 5"] --> R5["结果 5"]
|
||
I6["单元 6"] --> R6["结果 6"]
|
||
end
|
||
|
||
subgraph Layer2["第二层:分组归约 (group_size=3)"]
|
||
R1 & R2 & R3 --> G1["归约组 1"]
|
||
R4 & R5 & R6 --> G2["归约组 2"]
|
||
end
|
||
|
||
subgraph Layer3["第三层:最终归约"]
|
||
G1 & G2 --> Final["最终结果"]
|
||
end
|
||
```
|
||
|
||
## 6. 静态边消息复制
|
||
|
||
当目标节点同时有动态入边和静态入边时:
|
||
|
||
- **动态边消息**:按 split 策略拆分,每个单元执行一次目标节点
|
||
- **静态边消息**:**复制**到每个动态扩展实例
|
||
|
||
```yaml
|
||
nodes:
|
||
- id: Task Generator
|
||
type: passthrough
|
||
config: ...
|
||
- id: Extra Requirement
|
||
type: literal
|
||
config:
|
||
content: "请使用简洁的语言"
|
||
- id: Processor
|
||
type: agent
|
||
config:
|
||
name: gpt-4o
|
||
role: 处理任务
|
||
|
||
edges:
|
||
- from: Task Generator
|
||
to: Processor
|
||
dynamic: # 动态边:4 条任务 → 4 个并行单元
|
||
type: map
|
||
split:
|
||
type: message
|
||
config:
|
||
max_parallel: 10
|
||
- from: Extra Requirement
|
||
to: Processor # 静态边:复制到所有 4 个实例
|
||
trigger: true
|
||
carry_data: true
|
||
```
|
||
|
||
**执行结果**:Processor 执行 4 次,每次收到 1 条任务 + "请使用简洁的语言"
|
||
|
||
## 7. 完整示例
|
||
|
||
### 7.1 旅行规划(Map + Tree 组合)
|
||
|
||
```yaml
|
||
graph:
|
||
nodes:
|
||
- id: Eat Planner
|
||
type: literal
|
||
config:
|
||
content: 请规划在上海吃什么
|
||
role: user
|
||
- id: Play Planner
|
||
type: literal
|
||
config:
|
||
content: 请规划在上海玩什么
|
||
role: user
|
||
- id: Stay Planner
|
||
type: literal
|
||
config:
|
||
content: 请规划在上海住哪里
|
||
role: user
|
||
- id: Collector
|
||
type: passthrough
|
||
config:
|
||
only_last_message: false
|
||
- id: Travel Executor
|
||
type: agent
|
||
config:
|
||
name: gpt-4o
|
||
role: 你是旅行规划师,请按照用户请求进行规划
|
||
- id: Final Aggregator
|
||
type: agent
|
||
config:
|
||
name: gpt-4o
|
||
role: 请将输入的内容整合成一份完整的旅行计划
|
||
|
||
edges:
|
||
- from: Eat Planner
|
||
to: Collector
|
||
- from: Play Planner
|
||
to: Collector
|
||
- from: Stay Planner
|
||
to: Collector
|
||
- from: Collector
|
||
to: Travel Executor
|
||
dynamic: # Map 扇出:3 个规划请求 → 3 个并行执行
|
||
type: map
|
||
split:
|
||
type: message
|
||
config:
|
||
max_parallel: 10
|
||
- from: Travel Executor
|
||
to: Final Aggregator
|
||
dynamic: # Tree 归约:3 个结果 → 1 个最终计划
|
||
type: tree
|
||
split:
|
||
type: message
|
||
config:
|
||
group_size: 2
|
||
max_parallel: 10
|
||
```
|
||
|
||
### 7.2 长文档摘要(Tree 模式)
|
||
|
||
```yaml
|
||
edges:
|
||
- from: Document Source
|
||
to: Summarizer
|
||
dynamic:
|
||
type: tree
|
||
split:
|
||
type: regex
|
||
pattern: "(?s).{1,2000}(?:\\s|$)" # 2000 字符切分
|
||
config:
|
||
group_size: 3
|
||
max_parallel: 10
|
||
```
|
||
|
||
## 8. 性能建议
|
||
|
||
- **控制并发**:设置合理的 `max_parallel` 避免触发 API 限流
|
||
- **优化拆分粒度**:过细的拆分增加开销,过粗则无法充分并行
|
||
- **Tree 组大小**:`group_size=2-4` 通常是较好的选择
|
||
- **监控成本**:Dynamic 模式会显著增加 API 调用次数
|
||
|
||
## 9. 相关文档
|
||
|
||
- [边配置指南](../edges.md)
|
||
- [工作流编排指南](../workflow_authoring.md)
|
||
- [Agent 节点配置](../nodes/agent.md)
|