# Procedure DSL · 概念模型 > DSL 的**概念模型** —— 给 Agent 建立"这是个什么世界"的心智框架:数据怎么分类型、动作怎么抽象、工序怎么组织、目的怎么分层。 > > 实际产物是 `workflow.json`(结构化)+ HTML(可视化)。本文讲**模型与思路**;字段提取细节 → [extraction/fields.md](extraction/fields.md),控制流建模 → [extraction/control-flow.md](extraction/control-flow.md),字典树 → [taxonomy/](taxonomy/),workflow.json 契约 → [format/case-data.schema.json](format/case-data.schema.json)。不含手写 DSL 文本的逐构造语法(那是已降级的 `.md` 交付物用的)。 --- ## §1 五层架构 DSL 表达分 5 层, 职责不同, 演化速度不同。 | 层 | 是什么 | 类比 | 演化 | 在 workflow.json 里 | |---|---|---|---|---| | **L0 类型库** | 数据类型(字典树叶子)+ 属性 | type library | stdlib 慢, case 扩展 | IO item 的 `type` | | **L1 外部函数** | 绑定**具体 tool** 的稳定调用契约 | syscall | 只增不改 | step 的 `via`(工具名)| | **L2 抽象动作** | **抽象能力**(动作 kind), 由 L1 实现 | interface + impl | 可演化 | step 的 `action`(动作树路径)| | **L3 工序模板** | 由动作组合的可复用工序 | 函数 / 类 | 高频迭代 | 一个 `procedure` | | **L4 工序实例** | 具体 case 的 inputs + 实际值 + trace | 调用记录 | 每 case 一份 | step 的 `value` 回填 | **L1 vs L2 是关键区分**:L2 是工序内直接调用的**抽象能力**("反推提示词"),L1 是绑定具体工具的**实现**("via manus")。`impl A via B` 声明这层映射——**同一个抽象动作可由多个工具实现**(`impl 生成图像: via nano_banana / via seedream`)。workflow.json 里每 step 记**选定的** `via` + `action`;若有备选实现 / 选型理由,写进 `memo`。 --- ## §2 类型系统 **type = 数据的"制作角色"**,不承担调用情境或步骤属性。 - **一个 type = [类型字典树](taxonomy/type.json) 的一个叶子名**(按功能角色分类:程序控制 / 数据复用 / 内容 / 知识)。 - **case-specific 类型**(不在叶子里)写在 `workflow.json` 的 `procedures[i].type_registry`,格式 `{extends: 最近的 stdlib 叶子, desc}`,不污染 stdlib。 ### 2.1 实质 / 形式 二分 每个 IO 的**内容素材**再按两个正交维度标注(这是内容"长什么样"的描述,与 type 的"角色"正交): - **实质** = 内容**是什么**(人物 / 场景 / 道具 / 观念 / 事件 …) - **形式** = 内容**怎么呈现 / 组织**(光照 / 色调 / 构图 / 运镜 / 叙事 / 修辞 …) 取值来自**外部词表**(`分类库导出_{实质,形式}_*.json`,走 `taxonomy-lookup.py` 查,不进 context)。**标注对象是变量的 `value`(具体素材),不是变量名 / 类型** —— 例:变量"主角图"代表的那张具体图(女主特写)才是被标注对象,标 实质:/表象/视觉/人物 + 形式:/呈现/视觉/特写 (对复杂素材支持多路径标注,以 `+` 连接,在 `workflow.json` 中保存为 JSON 数组,如 `["/表象/视觉/人物", "/表象/视觉/空间"]`)。 ### 2.2 PromptBlock(prompt 的结构化思路) 一段 prompt 不是单串文本,可看作有序的**块**,每块有倾向:`实质 | 形式` 层 + 开放 `tags` + 角色 `role`(`main / constraint / trick / style_preset …`)。workflow.json 的 IO `value` 存完整 prompt 文本;这套分层思路帮你:(a) 判断该 IO 的 实质/形式 标注,(b) 把长 prompt 拆解理解。`trick` = 附着在某能力上、相对默认调用被验证有效的命名化偏离。 --- ## §3 动作模型 一个 step 的"怎么做"拆成正交字段(取值都受字典树 / 受控词约束): | 字段 | 含义 | 取值 | |---|---|---| | `via` | L1 外部工具 | 具体名 `nano_banana_pro` / 占位 `` / `human` / 控制块用 `-` | | `action` | L2 动作 kind | [动作树](taxonomy/action.json) 根→叶路径,e.g. `提取/化学提取/反推` | | `effect` | 在工序链中的位置 | [作用树](taxonomy/effect.json) 叶子,e.g. `主体生成` | | `feature` | 执行特征 | `随机 / 幂等 / 人工 / 本地 / 写外部 / 读外部` | | `control` | 控制流 | `并行 / 遍历 / 分支 / 请求 / 等待`;普通 step 留 `-`(详见 [control-flow.md](extraction/control-flow.md))| > **caller-side 修饰**(抽样 N 选 1 / 重试 / 缓存)不改动作本身,挂在 step 的 `instruction` 里:`@采样(n=4, pick=人工)` / `@重试` / `@缓存`。同一动作在不同 caller 处可挂不同修饰。 --- ## §4 工序结构(L3 / L4) - **L3 工序模板** = 一个 `procedure`:头部(`name / purpose / category / platform / author`)+ `declarations`(`inputs` 调用方传入 / `resources` 跨 case 长期资产 / `returns`)+ `steps`。一篇 case 可含多个 procedure(`procedures: []`)。 - **L4 工序实例** = 具体 case 的实际值:每个 IO 的 `value` **逐字回填**(prompt 原文 / 工具配置 / N 选 1 结果);`.md` 输出按 inputs / bindings / extracted_values / trace 分块(见 [md-structure §11](format/md-structure.md))。 - **控制流**(循环 / 并行 / 分支)展开成 `block + nested` 结构,**不要拍平**——详见 [control-flow.md](extraction/control-flow.md)。 - **跨 case 长期资产**(`resources`)用 `知识库` 类型声明;读写不是独立标注维度,就是普通 step —— 写入 = `action:存储/沉淀/入库` + `feature:写外部`,召回 = `action:获取/查询/调取` + `feature:读外部`。 --- ## §5 目的链 (Purpose Chain) "目的"不是单一属性,是按**稳定性 / 颗粒度**分层的链,各层不同载体: | 实体 | 持有方式 | 颗粒度 | 稳定性 | |---|---|---|---| | L3 工序 | `purpose` + 子维度 `category` | 顶层产品意图 | 全局稳定 | | L2 抽象动作 | docstring("能干啥")| 接口契约 | 跨 caller 不变 | | L3 块(并行/遍历)| `intent` + 子维度 `作用` | 中间策略 | 块内稳定 | | L3 step | `intent` + 子维度 `作用` | 此次调用情境 | 因调用而变 | | 变量声明 | 名字(+ 可选说明)| 数据角色 | 工序全程稳定 | **MVP 最小集**:工序头 `purpose` + 每个 step(或块)至少一个 `intent`。 --- ## §6 标注原则 - **caller-side vs callee-side**:step 的 `intent / 输入 / 输出` 是 **caller**(这次调用)的;动作的 `effect / action / feature` 是 **callee**(动作本身)的,跨 caller 稳定。 - **tags / type 解耦**:标注不重复 type 名已表达的领域语义(`生成图像` 上不再挂 `模态:image`)。 - **值 vs 来源分离**:`value` 写数据本身的内容;上游引用 / 下游去向归 `anchor`。 - **`#输入 / #输出` 列具体子项**,不写"全维"(列 实质·人物 + 实质·场景 …,不偷懒)。 --- ## §7 命名规范 | 元素 | 选择 | 例 | |---|---|---| | 类型名 / 动作名 / 关键字 | 中文 | `参考图 / 反推提示词 / 工序 / 输入 / 返回` | | **变量名** | **type + 工序中的稳定角色**(不带步骤属性 / 工具 / 状态)| `参考视频 / 正向提示词 / 主角图 / 分镜序列` | | 子维度 `key:value` | 中文受控词 | `作用:预处理 / 特性:随机` | | 工具品牌名 | 英文保留 | `manus / nano_banana_pro / seedream_4_5` | > **变量命名归一**:同一概念在不同 step 必须用同一名(lint 校验)。 --- > **字典树简称**:其余文档里的 §A.1 作用 = [effect.json](taxonomy/effect.json)、§A.2 动作 = [action.json](taxonomy/action.json)、§A.3 类型 = [type.json](taxonomy/type.json)(完整叶子 + 各节点 `分类说明` 以这三个文件为 canonical,本文不附录)。