Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
refactor: 统一Hands系统常量到单个源文件 refactor: 更新Hands中文名称和描述 fix: 修复技能市场在连接状态变化时重新加载 fix: 修复身份变更提案的错误处理逻辑 docs: 更新多个功能文档的验证状态和实现位置 docs: 更新Hands系统文档 test: 添加测试文件验证工作区路径
645 lines
22 KiB
Markdown
645 lines
22 KiB
Markdown
# Pipeline DSL 架构设计
|
||
|
||
> **目标**: 在 ZCLAW 中实现 OpenMagic 类教育功能,支持多步骤自动化工作流
|
||
> **原则**: 用户只看到 Pipeline,Hands/Skills 作为内部实现被隐藏
|
||
|
||
---
|
||
|
||
## 1. 背景
|
||
|
||
### 1.1 问题
|
||
|
||
当前 Hands + Skills 架构存在以下局限:
|
||
- **流程编排**: Skills 是静态提示模板,无法定义执行流程
|
||
- **状态管理**: 复杂场景需要跨多个步骤传递状态
|
||
- **可扩展性**: 不同行业需要不同的生成流程
|
||
- **前端绑定**: Hands 动作无法直接映射到 UI 组件
|
||
|
||
### 1.2 需求
|
||
|
||
- 输入课题 → 自动生成大纲 → 并行生成场景 → 渲染预览 → 导出文件
|
||
- 支持垂直扩展(不同学科)和水平扩展(跨行业)
|
||
- 内部播放预览 + 文件导出(PPTX/HTML/PDF)
|
||
|
||
---
|
||
|
||
## 2. 架构设计
|
||
|
||
### 2.1 分层架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ User Interface │
|
||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||
│ │ Pipeline List│ │ Pipeline Run│ │ Result Preview │ │
|
||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||
└─────────────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ Pipeline Engine (新增) │
|
||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||
│ │ DSL Parser │ │ Executor │ │ State Manager │ │
|
||
│ │ YAML/TOML │ │ DAG Runner │ │ Context Store │ │
|
||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||
└─────────────────────────────────────────────────────────┘
|
||
│
|
||
┌───────────────┼───────────────┐
|
||
▼ ▼ ▼
|
||
┌─────────────────┐ ┌─────────────┐ ┌─────────────────┐
|
||
│ Skills (隐藏) │ │ Hands (隐藏)│ │ Exporters │
|
||
│ prompt templates│ │ executors │ │ pptx/html/pdf │
|
||
└─────────────────┘ └─────────────┘ └─────────────────┘
|
||
```
|
||
|
||
### 2.2 核心组件
|
||
|
||
#### A. Pipeline DSL (声明式配置)
|
||
|
||
```yaml
|
||
# pipelines/education/classroom.yaml
|
||
apiVersion: zclaw/v1
|
||
kind: Pipeline
|
||
metadata:
|
||
name: classroom-generator
|
||
displayName: 互动课堂生成器
|
||
category: education
|
||
description: 输入课题,自动生成完整互动课堂
|
||
|
||
spec:
|
||
inputs:
|
||
- name: topic
|
||
type: string
|
||
required: true
|
||
label: 课题名称
|
||
placeholder: 例如:牛顿第二定律
|
||
- name: difficulty
|
||
type: select
|
||
options: [初级, 中级, 高级]
|
||
default: 中级
|
||
- name: export_formats
|
||
type: multi-select
|
||
options: [pptx, html, pdf]
|
||
default: [pptx, html]
|
||
|
||
steps:
|
||
# Step 1: 解析输入
|
||
- id: parse_input
|
||
action: llm.generate
|
||
template: skills/classroom-generator/parse.md
|
||
input:
|
||
topic: ${inputs.topic}
|
||
difficulty: ${inputs.difficulty}
|
||
output: parsed_data
|
||
|
||
# Step 2: 生成大纲
|
||
- id: generate_outline
|
||
action: llm.generate
|
||
template: skills/classroom-generator/outline.md
|
||
input: ${steps.parse_input.output}
|
||
output: outline
|
||
|
||
# Step 3: 并行生成场景
|
||
- id: generate_scenes
|
||
action: parallel
|
||
each: ${steps.generate_outline.output.items}
|
||
max_workers: 4
|
||
step:
|
||
action: llm.generate
|
||
template: skills/classroom-generator/scene.md
|
||
input:
|
||
item: ${item}
|
||
index: ${index}
|
||
output: scenes[]
|
||
|
||
# Step 4: 渲染课堂
|
||
- id: render
|
||
action: classroom.render
|
||
input:
|
||
outline: ${steps.generate_outline.output}
|
||
scenes: ${steps.generate_scenes.output}
|
||
output: classroom_data
|
||
|
||
# Step 5: 导出文件
|
||
- id: export
|
||
action: file.export
|
||
formats: ${inputs.export_formats}
|
||
input: ${steps.render.output}
|
||
output: export_paths
|
||
|
||
outputs:
|
||
classroom_id: ${steps.render.output.id}
|
||
preview_url: /classroom/${steps.render.output.id}
|
||
export_files: ${steps.export.output}
|
||
```
|
||
|
||
#### B. Pipeline Executor (执行引擎)
|
||
|
||
```rust
|
||
// crates/zclaw-pipeline/src/executor.rs
|
||
pub struct PipelineExecutor {
|
||
skill_registry: Arc<SkillRegistry>,
|
||
hand_registry: Arc<HandRegistry>,
|
||
llm_driver: Arc<dyn LlmDriver>,
|
||
state: PipelineState,
|
||
}
|
||
|
||
impl PipelineExecutor {
|
||
pub async fn execute(&self, pipeline: &Pipeline, inputs: Value) -> Result<PipelineOutput> {
|
||
let mut context = ExecutionContext::new(inputs);
|
||
|
||
for step in &pipeline.spec.steps {
|
||
match &step.action {
|
||
Action::LlmGenerate { template, input } => {
|
||
let prompt = self.render_template(template, &context)?;
|
||
let response = self.llm_driver.generate(prompt).await?;
|
||
context.set_output(&step.id, response);
|
||
}
|
||
Action::Parallel { each, step, max_workers } => {
|
||
let items = context.resolve(each)?;
|
||
let results = self.execute_parallel(step, items, *max_workers).await?;
|
||
context.set_output(&step.id, results);
|
||
}
|
||
Action::ClassroomRender { input } => {
|
||
let data = context.resolve(input)?;
|
||
let classroom = self.render_classroom(data).await?;
|
||
context.set_output(&step.id, classroom);
|
||
}
|
||
Action::FileExport { formats, input } => {
|
||
let paths = self.export_files(formats, input).await?;
|
||
context.set_output(&step.id, paths);
|
||
}
|
||
}
|
||
}
|
||
|
||
Ok(context.extract_outputs(&pipeline.outputs))
|
||
}
|
||
}
|
||
```
|
||
|
||
#### C. State Manager (状态管理)
|
||
|
||
```rust
|
||
// crates/zclaw-pipeline/src/state.rs
|
||
pub struct ExecutionContext {
|
||
inputs: Value,
|
||
steps_output: HashMap<String, Value>,
|
||
variables: HashMap<String, Value>,
|
||
}
|
||
|
||
impl ExecutionContext {
|
||
// 解析表达式 ${steps.generate_outline.output.items}
|
||
pub fn resolve(&self, expr: &str) -> Result<Value> {
|
||
// 支持的表达式:
|
||
// ${inputs.topic} - 输入参数
|
||
// ${steps.xxx.output} - 步骤输出
|
||
// ${item} - 循环变量
|
||
// ${index} - 循环索引
|
||
}
|
||
|
||
pub fn set_output(&mut self, step_id: &str, value: Value) {
|
||
self.steps_output.insert(step_id.to_string(), value);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 文件结构
|
||
|
||
### 3.1 新增 Crate
|
||
|
||
```
|
||
crates/zclaw-pipeline/
|
||
├── Cargo.toml
|
||
├── src/
|
||
│ ├── lib.rs
|
||
│ ├── parser.rs # YAML/TOML DSL 解析
|
||
│ ├── executor.rs # 执行引擎
|
||
│ ├── state.rs # 状态管理
|
||
│ ├── actions/ # 内置动作
|
||
│ │ ├── mod.rs
|
||
│ │ ├── llm.rs # LLM 调用
|
||
│ │ ├── parallel.rs # 并行执行
|
||
│ │ ├── render.rs # 渲染
|
||
│ │ └── export.rs # 导出
|
||
│ └── types.rs # 类型定义
|
||
```
|
||
|
||
### 3.2 Pipeline 配置目录
|
||
|
||
```
|
||
pipelines/
|
||
├── education/ # 教育类
|
||
│ ├── classroom.yaml # 互动课堂
|
||
│ ├── quiz-generator.yaml # 测验生成
|
||
│ └── flashcard.yaml # 闪卡生成
|
||
├── marketing/ # 营销类
|
||
│ ├── campaign.yaml # 营销方案
|
||
│ └── content-calendar.yaml # 内容日历
|
||
├── legal/ # 法律类
|
||
│ └── contract-review.yaml # 合同审查
|
||
└── _templates/ # 模板
|
||
└── base.yaml
|
||
```
|
||
|
||
### 3.3 隐藏 Skills/Hands
|
||
|
||
Skills 和 Hands 文件保留,但:
|
||
- 不在 UI 中直接展示
|
||
- 只通过 Pipeline DSL 引用
|
||
- 作为内部实现细节
|
||
|
||
---
|
||
|
||
## 4. 前端集成
|
||
|
||
### 4.0 设计原则
|
||
|
||
- **Pipeline 页面** - 类似 Hands 页面,展示所有可用 Pipeline
|
||
- **双触发入口** - 页面直接触发 + 对话中 Agent 引导触发
|
||
- **Agent 智能推荐** - 识别用户意图,推荐合适的 Pipeline
|
||
|
||
### 4.1 Pipeline 页面 (新增)
|
||
|
||
#### 页面布局 (参考 Hands 页面)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ Pipelines [+ 新建] │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ [全部] [教育] [营销] [法律] [研发] [更多...] │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ 📚 互动课堂生成 │ │ 📝 测验生成器 │ │
|
||
│ │ │ │ │ │
|
||
│ │ 输入课题,自动 │ │ 根据内容生成 │ │
|
||
│ │ 生成完整课堂 │ │ 选择题/填空题 │ │
|
||
│ │ │ │ │ │
|
||
│ │ [开始生成] │ │ [开始生成] │ │
|
||
│ └─────────────────┘ └─────────────────┘ │
|
||
│ │
|
||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||
│ │ 📊 营销方案生成 │ │ ⚖️ 合同审查 │ │
|
||
│ │ │ │ │ │
|
||
│ │ 输入产品信息, │ │ 上传合同文档, │ │
|
||
│ │ 生成营销策略 │ │ 自动审查风险点 │ │
|
||
│ │ │ │ │ │
|
||
│ │ [开始生成] │ │ [开始生成] │ │
|
||
│ └─────────────────┘ └─────────────────┘ │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
#### Pipeline 卡片组件
|
||
|
||
```typescript
|
||
interface PipelineCard {
|
||
id: string;
|
||
icon: string; // emoji 或图标
|
||
displayName: string;
|
||
description: string;
|
||
category: string;
|
||
tags: string[];
|
||
usage_count: number; // 使用次数(用于排序推荐)
|
||
last_used?: Date;
|
||
}
|
||
```
|
||
|
||
#### Pipeline 运行对话框
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 互动课堂生成器 [×] │
|
||
├─────────────────────────────────────────┤
|
||
│ │
|
||
│ 课题名称 * │
|
||
│ ┌───────────────────────────────────┐ │
|
||
│ │ 牛顿第二定律 │ │
|
||
│ └───────────────────────────────────┘ │
|
||
│ │
|
||
│ 难度等级 │
|
||
│ ○ 初级 ● 中级 ○ 高级 │
|
||
│ │
|
||
│ 导出格式 │
|
||
│ ☑ PPTX ☑ HTML ☐ PDF │
|
||
│ │
|
||
│ [取消] [开始生成] │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.2 对话中触发 (Agent 引导)
|
||
|
||
#### Agent 系统提示词注入
|
||
|
||
```typescript
|
||
// 在 Agent 系统提示词中注入 Pipeline 信息
|
||
const systemPrompt = `
|
||
你是一个智能助手。用户可能会描述一些任务需求,你可以推荐使用合适的 Pipeline 工具。
|
||
|
||
可用的 Pipeline 工具:
|
||
${pipelines.map(p => `- ${p.displayName}: ${p.description}`).join('\n')}
|
||
|
||
当用户的需求匹配某个 Pipeline 时:
|
||
1. 简要说明该 Pipeline 能做什么
|
||
2. 询问用户是否要使用
|
||
3. 如果用户同意,调用 run_pipeline 工具启动
|
||
|
||
示例:
|
||
用户: "帮我做一个关于光合作用的课件"
|
||
你: "我可以使用【互动课堂生成器】为你自动生成完整课件,包括幻灯片、讲解和测验。需要开始吗?"
|
||
`;
|
||
```
|
||
|
||
#### Agent 推荐行为模式
|
||
|
||
**主动推荐策略**(需求模糊时也推荐):
|
||
|
||
```typescript
|
||
// Agent 识别潜在需求的模式
|
||
const intentPatterns = [
|
||
// 教育类
|
||
{ keywords: ["准备.*课", "备课", "教案", "教学"], pipeline: "classroom-generator", confidence: 0.7 },
|
||
{ keywords: ["学生.*测验", "出题", "考试"], pipeline: "quiz-generator", confidence: 0.8 },
|
||
|
||
// 营销类
|
||
{ keywords: ["推广.*方案", "营销计划", "宣传"], pipeline: "marketing-campaign", confidence: 0.75 },
|
||
{ keywords: ["内容.*日历", "发布.*计划"], pipeline: "content-calendar", confidence: 0.7 },
|
||
|
||
// 法律类
|
||
{ keywords: ["合同.*审查", "条款.*风险", "法律.*检查"], pipeline: "contract-review", confidence: 0.8 },
|
||
];
|
||
|
||
// Agent 行为:
|
||
// 1. 监听用户对话内容
|
||
// 2. 匹配潜在需求模式
|
||
// 3. 当 confidence > 0.6 时,主动询问
|
||
// 4. 用户确认后启动 Pipeline
|
||
```
|
||
|
||
#### 对话触发流程
|
||
|
||
**场景 1: 需求明确**
|
||
|
||
```
|
||
用户: 帮我做一个关于牛顿第二定律的课件
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────┐
|
||
│ Agent 分析意图 │
|
||
│ - 关键词: 课件、牛顿第二定律 │
|
||
│ - 匹配 Pipeline: classroom-generator │
|
||
│ - confidence: 0.95 (直接推荐) │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
**场景 2: 需求模糊(主动推荐)**
|
||
|
||
```
|
||
用户: 我在准备下周的物理课,讲力学部分
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────┐
|
||
│ Agent 分析意图 │
|
||
│ - 关键词: 准备课、物理、力学 │
|
||
│ - 匹配 Pipeline: classroom-generator │
|
||
│ - confidence: 0.72 (主动询问) │
|
||
└─────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────┐
|
||
│ Agent 回复 │
|
||
│ "物理课准备啊!力学是个重要主题。 │
|
||
│ │
|
||
│ 我可以帮你:【互动课堂生成器】 │
|
||
│ • 自动生成力学课件大纲 │
|
||
│ • 创建互动幻灯片 │
|
||
│ • 生成课后测验 │
|
||
│ │
|
||
│ 要试试吗?课题就是'力学基础'?" │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────┐
|
||
│ Agent 回复 │
|
||
│ "我可以使用【互动课堂生成器】为你 │
|
||
│ 自动生成完整课件,包括: │
|
||
│ • 结构化大纲 │
|
||
│ • 互动幻灯片 │
|
||
│ • AI 老师讲解 │
|
||
│ • 课后测验 │
|
||
│ │
|
||
│ 需要开始生成吗?" │
|
||
└─────────────────────────────────────┘
|
||
│
|
||
▼ (用户: 好的)
|
||
│
|
||
┌─────────────────────────────────────┐
|
||
│ Agent 调用工具 │
|
||
│ run_pipeline( │
|
||
│ id: "classroom-generator", │
|
||
│ inputs: { │
|
||
│ topic: "牛顿第二定律", │
|
||
│ difficulty: "中级" │
|
||
│ } │
|
||
│ ) │
|
||
└─────────────────────────────────────┘
|
||
│
|
||
▼
|
||
┌─────────────────────────────────────┐
|
||
│ Pipeline 执行 & 进度反馈 │
|
||
│ Agent: "正在生成课堂大纲..." │
|
||
│ Agent: "正在生成第 3/8 个场景..." │
|
||
│ Agent: "课堂生成完成!" │
|
||
│ [预览课堂] [下载 PPTX] │
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 4.3 API 设计
|
||
|
||
```typescript
|
||
// kernel-client.ts 扩展
|
||
|
||
// 列出 Pipelines
|
||
async listPipelines(options?: {
|
||
category?: string;
|
||
search?: string;
|
||
}): Promise<Pipeline[]>
|
||
|
||
// 获取 Pipeline 详情
|
||
async getPipeline(id: string): Promise<PipelineDetail>
|
||
|
||
// 运行 Pipeline
|
||
async runPipeline(request: {
|
||
pipelineId: string;
|
||
inputs: Record<string, any>;
|
||
}): Promise<{ runId: string }>
|
||
|
||
// 获取运行进度
|
||
async getPipelineProgress(runId: string): Promise<{
|
||
status: 'running' | 'completed' | 'failed';
|
||
currentStep: string;
|
||
percentage: number;
|
||
message: string;
|
||
}>
|
||
|
||
// 获取运行结果
|
||
async getPipelineResult(runId: string): Promise<{
|
||
outputs: Record<string, any>;
|
||
files: { name: string; url: string; size: number }[];
|
||
}>
|
||
|
||
// 订阅进度事件
|
||
onPipelineProgress(runId: string, callback: (progress) => void): () => void
|
||
```
|
||
|
||
### 4.4 结果预览页
|
||
|
||
- 白板/幻灯片渲染器
|
||
- Agent 授课播放器
|
||
- 测验交互组件
|
||
- 导出文件下载
|
||
|
||
### 4.5 路由结构
|
||
|
||
```typescript
|
||
// 新增路由
|
||
/pipelines // Pipeline 列表页
|
||
/pipelines/:id // Pipeline 详情/运行页
|
||
/pipelines/run/:runId // 运行结果/进度页
|
||
/classroom/:id // 课堂预览页 (Pipeline 产出)
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 实现步骤
|
||
|
||
### Phase 1: Pipeline 基础 (1 周)
|
||
|
||
1. 创建 `zclaw-pipeline` crate
|
||
2. 实现 DSL Parser (YAML → Pipeline struct)
|
||
3. 实现 ExecutionContext 状态管理
|
||
4. 实现基础 Executor (顺序执行)
|
||
|
||
### Phase 2: 核心动作 (1 周)
|
||
|
||
1. 实现 `llm.generate` 动作
|
||
2. 实现 `parallel` 动作
|
||
3. 实现 `classroom.render` 动作
|
||
4. 实现 `file.export` 动作
|
||
|
||
### Phase 3: 前端集成 (1 周)
|
||
|
||
1. Pipeline 列表 API
|
||
2. Pipeline 运行 API
|
||
3. 进度订阅
|
||
4. 结果获取
|
||
|
||
### Phase 4: 教育模板 (1 周)
|
||
|
||
1. classroom-generator.yaml
|
||
2. 前端预览组件
|
||
3. 测试验证
|
||
|
||
---
|
||
|
||
## 6. 验证方案
|
||
|
||
### 6.1 单元测试
|
||
|
||
```rust
|
||
#[test]
|
||
fn test_pipeline_parse() {
|
||
let yaml = r#"
|
||
apiVersion: zclaw/v1
|
||
kind: Pipeline
|
||
...
|
||
"#;
|
||
let pipeline = PipelineParser::parse(yaml).unwrap();
|
||
assert_eq!(pipeline.metadata.name, "classroom-generator");
|
||
}
|
||
|
||
#[test]
|
||
fn test_expression_resolve() {
|
||
let ctx = ExecutionContext::new(json!({
|
||
"inputs": {"topic": "test"},
|
||
"steps": {"parse": {"output": {"items": [1, 2, 3]}}}
|
||
}));
|
||
let value = ctx.resolve("${steps.parse.output.items}").unwrap();
|
||
assert_eq!(value, json!([1, 2, 3]));
|
||
}
|
||
```
|
||
|
||
### 6.2 集成测试
|
||
|
||
```bash
|
||
# 启动 Pipeline
|
||
curl -X POST http://localhost:50051/pipelines/classroom-generator/run \
|
||
-d '{"topic": "牛顿第二定律", "difficulty": "中级"}'
|
||
|
||
# 检查进度
|
||
curl http://localhost:50051/pipelines/runs/{run_id}/progress
|
||
|
||
# 获取结果
|
||
curl http://localhost:50051/pipelines/runs/{run_id}/result
|
||
```
|
||
|
||
### 6.3 E2E 测试
|
||
|
||
1. 在 UI 中选择 "互动课堂生成器"
|
||
2. 输入课题,点击生成
|
||
3. 观察进度条,等待完成
|
||
4. 预览生成的课堂
|
||
5. 下载 PPTX/HTML 文件
|
||
|
||
---
|
||
|
||
## 7. 扩展性设计
|
||
|
||
### 7.1 添加新 Pipeline
|
||
|
||
只需创建新的 YAML 文件:
|
||
|
||
```yaml
|
||
# pipelines/marketing/campaign.yaml
|
||
apiVersion: zclaw/v1
|
||
kind: Pipeline
|
||
metadata:
|
||
name: marketing-campaign
|
||
category: marketing
|
||
spec:
|
||
steps:
|
||
- id: analyze_brand
|
||
action: llm.generate
|
||
template: skills/marketing/brand-analysis.md
|
||
# ...
|
||
```
|
||
|
||
### 7.2 添加新 Action
|
||
|
||
```rust
|
||
// 在 actions/ 目录添加新动作
|
||
pub struct CustomAction;
|
||
|
||
impl ActionExecutor for CustomAction {
|
||
async fn execute(&self, ctx: &ExecutionContext, config: &Value) -> Result<Value> {
|
||
// 实现自定义逻辑
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7.3 条件分支 (未来)
|
||
|
||
```yaml
|
||
steps:
|
||
- id: check_type
|
||
action: condition
|
||
branches:
|
||
- when: ${inputs.type == 'video'}
|
||
then: generate_video
|
||
- when: ${inputs.type == 'text'}
|
||
then: generate_text
|
||
```
|