207 lines
5.4 KiB
Markdown
207 lines
5.4 KiB
Markdown
|
|
# 工作流验证功能说明
|
|||
|
|
|
|||
|
|
## ✅ 已完成
|
|||
|
|
|
|||
|
|
已实现完整的工作流验证功能,确保工作流的正确性和完整性。
|
|||
|
|
|
|||
|
|
## 功能特性
|
|||
|
|
|
|||
|
|
### 1. 工作流验证器 (`backend/app/services/workflow_validator.py`)
|
|||
|
|
|
|||
|
|
- 节点验证:检查节点ID唯一性、节点类型
|
|||
|
|
- 边验证:检查边的源节点和目标节点是否存在
|
|||
|
|
- 结构验证:检查是否有开始节点、结束节点
|
|||
|
|
- 循环检测:使用DFS算法检测工作流中的循环
|
|||
|
|
- 可达性验证:检查所有节点是否从开始节点可达
|
|||
|
|
- 连接验证:验证节点连接的正确性
|
|||
|
|
- 配置验证:验证节点配置的完整性
|
|||
|
|
|
|||
|
|
### 2. 验证规则
|
|||
|
|
|
|||
|
|
#### 错误(会导致验证失败)
|
|||
|
|
|
|||
|
|
1. **缺少节点**:工作流必须包含至少一个节点
|
|||
|
|
2. **节点ID重复**:节点ID必须唯一
|
|||
|
|
3. **缺少开始节点**:工作流必须包含至少一个开始节点
|
|||
|
|
4. **循环检测**:工作流中不能存在循环
|
|||
|
|
5. **边连接错误**:边的源节点或目标节点不存在
|
|||
|
|
6. **自环检测**:节点不能连接到自身
|
|||
|
|
|
|||
|
|
#### 警告(不会导致验证失败)
|
|||
|
|
|
|||
|
|
1. **多个开始节点**:工作流包含多个开始节点
|
|||
|
|
2. **缺少结束节点**:工作流建议包含至少一个结束节点
|
|||
|
|
3. **不可达节点**:存在从开始节点不可达的节点
|
|||
|
|
4. **开始节点入边**:开始节点不应该有入边
|
|||
|
|
5. **结束节点出边**:结束节点不应该有出边
|
|||
|
|
6. **条件节点分支**:条件节点缺少True或False分支
|
|||
|
|
7. **节点配置不完整**:LLM节点缺少提示词或模型配置
|
|||
|
|
|
|||
|
|
## 使用方法
|
|||
|
|
|
|||
|
|
### 1. 后端API
|
|||
|
|
|
|||
|
|
#### 验证工作流(不保存)
|
|||
|
|
|
|||
|
|
```http
|
|||
|
|
POST /api/v1/workflows/validate
|
|||
|
|
Content-Type: application/json
|
|||
|
|
Authorization: Bearer {token}
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"name": "测试工作流",
|
|||
|
|
"nodes": [...],
|
|||
|
|
"edges": [...]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**响应**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"valid": true,
|
|||
|
|
"errors": [],
|
|||
|
|
"warnings": ["工作流建议包含至少一个结束节点"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 创建/更新工作流时自动验证
|
|||
|
|
|
|||
|
|
创建或更新工作流时,系统会自动验证工作流。如果验证失败,会返回错误信息。
|
|||
|
|
|
|||
|
|
### 2. 验证结果格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"valid": true, // 是否有效
|
|||
|
|
"errors": [], // 错误列表(会导致验证失败)
|
|||
|
|
"warnings": [] // 警告列表(不会导致验证失败)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 验证示例
|
|||
|
|
|
|||
|
|
### 示例1: 有效的工作流
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start-1", "type": "start", "data": {"label": "开始"}},
|
|||
|
|
{"id": "llm-1", "type": "llm", "data": {"label": "LLM", "prompt": "测试"}},
|
|||
|
|
{"id": "end-1", "type": "end", "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start-1", "target": "llm-1"},
|
|||
|
|
{"id": "e2", "source": "llm-1", "target": "end-1"}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**验证结果**: ✅ 通过
|
|||
|
|
|
|||
|
|
### 示例2: 缺少开始节点
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "llm-1", "type": "llm", "data": {"label": "LLM"}},
|
|||
|
|
{"id": "end-1", "type": "end", "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "llm-1", "target": "end-1"}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**验证结果**: ❌ 失败
|
|||
|
|
- 错误: `["工作流必须包含至少一个开始节点"]`
|
|||
|
|
|
|||
|
|
### 示例3: 循环检测
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start-1", "type": "start", "data": {"label": "开始"}},
|
|||
|
|
{"id": "node-1", "type": "default", "data": {"label": "节点1"}},
|
|||
|
|
{"id": "node-2", "type": "default", "data": {"label": "节点2"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start-1", "target": "node-1"},
|
|||
|
|
{"id": "e2", "source": "node-1", "target": "node-2"},
|
|||
|
|
{"id": "e3", "source": "node-2", "target": "node-1"} // 形成循环
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**验证结果**: ❌ 失败
|
|||
|
|
- 错误: `["检测到循环: node-2 -> node-1"]`
|
|||
|
|
|
|||
|
|
### 示例4: 条件节点分支验证
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"nodes": [
|
|||
|
|
{"id": "start-1", "type": "start", "data": {"label": "开始"}},
|
|||
|
|
{"id": "condition-1", "type": "condition", "data": {"label": "条件", "condition": "{value} > 10"}},
|
|||
|
|
{"id": "end-1", "type": "end", "data": {"label": "结束"}}
|
|||
|
|
],
|
|||
|
|
"edges": [
|
|||
|
|
{"id": "e1", "source": "start-1", "target": "condition-1"},
|
|||
|
|
{"id": "e2", "source": "condition-1", "target": "end-1", "sourceHandle": "true"}
|
|||
|
|
// 缺少false分支
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**验证结果**: ✅ 通过(但有警告)
|
|||
|
|
- 警告: `["条件节点 condition-1 缺少False分支"]`
|
|||
|
|
|
|||
|
|
## 测试结果
|
|||
|
|
|
|||
|
|
### 测试覆盖
|
|||
|
|
|
|||
|
|
- ✅ 有效工作流验证 (通过)
|
|||
|
|
- ✅ 缺少开始节点检测 (通过)
|
|||
|
|
- ✅ 循环检测 (通过)
|
|||
|
|
- ✅ 不可达节点检测 (通过)
|
|||
|
|
- ✅ 条件节点分支验证 (通过)
|
|||
|
|
|
|||
|
|
### 测试用例
|
|||
|
|
|
|||
|
|
1. **有效工作流**: 正常通过验证 ✅
|
|||
|
|
2. **缺少开始节点**: 正确检测错误 ✅
|
|||
|
|
3. **循环检测**: 正确检测循环 ✅
|
|||
|
|
4. **不可达节点**: 正确生成警告 ✅
|
|||
|
|
5. **条件节点**: 正确检测分支缺失 ✅
|
|||
|
|
|
|||
|
|
## 集成说明
|
|||
|
|
|
|||
|
|
### 自动验证
|
|||
|
|
|
|||
|
|
- 创建工作流时自动验证
|
|||
|
|
- 更新工作流时自动验证
|
|||
|
|
- 验证失败时阻止保存
|
|||
|
|
|
|||
|
|
### 手动验证
|
|||
|
|
|
|||
|
|
- 通过 `/api/v1/workflows/validate` 端点手动验证
|
|||
|
|
- 不保存工作流,只返回验证结果
|
|||
|
|
|
|||
|
|
## 优势
|
|||
|
|
|
|||
|
|
1. **提前发现问题**:在保存前发现工作流问题
|
|||
|
|
2. **详细错误信息**:提供清晰的错误和警告信息
|
|||
|
|
3. **多种验证规则**:覆盖节点、边、结构、配置等多个方面
|
|||
|
|
4. **区分错误和警告**:错误阻止保存,警告仅提示
|
|||
|
|
|
|||
|
|
## 后续计划
|
|||
|
|
|
|||
|
|
- [ ] 前端集成验证提示
|
|||
|
|
- [ ] 实时验证(编辑时)
|
|||
|
|
- [ ] 更多验证规则(数据流验证、类型检查等)
|
|||
|
|
- [ ] 验证规则自定义
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**状态**: ✅ 已完成
|
|||
|
|
**时间**: 2024年
|