Files
zclaw_openfang/plans/cryptic-imagining-peach.md
iven aa6a9cbd84
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
feat: 新增技能编排引擎和工作流构建器组件
refactor: 统一Hands系统常量到单个源文件
refactor: 更新Hands中文名称和描述

fix: 修复技能市场在连接状态变化时重新加载
fix: 修复身份变更提案的错误处理逻辑

docs: 更新多个功能文档的验证状态和实现位置
docs: 更新Hands系统文档

test: 添加测试文件验证工作区路径
2026-03-25 08:27:25 +08:00

22 KiB
Raw Permalink Blame History

Pipeline DSL 架构设计

目标: 在 ZCLAW 中实现 OpenMagic 类教育功能,支持多步骤自动化工作流 原则: 用户只看到 PipelineHands/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 (声明式配置)

# 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 (执行引擎)

// 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 (状态管理)

// 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 卡片组件

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 系统提示词注入

// 在 Agent 系统提示词中注入 Pipeline 信息
const systemPrompt = `
你是一个智能助手。用户可能会描述一些任务需求,你可以推荐使用合适的 Pipeline 工具。

可用的 Pipeline 工具:
${pipelines.map(p => `- ${p.displayName}: ${p.description}`).join('\n')}

当用户的需求匹配某个 Pipeline 时:
1. 简要说明该 Pipeline 能做什么
2. 询问用户是否要使用
3. 如果用户同意,调用 run_pipeline 工具启动

示例:
用户: "帮我做一个关于光合作用的课件"
你: "我可以使用【互动课堂生成器】为你自动生成完整课件,包括幻灯片、讲解和测验。需要开始吗?"
`;

Agent 推荐行为模式

主动推荐策略(需求模糊时也推荐):

// 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 路由结构

// 新增路由
/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 单元测试

#[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 集成测试

# 启动 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 文件:

# 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

// 在 actions/ 目录添加新动作
pub struct CustomAction;

impl ActionExecutor for CustomAction {
    async fn execute(&self, ctx: &ExecutionContext, config: &Value) -> Result<Value> {
        // 实现自定义逻辑
    }
}

7.3 条件分支 (未来)

steps:
  - id: check_type
    action: condition
    branches:
      - when: ${inputs.type == 'video'}
        then: generate_video
      - when: ${inputs.type == 'text'}
        then: generate_text