# 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, hand_registry: Arc, llm_driver: Arc, state: PipelineState, } impl PipelineExecutor { pub async fn execute(&self, pipeline: &Pipeline, inputs: Value) -> Result { 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, variables: HashMap, } impl ExecutionContext { // 解析表达式 ${steps.generate_outline.output.items} pub fn resolve(&self, expr: &str) -> Result { // 支持的表达式: // ${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 详情 async getPipeline(id: string): Promise // 运行 Pipeline async runPipeline(request: { pipelineId: string; inputs: Record; }): 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; 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 { // 实现自定义逻辑 } } ``` ### 7.3 条件分支 (未来) ```yaml steps: - id: check_type action: condition branches: - when: ${inputs.type == 'video'} then: generate_video - when: ${inputs.type == 'text'} then: generate_text ```