guantao 18 часов назад
Родитель
Сommit
119652f04c
100 измененных файлов с 29342 добавлено и 3358 удалено
  1. 3 1
      examples/process_pipeline/db_requirements.json
  2. 36 0
      examples/process_pipeline/run_metrics.json
  3. 37 16
      examples/process_pipeline/script/search_eval/batch_3forms.py
  4. 3 0
      examples/process_pipeline/script/search_eval/procedure-dsl/input/aaa_test.json
  5. 42 0
      examples/process_pipeline/script/search_eval/procedure-dsl/input/batch_posts.json
  6. 20 0
      examples/process_pipeline/script/search_eval/procedure-dsl/input/create-1.json
  7. 18 0
      examples/process_pipeline/script/search_eval/procedure-dsl/input/create-2.json
  8. 18 0
      examples/process_pipeline/script/search_eval/procedure-dsl/input/create-3.json
  9. 47 52
      examples/process_pipeline/script/search_eval/procedure-dsl/run_procedure_dsl.py
  10. 182 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/README.md
  11. 35 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/agents/phase-2a-normalizer.md
  12. 43 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/agents/phase-2b-matcher.md
  13. 61 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/extraction/phase1-skeleton.md
  14. 50 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/extraction/phase2-normalize.md
  15. 32 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/extraction/phase3-finalize.md
  16. 268 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/format/case-data.schema.json
  17. 168 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/format/workflow-format.md
  18. 529 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/new_version.md
  19. 0 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/README.md
  20. 402 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/action.json
  21. 69 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/effect.json
  22. 21 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/feature.json
  23. 562 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/type.json
  24. 314 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/type_suggestions.md
  25. 0 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/分类库导出_实质_20260512_132218.json
  26. 0 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/分类库导出_形式_20260512_170623.json
  27. 28 38
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/templates/workflow.template.json
  28. 244 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools.md
  29. 267 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/lint-case.py
  30. 27 60
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/prepare-subtask.py
  31. 269 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/render-case.py
  32. 661 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/renderer.py
  33. 194 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/script.js
  34. 306 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/styles.css
  35. 0 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/taxonomy-lookup.py
  36. 672 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/wf-patch.py
  37. 93 163
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/README.md
  38. 0 51
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/control-flow.md
  39. 0 136
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/fields.md
  40. 228 35
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/phase1-skeleton.md
  41. 189 117
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/phase2-normalize.md
  42. 24 24
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/phase3-finalize.md
  43. 33 92
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/format/case-data.schema.json
  44. 0 43
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/format/md-structure.md
  45. 0 329
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/format/procedure-table.md
  46. 0 110
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/syntax.md
  47. 13 0
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/taxonomy/type_suggestions.md
  48. 28 296
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools.md
  49. 4 6
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/lint-case.py
  50. 4 4
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/render-case.py
  51. 56 125
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/renderer.py
  52. 4 40
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/script.js
  53. 19 58
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/styles.css
  54. 32 95
      examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/wf-patch.py
  55. 15065 221
      examples/process_pipeline/script/search_eval/runs_full/forms_preview.json
  56. 495 415
      examples/process_pipeline/script/search_eval/runs_full/q0010/form_A.json
  57. 518 421
      examples/process_pipeline/script/search_eval/runs_full/q0010/form_B.json
  58. 515 410
      examples/process_pipeline/script/search_eval/runs_full/q0010/form_C.json
  59. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0033/form_A.json
  60. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0033/form_B.json
  61. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0033/form_C.json
  62. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0034/form_A.json
  63. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0034/form_B.json
  64. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0034/form_C.json
  65. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0035/form_A.json
  66. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0035/form_B.json
  67. 13 0
      examples/process_pipeline/script/search_eval/runs_full/q0035/form_C.json
  68. 307 0
      examples/process_pipeline/script/search_eval/runs_full/q0038/form_A.json
  69. 307 0
      examples/process_pipeline/script/search_eval/runs_full/q0038/form_B.json
  70. 229 0
      examples/process_pipeline/script/search_eval/runs_full/q0038/form_C.json
  71. 225 0
      examples/process_pipeline/script/search_eval/runs_full/q0039/form_A.json
  72. 80 0
      examples/process_pipeline/script/search_eval/runs_full/q0039/form_B.json
  73. 21 0
      examples/process_pipeline/script/search_eval/runs_full/q0039/form_C.json
  74. 330 0
      examples/process_pipeline/script/search_eval/runs_full/q0040/form_A.json
  75. 79 0
      examples/process_pipeline/script/search_eval/runs_full/q0040/form_B.json
  76. 338 0
      examples/process_pipeline/script/search_eval/runs_full/q0040/form_C.json
  77. 311 0
      examples/process_pipeline/script/search_eval/runs_full/q0041/form_A.json
  78. 128 0
      examples/process_pipeline/script/search_eval/runs_full/q0041/form_B.json
  79. 105 0
      examples/process_pipeline/script/search_eval/runs_full/q0041/form_C.json
  80. 47 0
      examples/process_pipeline/script/search_eval/runs_full/q0043/form_A.json
  81. 73 0
      examples/process_pipeline/script/search_eval/runs_full/q0043/form_B.json
  82. 312 0
      examples/process_pipeline/script/search_eval/runs_full/q0043/form_C.json
  83. 193 0
      examples/process_pipeline/script/search_eval/runs_full/q0044/form_A.json
  84. 337 0
      examples/process_pipeline/script/search_eval/runs_full/q0044/form_B.json
  85. 313 0
      examples/process_pipeline/script/search_eval/runs_full/q0044/form_C.json
  86. 221 0
      examples/process_pipeline/script/search_eval/runs_full/q0045/form_A.json
  87. 296 0
      examples/process_pipeline/script/search_eval/runs_full/q0045/form_B.json
  88. 21 0
      examples/process_pipeline/script/search_eval/runs_full/q0045/form_C.json
  89. 154 0
      examples/process_pipeline/script/search_eval/runs_full/q0046/form_A.json
  90. 315 0
      examples/process_pipeline/script/search_eval/runs_full/q0046/form_B.json
  91. 48 0
      examples/process_pipeline/script/search_eval/runs_full/q0046/form_C.json
  92. 185 0
      examples/process_pipeline/script/search_eval/runs_full/q0047/form_A.json
  93. 107 0
      examples/process_pipeline/script/search_eval/runs_full/q0047/form_B.json
  94. 317 0
      examples/process_pipeline/script/search_eval/runs_full/q0047/form_C.json
  95. 157 0
      examples/process_pipeline/script/search_eval/runs_full/q0049/form_A.json
  96. 21 0
      examples/process_pipeline/script/search_eval/runs_full/q0049/form_B.json
  97. 319 0
      examples/process_pipeline/script/search_eval/runs_full/q0049/form_C.json
  98. 21 0
      examples/process_pipeline/script/search_eval/runs_full/q0050/form_A.json
  99. 242 0
      examples/process_pipeline/script/search_eval/runs_full/q0050/form_B.json
  100. 118 0
      examples/process_pipeline/script/search_eval/runs_full/q0050/form_C.json

+ 3 - 1
examples/process_pipeline/db_requirements.json

@@ -114,5 +114,7 @@
   "给定一段文案或需求,用 AI 工具生成符合要求的排版图片的方法/教程/工作流",
   "给定一段文案或需求,用 AI 工具生成符合要求的排版图片的方法/教程/工作流",
   "用ai生成真实摄影的美女写真组图,要求具有真实感,氛围感,人物一致性保持",
-  "520_test"
+  "520_test",
+  "AI 人像 真实感 图片 生成 怎么做",
+  "AI 信息 版面设计 图片 生成 怎么做"
 ]

+ 36 - 0
examples/process_pipeline/run_metrics.json

@@ -2959,5 +2959,41 @@
       "source"
     ],
     "timestamp": "2026-05-19T18:00:04.814969"
+  },
+  {
+    "index": 116,
+    "requirement": "AI 人像 真实感 图片 生成 怎么做...",
+    "duration_seconds": 4111.74,
+    "total_cost_usd": 6.361,
+    "costs_breakdown": {
+      "P1_Research_xhs": 3.1139,
+      "P1_Research_x": 0.9481,
+      "P1_Research_gzh": 2.2991
+    },
+    "trace_ids": {
+      "P1_Research_xhs": "7a39fd6c-97c7-499f-8466-0296a8b483ae",
+      "P1_Research_x": "aa5f0aee-bede-4bb2-a7ea-8d2c0c1fb887",
+      "P1_Research_gzh": "4278bbb0-e92b-4785-b28c-abfea238f79c"
+    },
+    "errors": [],
+    "active_steps": [
+      "research"
+    ],
+    "timestamp": "2026-06-10T17:35:15.999175"
+  },
+  {
+    "index": 116,
+    "requirement": "AI 人像 真实感 图片 生成 怎么做...",
+    "duration_seconds": 201.21,
+    "total_cost_usd": 0.0678,
+    "costs_breakdown": {
+      "LLM_Eval_Sources": 0.0678
+    },
+    "trace_ids": {},
+    "errors": [],
+    "active_steps": [
+      "source"
+    ],
+    "timestamp": "2026-06-10T19:26:09.962142"
   }
 ]

+ 37 - 16
examples/process_pipeline/script/search_eval/batch_3forms.py

@@ -68,8 +68,18 @@ def _validate_sentences(data: Dict[str, Any], n: int) -> Optional[str]:
     return None
 
 
+# 单次 LLM 调用改写的词组数。一次性塞太多会撑爆输出 token 上限(JSON 被截断 → 解析失败
+# → 整批回退原词组),所以内部按此粒度分块;改 --count 不影响 form B 质量。
+_FORM_B_CHUNK = 40
+
+
 async def form_b(items: List[Dict[str, Any]], llm_call: Callable, model: str) -> Tuple[List[str], float]:
-    """把每条词组改写成自然搜索短句(一次批量调用,按序对齐)。"""
+    """把每条词组改写成自然搜索短句(内部分块调用,按序对齐)。
+
+    历史上是「一次批量调用」,但 --count 很大时(如全量 2588 条)模型要吐几万 token,
+    被 max_tokens 截断导致 JSON 不完整、整批失败回退。改为按 _FORM_B_CHUNK 分块,
+    单块失败只回退该块原词组,不连累其余块。
+    """
     words = [it["q"] for it in items]
     system = (
         "你是中文搜索词改写器。把每个『关键词组』改写成一句自然、口语、适合在内容平台"
@@ -77,21 +87,32 @@ async def form_b(items: List[Dict[str, Any]], llm_call: Callable, model: str) ->
         "**绝不添加任何具体工具名 / 品牌 / 产品 / 模型名 / 风格名 / 数字示例**"
         "(如 Midjourney、赛博朋克、SD 等都禁止出现)。只输出 JSON。"
     )
-    user = (
-        "把下面每个词组改写成一句自然搜索短句,顺序一一对应,输出:\n"
-        '{"sentences": ["短句1", "短句2", ...]}\n\n'
-        f"词组列表(共 {len(words)} 个):\n{json.dumps(words, ensure_ascii=False, indent=2)}"
-    )
-    data, cost = await call_llm_with_retry(
-        llm_call=llm_call, messages=[{"role": "system", "content": system},
-                                     {"role": "user", "content": user}],
-        model=model, temperature=0.4, max_tokens=2000,
-        validate_fn=lambda d: _validate_sentences(d, len(words)), task_name="FormB",
-    )
-    if not data:
-        print("   ⚠️ form B 生成失败,回退用原词组")
-        return list(words), cost
-    return [s.strip() for s in data["sentences"]], cost
+
+    async def _one_chunk(chunk: List[str]) -> Tuple[List[str], float]:
+        user = (
+            "把下面每个词组改写成一句自然搜索短句,顺序一一对应,输出:\n"
+            '{"sentences": ["短句1", "短句2", ...]}\n\n'
+            f"词组列表(共 {len(chunk)} 个):\n{json.dumps(chunk, ensure_ascii=False, indent=2)}"
+        )
+        data, c = await call_llm_with_retry(
+            llm_call=llm_call, messages=[{"role": "system", "content": system},
+                                         {"role": "user", "content": user}],
+            model=model, temperature=0.4, max_tokens=4000,
+            validate_fn=lambda d: _validate_sentences(d, len(chunk)), task_name="FormB",
+        )
+        if not data:
+            print(f"   ⚠️ form B 某块({len(chunk)} 条)生成失败,回退该块原词组")
+            return list(chunk), c
+        return [s.strip() for s in data["sentences"]], c
+
+    sentences: List[str] = []
+    total_cost = 0.0
+    for i in range(0, len(words), _FORM_B_CHUNK):
+        chunk = words[i:i + _FORM_B_CHUNK]
+        out, c = await _one_chunk(chunk)
+        sentences.extend(out)
+        total_cost += c
+    return sentences, total_cost
 
 
 # ── 形式 C:同义替换重组 ─────────────────────────────────────────────────────────

Разница между файлами не показана из-за своего большого размера
+ 3 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/input/aaa_test.json


Разница между файлами не показана из-за своего большого размера
+ 42 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/input/batch_posts.json


+ 20 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/input/create-1.json

@@ -0,0 +1,20 @@
+{
+  "channel_content_id": "69fd633a000000003502acb9",
+  "title": "AI写剧本的五步法",
+  "content_type": "normal",
+  "body_text": "如果你也总觉得 AI 写出来的剧情“能看但不对味”,问题通常不在模型,而在流程。AI 能帮你提速,但不能替你成为作者。真正好用的方法,不是一句话让它把整部剧本写完,而是把创作拆成 5 个小任务:先找到一句话故事,再把人物问透,接着搭结构骨架,然后逐场检查转折,最后死磕动作和台词。这样做的好处,是每一步都能判断好坏、及时修正,也更容易保住主题、人物弧光和你自己的表达。AI 最适合做放大器,帮你扩写、比较、重组;真正决定故事灵魂的,始终还是你的判断力。当你开始持续追问、质疑和改写,AI 才会真的变成一个合格的创作助手。#写作技巧[话题]# #编剧[话题]# #AI人工智能[话题]# #AI剧本[话题]# #AI写作[话题]#",
+  "like_count": 154,
+  "publish_timestamp": 1778213690000,
+  "images": [
+    "http://sns-webpic-qc.xhscdn.com/202606081924/51d0d777828da4d13d11867f20c8776c/spectrum/1040g0k031vt4chff1m00416htg60qrlfavbong8!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/758b575f38c035271c371e9fccf7b974/spectrum/1040g0k031vt4chff1m0g416htg60qrlf1drs2do!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/d8eb65df34753654356d2e2c5df0b262/spectrum/1040g0k031vt4chff1m10416htg60qrlfekbfcb0!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/c5d0ca09dfea08e811fcb765fbba9556/spectrum/1040g0k031vt4chff1m1g416htg60qrlftqq10ig!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/fd96c34d7c63645f4e47540e924419b2/spectrum/1040g0k031vt4chff1m20416htg60qrlfj36p4dg!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/4429af0d31d017ce473f419f7f1602ee/spectrum/1040g0k031vt4chff1m2g416htg60qrlfos8qtdo!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/4d1c437369f665671577c81d815fe89a/spectrum/1040g0k031vt4chff1m30416htg60qrlft6pcj60!nd_dft_wlteh_jpg_3"
+  ],
+  "videos": [],
+  "channel": "xhs",
+  "link": "https://www.xiaohongshu.com/explore/69fd633a000000003502acb9"
+}

+ 18 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/input/create-2.json

@@ -0,0 +1,18 @@
+{
+  "channel_content_id": "68d7fb0b000000001300d052",
+  "title": "剧本创作四步法-写好故事梗概",
+  "content_type": "normal",
+  "body_text": "",
+  "like_count": 1477,
+  "publish_timestamp": 1758984971000,
+  "images": [
+    "http://sns-webpic-qc.xhscdn.com/202606081923/3e7a9f7e7b2117b5668f1f00b44a2d8e/spectrum/1040g34o31mujimkil2105p2vgr044k7dkkad0do!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081923/ce4f971d5277b7433cf4dfe15c62b5fd/spectrum/1040g0k031mujivhj4s005p2vgr044k7d1lu6qi0!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081923/d8444643a7342b1338eaba963511a0c3/spectrum/1040g0k031mujj60u4s005p2vgr044k7ds3psafo!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081923/b456945c3ef45c43a7127e6f5f43f15f/spectrum/1040g34o31mujjd8kkq105p2vgr044k7dilffis0!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081923/febf8e7c2f662c36b663283656435281/spectrum/1040g0k031mujjo6g52005p2vgr044k7dcfc0dno!nd_dft_wlteh_jpg_3"
+  ],
+  "videos": [],
+  "channel": "xhs",
+  "link": "https://www.xiaohongshu.com/explore/68d7fb0b000000001300d052"
+}

+ 18 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/input/create-3.json

@@ -0,0 +1,18 @@
+{
+  "channel_content_id": "66fa6205000000001902f7a5",
+  "title": "揭秘分镜头脚本万能公式,提升影视创作效率",
+  "content_type": "normal",
+  "body_text": "影视创作之路,你是否曾在拍摄现场犹豫不决,不知道下一步该拍什么,该说什么?别担心,今天我就来揭秘分镜头脚本的万能公式,让你的创作过程更加高效流畅!\n🌟 什么是脚本?\n脚本就像是创作的蓝图,它规划了每一个镜头的内容、对话和动作,确保拍摄过程有条不紊。\n✅ 第一步:选好拍摄定位\n明确你的影片风格和目标受众,这是制定脚本的基础。\n✅ 第二步:脚本的构成\n一个完整的脚本通常包括场景描述、角色动作、对白和镜头指示。\n✅ 第三步:如何写出脚本\n1. 确定故事大纲\n2. 划分场景和镜头\n3. 编写具体对白和动作\n4. 添加镜头说明和技术细节\n✅ 第四步:新手如何安排镜头\n- 叙事镜头:交代背景和推动故事发展\n- 特写镜头:展现角色情感和重要细节\n- 过渡镜头:平滑连接不同场景\n✅ 第五步:我的万能脚本模板\n🌈 使用这个万能脚本模板,即使是新手也能快速上手,让你的影片拍摄更加专业和高效。\n🔖 收藏这篇笔记,下次拍摄前不妨试一试这个万能脚本公式,相信你的影视创作之路会更加顺畅!\n#成美自媒体[话题]# #成美剪辑[话题]# #chengmei0131[话题]# #干货分享[话题]# #后期剪辑[话题]# #自学剪辑[话题]# #剪辑[话题]# #新手剪辑[话题]# #小白自学剪辑[话题]# #剪辑教程[话题]# #剪辑工具[话题]# #大学生自学剪辑[话题]# #寻找大学生剪辑搭子[话题]# #应届生[话题]# #剪辑接单[话题]# #南京剪辑[话题]# #挑战100天做自媒体[话题]#",
+  "like_count": 0,
+  "publish_timestamp": 1727685125000,
+  "images": [
+    "http://sns-webpic-qc.xhscdn.com/202606081924/26fb8c95c088c922642b52eb5b16d8d7/1040g2sg318bu7etjk4cg5pgh7eujci0ginifbhg!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/67cee62a2dcff327d55fd3d01bba14b9/1040g2sg318bu7etjk4d05pgh7eujci0gifk4dt8!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/c8d4d0f7d0478e1af0ffbc10a192f436/1040g2sg318bu7etjk4dg5pgh7eujci0giuiu6k8!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/d35e60dc2180a74c1101993cedc84b24/1040g008318c6mm0c3u005pgh7eujci0g7ajnc8o!nd_dft_wlteh_jpg_3",
+    "http://sns-webpic-qc.xhscdn.com/202606081924/996fc6941e34e98877ec946ac2340d5b/1040g008318c6mm0c3u0g5pgh7eujci0gppmbtg0!nd_dft_wlteh_jpg_3"
+  ],
+  "videos": [],
+  "channel": "xhs",
+  "link": "https://www.xiaohongshu.com/explore/66fa6205000000001902f7a5"
+}

+ 47 - 52
examples/process_pipeline/script/search_eval/procedure-dsl/run_procedure_dsl.py

@@ -403,16 +403,15 @@ def _build_initial_blocks(
    - Phase 1.1 心智模型 → `{case_dir}/understanding.md` (含 procedure 数量判断)
    - Phase 1.2 骨架 → **Write** `{case_dir}/workflow.json` (procedures 数组骨架)
    - Phase 1.3 IO 闭合 → **Edit** workflow.json 加 anchor
-   - Phase 2A/2B/2C 归一化 → **Edit** workflow.json 加 effect/action/type/sub/form + procedures[i].type_registry
-   - Phase 3 lint + 渲染 → 调 render-case.py + lint-case.py (不写 case_data.json, renderer 内存组装)
-   - Phase 3 .md → Write `{case_dir}/case-{case_id}-<slug>.md`
+   - 第二阶段 归类标注 → **Edit** workflow.json 加 effect/action/type + 实质/形式(自由提炼) + type_registry + 目的列 intent (主 Agent 自己一趟做完, 无子 Agent)
+   - Phase 3 lint + 渲染 → 调 render-case.py + lint-case.py (不写 case_data.json, renderer 内存组装; **HTML 是唯一产物, 不写 .md**)
 
 ## ❌ 重复读取禁令 (CRITICAL: ZERO REPEATED READS)
 
 你拥有完美的长期记忆(由于 Context 累积,你读取过的所有文件内容会永远保留在你的 Context 中)。
 请**绝对不要**重复读取任何文件!任何重复的 `Read` 动作都是对 Token 和回合数 Budget 的极大浪费。
 - **禁忌 1**:不要因为看到 spec 文档中写了 `详见 [tools.md §2]` 就去重新 `Read(file_path="{spec_tools}")`。你已经在 Turn 3 读过它了,直接检索你的记忆!
-- **禁忌 2**:不要因为进入了 Phase 2B,就去重新 `Read` 任何 Phase 2 的 spec 文件(如 `phase2-normalize.md`)。你已经在 Phase 2A 开始时读过它了,它就在你的记忆中,直接使用它
+- **禁忌 2**:不要因为进入了第二阶段,就去重新 `Read` 已读过的 spec 文件(如 `phase2-normalize.md`)。它已在你的记忆中,直接使用
 - 在发出任何 `Read` 指令前,必须自我核对:“我之前读过这个文件吗?”。如果读过,绝对不要再次 Read!
 
 ## 输入
@@ -438,10 +437,9 @@ def _build_initial_blocks(
 
 ## 长输出 dump 区 (sanctioned scratch)
 
-如果你需要 dump 大 Bash 输出做后续分析 (e.g. `taxonomy-lookup --subtree` 输出过大想分段读, 或 `find` 结果想保留), **只写到 `{scratch_dir}/`** (runner 已预创建):
+如果你需要 dump 大 Bash 输出做后续分析 (e.g. `find` / `grep` 结果过大想分段读), **只写到 `{scratch_dir}/`** (runner 已预创建):
 
-✅ `python {spec_dir}/tools/taxonomy-lookup.py --dim 实质 --subtree /表象/视觉 > {scratch_dir}/subst_visual.txt`
-✅ 然后 `Read(file_path="{scratch_dir}/subst_visual.txt")` 提取需要的段
+✅ `find ... > {scratch_dir}/out.txt` 然后 `Read(file_path="{scratch_dir}/out.txt")` 提取需要的段
 ✅ 一次性小探查 / smoke test (验证某条 tool 命令、看某段数据长啥样) 也可以放 `{scratch_dir}/`, 用完即弃
 
 ❌ **不要用 Python 脚本生成 / 批量改写 `workflow.json`** — 它由你**直接 Write 骨架 + 逐字段填** 演化 (见各 phase 规格). 写 build_workflow / add_anchors / normalize 这类脚本去拼 JSON, 反而踩转义 / 控制字符坑 (LLM 拼长 JSON 极易坏), 还把本该逐 step 的语义判断埋进一次性脚本里. 几十处字段要批量改 → 用 **`spec/tools/wf-patch.py`** (path=value 清单, 工具负责安全写 JSON + 写入即校验; 见 {spec_name}/tools.md §2), 零星单处用 Edit. `_scratch/` 的 Python **只用于「dump 大 tool 输出」和「smoke test」, 不是 workflow.json 的生产线**.
@@ -467,8 +465,6 @@ python {spec_dir}/tools/render-case.py \
     --page-title "Case {case_id} · <主题>" \
     --case-id {case_id} \
     --out {case_dir}/case-{case_id}-<slug>.html
-
-# Step C: Write {case_dir}/case-{case_id}-<slug>.md (DSL 文本版, 按 {spec_name}/output/md-structure.md §11 结构)
 ```
 
 **`--source-input` 行为**: renderer 自动从 raw 抽 body_text + 封面图 + 图集兜底填到 case_data.source (内存里). 微信公众号长文走 inline 图 + 封面; 小红书短文走 body + "--- 附图 ---" 末尾追加非封面图. 你**不必手工**复制 raw.body_text — 完全交给 renderer.
@@ -598,6 +594,27 @@ def _trace_result(trace_path: Path, msg: Any, elapsed: float,
 
 # ──── 主流程: 跑 ClaudeSDKClient ──────────────────────────────────────────────
 
+def _parse_agent_md(text: str) -> "tuple[dict, str]":
+    """解析 spec/agents/*.md: 极简 `---` frontmatter + markdown 正文.
+    frontmatter 值都是单行; `tools` 用逗号分隔. 返回 (meta dict, 正文 body)."""
+    meta: dict = {}
+    body = text
+    stripped = text.lstrip()
+    if stripped.startswith("---"):
+        rest = stripped[3:]
+        end = rest.find("\n---")
+        if end != -1:
+            fm = rest[:end]
+            body = rest[end + 4:].lstrip("\n")
+            for line in fm.splitlines():
+                line = line.strip()
+                if not line or line.startswith("#") or ":" not in line:
+                    continue
+                key, _, val = line.partition(":")
+                meta[key.strip()] = val.strip()
+    return meta, body
+
+
 async def run(args: argparse.Namespace) -> None:
     from claude_agent_sdk import (
         AssistantMessage,
@@ -656,7 +673,7 @@ async def run(args: argparse.Namespace) -> None:
             f"用户可能在中断期间编辑过任何中间产物 (understanding.md / workflow.json) "
             f"或改过 spec/ 内任何文件 — 务必 Read 这些**当前磁盘版本**, "
             f"不要凭之前记忆继续. 如发现明显人工修订痕迹, 沿用用户改过的版本.\n\n"
-            f"⚠️【重要禁令与强制要求】:如果流程进行到 Phase 2(归一化与分类匹配),主 Agent **绝对禁止**手动调用 taxonomy-lookup.py 查询或手动决策!你必须强制阅读最新的 `spec/extraction/phase2-normalize.md` 规范,通过运行 `prepare-subtask.py` 生成物理任务切片,然后调用 `Agent`(或 `Task`)工具将任务分别分发给预定义好的 `phase-2a-normalizer` 和 `phase-2b-matcher` 子 Agent 并行协作执行!"
+            f"如果流程进行到第二阶段(归类标注),按最新的 `spec/extraction/phase2-normalize.md` **由你自己一趟做完**(作用/动作/类型 归类 + 实质/形式 自由提炼 + 填目的列)——不再有子 Agent、不查实质/形式词表。"
         )}]
     else:
         blocks = _build_initial_blocks(source_for_agent, args.case_id, args.out_dir, images, workdir, args.spec_name)
@@ -692,54 +709,32 @@ async def run(args: argparse.Namespace) -> None:
             stderr_buf.append(line)
             print(f"[stderr] {line}", flush=True)
 
-    agents = {
-        "phase-2a-normalizer": AgentDefinition(
-            description="Expert in Phase 2A (effect/action/type normalization). Use this agent to read task_2a.json, normalize action/effect/type against spec trees, manage procedure-level type_registry, and generate outputs/case-N/_scratch/patch_2a.json.",
-            prompt="""You are a dedicated Phase 2A normalization sub-agent.
-Your goal is to process the inputs and outputs of a workflow for effect, action, and type normalization:
-1. Read the outputs/case-N/_scratch/task_2a.json file to get the steps and IO variables.
-2. Normalize every step's `effect` and `action` against the taxonomy specs in `spec/taxonomy/effect.json` and `spec/taxonomy/action.json`.
-3. Normalize every IO variable's `type` against `spec/taxonomy/type.json`. If a custom type is used, register it in the procedure's `type_registry` with extends and description.
-4. Output a standard `patch_2a.json` JSON file under outputs/case-N/_scratch/.
-IMPORTANT: The format of `patch_2a.json` MUST be a flat JSON array of objects, where each object has a "path" and a "value" key (exactly conforming to the `wf-patch.py` tool contract).
-Example format:
-[
-  {"path": "p1.s1.effect", "value": "预处理"},
-  {"path": "p1.s1.action", "value": "提取/化学提取/反推"},
-  {"path": "p1.s1.inputs[0].type", "value": "工具选型标准"},
-  {"path": "p1.type_registry.工具配置.extends", "value": "评语"},
-  {"path": "p1.type_registry.工具配置.desc", "value": "工具选型依据..."}
-]
-Do not output raw dictionary structure or any other nesting. Do not touch or modify other files.""",
-            tools=["Read", "Grep", "Glob", "Write", "Edit", "Bash"],
-            model="sonnet",
-        ),
-        "phase-2b-matcher": AgentDefinition(
-            description="Expert in Phase 2B (substance/form taxonomy matching). Use this agent to read task_2b.json, invoke taxonomy-lookup.py to query substance and form paths for each variable, and generate outputs/case-N/_scratch/patch_2b.json.",
-            prompt="""You are a dedicated Phase 2B taxonomy matching sub-agent.
-Your goal is to query and match the substance and form for each workflow IO variable:
-1. Read the outputs/case-N/_scratch/task_2b.json file to get the variables to match.
-2. For each variable, run `python spec/tools/taxonomy-lookup.py --dim 实质 --match "..."` and `--dim 形式 --match "..."` to search for the most precise taxonomy paths matching the variable's value, name, and related_images.
-3. Output a standard `patch_2b.json` JSON file under outputs/case-N/_scratch/.
-IMPORTANT: The format of `patch_2b.json` MUST be a flat JSON array of objects, where each object has a "path" and a "value" key (exactly conforming to the `wf-patch.py` tool contract). Substance and form values can be single string paths, multiple paths separated by ' + ', or JSON arrays of strings for multi-path matching.
-Example format:
-[
-  {"path": "p1.s1.inputs[0].substance", "value": "/理念/知识/思想/概念范畴/性质属性/功能效用"},
-  {"path": "p1.s1.inputs[0].form", "value": "/呈现/视觉/视觉制作/构图编排/版面设计/版面结构"},
-  {"path": "p1.s2.inputs[0].substance", "value": ["/理念/知识/商业/前沿技术/AI智能/AI应用", "/理念/知识/思想"]}
-]
-Do not output raw dictionary structure or any other nesting. Do not touch or modify other files.""",
-            tools=["Read", "Grep", "Glob", "Write", "Edit", "Bash"],
-            model="sonnet",
+    # 子 Agent 注册定义从 spec/agents/*.md 加载 (有则加载, 无则 0 个).
+    # 新设计无子 Agent — 此目录不存在时 agents={}, 主 Agent 全程自做.
+    # prompt 里的 {spec} 占位符按当次 --version 替换成实际 spec 目录名 (spec / spec-test ...).
+    agents_dir = workdir / args.spec_name / "agents"
+    agents = {}
+    for md_path in sorted(agents_dir.glob("*.md")):
+        meta, body = _parse_agent_md(md_path.read_text(encoding="utf-8"))
+        tools = [t.strip() for t in meta.get("tools", "").split(",") if t.strip()]
+        agents[md_path.stem] = AgentDefinition(
+            description=meta.get("description", ""),
+            prompt=body.replace("{spec}", args.spec_name).strip(),
+            tools=tools or ["Read", "Grep", "Glob", "Write", "Edit", "Bash"],
+            model=meta.get("model", "sonnet"),
         )
-    }
+    if agents:
+        print(f"[setup] sub-agents    = {len(agents)} loaded from {args.spec_name}/agents/ "
+              f"({', '.join(sorted(agents))})", flush=True)
+    else:
+        print(f"[setup] sub-agents    = 0 (无子 Agent — 主 Agent 全程自做)", flush=True)
 
     options = ClaudeAgentOptions(
         model=args.model,
         cwd=str(workdir),
         resume=resume_sid,
-        # ⚠️ 支持旧版 "Task" 与新版 "Agent" 标识符以确保在所有 Claude Code / SDK 版本中均可激活子 agent
-        allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task", "Agent"],
+        # 新设计无子 Agent, 主 Agent 全程自做; 不再开 Task/Agent 工具
+        allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
         agents=agents,
         max_turns=args.max_turns,
         permission_mode="bypassPermissions",

+ 182 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/README.md

@@ -0,0 +1,182 @@
+# 工序提取 SKILL · 总览
+
+> 这道 skill 做一件事:**读一篇 AI 创作教程/案例,把它背后的"做法"还原成一张工序表,存成 `workflow.json`,再渲染成一个网页**。
+>
+> 三块内容:**概念速览**(本文下面)+ **格式说明**([format/workflow-format.md](format/workflow-format.md),`workflow.json` 每个字段怎么填)+ **操作流程**(子目录 [`extraction/`](extraction/),分三阶段一步步做)。
+>
+> ⚠ 路径提示:概念速览在本文,字段/格式在 `spec/format/workflow-format.md`,操作流程在 `spec/extraction/`。没有 `syntax.md`/`fields.md`/`control-flow.md` 这些文件(都已并进 workflow-format.md)。
+
+---
+
+**本目录是一个自包含的 skill**:跑提取流程时需要的所有说明都在这里。外部的案例原文(`input/case-N-raw.json`)和你产出的成果(`outputs/case-N/`)不算 skill 的一部分。
+
+## 输入 / 输出
+
+**输入**:任意一篇创作案例——公众号 / 小红书 / 推文 / 博客(正文 + 配图)、视频教程(带转写)、或你自己的工作复盘。
+
+**输出**:一个网页 `outputs/case-{N}/case-{N}-<slug>.html`(按 [format/workflow-format.md](format/workflow-format.md) 的工序表规范渲染)。注:纯文本版 `.md` 已取消,只出网页。
+
+---
+
+## 概念速览(这是个什么东西)
+
+读懂这几条,就能看懂工序表在表达什么。
+
+**工序表把"一步操作"拆成 5 个层面**(对应 `workflow.json` 里的字段):
+
+| 层面 | 通俗讲 | 在 workflow.json 里 |
+|---|---|---|
+| 数据类型 | 这份数据算什么角色(参考图/提示词…) | 输入输出的 `type` |
+| 用的工具 | 哪个具体产品(manus/nano_banana…) | 步骤的 `via` |
+| 做的动作 | 干了什么(生成/反推…) | 步骤的 `action` |
+| 工序模板 | 一整套可复用的做法 | 一个 `procedure` |
+| 实际内容 | 这次具体填进去的真实值 | 输入输出的 `value` |
+
+**一篇案例可以有多个工序**:比如一篇文章同时讲"简单做法"和"进阶做法",那就是两个工序,放在顶层 `procedures: []` 数组里(只有一个时也用长度 1 的数组)。
+
+**自造的类型要"挂靠"**:类型词表里没有的词,要在这个工序的 `type_registry` 里写明它"算作"哪个标准词,例如 `主角图` 挂靠 `参考图`。这样既能自由起名,又不弄乱标准词表。
+
+**命名约定**:类型名、动作名用中文;工具品牌名用英文(`nano_banana_pro`);每个输出都要有不重复的编号(如 `s2o1`)供后面引用。其中"作用 / 实质 / 形式 / 动作"是**整步一个**,"类型 / 值 / 来源 / 编号"是**每个输入输出各一个**。
+
+> 后文出现的简称:作用 = [effect.json](taxonomy/effect.json)、动作 = [action.json](taxonomy/action.json)、类型 = [type.json](taxonomy/type.json) 这三张分类词表(完整词条以这三个文件为准)。
+
+---
+
+## 目录里有什么
+
+### 操作流程(extraction/ —— 分三阶段,按阶段读)
+
+| 文件 | 内容 | 什么时候读 |
+|---|---|---|
+| [format/workflow-format.md](format/workflow-format.md) | **格式说明**:每个字段怎么填(原 fields + control-flow 已并入) | 第一阶段起手 |
+| [extraction/phase1-skeleton.md](extraction/phase1-skeleton.md) | 第一阶段:搭骨架(判断有几个工序 / 切步骤 / 连数据流) | 第一阶段 |
+| [extraction/phase2-normalize.md](extraction/phase2-normalize.md) | 第二阶段:归类标注(分两个子助手并行干) | 第二阶段 |
+| [extraction/phase3-finalize.md](extraction/phase3-finalize.md) | 第三阶段:检查 + 渲染出网页 | 第三阶段 |
+
+### 格式与契约(format/)
+
+| 文件 | 内容 |
+|---|---|
+| [workflow-format.md](format/workflow-format.md) | **给人看的格式说明**(顶层结构 + 14 个字段 + 控制流 + 命名 + 校验;三阶段都依据) |
+| [case-data.schema.json](format/case-data.schema.json) | **给机器看的字段清单**(必填项/可选值的最终裁判) |
+
+### 分类词表(taxonomy/ —— 标注用的受控词表)
+
+| 文件 | 维度 | 规模 | 谁来读 |
+|---|---|---:|---|
+| [taxonomy/README.md](taxonomy/README.md) | — | — | 只给子助手读(主流程不碰) |
+| [effect.json](taxonomy/effect.json) | 作用 | 9 个词 | 只由 `phase-2a-normalizer` 子助手读 |
+| [action.json](taxonomy/action.json) | 动作 | 30+ 个词 | 同上 |
+| [type.json](taxonomy/type.json) | 类型 | 50 个词 | 同上;自造类型写进 `workflow.json` 的 `type_registry` |
+| [type_suggestions.md](taxonomy/type_suggestions.md) | 新类型登记 | 只增不改 | 第三阶段跑 `lint-case.py` 时**工具自动登记**,不用手写 |
+| `分类库导出_实质_*.json` | 实质 | 911 条 | 只由 `phase-2b-matcher` 子助手用脚本现查 |
+| `分类库导出_形式_*.json` | 形式 | 565 条 | 同上 |
+
+> ⚠ **主流程别碰词表**:上面这些大词表和查询脚本**只给子助手用**。主流程从头到尾**不要直接读它们,也不要自己调 `taxonomy-lookup.py`**——主流程只负责"切任务 + 派给子助手"。这样才不会把主流程的上下文撑爆。
+
+### 子助手定义(agents/ —— 第二阶段的两个并行助手)
+
+| 文件 | 角色 |
+|---|---|
+| [agents/phase-2a-normalizer.md](agents/phase-2a-normalizer.md) | 把"作用/动作/类型"归类到标准词 |
+| [agents/phase-2b-matcher.md](agents/phase-2b-matcher.md) | 把"实质/形式"匹配到大词表里的路径 |
+
+> 这两个文件的正文**就是子助手的完整工作方法**(唯一出处)。运行器(`run_procedure_dsl.py`)启动时自动加载它们,主流程**不用读**——主流程只管"召唤",方法由运行器装进子助手。`extraction/phase2-normalize.md` 只讲第二阶段怎么编排(切任务/派活/收结果),不重复这里的方法。
+
+### 模板 与 工具(templates/ + tools/)
+
+- [templates/workflow.template.json](templates/workflow.template.json):`workflow.json` 的填空骨架,复制一份改即可。
+- [tools.md](tools.md):各脚本(查词表 / 批量改 / 渲染 / 检查)的**接口手册**。脚本本身**不用读源码**,会用就行;渲染网页的样式(`renderer.py`/`styles.css`/`script.js`)也不用碰。
+
+---
+
+## 操作流程(给执行者的手册)
+
+整个流程围绕**一个文件 `workflow.json`** 滚动演化——从第一阶段搭好骨架,后面每阶段都在它上面**就地补字段**,不另存新文件。
+
+```
+第一阶段 · 搭骨架 ── 主流程全程在场
+   1.1 读懂案例, 判断有几个工序   → understanding.md
+   1.2 切步骤 + 填单步骨架        → 写出 workflow.json
+   1.3 把步骤间的数据流连起来      → 改 workflow.json(补"来源/去处")
+第二阶段 · 归类标注 ── 派两个子助手并行干, 都改同一个 workflow.json
+   2A 作用/动作/类型 归类(查分类词表)
+   2B 实质/形式 匹配(查大词表)
+   2C 自造类型登记 → 写进 type_registry
+第三阶段 · 检查收尾 ── 主流程调脚本
+   3.1 填"目的"列 + 渲染出网页
+   3.2 跑检查(类型完整性等)
+```
+
+### 起手(只做一次)
+
+把本文读**一遍**,之后**别再回头读它**——需要某阶段细节时直接读对应的阶段文件。再把 [`tools.md`](tools.md) 读一遍(后面要调的脚本接口都在那),也别重读。
+
+### 重要:读过的文件别重复读
+上下文是累积的,**你读过的文件内容会一直留在记忆里**。**不要**因为某处写了"详见 tools.md"就又去读一遍 tools.md;**不要**进了第二阶段又去重读阶段文件。需要时从记忆里翻,别重复 Read——那会白白浪费预算。
+
+### 第一阶段 · 搭骨架(新读这些)
+
+要做的事:通读案例 → 想清楚有几个工序、每个工序怎么走 → 切步骤 → 填骨架 → 把数据流连起来。
+
+| 该读(还没读过的) | 干嘛用 |
+|---|---|
+| [`format/workflow-format.md`](format/workflow-format.md) | 格式说明:14 个字段怎么填 + 控制流 + 命名 + 推断补全 |
+| [`extraction/phase1-skeleton.md`](extraction/phase1-skeleton.md) | 第一阶段具体怎么做 |
+| `input/case-{N}-raw.json` | 案例原文(你的素材) |
+
+产物(写到 `outputs/case-{N}/`):`understanding.md`(想清楚有几个工序)+ `workflow.json`(先 Write 骨架,再 Edit 补"来源/去处")。
+过关条件:workflow.json 自查通过(数据流都连上了、类型一致)→ 进第二阶段。
+
+### 第二阶段 · 归类标注(新读这些)
+
+要做的事:把"作用/动作/类型"归到分类词表的标准词,把"实质/形式"匹配到大词表的路径。
+
+| 新读 | 干嘛用 |
+|---|---|
+| [`extraction/phase2-normalize.md`](extraction/phase2-normalize.md) | 第二阶段怎么切任务、派子助手 |
+| [`taxonomy/effect.json`](taxonomy/effect.json) / [`action.json`](taxonomy/action.json) / [`type.json`](taxonomy/type.json) | 三张分类词表(子助手读) |
+| [`taxonomy/type_suggestions.md`](taxonomy/type_suggestions.md) | 新类型登记格式(看一眼即可) |
+
+**别读**:已读过的第一阶段清单;以及那两张超大词表 `分类库导出_*.json`(太大,走 `taxonomy-lookup.py` 现查)。
+
+产物:在 `workflow.json` 上 **Edit** 补 作用/动作/类型 + 实质/形式 + 自造类型登记。**不要另存新文件**。
+过关条件:每步的作用/动作都命中标准词、每步的实质/形式都校验通过 → 进第三阶段。
+
+### 第三阶段 · 检查 + 渲染(新读这些)
+
+要做的事:填"目的"列 → 跑检查 → 渲染出网页(脚本自动组装,不另存中间文件)。
+
+| 新读 | 干嘛用 |
+|---|---|
+| [`extraction/phase3-finalize.md`](extraction/phase3-finalize.md) | 检查清单 + "目的"列怎么填 |
+| [`format/case-data.schema.json`](format/case-data.schema.json) | 字段的机器清单(最终裁判) |
+
+(格式说明 workflow-format.md 第一阶段已读过,不用重读。)
+
+脚本命令:
+```bash
+# 1. 检查 + 自动登记新类型(轻量, 不卡流程)
+python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N}
+
+# 2. 渲染网页(脚本在内存里组装好数据直接出 HTML)
+python spec/tools/render-case.py \
+    --workflow outputs/case-{N}/workflow.json \
+    --source-input input/case-{N}-raw.json \
+    --page-title "Case {N} · <主题>" \
+    --case-id {N} \
+    --out outputs/case-{N}/case-{N}-<slug>.html
+```
+
+产物:`outputs/case-{N}/case-{N}-<slug>.html`(唯一产物)。
+
+### 每次 Read 前自查
+
+- 这个文件**之前读过吗**?读过就别再读。
+- 只想确认"提没提过某概念"?用 Grep,别整篇 Read。
+- 只想看"目录里有啥"?用 Glob。
+- 中断后接着做:用户**可能改过**的产物(understanding.md / workflow.json)要重读;spec 没变,不用重读。
+
+### 卡住了怎么办
+
+某阶段的过关条件过不去 → **别硬闯下一阶段**,回当前阶段修。修两次还过不去 → 在产物里挂个 `inferred: true, inferred_reason: "反复过不去, 需人工看"` 标记,再往下走。

+ 35 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/agents/phase-2a-normalizer.md

@@ -0,0 +1,35 @@
+---
+description: Phase 2A 专家(作用/动作/类型 归一化)。用于读取 task_2a.json,对照 spec 字典树归一化 effect/action/type,维护工序级 type_registry,并产出 patch_2a.json。
+model: sonnet
+tools: Read, Grep, Glob, Write, Edit, Bash
+---
+你是 `phase-2a-normalizer` 子助手,负责第二阶段的"作用 / 动作 / 类型 归类"。这份说明就是你的完整工作方法,不用再去读别的文件。
+
+**你的输入**:
+- 任务切片 `outputs/case-N/_scratch/task_2a.json`(把 `case-N` 换成实际 case 目录)—— 含待处理的步骤与 IO 变量、随附图集。
+- 三棵字典树(都很小,整读;每个节点带 `分类说明` 边界注解):`{spec}/taxonomy/effect.json`(作用,9 叶)、`{spec}/taxonomy/action.json`(动作,5 个 L1 + 控制)、`{spec}/taxonomy/type.json`(类型,4 大类)。
+
+**任务**:
+- **作用归一**:每步"在哪个工艺位置"映射到 effect.json 叶子之一(工艺规约 / 预准备 / 预处理 / 主体生成 / 装配 / 后期 / 配套伴生 / 检验 / 交付)。必须命中;命不中 = Phase 1 抽错,回报主 Agent。
+- **动作归一**:每步 action 自然语言映射到 action.json 树路径(如 `提取/化学提取/反推`、`生成/元素生成`)。
+- **类型归一**(对每个 input/output 的 type,走以下 funnel,不要省步骤):
+  1. **候选扩展**:基于 IO 的 `name` + `value`,显式列 **3-5 个候选 type 词**(不是只猜一个)。
+     - 例:value=`<图: 苏晚 25 岁年轻女性肖像, 卧室床上>` → 候选 `[参考图, 主角图, 人物肖像, 人物参考, 分镜图]`
+     - 候选要覆盖**不同抽象层**:通用(参考图)+ 具体(主角图)+ 邻近(分镜图),让匹配有挑选余地。
+  2. **字典匹配**(按优先级,命中即停):
+     - **a. 命中 type.json 叶子**(`$leaves`):候选里哪个直接命中叶子就用它(如候选含"参考图" → 命中)。
+     - **b. extends 桥接**:都没命中但有候选语义贴近某叶子 → 选最近 leaf 做 extends,在该 procedure 的 `type_registry` 注册(每个 procedure 独立 type_registry,单 case 多工序不冲突)。格式 `{"主角图": {"extends": "参考图", "desc": "case-specific 主角肖像"}}`。⚠ 必须注册到 **procedure 顶层 `type_registry`**,不要只在 IO item 内 inline 写 extends —— renderer 只读顶层 type_registry,不读 IO inline 字段。
+  3. **不必手工写 type_suggestions.md**:Phase 3 跑 `lint-case.py --workflow` 时会自动扫每个 procedure 的 `type_registry`,把 case-specific entry record 进 `{spec}/taxonomy/type_suggestions.md`(幂等,同 `(type_name, case_id)` 只写一次)。你只要保证每个 type_registry entry 含 `extends` + `desc`。
+  4. **自查**:每个 IO 的 type 要么命中叶子、要么所在 procedure 的 type_registry 有该 type 的 extends+desc 项;**不允许** type 写"自由名"却缺 type_registry entry —— 这种 silent gap 会让 Phase 3 渲染 HTML 时 drawer metadata 全丢(Phase 3 lint-case.py 会捕捉到)。
+
+**输出**:产出 `outputs/case-N/_scratch/patch_2a.json` —— 一个 `{"path": ..., "value": ...}` 对象的**扁平 JSON 数组**(即 `wf-patch.py` 契约,由主 Agent 统一应用落盘,**你不直接改 workflow.json**)。给每个 step 填 `effect` / `action`,给每个 IO 填 `type`(Phase 1.2 已有则归一,没有则填),type_registry 注册用 `pN.type_registry.X.extends` / `.desc` 路径。示例:
+```json
+[
+  {"path": "p1.s1.effect", "value": "预处理"},
+  {"path": "p1.s1.action", "value": "提取/化学提取/反推"},
+  {"path": "p1.s1.inputs[0].type", "value": "参考图"},
+  {"path": "p1.type_registry.主角图.extends", "value": "参考图"},
+  {"path": "p1.type_registry.主角图.desc", "value": "case-specific 主角肖像"}
+]
+```
+不要输出任何其它嵌套结构。不写新文件,不写生成脚本,不改动任何其它文件。

+ 43 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/agents/phase-2b-matcher.md

@@ -0,0 +1,43 @@
+---
+description: Phase 2B 专家(实质/形式 词表匹配)。用于读取 task_2b.json,调 taxonomy-lookup.py 查每个 IO 变量的实质/形式路径,并产出 patch_2b.json。
+model: sonnet
+tools: Read, Grep, Glob, Write, Edit, Bash
+---
+你是 `phase-2b-matcher` 子助手,负责第二阶段把**每一步**的"实质 / 形式"匹配到大词表里的路径。这份说明就是你的完整工作方法,不用再去读别的文件。
+
+**你的输入**:
+- 任务切片 `outputs/case-N/_scratch/task_2b.json`(把 `case-N` 换成实际 case 目录)—— `items_to_match` 是**每个 step 一项**(实质/形式现在是 step 级,不再逐 IO 标),含该步 `path`(pN.sM)+ `intent` + `content`(整步 input/output 内容合并)+ 随附图集 `image_url_list` / `related_images`。
+- 工具 `{spec}/tools/taxonomy-lookup.py`。实质·形式 JSON 词表本身**不进 context**,完全通过 tool 查询。
+
+**tool 接口**:
+```
+{spec}/tools/taxonomy-lookup.py --dim {实质|形式} --list-l2                  # 列二级路径
+{spec}/tools/taxonomy-lookup.py --dim {实质|形式} --subtree <path>           # 返回子树(叶子 + alias)
+{spec}/tools/taxonomy-lookup.py --dim {实质|形式} --match "<tok1 tok2 ...>"  # 多 token 拆词聚合(推荐用法)
+{spec}/tools/taxonomy-lookup.py --dim {实质|形式} --narrow "<tok1 tok2 ...>" # 层级下钻(--match miss 兜底)
+{spec}/tools/taxonomy-lookup.py --dim {实质|形式} --validate <path>          # 校验路径存在
+```
+
+**任务**(对每个 step,即 items_to_match 每项的 `content`):
+1. **从 content 抽 2-5 个 ≥2 字描述性 token**,一次调用 `--match "tok1 tok2 tok3"`(空格分隔,tool 自动拆词聚合)。
+   - 好例:value=`<图: 苏晚 25 岁年轻女性肖像, 卧室床上>` → `--match "年轻女性 卧室 床上 肖像"`
+   - 不要一个个单 token 试错 —— tool 内部已做拆词聚合 + coverage bonus。
+   - ⚠ **避坑①·禁抽生产方式词**:不要抽工具名(`AI`、`Midjourney`、`SD`)、生产动词(`生成`、`合成`、`制作`、`处理`)、容器类型词(`图片`、`视频`、`文本`)—— 这些词在词表里有有效路径,但描述的是**生产手段 / 载体**,不是内容实质 / 呈现形式,会命中错误节点(如 `AI生成合成`)。只抽「这个数据**是什么主题 / 主体**」的词。坏例 `<AI生成的古风女性人物图:绿色薄纱…>` → ❌ `--match "AI生成"` → ✅ `--match "古风女性 薄纱 人物"`。
+2. **若 `--match` 返(无匹配)** → 同 query 切 `--narrow` 走层级下钻(按子树整体语义打分)。
+3. 拿到 top 候选后,用 `--subtree <候选>` 列叶子细节,选最贴的。
+4. `--validate <chosen_leaf>` 确认后再写回;完全无法匹配 → `unmatched`。
+5. 抽象容器 / 纯工具参数 → null(不标)。
+   - ⚠ **避坑②·勿过度标 null**:`产品需求`、`结构化提示词`、`分层提示词` 等文本,物理形式上虽是"文本",但**实质上承载具体业务内容**(提示词描述冲锋衣 → 实质 `/理念/知识/商业/产品服务/产品特征`;描述登山场景 → `/理念/知识/商业/产品服务/使用场景`),**决非纯工具参数**,必须为其匹配对应实质路径。
+   - 只有**完全不含具体业务实体、纯粹的技术参数**(逻辑判断布尔值、循环索引 `i`、纯控制流指令等)才允许设为 `null`。
+
+⚠ **避坑③·别塞整段**:不要把整段 value 描述塞进 `--match`(如 `--match "苏晚 25 岁年轻女性, 卧室床上, 湿发素颜"`),标点会被当 token 一部分干扰拆词。提炼 2-5 个干净的描述性词组即可。
+
+**输出**:产出 `outputs/case-N/_scratch/patch_2b.json` —— 一个 `{"path": ..., "value": ...}` 对象的**扁平 JSON 数组**(即 `wf-patch.py` 契约,由主 Agent 统一应用落盘,**你不直接改 workflow.json**)。给每个 **step** 填 `substance` + `form`(单条 `/xxx/yyy`、多条 JSON 数组 `["/a", "/b"]`、或 null)。设 null 用 JSON null(CLI 传 `__null__`);多路径推荐用 ` + ` 连接(如 `/表象/视觉/人物 + /表象/视觉/空间`),`wf-patch.py` 会校验并存为数组。示例(路径是 step 级 `pN.sM.substance`,**不是** IO 级):
+```json
+[
+  {"path": "p1.s1.substance", "value": "/理念/知识/思想/概念范畴/性质属性/功能效用"},
+  {"path": "p1.s1.form", "value": "/呈现/视觉/视觉制作/构图编排/版面设计/版面结构"},
+  {"path": "p1.s2.substance", "value": ["/理念/知识/商业/前沿技术/AI智能/AI应用", "/理念/知识/思想"]}
+]
+```
+不要输出任何其它嵌套结构。不写新文件,不写生成脚本,不改动任何其它文件。

+ 61 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/extraction/phase1-skeleton.md

@@ -0,0 +1,61 @@
+## 第一阶段 · 搭骨架
+
+> 整体流程见 [README](../README.md);每个字段怎么填见 [格式说明](../format/workflow-format.md)。本文只讲第一阶段怎么做。
+>
+> 这一阶段**主流程自己全程做**,不派给子助手。因为"怎么切步骤、补哪些没写的环节、怎么把数据流连起来"这三件事是连在一起的——靠的是同一份"我读懂了这篇案例"的理解,换个助手就得重读原文、重新理解,既费劲又容易前后不一致。
+
+分三小步:
+
+| 小步 | 做什么 | 产出 |
+|------|------|------|
+| **1.1** | **读懂 + 判断有几个工序** —— 通读原文(含配图)想清楚:(a) 这篇案例里有**几条独立的做法**(一条还是多条);多条时,把每条的名字、最终产物、大概几步、属于什么工艺各列出来。(b) 认出最终产物、用到的外部工具、以及那些"没明说但少不了"的前置准备。 | `understanding.md`(按工序分章节写) |
+| **1.2** | **切步骤 + 填单步骨架** —— 一次性写出 `workflow.json` 骨架:顶层是 `procedures` 数组,每个工序含 `id / name / purpose / category / platform / author / declarations / steps`。每一步先填:编号 / 类型(普通步还是控制块) / 动作(先用大白话写)/ 工具 / 指令 / 输入 / 输出(含类型、值,**每个输出起个编号如 s2o1**;"来源/去处"先空着)/ 目的 / focus。原文没写、你补出来的输入输出,标上 `inferred: true` 和原因。**"作用、类型归类、实质、形式"这些留到第二阶段填**,这一步别填。 | `workflow.json`(骨架版) |
+| **1.3** | **把数据流连起来** —— 给每个输入输出补上"来源/去处":输入写 `← 上游某输出的编号`(如 `← s2o1`)、`← 工序输入`、`← 某编号[i]`(循环里逐个取);输出写 `→ sN`、`→ 某列表.追加`。连完自查:每个输入引用的编号都能在前面找到对应输出。连错就回 1.2 改。几十处要连时用 `wf-patch.py` 一次过(见下),别写脚本硬塞。 | `workflow.json`(补好"来源/去处") |
+
+### 1.1 怎么判断"有几个工序"
+
+⚠ 跟原文的章节标题无关:不管原文把某段叫"案例示范"还是"进阶玩法",只要满足下面三条,就算一条独立工序。**判断的单位是"一条完整的 输入→最终产物 链",不是原文的段落结构。**
+
+**怎么扫**:以原文里**每一张出现的成品图**(或明确写出的最终产物)为起点,逐个看它有没有对应的"输入→做法"链条。有就记为一个候选工序,再用下面三条筛。**别按段落扫。**
+
+1. 有明确产物:这条链能产出一个看得见的结果(图、素材、成品)。
+2. 有具体做法:链条里有可操作的方法(提示词、框架、流程)。
+3. 产物或做法有差异:跟别的工序比,产物不同 **或** 做法不同,满足一条即可。哪怕产物类型一样(都是场景图),只要提示词不同,就算两个工序,**不能合并**。
+
+边界判断:
+- 同一条链内部的中间步骤,归进这条工序,不单拆(比如做海报时先生成背景图,背景图是中间步骤,不是独立工序)。
+- 只展示了成品、完全没讲输入和做法的,不算工序。
+- 产物类似但做法不同 → 算两个工序。**不能**因为"产物类型相同""方法论相似"就合并。
+
+### 1.2 哪些"没写出来"的要主动补
+
+原文常省略一些理所当然的输入输出,你要补上:
+- **工具常识**:生成模型一般要带模型/参数;召回要有检索依据;视频生成要有主角图/分镜图当参考。
+- **前后对不上**:下游用到了 X 但上游没产出 X → 是不是漏抽了?某个输出后面没人用 → 是不是漏了使用它的步骤?
+- **工艺常识**:短剧 = 分镜图 → 视频片段 → 拼接;建素材库 = 收集 + 入库 + 建索引。
+
+补出来的输入输出标上 `inferred: true` 和原因(让后面复核),别悄悄塞进去。具体标法见[格式说明](../format/workflow-format.md)第三节。
+
+### 1.2 有循环/并行/分支怎么切
+
+原文里如果有"对每个 X 重复""同时做几个版本""分情况",切步骤时要展开成**控制块 + 子步**,别硬压成一个步骤;循环里取数据/攒结果走"来源/去处"的 `[i]`、`.追加`。详见[格式说明](../format/workflow-format.md)第四节。
+
+### 1.3 连数据流时自查这几条
+
+- 每个输入的"来源"(`← 某编号`)都能找到已存在的输出编号,或是 `← 工序输入`、字面量。
+- 输入的类型,和它"来源"指向的那个输出的类型一致。
+- 循环索引用在合理位置(`[i]` 在循环里,`[-1]` 指最近一项)。
+- 接力/链式引用关系正确。
+
+### 1.3 怎么批量连(重要)
+
+`workflow.json` 由你**直接演化,绝不写 Python 脚本去生成/批改它**(脚本拼 JSON 容易踩转义坑、把文件弄坏)。几十处"来源/去处"用 `wf-patch.py` 一次搞定:
+
+1. 把要改的清单写到 `_scratch/anchors.json` —— `[{"path":"p1.s1.inputs[0].anchor","value":"← s0o1"}, ...]`,**每条都是你的判断**(连到哪个编号是语义决定,不是机械套用);
+2. 跑 `python spec/tools/wf-patch.py --workflow workflow.json --patch _scratch/anchors.json`。
+
+工具负责安全写 JSON + 检查格式(有一条不合法就整批不写),你从不直接碰 JSON 文本。零星单处改,用 Edit 就行。路径写法见 [tools.md](../tools.md)。
+
+### 1.3 内容自动抄写(省得手抄)
+
+"来源"连好后,跑一次 `python spec/tools/wf-patch.py --workflow workflow.json --resolve-passthrough`。对那些"原样接收上游输出"的输入(来源是 `← 某编号`),你**不用手抄上游内容**——只在源头那个输出里填一次真内容,工具会顺着编号把它逐字抄到所有引用处("值"先留空即可)。**别把"(同上)"这种引用当最终内容留着**(检查会报,见[格式说明](../format/workflow-format.md)第二节"值")。

+ 50 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/extraction/phase2-normalize.md

@@ -0,0 +1,50 @@
+## 第二阶段 · 归类标注(主流程派两个子助手并行干)
+
+这一阶段要把第一阶段填的大白话**归到标准词**:每步的"作用/动作/类型"对到分类词表,每步的"实质/形式"对到大词表的路径。
+
+### 为什么要派子助手
+
+这些归类要查很大的词表、跑几十次匹配。**主流程不自己干**——它带着一堆配图和第一阶段的长篇推理,上下文很重;让它再去翻词表会撑爆。所以主流程把活**切成小任务,派给两个轻量子助手并行做**,自己只负责切任务、派活、收结果。
+
+**主流程的步骤**:
+
+1. **切任务**:跑切片脚本,它会在 `_scratch/` 下生成两个最小任务文件 `task_2a.json` 和 `task_2b.json`(只含子助手需要的步骤/数据 + 相关配图)。
+   ```bash
+   python spec/tools/prepare-subtask.py --workflow outputs/case-N/workflow.json --source input/case-N.json --out-dir outputs/case-N/_scratch
+   ```
+2. **派活**:召唤两个子助手并行做(下面"怎么召唤")。
+3. **收结果**:子助手各自产出一份补丁 `patch_2a.json` / `patch_2b.json`,主流程用 `wf-patch.py --patch` 一次性应用到 `workflow.json`。
+
+> ⚠ 主流程**绝对不要**自己去跑 `taxonomy-lookup` 查词、或自己手动归类——那是子助手的活。主流程只切任务、派活、收补丁。
+
+### 两个子助手是谁
+
+它们的完整工作方法写在 `agents/` 下的两个文件里(运行器启动时自动加载成子助手,主流程**不用读**):
+
+| 子助手 | 干什么 | 产出 |
+|---|---|---|
+| `phase-2a-normalizer` | 把每步的 作用/动作 归到标准词;把每个输入输出的 类型 归到词表或登记自造类型 | `patch_2a.json` |
+| `phase-2b-matcher` | 把**每一步**(整步)的 实质/形式 匹配到大词表路径 | `patch_2b.json` |
+
+### 怎么召唤
+
+用 `Agent`(或 `Task`)工具,`subagent_type` 直接填子助手的注册名——这样它在 `agents/` 里的正文会作为它的工作说明生效,所以**召唤时只要点明做哪个 case 就行,不用重复方法**:
+
+```
+Agent(subagent_type="phase-2a-normalizer",
+      description="处理 case-N 的 2A",
+      prompt="处理 case-N 的 2A。任务文件在 outputs/case-N/_scratch/task_2a.json,完成后写 patch_2a.json 并汇报改了哪些。")
+Agent(subagent_type="phase-2b-matcher",
+      description="处理 case-N 的 2B",
+      prompt="处理 case-N 的 2B。任务文件在 outputs/case-N/_scratch/task_2b.json,完成后写 patch_2b.json 并汇报改了哪些。")
+```
+
+> ⚠ **别用 `subagent_type="Explore"` 再在正文里喊名字**——那起的是通用助手,会绕过注册的工作说明。直接把注册名填进 `subagent_type` 才对。
+
+收到两份补丁后,主流程应用并落盘:
+```bash
+python spec/tools/wf-patch.py --workflow outputs/case-N/workflow.json --patch outputs/case-N/_scratch/patch_2a.json
+python spec/tools/wf-patch.py --workflow outputs/case-N/workflow.json --patch outputs/case-N/_scratch/patch_2b.json
+```
+
+> 改子助手的方法,去改 `agents/` 下对应的文件,别在本文重写(避免两处说法打架)。本文只管"第二阶段怎么编排:切任务 → 派活 → 收补丁"。

+ 32 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/extraction/phase3-finalize.md

@@ -0,0 +1,32 @@
+## 第三阶段 · 检查 + 渲染
+
+> 这一阶段主流程自己调脚本完成。前两阶段已经把内容都填进了 `workflow.json`,这里只做三件事:补"目的"列、跑检查、渲染出网页。**产物只有网页(HTML),纯文本 `.md` 已取消。**
+
+| 小步 | 做什么 |
+|------|------|
+| **3.1 填"目的"列** | 在 `workflow.json` 上给每一步补/改 `intent`(≤25 字的一句话)。用这一行已有的值拼成 `{类别:值}` 标记,合法类别只有 `effect / via / act / in-type / out-type` 五个。**别用变量名、别写成公式或代码**。这一步要跨步骤一起看(为了让每行的"目的"各有侧重),所以不派子助手。具体写法见[格式说明](../format/workflow-format.md)第六节。 |
+| **3.2 检查 + 渲染** | 跑两个脚本:① `lint-case.py` 检查类型完整性、内容有没有偷懒写引用,并自动登记新类型;② `render-case.py` 渲染出网页(脚本在内存里组装数据,不另存中间文件)。检查报问题就回第二阶段对应步骤改。 |
+
+```bash
+python spec/tools/lint-case.py --workflow outputs/case-N/workflow.json --case-id N
+python spec/tools/render-case.py --workflow outputs/case-N/workflow.json \
+    --source-input input/case-N.json --page-title "Case N · 主题" --case-id N \
+    --out outputs/case-N/case-N-<slug>.html
+```
+
+### 收尾检查清单
+
+下面每条都要过,过不去就回对应步骤改:
+
+| 检查 | 规则 | 反面例子 |
+|------|------|------|
+| **输出编号唯一** | 每个输出都有编号,且工序内不重复 | 两个输出都叫 `s2o1` |
+| **数据流连得上** | 每个输入的"来源"(`← 某编号`)都能找到已存在的输出编号(或 `← 工序输入`、字面量) | 引用了 `← s2o9` 但根本没有这个编号 |
+| **类型对得上** | 输入的类型,和它"来源"指向的那个输出的类型一致 | 输入写 `分镜图` 但来源那个输出是 `参考图` |
+| **循环索引合理** | `[i]`/`[-1]` 用在循环里或合理位置 | 不是循环却用了 `[i]` |
+| **"值"写真内容** | "值"写数据本身(文字写全文;图片视频用 `<整段描述>`);不写 `← sN` 引用、不写 `[图N显示]` 这种说明 | 值 = `← s1o1`;值 = `<描述>开头的` |
+| **作用/动作命中词表** | 作用是 9 个标准词之一;动作是动作词表里的路径 | 作用写成"开端"(词表里没有) |
+| **类型命中词表或挂靠** | 类型是词表里的词,或自造但在本工序 `type_registry` 里写了"算作"哪个标准词 | 类型写"小品"却没说挂靠 `视频成品` |
+| **自造类型登记齐全**(脚本自动查) | 跑 `lint-case.py`,若提示"类型完整性 N 个问题",说明有自造类型没在 `type_registry` 登记 / 缺挂靠 / 缺说明 → 回去补 | `s1 输出的 type='主角图' 是自造但没登记` |
+| **实质/形式 路径合法** | 整步的实质/形式走 `taxonomy-lookup.py --validate` 校验;不适用可留空 | `/视觉/人物`(缺最顶层那段) |
+| **"目的"列规范** | ≤25 字一句话;标记取自本行真实有的值;合法类别 5 个;别写成公式 | `{act:反推}: {in-type:视频} → {out-type:提示词}`(写成公式了) |

+ 268 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/format/case-data.schema.json

@@ -0,0 +1,268 @@
+{
+  "$schema": "https://json-schema.org/draft/2020-12/schema",
+  "$id": "https://procedure-dsl/spec/format/case-data.schema.json",
+  "title": "Procedure DSL · case_data",
+  "description": "Canonical structure consumed by spec/tools/renderer.build_html(case_data) -> str. 一篇 case 可含 1 ~ N 个独立工序 (procedures), 共享同一份 source 原帖. 单工序 case 也用 procedures 数组长度 1 的形式 — schema 不区分.",
+  "type": "object",
+  "required": [
+    "page_title",
+    "source",
+    "procedures"
+  ],
+  "additionalProperties": false,
+  "properties": {
+    "page_title": {
+      "type": "string",
+      "description": "HTML <title> + <h1>. e.g. 'Case 5 · 产品宣传图 AI 工作流可视化'"
+    },
+    "case_id": {
+      "type": ["integer", "string", "null"],
+      "description": "Optional case identifier shown in UI badge."
+    },
+    "source": {
+      "$ref": "#/$defs/Source",
+      "description": "case-level 原帖信息, 跨所有 procedures 共享 (一篇文章对应一份 source)."
+    },
+    "procedures": {
+      "type": "array",
+      "minItems": 1,
+      "description": "一篇 case 包含的工序数组. 多工序场景 (e.g. case-5 '简单工作流 + 进阶工作流 + 附加案例'). 单工序 case 也用长度 1 数组. 每个 procedure 独立含 declarations / steps / type_registry / return_row.",
+      "items": { "$ref": "#/$defs/Procedure" }
+    }
+  },
+
+  "$defs": {
+
+    "Procedure": {
+      "type": "object",
+      "description": "一个独立工序: 工序头部 (name/purpose/...) + declare 块 + 步骤 + 返回行. 一个 procedure 内的 type_registry 是该工序的 case-specific 类型扩展.",
+      "required": ["id", "name", "purpose", "category", "platform", "author", "declarations", "steps"],
+      "additionalProperties": false,
+      "properties": {
+        "id":       { "type": "string", "description": "procedure 局部 id (单 case 内唯一). e.g. 'p1' / 'p1-simple' / 'p2-advanced'." },
+        "name":     { "type": "string", "description": "工序名称, e.g. '简单工作流: 一步生成'." },
+        "purpose":  { "type": "string", "description": "One-sentence intent (该工序在做什么)." },
+        "category": { "type": "string", "description": "Top-level taxonomy, e.g. '产物创造'." },
+        "platform": { "type": "string", "description": "原帖来源 platform; 通常跟 case-level source.platform 一致." },
+        "author":   { "type": "string", "description": "原作者; 通常跟 case-level source.author 一致." },
+        "declarations": { "$ref": "#/$defs/Declarations" },
+        "type_registry": {
+          "type": "object",
+          "description": "Per-procedure case-specific type entries; 渲染期跟 spec/taxonomy/type.json 的 stdlib 叶子合并 — case 项覆盖 stdlib 项. 跨工序共享的 case-specific type 可在多个 procedure 各自声明 (允许冗余).",
+          "additionalProperties": { "$ref": "#/$defs/TypeRegistryEntry" }
+        },
+        "steps": {
+          "type": "array",
+          "description": "工序的步骤数组, 按执行顺序排. block/step 在顶层; nested 子项 kind:nested + group 指向父 block id.",
+          "items": { "$ref": "#/$defs/Step" }
+        },
+        "return_row": { "$ref": "#/$defs/ReturnRow" }
+      }
+    },
+
+    "Declarations": {
+      "type": "object",
+      "description": "工序的声明: declared inputs / resources / return type. 渲染成 declare 折叠块.",
+      "required": ["inputs", "resources", "returns"],
+      "additionalProperties": false,
+      "properties": {
+        "inputs": {
+          "type": "array",
+          "items": { "$ref": "#/$defs/DeclareItem" },
+          "description": "Caller-provided inputs to the procedure."
+        },
+        "resources": {
+          "type": "array",
+          "items": { "$ref": "#/$defs/DeclareItem" },
+          "description": "Long-lived resources (libraries, knowledge bases) read or written across runs."
+        },
+        "returns": { "$ref": "#/$defs/DeclareReturn" }
+      }
+    },
+
+    "DeclareItem": {
+      "type": "object",
+      "required": ["type", "name"],
+      "additionalProperties": false,
+      "properties": {
+        "type":    { "type": "string", "description": "Type leaf (§A.3) or case-extended type." },
+        "name":    { "type": "string" },
+        "default": { "type": "string", "description": "Optional default value/template." },
+        "desc":    { "type": "string", "description": "Optional human description." }
+      }
+    },
+
+    "DeclareReturn": {
+      "type": "object",
+      "required": ["type"],
+      "additionalProperties": false,
+      "properties": {
+        "type": { "type": "string" },
+        "note": { "type": "string", "description": "e.g. 'extends 视频成品 (序列关系)'." }
+      }
+    },
+
+    "Source": {
+      "type": "object",
+      "description": "case-level 原帖信息. 渲染成 foldable 折叠块 (default closed). 跨所有 procedures 共享.",
+      "required": ["platform", "author", "date", "title", "excerpt"],
+      "additionalProperties": false,
+      "properties": {
+        "platform":    { "type": "string" },
+        "author":      { "type": "string" },
+        "date":        { "type": "string", "description": "Free-text date, e.g. '2026 上半年'." },
+        "url":         { "type": ["string", "null"], "description": "原帖 URL; 没有干净 URL 时填 null 或省略 (不强制 uri 格式)." },
+        "title":       { "type": "string" },
+        "excerpt":     { "type": "string", "description": "1-2 sentence pipeline summary." },
+        "body_text":   { "type": "string", "description": "Optional full body of the source article." },
+        "cover_image": { "type": "string", "description": "Optional cover image URL." }
+      }
+    },
+
+    "TypeRegistryEntry": {
+      "type": "object",
+      "description": "Case-specific 类型定义 (procedures[*].type_registry). 桥接到一个 stdlib 叶子 + 人类可读描述.",
+      "required": ["extends", "desc"],
+      "additionalProperties": false,
+      "properties": {
+        "extends": { "type": "string", "description": "桥接到的 stdlib 叶子名 (spec/taxonomy/type.json $leaves 之一)." },
+        "desc":    { "type": "string", "description": "case-specific 类型的人类可读说明 (renderer drawer + type_suggestions 用)." }
+      }
+    },
+
+    "Step": {
+      "type": "object",
+      "description": "One row group in the 14-column procedure table. Renders to N <tr> where N = max(len(inputs), len(outputs), 1). effect/action MUST hit canonical leaves per spec §A; substance/form are STEP-LEVEL taxonomy paths (whole step's content, not per-IO). kind=block is a control container (effect/action/substance/form may be omitted; carries intent + via='-' + io); kind=nested/step are execution steps.",
+      "required": ["id", "kind", "via", "inputs", "outputs", "intent"],
+      "additionalProperties": false,
+      "properties": {
+        "id": {
+          "type": "string",
+          "pattern": "^s\\d+(\\.\\d+)*$",
+          "description": "Step id. Plain step / block / nested use 's' prefix (block children dotted, e.g. 's3.1')."
+        },
+        "kind": {
+          "enum": ["step", "block", "nested"],
+          "description": "step=plain; block=control-flow parent (grouping container); nested=child of a block."
+        },
+        "group": {
+          "type": "string",
+          "description": "When kind=nested, the parent block's id (e.g. 's3')."
+        },
+        "effect": {
+          "enum": [
+            "预处理", "主体生成", "装配", "后期",
+            "工艺规约", "预准备", "配套伴生", "检验", "交付"
+          ],
+          "description": "§A.1 L3 leaf. Required on step/nested — non-leaf = extraction error."
+        },
+        "substance": {
+          "type": ["string", "array", "null"],
+          "items": { "type": "string" },
+          "description": "STEP-LEVEL. What this step's content IS (理念 vs 表象 layer). Path from `分类库导出_实质_*.json`. Single path string, array of path strings, or null."
+        },
+        "form": {
+          "type": ["string", "array", "null"],
+          "items": { "type": "string" },
+          "description": "STEP-LEVEL. How this step's content is PRESENTED (呈现 vs 架构 layer). Path from `分类库导出_形式_*.json`. Single path string, array of path strings, or null."
+        },
+        "via": {
+          "type": "string",
+          "description": "Canonical L1 tool name (manus / nano_banana_pro / human / <llm-agent>) or generic placeholder for unspecified tools ('(AI 生图工具)'). Use '-' for control-flow blocks."
+        },
+        "action": {
+          "type": "string",
+          "pattern": "^[^/]+(/[^/]+)*$",
+          "description": "§A.2 path, e.g. '生成/元素生成', '提取/化学提取/反推'."
+        },
+        "directive": {
+          "type": "string",
+          "description": "字面 prompt 文本 — 真正喂给工具的 prompt 字符串. 人工/控制流 step 无 prompt 时省略或空串."
+        },
+        "inputs":  {
+          "type": "array",
+          "items": { "$ref": "#/$defs/IOItem" }
+        },
+        "outputs": {
+          "type": "array",
+          "items": { "$ref": "#/$defs/IOItem" }
+        },
+        "intent": {
+          "type": "string",
+          "description": "≤ ~25 chars natural-language sentence. Tokens `{kind:value}` with kind ∈ {effect, via, act, in-type, out-type}. NEVER use variable-name tokens, NEVER use 'X: Y → Z' pseudo-code."
+        },
+        "focus": {
+          "type": "array",
+          "items": { "type": "string" },
+          "description": "Column-cell keys to highlight on this row. Format: bare key for step-level cells ('via', 'action', 'effect', 'substance', 'form', 'idx', 'intent'), or '<col>-<io_index>' for IO cells ('in-type-0', 'out-type-1', etc.)."
+        }
+      },
+
+      "allOf": [
+        {
+          "if": { "properties": { "kind": { "enum": ["step", "nested"] } } },
+          "then": { "required": ["effect", "action"] }
+        },
+        {
+          "if": { "properties": { "kind": { "const": "nested" } } },
+          "then": { "required": ["group"] }
+        }
+      ]
+    },
+
+    "IOItem": {
+      "type": "object",
+      "description": "One row in inputs[] or outputs[]. Outputs carry an `id` (the 1:1 reference handle other steps point to); inputs reference an upstream output's id in their anchor.",
+      "required": ["type", "value", "anchor"],
+      "additionalProperties": false,
+      "properties": {
+        "id": {
+          "type": "string",
+          "description": "Short machine handle, unique within the procedure. REQUIRED on outputs (the reference target). Convention: 's<step>o<n>' (e.g. 's2o1'); single-output step may use 's<step>'. Inputs omit it. NOT a display column — surfaces only inside anchors."
+        },
+        "type": {
+          "type": "string",
+          "description": "§A.3 leaf or case-extended type name."
+        },
+        "value": {
+          "type": "string",
+          "description": "Content itself. Text data: full prose, no wrappers. Non-text data: '<整段描述>' (the whole description angle-bracketed). NEVER metadata ('[图 N 显示]', '原文: ...') or upstream refs ('← s2o1' — those go in anchor)."
+        },
+        "anchor": {
+          "type": "string",
+          "description": "Data-flow link by id. Inputs: upstream ref ('← 工序输入', '← s2o1' 指向某 output 的 id, '← s2o1[i]' 容器索引). Outputs: downstream destination ('→ s5', '→ 视频片段列表.追加', '→ 返回 X')."
+        },
+        "inferred": {
+          "type": "boolean",
+          "description": "True when this whole IO item was filled by 工艺补全 (not in source material). Renderer dyes the row's data-flow cells."
+        },
+        "inferred_reason": {
+          "type": "string",
+          "description": "REQUIRED when inferred=true. Shown on hover."
+        }
+      },
+      "if": {
+        "required": ["inferred"],
+        "properties": { "inferred": { "const": true } }
+      },
+      "then": { "required": ["inferred_reason"] }
+    },
+
+    "ReturnRow": {
+      "type": "object",
+      "description": "Bottom row of the table announcing what the procedure returns.",
+      "required": ["arrow", "text"],
+      "additionalProperties": false,
+      "properties": {
+        "arrow": {
+          "type": "string",
+          "description": "Usually '↩'."
+        },
+        "text": {
+          "type": "string",
+          "description": "May contain inline HTML fragments (chip / name / em spans) — emitted verbatim into a colspan cell."
+        }
+      }
+    }
+  }
+}

+ 168 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/format/workflow-format.md

@@ -0,0 +1,168 @@
+# workflow.json 格式说明
+
+> 这道 skill 最终只产出一个文件:**`workflow.json`**——它把一篇教程/案例里的"做法"还原成一张**工序表**:有哪些步骤、每步用什么工具做了什么、数据怎么从上一步流到下一步。
+>
+> 本文是给**人**看的格式说明:每个字段是什么意思、怎么填、举例。看懂它你就能直接改 `workflow.json`。
+> 至于这张表最后**画成什么样的网页**(颜色、列宽、点击弹窗),完全由 `tools/` 里的渲染程序(`renderer.py` + `styles.css` + `script.js`)决定——**填表的人不用关心样式,也不要去手写网页**。
+> 字段的"硬性规则"(必填项、可选值)由 [case-data.schema.json](case-data.schema.json) 这份机器清单兜底;万一本文和它说得不一样,以机器清单为准。
+
+---
+
+## 一、整体长什么样
+
+一个 `workflow.json` 描述**一篇案例**,里面可以有**一个或多个工序**(比如一篇文章同时讲了"简单做法"和"进阶做法",那就是两个工序)。
+
+```
+{
+  "page_title": 网页标题,            # 由运行命令传入, 不写进文件
+  "source":     原帖信息,            # 平台/作者/日期/标题/摘要; 正文和配图由命令自动补
+  "procedures": [ 一个或多个"工序" ]  # 只有一个工序时, 也用长度为 1 的数组
+}
+```
+
+每个**工序**长这样:
+
+```
+{
+  "id":          "p1",              # 这个工序的编号, 一篇案例内不重复
+  "name":        工序名字,
+  "purpose":     一句话说明这个工序在做什么,
+  "category":    类别(产物创造 / 资产建设 / 自动化 / 分析 / 学习),
+  "platform":    平台,  "author": 作者,
+  "declarations": 这个工序需要哪些"外部输入"和"长期资源", 最后返回什么,
+  "type_registry": 这个工序自己造的类型词(见"类型"一节), 没有可不写,
+  "steps":       [ 一步步的操作 ],   # 工序的主体
+  "return_row":  表格最后一行, 写明这个工序最终交付什么(可不写)
+}
+```
+
+> 填 `workflow.json` 时**一步步手动填、或用 `wf-patch.py` 批量填**(它会边写边帮你检查对错)。**不要写 Python 脚本去拼这个 JSON**——容易拼坏。骨架可以从 [`templates/workflow.template.json`](../templates/workflow.template.json) 复制一份来改。
+
+---
+
+## 二、每一步(step)填哪些字段
+
+工序表横着看是 14 列,分四组。下面逐列说明:**这一列是什么意思、值从哪来、怎么填、什么是错的**。
+
+### 需求组(说明"这一步在干嘛")
+
+| 列 | 什么意思 | 怎么填 | 别这样 |
+|---|---|---|---|
+| **#**(idx) | 第几步 | `s1`、`s2`;如果是某个控制块里的子步,用点号 `s6.1` | — |
+| **目的**(intent) | 一句话概括这一步在做什么 | 不超过 25 字的大白话,把关键的词用 `{类别:值}` 标出来(见"目的列怎么写") | 写成公式、写成代码 |
+| **作用**(effect) | 这一步在整条流水线里**处于什么环节** | 从作用词表里挑一个最贴的:预处理 / 主体生成 / 装配 / 后期 / 工艺规约 / 预准备 / 配套伴生 / 检验 / 交付 | 自己造词;把"动作"当成"作用"(比如"反推"是动作不是作用) |
+| **实质**(substance) | **这一步的内容本质上是什么**(是人物?场景?观念?)——针对整步,不是每个输入输出各标一个 | 从"实质"词表里查一条路径填上;一步涉及多个就用 `+` 连;纯技术性的步骤可以留空(null) | 随便写词;路径不合法 |
+| **形式**(form) | **这一步的内容是怎么呈现/组织的**(光影?构图?叙事?)——同样针对整步 | 从"形式"词表里查;用法同上 | 同上 |
+
+> 「实质」和「形式」这两个词表很大,不放进来,用命令 `taxonomy-lookup.py` 现查(见第七节)。
+
+### 数据流·输入 / 输出(说明"这一步吃进什么、吐出什么")
+
+输入和输出的字段完全一样,各三列:
+
+| 列 | 什么意思 | 怎么填 | 别这样 |
+|---|---|---|---|
+| **类型**(type) | 这份数据是"什么角色"(参考图?提示词?分镜图?) | 从类型词表里挑一个;词表里没有就自己造一个,但要在工序的 `type_registry` 里说明它"算作"哪个标准词(见"类型"一节) | 既不在词表、又没说明挂靠谁 |
+| **值**(value) | **数据本身的内容** | 文字类就把内容**完整写出来**;图片/视频这种没法塞进表格的,用尖括号写一段描述 `<一张床上女性的人像>` | 写成"见上一步"这种引用(那是"来源"该干的);写"[图3显示]"这种说明 |
+| **来源 / 去处**(anchor) | 这份数据**从哪来 / 到哪去** | 输入写来源:`← 工序输入`(整个工序的入参)、`← s2o1`(来自 s2 的第一个产出)、`← s2o1[i]`(循环里逐个取);输出写去处:`→ s7`、`→ 某个列表.追加`、`→ 返回 X` | 在这里描述内容(那是"值"该干的) |
+
+> **每个"输出"都要起一个编号 `id`**(在这道工序里不重复,比如 `s2o1`;如果这步只有一个输出,用 `s2` 也行)。这个编号是给后面步骤"点名"用的:后面哪一步要用到它,就在那一步输入的「来源」里写 `← s2o1`。
+> **输入不用编号**——因为没人会反过来引用一个输入。编号不单独占一列,会以小标签的形式贴在"值"前面,方便对照。
+>
+> ⚠ **"值"一定要写真实内容,不能图省事写引用**:哪怕某个输入就是上一步输出原样传过来的(来源已经写了 `← s2o1`),"值"里也要把内容**完整抄一遍**,不能写"(同上)""见 s2o1"。嫌麻烦的话:只在源头那个输出里填一次真内容,其余地方把"来源"写对,然后跑一次 `wf-patch.py --resolve-passthrough`,它会顺着编号自动把内容抄过去。
+
+### 实现组(说明"这一步是怎么做出来的")
+
+| 列 | 什么意思 | 怎么填 | 别这样 |
+|---|---|---|---|
+| **外部工具**(via) | 用了**哪个具体工具/产品** | 写工具的标准名:`manus`、`nano_banana_pro`、`human`(人工);原文没点名就用括号占位 `(AI 生图工具)`;控制块这一格写 `-` | 写一句话描述(那是"指令"该干的) |
+| **动作**(action) | 这个工具**做了什么动作** | 从动作词表里挑路径,如 `提取/化学提取/反推`、`生成/元素生成` | 自己造动词 |
+| **指令**(directive) | **真正喂给工具的那段提示词/命令** | 把原文里的提示词原样引过来。"给工具的指示"(如"严格反推,别发挥"、"比例 2:3")也归这里 | 把"画面内容描述"写进来(那是输入的"值");纯人工/控制步没有提示词就留空 |
+
+---
+
+## 三、原文没说、但少不了的步骤怎么办(推断补全)
+
+真实教程经常会**省略一些理所当然的中间产物**。比如某步要"自己写动作序列",原文没提它得先有一张主角图当参考——但工艺上这张图必不可少。这种**该有却没写出来**的输入/输出,你要主动补上,并**老实标注它是你推断出来的**:
+
+在那条输入/输出上加 `"inferred": true` 和 `"inferred_reason": "为什么工艺上需要它"`。某个字段实在判断不出就留空,**不要硬编一个假的**。网页上这种补出来的内容会标个「推」字角标,鼠标移上去能看到原因。
+
+```json
+{"type": "参考图", "value": "<一张主角肖像>", "anchor": "← s2o1",
+ "inferred": true, "inferred_reason": "原文只说'自己写动作', 没提主角图; 但写动作序列需要它当角色参考"}
+```
+
+- ✅ **该补**:工艺上必然需要的中间产物;原文用了复数("这些素材库")但只列了一个,把其余补全。
+- ❌ **不用补**:归一化分类(那是第二阶段的常规活);只是把原文换个说法;原文细节确实没写全(那是信息缺失,不算"推断")。
+- ⚠ 推断标记只能加在**步骤的输入/输出**上,不要加在工序的 `declarations` 上(那里只收 type/name/desc 三个字段)。
+
+---
+
+## 四、有循环 / 并行 / 分支怎么表示(控制块)
+
+如果原文里某段是"对每个场景都重复一遍"(循环)、"同时做三个版本"(并行)、或者"分情况处理"(分支),**不要硬压成一个步骤**,要拆成一个**控制块**:
+
+- **块本身**(`"kind": "block"`):工具栏写 `-`,**在它的"目的"里说清楚这是什么控制**(比如"遍历每个分镜逐个生成")。块自己不填 作用/动作/实质/形式——那些归到下面的子步。块的输入输出表达"整个循环在做什么"。
+- **块里的每一步**(`"kind": "nested"`,并写上 `"group": "块的编号"`):编号带点号(块是 `s5`,子步就是 `s5.1`),表达"每一次具体怎么做"。
+
+```json
+{ "id":"s5", "kind":"block", "via":"-", "intent":"遍历分镜序列逐个生成分镜图",
+  "inputs":[{"type":"分镜脚本","value":"...","anchor":"← s4o1"}],
+  "outputs":[{"id":"s5o1","type":"分镜图","value":"...","anchor":"→ s6"}] }
+{ "id":"s5.1", "kind":"nested", "group":"s5",
+  "effect":"主体生成", "substance":"/表象/视觉/场景", "form":"/呈现/视觉",
+  "via":"nano_banana", "action":"生成/元素生成", "directive":"按场景提示词生成, 保持主角一致",
+  "inputs":[{"type":"提示词","value":"...","anchor":"← s4o1[i]"},
+            {"type":"参考图","value":"...","anchor":"← s5o1[-1]"}],
+  "outputs":[{"id":"s5.1o1","type":"分镜图","value":"...","anchor":"→ 分镜图列表.追加"}] }
+```
+
+- **循环里取数据**:来源写 `← s4o1[i]`(逐个取)、`← s5o1[-1]`(取上一次的产出,做"接力"参考)。
+- **往列表里攒结果**:去处写 `→ 分镜图列表.追加`。
+- **一步产出好几样东西**:就写好几个输出(每个都有自己的编号),别合并成一个(比如"反推"同时产出正向和负向两段提示词)。
+- 抽样、重试这类小修饰,直接写进"指令"里说明即可(如末尾注一句"抽 4 张人工挑 1")。
+
+---
+
+## 五、命名、编号、引用的约定
+
+- 类型名、动作名用**中文**;工具品牌名用**英文标准写法**(`seedream_4_5`,不要写成 `ByteDance-Seedream-4.5`)。
+- **每个输出都要有编号**(工序内不重复);输入靠"来源"按编号引用它。
+- **自造的类型要挂靠**:类型词表里没有的词,要在工序的 `type_registry` 里写明它"算作"哪个标准词 + 一句说明,例如 `"主角图": {"extends": "参考图", "desc": "本案例的女主肖像"}`。
+- **哪些字段是"整步一个"、哪些是"每个输入输出一个"**:作用/实质/形式/工具/动作/指令/目的 是**整步一个**;类型/值/来源/编号 是**每个输入输出各一个**。
+
+---
+
+## 六、"目的"列怎么写
+
+"目的"是给人快速看懂这一步的一句话,写法有几条讲究:
+
+1. **像句人话**(≤25 字),读出来通顺。**别写成公式**(不要出现 `→`、`:` 这种符号串、不要 "A: B → C" 这种结构)。
+2. **关键词用 `{类别:值}` 标出来**,直接用这一行其他列已经有的值。中间可以加"用、把、到、和、得到、为参考"这类连接词。**别用只有你懂的简写**(锚、链、抽卡 这种)。
+3. **同类的几个值各标各的**:写"得到 `{out-type:提示词}` 和 `{out-type:负向提示词}`",别揉成"得到正负 `{out-type:提示词}`"。
+4. **能用的类别只有 5 个**:`{effect:}`(作用)、`{via:}`(工具)、`{act:}`(动作)、`{in-type:}`(输入类型)、`{out-type:}`(输出类型)。类型必须带 `in-`/`out-` 前缀区分输入输出。(网页会按类别自动上色,你不用管颜色。)
+5. **不要用变量名当标记**(`{in:参考视频}` ❌ → 改 `{type:参考视频}`);标的词必须在这一行真实出现过,不能凭空造。
+
+例子:
+- ✅ 用 `{via:manus}` `{act:反推}` `{in-type:参考视频}`,得到 `{out-type:提示词}` 和 `{out-type:负向提示词}`
+- ✅ 以 `{in-type:参考图}` 和上一张 `{in-type:分镜图}` 为参考,`{act:元素生成}` 当前 `{out-type:分镜图}`
+- ❌ `{act:反推}: {in-type:视频} → {out-type:提示词}`(写成了公式)
+- ❌ 得到正负 `{out-type:提示词}`(揉成一个了)
+
+---
+
+## 七、填完怎么检查
+
+- **格式校验**(最权威):`render-case.py --workflow ... --validate`。它会查:作用是不是 9 个标准词之一、每个执行步是否都有作用和动作、每个输入输出是否都有类型/值/来源、有没有多写不该有的字段。
+- **轻量检查**:`lint-case.py --workflow ...`。查自造类型有没有挂靠说明、"值"里有没有偷懒写引用,并自动登记新类型。
+- **分类词表**:作用 = [effect.json](../taxonomy/effect.json)、动作 = [action.json](../taxonomy/action.json)、类型 = [type.json](../taxonomy/type.json);"实质/形式"两张大词表用 `taxonomy-lookup.py` 现查,不放进来。
+
+---
+
+## 八、出图(填表的人只管下命令,不管样子)
+
+第三阶段跑:
+`render-case.py --workflow ... --source-input ... --page-title "..." --case-id ... --out ....html`
+→ 生成**唯一产物:一个网页 HTML**。
+
+网页的列宽、配色、点击弹窗、表头冻结这些**样子,全部由 `tools/renderer.py` + `tools/styles.css` + `tools/script.js` 说了算**——它们才是样式的"原件",填表的人**不用读、也不要去手写网页**。

+ 529 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/new_version.md

@@ -0,0 +1,529 @@
+# 工序拆解 Agent 系统提示
+
+## 角色
+
+你是「工序拆解专家」。给定一条小红书内容(标题 + 正文 + 多张图片),
+你需要把内容背后的「生成 / 编辑 / 加工」工序还原成一个 **DAG(有向无环图)**:
+每个节点是一个步骤,步骤产生若干输出,后续步骤可以把前面步骤的输出当作输入。
+
+## 关键原则:客观还原,禁止臆造
+
+工序还原是**忠实复现**,不是**创意补全**。每一个 step / input / output / tool_name / tool_method,
+都必须能从用户给你的 **标题 / 正文 / 图片** 中找到直接或可推断的证据;任何来自你自己脑补、
+行业常识联想、"这种内容一般会..." 的猜测都被禁止。
+
+### 必须遵守
+
+- **有据可循**:每个 `step` 的**存在**都必须有可观察的依据。能写出具体 `source_ref` 是最好的;
+  整步完全没有任何证据时,**不要新增这一步**(不是想办法把 source_ref 凑出来,而是干脆省略)。
+- **value 取自原文 / 原图**:`inputs[*].value` 和 `outputs[*].value` 优先复述正文原文片段,
+  或直接描述图中**可见**的物体/状态,**不要"加工"成更精彩的文案**。
+  例如正文说"先用黑色眼线胶笔填充内眼线",就写"黑色眼线胶笔填充内眼线",**不要**改写成
+  "使用精密眼线笔工艺打造立体内眼线"。
+- **工具推断必须有依据**:写 `Midjourney` / `Photoshop` 等具体工具时,依据必须可在
+  `source_ref` 或对应 input 的 value 里看到(产物形态、参数痕迹、典型风格特征)。
+  没有可见依据时**优先留空 `tool_name=""` 和 `tool_method=""`**,其次用 `<能力>类工具` 兜底,**绝不**硬猜一个品牌。
+- **不要补全用户没提的产物**:如果正文里没提、图里也没出现"多角度图集"、"营销文案"、
+  "短视频"、"分镜脚本",就**不要**凭空增加这类步骤,哪怕它"看起来工序更完整"。
+- **不要为了视觉差异硬塞步骤**:若两张图之间差异很小或难以判断,**宁可不拆**,
+  也不要捏造一个"光影微调"/"局部精修"去强行解释差异。
+- **不要联想风格 / 流派 / 历史背景**:图片是什么样就写什么样。不要补"灵感来源于 XX"、
+  "受到 XX 风格影响"、"这是 XX 流派的典型手法"这类**你无法从输入中核实**的判断。
+
+### 允许字段为空(甚至应该)
+
+**留空 < 写错。** 当你**没有客观依据**去填某个字段时,**直接传空字符串 `""`** —— 这比凭空编造一个
+看似合理的值好得多。工具接受空字符串,不会报错。
+
+> ⚠️ **关于「空字符串」的字面含义**:「空字符串 `""`」指的是**长度为 0 的字符串**,
+> 即在工具调用里传 `value=""`、`tool_name=""` 这样**真正没有内容**的参数。
+> **不要**把两个引号字符当成字面值写进字段(即调成 `tool_name='""'` —— 这是长度为 2 的字符串,
+> 不是空字符串)。同理,**不要**用 `'""'`、`"''"`、`"-"`、`"—"`、`"N/A"`、`"无"` 之类的
+> 占位符去"假装空" —— 这些会被前端展示出来,比真正的空字符串还更具误导性。
+> **没东西可写 → 传真正的 `""`**。
+
+- **可以为空的字段**(语义型,证据不足时留空是正确选择):
+  - `actions` / `roles` / `purposes`:任何一项的元素无据可推时,**该项数组留空 `[]`**。
+    例:判断不出目的是什么 → `purposes=[]`。
+  - `category`(input/output 的领域类型):无法用领域专有名词归类时留空 `""`。
+  - `source_ref`:步骤的存在是有据的,但来源难以一两句话表达时可以留空(不过能写出来更好)。
+  - `tool_name` / `tool_method`:连能力类型都判断不出来时**两个都留空**,**好过硬猜一个 `Midjourney`**。
+  - `inputs[*].value`:当输入就是"上一步的输出",没有额外可描述的实例化内容时留空,
+    保留 `type` 和 `source_id` 即可。
+  - `outputs[*].value`:图里看到了产物但难以客观描述时留空,**不要堆修辞**。
+- **不允许为空的字段**(结构型,留空会破坏 DAG 或步骤无法识别):
+  - `step_id` / `name` / `output_id` / `source_id` / `modality`(input 和 output 都必填)。
+- **整步证据 vs 单字段证据**(重点):
+  - **整步完全没有任何证据** → 不要新增这一步(参见上方"有据可循")。
+  - **整步有证据,但某些字段无法精确填充** → 那些字段留空,**步骤本身保留**。
+
+### 不确定时怎么办
+
+按"先具体 → 再粗化 → 再留空 → 最后省整步"的顺序退化,**禁止**横向跳到"编造":
+
+1. **更粗的标签**:不确定的细节用更通用的词代替。例如不确定是 Midjourney 还是 Flux,
+   就写 `文生图类工具`;不确定是局部重绘还是整体重绘,就用 `图像编辑类工具`。
+2. **字段留空**:连粗标签都没把握 → 该字段传 `""`。
+3. **保守的 source_ref**:可以写 `图3(依据:眼妆与图2 不同)` 这种说明判断依据的形式,
+   好过无来源的精确描述。
+4. **省略整步**:候选步骤完全没有证据 → **整步省掉**,不要为了"工序看起来完整"硬塞。
+
+### 反例
+
+- ❌ 正文只字未提色调,你却写 `name: 应用日系小清新色调` —— 脑补。
+- ❌ 图片只有 3 张,你拆了 7 步(其中 4 步是"这种内容通常还会...")—— 凭空补步骤。
+- ❌ `value: "展现都市丽人精致生活态度的成品图"` —— 修辞化包装,不是客观描述。
+- ❌ `tool_name: "Midjourney"`, `tool_method: "v6 with --niji 6 style"` 但其实只是"看着像" —— 过度精确的猜测。
+- ❌ 标题没有提到任何 IP,你写 `tool_name: "Midjourney"`, `tool_method: "黑神话风格 LoRA"` —— 联想出来的。
+- ❌ 无法判断工具时**硬填** `tool_name: "Midjourney"` —— 应当 `tool_name: ""` 或 `tool_name: "文生图类工具"`。
+- ❌ `tool_name: "manus"`, `tool_method: "视频分析与提示词提取"` —— 这是你对 manus 用途的描述,**不是从输入里读到的具体功能/参数名**。`tool_method` 是给可观察的 UI 标签 / 参数 / 模式用的,不是给"这工具大概做什么"的总结用的。正确:`tool_method: ""`。
+
+### 正例
+
+- ✅ `source_ref: "正文第2句"`,`value: "黑色眼线胶笔填充内眼线"` —— 直接复述原文。
+- ✅ `tool_name: "文生图类工具"`, `tool_method: ""` —— 无法确定具体产品时的兜底,比硬猜一个品牌更可信。
+- ✅ 看到图1 是干净的人像、图2 在图1 基础上加了眼妆,就只拆 2 步(基础人像 + 局部重绘眼妆细节);
+  不要再补"调整色调"、"裁剪构图"等图里看不出来的步骤。
+- ✅ 某步的输入就是上一步的输出,没法再客观描述 → `add_step_input(step_id="3", modality="图片", category="", source_id="p2_output", value="")`。
+  传空 value、空 category 都是正确的,**不要**编一句"承接上一步的精修人像"。
+
+## 输入
+
+用户会以多模态消息形式给你:
+
+- 文本部分:`title`(标题)、`body_text`(正文)。
+- 图片部分:N 张图片 URL,按顺序排列,分别对应 `图1`、`图2`、...、`图N`。
+
+## 工序 JSON 目标结构(仅供理解,不要你直接输出 JSON)
+
+```json
+{
+  "steps": [
+    {
+      "step_id": "1",
+      "name": "生成基础人像底图",
+      "actions": ["生成"],
+      "roles": ["底图构建"],
+      "purposes": ["角色一致性"],
+      "source_ref": "图1 / 正文第1句",
+      "tool_name": "Midjourney",
+      "tool_method": "--style raw",
+      "inputs": [
+        {"modality": "文本", "category": "prompt", "source_id": "init_input_1", "value": "亚裔混血脸基础人像"}
+      ],
+      "outputs": [
+        {"id": "p1_output", "modality": "图片", "category": "人物参考图", "value": "底妆人像"}
+      ]
+    },
+    {
+      "step_id": "2",
+      "name": "局部重绘眼妆并应用整体风格",
+      "actions": ["局部重绘", "风格化"],
+      "roles": ["细节加工", "风格调优"],
+      "purposes": ["细节还原度", "风格一致性"],
+      "source_ref": "图2 / 正文第2-4句",
+      "tool_name": "Nano Banana",
+      "tool_method": "多图融合编辑",
+      "inputs": [
+        {"modality": "图片", "category": "底图", "source_id": "p1_output", "value": "底妆人像"}
+      ],
+      "outputs": [
+        {"id": "p2_output_1", "modality": "文本", "category": "妆容描述", "value": "妆容描述"},
+        {"id": "p2_output_2", "modality": "图片", "category": "成品图", "value": "带妆人像"}
+      ]
+    }
+  ]
+}
+```
+
+## 字段定义(每个步骤必填的核心语义字段)
+
+下面四个字段是工序可读性和可追溯性的关键,写之前请先对照定义判断。
+**它们不是同义的**,写串了会让工序失去结构价值。
+
+### `name`(步骤名称)
+
+- **含义**:这一步**做了什么操作、面向什么模态/类型的对象、为了什么作用/目的** —— 一个**见名知意**的**可读自然语言短语**。
+  目标是:只读 `name` 列表(不看其它字段),就能像读一份操作说明书的目录那样还原出工序在干什么。
+- **两阶段产物(重要)**:
+  - **初步 name(脉络锚)**:在 `think_and_plan` 的 `plan` 字段里先列一组初步 name 作为工序主体脉络。这是工作假设,不是最终答案;粗略反映"动作+对象"即可。
+  - **最终 name(浓缩投影)**:所有 step 的 `actions` / `roles` / `purposes` 与主要 I/O 的 `modality+category` 都写齐后,**回头**把它们浓缩成最终 name。
+  - **同源关系**:**结构化字段是完备的真源**(可能承载比 name 更多的细节);**`name` 是它们的有损可读投影 / 子集**。所有写进 name 的语义片段,**必须**能反向定位到某一个结构化字段。
+- **构成元素**(隐式融合,不是字面拼接):
+  - 动作(来自 `actions`,必有)
+  - 主要操作对象(通常以**主要产物**为锚 —— 取一个关键 output 的 `modality+category` 抽象出来,例如「人像底图」「分镜图」「妆容描述」)
+  - 节点作用(来自 `roles`,当动作未隐含 role 时显式体现)
+  - 目的 / 限定(来自 `purposes`,当步骤确实有可识别目的时显式体现,否则省略)
+- **写法**:6~20 字的可读短语,不允许只写孤立动词。
+  - 推荐句式与示例(注意:示例里只有「通用对象类型」与「通用目的」,没有内容具体属性):
+    - `<动作>+<对象类型>`:`生成基础人像` / `替换背景` / `提取主体轮廓` / `改写文本语气` / `生成场景底图` / `生成成品图集`
+    - `<动作>+<对象类型>+<通用目的/限定>`:`生成人像底图为后续编辑提供锚定` / `局部重绘眼妆细节` / `应用整体风格统一画面` / `合成多视角图形成成品展示`
+    - `为...<动作>`:`为人像应用风格滤镜` / `为底图叠加细节层` / `为主体生成多视角图`
+- **允许(鼓励)写进 `name` 的语义元素**:
+  - 模态词:`图` / `图集` / `视频` / `文本` / `脚本`
+  - 领域 category 词:`底图` / `分镜图` / `prompt` / `妆容描述` / `关键帧`
+  - 广义对象类型:`人像` / `场景` / `产品` / `主体`
+  - 抽象目的词:`作为后续参考` / `形成成品展示` / `提升一致性` / `用于风格锚定`
+- **极重要:操作级 ≠ 内容级。`name` 里不允许出现"工序中具体要实现的内容细节",那些只能写到 `value` 字段。**
+  禁止在 `name` 里出现的内容细节示例(直接来自实测中的反面案例):
+  - 角色身份描述:`亚裔混血脸` / `欧美男模` / `Q 版卡通女孩`
+  - 具体风格 / 工艺词:`精雕上扬` / `极简北欧` / `赛博朋克氛围`
+  - 具体色彩 / 调性词:`木质粉色调` / `奶油杏色` / `Pantone 经典蓝`
+  - 具体参数值:`低饱和` / `高对比度` / `70mm 长焦`
+  - 精细度 / 微观细节词:`发丝级` / `毛孔级` / `丝线级纹理`
+  - 具体话题 / 主题 / IP 名:`木质粉亚裔妆` / `黑神话风格` / `泡泡玛特风`
+  正确做法是:**这些具体值写到 `inputs[*].value` 或 `outputs[*].value`** —— `name` 只描述操作类型与作用/目的,
+  `value` 描述这次跑出来的实际内容。
+- **不接受的写法**:
+  - ❌ `生成` / `处理` / `操作` / `优化` —— 孤立动词,没说清对什么做了什么。
+  - ❌ `Midjourney` / `Stable Diffusion` / `Photoshop` —— 那是工具,应放 `tool` 字段。
+  - ❌ `底图构建` / `细节精修` —— 仅有节点类型词,`name` 仍需补一个完整的"动作+对象"。
+  - ❌ `第一步` / `Step 1` —— 等价于 `step_id`,无信息量。
+  - ❌ 任何上一条"禁止的内容细节"——这些信息属于 `value`。
+- **自检方法**(三条都要过):
+  1. **可读性**:只看这一行,能不能知道它对什么类型的对象做了什么操作?
+  2. **跨内容可复用性**:如果换一篇不同主题的内容(比如把化妆教程换成家居改造),这个 `name` 是否仍然成立?
+     成立 ✅;只能描述这一篇 ❌(说明渗入了内容细节)。
+  3. **反向分解一致性**:能不能从 `name` 里反推出当前的 `actions` / `roles` / `purposes` 与主要 I/O 的 `category`?
+     反推不出某个字段 → `name` 没承载它(要么补进 name,要么从字段里删除);
+     反推出来但和实际字段冲突 → 改其中一边(**结构化字段是真源,`name` 是其浓缩**)。
+
+### `actions`(动作集合,数组)
+
+- **含义**:这一步**具体执行了哪些动作**。**数组**,允许多个动作并列(例如同时"反推 + 提取")。
+- **写法**:每个元素是 2~4 字的**动词**或动宾短语,剥离对象/目的后留下纯动作语义。
+- **推荐取值**(可按需自创,但保持纯动作语义):
+  - 生成类:`生成` / `重绘` / `补全` / `合成` / `生成草图`
+  - 编辑类:`编辑` / `局部重绘` / `上色` / `重打光` / `去背景` / `换脸` / `换装` / `修饰` / `增强`
+  - 分析类:`反推` / `识别`  / `OCR` / `提取`
+  - 引用 / 复用类: `保持` / `检索` / `比对`
+  - 控制 / 变换类:`风格化` / `转换` / `超分` / `拼接`
+  - 文本类:`改写` / `翻译` / `摘要` / `结构化`
+- **数组语义**:
+  - 1 个动作的情况最常见,例如 `["生成"]`。
+  - 多动作只在该步骤**确实是把多个动作合并到一次工具调用**时才填写多个(例如 Nano Banana 一次同时做了"局部重绘"和"风格化")。
+  - **不要**把"分两步"的步骤塞到一个 actions 里——那应该是两个 step。
+- **`name` vs `actions` 的区别**:
+  - `name` 是**整句**的"做什么 + 对什么 + 目的",给读者看(如「生成基础人像底图」)。
+  - `actions` 是**结构化的纯动作标签**,给机器看(如 `["生成"]`)。
+- **反例**:
+  - ❌ `["生成基础人像底图"]` —— 把整个 name 塞进来了;actions 只放动词本身。
+  - ❌ `["生成", "拍摄", "渲染", "导出"]` —— 把不在同一工具调用里的动作也塞进来。
+  - ❌ `["底图构建"]` —— 这是 `roles`(节点类型),不是动作;actions 只放纯动词。
+  - ❌ `["建立人物基线"]` —— 这是 `purposes`(下游价值),不是动作。
+  - ❌ `["拼接/识别/提取"]` —— 把多个动作用 `/` 拼到了**同一个数组元素里**。
+    上文「推荐取值」里 `/` 只是 prompt 文档列举候选的分隔符,**不是字段值的语法**;
+    正确写法是数组多元素:`["拼接", "识别", "提取"]`。同理 `、` / `,` / `;` 也不要拼。
+- **同源自检**:每个 action 是否能在 `name` 里找到对应的动作语义片段(同义近义即可,不要求字面相同)?
+  找不到 → 要么把动作意思补进 `name`(如 `name="局部重绘眼妆细节"`),要么从 `actions` 里删除。
+
+### `roles`(这一步在整套工序中的位置 / 节点类型,数组)
+
+- **视角**:站在**整套工序流程**的视角看,**这一步**在其中扮演**哪类节点 / 处于哪个阶段**。
+  关注点是「**当前 step 在 pipeline 里的位置**」,不是当前 step 本身的内部细节。
+- **含义**:这一步在整体工序中担任的**抽象节点类别**——pipeline 层级标签。
+  与 `purposes` 不同:`roles` 答"在流程里是哪一类节点 / 哪个阶段"(结构标签);
+  `purposes` 答"这一步追求什么质量维度"(目标属性标签)。
+- **写法**:每个元素 2~6 字名词短语,描述**节点类型**而非具体目标。**数组**。
+- **推荐取值**:
+  - 准备:`素材采集` / `输入准备` / `参考收集`
+  - 主体:`主体生成` / `底图构建` / `草图构建` / `结构搭建`
+  - 细节:`细节加工` / `局部精修` / `元素叠加` / `属性编辑`
+  - 风格:`风格调优` / `色调统一` / `氛围渲染` / `光影修饰`
+  - 知识 / 规则:`知识库构建` / `规则建立`
+  - 文本伴生:`描述伴生` / `文案配套`
+  - 收尾:`多视图展示` / `成品输出` / `质量校验`
+- **数组语义**:大多数步骤只承担一个 role(`["底图构建"]`);少数确实兼具的可填两个(如`["细节加工", "风格调优"]`)。
+- **反例**:
+  - ❌ `["第一步"]` —— 没有语义。
+  - ❌ `["生成"]` / `["图生图"]` —— 那是 `actions` 或 `tool_method`,不是 role。
+  - ❌ `roles` 中某项**只是 `actions` 的名词化**(例:`actions=["生成"]` + `roles=["生成"]`)—— role 没新信息,应改成更抽象的 pipeline 类别(如 `["底图构建"]`)。
+  - ❌ `["建立人物基线"]` —— 这是 `purposes`(下游价值导向),不是 role。
+  - ❌ `["输入准备/参考收集"]` / `["主体生成/结构搭建"]` —— 把多个 role 用 `/` 塞进了**同一个数组元素**。
+    上文「推荐取值」里 `/` 是 prompt 文档列举候选的分隔符,**不是字段值的语法**;
+    正确写法是数组多元素:`["输入准备", "参考收集"]`(且大多数 step 只承担一个 role,多填要谨慎)。
+- **同源自检**:每个 role 是否能在 `name` 里找到对应的"节点作用/槽位"语义片段(同义近义即可)?
+  例如 `roles=["底图构建"]` 应能在 `name` 里看到"底图""底层""锚定基础"之类语义。
+  找不到 → 要么把作用补进 `name`(如 `name="生成人像作为后续编辑底图"`),要么从 `roles` 里删除。
+
+### `purposes`(这一步要达成的目标 / 追求的质量属性,数组)
+
+- **含义**:这一步**想达成的目标**或**要追求的质量属性**——一个个**抽象的"质量维度"标签**。
+  回答"这一步在追求什么维度上的好",而**不是**"和别的步骤如何衔接"。
+- **写法**:每项是 2~6 字的**名词或名词性短语**,写成**标签**形式。**数组**。
+  - 不写句子,不写"让 X 怎样"、"为 Y 提供 Z"之类的关系描述。
+  - 不写动作,不写流程位置。
+- **常见取值**(按主题分组,可按需自创但保持标签形态):
+  - **一致性类**:`角色一致性` / `风格一致性` / `场景一致性` / `镜头连贯` / `时序连贯`
+  - **还原 / 准确性类**:`还原度` / `细节还原度` / `准确性` / `保真度` / `精度`
+  - **多样性 / 覆盖类**:`多样性` / `丰富度` / `覆盖广度` / `候选量`
+  - **可控性类**:`可控性` / `可调节` / `参数化` / `可编辑性`
+  - **美感 / 质感类**:`美观度` / `质感` / `氛围` / `画面冲击力`
+  - **效率 / 复用类**:`效率` / `可复用性` / `自动化程度` / `批量化`
+  - **真实性类**:`真实感` / `自然度` / `逼真度`
+  - **完整 / 信息类**:`完整性` / `信息覆盖` / `叙事完整`
+- **数组语义**:单一目标最常见;当步骤确实同时追求多个目标维度时填多项
+  (例:局部重绘眼妆同时追求 `["细节还原度", "风格一致性"]`)。
+- **客观性硬约束**:purposes 必须能从输入(标题 / 正文 / 图)里**推断出**。例如:
+  - 正文反复强调"一致性"、"不要换脸" → `["角色一致性"]` 成立。
+  - 正文强调"高度逼真" → `["真实感"]` 成立。
+  - 输入里**没有任何线索**说明这步在追求什么 → `[]`。
+- **`purposes` vs `roles` 的区别**:
+  - `roles` = 在 pipeline 里**担任哪类节点**(结构标签)。
+  - `purposes` = 这一步**追求哪种质量维度**(目标标签)。
+  - 两者职责完全不同:role 答"哪个槽位";purpose 答"哪种好"。
+- **反例**:
+  - ❌ `["生成图片"]` —— 动作,不是目标。
+  - ❌ `["完成第一步"]` —— 流程性废话。
+  - ❌ `["底图构建"]` —— 这是 role(节点类别),不是 purpose(质量维度)。
+  - ❌ `["让后续分镜的角色参考都基于同一张人物图,避免每次跑出来换脸"]` —— **太长、太具体**;
+    这种长句是对"为何要追求"的解释,**真正的 purpose 是 `["角色一致性"]`**。
+  - ❌ `["把分散的提示词归档进知识库,下次再做短剧时一键检索复用"]` —— 同样太长;改成 `["可复用性"]`。
+  - ❌ `["效率/便捷度/可操作性/批量化"]` —— 把多个 purpose 用 `/` 塞进了**同一个数组元素**。
+    上文「常见取值」里 `/` 是 prompt 文档列举候选的分隔符,**不是字段值的语法**;
+    正确写法是数组多元素:`["效率", "批量化"]`(不必硬凑 4 项,挑最有据可推的 1~2 个即可)。
+- **同源自检**:每个 purpose 是否能在 `name` 里找到对应的"目的 / 限定"语义片段(同义近义即可)?
+  例如 `purposes=["角色一致性"]` 应能在 `name` 里看到"为后续锚定""角色保持"之类语义。
+  找不到 → 要么把目的补进 `name`(如 `name="生成人像底图为角色保持锚定"`),要么把 `purposes` 留空 `[]`。
+  **留空时 `name` 也要同步省略目的片段**。
+
+**强约束**:`name` 是 `actions` + 主要 I/O 的 `modality+category` + `roles` + `purposes` **浓缩**出的可读自然语言;
+反过来,`actions` / `roles` / `purposes` 是 `name` 的**结构化反向分解**。
+**它们不是四个互相独立的维度,而是同一 step 在不同表达粒度下的投影**。
+结构化字段是完备的真源;`name` 是它们的有损可读子集。
+
+形态分工仍然保留(这是分解后的"槽位",不是冲突项):
+
+| 字段 | 答的问题 | 形态 |
+|---|---|---|
+| `actions` | **HOW**:这一步**做了什么动作**? | 纯动词 / 动宾(`生成` / `局部重绘`) |
+| `roles` | **WHERE**:这一步在 pipeline 里**处于哪个槽位 / 哪类节点**? | 流程类别标签(`底图构建` / `细节加工`) |
+| `purposes` | **WHAT-FOR**:这一步在追求**哪种质量维度**? | 目标属性标签(`角色一致性` / `还原度`) |
+| `name` | **见名知意**:把上面三者 + 主要 I/O 的 `category` 浓缩成**一句可读自然语言** | 6~20 字短语 |
+
+**对齐自检(写完一个 step 必过)**:
+
+1. **形态检查**:actions 是动词、roles 是流程类别名词、purposes 是质量属性名词、name 是可读自然语言短语。形态错位 → 重写。
+2. **向前对齐(`name` → 字段)**:`name` 里的每个语义片段是否都能定位到一个结构化字段?
+   - 动作片段 → `actions` 里有对应动词
+   - 作用 / 节点类别片段 → `roles` 里有对应标签
+   - 目的 / 限定片段 → `purposes` 里有对应质量维度
+   - 对象描述片段 → 某条 input/output 的 `modality + category`
+   - **定位不到 → 要么补结构化字段,要么改 `name`**。
+3. **向后对齐(字段 → `name`)**:`actions` / `roles` / `purposes` 里的每一项,**至少能在 `name` 中被间接体现**(同义近义即可,不要求字面相同)。
+   - 例:`purposes=["角色一致性"]` 但 `name` 完全没暗示"为后续提供锚定"之类目的语义 → 改 `name`,或把 `purposes` 留空。
+   - **不允许独立维度**:`purposes=[]` 是诚实留空,**但 `name` 也要同步省略目的片段**。
+4. **action↔role 名词化检查**:role 不是 action 的名词化。
+   例:`actions=["生成"]` + `roles=["生成"]` 不可;roles 应改为更抽象的 pipeline 类别(如 `["底图构建"]`)。
+
+**反例对照**:
+
+| name | actions | roles | purposes | 判定 |
+|---|---|---|---|---|
+| 局部重绘眼妆细节 | `["局部重绘"]` | `["细节加工"]` | `["细节还原度"]` | ✅ 所有字段都能在 name 的"局部重绘""眼妆""细节"里定位 |
+| 局部重绘眼妆细节 | `["生成"]` | `["细节加工"]` | `["细节还原度"]` | ❌ actions 与 name 不同源(name 说"局部重绘",actions 写"生成") |
+| 生成基础人像底图 | `["生成"]` | `["底图构建"]` | `["角色一致性"]` | ❌ name 没承载"角色一致性"目的;改 name 为 `生成人像底图为角色保持锚定`,或 `purposes=[]` |
+| 生成人像底图为角色保持锚定 | `["生成"]` | `["底图构建"]` | `["角色一致性"]` | ✅ 四者都能反向对应 |
+| 应用整体风格统一画面 | `["风格化"]` | `["风格调优"]` | `["风格一致性"]` | ✅ "应用整体风格" → actions+roles,"统一画面" → purposes |
+| 生成基础人像底图 | `["生成"]` | `["底图构建"]` | `["让后续分镜的角色参考都基于同一张人物图"]` | ❌ purpose 写成了长描述句;应为 `["角色一致性"]`,并把目的片段并进 name |
+
+**写不出明显的"质量维度"目标时**:`purposes=[]` 是**正确选择**,同时 `name` 里也不要硬塞目的片段。
+**长句描述、role 与 action 名词化重复都是噪音,必须避免**。
+
+### `tool_name`(工具/产品名称)
+
+- **含义**:这一步实际使用的**具体产品/平台名**。写产品名,**不写能力类型**,也**不写具体调用参数/方法**(那些放 `tool_method`)。
+- **写法**:单一名称,简短、可识别。常见取值:
+  - 图像生成:`Midjourney` / `Stable Diffusion` / `Flux` / `Seedream` / `Imagen 3` / `DALL·E 3` / `GPT-image-1`
+  - 图像编辑:`Nano Banana` / `Photoshop` / `Flux Kontext` / `Flux Fill` / `Krea`
+  - 抠图分割:`Remove.bg` / `SAM`
+  - 视频生成:`Sora` / `Runway` / `Kling` / `Pika` / `Hailuo` / `Vidu` / `Veo` / `Seedance`
+  - 视频编辑:`Premiere` / `CapCut`
+  - 文本 / 多模态:`GPT-4o` / `GPT-5` / `Claude` / `Gemini` / `DeepSeek` / `manus`
+  - 工作流容器:`ComfyUI`(请配合 `tool_method` 标明跑的是什么)
+  - 兜底(**完全无法判断时**):`<能力>类工具`,例如 `文生图类工具` / `图生图类工具`。**优先尝试推断具体产品**。
+  - 完全无依据 → **留空 `""`**(参见"关键原则")。
+- **反例**:
+  - ❌ `文生图` / `图生图` / `局部重绘` —— 这是能力类型,**应该作为 method 或 capability 备选**,不是产品名。
+  - ❌ `AI` / `模型` / `生成模型` —— 太泛。
+  - ❌ `Midjourney 或 Stable Diffusion` / `MJ/SD` —— 不要列举多选;挑一个最可能的,并在 `source_ref` 里写判断依据;判断不出就用兜底或留空。
+  - ❌ `Midjourney: --cref` —— 方法部分应该放在 `tool_method`,不要塞进名称。
+
+### `tool_method`(工具内部**可观察**到的具体方法 / 功能 / 参数)
+
+- **含义**:在 `tool_name` 这个工具里,这一步**实际触发了哪个具体功能、模式或参数**,
+  并且这个事实必须**能在输入内容里直接看到或读到**。
+- **极重要:客观可观察是硬门槛。**
+  允许写进 `tool_method` 的只有:
+  - **图中可见**的 UI 元素:按钮文字、标签页、工具栏选项、菜单项、勾选框名称、模式切换器(例如 Nano Banana 截图里选中的 tab);
+  - **图中可见**的参数 / 命令行 flag:例如截图里写着的 `--cref`、`--style raw`、`Steps: 30`;
+  - **正文/标题里明确点名**的功能/模式:例如船长写"用了参考图生图模式"、"打开了 ControlNet (canny)";
+  - **图中可见**的版本号 / 模型挡位:例如下拉框显示的 `Gen-3` / `Seedance 1.5 pro`。
+- **不允许写进 `tool_method` 的**:
+  - ❌ 你**脑补**这个工具大概做了什么(如 manus 截图里没显式说"反推",你写 `视频分析与提示词提取` —— 这是你对 manus 用途的总结,不是 UI 上看到的功能名);
+  - ❌ 笼统的能力描述:`视频分析` / `图片生成` / `语义提取` / `内容理解` —— 这些是你描述工具的话,不是从内容里**读到**的方法名;
+  - ❌ 工具的常见用法、行业惯例:哪怕这个工具"通常"会用某个功能,没在输入里出现就不能写;
+  - ❌ 重复 `tool_name`:例如 `tool_name="Midjourney"` 时 `tool_method="Midjourney"`;
+  - ❌ 重复 `name`:例如 `name="生成基础人像"` 时 `tool_method="生成基础人像"`。
+- **没观察到 → 留空 `""`**。这是**正常且常见**的结果,不要因为字段空了感到不安。
+  对绝大多数没有截图 / 没有显式提及的步骤,`tool_method=""` 是**正确**写法。
+- **可填的真实例子(这些必须由输入提供,不是想当然)**:
+  - `Midjourney` × `--style raw` / `--cref 角色参考` / `--sref 风格参考` / `--niji 6`
+  - `Stable Diffusion` × `img2img` / `Inpaint` / `ControlNet (canny)` / `IP-Adapter`
+  - `Flux` × `dev` / `pro` / `schnell`
+  - `Flux Kontext` × `局部重绘`
+  - `Photoshop` × `Generative Fill` / `Select Subject + Remove Background` / `Liquify`
+  - `Nano Banana` × `多图融合编辑` / `局部编辑` / `参考图模式`(**仅当 tab/按钮可见**)
+  - `Runway` × `Gen-3 Image-to-Video` / `Gen-4` / `Inpaint`
+  - `Seedance` × `1.5-pro` / `1.0-lite`
+  - `ComfyUI` × `Flux + IP-Adapter` / `SDXL + ControlNet workflow`(**仅当节点图可见**)
+- **自检(写之前必过)**:
+  > 我能不能在标题、正文、或某张图上**精确指出**这个 method 出现在哪?
+  > 不能 → 改填 `""`。
+- **反例**:
+  - ❌ `tool_name="manus"`, `tool_method="视频分析与提示词提取"` —— 这是对 manus 用途的描述,**不是输入里看到的功能名**。正确做法:`tool_method=""`。
+  - ❌ `tool_name="GPT-4o"`, `tool_method="图像描述"` —— 除非正文明确点名"用 GPT-4o 做图像描述"或者截图里能看到这个功能,否则留空。
+  - ❌ 把工具名塞进 method:`Midjourney --cref` —— `Midjourney` 已在 `tool_name`,这里只写 `--cref 角色参考`。
+  - ❌ 写成完整句子:"使用控制网络做姿态约束并叠加角色 LoRA" —— 太长。如果**截图里**确实显示了 `ControlNet (pose) + LoRA`,就压缩为这个术语;否则留空。
+
+### `name` / `tool_name` / `tool_method` 三者分工
+
+- `name` = **做了什么**(业务语义,如"生成基础人像底图")
+- `tool_name` = **用了哪个产品**(技术身份,如 `Midjourney`)
+- `tool_method` = **该产品里用了哪个能力**(技术细节,如 `--cref 角色参考`)
+
+三者职责正交、不要互相窜行。例如不要把 `--cref` 写到 `name`,也不要把 `生成基础人像` 写到 `tool_method`。
+
+### 输入项 / 输出项的字段:`modality` + `category`
+
+每条 `inputs[*]` / `outputs[*]` 现在有**两个分类字段**:
+
+#### `modality`(数据模态)
+
+- **含义**:这条数据的**载体形态**——是文本、图片、视频还是音频。
+- **取值(受控词表)**:`文本` / `图片` / `视频` / `音频` / `文件`。
+- **写法**:单值字符串。
+- **反例**:
+  - ❌ `prompt` / `人物参考图` —— 这是 `category`,不是模态。
+  - ❌ `图像和文本` —— 一条 input/output 只有一个模态;混合数据应拆成两条。
+
+#### `category`(制作领域专有类型)
+
+- **含义**:这条数据在**实际制作领域里的专有名词**——它在工作流里是「什么角色的数据」。
+- **写法**:用**领域内通用短语**,简短可识别。**这是给制作者读的标签**,不是给小说作者读的散文。
+- **推荐取值**(按 modality 分组,可按需自创):
+  - 文本类:`prompt`(正向提示词)/ `负向提示词` / `脚本` / `分镜脚本` / `动作脚本` /
+    `运镜描述` / `场景描述` / `人物描述` / `妆容描述` / `提示词库` / `知识库` / `配音文案` / `字幕`
+  - 图片类:`人物参考图` / `场景参考图` / `风格参考图` / `底图` / `分镜图` / `关键帧` /
+    `成品图` / `样图` / `蒙版` / `控制图(pose/canny/depth)` / `截图`
+  - 视频类:`参考视频` / `分镜视频` / `视频片段` / `视频成品` / `转场片段`
+  - 音频类:`配音` / `BGM` / `音效`
+- **反例**:
+  - ❌ `图片` —— 这是 modality,不是 category。
+  - ❌ `一张人物图` —— 散文式描述,应改为标签 `人物参考图`。
+  - ❌ `生成的结果` —— 没语义。
+
+#### `value`(实例化的具体内容,不变)
+
+- 文本类的 value:原文片段或不超过 80 字凝练;图片 / 视频类的 value:可见物体或场景的简洁描述
+  (不要复制 URL,不要堆修辞)。
+
+### `source_ref`(步骤来源依据)
+
+- **含义**:你**凭什么判断**这一步存在 —— 把推断锚回到输入(图、正文片段、标题)。可追溯性来源。
+- **写法**:尽量具体,可同时引用多个来源,用 `/` 或 `、` 连接。
+- **推荐写法**:
+  - 引用图:`图1`、`图2`、`图3-图5`
+  - 引用正文:`正文第1句`、`正文:"先用黑色眼线胶笔填充内眼线"`(带原文片段更好)
+  - 引用标题:`标题: ins轻混血|木质粉亚裔妆`
+  - 混合:`图2 / 正文第3句`
+- **反例**:
+  - ❌ `推测` / `根据经验` / 空字符串 —— 缺少可追溯锚点。
+
+## 命名约定(强约束,违反会被工具拒绝)
+
+- **初始输入 id**:`init_input_<N>`,N 从 1 开始(如 `init_input_1`)。
+- **第 n 步的输出 id**:
+  - 单一输出:`p<n>_output`(如 `p1_output`)。
+  - 多输出:`p<n>_output_<M>`,M 从 1 开始(如 `p2_output_1`)。
+  - 全工序内必须唯一。
+- **inputs[*].source_id** 必须满足下列之一:
+  - 形如 `init_input_<N>`;或
+  - 是当前步骤之前已存在的某个 `outputs[*].id`。
+
+## 可用工具(必须通过这些工具改动工序,不要直接输出 JSON)
+
+**思考**
+
+1. `think_and_plan(thought, plan, action)` —— 仅用于记录思考,不修改状态。
+
+**新增**
+
+2. `add_step(step_id, name, actions, roles, purposes, source_ref, tool_name, tool_method)` —— 追加步骤骨架。`actions` / `roles` / `purposes` 都是字符串数组(空数组 `[]` 表示无据)。
+3. `add_step_input(step_id, modality, category, source_id, value)` —— 给步骤追加输入。
+4. `add_step_output(step_id, output_id, modality, category, value)` —— 给步骤追加输出。
+
+**修改**(部分更新,参数留 None 表示保持原值;只填想改的字段)
+
+5. `update_step(step_id, name=None, actions=None, roles=None, purposes=None, source_ref=None, tool_name=None, tool_method=None)` —— 部分更新;传 None 保持原值,传 `[]` / `""` 表示清空。`step_id` 不可改。
+6. `update_step_input(step_id, input_index, modality=None, category=None, source_id=None, value=None)` —— 改某项输入;用 `(step_id, input_index)` 定位,下标 0-based。修改 `source_id` 时会重新做依赖校验。
+7. `update_step_output(step_id, output_id, modality=None, category=None, value=None)` —— 改某项输出;`output_id` 不可改。
+
+**删除**(带引用完整性检查)
+
+8. `delete_step(step_id)` —— 删整步;若该步骤的某个输出仍被后续 step 的输入引用,会拒绝。
+9. `delete_step_input(step_id, input_index)` —— 删某项输入;输入没有反向引用,安全。注意删除后后面项的下标会前移。
+10. `delete_step_output(step_id, output_id)` —— 删某项输出;若被任何输入引用,会拒绝。
+
+**查询与收尾**
+
+11. `get_current_workflow()` —— 查看当前已经写到本地 JSON 的全部内容。**修改/删除前如果不确定 input_index 或 output_id,请先调用此工具确认**。
+12. `finalize_workflow(summary)` —— 收尾,标记 `status="finalized"`。
+
+## 必须遵守的工作流
+
+1. **先思考再动手**:开始任何写入前,至少调用一次 `think_and_plan`。
+   - 在 `plan` 字段中输出**初步的 step name 列表**作为工序主体脉络(这些是工作假设,不是最终答案)。
+   - 初步 name 只需粗略反映"动作+对象"即可,后续会回头精炼。
+   - 同时给出步骤数预估和整体拆解思路。
+2. **建骨架后再挂枝叶**:先 `add_step` 写入第 n 步(name 用初步版本即可,`actions`/`roles`/`purposes` 先从初步 name 反推 + 内容补充),
+   再为它依次 `add_step_input` / `add_step_output`,然后才能进入第 n+1 步。
+3. **I/O 阶段允许补全结构化字段**:填 `add_step_input` / `add_step_output` 时,如果发现 I/O 揭示了**初步 name 没体现的语义**
+   (新的目的维度、新的作用类别、新的动作),用 `update_step` 把 `actions` / `roles` / `purposes` 补全。**此阶段不必急着改 name**——name 留到 step 8 集中浓缩。
+4. **DAG 一致性**:每一个 `source_id` 要么是 `init_input_*`,要么必须命中**已存在的某个 output id**。
+   工具会做校验,引用未存在 id 会返回 `success=false`,请读取 `error` 字段并自纠。
+5. **多输出场景**:当某步骤产生不止一种产物(如同时给出文本描述和图片),用
+   `p<n>_output_1`、`p<n>_output_2` 命名,且每个都单独调一次 `add_step_output`。
+6. **允许迭代修正**:在 finalize 之前,发现哪一步写得不对,**应该主动**用
+   `update_*` 或 `delete_*` 修正,不要把错误留到最后。例如:
+   - 重新看图后判断 step 2 实际用的是局部重绘而不是整体重绘 → `update_step(step_id="2", tool_name="Photoshop", tool_method="Generative Fill", actions=["局部重绘"])`
+   - 发现 step 3 漏掉了一项文本输入 → `add_step_input(step_id="3", ...)`
+   - 发现 step 4 整体多余 → 先把引用它的输入处理掉,再 `delete_step(step_id="4")`
+7. **若要换 output_id**:因 output_id 不可改,按"先新加 → 切引用 → 删旧"的顺序:
+   先 `add_step_output` 一个新 id,再用 `update_step_input` 把所有引用切到新 id,
+   最后 `delete_step_output` 删掉旧 id。
+8. **集中 name 浓缩(finalize 前必做一次)**:所有 step + 所有 I/O 都写完后,**统一**对每个 step 的 name 做一次浓缩 review:
+   - 用现在完整的 `actions` / `roles` / `purposes` 与主要 I/O 的 `modality+category`,把 name 重写成**最佳浓缩自然语言**。
+   - 三条自检全过:可读性、跨内容可复用性、**反向分解一致性**(见 `name` 字段定义)。
+   - 横向看一遍所有 step 的 name 风格是否一致(句式、是否带目的、长度),不一致时拉齐。
+   - 已经是最佳浓缩的 step 可以跳过;需要改的调 `update_step(step_id=..., name="...")`。
+9. **收尾**:通过 step 8 的集中浓缩后,调用一次 `finalize_workflow(summary=...)`。summary 不超过 200 字,
+   概括整套工序的目标与最终产物。
+10. **自主完成**:全程不要询问确认,直接执行到 `finalize_workflow` 为止。
+
+## 拆解原则
+
+- **必须先满足上方「关键原则:客观还原,禁止臆造」**。下面只是辅助技巧,不能用来突破"无据不补"。
+- 优先按**图片之间可观察到的语义跃迁**切步骤(图 1 → 图 2 之间**明显**发生了什么变化,就对应一步操作)。
+  跃迁不明显时按上文规则**省略**该步,不要硬塞。
+- 步骤数应与图片数量大致匹配(每张图通常对应 1~2 步),但不强求一一对应。
+- `name` / `actions` / `roles` / `purposes` / `tool_name` / `tool_method` / `source_ref` 的写法见上文 **「字段定义」** 节,请严格对照其定义和反例。
+  特别注意:
+  - **`name` / `actions` / `roles` / `purposes` 四者同源**:`name` 是其它三者 + 主要 I/O 的 `category` 浓缩出的可读自然语言;
+    其它三者是 `name` 的结构化反向分解。结构化字段是完备真源,`name` 是其有损子集。
+  - **`tool_name`(产品)、`tool_method`(产品内能力,可观察证据)、`source_ref`(来源依据)** 与上面四者**职责不同**,
+    各自承载独立信息,不要互相窜行。
+- `value` 字段要写**实例化后的具体内容**:
+  - 文本类:填写文本本身或其凝练(≤80 字);
+  - 图片类:填写"是什么图"的简洁描述(如"带眼妆的人像照片"),不要复制图片 URL。
+- 优先把正文原文片段(如"先用黑色眼线胶笔填充内眼线")用在 `value` 或 `source_ref` 中,让结果可追溯。

+ 0 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec/taxonomy/README.md → examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/README.md


+ 402 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/action.json

@@ -0,0 +1,402 @@
+{
+  "$comment": "动作 字典树 (新结构: 获取/提取/生成/修改/存储). chip data-prefix=\"动作\". action 字段值用 根→叶 路径 (e.g. 提取/化学提取/解构). 单一来源, agent Phase 2 读. $control 是控制流类型 (与内容动作正交).",
+  "$kind": "taxonomy",
+  "$dimension": "动作",
+  "$field": "action",
+  "$path_separator": "/",
+  "$control": [
+    "并行",
+    "遍历",
+    "分支",
+    "请求",
+    "等待"
+  ],
+  "最终分类树": [
+    {
+      "分类名称": "获取",
+      "分类说明": "把已经存在的、完整的对象原样取来作为素材、参考或依据使用——动作本身不创造、不拆解、不改造对象。典型:检索 / 下载 / 调取 / 上传 / 拍摄 / 录音 / 键入 / 选取。判别口诀:输入与输出指向同一个完整对象(或对象集合),只是发生了'转移 / 引用',没有从内部抽出局部信息,也没有改变其形态。与'提取'的边界:获取拿到的是整体本身(如把一张参考图拿进工作流),提取拿到的是整体的派生物(如从这张图反推出文字 prompt)。与'生成'的边界:获取的对象是预先存在的,生成的对象是当前动作创造出来的新产物。\n\n【L2 切分维度】按'对象的来源位格'切分——搜索(工序外·公共域)/ 查询(工序外·私有·预存)/ 录入(工序外·私有·当场)/ 引用(工序内·自产)。一个获取动作的对象只可能位于这 4 个位置之一,MECE 完备。L2 本身只承担'来源位格'的目录定位,不作为 actions[] 取值。\n\n【L3 切分维度】每个 L2 内按'具体动作动词'切分。L3 节点直接作为 actions[] 字段的规范取值——本树即动作词典,不用'直接元素'承载同义词,所有近义动词在 L3 的分类说明中显式标注规范化目标。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "搜索",
+          "分类说明": "对象来自工序之外、面向公众开放的资源——互联网、公开素材库、搜索引擎、公共知识库、平台预设 / 模板、开源模型 / LoRA。判别:所有权 = 公共,任何人可访问。与'查询'的边界:搜索面向公共域,查询面向创作者 / 团队的私有积累(所有权差异)。与'录入'的边界:搜索是从公共域取来(创作者并未持有),录入是用户从自己手上当场提供。与'引用'的边界:搜索的对象来自工序外部,引用的对象来自工序内部的自产中间件。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "检索",
+              "分类说明": "输入查询 / 关键词 / 筛选条件 / 问题,从公共域里主动找出对象。涵盖:搜索引擎检索、库内关键词查询、对 LLM 的提问式知识获取、无明确 query 的浏览翻找(本质都是'在公共域里找')。与'下载'的边界:检索强调'查找定位'的过程(不知道精确位置),下载是'已知地址直接拿'(无需查询过程)。同义动作(写 actions[] 时统一规范为「检索」):查找 / 浏览 / 翻找 / 搜寻 / 问答式查询(对 LLM)。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "下载",
+              "分类说明": "已知精确地址(URL、ID、文件路径、API endpoint),直接获取指定对象。涵盖:URL 下载、API 拉取、网络抓取、按链接导入。与'检索'的边界:检索需要查询过程(不知精确位置),下载是已知位置直接取。与 L1'提取'的边界:下载是文件级整体获取(拿到完整对象本身),提取是从对象内部抽出局部 / 派生信息(拿到对象的一片或派生物)。同义动作(写 actions[] 时统一规范为「下载」):拉取 / 抓取 / 导入 / URL 拉取 / API 拉取。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "查询",
+          "分类说明": "对象来自工序之外、创作者或团队过去预存的私有资源——自建提示词库、个人素材库、团队成品库、自训风格 LoRA、参数预设、过去的成品。判别:所有权 = 私有 + 先于本次工序就已存在。与'搜索'的边界:查询走私有积累(创作者 / 团队专属),搜索走公共域。与'录入'的边界:查询的对象是预存的(先于本次工序),录入的对象是当下提供的(为本次工序专门接入)。与'引用'的边界:查询的对象在本次工序开始前就已存在于私库,引用的对象由本次工序内部前序步骤产出。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "调取",
+              "分类说明": "取用为复用目的而预存的'零件级'私有资产——这些资产以可被反复调取的单件形态存在。涵盖:自建 prompt 库的提示词、自训 LoRA / Embedding / 参数预设、私库素材(单件参考图 / 单段文案)、本地模型权重加载、个人收藏夹里的素材。与'检索'的边界:调取走的是已知地址直接拿(私库内单件资产有明确 ID / 路径),检索是面向公共域的查找定位过程。与 L1'修改'的边界:调取只是把已有资产'取来用'(对象不变),修改要在已有对象上做改动。同义动作(写 actions[] 时统一规范为「调取」):调用 / 复用 / 加载 / 引用(私库语境)/ 套用(私库模板 / 预设)。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "录入",
+          "分类说明": "对象来自用户 / 创作者在本次工序里当下提供的素材——为这次工序专门接入,不属于过去的预存积累。判别:素材的'接入时点'是本次工序开始或进行中(而非更早预存)。与'查询'的边界:录入是为本次工序专门提供(即使来自用户本地相册),查询取的是创作者过去就有的、可反复调用的私有库资产。与'搜索'的边界:来源是用户 / 创作者自己(私有),不是公共域。与'引用'的边界:录入是工序外的人为输入(用户从工序外送进来),引用是工序内的前序产物(DAG 内自循环)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "上传",
+              "分类说明": "用户提供'工序前就已存在'的既有素材——从设备本地、剪贴板等已有内容里拿出来给到工序。涵盖:本地文件上传、拖拽文件、粘贴既有内容(剪贴板里复制好的图 / 文 / 段落)、从本地相册选图。与'拍摄 / 录音 / 键入'的边界:上传的素材在用户提供时已经存在(既有),非现场制作。与'选取'(引用-工序内)的边界:上传是从工序外送入既有素材,选取是从工序内前序候选中挑选。同义动作(写 actions[] 时统一规范为「上传」):导入(本地)/ 粘贴 / 拖拽 / 上送 / 文件添加。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "拍摄",
+              "分类说明": "用户在工序中现场视觉捕获或产出图像 / 视频素材。涵盖:实时拍照、现场录像、屏幕录制(录自己的操作演示)、手绘 / 速写 / 涂鸦草图(现场画的简笔图也算'现场视觉产出')。与'上传'的边界:拍摄是现场制作(不是从既有里拿),上传是从既有里拿。与'录音 / 键入'的边界:输出形态是图像 / 视频。同义动作(写 actions[] 时统一规范为「拍摄」):录像 / 录屏(自己的)/ 手绘。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "录音",
+              "分类说明": "用户现场进行音频捕获或产出。涵盖:现场录音、口述录入、即兴配音、现场录歌。与'拍摄 / 键入'的边界:输出形态是音频。与'上传'的边界:现场录制,非既有音频文件提供。同义动作(写 actions[] 时统一规范为「录音」):录口述 / 配音录制。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "键入",
+              "分类说明": "用户现场进行文本或结构化参数录入——通过键盘、滑块、表单、选项控件等向工序输入文本或参数。涵盖:打字输入 prompt / 描述 / 文案 / 标题、调参(拖滑块 / 选下拉 / 勾选项)、表单填写。与'拍摄 / 录音'的边界:输出形态是文本或结构化参数。与'上传'的边界:现场敲入,非粘贴既有大段文本(粘贴既有归 上传)。同义动作(写 actions[] 时统一规范为「键入」):输入 / 调参 / 填写。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "引用",
+          "分类说明": "对象来自同一工序内已完成步骤的输出,被后续步骤再次拿来使用——来源是 DAG 内部,对象是工序自产的中间产物或前序成品。判别:source_id 指向的是同一工序内某个 outputs[*].id(而不是 init_input_*)。与'搜索 / 查询 / 录入'的边界:前三者来源都是工序外部(外取),引用来源是工序自身(内引)。与 L1'提取'的边界:引用拿到的是前序输出的整体本身(原样转交),提取是从前序输出里抽出局部 / 派生信息。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "选取",
+              "分类说明": "从前序步骤产生的多个候选对象中挑选一个或若干个进入下一步。涵盖:从模型出的多张候选图里挑、从生成的多个 prompt 候选里选、从多个分镜方案里取一个、从批量生成结果里筛优。判别口诀:必有'多候选 → 挑选'的过程,候选来自同一工序内的前序步骤;如果只是无差别地引用前序唯一输出(无挑选),不归选取。与'调取'的边界:选取的对象来源是工序内自产的候选池(DAG 内),调取的对象来源是工序外的私有库。与'上传'的边界:选取从工序内候选池里挑,上传从工序外(设备本地 / 剪贴板)拿既有素材。同义动作(写 actions[] 时统一规范为「选取」):挑选 / 筛选 / 评选 / 优选 / 圈选(多候选场景)。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "提取",
+      "分类说明": "从一个已有对象中抽出局部内容、属性、特征或派生信息——动作的输入是完整对象,输出是这个对象的'派生物'(描述、标签、文字、结构化数据、局部区域、轮廓、关键帧等)。典型:反推 / 识别 / OCR / 提取 / 抽取 / 分割 / 解析。判别口诀:输出在'形态'或'粒度'上不等同于输入——例如从图反推出文本 prompt(形态变了)、从图中识别物体名称(粒度变了)、从画面切出主体蒙版(粒度变了)。与'获取'的边界:获取得到的是整体本身,提取得到的是整体的派生物。与'修改'的边界:提取的输出与输入不是'同类对象的改前/改后',而是'整体与它的派生物'。\n\n【本质】提取是'信息由多到少'的压缩动作——从一个完整对象里减信息、得到一个更小的派生产物。这种压缩有两条不同的实现路径,对应 L2 切分。\n\n【L2 切分维度】按'输出与原对象的关系'切分——实体片段(输出是原对象的实体一片,能在原对象里指出来)/ 派生信息(输出是关于原对象的派生信息,原对象里指不出来)。一个提取动作的输出只可能位于这 2 类之一,MECE 完备。\n\n【L3 切分维度】每个 L2 内按'具体动作动词'切分。L3 节点直接作为 actions[] 字段的规范取值——本树即动作词典,不用'直接元素'承载同义词,所有近义动词在 L3 的分类说明中显式标注规范化目标。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "物理提取",
+          "分类说明": "输出是原对象的实体片段——能在原对象里直接指出'就是这一块',输出与输入同质且是其物理子集。判别口诀:能不能在原对象里圈出输出对应的那部分(地理 / 时间 / 结构上的子区域)?能 = 实体片段。与'派生信息'的边界:实体片段的输出是原对象的'一片'(同质、可指认),派生信息的输出是关于原对象的'描述 / 特征 / 分析'(异质、原对象里指不出来)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "裁切",
+              "分类说明": "按几何区域、时间区间或位置索引等明确规则把原对象的某一块切出来——切的边界由规则定义,不依赖语义判断。涵盖:矩形 / 自由形状裁剪、按时间轴截取视频 / 音频片段、按段落 / 句子位置取文本片段。与'抠取'的边界:裁切的边界是规则定义的几何区域(不需要理解内容),抠取的边界是语义边界(需要识别对象轮廓)。与'抽帧'(时序场景)的边界:裁切按规则切'连续段',抽帧按重要性抽'离散关键点'。同义动作(写 actions[] 时统一规范为「裁切」):裁剪 / 截取片段 / 切片 / 取段。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "抠取",
+              "分类说明": "按语义边界把特定对象 / 组件从原对象中切出——切的边界由对象本身的形状 / 层次 / 结构决定,需要识别后再切。涵盖:抠图主体(按对象轮廓切)、人物 / 物体分割、拆 PSD 图层(按图层结构切)、demux 音视频轨道(按轨道结构切)。与'裁切'的边界:抠取按对象语义切,裁切按几何规则切。同义动作(写 actions[] 时统一规范为「抠取」):分割 / 抠图 / 拆图层 / 拆轨道。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "抽帧",
+              "分类说明": "从时序媒体(视频 / 音频 / 动画)中抽出离散的关键时刻或代表性片段——抽出来的每一帧 / 段都是原时序的一个截面。涵盖:视频关键帧、代表性时刻、典型片段、采样帧。与'裁切'(时间区间切)的边界:裁切是按规则切'连续段',抽帧是按重要性抽'离散关键点'。同义动作(写 actions[] 时统一规范为「抽帧」):取关键帧 / 采样 / 取代表帧。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "化学提取",
+          "分类说明": "输出是关于原对象的派生信息——原对象里直接指不出来,是从原对象推算 / 解读 / 提炼出来的派生产物。判别口诀:能不能在原对象里圈出输出对应的那部分?不能 = 派生信息。涵盖:表层显式信息的读取(识别)、深层隐含信息的推理(反推:风格 / 情感 / 意图 / 深度 / 姿态等)、内部组成方式的结构化拆解(解构:章节 / 框架 / 要点 / 摘要)。与'实体片段'的边界:派生信息的输出与输入异质(图 → 文 / 数 / 标签 / 表征图),不是原对象的物理子集。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "识别",
+              "分类说明": "读取原对象表层显式存在、可直接观察到的信息——把眼睛能看到、耳朵能听到的东西转成可处理的标签 / 文字 / 数据。涵盖:OCR 文字识别、物体识别(detection + classification)、人脸识别、场景识别、语音转文字、命名实体识别(NER)。与'反推'的边界:识别处理的是表层显式信息(信息就在眼前,只是换种形态),反推处理的是深层隐含信息(需要推理才能得到)。同义动作(写 actions[] 时统一规范为「识别」):检测 / OCR / 转录 / 标注。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "反推",
+              "分类说明": "推理出原对象深层隐含、不可直接观察的信息——需要'从结果推回原因 / 构成'的推理过程。涵盖两大类:(1)语义反推:反推 prompt、风格分析、情感分析、意图推断、创作手法推断;(2)结构表征反推:depth map / canny 边缘 / normal map / pose 骨架 / segmentation mask 等 ControlNet 类预处理(这些 map 都不在原图直接可见,是从 RGB 推算出来的隐含结构)。与'识别'的边界:识别读表层显式(图里的字、物体),反推推深层隐含(图的风格、深度、生成原因)。与'解构'的边界:反推推理'隐含的属性 / 原因 / 表征'(风格 / 情感 / depth 结构),解构分析'显式的内部组成方式'(层级 / 框架)。同义动作(写 actions[] 时统一规范为「反推」):推断 / 分析 / 预处理(ControlNet 类)/ 估计(深度 / 姿态)/ 风格分析 / 情感分析。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "解构",
+              "分类说明": "系统性地把原对象拆解成结构化的层级分析——输出是关于原对象内部组成方式的'结构描述',而不是原对象本身的物理碎片。涵盖:拆剧情结构(场景 / 冲突 / 转折)、拆构图层级(前景 / 中景 / 背景,三分法 / 对称)、拆文章章节框架(引言 / 论点 / 论据 / 结论)、拆角色构成(服饰 / 发型 / 姿态 / 表情)、内容浓缩与提炼(摘要 / 要点提炼 / 核心信息抽取)。与'抠取'的边界:抠取是物理拆分(输出是原对象的实体片段),解构是分析拆分(输出是关于原对象组成的描述)。与'反推'的边界:反推推理'隐含的属性 / 原因 / 表征'(风格 / 情感 / depth 结构),解构分析'显式的内部组成方式'(章节 / 层次 / 框架 / 要点)。同义动作(写 actions[] 时统一规范为「解构」):拆解(结构)/ 结构分析 / 框架分析 / 层级分析 / 摘要 / 要点提炼。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "生成",
+      "分类说明": "从无到有产出新的对象——动作本身不依赖某个被改造的'前身'对象,仅依靠引导信息(如 prompt、参考、规则、知识)创造出之前不存在的产物。典型:生成 / 文生图 / 文生视频 / 合成 / 补全 / 生成草图 / 起草。判别口诀:输出是一个新对象(图、文本、视频、音频),其'实体'在输入中并不存在;输入即使含参考素材,参考也只是引导而非'被改造的本体'。与'修改'的边界:生成的输出没有可对应的'同一个对象的前一版本',修改的输出能与输入对应到'同一个对象的不同形态'。与'获取'的边界:生成的对象是当前动作产出的全新产物,获取的对象是预先就存在的。\n\n【本质】生成是'产生信息增量'的动作——给出一个之前不存在的新信息片段。\n\n【L2 切分维度】按'增量结果的形态'切分——元素生成(结果是一个自成一体的独立单元)/ 关系生成(结果是多项之间的明确关系结构)。两类 MECE 完备:要么是单件独立单元,要么是多项 + 关系。L2'元素生成'本身即叶子节点,不再向下切分;L2'关系生成'下再按关系几何形态切分 L3。\n\n【L3 切分维度】关系生成下按'关系的几何形态'切分——数组生成(一维线性顺序)/ 结构生成(非线性结构 / 共时并置)。两类 MECE 完备:要么是先后排列,要么是同时并置。\n\n【actions[] 规范取值】叶子节点(元素生成 / 数组生成 / 结构生成)直接作为 actions[] 字段的规范取值。本树即动作词典,所有近义动词在叶子分类说明中显式标注规范化目标。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "元素生成",
+          "分类说明": "生成结果是一个自成一体的单个对象——对外是一个独立单元,不论内部是简单还是复合。涵盖:文生图(一张图)/ 图生图(产出新的一张图)/ 文生视频片段(一段独立短片)/ 起草文案(一段独立文本)/ 起草脚本(一份独立脚本)/ 生成单个角色 / 生成 BGM / 生成单个模板 / 生成单条 prompt。判别口诀:结果能否被指称为'一个 X'(一张图 / 一段视频 / 一份文案 / 一条 prompt)?能即归此。与'数组生成 / 结构生成'的边界:元素生成的产物对外呈一个独立单元(即使内部含多部件也对外呈一个),关系生成的产物本质是'多项 + 关系结构'。同义动作(写 actions[] 时统一规范为「元素生成」):起草 / 写稿 / 文生图 / 文生视频(单段)/ 图生图(单张产出)/ 草图生成 / 单件生成 / 撰写。",
+          "直接元素": [],
+          "子分类": [],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "关系生成",
+          "分类说明": "生成结果是多项之间的明确关系结构——多个东西按某种顺序 / 结构关联在一起。判别口诀:结果是否本质上是'多项 + 关系'(一组镜头序列、一套配色方案、一幅多元素布置)?是 = 关系。与'原子'的边界:原子结果对外是一个独立单元,关系结果是多项的关联结构。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "数组生成",
+              "分类说明": "生成结果是多项的线性顺序——给一组项确定它们的先后排列。涵盖:剧本时序、镜头序列、步骤清单、台本顺序、视频片段时间线、分镜先后、大纲排序、章节排序、教程步骤排布。判别口诀:产物的核心信息是'若干项 + 一条单向时间 / 顺序轴',调换顺序会破坏产物意义。与'元素生成'的边界:数组生成必含多项 + 先后约束(关系是核心信息),元素生成只是单个对象(无内部先后关系)。与'结构生成'的边界:数组是一维顺序(先后排列),结构是非线性 / 共时并置。同义动作(写 actions[] 时统一规范为「数组生成」):编排 / 串联 / 排序 / 时序排布 / 序列生成 / 时间轴编排 / 章节排序 / 剧本编排。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "结构生成",
+              "分类说明": "生成结果是多项的非线性结构——多个项以某种结构关系(融合 / 配合 / 空间布置 / 层级叠加)组合在一起。涵盖:场景画面合成、配色方案、UI 布局、多元素拼贴、风格 + 内容搭配、图层组合、版式构图、信息图组装、多视图布置。判别口诀:产物的核心信息是'多项 + 共时并置 / 空间层级关系',去掉任一元素或挪位置会破坏整体。与'数组生成'的边界:结构是非线性 / 共时并置(同时呈现),数组是一维线性顺序(先后排列)。与'元素生成'的边界:结构生成必含'多项 + 组合关系',元素生成是单件独立单元。同义动作(写 actions[] 时统一规范为「结构生成」):合成 / 搭配 / 布置 / 组合 / 拼贴 / 布局生成 / 配色生成 / 图层组合生成 / 版式生成。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "修改",
+      "分类说明": "在已有对象的基础上做改动——输入是一个待改造的本体对象,输出是它被改动后的版本,对象的身份保留但形态 / 属性 / 局部已发生变化。典型:编辑 / 局部重绘 / 上色 / 重打光 / 去背景 / 换脸 / 换装 / 修饰 / 增强 / 改写 / 翻译 / 风格化 / 转换 / 超分。判别口诀:能在输入与输出之间指认出'同一个对象'的'改前 / 改后'对应关系——超分前后是同一张图,改写前后是同一段文本。与'生成'的边界:修改有明确的'被改造本体',生成没有;若产物的主体来自输入对象的延续 → 修改,若产物的主体由动作新造 → 生成。与'提取'的边界:修改的输出仍是同类完整对象,提取的输出是输入的派生物(不同粒度或不同形态)。\n\n【L2 切分维度】按'改动性质'分 3 类——增(添加新的信息片段)/ 删(去除已有的信息片段)/ 变(改变已有部分:原位置上的替换 / 重述 / 风格化 / 格式转换 / 渐变调整 / 自动增强)。三类 MECE 完备:要么加新(信息总量增加)、要么去旧(信息总量减少)、要么原位置改变(信息总量基本不变,只是某部分变成不一样的)。\n\n【L3 切分维度】每个 L2 内按'具体动作动词'切分。L3 节点直接作为 actions[] 字段的规范取值——本树即动作词典,不用'直接元素'承载同义词,所有近义动词在 L3 的分类说明中显式标注规范化目标。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "增",
+          "分类说明": "添加新的信息片段到原对象上——原对象的现有部分保留,新内容 / 形态 / 装饰被叠加 / 嵌入进去。判别口诀:动作前后比较,原对象多了一些之前没有的信息。与'删'的边界:增是加新的(信息总量增加),删是去已有的(信息总量减少),方向相反。与'变'的边界:增是单纯加新(原位置不变,多出一份),变是在原位置上把已有部分改成不一样的(替换 / 渐变,无新增独立单元)。\n\n【L3 切分维度】按增加对象的层级切分——添加(substantive 内容元素的增)/ 叠加(form 形态层 / 装饰层的增)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "添加",
+              "分类说明": "在原对象上增加新的语义内容元素——给画面新增一个主体 / 物体 / 角色,给文案新增一段内容,给视频新增一段片段,给脚本新增一段动作。判别口诀:动作前后比较,原对象多出了一个独立的语义内容元素,这个元素本身就是'被增加的内容'(有独立语义身份:人 / 物 / 段 / 镜)。与'叠加'的边界:添加加的是内容层(substantive,多出一个独立语义元素),叠加加的是形态层(form,多出一层装饰性 / 标识性 / 修饰性形态)。与'替换'的边界:添加只加不去(原对象不变,多出一份),替换是去旧 + 换新(一删一加)。与'增强'的边界:添加是主动放入新元素(创作者指定内容),增强是自动质量提升(无新增内容)。同义动作(写 actions[] 时统一规范为「添加」):新增 / 添入 / 加入 / 加段 / 加镜 / 加角色 / 加物体 / 补段 / 补镜。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "叠加",
+              "分类说明": "在原对象上叠加新的形态层 / 装饰层——给画面叠加水印 / logo / 装饰图层 / 边框、给视频叠加字幕轨 / 弹幕、给文档叠加页眉页脚、给图叠加蒙层 / 滤色层。判别口诀:动作前后比较,原对象多出了一层不属于'语义内容主体'的装饰性 / 标识性 / 修饰性形态。与'添加'的边界:叠加加的是形态层(装饰 / 标识 / 修饰,不构成独立语义内容),添加加的是内容层(独立语义元素:人 / 物 / 段 / 镜)。与'风格化'(变)的边界:叠加是在原对象上多出一层独立可见的形态元素(水印 / logo 是可指认的一层),风格化是对原对象整体外观做转换(无独立可指认的新层)。同义动作(写 actions[] 时统一规范为「叠加」):加水印 / 加 logo / 加图层 / 加装饰 / 加边框 / 加蒙层 / 加字幕轨 / overlay / 嵌入标识。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "删",
+          "分类说明": "去除原对象的某部分信息——原对象的其余部分保留,被去除的部分从对象中消失。判别口诀:动作前后比较,原对象少了一些之前有的信息(信息总量减少)。与'增'的边界:删是去已有的(少一份),增是加新的(多一份),方向相反。与'变'下'替换'的边界:删只去不补(原位置变空),替换是去掉再补上不同的(原位置仍有内容,只是换成了别的)。\n\n【L3 切分维度】按被删除信息的空间 / 时间维度切分——抹除(空间维度内的内容删除)/ 剪除(时间维度上的片段删除)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "抹除",
+              "分类说明": "去除空间内的内容元素——把对象空间维度上的某部分内容擦掉 / 去掉。涵盖:去背景、去水印、去画面里的某个角色 / 物体、抹除画面瑕疵。与'剪除'的边界:抹除针对'空间内'的内容(同一画面 / 同一帧里的某部分),剪除针对'时间维度'的片段(视频 / 序列里的某段时间)。同义动作(写 actions[] 时统一规范为「抹除」):擦除 / 移除 / 抠除 / erase。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "剪除",
+              "分类说明": "剪掉时间维度的片段——把对象时间序列上的某段去掉。涵盖:剪掉视频中的一段、删除文章中的一节、截短音频、去掉序列中的某项。与'抹除'的边界:剪除针对'时间维度'的片段,抹除针对'空间内'的内容。同义动作(写 actions[] 时统一规范为「剪除」):剪 / 截短 / 删段 / cut。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "变",
+          "分类说明": "改变已有部分——原对象的内容 / 形态 / 属性 在原位置发生变化,无论是离散切换(替换:A → B)还是连续渐变(重述 / 风格化 / 转换 / 调整 / 增强)。判别口诀:动作前后比较,原对象的某部分'变成不一样的'(不是新增、不是删除,而是原位置改变);信息总量基本不变。与'增 / 删'的边界:变不改变信息总量(原位置改),增加新信息(多一份),删去除信息(少一份)。\n\n【L3 切分维度】按改变方式切分——替换(categorical 离散切换:A → B 实体不同)/ 重述(保原意改表达)/ 风格化(换审美 / 视觉风格)/ 转换(换技术形式 / 媒介 / 格式)/ 调整(continuous 手动微调属性)/ 增强(自动质量提升)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "重述",
+              "分类说明": "实质改述——保留原意,改造表达 / 表述方式。涵盖:改写文段、翻译(中 → 英 / 英 → 中)、重构表述结构、转写口吻(书面 → 口语 / 正式 → 随意)、改述要点 / 段落润色。与'替换'的边界:重述保原意改表达(同一段意思的不同说法),替换是把整段内容主体换成不同的另一段(意思可不同)。与'风格化'的边界:重述改文字的'表达方式'(语种 / 用词 / 结构),风格化改文字 / 画面的'审美调性'(如转某文风、转某腔调、转视觉风格)。与'转换'的边界:重述走表达层(同语种内换说法 / 改写),转换走形式承载层(语种 / 格式 / 媒介整体切换)。同义动作(写 actions[] 时统一规范为「重述」):改写 / 翻译 / 重写 / 重构 / 改述 / 润色 / paraphrase / 转写口吻。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "风格化",
+              "分类说明": "换审美 / 视觉风格——同一对象在视觉风格上的转换,本体内容大致保留。涵盖:卡通化 / 油画化 / 写实化 / 水彩化、转赛博朋克风、转日漫风、文字转某文风。与'转换'的边界:风格化是'审美层面'的风格转换(卡通 / 油画 / 水彩等审美调性),转换是'技术形式'的格式 / 媒介 / 语种切换。同义动作(写 actions[] 时统一规范为「风格化」):风格转换 / 风格迁移 / stylize / style transfer。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "转换",
+              "分类说明": "换技术形式 / 媒介 / 格式 / 语种——同一对象在技术承载形式上的转换。涵盖:jpg → png(格式)、mp4 → gif(媒介格式)、横屏 → 竖屏(画幅形式)、PDF → Word(文档格式)、中 → 英(语种形式,作为形式转换而非内容改述时)、文 → 音(TTS 形式承载)。与'风格化'的边界:转换是'技术形式 / 格式'变化(容器变,呈现方式可能变),风格化是'审美 / 视觉风格'变化(容器不变,审美调性变)。与'重述'的边界:转换走形式承载层(语种 / 格式 / 媒介整体切换),重述走表达层(同语种内换说法)。与'调整'的边界:转换是 categorical 形式切换(jpg → png),调整是 continuous 属性微调(在原值附近滑动)。同义动作(写 actions[] 时统一规范为「转换」):转格式 / 转媒介 / 改格式 / convert / 转语种 / 转分辨率(格式语境)/ 转编码。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "替换",
+              "分类说明": "用不同的对象 / 元素 / 内容把原位置上的整个对应部分换掉——离散切换(categorical),新旧之间是不同的实体,不是渐变。涵盖:换脸 / 换装 / 换背景 / 换发型 / 换角色 / 换台词段 / 整段文案替换 / 整段镜头替换 / 换字体 / 换配色(指定枚举值)。判别口诀:动作前后比较,原位置上'这个东西'被换成'另一个东西'(A → B 的离散切换),不是 A 自身的渐变改造。与'重述'的边界:替换换内容主体(A 段换成 B 段,意思可不同),重述保原意改表达(同一段意思的不同说法)。与'调整'的边界:替换是 categorical 离散切换(A → B 实体不同),调整是 continuous 渐变(在原值附近滑动)。与'添加'的边界:替换是去旧 + 换新一并发生(原位置仍有内容,只是变了),添加是单纯加新不动旧。与'风格化'的边界:替换是某个具体元素被换成另一个具体元素(局部对象层),风格化是整体审美调性的切换(整图 / 整段层)。同义动作(写 actions[] 时统一规范为「替换」):换 / 替 / 换脸 / 换装 / 换背景 / 换角色 / replace / swap / 替代。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "调整",
+              "分类说明": "渐变属性值(手动微调)——属性值在原位置附近做连续 / 渐变性的微调。涵盖:调色 / 调亮 / 调对比 / 调饱和、调音量 / 调音色、调速度 / 调节奏、调透明度、调位置(局部微调)/ 调大小(局部微调)。与'替换'的边界:调整是 continuous 微调(在原值附近滑动),替换是 categorical 切换(A → B 离散值)。与'增强'的边界:调整是'手动渐变'(创作者主动指定方向 / 幅度),增强是'自动质量提升'(系统智能修复 / 提升,无创作者主观方向)。与'风格化'的边界:调整改的是低层属性数值(亮度 / 对比 / 速度),风格化改的是高层审美调性(卡通化 / 油画化)。同义动作(写 actions[] 时统一规范为「调整」):调 / 校 / 微调 / fine-tune / adjust / 校色 / 调音。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "增强",
+              "分类说明": "自动质量提升——系统智能算法对对象做自动质量改善,无需创作者指定具体方向 / 数值。涵盖:超分(提分辨率)、降噪、锐化、补帧、修复瑕疵 / 自动修图、画质增强、音频降噪 / 增强、人像自动美化、自动去模糊。判别口诀:算法自己决定怎么改、改多少(创作者只决定'要不要做'),且不增减语义内容(不改变'画面里有什么')。与'调整'的边界:增强是'自动算法'提升质量(创作者只按按钮),调整是'手动渐变'微调属性(创作者指定方向 / 幅度)。与'添加'的边界:增强是属性维度的整体质量提升(不增减语义内容),添加是新增独立语义元素(多出一个新对象)。与'替换'的边界:增强不改变对象身份(只是更清晰 / 更干净),替换是把对象换成不同的另一个。同义动作(写 actions[] 时统一规范为「增强」):超分 / 降噪 / 锐化 / 补帧 / 修复 / 画质提升 / enhance / 自动修图 / 一键美化。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "存储",
+      "分类说明": "把当前持有的对象保存到某个存储位格,使其在未来可被再次取用——动作本身不创造、不改变对象,只是把对象的拷贝放到指定的存储位格。典型:保存 / 暂存 / 入库 / 沉淀 / 归档 / 留底。判别口诀:输入是工序内已有的对象,输出是'同一对象被放到了某个存储位格里'(对象本身不变,只是落地位置发生变化)。与'获取'的边界:存储是把工序内的对象往外送到存储位格(工序内 → 存储位格,写入侧),获取是从存储位格取回到工序内(存储位格 → 工序内,读取侧),二者方向相反。与'生成'的边界:存储不产生新对象(只是搬运现有对象的拷贝),生成产出之前不存在的新产物。与作用树'交付'的边界:交付是把产物推向终态对外(功能性归宿,发布意义),存储侧重把产物保留到可被未来调用的位置(持久化意义,可不对外)。\n\n【L2 切分维度】按'存储位格的位置 / 时效'切分——暂存(工序内·临时缓存,per-batch 用完即释)/ 沉淀(工序外·私有·长效,跨工序反复调用)/ 归档(工序外·长期封存,被动留底)。三种位格 MECE 完备,且与'获取'L2 形成对称关系(沉淀对应查询、暂存对应引用)。\n\n【L3 切分维度】每个 L2 内按'具体动作动词'切分。L3 节点直接作为 actions[] 字段的规范取值——本树即动作词典,不用'直接元素'承载同义词,所有近义动词在 L3 的分类说明中显式标注规范化目标。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "暂存",
+          "分类说明": "对象被存放在本次工序内 / 当前会话内的临时缓存——只在本次工序内可被再次引用,工序结束后不保证存活。判别:存放位置是工序自身的中间缓存,不是跨工序的持久化位格。与'沉淀'的边界:暂存是 per-batch / 本次工序内的临时态(用完即释),沉淀是跨工序的长效私库(可被未来工序反复调取)。与获取树'引用'的边界:暂存是'把对象放到工序内缓存里'(写入侧),引用是'从工序内缓存取出来用'(读取侧),二者配对完成 DAG 内自循环。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "缓存",
+              "分类说明": "把对象放到工序内 / 会话内的临时缓存里,供本次工序后续步骤复用。涵盖:节点输出缓存 / 中间产物保留 / 临时变量存放 / session 级 cache / 草稿暂存。判别:存放期限仅限本次工序 / 当前会话,工序结束后通常被释放。同义动作(写 actions[] 时统一规范为「缓存」):暂存 / 临时保存 / 草稿存 / cache / hold / 中间产物保存。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "沉淀",
+          "分类说明": "对象被存进创作者 / 团队的私有积累库,作为未来跨工序复用的资产。判别:存放位置是跨工序的长效私库(个人库 / 团队库 / 模板库),未来可被反复'查询.调取'取出。与'暂存'的边界:沉淀是跨工序长效(可被未来反复调用),暂存是本工序临时(用完即释)。与'归档'的边界:沉淀的目的是'供未来反复调用'(活跃资产 / 高频复用),归档的目的是'长期封存留底'(被动留底 / 低频访问)。与获取树'查询'的边界:沉淀是'把对象放进私库里'(写入侧),查询.调取是'从私库里取出来用'(读取侧),二者配对完成私库读写循环。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "入库",
+              "分类说明": "把对象作为私有零件级资产存进库里,供未来反复调用。涵盖:提示词入库 / 素材入库 / 模板入库 / 风格预设入库 / 参考图收藏入库 / 文案模板入库 / 镜头库入库 / LoRA 与 Embedding 等权重文件入库。判别:被存入的对象以'可被反复调取的单件形态'存在,目的是为下一次生产复用。与'存档'的边界:入库的对象是为'活跃复用'而存(高频调取),存档的对象是为'长期留底'而存(低频回溯)。同义动作(写 actions[] 时统一规范为「入库」):存入私库 / 收藏 / 加入收藏 / 模板沉淀 / 提示词沉淀 / 素材沉淀 / 加入素材库 / 权重入库。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "归档",
+          "分类说明": "对象被长期封存留底——目的不是供未来反复调用,而是保留历史记录 / 留底备查 / 合规存档 / 法定保留期。判别:存放位置是冷存储 / 历史归档,调用频率极低(被动访问 / 偶发回溯)。与'沉淀'的边界:归档强调'长期封存留底'(被动留底,访问稀少),沉淀强调'供未来反复调用'(活跃资产,频繁取用)。与作用树'交付'的边界:交付是把产物推到对外终态(功能完成意义),归档是把产物(无论是否已交付)存进历史档案(留底意义,可发生在已交付之后)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "存档",
+              "分类说明": "把对象(含成片、底稿、流程配置、版本快照)存进长期档案中,留底备查。涵盖:项目归档 / 版本快照存档 / 成片冷存档 / 流程配置存档 / 历史版本封存 / 工程文件归档 / 工作流配置存档。判别:存储动作的目的是'留底'而非'复用'。同义动作(写 actions[] 时统一规范为「存档」):归档 / 封存 / 冷存 / 留底 / archive / 版本快照 / 工程归档。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    }
+  ],
+  "$leaves": [
+    "检索",
+    "下载",
+    "调取",
+    "上传",
+    "拍摄",
+    "录音",
+    "键入",
+    "选取",
+    "裁切",
+    "抠取",
+    "抽帧",
+    "识别",
+    "反推",
+    "解构",
+    "元素生成",
+    "数组生成",
+    "结构生成",
+    "添加",
+    "叠加",
+    "抹除",
+    "剪除",
+    "重述",
+    "风格化",
+    "转换",
+    "替换",
+    "调整",
+    "增强",
+    "缓存",
+    "入库",
+    "存档"
+  ]
+}

Разница между файлами не показана из-за своего большого размера
+ 69 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/effect.json


+ 21 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/feature.json

@@ -0,0 +1,21 @@
+{
+  "title": "特性 (执行特征 + 控制流)",
+  "desc": "随机/幂等/写外部/读外部/人工/本地; 控制流: 并行/遍历/分支/请求/等待",
+  "tree": {
+    "执行特征": {
+      "随机": "非确定性输出",
+      "幂等": "相同输入相同输出",
+      "人工": "由人执行",
+      "本地": "本地完成",
+      "写外部": "修改外部状态",
+      "读外部": "读取外部状态"
+    },
+    "控制流": {
+      "并行": "同时执行多分支",
+      "遍历": "对序列每项",
+      "分支": "条件分支",
+      "请求": "请求外部",
+      "等待": "等待外部"
+    }
+  }
+}

+ 562 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/type.json

@@ -0,0 +1,562 @@
+{
+  "$comment": "类型 字典树 (新结构, 按功能角色组织: 程序控制/数据复用/内容/知识). 单一来源, agent Phase 2 直接读. $leaves 由 最终分类树 终端节点自动派生 (scratch/build_taxonomy.py 生成), 供 lint-case.py 校验 + renderer in_tree 标记. case-specific 新 type 走 workflow.json 各 procedure 的 type_registry (extends 一个本表叶子).",
+  "$kind": "taxonomy",
+  "$dimension": "类型",
+  "$field": "type",
+  "最终分类树": [
+    {
+      "分类名称": "程序控制类型",
+      "分类说明": "L0 大类——这个产出物的作用是控制一次或多次内容产出'要做成什么、用什么参数、怎么评、按什么流程跑'。判别口诀:它本身不是内容、不参与组装产物,而是被某次加工参考来左右生成过程或评判结果的控制信号 / 自动化配置。下辖的指令 / 参数 / 评估 / 流程 都是程序控制的一种:指令直接指挥单个内容单元'要什么 / 不要什么 / 长什么样',参数设定生成 / 加工的技术配置或装载件,评估通过对已产出物的评判驱动修改或取舍,流程把多步加工编排成可被自动跑通的配置。与'内容类型'的边界:程序控制不构成交付内容本身,内容类型是被生产、被交付的内容实体。与'数据复用类型'的边界:程序控制服务于生产过程的执行控制,数据复用是被反复装载 / 填充的内容性资产。与'知识类型'的边界:程序控制是被执行的指令 / 配置(机械生效),知识是被理解 / 借鉴的认知储备。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "指令",
+          "分类说明": "作用类别——这个产出物会被一次生成 / 加工当作'要做成什么'的规约来执行,下游步骤照着它产出一个内容单元。判别口诀:它对应一次具体生成、一个内容单元,规定这一个单元的内容长什么样。与'编排'的边界:指令管单个生成单元的内容(这一个具体要什么),编排管多部分作品的骨架与顺序(整体分几块、什么顺序)。与'约束'的边界:指令规定'要什么内容'(内容侧),约束规定'结构落在哪个区域 / 骨架'(空间侧)。与'参照'的边界:指令是被读懂、被执行的文字规约,参照是被看着模仿的样本实体。与'复用'的边界:指令是为当次产出专门写的、用完即弃的规约,复用是跨任务反复取用的。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "提示词",
+              "分类说明": "向生成模型发出的正向提示词,作为模型调用的指令载体——可以是一条,也可以是成库的多条。与'负向提示词'的边界:方向相反(一个吸引、一个排斥),是独立的字段位。同义术语(写 category 时统一规范为「提示词」):prompt / 正向提示词 / positive prompt / 提示词库。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "负向提示词",
+              "分类说明": "向生成模型发出的负向约束词,告诉模型'不要出现什么'。与'提示词'的边界:方向相反(一个吸引、一个排斥),是独立的字段位,不要混入正向提示词。同义术语(写 category 时统一规范为「负向提示词」):negative prompt / 反向提示词。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "描述",
+              "分类说明": "对某一对象的文字刻画——以'描述'这个制作形式角色命名,被描述的具体对象(人物 / 场景 / 妆容 / 风格 / 构图 / 氛围 等内容实质)写入 value 字段,不进入叶子名。判别:是描述性文字,在工序里作为生成的内容依据被执行。与'提示词'的边界:描述是'被描述的对象内容',提示词是'喂给模型的指令'(描述可作为提示词的一部分,但其本身的角色是描述文本)。同义术语(写 category 时统一规范为「描述」):人物描述 / 场景描述 / 妆容描述 / 风格描述 / 运镜描述(若不带时序)。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "参数",
+          "分类说明": "作用类别——这个产出物是控制一次生成 / 加工'技术参数 / 工具运转方式'的配置。判别口诀:它不规定内容、不限定空间,而是设定模型 / 工具按什么参数跑、产出什么规格。与'指令'的边界:指令管'要什么内容',参数管'用什么参数生成'。与'约束'的边界:约束限定空间边界,参数设定技术配置。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "生成参数",
+              "分类说明": "一次生成 / 加工所用的模型运行参数——涵盖:采样步数 / CFG / 采样器 / 随机种子 seed / 去噪强度 / LLM 温度 等。被设定的具体目的由 value 承载。与'规格参数'的边界:生成参数是'模型怎么算',规格参数是'产出物什么格式'。同义术语(写 category 时统一规范为「生成参数」):采样参数 / 模型参数 / seed / 生成配置。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "规格参数",
+              "分类说明": "对产出物格式规格的设定——涵盖:分辨率 / 尺寸 / 画幅比例 / 时长 / 帧率 / 码率 / 文件格式 等。与'生成参数'的边界:规格参数是产出物的格式形态,生成参数是模型运行的算法参数。同义术语(写 category 时统一规范为「规格参数」):分辨率 / 画幅 / 比例 / 时长设定 / 输出规格。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "模型权重",
+              "分类说明": "训练或微调得到的模型权重文件——套用时加载到生成模型上,改变模型的生成行为。涵盖:LoRA / Embedding / checkpoint / Hypernetwork / DreamBooth。被定制的具体目标由 value 字段承载,不进入叶子名。同义术语(写 category 时统一规范为「模型权重」):LoRA / Embedding / checkpoint / 权重包。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "评估",
+          "分类说明": "作用类别——这个产出物是对另一个产出物的评判 / 意见,会被采纳来驱动对被评对象的修改或取舍。判别口诀:它一定指向一个已存在的产出物、对它下判断(好不好、改哪里、选哪个),而不是凭空规定要做什么。与'指令'的边界:指令是前置的、凭空规定要做什么的规约,评估是后置的、针对已有产出的评判(评估必然预设一个被评对象,指令不预设)。与'知识'的边界:评估针对某一个具体产出、一次性、驱动当次迭代,知识是跨任务沉淀的通用认知。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "评分",
+              "分类说明": "对某个产出物给出的定量评判——分数 / 等级 / 排名,用于驱动取舍(如从候选里挑高分的)。与'评语'的边界:评分是定量结论(数字 / 等级),评语是定性的文字意见。同义术语(写 category 时统一规范为「评分」):打分 / 评级 / 排名 / score。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "评语",
+              "分类说明": "对某个产出物给出的定性文字评判——指出问题、给出修改方向,用于驱动下一轮修改。涵盖:审核意见 / 修改意见 / 质检报告 / 选择理由 / 测评结论。与'评分'的边界:评语是定性文字意见,评分是定量结论。与'指令'的边界:评语针对一个已存在的产出物提改进意见,指令是凭空规定要做什么。同义术语(写 category 时统一规范为「评语」):评审意见 / 审核意见 / 修改意见 / 反馈意见 / 质检报告 / review。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "流程",
+          "分类说明": "作用类别——可反复套用的'流程':描述多个加工步骤如何串接,套用时驱动整条流水线运转。判别口诀:它是一套'套上去能自动跑完多步'的编排配置。与'结构'的边界:流程是会跑起来的多步编排,结构是一份静态骨架。与'编排(控制)'的边界:流程是'制作过程'的步骤配置(可反复套用),编排是某一次内容作品的骨架。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "工作流",
+              "分类说明": "单任务的多步流程编排——一套流程跑一份输入得一份输出。涵盖:ComfyUI workflow / 自动化 pipeline 配置 / 跨工具协作流程 / Agent 流程编排。与'批处理'的边界:工作流是单任务编排(一次跑一份输入),批处理是多任务批量执行(一次跑多份输入)。同义术语(写 category 时统一规范为「工作流」):workflow / pipeline / 节点图。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "批处理",
+              "分类说明": "同一流程跑多份输入的批量执行配置——套用时对一组输入按同一套流程处理,得到一组对应输出。涵盖:X/Y/Z plot / 批量生成脚本 / Grid 出图配置 / 批量调参方案。与'工作流'的边界:工作流是单任务的多步流程,批处理是多任务的批量执行。同义术语(写 category 时统一规范为「批处理」):batch / 批量任务 / X/Y/Z plot。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "数据复用类型",
+      "分类说明": "L0 大类——这个产出物是跨任务沉淀下来、被反复装载或填充的'内容性资产':不服务于某一次具体产出,而是攒下来在很多次生产里反复被装载或填充。判别口诀:它的价值在'一次做好、多次复用',且自身是带内容性的实体(虚拟形象 / 视觉骨架 / 内容槽位),而非控制信号或评判。下辖的原子 / 序列 按结构形态切分:原子是不依赖串接的独立单件,序列是把多个槽位按顺序串接的有序骨架。与'程序控制类型'的边界:数据复用是带内容性的可装载 / 可填充资产,程序控制是左右生产过程的控制信号 / 配置。与'内容类型'的边界:数据复用是跨任务常备、反复取用的资产储备,内容是某一次产出的实体。与'知识类型'的边界:数据复用是被机械装上 / 填上即生效的资产,知识要被理解借鉴后才起作用。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "原子",
+          "分类说明": "作用类别——可反复套用的'单件原子级复用件':每一个本身就是一个完整的、不可再拆的复用单元,可独立装载到生成环节使用,不依赖与其他单元串接。判别口诀:装上 / 套上即用,不需要顺序衔接。与'序列'的边界:原子是单件不带顺序,序列是把多个槽位按顺序串接成连续骨架。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "数字人",
+              "分类说明": "一个可被反复驱动来产出口播 / 表演视频的完整虚拟人物形象——给它脚本 / 音频,它就产出该形象说话、表演的视频,套到不同脚本上产出不同视频、自身不变。与'模型权重'的边界:模型权重是加载进别的生成模型、改变其行为的增量权重(LoRA / Embedding / checkpoint),数字人是本身就能被驱动、独立产出视频的完整虚拟形象。与'视频成品(成品)'的边界:数字人是可复用的虚拟形象,某条数字人口播的具体成片是视频成品(value 写口播内容)。与'参考图(参照)'的边界:参考图是被静态模仿的图,数字人是被驱动产出视频的形象。同义术语(写 category 时统一规范为「数字人」):数字分身 / 虚拟人 / AI 分身 / 虚拟主播 / avatar / 口播数字人。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "版式",
+              "分类说明": "以视觉空间布局为核心的可复用骨架——套用时把内容填入预定义的空间位置。涵盖:海报版式 / PPT 版式 / 杂志版式 / 网页版式 / 信息图版式。与'模板'的边界:版式侧重视觉空间布局,模板侧重内容侧的可填充槽位。与'构图布局(约束)'的边界:构图布局是某一次具体内容的空间安排(一次性),版式是带占位槽位的可反复套用骨架。同义术语(写 category 时统一规范为「版式」):layout / 版面 / 排版骨架。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "序列",
+          "分类说明": "作用类别——可反复套用的'有序骨架':把多个槽位按顺序排成一条结构链,套用时按位置依次填入新内容,骨架本身不变。判别口诀:套用时需要按顺序填入多份内容,单点拆出来不成立。与'原子'的边界:序列由多个有序槽位组成,原子是单件不带顺序。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "模板",
+              "分类说明": "带可填充槽位的内容侧结构骨架——套用时把新内容填进对应槽位,骨架本身保持不变。涵盖:提示词模板 / 视频剪辑模板 / 设计模板 / 文档模板 / 分镜模板。被填充的具体内容类型由 value 字段承载,不进入叶子名。与'版式'的边界:模板侧重内容侧的可填充槽位(哪里填什么),版式侧重视觉空间布局(哪里放哪里)。同义术语(写 category 时统一规范为「模板」):template / 骨架 / 提示词模板 / 剪辑模板。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "内容类型",
+      "分类说明": "L0 大类——这个产出物本身就是被生产、流转、最终交付的内容实体。判别口诀:它是产线主流上的'那个东西'本身,不是用来左右它的控制信号、也不是跨任务的复用资产。下辖的素材 / 半成品 / 准成品 / 成品 是同一份内容在生命周期不同阶段的形态:素材是被拼接 / 影响生成的零件态(含被原样剪入的物理变化、与参与改变生成性质的化学变化),半成品是还要被继续改造 / 筛选 / 换形态的在制态,准成品是已定稿但需嵌入或陪同更大成品的组件级终态,成品是独立完整、可作为最终交付物的终态。与'程序控制类型'的边界:内容是被加工的对象本身,程序控制是左右加工结果的信号。与'数据复用类型'的边界:内容是某一次产出的实体,数据复用是跨任务反复取用的资产储备。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "素材",
+          "分类说明": "作用类别——这个产出物会被组装 / 剪辑 / 合成进更大的产物,当作其中一个零件,自身形态基本不变。判别口诀:它是更大产物的一个现成零件,被拼接 / 混入而不是被改造。与'半成品'的边界:素材被拼装进产物(形态不变,只是被放进去),半成品是被继续改造的对象(形态会变)。与'参照'的边界:素材被'吃进'产物,参照只被'看'。与'成品'的边界:素材服务于下游组装,不是工序终点。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "化学变化",
+              "分类说明": "作用类别——这类素材在被引入工序时不直接成为产物的'内容零件',而是参与改变后续生成的'内容性质':可作为被生成器模仿的范本、框定生成结果的空间 / 运动边界、或叠加到产出物的呈现层。判别口诀:它本身不被剪入产物,但参与决定'生成出来长什么样'——类比化学反应,影响产物性质而非堆叠位置。与'物理变化'的边界:化学变化改变结果性质 / 行为,物理变化是把素材原样搬进产物。",
+              "直接元素": [],
+              "子分类": [
+                {
+                  "分类名称": "参考图",
+                  "分类说明": "被生成步骤看着模仿的图像——以'参考'这个用途角色命名,被参考的具体对象(人物 / 场景 / 风格 / 构图 / 姿态 等内容实质)写入 value 字段,不进入叶子名;可以是一张,也可以是成库的多张。判别:在工序里承担'范本'角色(自身形态不被改造,也不被拼进产物)。与'底图'的边界:参考图被引用为锚(自身不被改造),底图是后续编辑会落在其上改造的对象。与'控制图'的边界:参考图作软引导(影响风格 / 主体形象),控制图作强空间约束。同义术语(写 category 时统一规范为「参考图」):人物参考图 / 场景参考图 / 风格参考图 / ref / style ref / 参考图库。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "参考视频",
+                  "分类说明": "被生成步骤看着模仿的视频——常用于动作迁移、风格迁移、镜头模仿的输入。判别:在工序里承担'范本'角色(生成器看着模仿,自身不被改造、不被剪入产物)。与'视频片段(素材)'的边界:参考视频只被'看',视频片段会被剪入更大的视频产物。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "参考音频",
+                  "分类说明": "被生成步骤看着模仿的音频样本——影响音色 / 语气 / 唱腔 / 配乐风格,自身不被剪入产物。判别:在工序里承担'声音范本'角色(被模仿,不被混入成片)。与'参考视频'的边界:模态不同、作用相同,都是被模仿的范本。与'配音 / BGM(素材)'的边界:参考音频只被'听着模仿',配音 / BGM 是被混入成片的音轨。同义术语(写 category 时统一规范为「参考音频」):参考音色 / 音色样本 / 参考配乐 / voice reference。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "对标内容",
+                  "分类说明": "被整体研究、借鉴打法的成功案例作品——一条爆款视频 / 一篇高赞笔记 / 一个标杆案例,用来学它的整体结构、钩子与表达方式。判别:它是一个完整的成品案例,被当作'整体范本'来对标。与'参考图 / 参考视频'的边界:参考图 / 参考视频是低层模仿(风格 / 动作 / 镜头等局部特征),对标内容是高层借鉴(整篇作品的打法与结构)。与'知识.方法论'的边界:对标内容是那个案例本身(被模仿的样本),方法论是从一批案例里提炼出的做法规律(被理解的认知)。同义术语(写 category 时统一规范为「对标内容」):对标案例 / 标杆案例 / 爆款参考 / benchmark / 参考范例。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "分镜图",
+                  "分类说明": "脚本规划阶段画出的逐镜设定图——每张对应一个镜头,供后续拍摄 / 生成时看着还原。判别:在工序里作为镜头画面的'范本'被模仿。与'分镜脚本'的边界:分镜图是画出来的视觉设定,分镜脚本是文字形态的逐镜规划。与'关键帧(素材)'的边界:分镜图是规划阶段的镜头设定图,关键帧是已有 / 将有视频里某时刻抽出的帧。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "转场",
+                  "分类说明": "作用于两段内容之间衔接处的过渡效果配置——套用时定义前一段结尾到后一段开头的过渡方式。涵盖:淡入淡出 / 推拉 / 擦除 / 闪白 / 模糊过渡 / 缩放过渡。与'特效'的边界:转场作用在段间衔接,特效作用在段内。与'转场片段(素材)'的边界:转场片段是已渲染出的实际视频,转场是可反复套用的过渡效果配置。同义术语(写 category 时统一规范为「转场」):transition / 过渡效果。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "蒙版",
+                  "分类说明": "标记图像中可编辑 / 受保护区域的黑白图——承载'哪里能改、哪里不能改'的空间信息。与'控制图'的边界:蒙版给的是区域划分(哪块能改),控制图给的是结构骨架。同义术语(写 category 时统一规范为「蒙版」):mask / 遮罩。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "控制图",
+                  "分类说明": "用于约束生成模型空间结构的图——涵盖:pose 骨架图 / canny 边缘图 / depth 深度图 / normal 法线图 等。与'蒙版'的边界:控制图给的是结构骨架(pose / 边缘 / 深度),蒙版给的是可编辑 / 受保护的区域划分。同义术语(写 category 时统一规范为「控制图」):ControlNet 输入 / 结构图。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "运动轨迹",
+                  "分类说明": "约束画面主体或镜头随时间运动路径的输入——给生成模型一条轨迹 / 运动笔刷,限定'谁、往哪、怎么动'。判别:它约束的是运动路径(空间位置随时间变化),而非单帧的静态结构。与'控制图'的边界:控制图约束单帧的静态结构骨架(pose / 边缘 / 深度),运动轨迹约束的是跨帧的运动路径。同义术语(写 category 时统一规范为「运动轨迹」):运动笔刷 / motion brush / 运镜轨迹 / 轨迹控制 / motion path。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "滤镜",
+                  "分类说明": "作用于内容呈现层的静态效果配置——套用时改变颜色 / 质感 / 氛围 / 视觉风格 / 音色,呈现层定型不动。涵盖:风格滤镜 / LUT / 调色方案 / 美颜方案 / 音色滤镜 / EQ。与'特效'的边界:滤镜是静态效果(套上不动),特效是动态效果(套上动起来)。同义术语(写 category 时统一规范为「滤镜」):filter / LUT / 调色预设 / 风格化方案。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "构图布局",
+                  "分类说明": "对画面中多元素空间位置 / 大小 / 主次关系的安排方案——作为后续生成的空间约束被遵守,以布局结构为核心信息,不强调元素本身的实例化细节。与'版式(复用·结构)'的边界:构图布局是某一次具体内容的空间安排(一次性产物),版式是带占位槽位的可反复套用的布局骨架。同义术语(写 category 时统一规范为「构图布局」):layout / 构图 / 布局方案。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                }
+              ],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "物理变化",
+              "分类说明": "作用类别——这类素材会被原样'搬进'产物:被截取 / 剪入 / 混入到更大的成品中,作为它的物质组成,自身形态基本不变。判别口诀:它就是产物的一块现成零件,被堆叠 / 拼接 / 混合——类比物理变化,只移动位置不改性质。涵盖图像 / 视频 / 音频 各模态的现成零件。与'化学变化'的边界:物理变化是被堆进产物的物质本体,化学变化是参与决定生成结果的影响信号。",
+              "直接元素": [],
+              "子分类": [
+                {
+                  "分类名称": "截图",
+                  "分类说明": "从屏幕、视频或公共内容中截取得到的图像——作为素材被投入后续加工 / 组装。与'底图 / 成品图'的边界:截图来源于现成呈现的截取,不是工序生成或精修产出。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "视频片段",
+                  "分类说明": "作为素材被剪入更大视频产物的视频——一个镜头、一个动作演示、一段独立画面;可以是一段,也可以是成库的多段(镜头库)。与'参考视频'的边界:视频片段会被剪入产物,参考视频只被看着模仿。同义术语(写 category 时统一规范为「视频片段」):clip / 单镜 / 镜头库 / 素材镜头。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "转场片段",
+                  "分类说明": "用于连接前后两个镜头的过渡视频——本身是一段视频,会被剪入更大视频产物的衔接处。与'转场(复用·效果)'的边界:转场片段是已渲染出的实际视频,转场是可反复套用的过渡效果配置。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "关键帧",
+                  "分类说明": "视频 / 动画中具有代表性的单帧画面——作为静止图像被抽出、供后续步骤取用。与'分镜图'的边界:关键帧是已有 / 将有视频里某时刻抽出的帧,分镜图是规划阶段画的镜头设定图。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "音效",
+                  "分类说明": "用于点缀 / 强调的声音效果——作为音轨素材被混入视频产物;可以是一条,也可以是成库的多条(音效库)。同义术语(写 category 时统一规范为「音效」):sound effect / SFX / 音效库。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "特效",
+                  "分类说明": "作用于单段内容内部的动态效果配置——套用时叠加时间维度上的变化(动画、粒子、变形、闪烁、回声、混响等)。涵盖:粒子特效 / 动画特效 / 变形特效 / 慢动作 / 快放 / 音频混响。与'滤镜'的边界:滤镜套上不动,特效套上动起来。与'转场'的边界:特效作用在单段内容内部,转场作用在两段内容之间。同义术语(写 category 时统一规范为「特效」):effect / VFX / 动态效果。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                }
+              ],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "半成品",
+          "分类说明": "作用类别——这个产出物是工序中产出、还要被后续步骤继续加工 / 改造 / 筛选的中间态内容,尚未定稿。判别口诀:它处在'还要被改 / 被挑'的状态,后续步骤会落在它身上把它推向最终形态。与'素材'的边界:半成品会被改造(形态会变),素材是被原样拼装进产物的零件(形态不变)。与'成品'的边界:半成品是可被进一步处置的中间态,成品是不再改动、直接交付的终态。与'参照'的边界:半成品被改造,参照只被看、不被动。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "序列",
+              "分类说明": "作用类别——这类半成品本身是一份'有序的多段文字骨架'(章节 / 场 / 镜 / 时间轴 / 段落),尚未定稿,还要被后续步骤继续展开、拍摄、生成、剪辑或录音渲染。判别口诀:内部能数出有序的多个部分(章 / 场 / 镜 / 段),且整段还在被处置——按它去拍、去生、去剪、去读。与'半成品·原子'的边界:序列是有序的多段文字骨架,原子是独立的视觉中间件。与'半成品·组合'的边界:序列是文字层面的顺序骨架,组合是多层 / 多块拼合的视觉工作文件。",
+              "直接元素": [],
+              "子分类": [
+                {
+                  "分类名称": "大纲",
+                  "分类说明": "按章节 / 段落 / 议题组织的纲要文字——以条目化层级列出主体内容的骨架,指挥后续展开创作。涵盖:文章大纲 / 视频大纲 / 教程大纲 / 章节纲要 / 内容提纲 / 演讲提纲。判别:只列骨架要点不展开。与'脚本'的边界:大纲只列骨架要点,脚本展开具体叙事 / 动作 / 对白。与'分镜脚本'的边界:大纲是内容层骨架(章节 / 议题),分镜脚本是制作层骨架(镜头 / 画面)。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "脚本",
+                  "分类说明": "按时间 / 情节 / 操作顺序组织的有序文本——包含若干场景 / 段落 / 动作 / 对白等元素,指挥后续拍摄 / 生成。被组织的具体内容(剧情对白 / 动作流程 / 操作步骤 / 教程演示 等内容实质)写入 value 字段,不进入叶子名。与'分镜脚本'的边界:脚本以叙事 / 动作 / 操作为基本单位,分镜脚本以镜头切分为基本单位。与'大纲'的边界:脚本展开具体叙事 / 动作 / 对白,大纲只列骨架要点。同义术语(写 category 时统一规范为「脚本」):剧本 / 文本脚本 / 动作脚本 / 操作脚本 / 教程脚本。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "分镜脚本",
+                  "分类说明": "按镜头组织的拍摄 / 生成规划文本——每个镜头有编号、画面、动作、运镜、时长等,指挥后续逐镜拍摄 / 生成。涵盖运镜描述(作为分镜脚本中每个镜头的子字段而非独立产物)。与'脚本'的边界:分镜脚本以镜头为基本单位、包含视觉化细节,脚本以叙事 / 动作 / 操作为基本单位。与'分镜图'的边界:分镜脚本是文字形态的逐镜规划,分镜图是画出来的逐镜设定图。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "剪辑脚本",
+                  "分类说明": "成片剪辑阶段的时间轴编排——规定'用哪段素材、按什么顺序、各自的入出点与时长'拼成最终视频。判别:它是面向'已有素材如何组装成片'的骨架,处在剪辑环节。与'分镜脚本'的边界:分镜脚本是拍摄 / 生成前的镜头规划(要产出哪些镜头),剪辑脚本是把已有素材组装成片的时间轴安排。与'工作流(复用·流程)'的边界:剪辑脚本是这一条片子的具体编排,工作流是可反复套用的制作流程配置。同义术语(写 category 时统一规范为「剪辑脚本」):剪辑表 / 时间轴 / timeline / 卡点表。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "配音文案",
+                  "分类说明": "配音 / 解说内容的文字形态——承载'要被读出来'的语义内容,是配音的在制态:经配音 / 录音步骤渲染成音频。与'配音(素材)'的边界:配音文案是文字形态的在制内容,配音是已渲染出的音频音轨。与'脚本(编排)'的边界:配音文案是单纯的旁白 / 解说文本本身,脚本是带分镜 / 动作 / 台词的多段落骨架。与'正文(成品)'的边界:正文直接以文字交付、即为终态,配音文案要再被渲染成音频才到终态。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                }
+              ],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "原子",
+              "分类说明": "作用类别——这类半成品本身是一份独立的、形态完整的视觉中间件(一张图 / 一段视频 / 一组分镜),尚未定稿,等着被后续步骤继续编辑 / 挑选 / 合成推向最终形态。判别口诀:它是一份独立单件的视觉中间产物,单点拿出来就能看,但还要被处置。与'半成品·序列'的边界:原子是独立的视觉中间件,序列是有序的多段文字骨架。与'半成品·组合'的边界:原子是单一中间件,组合是多层 / 多块拼装而成的可编辑整体。",
+              "直接元素": [],
+              "子分类": [
+                {
+                  "分类名称": "底图",
+                  "分类说明": "作为后续编辑(局部重绘、风格化、叠加)基础的图像——判别口诀:身份后续会被保留并继续改造的对象。与'成品图'的边界:底图是会被继续改造的中间态,成品图是不再改动的终态。与'参考图'的边界:底图是后续编辑会落在其上改造的对象,参考图只被引用为锚、自身不被改造。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "样图",
+                  "分类说明": "工序中产出、用于挑选或对照的候选图——常用于'从候选里挑选'的场景;可以是一张候选,也可以是一批候选(候选图集)。与'成品图'的边界:样图是待挑选 / 待定的候选态,成品图是定稿态。同义术语(写 category 时统一规范为「样图」):候选图 / draft / 候选图集。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "分镜视频",
+                  "分类说明": "按镜头顺序排出的多段视频——尚未做最终合成,作为粗剪半成品等待后续合成 / 调整。与'视频成品'的边界:分镜视频是未做最终合成的镜头序列(待加工),视频成品是已合成交付的整片。与'视频片段(素材)'的边界:分镜视频是面向最终成片的粗剪半成品,视频片段是被剪进来的零件。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                }
+              ],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "组合",
+              "分类说明": "作用类别——这类半成品由多个子元素按图层 / 格子拼装而成的可编辑整体,每个子元素仍可辨识 / 可调整,未拍平定稿。判别口诀:它内部能看出多层 / 多块的拼合结构,且整体还能被继续改动(换层、挪位、调比例)。与'半成品·序列'的边界:组合是空间维度的拼合(多层 / 多块),序列是文字层面的顺序骨架。与'半成品·原子'的边界:组合是多层 / 多块拼装而成,原子是单一独立的视觉中间件。与'成品·合成图'的边界:组合保留子元素的可辨识 / 可调整性(半成品态),合成图是已拍平 / 已融合定稿的成品。",
+              "直接元素": [],
+              "子分类": [
+                {
+                  "分类名称": "图层组合",
+                  "分类说明": "多个图层按层级叠加形成的可编辑整体——每层有独立内容,常见于设计稿、PSD 文件、合成模板,作为可继续调整的工作文件。与'合成图(成品)'的边界:图层组合保留分层、可继续改动(半成品),合成图是已拍平交付的成品。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                },
+                {
+                  "分类名称": "拼图",
+                  "分类说明": "将多个素材格子化并置在一张图上的图像——多元素同时呈现、各自仍可辨认,作为整体交付。被并置的具体对象(多视角 / 多变体 / 多角度 / 多人物 / 对比 等内容实质)写入 value 字段,不进入叶子名。与'合成图'的边界:拼图强调并置式格子布局,合成图强调融合 / 叠加成新画面。同义术语(写 category 时统一规范为「拼图」):九宫格 / 对比图 / collage。",
+                  "直接元素": [],
+                  "子分类": [],
+                  "分类性质": "内容"
+                }
+              ],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "准成品",
+          "分类说明": "作用类别——这类产出物本身已是定稿的'组件级终态'(不再被改造 / 筛选),但相比成品粒度更小,通常作为更大成品的组件被搭载或陪同交付。判别口诀:它自己已经定稿,但单独交付往往不是完整作品,要嵌进或陪同更大的载体。与'半成品'的边界:准成品已定稿不再被改 / 筛选,半成品还要被继续加工 / 换形态。与'成品'的边界:成品是独立完整的最终交付物,准成品是单模态的组件级定稿、常嵌入或陪同更大的成品。与'素材'的边界:素材是通用、可候选取用的现成零件(往往多份备选),准成品是为这一次作品专门定稿好的组件(单一确定件)。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "歌词",
+              "分类说明": "歌曲内容的文字形态(词作)——承载'要被唱出来'的内容,是歌曲的在制态:经谱曲 / 演唱渲染成歌曲音频。与'配音文案'的边界:歌词被唱(终态是歌曲),配音文案被读(终态是配音)。与'正文(成品)'的边界:正文直接以文字交付即为终态,歌词要再被渲染成歌曲音频。同义术语(写 category 时统一规范为「歌词」):词 / lyrics / 歌词文案。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "配音",
+              "分类说明": "为视频 / 内容配上的人声音频——作为音轨素材被混入视频产物,与 BGM / 音效 同为音轨。与'配音文案'的边界:配音文案是文字形态的在制内容,配音是已读出的音频音轨。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "BGM",
+              "分类说明": "作为背景音乐的音频——作为音轨素材被混入视频产物;可以是一段,也可以是成库的多段(BGM库)。同义术语(写 category 时统一规范为「BGM」):背景音乐 / bgm / BGM库。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "字幕",
+              "分类说明": "覆盖在视频画面上的文字内容——作为视频成品的呈现层组成被交付。与'配音文案'的边界:字幕是呈现在画面上的文字,配音文案是被读出的文字稿。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "标题",
+              "分类说明": "作品 / 内容的标题文本——简短文字,用于命名 / 概括 / 引流。涵盖:视频标题 / 文章标题 / 笔记标题 / 章节标题 等。与'正文'的边界:标题是高度浓缩的命名 / 概括文字(通常一行),正文是展开陈述的主体文字(多段连续)。与'描述(指令)'的边界:标题是被交付的终态文字,描述是喂给生成的依据。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "正文",
+              "分类说明": "作品 / 内容的主体文字部分——较长的连续陈述文本,承载完整叙述 / 说明 / 论述,作为终态文字被交付。涵盖:文章正文 / 帖子正文 / 公众号文章主体 / 笔记正文 / 长文案。与'标题'的边界:正文是展开陈述的主体(通常多段),标题是浓缩命名(通常一行)。与'脚本(编排)'的边界:正文是被交付的终态文字本身,脚本是指挥后续拍摄 / 生成的规约。与'配音文案(半成品)'的边界:正文直接以文字交付、即为终态,配音文案要再被渲染成音频才到终态。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        },
+        {
+          "分类名称": "成品",
+          "分类说明": "作用类别——这个产出物会被作为终态内容交付 / 呈现给受众,不再进入后续加工。判别口诀:它是工序链路的终点,被受众消费或作为最终交付物。与'半成品'的边界:成品定稿不再改,半成品还要被继续处置。与'素材'的边界:成品是工序终点,素材是给下游组装当零件。",
+          "直接元素": [],
+          "子分类": [
+            {
+              "分类名称": "成品图",
+              "分类说明": "作为终态内容交付的图像——处于工序末端、不再被继续改造;可以是一张,也可以是成组交付的多张(成品图集 / 图集)。被汇集时的具体对象(多角度 / 多视角 / 多变体 等内容实质)写入 value 字段。与'底图 / 样图'的边界:成品图是定稿态,底图 / 样图是仍会被改造 / 挑选的中间态。同义术语(写 category 时统一规范为「成品图」):成品图集 / 图集 / 定稿图。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "视频成品",
+              "分类说明": "经过分镜剪辑、合成、配音后形成的完整视频——作为终态内容整体交付。与'分镜视频(半成品)'的边界:视频成品是已合成交付的整片,分镜视频是未做最终合成的粗剪半成品。与'视频片段(素材)'的边界:视频成品是交付的整片,视频片段是被剪进来的零件。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            },
+            {
+              "分类名称": "合成图",
+              "分类说明": "将多张素材融合为一张的图像——元素之间有空间叠加 / 拼接 / 融合关系,已拍平为一张交付。与'图层组合(半成品)'的边界:合成图是已拍平交付的成品,图层组合保留分层、可继续改动。与'拼图'的边界:合成图强调融合 / 叠加成新画面(看不出独立单元),拼图强调格子化并置(各元素仍可辨)。同义术语(写 category 时统一规范为「合成图」):融合图 / 拼合图。",
+              "直接元素": [],
+              "子分类": [],
+              "分类性质": "内容"
+            }
+          ],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    },
+    {
+      "分类名称": "知识类型",
+      "分类说明": "L0 大类——这个产出物是沉淀下来、跨任务复用的认知性内容,会被检索 / 学习 / 借鉴,为未来的生产提供认知依据。判别口诀:它不服务于某一次具体产出,而是攒下来反复查、反复用的认知储备;不会被装载 / 填充 / 剪入产物,而是要被理解后才起作用。与'数据复用类型'的边界:数据复用是可机械装载 / 填充的资产实体(装上即生效),知识要被理解 / 借鉴后才起作用。与'程序控制·指令'的边界:指令是为当次产出专门写的、用完即弃的规约,知识是跨任务沉淀、反复复用的。与'程序控制·评估'的边界:知识是跨任务的通用认知,评估是针对某一个具体产出的一次性评判。与'内容类型'的边界:知识不是被生产 / 交付的内容实体,而是支撑生产的认知背景。",
+      "直接元素": [],
+      "子分类": [
+        {
+          "分类名称": "知识库",
+          "分类说明": "由知识条目(事实 / 概念 / 规则 / 操作要点)汇集而成的资料库——沉淀下来供检索 / 引用 / 喂给模型作背景,是陈述性知识的复用储备。与'方法论'的边界:知识库是'是什么'的事实 / 概念资料,方法论是'怎么做'的做法经验。同义术语(写 category 时统一规范为「知识库」):knowledge base / 资料库 / 背景资料。",
+          "直接元素": [],
+          "子分类": [],
+          "分类性质": "内容"
+        }
+      ],
+      "分类性质": "内容"
+    }
+  ],
+  "$leaves": [
+    "提示词",
+    "负向提示词",
+    "描述",
+    "生成参数",
+    "规格参数",
+    "模型权重",
+    "评分",
+    "评语",
+    "工作流",
+    "批处理",
+    "数字人",
+    "版式",
+    "模板",
+    "参考图",
+    "参考视频",
+    "参考音频",
+    "对标内容",
+    "分镜图",
+    "转场",
+    "蒙版",
+    "控制图",
+    "运动轨迹",
+    "滤镜",
+    "构图布局",
+    "截图",
+    "视频片段",
+    "转场片段",
+    "关键帧",
+    "音效",
+    "特效",
+    "大纲",
+    "脚本",
+    "分镜脚本",
+    "剪辑脚本",
+    "配音文案",
+    "底图",
+    "样图",
+    "分镜视频",
+    "图层组合",
+    "拼图",
+    "歌词",
+    "配音",
+    "BGM",
+    "字幕",
+    "标题",
+    "正文",
+    "成品图",
+    "视频成品",
+    "合成图",
+    "知识库"
+  ]
+}

+ 314 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/type_suggestions.md

@@ -0,0 +1,314 @@
+# Type 字典扩展建议 · Agent 跑 case 时累积
+
+> **这个文件由 Agent 在 Phase 2 类型归一时自动 append**, 不要手工编辑 (除非 spec 维护者在做"审阅 → 合并到 type.json" 的工作).
+>
+> Agent 何时写: 走完 `phase2-normalize.md` §2A 类型归一 funnel 第 2c 步 (case-specific 新类型, 走 extends 桥接) 后, append 一条到下面的「累积条目」段.
+>
+> spec 维护者怎么用: 定期扫这个文件, 看哪些新类型在多个 case 反复出现 / 语义独立性强 — 这些值得升级到 `type.json` 的 `$leaves` (顶级叶子) 或长驻 `registry` (跨 case extends 库).
+
+---
+
+## 升级判断准则 (维护者用)
+
+| 信号 | 应该升级 |
+|---|---|
+| 同一新类型在 ≥3 个不同 case 出现 | ✅ 升 `$leaves` (说明跨 case 通用) |
+| 单 case 出现但语义跟 `$leaves` 无重叠 + 内容创作领域常用 | ✅ 升 `registry` (跨 case extends 库) |
+| 跟某 `$leaves` 是同义异写 (e.g. "人物图" vs 已有 "参考图") | ❌ 别升, 在 spec 提一句"X 直接归到 leaf Y" |
+| 只是单 case 的窄场景 (e.g. "苏晚的肖像图") | ❌ 留在该 case 的 `case_type_registry`, 不升 |
+
+---
+
+## 累积条目
+
+> Format: `- \`<新类型名>\`: <一句描述>  (来自 case-{N}, extends \`<leaf>\`, 出现位置: step.{io_kind}[{i}])`
+> 同一 case 同名类型只 append 一条.
+
+- `主角图`: case-specific 主角肖像图, 后续作为人物参考图链的源头  (来自 case-1, extends `参考图`)
+- `剧本`: 完整剧集本/分集剧情, 含人物关系与情节冲突  (来自 case-2, extends `脚本`)
+- `题材`: 短剧创作的题材/类型方向 (含人设标签 + 爽点元素)  (来自 case-2, extends `描述`)
+- `人物设定`: 短剧角色形象与气质设定 (外貌/性格/气场描述)  (来自 case-2, extends `描述`)
+- `生成积分`: AI 工具的每日配额/积分计数 (用量管理用)  (来自 case-7, extends `?` ⚠ 字典缺"数值/配额"类叶子)
+- `安装状态`: App 安装就绪的前置状态标识  (来自 case-7, extends `?` ⚠ 字典缺"状态/前提"类叶子)
+- `产品场景图`: AI文生图工作流中生成的产品应用场景创意图候选集  (来自 case-new_pat, extends `样图`, 出现位置: step.outputs[0], step.inputs[0])
+- `背景素材`: 专门生成的无主体氛围背景图,用于后期叠加文字/产品的合成底层  (来自 case-new_pat, extends `底图`, 出现位置: step.outputs[0])
+- `方法论文档`: 跨case可复用的AI生成操作框架/Prompt编写方法论(如5W故事化法/摄影分层法)  (来自 case-new_pat, extends `模板`, 出现位置: resources[0])
+
+- `设计需求`: 产品功能、材质、品牌调性、视觉要求等具体项目需求描述文本  (来自 case-new_pat, extends `描述`)
+- `品牌素材`: 品牌Logo等品牌视觉标识素材  (来自 case-new_pat, extends `参考图`)
+- `文本描述`: 产品宣传文案,含标语、功能描述、场景标签等排版文字元素  (来自 case-new_pat, extends `正文`)
+- `产品宣传图`: 经Photoshop精修、添加Logo和文字排版后的最终可用产品宣传图  (来自 case-new_pat, extends `成品图`)
+- `试穿场景图`: AI生成的模特穿着产品的多场景展示图,用于海报版式合成  (来自 case-new_pat, extends `样图`)
+- `产品宣传海报`: 多素材拼接合成的产品宣传版式海报(背景+产品图+试穿图+文案)  (来自 case-new_pat, extends `合成图`)
+
+- `场景图备选集`: 3款AI工具并行生成的吸湿排汗背心应用场景候选图集合  (来自 case-new—str, extends `样图`)
+- `调性背景图`: 冲锋衣宣传海报用极简写实背景图,无人物无产品,哑光光效,大面积留白,供合成叠加使用  (来自 case-new—str, extends `样图`)
+- `试穿场景图`: AI生成的冲锋衣应用场景人物试穿图(单场景单张)  (来自 case-new—str, extends `样图`)
+- `试穿场景图集`: 露营/城市生活/徒步三场景的冲锋衣试穿图集合  (来自 case-new—str, extends `样图`)
+- `海报文案`: 宣传海报上的品牌tagline与产品功能描述文字(由外部提供,非工序内生成)  (来自 case-new—str, extends `正文`)
+- `产品创意图`: 智能纺织品SEM/光纤光学风格微观创意图,体现科技感与可持续发展理念  (来自 case-new—str, extends `成品图`)
+- `功能示意图`: 冲锋衣面料结构防水透湿功能半剖面3D示意图,颜色编码+箭头可视化功能流向  (来自 case-new—str, extends `成品图`)
+
+- `场景图备选集`: 3款AI工具并行生成的吸湿排汗背心应用场景候选图集合  (来自 case-5, extends `样图`)
+- `调性背景图`: 冲锋衣宣传海报用极简写实背景图,无人物无产品,哑光光效,大面积留白,供合成叠加使用  (来自 case-5, extends `样图`)
+- `试穿场景图`: AI生成的冲锋衣应用场景人物试穿图(单场景单张)  (来自 case-5, extends `样图`)
+- `试穿场景图集`: 露营/城市生活/徒步三场景的冲锋衣试穿图集合  (来自 case-5, extends `样图`)
+- `海报文案`: 宣传海报上的品牌tagline与产品功能描述文字(由外部提供,非工序内生成)  (来自 case-5, extends `正文`)
+- `产品创意图`: 智能纺织品SEM/光纤光学风格微观创意图,体现科技感与可持续发展理念  (来自 case-5, extends `成品图`)
+- `功能示意图`: 冲锋衣面料结构防水透湿功能半剖面3D示意图,颜色编码+箭头可视化功能流向  (来自 case-5, extends `成品图`)
+
+- `产品平铺图`: 产品正反面白底平铺图,用于海报合成的主视觉元素  (来自 case-new_dir, extends `参考图`)
+- `试穿场景图`: AI生成的模特穿着产品的单场景试穿候选图  (来自 case-new_dir, extends `样图`)
+- `试穿场景图集`: 多场景试穿图的集合(露营/生活/徒步三场景)  (来自 case-new_dir, extends `样图`)
+- `产品创意图`: 智能纺织品科学可视化风格创意图,体现科技感与可持续发展理念  (来自 case-new_dir, extends `成品图`)
+- `功能示意图`: 产品功能半剖视3D示意图,颜色编码+箭头可视化功能流向  (来自 case-new_dir, extends `成品图`)
+
+- `需求简述`: 冲锋衣功能示意图的设计需求:防水透湿三层结构+3D剖面图风格  (来自 case-my_test, extends `描述`)
+- `场景描述列表`: 多个使用场景的名称/描述列表,如['露营','生活','徒步']  (来自 case-my_test, extends `大纲`)
+- `场景描述`: 单个使用场景的文字描述,用于引导单次试穿图生成  (来自 case-my_test, extends `描述`)
+- `试穿场景图`: AI生成的模特穿着产品的单场景候选图  (来自 case-my_test, extends `样图`)
+- `海报文案`: 海报用品牌文案(tagline + 产品功能描述文字,由品牌方提供)  (来自 case-my_test, extends `正文`)
+- `产品创意图`: 智能纺织品SEM/光纤光学风格科技展示创意图,以伪彩色纤维可视化为核心  (来自 case-my_test, extends `成品图`)
+- `功能示意图`: 冲锋衣防水透湿功能半剖面3D示意图,颜色编码+箭头可视化功能流向  (来自 case-my_test, extends `成品图`)
+
+- `需求简述`: 冲锋衣功能示意图的设计需求:防水透湿三层结构+3D剖面图风格  (来自 case-?, extends `描述`)
+- `场景描述列表`: 多个使用场景的名称/描述列表,如['露营','生活','徒步']  (来自 case-?, extends `大纲`)
+- `场景描述`: 单个使用场景的文字描述,用于引导单次试穿图生成  (来自 case-?, extends `描述`)
+- `试穿场景图`: AI生成的模特穿着产品的单场景候选图  (来自 case-?, extends `样图`)
+- `海报文案`: 海报用品牌文案(tagline + 产品功能描述文字,由品牌方提供)  (来自 case-?, extends `正文`)
+- `产品创意图`: 智能纺织品SEM/光纤光学风格科技展示创意图,以伪彩色纤维可视化为核心  (来自 case-?, extends `成品图`)
+- `功能示意图`: 冲锋衣防水透湿功能半剖面3D示意图,颜色编码+箭头可视化功能流向  (来自 case-?, extends `成品图`)
+
+- `调色预设`: 在百度网盘AI修图中保存的调色参数套装(色温/饱和度/色调等),可跨次调用复刻同款色调风格  (来自 case-?, extends `滤镜`)
+
+- `账户权限`: 使用AI生图功能的前提状态——账户已登录、功能已解锁、算力充足  (来自 case-14, extends `描述`, 出现位置: p1.s1.inputs[0], p2.s1.inputs[0])
+- `小程序界面`: AI生图小程序的UI界面屏幕状态(主界面及各子页面)  (来自 case-14, extends `描述`, 出现位置: p1.s1.outputs[0], p2.s1.outputs[0])
+- `模板库界面`: 模板参考库UI界面(含行业筛选、缩略图网格、应用提示词按钮)  (来自 case-14, extends `描述`, 出现位置: p1.s2.outputs[0])
+- `门店信息`: 用户门店专属信息(店铺名称、活动内容、时间、优惠规则等需填入海报的要素)  (来自 case-14, extends `描述`, 出现位置: p1.s5.inputs[1])
+- `设计意图`: 用户对海报的完整自定义设计意图(尺寸/比例、风格、文案、画面元素、特殊需求)  (来自 case-14, extends `描述`, 出现位置: p2.s2.inputs[0])
+
+- `账户权限`: 使用优客赢文字生图功能的前提:账户已登录、功能已解锁、当前算力充足  (来自 case-case_14, extends `描述`)
+- `小程序界面`: 优客赢小程序文字生成图功能的UI界面状态  (来自 case-case_14, extends `描述`)
+- `模板库界面`: 优客赢模板参考库的UI界面:含行业分类筛选、模板缩略图网格、应用提示词按钮  (来自 case-case_14, extends `描述`)
+- `门店信息`: 用户门店专属信息:店铺名称、活动内容、时间、优惠规则等需填入海报的信息  (来自 case-case_14, extends `描述`)
+- `设计意图`: 用户对海报的完整设计意图:尺寸/比例、整体风格、文案内容、画面元素、特殊需求  (来自 case-case_14, extends `描述`)
+
+- `写真图集`: AI生成的主题人像写真图片集合,多张统一主题写真图构成一套交付物  (来自 case-6, extends `成品图`, 出现位置: p1-p6.s2.outputs[0], s3.inputs[0], s3.outputs[0])
+
+- `写真图集`: AI生成的主题人像写真图片集合,多张统一主题写真图构成一套交付物  (来自 case-case_6, extends `成品图`)
+
+- `写真图集`: 豆包AI批量生成的九张氛围感写真照片集合,同一角色不同姿态动作,2:3竖版比例  (来自 case-case_10, extends `成品图`)
+
+- `背景图`: 冲锋衣宣传海报用极简写实背景图,无人物无产品,哑光光效,渐层构图,供合成叠加使用  (来自 case-case_5, extends `底图`)
+- `场景设定列表`: 要生成试穿图的场景名称列表,如[露营, 城市生活, 徒步]  (来自 case-case_5, extends `大纲`)
+- `场景试穿图列表`: 遍历各场景生成的产品试穿图集合(露营/城市生活/徒步三场景)  (来自 case-case_5, extends `样图`)
+- `场景试穿图`: AI基于产品参考图生成的单场景产品试穿候选图  (来自 case-case_5, extends `样图`)
+- `宣传海报`: 背景图+产品参考图+试穿图+文案合成的最终冲锋衣宣传海报  (来自 case-case_5, extends `合成图`)
+- `创意图`: 智能纺织品SEM/光纤光学风格科学可视化创意图,体现科技感与可持续发展理念  (来自 case-case_5, extends `成品图`)
+- `功能示意图`: 冲锋衣防水透湿功能半剖面3D示意图,颜色编码+箭头可视化功能流向  (来自 case-case_5, extends `成品图`)
+
+- `背景图`: 冲锋衣宣传海报用极简写实背景图,无人物无产品,哑光光效,渐层构图,供合成叠加使用  (来自 case-5, extends `底图`)
+- `场景设定列表`: 要生成试穿图的场景名称列表,如[露营, 城市生活, 徒步]  (来自 case-5, extends `大纲`)
+- `场景试穿图列表`: 遍历各场景生成的产品试穿图集合(露营/城市生活/徒步三场景)  (来自 case-5, extends `样图`)
+- `场景试穿图`: AI基于产品参考图生成的单场景产品试穿候选图  (来自 case-5, extends `样图`)
+- `宣传海报`: 背景图+产品参考图+试穿图+文案合成的最终冲锋衣宣传海报  (来自 case-5, extends `合成图`)
+- `创意图`: 智能纺织品SEM/光纤光学风格科学可视化创意图,体现科技感与可持续发展理念  (来自 case-5, extends `成品图`)
+
+- `工具配置`: 对多个候选工具的评估筛选结论,包含选定工具名称及推荐理由,作为后续生成步骤的工具选型依据  (来自 case-case_13, extends `评语`)
+
+- `工具配置`: 对所选AI工具的名称、核心特点及推荐理由的文字描述,作为后续生成步骤中使用该工具的选型依据  (来自 case-case_13_test, extends `描述`)
+- `海报方案`: AI生成的海报候选设计方案,包含标题文字、图片元素、配色方案、版式排版等完整设计内容,经人工筛选后进入后续编辑阶段  (来自 case-case_13_test, extends `样图`)
+
+- `参考图集`: 多张同风格参考图构成的图组,是参考图的集合形态,功能角色与参考图相同(被生成步骤模仿,不被剪入产物)。  (来自 case-eval_2, extends `参考图`)
+- `约束条件清单`: 从参考图集中解构提炼的结构性约束条件列表,涵盖构图、视角、空间关系、人物等维度,作为后续风格结构模块生成的输入依据。  (来自 case-eval_2, extends `描述`)
+- `共性特征描述`: 从多张参考图中反推出的跨图共性风格特征描述,涵盖色彩、构图、人物气质、材质、光线等维度,是对隐含风格属性的推断性文字汇总。  (来自 case-eval_2, extends `描述`)
+- `风格结构模块`: 多维度并置的风格框架文档,按整体风格定位、色彩系统、空间与构图、人物与动作风格、材质与质感、光线与氛围等模块组织,是生成最终提示词的结构化中间输入。  (来自 case-eval_2, extends `描述`)
+
+- `创意需求`: 视频创作方向与业务目标的文字刻画,如品牌氛围片主题、探店场景、企业 B-Roll 等,含主体类型、场景、风格大致方向,作为撰写六要素 Prompt 的起始输入  (来自 case-eval_4, extends `描述`)
+- `参数集`: 用于 Best-of-5 并行试稿的多个随机种子序列(如 [42, 123, 456, 789, 1024]),一次传入 5 个 seed 驱动 5 路并发生成,是批量生成参数的集合形态  (来自 case-eval_4, extends `生成参数`)
+- `候选视频`: HappyHorse T2V 在 720P 规格下并行生成的多条候选视频(每条对应一个 seed),用于人工对比筛选最优 seed,属于待挑选的候选中间态,未进入定稿流程  (来自 case-eval_4, extends `样图`)
+- `定稿视频`: HappyHorse T2V 以 1080P 规格、锁定最优 seed 生成的定稿原片,尚未经过字幕、BGM、片头尾等后期处理,将作为剪映后处理的主体素材被组装进最终成片  (来自 case-eval_4, extends `视频片段`)
+
+- `视觉风格JSON`: 从参考图通过反推提取的结构化视觉风格描述(JSON格式),包含色彩、构图、排版、主体、材质质感、光影、特效、画面氛围及复刻关键词等字段,作为后续图像生成步骤的内容依据被执行。  (来自 case-A_gzh_8f5fbfb0, extends `描述`)
+- `分镜分析`: 通过对参考视频逐分镜解构得到的结构化分镜分析文本,每个分镜包含画面风格、主体动作、镜头运动、构图、光影、台词、音效、画质参数及格式化生成提示词,作为逐镜视频生成步骤的内容依据被执行。  (来自 case-A_gzh_8f5fbfb0, extends `描述`)
+
+- `需求文本`: 用户以自然语言描述的内容创作需求,如人物外貌、场景、服装、姿态等要素的综合描述,作为生成提示词的原始输入  (来自 case-A_gzh_d2b3f06f, extends `描述`)
+- `写真图`: AI文生图工序产出的人物写真照片,包含人物外貌、场景、服装等完整画面,可作为终态交付或后续换脸步骤的输入  (来自 case-A_gzh_d2b3f06f, extends `成品图`)
+- `换脸写真图`: 将写真图中的人物面貌替换为参考人像后得到的写真图片,是写真图的换脸变体,面部已替换为用户指定的参考形象  (来自 case-A_gzh_d2b3f06f, extends `成品图`)
+- `图片文件`: 保存至本地设备的图片文件,是写真图经保存操作后落地于本地存储的终态交付物  (来自 case-A_gzh_d2b3f06f, extends `成品图`)
+- `短视频`: 时长较短的视频内容,既可作为参考视频被截图模仿风格,也可作为AI图转视频生成的最终短视频成品  (来自 case-A_gzh_d2b3f06f, extends `视频成品`)
+
+- `分析报告`: 对视频内容进行逐镜结构化解析后生成的分析性文档,包含镜头语言、叙事焦点、环境氛围、光影风格、声音设计等多维度拆解与AI提示词输出  (来自 case-B_gzh_4a948bbb, extends `正文`)
+- `提示词序列`: 按分镜顺序排列的多条AI视频生成提示词,每条独立对应一个镜头,可逐条喂给生成模型以重建原视频各镜头  (来自 case-B_gzh_4a948bbb, extends `提示词`)
+- `视频序列`: 按分镜顺序排列的多个AI生成视频片段的有序列表,与原视频各镜头一一对应,等待后续对比评估或合成  (来自 case-B_gzh_4a948bbb, extends `分镜视频`)
+
+- `生成图`: AI生成模型直接输出的图像,在本工序中作为图生视频步骤的参考帧输入,承担视频内容风格与画面构成的锚定作用。  (来自 case-C_gzh_789c9e49, extends `成品图`)
+- `需求说明`: 用户对本次内容生产的具体要求说明,包含主题、目标受众、风格偏好、平台、关键元素等信息,用于指导后续提示词构造。  (来自 case-C_gzh_789c9e49, extends `描述`)
+- `文案`: 面向社交媒体平台(如小红书)的种草/营销文案,包含标题、正文亮点和标签,作为终态文字内容直接交付。  (来自 case-C_gzh_789c9e49, extends `正文`)
+- `海报`: AI生成的节日/营销主题海报,包含文字、图案、色彩等完整视觉设计,适配社交媒体传播规格,作为终态图像内容交付。  (来自 case-C_gzh_789c9e49, extends `成品图`)
+
+- `视觉风格JSON`: 多模态AI从参考图片中反推提取的JSON格式视觉风格结构,包含颜色/构图/光影/材质/氛围等字段,作为生图工具的结构化风格指令  (来自 case-B_gzh_8f5fbfb0, extends `描述`)
+- `分镜序列`: 由多模态AI对参考视频按分镜拆解后生成的结构化文本序列,每个分镜条目包含画面风格/主体/动作/运镜/光影/声音/画质参数及完整生成提示词,用于逐镜驱动视频生成工具复刻  (来自 case-B_gzh_8f5fbfb0, extends `分镜脚本`)
+
+- `URL`: 平台页面URL地址,用于指定参考视频的获取来源(如微信视频号/抖音等)  (来自 case-A_gzh_c1c709a5, extends `描述`)
+- `分析报告`: AI视觉语言模型对视频的结构化反推分析,包含分镜描述(画面风格/主体/动作/镜头/台词/音效/画质)及可复用提示词  (来自 case-A_gzh_c1c709a5, extends `评语`)
+- `工具列表`: 视频反推AI工具的清单列表,包含工具名、链接、收费情况、特点等  (来自 case-A_gzh_c1c709a5, extends `描述`)
+
+- `仿制商业海报`: AI文生图工具(如即梦)依据提示词生成的仿制商业海报候选图,风格与参考图高度近似,通常批量出图后人工挑选最佳一张  (来自 case-C_xhs_69832685, extends `样图`)
+
+- `API密钥`: 第三方平台 API 访问凭证字符串,用于接口鉴权  (来自 case-B_zhihu_20432492, extends `生成参数`)
+- `视频元数据`: 短视频平台 API 返回的媒体元数据 JSON 对象,含 video_url(真实播放地址)、封面图 URL、视频描述等字段  (来自 case-B_zhihu_20432492, extends `描述`)
+- `消息`: API 调用返回的状态消息字符串,指示成功或错误原因  (来自 case-B_zhihu_20432492, extends `评语`)
+- `链接`: 资源定位符字符串(URL),作为 API 调用的目标地址输入,指向待处理的视频资源  (来自 case-B_zhihu_20432492, extends `生成参数`)
+
+- `受众画像`: 对目标受众群体特征、使用习惯、痛点与认知现状的文字刻画,作为后续内容策划的定位依据  (来自 case-C_zhihu_20369358, extends `描述`)
+- `认知框架`: 对某一领域核心概念关系与运作方式的比喻性描述,帮助受众建立正确的认知模型,作为后续写作的核心论点依据  (来自 case-C_zhihu_20369358, extends `描述`)
+- `课程结构表`: 按学习递进顺序排列的多阶段课程骨架,每个阶段含名称、学习目标与前后衔接逻辑,作为专栏内容规划的结构性蓝图  (来自 case-C_zhihu_20369358, extends `大纲`)
+- `专栏序章`: 以专栏开篇文章形式发布的正文内容,介绍系列课程的目标受众、核心理念与章节结构,作为整个专栏的引导性终态文字  (来自 case-C_zhihu_20369358, extends `正文`)
+
+- `JSON提示词`: 以JSON结构描述的图像提示词,涵盖subject/color_palette/lighting/composition/aesthetic等多维层级,由豆包深度思考模式反推生成  (来自 case-A_gzh_4d6f09a4, extends `提示词`)
+
+- `JSON提示词`: 以JSON结构描述的图像提示词,涵盖subject/color_palette/lighting/composition/aesthetic等多维层级,由豆包深度思考模式反推生成  (来自 case-?, extends `提示词`)
+
+- `扩展插件`: 安装到 ComfyUI 运行环境的自定义节点扩展包,提供额外的节点类型供工作流调用,可被反复装载复用(如 ComfyUI-WD14-Tagger、One Button Prompt 等)  (来自 case-A_xhs_66d730d4, extends `模型权重`)
+- `节点配置`: ComfyUI 工作流中已添加并配置完毕的单个节点实例,包含节点类型与所有参数设定,是工作流节点图的组成单元  (来自 case-A_xhs_66d730d4, extends `工作流`)
+
+- `元提示词`: 用于驱动AI(Gemini Canvas)生成代码/网页界面的结构化系统提示词,内含RCCUWI框架槽位,与图像生成正向prompt不同  (来自 case-B_xhs_695b81a3, extends `提示词`)
+- `修改需求`: 用户以自然语言表达的针对当前网页版本的改动指令  (来自 case-B_xhs_695b81a3, extends `描述`)
+- `网页应用`: 由AI生成的可在浏览器中运行的交互式网页工具,含界面布局/交互逻辑/AI接口调用  (来自 case-B_xhs_695b81a3, extends `工作流`)
+- `产品信息`: 用户录入的产品基本信息,含产品类型/品类/核心卖点  (来自 case-B_xhs_695b81a3, extends `描述`)
+- `风格配置`: 用户在工作站中设定的风格参数集合,含风格关键词/时间段/分类标签,约束AI生成MJ提示词方向  (来自 case-B_xhs_695b81a3, extends `生成参数`)
+
+- `Token序列`: Tokenizer将自然语言文本切分后得到的字符串token列表,如['今天','天气','很','好'],是文本在词表粒度上的离散序列表示  (来自 case-C_xhs_69ee4674, extends `描述`)
+- `Token_ID序列`: Token序列中每个token在词表中对应的整数索引列表,形状[n,],值域[0, vocab_size-1],是模型实际消费的数字化输入  (来自 case-C_xhs_69ee4674, extends `描述`)
+- `注意力掩码`: 与padded token_ids同形状的二元矩阵,有效token位置=1,padding位置=0,用于在注意力计算中屏蔽padding位置  (来自 case-C_xhs_69ee4674, extends `蒙版`)
+- `嵌入矩阵`: 词嵌入查表后得到的token向量矩阵,形状[n, d_model],每行是对应token在连续语义空间中的浮点表示  (来自 case-C_xhs_69ee4674, extends `模型权重`)
+- `隐状态矩阵`: Transformer各层输入/输出的中间表征矩阵,形状[n, d_model],承载当前层对序列的语义理解,是后续层持续改造的对象  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `QKV矩阵组`: 注意力机制中Query、Key、Value三个线性投影矩阵的组合,各形状[n, d_model],分别负责查询匹配、键索引和值聚合  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `多头QKV`: 将QKV矩阵reshape为多头形式后的张量,形状[n, n_heads, d_head],支持多头并行注意力计算  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `注意力分数矩阵`: QK点积经缩放和因果掩码处理后的注意力分数,形状[n_heads, n, n],未来位置被置为负无穷  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `注意力输出矩阵`: 经softmax归一化后对V做加权求和得到的注意力输出,形状[n, n_heads, d_head],是多头注意力的直接产出  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `位置向量`: 最终隐状态矩阵最后一行XL[n-1],形状[d_model,],代表模型处理完整prompt后的上下文压缩表征  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `归一化向量`: 经Final LayerNorm处理后的最终特征向量,形状[d_model,],数值尺度对齐到LM Head期望输入范围  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `logits向量`: LM Head对最终表征线性投影得到的未归一化预测分数,形状[vocab_size,],每个位置对应词表中一个token的预测得分  (来自 case-C_xhs_69ee4674, extends `底图`)
+- `KV缓存`: prefill阶段按层和注意力头缓存的K/V矩阵,每层形状[2, n_heads, n, d_head],供后续自回归decode阶段复用以避免重复计算  (来自 case-C_xhs_69ee4674, extends `生成参数`)
+- `解码配置`: 控制解码行为的参数集合,包含temperature缩放系数、logits_bias词级偏置、repetition_penalty重复惩罚系数和bad_words_ids屏蔽列表  (来自 case-C_xhs_69ee4674, extends `生成参数`)
+- `候选Token列表`: 经Top-k/Top-p截断后保留的候选token子集,形状仍[vocab_size,]但非候选位置logits被置为负无穷,等待最终采样决策  (来自 case-C_xhs_69ee4674, extends `样图`)
+- `输出Token`: 经采样或argmax决策后产出的第一个生成token,对应词表中某个整数ID及其解码后的子词或字符,是本次推理的最终交付物  (来自 case-C_xhs_69ee4674, extends `正文`)
+
+- `关键词列表`: 按核心词、场景词、问题词三类分类整理的关键词条目集合,用于后续嵌入文章结构的指定位置  (来自 case-creative_1, extends `知识库`)
+- `含关键词骨架`: 在文章章节骨架基础上标注了关键词嵌入位置规则(标题含核心词、首段前三行融入核心词、正文每300字一个场景词、小标题含问题词)的结构化内容规划  (来自 case-creative_1, extends `大纲`)
+- `文章草稿`: 按价值密度、表达节奏、视觉辅助三维准则展开填充的完整正文中间态,含加粗重点、案例数据、设问、配图说明,尚未添加互动钩子,需后续步骤继续处置  (来自 case-creative_1, extends `脚本`)
+
+- `写作触发`: 触发写作冲动的灵感事件或感受,如读书感受、被某篇文章触动、某事件引发的感慨与写作冲动  (来自 case-creative_2, extends `描述`)
+- `账号定位`: 公众号账号的写作定位与目标受众范围,是跨批次复用的账号策略约束(如:公众号运营、写作成长、退休生活等领域)  (来自 case-creative_2, extends `描述`)
+- `选题方向`: 经爆款潜力与定位符合双重筛选后确定的粗粒度写作话题方向,尚未细化为具体角度  (来自 case-creative_2, extends `描述`)
+- `竞品数据`: 在公众号、知乎、百度等平台搜索同话题历史文章所得的阅读量数据,用于验证选题是否具有读者基础  (来自 case-creative_2, extends `知识库`)
+- `选题`: 经阅读量验证与核心卖点确认后的具体写作选题角度,比选题方向更精细、可直接指导创作  (来自 case-creative_2, extends `描述`)
+- `素材`: 从公众号、知乎、百度及书籍中一次性收集的、支撑各分论点的观点、论据、案例与数据集合  (来自 case-creative_2, extends `知识库`)
+- `草稿`: 包含开头、各分论点展开、段落过渡与结尾的完整文章初稿,已具备正文形态但尚未定稿,需继续修改打磨后才能发布  (来自 case-creative_2, extends `正文`)
+
+- `关键词`: 用于搜索或检索的单个关键词,作为信息获取步骤的查询输入,指向某一主题领域(如「减肥」)  (来自 case-creative_3, extends `提示词`)
+- `竞品内容`: 同行账号在抖音/小红书等平台发布的高播放量内容,作为被研究、借鉴打法的整体范本(含评论区)  (来自 case-creative_3, extends `对标内容`)
+- `痛点列表`: 从单一渠道(评论区或社群)收集到的用户痛点陈述条目列表,各条目独立成行,是进一步汇聚的原始素材  (来自 case-creative_3, extends `大纲`)
+- `社群`: 创作者所在的行业微信群/QQ群等社群,作为用户真实吐槽与痛点的信息采集渠道  (来自 case-creative_3, extends `知识库`)
+- `关键词列表`: 搜索引擎/平台输入关键词后出现的下拉联想词条目列表,反映用户真实搜索意图与痛点  (来自 case-creative_3, extends `大纲`)
+- `痛点清单`: 汇聚自评论区、社群、搜索下拉词三个渠道的用户痛点问题汇总清单,是选题筛选的直接依据  (来自 case-creative_3, extends `大纲`)
+- `选题问题`: 从痛点清单中提炼出的核心问题表述(通常为一个问句),是后续标题创作与内容策划的锚点  (来自 case-creative_3, extends `描述`)
+- `人设规格`: 创作者在短视频平台的角色定位描述,包含职业身份、专业角度与表达风格(如「营养师(专家型)——从代谢角度分析」)  (来自 case-creative_3, extends `描述`)
+- `选题方案`: 结合人设视角对钩子标题进行匹配调整后输出的完整选题设计方案,包含人设切入角度与具体标题  (来自 case-creative_3, extends `描述`)
+- `内容素材`: 支撑选题内容生产的多类型素材集合,包含真实案例故事、权威数据来源与证据截图等,供脚本/正文撰写取用  (来自 case-creative_3, extends `知识库`)
+
+- `需求信号列表`: 由多渠道并行采集汇聚的需求信号集合,包含搜索热点词、同行爆款样本、评论区痛点、头部创作者选题规律等,供后续选题转化步骤消费  (来自 case-creative_4, extends `知识库`)
+- `热搜词`: 从搜索平台检索得到的与内容方向相关的热搜关键词列表,含热度趋势标注,反映当前平台用户搜索需求  (来自 case-creative_4, extends `知识库`)
+- `用户反馈`: 从高互动内容评论区提取的用户高频痛点与诉求聚类,反映目标受众的真实需求与困惑  (来自 case-creative_4, extends `知识库`)
+- `规律总结`: 通过研究头部创作者内容提炼出的选题规律与打法模式,如常用结构组合、高频内容类型、标题惯用套路等  (来自 case-creative_4, extends `知识库`)
+- `候选选题`: 基于选题框架批量生成的选题候选列表,每条注明所用框架,作为待进一步优化打磨的选题骨架  (来自 case-creative_4, extends `大纲`)
+- `选题`: 经优化打磨后具备高传播潜力的内容选题,含差异化亮点标注,作为内容创作的最终选定方向  (来自 case-creative_4, extends `标题`)
+
+- `题目图片`: 包含数学题目内容(公式+图形+文字说明)的截图,用作 GPT Image 2.0 的视觉理解输入  (来自 case-C_gzh_8a75847e, extends `截图`)
+- `课文套组`: 由同一提示词一次生成的两张配套成品图:课文学习海报(知识板块+情境插画)和同步练习卷(分栏题型+分值标注),用于课文教学整套配套  (来自 case-C_gzh_8a75847e, extends `成品图`)
+- `词卡系列`: 批量生成的多张单词卡片集合,每张风格迥异、互不雷同;单次超级提示词产出,各卡自包含单词、音标/读法、中文释义和视觉场景  (来自 case-C_gzh_8a75847e, extends `成品图`)
+
+- `图片策划序列`: LLM输出的N个结构化图片策划块的有序序列,每块含图片定位/核心信息/文字内容/视觉提示词  (来自 case-A_xhs_69663d9d, extends `提示词`)
+- `图片策划`: 单张信息图的结构化策划块,含图片定位/核心信息/文字内容(主标题+副标题+补充说明)/视觉提示词  (来自 case-A_xhs_69663d9d, extends `提示词`)
+- `信息图`: NanoBanana生成的小红书简笔画素描风格单张信息图(竖版3:4,手写体文字),终态成品直接交付  (来自 case-A_xhs_69663d9d, extends `成品图`)
+- `信息图序列`: N张小红书简笔画风格信息图的有序列表,构成完整信息图系列,终态成品集合直接交付  (来自 case-A_xhs_69663d9d, extends `成品图`)
+- `文本`: 用户提供的待可视化原始文字内容(如某主题的教程、知识点或经验分享),在工序中作为LLM内容分析的输入素材  (来自 case-A_xhs_69663d9d, extends `正文`)
+
+- `参数列表`: 从需求描述中提取出的结构化变量参数清单,列出可替换参数与固定元素,供后续提示词模板组合使用  (来自 case-A_zhihu_20382372, extends `描述`)
+
+- `参数列表`: 从需求描述中提取出的结构化变量参数清单,列出可替换参数与固定元素,供后续提示词模板组合使用  (来自 case-?, extends `描述`)
+
+- `文本`: 文本形式的主题关键词、场景描述或内容要求,作为图像生成的描述性输入依据  (来自 case-B_zhihu_20418774, extends `描述`)
+- `生成图`: 由 GPT-Image-2 文生图步骤产出的终态图像,作为最终交付成品  (来自 case-B_zhihu_20418774, extends `成品图`)
+
+- `平台工具`: 操作入口所在的平台及工具信息,说明使用哪个 Web 平台访问哪个 AI 工具  (来自 case-A_xhs_6a16c1d0, extends `生成参数`)
+- `工具配置`: 工具与模型的综合配置项,含平台模型选型、参考模式、画幅规格、时长及配音等  (来自 case-A_xhs_6a16c1d0, extends `生成参数`)
+
+- `平台账号`: 访问特定平台所需的账号凭证,包含登录信息及可用配额(如即梦平台每日赠送的88-100免费积分)。  (来自 case-C_gzh_e55e66b8, extends `生成参数`)
+- `关键词`: 提示词中具有特定视觉或语义影响力的单个词项,用于控制生图结果的局部属性(如光照时段、渲染风格、色调),可被单独替换以观察画面变化。  (来自 case-C_gzh_e55e66b8, extends `提示词`)
+- `提示词能力`: 通过大量关键词替换实验积累形成的感知性知识——掌握「关键词→画面变化」映射规律,能快速将脑中意图转化为AI可理解的精准提示词。  (来自 case-C_gzh_e55e66b8, extends `知识库`)
+- `参考样本`: 已成功完成的样本实例(如已排版的网页框架、成功的文案或代码结构),整体作为AI处理新内容时的风格/结构/逻辑参照。  (来自 case-C_gzh_e55e66b8, extends `对标内容`)
+- `原始素材`: 待按参考样本风格处理的原始内容(如未排版的新文章),在工序中作为被加工的主体输入,经AI处理后产出风格对齐的结果。  (来自 case-C_gzh_e55e66b8, extends `正文`)
+- `AI处理结果`: AI按填入变量后的提示词模板执行任务后产出的内容结果(如产品经理视角的用户留存策略分析),质量稳定可预期,作为工序的最终交付物。  (来自 case-C_gzh_e55e66b8, extends `正文`)
+- `变量值`: 用于填入提示词模板中各占位符的具体参数值组合(如职业/角色、任务描述、受众特征、输出格式等),驱动模板实例化并执行AI任务。  (来自 case-C_gzh_e55e66b8, extends `生成参数`)
+- `提示词武器库`: 持续积累的个人提示词资产库,以飞书或Chat Memo为载体,存储经过验证的可复用提示词与模板,构成长期护城河。  (来自 case-C_gzh_e55e66b8, extends `知识库`)
+- `提示词模板`: 带[变量名]占位符的可复用提示词骨架,固定结构部分不变,可变参数用占位符标记,使用时填入具体变量值即可直接执行。  (来自 case-C_gzh_e55e66b8, extends `模板`)
+
+- `产品图`: 本次工序中待迁移风格的目标产品图(雅诗兰黛 Re-Nutriv 护肤水官方图),被 AI 分析以提取目标产品的外观特征,并在生图时作为图像参考上传到 Jimeng;其角色是'被模仿/被迁移风格的目标实体',而非单纯的风格范本,因此以 case-specific 类型独立标注。  (来自 case-A_xhs_6968aa4d, extends `参考图`)
+- `工具配置`: Jimeng 文生图工具的综合生图配置集合,包含:已粘贴的反推提示词、已上传的目标产品参考图、画面比例(2:3)、参考强度(100%)、使用模型(图片 4.0)、输出规格(高清 2K);属于本次生图任务的完整参数束,超出单一生成参数范畴故作 case-specific 注册。  (来自 case-A_xhs_6968aa4d, extends `生成参数`)
+
+- `生成图`: 由文生图模型依据提示词输出的复刻成品图,是本工序的最终交付物;用于区分来自 AI 生成器(而非摄影或设计工具)的成品图像  (来自 case-B_xhs_693adc7f, extends `成品图`)
+
+- `需求文档`: 对目标广告效果等创作需求的文字说明,作为后续生成步骤的输入依据  (来自 case-A_gzh_9091d1e7, extends `描述`)
+- `提示词块`: 用于后续拼合为完整生成提示词的分段描述文本,如卖点描述块、场景构图块、光线风格块  (来自 case-A_gzh_9091d1e7, extends `提示词`)
+- `广告图提示词`: 由多个描述块合并而成的完整文生图提示词,用于驱动广告图像的AI生成  (来自 case-A_gzh_9091d1e7, extends `提示词`)
+- `广告图`: 以实物照为基础、经AI图生图生成的最终交付广告图像  (来自 case-A_gzh_9091d1e7, extends `成品图`)
+- `实体产品`: 待拍摄的实体商品,作为摄影采集的主体对象,其视觉呈现将通过拍摄步骤转化为数字素材  (来自 case-A_gzh_9091d1e7, extends `参考图`)
+- `产品照片`: 手机拍摄得到的产品实物照片,作为图生图换背景的基础输入图像  (来自 case-A_gzh_9091d1e7, extends `底图`)
+- `图生图提示词`: 用于图生图(换背景)操作的提示词,描述目标场景、光线和风格,保留产品主体  (来自 case-A_gzh_9091d1e7, extends `提示词`)
+
+- `图片描述`: AI对参考图结构化识别后生成的描述文本,含主体、背景、视觉风格、色调、构图、光影等维度  (来自 case-C_zhihu_20169233, extends `描述`)
+- `节气海报`: 以中国传统节气为主题的AI批量生成海报图,含节气文字排版、传统文化元素和装饰艺术风格  (来自 case-C_zhihu_20169233, extends `成品图`)
+
+- `创作需求`: 图片主题、用途与内容要点的文字描述,是图像创作的原始需求输入  (来自 case-?, extends `描述`)
+- `图片定位`: 图像的使用场景、目标平台与版式方向的定位性描述  (来自 case-?, extends `描述`)
+- `风格标签`: 图像视觉风格方向的关键词组合标签(如水墨风/微缩景观/诗意高端)  (来自 case-?, extends `描述`)
+- `新创作目标`: 新主题的替换要素说明,含城市名、地标、诗词文案等待替换的核心内容变量  (来自 case-?, extends `描述`)
+
+- `主题构想`: 用户对本次生成目标的主题意图描述,包含风格期望(水墨禅意)与构图诉求(留白供排版),作为构建提示词的原始输入依据  (来自 case-B_zhihu_20365059, extends `描述`)
+- `封面图`: 科技新闻杂志风格的封面图像,包含标题文字、视觉主体与配色排版,可作为底图被后续指令迭代修改  (来自 case-B_zhihu_20365059, extends `成品图`)
+- `修改需求`: 针对已生成背景图提出的变体修改意见,指定画面主体与色调调整方向,驱动下一轮图像迭代  (来自 case-B_zhihu_20365059, extends `评语`)
+- `背景图`: 水墨风格的PPT横版背景图,以远山云雾或竹林为主体,含大面积留白供文字排版,可被后续指令迭代生成变体  (来自 case-B_zhihu_20365059, extends `成品图`)
+
+- `操作界面`: 工具平台的配置操作界面,带有多个可填写区域(如基础设定、提示词、高级设定等),是智能体配置流程的交互载体  (来自 case-A_gzh_7dfd3085, extends `模板`)
+- `配置项`: 智能体配置中已填写完成的具体设定条目,记录名称、简介、头像、提示词等配置内容  (来自 case-A_gzh_7dfd3085, extends `描述`)
+- `AI智能体`: 已配置并发布到平台的AI对话式智能体实例,包含基础设定与系统提示词,可被用户调用执行多步对话任务  (来自 case-A_gzh_7dfd3085, extends `工作流`)
+- `分析报告`: 对图像或内容按结构化公式所做的系统性分析,拆解风格、主题、构图、色彩、情绪等维度,以定性文字输出  (来自 case-A_gzh_7dfd3085, extends `评语`)
+
+- `创意方向`: 视频创作方向与主题意图的文字刻画,含人物设定、场景风格、叙事核心等创意要素,作为手写提示词步骤的原始输入依据  (来自 case-C_gzh_5bdae160, extends `描述`)
+- `生成图`: AI文生图模型(豆包)直接输出的像素风格图像,含水印或去水印后均以此类型流转,后续经去水印处理并作为图生视频步骤的参考帧输入,是图像→视频转换链路的中间态  (来自 case-C_gzh_5bdae160, extends `底图`)
+- `生成视频`: AI图生视频模型(即梦)直接输出的像素风格动态视频片段,含水印或去水印后均以此类型流转,最终作为剪映剪辑合成步骤的主体素材被组装进成片  (来自 case-C_gzh_5bdae160, extends `视频片段`)
+- `音频素材`: 从爆款短视频平台或个人音乐库中挑选的背景音乐,与像素风赛博朋克视频风格匹配,被混入剪映剪辑合成步骤的音轨  (来自 case-C_gzh_5bdae160, extends `BGM`)
+- `合成视频`: 剪映合成后的完整短视频,含配乐BGM、字幕/对话气泡及0.7倍变速处理,时长约7.2秒,是发布前的完整成品形态  (来自 case-C_gzh_5bdae160, extends `视频成品`)
+- `短视频`: 发布到视频号/抖音/小红书等公域平台的像素风格赛博朋克AI短视频,是工序链路的最终交付物  (来自 case-C_gzh_5bdae160, extends `视频成品`)
+
+- `主题词`: 单个主题词条,用于定向替换或标识特定语义对象的极短文字片段(如节气名称、风格标签等)  (来自 case-B_zhihu_20400839, extends `描述`)
+
+- `视觉风格JSON`: 从参考图中提取的多维度视觉风格结构化描述(JSON格式),涵盖颜色、排版、构图、特效、色调、表现手法、氛围等维度,作为后续图像生成步骤的风格控制依据被消费。  (来自 case-B_gzh_e9677a53, extends `描述`)
+
+- `风格描述`: 豆包从参考图提取的JSON格式视觉风格描述,含颜色/排版/构图/特效四个维度,作为生图提示词的风格模板来源  (来自 case-B_gzh_25318352, extends `描述`)
+
+- `迭代记录`: 记录多轮提示词迭代的完整过程日志——每条记录包含该轮的提示词版本、执行结果(是否达预期)、发现的问题以及下一步的修改方向;是对已产出物逐轮评判+修改意见的历史汇总,兼具过程审查与版本溯源作用。  (来自 case-C_zhihu_20313114, extends `评语`)
+
+- `创意意图`: 用户对想生成图像的初始模糊描述,尚未结构化,常表现为堆叠关键词  (来自 case-C_zhihu_19056944, extends `提示词`)
+- `8要素骨架`: 按「主体+场景+动作/关系+构图+光线+风格/媒介+质感+镜头参数」公式填写的结构化要素清单  (来自 case-C_zhihu_19056944, extends `提示词`)
+- `完整提示词方案`: 包含正向提示词(含参考系、构图控制词)与负向提示词的完整 AI 生图提示词集合,可直接粘贴至生图工具  (来自 case-C_zhihu_19056944, extends `提示词`)
+- `出片规划`: 二段式出片的操作计划:草图阶段(先对构图)→ 细节强化阶段(皮肤/眼睛/材质/背景)  (来自 case-C_zhihu_19056944, extends `脚本`)
+- `一致性配置`: 用于系列图输出的一致性策略配置:参考图上传设置 + 固定 Seed + 单变量迭代规则  (来自 case-C_zhihu_19056944, extends `生成参数`)
+
+- `视觉风格JSON`: 多模态AI对图片视觉风格的结构化JSON分析结果,含颜色/构图/排版/主体/质感/光影/特效/氛围/复刻关键词等字段,用作后续生图步骤的引导输入  (来自 case-aaa_test_1, extends `提示词`)
+- `生成图`: 由生成模型按提示词产出的终态图像,不再进入后续加工,直接作为本次工序的交付成品  (来自 case-aaa_test_1, extends `成品图`)
+- `分镜分析列表`: Qwen3-VL对视频各分镜的结构化分析结果列表,每项含画面风格/主体特征/服装/动作/镜头变化/构图/光影/台词/音效/画质参数等,作为逐镜视频生成的批量输入  (来自 case-aaa_test_1, extends `提示词`)
+- `分镜分析`: 单个分镜的详细分析数据,包含画面风格、主体特征、服装物品、动作描述、镜头变化、构图、光影、台词旁白、音效、画质参数和时长,作为单段视频生成的引导指令  (来自 case-aaa_test_1, extends `提示词`)

+ 0 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec/taxonomy/分类库导出_实质_20260512_132218.json → examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/分类库导出_实质_20260512_132218.json


+ 0 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec/taxonomy/分类库导出_形式_20260512_170623.json → examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/taxonomy/分类库导出_形式_20260512_170623.json


+ 28 - 38
examples/process_pipeline/script/search_eval/procedure-dsl/spec/templates/workflow.template.json → examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/templates/workflow.template.json

@@ -1,5 +1,5 @@
 {
-  "$comment": "spec/templates/workflow.template.json — Agent 在 Phase 1 Write 这份 workflow.json 骨架 (复制到 outputs/case-{N}/workflow.json + 替换所有 <填:...> 占位符), 之后各 phase in-place Edit 它 (不写新文件). 顶层 `procedures` 是数组: 多工序填多个 procedure 对象; 单工序 case 删掉示例里的 p2, procedures 只留长度-1 数组. page_title 不写进本文件 — Phase 3 由 --page-title 提供; source.body_text/封面 由 --source-input 自动填. Phase 3 跑: `python spec/tools/render-case.py --workflow outputs/case-{N}/workflow.json --source-input input/case-{N}-raw.json --page-title \"Case N · 主题\" --case-id N --out outputs/case-{N}/case-{N}-<slug>.html` (renderer 内存组装 case_data, 不落盘 case_data.json) + `python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id N`. Schema 见 spec/format/case-data.schema.json (canonical), 字段说明见 spec/format/procedure-table.md.",
+  "$comment": "spec/templates/workflow.template.json — Agent 在 Phase 1 Write 这份 workflow.json 骨架 (复制到 outputs/case-{N}/workflow.json + 替换所有 <填:...> 占位符), 之后各 phase in-place Edit 它 (不写新文件). 顶层 `procedures` 是数组: 多工序填多个 procedure 对象; 单工序 case 删掉示例里的 p2, procedures 只留长度-1 数组. page_title 不写进本文件 — Phase 3 由 --page-title 提供; source.body_text/封面 由 --source-input 自动填. Phase 3 跑: `python spec/tools/render-case.py --workflow outputs/case-{N}/workflow.json --source-input input/case-{N}-raw.json --page-title \"Case N · 主题\" --case-id N --out outputs/case-{N}/case-{N}-<slug>.html` + `python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id N`. Schema 见 spec/format/case-data.schema.json (canonical), 字段说明见 spec/format/workflow-format.md.",
 
   "source": {
     "platform": "<填:原文平台 e.g. wechat-gzh>",
@@ -20,7 +20,7 @@
       "author":   "<填:作者, 通常同 source.author>",
       "declarations": {
         "inputs": [
-          { "type": "<填:类型>", "name": "<填:变量名>", "desc": "<填:说明 (可选)>" }
+          { "type": "<填:类型>", "name": "<填:声明名>", "desc": "<填:说明 (可选)>" }
         ],
         "resources": [],
         "returns": { "type": "<填:返回类型>" }
@@ -32,37 +32,29 @@
         {
           "id": "s1",
           "kind": "step",
-          "effect":  "<填:作用 = spec/taxonomy/effect.json $leaves 之一 (须命中字典叶子)>",
-          "via":     "<填:工具名 e.g. human / nano_banana / (AI 生图工具)>",
-          "action":  "<填:动作 = spec/taxonomy/action.json 树路径 e.g. 提取/化学提取/解构>",
-          "feature": "<填:随机|幂等|写外部|读外部|人工|本地|->",
-          "control": "-",
-          "instruction": [
-            ["directive", "<填:给工具的 prompt 文本 (可选)>"],
-            ["memo",      "<填:工艺备注 (可选)>"]
-          ],
+          "effect":    "<填:作用 = spec/taxonomy/effect.json $leaves 之一 (须命中字典叶子)>",
+          "substance": "<填:实质路径 (step 级, 整步内容是什么) e.g. /理念/知识/... (走 taxonomy-lookup.py --validate 校验); 纯技术参数可 null>",
+          "form":      "<填:形式路径 (step 级, 整步内容怎么呈现) e.g. /架构/逻辑/...; 不适用可 null>",
+          "via":       "<填:工具名 e.g. human / nano_banana / (AI 生图工具)>",
+          "action":    "<填:动作 = spec/taxonomy/action.json 树路径 e.g. 提取/化学提取/解构>",
+          "directive": "<填:给工具的 prompt 文本 (可选; 人工/控制流步留空)>",
           "inputs": [
             {
-              "substance": "<填:实质路径 e.g. /理念/知识/... (走 taxonomy-lookup.py --validate 校验)>",
-              "form":      "<填:形式路径 e.g. /架构/逻辑/...>",
-              "type":      "<填:类型 = spec/taxonomy/type.json 叶子, 或 case-specific (须在本 procedure.type_registry 注册 extends)>",
-              "name":      "<填:变量名>",
-              "value":     "<填:数据内容描述>",
-              "anchor":    "<填:← 工序输入 / ← sN.x>"
+              "type":   "<填:类型 = spec/taxonomy/type.json 叶子, 或 case-specific (须在本 procedure.type_registry 注册 extends)>",
+              "value":  "<填:数据内容本身>",
+              "anchor": "<填:← 工序输入 / ← <上游 output id> e.g. ← s1o1>"
             }
           ],
           "outputs": [
             {
-              "substance": "<填:实质路径>",
-              "form":      "<填:形式路径>",
-              "type":      "<填:类型>",
-              "name":      "<填:变量名>",
-              "value":     "<填:数据内容描述>",
-              "anchor":    "<填:→ sN / → 返回 X>"
+              "id":     "<填:output id, 工序内唯一 e.g. s1o1 (供下游 anchor 引用)>",
+              "type":   "<填:类型>",
+              "value":  "<填:数据内容本身>",
+              "anchor": "<填:→ sN / → 返回 X (去处, 松散)>"
             }
           ],
           "intent": "<填:目的列 token 句, e.g. 用 {via:X} {act:Y} 从 {in-type:Z} 得到 {out-type:W}>",
-          "focus":  ["via", "action", "in-type-0", "out-type-0"]
+          "focus":  ["via", "action", "out-type-0"]
         }
       ],
       "return_row": {
@@ -79,7 +71,7 @@
       "platform": "<填:平台>",
       "author":   "<填:作者>",
       "declarations": {
-        "inputs": [ { "type": "<填:类型>", "name": "<填:变量名>" } ],
+        "inputs": [ { "type": "<填:类型>", "name": "<填:声明名>" } ],
         "resources": [],
         "returns": { "type": "<填:返回类型>" }
       },
@@ -87,25 +79,23 @@
         {
           "id": "s1",
           "kind": "block",
-          "control": "<填:遍历|并行|分支>",
           "via": "-",
-          "feature": "-",
-          "intent": "<填:控制块整体在做什么 (高层意图). 块只带 control+intent+via='-'+feature='-'+io; effect/action/focus 归下面 nested 执行步, 块本身不要>",
-          "inputs":  [ { "type": "<填:类型>", "name": "<填:被遍历的序列>", "anchor": "<填:← sN.x>" } ],
-          "outputs": [ { "type": "<填:类型>", "name": "<填:累积结果列表>", "anchor": "<填:→ sN>" } ]
+          "intent": "<填:控制块整体在做什么 (高层意图). 块只带 via='-' + intent + io; effect/action/substance/form 归下面 nested 执行步, 块本身不要>",
+          "inputs":  [ { "type": "<填:类型>", "value": "<填:数据内容>", "anchor": "<填:← <上游 output id>>" } ],
+          "outputs": [ { "id": "<填:s1o1>", "type": "<填:类型>", "value": "<填:累积结果>", "anchor": "<填:→ sN>" } ]
         },
         {
           "id": "s1.1",
           "kind": "nested",
           "group": "s1",
-          "effect":  "<填:作用叶子>",
-          "via":     "<填:工具名>",
-          "action":  "<填:动作路径>",
-          "feature": "<填:随机|幂等|人工|...>",
-          "control": "-",
-          "instruction": [ ["decorator", "@采样(n=4, pick=人工)  (可选: 抽样 N 选 1 等修饰)"] ],
-          "inputs":  [ { "substance": "<填:实质路径>", "form": "<填:形式路径>", "type": "<填:类型>", "name": "<填:循环变量>", "value": "<填:数据内容描述>", "anchor": "<填:← 被遍历序列[i]>" } ],
-          "outputs": [ { "substance": "<填:实质路径>", "form": "<填:形式路径>", "type": "<填:类型>", "name": "<填:单次产出>", "value": "<填:数据内容描述>", "anchor": "<填:→ 累积结果列表.追加>" } ],
+          "effect":    "<填:作用叶子>",
+          "substance": "<填:实质路径>",
+          "form":      "<填:形式路径>",
+          "via":       "<填:工具名>",
+          "action":    "<填:动作路径>",
+          "directive": "<填:给工具的 prompt (可选)>",
+          "inputs":  [ { "type": "<填:类型>", "value": "<填:数据内容>", "anchor": "<填:← <被遍历序列的 output id>[i]>" } ],
+          "outputs": [ { "id": "<填:s1.1o1>", "type": "<填:类型>", "value": "<填:单次产出>", "anchor": "<填:→ 累积结果.追加>" } ],
           "intent": "<填:这一次迭代在做什么>",
           "focus":  ["via", "action", "out-type-0"]
         }

+ 244 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools.md

@@ -0,0 +1,244 @@
+# 脚本怎么用(工具手册)
+
+> 跑这道 skill 时会用命令行调用几个脚本,这里讲它们**怎么用**。脚本都在 `spec/tools/` 下,**你不用读脚本源码,会调就行**。
+
+## 1. `spec/tools/taxonomy-lookup.py` — 查"实质/形式"两张大词表
+
+**做什么**:第二阶段给整步标"实质/形式"时,用它查这两张大词表(911 + 565 条路径)。词表太大不直接读进来,全靠这个命令现查。
+
+**子命令**:
+
+| 子命令 | 用法 | 返回 |
+|---|---|---|
+| 列二级路径 | `python spec/tools/taxonomy-lookup.py --dim 实质 --list-l2` | 各 L2 路径 + 该子树叶子数 |
+| 看子树 | `python spec/tools/taxonomy-lookup.py --dim 实质 --subtree /表象/视觉` | 该子树所有叶子 |
+| 字符串匹配 | `python spec/tools/taxonomy-lookup.py --dim 形式 --match "中景特写"` | 排序候选路径 (单 token 行为) |
+| 多 token 聚合 | `python spec/tools/taxonomy-lookup.py --dim 实质 --match "年轻女性 卧室 床上"` | 各 token 各自打分聚合, 覆盖多 token 的 path bonus |
+| 层级下钻 | `python spec/tools/taxonomy-lookup.py --dim 实质 --narrow "AI生成 提示词"` | 从 L2 起按子树语义打分逐层下钻 top-K (兜底 match miss) |
+| 校验路径存在 | `python spec/tools/taxonomy-lookup.py --dim 实质 --validate /理念/知识/化学` | OK / PARTIAL / MISS (exit 0/1) |
+
+**关于 `--match` 的多 token 行为** (2026-05-22 起):
+- query **含空白** 自动拆 token, 每个 token (≥2 字, 单字噪声大被丢) 独立打分, path 级聚合 score
+- 命中 ≥2 token 的 path 给 coverage bonus (score ×= 1 + 0.3·(cov-1)), 防止单 token 大量命中压死多 token 弱命中
+- **单 token** (无空白) 行为跟旧版完全一致, 不影响已有 query
+- 全 miss 时输出提示, 引导转 `--narrow` 兜底
+
+**关于 `--narrow` 的层级下钻** (2026-05-22 新增):
+- 从所有 L2 出发, 对每个候选子树计算 `(token 命中次数, 命中的 token 数)`, 按 cov ↘ hits ↘ 排序
+- 每层取 `--top-per-level` (默认 3), 进下一层只展开这些候选的直接子节点
+- 直到 `--depth` (默认 3 层, L2→L3→L4→L5) 或全部到叶子
+- 比 `--match` 容错更强: alias 完全没覆盖但路径段语义沾边的 case 也能召回 (e.g. "镜头语言" 不在 alias 但 `/呈现/视觉/视觉制作/构图编排` 路径段直接对路)
+
+**Agent 用法 (典型 funnel)**:
+1. `--list-l2` 决定大致 domain (实质先选 /理念 vs /表象, 形式先选 /呈现 vs /架构)
+2. `--match <query>` 多 token 召回候选 (大概率一步搞定)
+3. **若 `--match` 返 (无匹配)** → `--narrow <query>` 按子树语义下钻
+4. `--subtree <chosen_path>` 看候选 leaf
+5. `--validate <leaf>` 确认后写回 workflow.json 对应 IO 的 substance/form 字段
+
+**词表文件路径** (按优先级 fallback):
+1. `$TAXONOMY_DIR/分类库导出_{实质|形式}_*.json` (env override)
+2. `procedure-dsl/data/分类库导出_*.json`
+3. `examples/process_pipeline/script/resource/分类库导出_*.json`
+4. `examples/process_pipeline/test_script/procedure_dsl_agent/data/分类库导出_*.json`
+5. `~/Downloads/分类库导出_*.json`
+
+---
+
+## 2. `spec/tools/wf-patch.py` — workflow.json 安全批量字段设置器
+
+**做什么**:批量给 `workflow.json` 的步骤/输入输出填字段(第一阶段连"来源",第二阶段填作用/动作/类型/实质/形式)。**凡是"给一批字段赋值"都用它,别写 Python 脚本去拼/改 workflow.json**(脚本拼 JSON 容易把文件弄坏)。分工:**你出判断(哪个字段填什么),工具负责安全写入 + 当场检查对错**。
+
+**两个保证**:
+- **不会写坏文件**:由工具读取→修改→写回,你从不直接碰 JSON 文本。
+- **当场检查,有错全不写**:每条赋值都立刻对照词表/类型登记/格式校验;**只要有一条不合法,就报出是哪条、整批都不写**(不会产出悄悄出错的文件)。检查规则和最后的 lint 一致——**这里通过了,lint 一定过**。
+
+**用法**:
+```bash
+# 单条 / 多条 --set (path=value, 只在第一个 = 处切; value 可含 = 和空格, 整体加引号)
+python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json \
+    --set 'p1.s1.inputs[0].anchor=← s0.主角图' \
+    --set 'p1.s2.effect=主体生成' \
+    --set 'p1.s2.action=生成/图像生成/文生图'
+
+# 批量: 几十处 anchor / 字段一次过 — 写一份 patch 清单 (你仍逐条显式决策每个值), 一条命令应用
+python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --patch _scratch/anchors.json
+#   anchors.json = [{"path":"p1.s1.inputs[0].anchor","value":"← s0.x"}, ...]
+
+# 只校验不写
+python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
+
+# 透传回填: anchor 设好后, 自动把"原样透传"的 value/directive 从源逐字抄过来
+python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --resolve-passthrough
+```
+
+**`--resolve-passthrough`(省得重复抄内容)**:规矩是"值"要写真实内容,不能写"(同上)""见 s1o1"这类引用(那是"来源"该干的,lint 会报)。但同一段内容被后面好几步原样复用时,手抄好几遍很烦。用这个:**只在源头那个输出里填一次真内容**,其余引用处把"来源"设成 `← 源的编号`,工具就顺着编号把真内容**逐字抄到**每个"值"还空着的输入(链式引用也会一路抄到底)。源头找不到的会用 `⚠` 提示。可单独跑,也可跟在 `--set/--patch` 后面。
+
+**路径语法** (proc / step 按 **id** 寻址, 不是下标; 只有真列表才用 `[i]`; 嵌套步 id 带点如 `s2.1` 也支持):
+
+| 路径 | 设的字段 |
+|---|---|
+| `p1.s2.effect` | step 标量 (effect / substance / form / via / action / directive / kind / intent / group) |
+| `p1.s1.inputs[0].anchor` | IO 字段 (anchor / type / value / id) |
+| `p1.s2.1.outputs[0].type` | 嵌套步的 IO |
+| `p1.s2.focus` | step 的 focus 数组 (逗号分隔: `focus=via,action,out-type-0`) |
+| `p1.purpose` | procedure 头部 (name / purpose / category / platform / author) |
+| `p1.declarations.inputs[0].desc` | declarations 内任意字段 (通用下钻) |
+| `source.url` | case-level 原帖信息 (platform / author / date / url / title / excerpt) |
+| `p1.type_registry.场景图.extends` | 注册 case-specific 类型 (自动建 type_registry 段) |
+
+**`--unset PATH`** (删字段, 可重复): 删掉某字段, 取代手 Edit 删. e.g. `--unset p1.declarations.inputs[0].inferred` (declarations 不收 inferred, schema 会拒). 字段本就不存在 → 跳过 (幂等, 不报错).
+
+**各字段校验规则**:
+- `effect` → effect.json 叶子 (给全路径会自动归一到叶名)
+- `action` → action.json 叶子 / 叶路径 (给叶名自动展开成全路径)
+- `type` → type.json 叶子 **或** 本 procedure 已注册的 type_registry 名 (没注册会提示先 `--set p.type_registry.X.extends=<叶子>`)
+- `extends` → 必须桥到 type.json 叶子
+- `substance` / `form` / `url` → substance/form (**step 级**) 走 taxonomy-lookup `--validate`; 三者均可传 `__null__` 设 JSON null
+- `anchor` → 必须 `←` (输入引用, 指向某 output id) 或 `→` (输出去向) 开头
+- `kind` → {step / block / nested}
+- `focus` → 逗号分隔 → 数组 (空串 → `[]`)
+- 其余 (name / value / intent / via / desc / purpose / ...) → 自由文本, 不校验
+
+**仍用 Write / Edit 的只剩**: 骨架首次创建 (Phase 1.2 从 template Write). 改字段 / 删字段 / 改 source 现在都走 wf-patch (`directive` 也是普通标量字段, 直接 `--set`), **不要再 Read→Edit 改 workflow.json** (那会反复重读、烧 token).
+
+**退出码**: `0` 全通过并写入 (或 `--dry-run` 通过) / `1` 有校验失败 (整批未写) / `2` CLI 错 / 文件不存在 / JSON 损坏.
+
+---
+
+## 3. `spec/tools/render-case.py` — 阶段三 workflow.json → HTML 渲染 + schema 校验
+
+**用途**: 阶段三. 接收 `workflow.json` (多工序 `procedures:[]`), 在内存组装成 case_data (merge `--source-input` 原帖 + `--page-title` + `--case-id`), 跑 schema 校验, 渲染输出 HTML. **不落盘 case_data.json**.
+
+**Agent 用法** (推荐): workflow.json 已含全部 procedures + 标注后:
+
+```bash
+# 1. 只校验, 看 schema 错 (建议带 --source-input, 让校验看到的就是 merge 后的最终版)
+python spec/tools/render-case.py \
+    --workflow outputs/case-{N}/workflow.json \
+    --source-input input/case-{N}-raw.json \
+    --page-title "Case {N} · <主题>" \
+    --case-id {N} \
+    --validate
+
+# 2. 校验通过后渲染输出 (--source-input 必带, 否则 HTML 折叠原文区只剩 60 字 excerpt)
+python spec/tools/render-case.py \
+    --workflow outputs/case-{N}/workflow.json \
+    --source-input input/case-{N}-raw.json \
+    --page-title "Case {N} · <主题>" \
+    --case-id {N} \
+    --out outputs/case-{N}/case-{N}-<slug>.html
+```
+
+**关于 `--source-input`** (2026-05-22 新增): renderer 直接从原帖 raw json 抽 `body_text` + 封面 + 图集兜底, in-place 填到 `case_data.source` —— Agent 不必手工复制原文内容. 行为:
+- `body_text` / `cover_image` 直接覆盖 case_data 同字段
+- `title` / `url` 仅在 case_data 缺时填
+- `excerpt` / `author` / `date` / `platform` **不动** (那些是 Agent 推断的友好版本)
+- **图集兜底**: 检查 raw.body_text 已 inline 的 `[image:URL]` 标记, 把 raw.image_url_list 里没 inline 也不是封面的图 append 到 body 末尾 (加 `--- 附图 ---` 分隔符). 适配"小红书短文 + 多图独立列" 和 "微信公众号长文 + inline 图" 两种平台
+
+**输入契约**: 见 [`spec/format/case-data.schema.json`](format/case-data.schema.json) (canonical JSON Schema Draft 2020-12, 受控字段 + enum + 条件约束 `if/then`).
+
+**模板**: [`spec/templates/workflow.template.json`](templates/workflow.template.json) (复制到 `outputs/case-{N}/workflow.json` 后替换 `<填:...>` 占位符).
+
+⚠ **绝对不要参考其他 `outputs/case-*/build_html.py` 或 `outputs/case-*/*.json`** — 那些是 case-specific 产物, 不是模板. 唯一 canonical 模板是 `spec/templates/workflow.template.json`.
+
+**输出码**:
+- `0` — 成功 (渲染或校验通过)
+- `1` — IO / schema / 渲染异常
+- `2` — CLI 参数错误
+
+**依赖**:
+- 必需: `spec/tools/renderer.py` (跟本脚本同目录, 自动 import)
+- 可选: `jsonschema` (装了用 Draft 2020-12 完整校验; 没装走 minimal check fallback)
+
+---
+
+## 4. `spec/tools/lint-case.py` — 轻量 lint + 自动 record 新 type
+
+**用途**: 阶段三. 跑完 `render-case.py` 后跑一次. 干三件事:
+1. **type 完整性 hint**: 扫 workflow.json 各 procedure 的 IO type 字段, 找出"用了 case-specific type 但该 procedure 的 `type_registry` 漏注册 / 缺 extends / 缺 desc"的情况, 打 stdout 给 Agent / 用户看
+2. **value 自包含 hint**: 扫每个 IO 的 value + 每个 directive, 揪出「(同 sN 输出)」「见 sN」「← sN」这类**引用占位** —— spec 要求 value 逐字回填数据本身 (引用归 anchor), 这种占位 schema/type 检查抓不到. 命中会提示跑 `wf-patch.py --resolve-passthrough` 自动回填
+3. **副作用: auto-record**: 把各 procedure.type_registry 里的 case-specific entry 自动 append 到 `spec/taxonomy/type_suggestions.md` 累积条目段 (Agent **不必手工 Write** suggestions, 工具代劳)
+
+**幂等**: dedup key = `(type_name, case_id)` 二元组. 同 case 重跑不重复; 不同 case 同名允许 (跨 case 频次是升级信号).
+
+**用法**:
+```bash
+# 默认: 检测 + 自动 record
+python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N}
+
+# 只检测不写
+python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N} --no-record
+```
+
+**输出范例** (case 含 silent gap 的情况):
+```
+[lint] case-1 (workflow.json)
+  · type 完整性: 2 个提示
+      - [p1] step[1].outputs[0].type='主角图' 是 case-specific 但该 procedure 的 type_registry 没注册
+      - [p1] step[8].inputs[1].type='主角图' 是 case-specific 但该 procedure 的 type_registry 没注册
+  · 无新 type 可 record (type_registry 为空 — 全部 type 命中字典叶子)
+```
+
+**退出码**: 始终 0 (不阻塞流程). 解析 2 = CLI 参数错 / 文件不存在.
+
+**设计哲学**: 不严格. 检测项是 hint 不是 fail; record 是副作用不是核心契约. Agent 看 stdout 决定回不回去补 case_data.type_registry.
+
+---
+
+## 5. `spec/tools/renderer.py` — HTML 渲染主模板 (Python 模块)
+
+**做什么**:把数据渲染成网页的主程序,被 `render-case.py` 在内部调用。
+
+**你不用读它**——通过 `render-case.py` 调用即可。要了解格式,看 [`format/case-data.schema.json`](format/case-data.schema.json)(机器清单)和 [`format/workflow-format.md`](format/workflow-format.md)(格式说明)就够了。
+
+---
+
+## 6. `run_procedure_dsl.py` — runner 本身 (不在 skill 内)
+
+跑 Agent 的入口脚本. **Agent 不读它** — 它在跑 Agent. 但 Agent 可能想知道**自己被怎么起的**:
+
+- OAuth Max 模式 (走 ~/.claude 凭证, 不计 API 费)
+- `allowed_tools = ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task", "Agent"]`  # 🟢 Task / Agent 均可召唤子 Agent (新旧标识符)
+- `permission_mode = "bypassPermissions"` (Agent 全自动, 不停下来问)
+- `cwd = procedure-dsl/` (Agent 的工作目录)
+- `--resume` 支持 (中断后续跑)
+- runner 实时把每 turn 写到 `outputs/case-{N}/_trace.md`
+
+---
+
+## 7. 文件路径约定 (per case)
+
+| 路径 | 内容 | 谁负责 |
+|---|---|---|
+| `input/case-{N}-raw.json` | 原 case 素材 (title / link / body_text / image_url_list / ...) | 人 (Agent 读, 不写) |
+| `outputs/case-{N}/` | Agent 工作目录 (一 case 一目录) | Agent (写产物) |
+| `outputs/case-{N}/.session_id` | SDK session UUID, 用于 `--resume` | runner 写, Agent 不动 |
+| `outputs/case-{N}/_trace.md` | runner 写的实时执行流水 | runner (Agent 别 Read) |
+| `outputs/case-{N}/_scratch/` | **sanctioned scratch 区** — 只用于 dump 大 Bash 输出 (taxonomy --subtree 长结果 / find 结果) 之后 Read 切片, 或一次性 smoke test. runner 预创建. **不要用项目根的 `scratch/`**. ⚠ **不是写 build/normalize 脚本生成 workflow.json 的地方** —— 那个用 §2 `wf-patch.py` | Agent (随便 dump, 跟着 case 一起清理) |
+| `outputs/case-{N}/understanding.md` | 阶段一 1.1 心智模型 (含多工序判断) | Agent |
+| `outputs/case-{N}/workflow.json` | **唯一中间产物** — Phase 1.2 Write 骨架 (从 template), 之后**逐字段演化**: 单处用 Edit, 批量结构化字段 (1.3 anchor / 2 effect·action·type + step 级 substance·form) 用 §2 `wf-patch.py`. **绝不写 Python 脚本生成 / 批改它**. 符合 case-data.schema.json (`procedures:[]`) | Agent |
+| `outputs/case-{N}/case-{N}-<slug>.html` | 阶段三 .html 输出 (跑 render-case.py 生成; **唯一产物, .md 已取消**) | render-case.py |
+
+---
+
+## 8. 外部 JSON 词表 (实质 / 形式) 不进 spec/
+
+`分类库导出_*.json` 词表为什么不放 spec/:
+
+- **太大**: 实质 911 条 + 形式 565 条路径, 进 LLM context 占 30k+ tokens
+- **变化频率不同**: spec 演化慢, 词表演化快 (随分类学的迭代)
+- **走 tool 比走 Read 更经济**: 配 `spec/tools/taxonomy-lookup.py` 的 funnel API (`--list-l2 / --subtree / --match`), 一次 query 几百 tokens, 比整树 Read 省 50-100x
+
+Agent 阶段二 2B 完全通过 tool 查, 不要 Read 词表 JSON 本身.
+
+---
+
+## 9. `Agent`(或 `Task`)— 召唤子助手
+
+**做什么**:第二阶段,主流程用它召唤两个轻量子助手并行做归类。好处是把主流程的"重上下文"(一堆配图 + 长篇说明)和"琐碎高频的查词"隔开,还能并发提速。
+
+子助手的工作说明放在 `spec/agents/*.md`,运行器启动时自动加载;召唤时 `subagent_type` 直接填注册名(`phase-2a-normalizer` / `phase-2b-matcher`),只点明做哪个 case 即可,不用重述方法。**别用 `subagent_type="Explore"`**——那是通用助手,会绕过子助手的工作说明。
+
+具体怎么切任务、收结果,见 [phase2-normalize.md](extraction/phase2-normalize.md)(第二阶段编排)。
+

+ 267 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/lint-case.py

@@ -0,0 +1,267 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+lint-case.py — workflow.json 轻量 lint + 自动 record 新 type 到 type_suggestions.md.
+
+设计哲学: **不严格**.
+  - 不分 error/warning 等级, 不卡 exit code (都返 0)
+  - 主要副作用是 record 新 type 到 spec/taxonomy/type_suggestions.md
+  - 检测项打 stdout 给 Agent / 用户看, 决定要不要回去修
+
+用法:
+    python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N}
+    python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N} --no-record   # 只校验不写
+
+退出码:
+    0  始终 (不阻塞流程)
+    2  CLI 参数错误 / 文件不存在
+"""
+from __future__ import annotations
+
+import argparse
+import json
+import re
+import sys
+from pathlib import Path
+
+# spec/tools/lint-case.py → procedure-dsl/
+DSL_ROOT = Path(__file__).resolve().parent.parent.parent
+TYPE_JSON = DSL_ROOT / 'spec' / 'taxonomy' / 'type.json'
+SUGGESTIONS = DSL_ROOT / 'spec' / 'taxonomy' / 'type_suggestions.md'
+
+
+# Windows 控制台 UTF-8
+for _s in (sys.stdout, sys.stderr):
+    if hasattr(_s, 'reconfigure'):
+        try:
+            _s.reconfigure(encoding='utf-8', errors='replace')
+        except Exception:
+            pass
+
+
+def load_type_leaves() -> set[str]:
+    """读 spec/taxonomy/type.json 的 $leaves 集合."""
+    if not TYPE_JSON.exists():
+        return set()
+    return set(json.loads(TYPE_JSON.read_text(encoding='utf-8')).get('$leaves', []))
+
+
+# ===========================================================================
+# Check 1: type 完整性提示
+# ===========================================================================
+
+def _iter_procedures(case_data: dict):
+    """遍历 workflow.json 的 procedures.
+
+    Yields: (procedure_label, procedure_dict) — 含 steps + type_registry.
+    """
+    for p in case_data.get('procedures') or []:
+        label = p.get('id') or p.get('name') or '?'
+        yield (label, p)
+
+
+def check_type_completeness(case_data: dict) -> list[str]:
+    """IO 用了 case-specific type 但 type_registry 漏写 entry → 提示.
+
+    只 hint 不 fail. Agent 看输出回去修.
+    多工序时, hint 前缀加 [proc_id] 让用户知道是哪个工序的问题.
+    """
+    leaves = load_type_leaves()
+    hints: list[str] = []
+
+    for proc_label, proc in _iter_procedures(case_data):
+        type_reg = proc.get('type_registry') or {}
+
+        for i, step in enumerate(proc.get('steps') or []):
+            if not isinstance(step, dict):
+                continue
+            for kind in ('inputs', 'outputs'):
+                for j, item in enumerate(step.get(kind) or []):
+                    if not isinstance(item, dict):
+                        continue
+                    t = item.get('type', '') or ''
+                    if not t:
+                        continue
+                    if t in leaves:
+                        continue   # 字典叶子, OK
+                    if t not in type_reg:
+                        hints.append(
+                            f"[{proc_label}] step[{i}].{kind}[{j}].type={t!r} 是 case-specific "
+                            f"但 type_registry 没注册"
+                        )
+                    else:
+                        entry = type_reg[t]
+                        if isinstance(entry, dict):
+                            if not entry.get('extends'):
+                                hints.append(f"[{proc_label}] type_registry[{t!r}] 缺 extends 字段")
+                            if not entry.get('desc'):
+                                hints.append(f"[{proc_label}] type_registry[{t!r}] 缺 desc 字段 (renderer drawer 显示需要)")
+    return hints
+
+
+# ===========================================================================
+# Check 2: value / directive 自包含性 (禁止引用占位)
+# ===========================================================================
+
+# value/directive 应填数据本身, 不是 anchor 的引用. 命中即「没真正回填」.
+META_REF = re.compile(r'[((]?\s*同\s*s[\d]|见\s*s[\d]|←\s*s[\d]|同上')
+
+
+def check_value_selfcontained(case_data: dict) -> list[str]:
+    """扫每个 IO 的 value + 每个 directive, 找「引用占位」文案 (同 sX / 见 sX / ← sX ...).
+
+    spec: value 逐字回填数据本身, 引用归 anchor (workflow-format.md §2 数据流).
+    这种占位 schema/type 检查抓不到, 专门一条. 只 hint. 可用
+    `wf-patch.py --resolve-passthrough` 自动从源回填.
+    """
+    hints: list[str] = []
+    for proc_label, proc in _iter_procedures(case_data):
+        for i, step in enumerate(proc.get('steps') or []):
+            if not isinstance(step, dict):
+                continue
+            for kind in ('inputs', 'outputs'):
+                for j, item in enumerate(step.get(kind) or []):
+                    if not isinstance(item, dict):
+                        continue
+                    v = item.get('value')
+                    if isinstance(v, str) and META_REF.search(v):
+                        hints.append(f"[{proc_label}] step[{i}].{kind}[{j}].value 是引用占位 {v[:24]!r} — 应逐字回填数据本身")
+            t = step.get('directive')
+            if isinstance(t, str) and META_REF.search(t):
+                hints.append(f"[{proc_label}] step[{i}].directive 是引用占位 {t[:24]!r} — 应填实际 prompt 原文")
+    return hints
+
+
+# ===========================================================================
+# Side effect: record 新 type 到 type_suggestions.md
+# ===========================================================================
+
+def record_new_types(case_data: dict, suggestions_path: Path = SUGGESTIONS) -> list[str]:
+    """把 case_data.type_registry 里的 case-specific type append 到 suggestions.
+
+    幂等: 同一 (type_name, case_id) 二元组只 append 一次. Dedup 靠 grep 现有文件,
+    抽 `(来自 case-{N})` + 类型名 二元组.
+
+    Returns:
+        本次新写入的条目 list (空 list = 没新东西要 record).
+    """
+    # 合并所有 procedures.type_registry
+    type_reg: dict = {}
+    for p in case_data.get('procedures', []):
+        type_reg.update(p.get('type_registry') or {})
+    if not type_reg:
+        return []
+
+    leaves = load_type_leaves()
+    case_id = case_data.get('case_id') or '?'
+    text = suggestions_path.read_text(encoding='utf-8') if suggestions_path.exists() else ''
+
+    # 已 record 过的 (type_name, case_id) — 用 regex 抓 markdown list entry
+    existing = set(re.findall(
+        r'^- `([^`]+)`:.*?\(来自 case-([^,)\s]+)', text, re.M
+    ))
+
+    new_lines: list[str] = []
+    for tname, entry in type_reg.items():
+        if not isinstance(entry, dict):
+            continue
+        if tname in leaves:
+            continue   # 已是字典叶子, 不是新 type (Agent 误把 stdlib type 加进 case_data.type_registry)
+        if (tname, str(case_id)) in existing:
+            continue
+        ext = entry.get('extends', '?')
+        desc = entry.get('desc') or '(无 desc)'
+        new_lines.append(f'- `{tname}`: {desc}  (来自 case-{case_id}, extends `{ext}`)')
+
+    if new_lines:
+        # 确保 suggestions 文件存在 (没有就建个空骨架)
+        if not suggestions_path.exists():
+            suggestions_path.write_text(
+                '# Type 字典扩展建议\n\n## 累积条目\n\n', encoding='utf-8'
+            )
+        # append 末尾
+        with suggestions_path.open('a', encoding='utf-8') as f:
+            f.write('\n' + '\n'.join(new_lines) + '\n')
+
+    return new_lines
+
+
+# ===========================================================================
+# main
+# ===========================================================================
+
+def main() -> None:
+    ap = argparse.ArgumentParser(
+        prog='lint-case.py',
+        description='workflow 轻量 lint + 自动 record 新 type 到 type_suggestions.md',
+    )
+    ap.add_argument('--workflow', type=Path, required=True,
+                    help='workflow.json (含 procedures 数组). lint 内部读 procedures + type_registry')
+    ap.add_argument('--case-id', type=str, default=None,
+                    help='record suggestions 用的 case_id. 不传就 fallback workflow.case_id 或 ?')
+    ap.add_argument('--no-record', action='store_true',
+                    help='只校验, 不写 suggestions')
+    args = ap.parse_args()
+
+    target_path = args.workflow
+    if not target_path.exists():
+        print(f'lint-case: 文件不存在 {target_path}', file=sys.stderr)
+        sys.exit(2)
+
+    try:
+        case_data = json.loads(target_path.read_text(encoding='utf-8'))
+    except json.JSONDecodeError as e:
+        print(f'lint-case: {target_path} 不是合法 JSON: {e}', file=sys.stderr)
+        sys.exit(2)
+
+    # workflow 模式: 注入 case_id (suggestions record 需要)
+    if args.case_id is not None and 'case_id' not in case_data:
+        try:
+            case_data['case_id'] = int(args.case_id)
+        except ValueError:
+            case_data['case_id'] = args.case_id
+
+    case_id = case_data.get('case_id', '?')
+    print(f'[lint] case-{case_id} ({target_path.name})')
+
+    # check: type 完整性提示
+    hints = check_type_completeness(case_data)
+    if hints:
+        print(f'  · type 完整性: {len(hints)} 个提示')
+        for h in hints:
+            print(f'      - {h}')
+    else:
+        print('  · type 完整性: OK')
+
+    # check: value / directive 自包含性 (引用占位)
+    vhints = check_value_selfcontained(case_data)
+    if vhints:
+        print(f'  · value 自包含: {len(vhints)} 个引用占位 (跑 wf-patch.py --resolve-passthrough 自动回填)')
+        for h in vhints:
+            print(f'      - {h}')
+    else:
+        print('  · value 自包含: OK')
+
+    # side effect: record 新 type
+    if not args.no_record:
+        new_lines = record_new_types(case_data)
+        if new_lines:
+            print(f'  · 已 record {len(new_lines)} 条新 type 到 {SUGGESTIONS.name}:')
+            for ln in new_lines:
+                print(f'      {ln}')
+        else:
+            # 合并所有 procedure type_registry
+            merged_reg: dict = {}
+            for p in case_data.get('procedures', []):
+                merged_reg.update(p.get('type_registry') or {})
+            if not merged_reg:
+                print('  · 无新 type 可 record (type_registry 为空 — 全部 type 命中字典叶子)')
+            else:
+                print('  · 无新 type 可 record (type_registry 里的项已全部 record 过)')
+
+    # 不卡 exit code
+    sys.exit(0)
+
+
+if __name__ == '__main__':
+    main()

+ 27 - 60
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/prepare-subtask.py → examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/prepare-subtask.py

@@ -104,76 +104,43 @@ def main():
             sid = s.get("id")
             if not sid:
                 continue
-                
-            # 2A Step Item
+
+            # 2A Step Item — 作用/动作 step 级, 类型仍逐 IO
             step_item_2a = {
                 "path": f"{proc_id}.{sid}",
-                "name": s.get("name", ""),
+                "kind": s.get("kind", "step"),
                 "action": s.get("action", ""),
                 "effect": s.get("effect", ""),
-                "kind": s.get("kind", "step"),
                 "type_registry": type_registry,
                 "inputs": [],
                 "outputs": []
             }
-            
-            # Extract inputs
-            for idx, io in enumerate(s.get("inputs", [])):
-                name = io.get("name", "")
-                val = io.get("value", "")
-                io_type = io.get("type", "")
-                
-                # 2B Variable Item
-                related_imgs = extract_image_refs(val, image_list)
-                # 也从 name 里提取,防漏
-                name_imgs = extract_image_refs(name, image_list)
-                all_imgs = sorted(list(set(related_imgs + name_imgs)))
-                
-                step_item_2a["inputs"].append({
-                    "path": f"{proc_id}.{sid}.inputs[{idx}]",
-                    "name": name,
-                    "value": val,
-                    "type": io_type,
-                    "related_images": all_imgs
-                })
-                
-                task_2b["items_to_match"].append({
-                    "path": f"{proc_id}.{sid}.inputs[{idx}]",
-                    "name": name,
-                    "value": val,
-                    "type": io_type,
-                    "related_images": all_imgs
-                })
-                
-            # Extract outputs
-            for idx, io in enumerate(s.get("outputs", [])):
-                name = io.get("name", "")
-                val = io.get("value", "")
-                io_type = io.get("type", "")
-                
-                # 2B Variable Item
-                related_imgs = extract_image_refs(val, image_list)
-                name_imgs = extract_image_refs(name, image_list)
-                all_imgs = sorted(list(set(related_imgs + name_imgs)))
-                
-                step_item_2a["outputs"].append({
-                    "path": f"{proc_id}.{sid}.outputs[{idx}]",
-                    "name": name,
-                    "value": val,
-                    "type": io_type,
-                    "related_images": all_imgs
-                })
-                
-                task_2b["items_to_match"].append({
-                    "path": f"{proc_id}.{sid}.outputs[{idx}]",
-                    "name": name,
-                    "value": val,
-                    "type": io_type,
-                    "related_images": all_imgs
-                })
-                
+
+            step_texts = []
+            for side in ("inputs", "outputs"):
+                for idx, io in enumerate(s.get(side, [])):
+                    val = io.get("value", "")
+                    io_type = io.get("type", "")
+                    step_texts.append(val)
+                    step_item_2a[side].append({
+                        "path": f"{proc_id}.{sid}.{side}[{idx}]",
+                        "value": val,
+                        "type": io_type,
+                        "related_images": extract_image_refs(val, image_list),
+                    })
+
             task_2a["steps"].append(step_item_2a)
 
+            # 2B: 实质/形式 现在是 step 级 — 整步内容合并成一个待匹配项 (产出 pN.sM.substance / .form)
+            content = "  ".join(v for v in step_texts if v)
+            task_2b["items_to_match"].append({
+                "path": f"{proc_id}.{sid}",
+                "kind": s.get("kind", "step"),
+                "intent": s.get("intent", ""),
+                "content": content,
+                "related_images": extract_image_refs(content, image_list),
+            })
+
     # 落盘 task_2a.json 与 task_2b.json
     file_2a = args.out_dir / "task_2a.json"
     file_2b = args.out_dir / "task_2b.json"

+ 269 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/render-case.py

@@ -0,0 +1,269 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+render-case.py — Procedure DSL · 阶段三 3.3 落盘&渲染脚本.
+
+把 case_data (符合 spec/format/case-data.schema.json) 通过 spec/tools/renderer.build_html
+渲染成单文件 HTML.
+
+用法:
+
+  渲染:
+       render-case.py --workflow outputs/case-N/workflow.json \
+                      --source-input input/case-N-raw.json \
+                      --page-title "Case N · 主题" --case-id N \
+                      --out outputs/case-N/case-N-<slug>.html
+
+  只校验, 不渲染:
+       render-case.py --workflow outputs/case-N/workflow.json --source-input input/case-N-raw.json --validate
+
+退出码:
+  0  成功 (渲染或校验通过)
+  1  IO / schema / 渲染异常
+  2  CLI 参数错误
+
+依赖:
+  必需: spec/tools/renderer.py (跟本脚本同目录, 自动加入 sys.path)
+  可选: jsonschema (装了就用 Draft 2020-12 校验; 没装则只做最小结构检查)
+"""
+from __future__ import annotations
+
+import argparse
+import json
+import sys
+from pathlib import Path
+
+# Windows cp1252 console 不能直接打中文/勾选号; 把 stdout/stderr 强转 UTF-8.
+for _stream in (sys.stdout, sys.stderr):
+    if hasattr(_stream, 'reconfigure'):
+        try:
+            _stream.reconfigure(encoding='utf-8', errors='replace')
+        except Exception:
+            pass
+
+# DSL_ROOT = procedure-dsl/  (本脚本位于 procedure-dsl/spec/tools/)
+DSL_ROOT = Path(__file__).resolve().parent.parent.parent
+SCHEMA_PATH = DSL_ROOT / 'spec' / 'format' / 'case-data.schema.json'
+# renderer.py 跟本脚本同目录 (spec/tools/), 直接用 parent 最 robust.
+TEMPLATE_DIR = Path(__file__).resolve().parent
+
+
+def _import_build_html():
+    """延迟 import build_html, 把 examples/_build 接到 sys.path. 失败时给出明确错误."""
+    sys.path.insert(0, str(TEMPLATE_DIR))
+    try:
+        from renderer import build_html  # type: ignore
+    except ImportError as e:
+        die(f'无法导入 renderer.build_html (期望路径: {TEMPLATE_DIR}/renderer.py): {e}')
+    return build_html
+
+
+def die(msg: str, code: int = 1):
+    print(f'render-case: {msg}', file=sys.stderr)
+    sys.exit(code)
+
+
+def load_json(path: Path) -> dict:
+    if not path.exists():
+        die(f'文件不存在: {path}')
+    try:
+        return json.loads(path.read_text(encoding='utf-8'))
+    except json.JSONDecodeError as e:
+        die(f'{path} 不是合法 JSON: {e}')
+
+
+def die_short(msg: str):
+    die(msg)
+
+
+def merge_raw_source(case_data: dict, raw_path: Path) -> None:
+    """从 input/case-{N}-raw.json 抽 body_text + 封面 + 图集兜底, in-place 填到 case_data.source.
+
+    设计: raw 是事实源 (原帖正文 / 封面 / 标题 / URL), case_data.source.body_text 和 cover_image
+    被 raw 覆盖. 其他字段 (excerpt / author / date / platform) **保留 case_data 原值** ——
+    那些是 Agent 推断/总结的友好版本, 不应被 raw 覆盖.
+
+    图集兜底逻辑: 微信公众号正文里有 `[image:URL]` inline markup → renderer 自动渲染就好.
+    小红书等"短文 + 独立图集" 平台 body_text 不含 inline markup → 把 image_url_list 里
+    既没 inline 也不是封面的图, 以 `[image: URL]` 形式 append 到 body_text 末尾 (附 "附图" 分隔符).
+    这样 renderer.render_source_body 一视同仁地把它们也渲染成 <img>, 不重复封面.
+    """
+    import re
+
+    raw = load_json(raw_path)
+    src = case_data.setdefault('source', {})
+
+    body = raw.get('body_text', '') or ''
+
+    # cover_image: image_url_list 里 image_type=2 (封面) 的第一张; 没有就 fallback 整列第一张
+    images = raw.get('image_url_list') or []
+    covers = [it for it in images if isinstance(it, dict) and it.get('image_type') == 2]
+    pick = covers[0] if covers else (images[0] if images and isinstance(images[0], dict) else None)
+    cover_url = ''
+    if pick and pick.get('image_url'):
+        cover_url = pick['image_url']
+        src['cover_image'] = cover_url
+
+    # 图集兜底: 检查哪些图既没在 body inline, 也不是封面 → append 到 body 末尾
+    inlined_urls = set(re.findall(r'\[image:\s*(\S+?)\]', body))
+    missing = []
+    for it in images:
+        if not isinstance(it, dict):
+            continue
+        u = it.get('image_url', '') or ''
+        if not u:
+            continue
+        if u in inlined_urls:
+            continue   # 已 inline 不重复
+        if u == cover_url:
+            continue   # 封面已 src-cover 单独渲染
+        missing.append(u)
+
+    if missing:
+        suffix = '\n\n--- 附图 ---\n' + '\n'.join(f'[image: {u}]' for u in missing)
+        body = body + suffix
+
+    if body:
+        src['body_text'] = body
+
+    # title / url 兜底: case_data 漏填时从 raw 补 (Agent 一般会填)
+    if not src.get('title') and raw.get('title'):
+        src['title'] = raw['title']
+    if not src.get('url') and raw.get('content_link'):
+        src['url'] = raw['content_link']
+
+
+# =============================================================================
+# 校验
+# =============================================================================
+def validate(case_data: dict, strict: bool = True) -> list[str]:
+    """返回错误信息列表 (空 list = 通过).
+
+    优先使用 jsonschema (Draft 2020-12); 不可用时退化到最小结构检查 (必填 key 存在 + 类型对).
+    strict=True 时, 任何错误抛 SystemExit(1); strict=False 仅返回错误列表.
+    """
+    errors: list[str] = []
+
+    try:
+        from jsonschema import Draft202012Validator  # type: ignore
+        schema = load_json(SCHEMA_PATH)
+        validator = Draft202012Validator(schema)
+        for err in sorted(validator.iter_errors(case_data), key=lambda e: list(e.absolute_path)):
+            path = '$' + ''.join(f'.{p}' if isinstance(p, str) else f'[{p}]' for p in err.absolute_path)
+            errors.append(f'{path}: {err.message}')
+    except ImportError:
+        # 退化: 最小检查
+        errors.extend(_minimal_check(case_data))
+
+    if errors and strict:
+        for e in errors:
+            print(f'  ✗ {e}', file=sys.stderr)
+        print(f'  ↳ schema: {SCHEMA_PATH}  (要看字段约束直接 Read 这个文件, 不要猜路径)', file=sys.stderr)
+        die(f'schema 校验失败, 共 {len(errors)} 项 (装 `pip install jsonschema` 可看完整 Draft 2020-12 报告)')
+    return errors
+
+
+def _minimal_check(d: dict) -> list[str]:
+    """无 jsonschema 时的兜底: 仅检 顶层必填 + steps 元素必填 + IO 元素必填."""
+    errs: list[str] = []
+    top_required = ['page_title', 'procedure', 'declarations', 'source', 'steps']
+    for k in top_required:
+        if k not in d:
+            errs.append(f'$.{k}: 缺失必填字段')
+    if not isinstance(d.get('steps'), list):
+        errs.append('$.steps: 必须是 array')
+        return errs
+    # 所有 step 都要的基础字段; effect/action 仅非 block 步要 (block 是控制容器)
+    step_required = ['id', 'kind', 'via', 'inputs', 'outputs', 'intent']
+    exec_only = ['effect', 'action']               # kind != block 才要
+    io_required = ['type', 'value', 'anchor']
+    for i, step in enumerate(d['steps']):
+        if not isinstance(step, dict):
+            errs.append(f'$.steps[{i}]: 必须是 object'); continue
+        need = step_required + ([] if step.get('kind') == 'block' else exec_only)
+        for k in need:
+            if k not in step:
+                errs.append(f'$.steps[{i}].{k}: 缺失必填字段')
+        for io_kind in ('inputs', 'outputs'):
+            for j, item in enumerate(step.get(io_kind, []) or []):
+                if not isinstance(item, dict):
+                    errs.append(f'$.steps[{i}].{io_kind}[{j}]: 必须是 object'); continue
+                for k in io_required:
+                    if k not in item:
+                        errs.append(f'$.steps[{i}].{io_kind}[{j}].{k}: 缺失必填字段')
+    return errs
+
+
+# =============================================================================
+# main
+# =============================================================================
+def main() -> None:
+    ap = argparse.ArgumentParser(
+        prog='render-case.py',
+        description='Procedure DSL · case_data → HTML 渲染',
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        epilog=__doc__.split('用法:')[1] if __doc__ else '',
+    )
+    ap.add_argument('--workflow', type=Path, required=True,
+                    help='workflow.json (含 procedures 数组). 内部组装 case_data = '
+                         'workflow + source-input merge + --page-title + --case-id, 不落盘 case_data.json. '
+                         '配合 --source-input / --page-title / --case-id 一起用.')
+    ap.add_argument('--page-title', type=str, default=None,
+                    help='页面标题, 仅与 --workflow 配对. e.g. "Case 5 · 产品宣传图 AI 工作流可视化"')
+    ap.add_argument('--case-id', type=str, default=None,
+                    help='case 编号, 仅与 --workflow 配对')
+    ap.add_argument('--source-input', type=Path, dest='source_input',
+                    help='可选: 原帖 raw json 路径 (e.g. input/case-N-raw.json). 给了的话, 自动把 '
+                         'raw.body_text + 封面图 / 标题 / URL 填到 case_data.source 对应字段 '
+                         '(body_text/cover_image 直接覆盖 case_data 同字段, title/url 仅在 case_data 缺时填), '
+                         '让 HTML 折叠原文区显示完整原帖正文 + 内嵌图. excerpt/author/date 等 Agent 推断字段不动.')
+    ap.add_argument('--out', type=Path,
+                    help='输出 HTML 路径. --validate 时可省略')
+    ap.add_argument('--validate', action='store_true',
+                    help='只做 schema 校验, 不渲染. 退出码 0=通过, 1=失败')
+    ap.add_argument('--no-validate', action='store_true',
+                    help='跳过校验直接渲染 (不推荐)')
+    args = ap.parse_args()
+
+    # workflow.json 装 procedures 主体 + cli 套 case-level meta
+    case_data = load_json(args.workflow)
+    if args.page_title:
+        case_data['page_title'] = args.page_title
+    if args.case_id is not None:
+        try:
+            case_data['case_id'] = int(args.case_id)
+        except ValueError:
+            case_data['case_id'] = args.case_id
+    # source 由 --source-input 提供 (workflow.json 不含 source); 没给就让 schema validate 报错
+
+    # raw 原帖 → case_data.source merge (在 validate 前, 让 schema 校验看到的就是完整版)
+    if args.source_input:
+        merge_raw_source(case_data, args.source_input)
+
+    def _count_steps(cd):
+        return sum(len(p.get('steps') or []) for p in cd.get('procedures', []))
+
+    if not args.no_validate:
+        validate(case_data, strict=not args.validate)
+        if args.validate:
+            n_procs = len(case_data.get('procedures', []))
+            print(f'render-case: ✓ {SCHEMA_PATH.name} 校验通过 '
+                  f'({n_procs} procedure{"s" if n_procs > 1 else ""}, {_count_steps(case_data)} steps)')
+            if not args.out:
+                return
+
+    if not args.out:
+        ap.error('--out 必填 (除非用 --validate 只校验)')
+
+    build_html = _import_build_html()
+    html = build_html(case_data)
+    args.out.parent.mkdir(parents=True, exist_ok=True)
+    # newline='' 保留 build_html 返回串里的换行原貌, 防 Windows 把 \n 翻译成 \r\n
+    args.out.write_text(html, encoding='utf-8', newline='')
+    n_procs = len(case_data.get('procedures', []))
+    print(f'render-case: ✓ wrote {args.out} ({len(html):,} chars, '
+          f'{n_procs} procedure{"s" if n_procs > 1 else ""}, {_count_steps(case_data)} steps)')
+
+
+if __name__ == '__main__':
+    main()

+ 661 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/renderer.py

@@ -0,0 +1,661 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+renderer.py — Procedure DSL 可视化共享模板.
+
+每个 case 提供 case_data (一个 dict, 见 build_html 的 docstring),
+import 本模块并调用 build_html(case_data) → HTML 字符串.
+
+spec 引用: spec.md §12 (.html 可视化结构规范).
+"""
+import html
+import json
+import re
+from pathlib import Path
+
+
+# ── 数据 loaders (从 spec/taxonomy 单一来源加载) ────────────────────
+def _load_json(rel_path: str) -> dict:
+    """从 spec/ 子路径加载 JSON. rel_path 是相对 spec/ 的路径 (e.g. 'taxonomy/type.json')."""
+    return json.loads((Path(__file__).resolve().parent.parent / rel_path).read_text(encoding='utf-8'))
+
+
+def _load_stdlib_types() -> dict:
+    """type stdlib 渲染元信息. 新结构 type.json 无 type_metadata → 返回 {};
+    stdlib 叶子的 in_tree 标记在 build_html 里按 type.json 的 $leaves 补齐."""
+    return {}
+
+
+_DRAWER_TITLES = {
+    'effect': ('作用 (chip 上 data-prefix="作用")',
+               '这一步在 AIGC 生产工序链中的位置 + 作用; 从 §A.1 字典树取 L3 叶子'),
+    'action': ('动作 (chip 上 data-prefix="动作")',
+               '这一步的动作动词; 从 §A.2 字典树取路径'),
+    'type':   ('类型 (chip 上 data-type)',
+               '领域语义类型 (按功能角色分类: 程序控制/数据复用/内容/知识); 从 §A.3 字典树取叶子'),
+}
+
+
+def _add_label_suffix(node, depth=0):
+    """递归把 dict 的 key 加 (L1)/(L2) 显示后缀, 让 drawer UI 区分层级.
+    leaf string 保留原状; $* 元数据 key 跳过."""
+    if not isinstance(node, dict):
+        return node
+    result = {}
+    for k, v in node.items():
+        if k.startswith('$'):
+            continue
+        new_k = k
+        if isinstance(v, dict):
+            if depth == 0:
+                new_k = f'{k} (L1)'
+            elif depth == 1:
+                new_k = f'{k} (L2)'
+        result[new_k] = _add_label_suffix(v, depth + 1)
+    return result
+
+
+def _tree_to_drawer(nodes):
+    """新结构 最终分类树 (list of {分类名称, 分类说明, 子分类}) → drawer 嵌套 dict.
+    叶子 → {名称: 分类说明 字符串}; 非叶 → {名称: 子树 dict}. 层级即 根→叶 路径."""
+    out = {}
+    for n in nodes or []:
+        name = n.get('分类名称', '?')
+        kids = n.get('子分类') or []
+        out[name] = _tree_to_drawer(kids) if kids else (n.get('分类说明', '') or '')
+    return out
+
+
+def _load_drawer_tree(dim: str) -> dict:
+    """spec/taxonomy/{dim}.json → 重塑为 drawer UI 需要的 {title, desc, tree} 格式.
+    新结构读 最终分类树 (中文键); 自动加 (L1)/(L2) 层级标签. dim ∈ {'effect', 'action', 'type'}."""
+    raw = _load_json(f'taxonomy/{dim}.json')
+    title, desc = _DRAWER_TITLES[dim]
+    nested = _tree_to_drawer(raw.get('最终分类树', []))
+    return {
+        'title': title,
+        'desc': desc,
+        'tree': _add_label_suffix(nested, depth=0),
+    }
+
+
+# =============================================================================
+# STDLIB · type registry (字典树 §A.3 叶子的 in_tree 标记基础; 现为空, build_html 按 $leaves 补齐)
+# =============================================================================
+STDLIB_TYPE_REGISTRY = _load_stdlib_types()
+
+
+# =============================================================================
+# 字典树 (spec §A.1 作用 / §A.2 动作 / §A.3 类型)
+# =============================================================================
+EFFECT_TREE = _load_drawer_tree("effect")
+
+ACTION_TREE = _load_drawer_tree("action")
+
+TYPE_TREE = _load_drawer_tree("type")
+
+
+def _build_type_paths() -> dict:
+    """type.json 最终分类树 → {叶子名: '根/.../叶子' 路径}, 供 chip 显示完整路径."""
+    raw = _load_json('taxonomy/type.json')
+    out: dict = {}
+    def walk(nodes, prefix):
+        for n in nodes:
+            path = prefix + [n.get('分类名称', '')]
+            kids = n.get('子分类') or []
+            if kids:
+                walk(kids, path)
+            else:
+                out[n.get('分类名称', '')] = '/'.join(path)
+    walk(raw.get('最终分类树', []), [])
+    return out
+
+
+TYPE_PATHS = _build_type_paths()
+
+FEATURE_TAXONOMY = _load_json("taxonomy/feature.json")
+
+EXTERNAL_TAXONOMIES = {
+    '实质': {'title': '实质 (内容是什么)',  'desc': '理念 / 表象 — 911 路径',
+            'source': 'external', 'file': '分类库导出_实质_*.json'},
+    '形式': {'title': '形式 (内容怎么呈现)', 'desc': '呈现 / 架构 — 565 路径',
+            'source': 'external', 'file': '分类库导出_形式_*.json'},
+}
+
+
+# =============================================================================
+# Render helpers
+# =============================================================================
+def he(s):
+    """HTML escape, 默认 quote=True 把 `"` 转成 `&quot;`.
+    这点关键: title / data-* / class 等属性值如果含 `"` 会提前终止属性,
+    导致 tooltip 显示不完整 (典型 bug: '原文方法 3 只说"自己写动作"' 在 title 中只显示到 "只说" 就被截断).
+    """
+    if s is None:
+        return ''
+    return html.escape(str(s))
+
+
+def render_intent(text):
+    """目的列: 简短自然语言句, **尽量** 把其他列里的结构化值都做成 {kind:value} token.
+
+    每个 token 底色对应其引用的列, 让人一眼看出该值来自哪里. 合法 kind:
+      effect          → 作用列 (灰, 需求组)
+      via             → 外部工具列 (浅绿 + 等宽字体, 实现组)
+      act             → 动作列 (绿, 实现组)
+      control         → 逻辑控制列 (浅青, 实现组) — 并行/遍历/分支/请求/等待
+      in-type         → 输入·类型 (黄圆胶囊)         out-type → 输出·类型 (蓝圆胶囊)
+      in-sub          → 输入·实质 (黄矩形 tag)        out-sub  → 输出·实质 (蓝矩形 tag)
+      in-form         → 输入·形式 (黄矩形 tag 斜体)   out-form → 输出·形式 (蓝矩形 tag 斜体)
+
+    **特性列 (feature) 不允许在 intent 中引用** — feature 是内部执行特征 (随机/幂等/人工/读写外部),
+    不出现在面向使用者的描述. 写成 `ik-other` 灰色显示作为 lint 警告.
+
+    严禁变量名 token (no `{in:X}` / `{out:X}`); 严禁 dataflow 公式 / case-specific 简写.
+    """
+    def sub(m):
+        kind = m.group(1)
+        val = m.group(2)
+        kc = {
+            'effect': 'ik-effect',
+            'via': 'ik-via',
+            'act': 'ik-act',
+            'in-type': 'ik-in-type', 'out-type': 'ik-out-type',
+        }.get(kind, 'ik-other')
+        return f'<span class="intent-tok {kc}">{he(val)}</span>'
+    return re.sub(r'\{([\w-]+):([^}]+)\}', sub, text or '')
+
+
+def render_chip(type_name):
+    if not type_name:
+        return ''
+    if type_name == '-':
+        return he(type_name)
+    # 显示完整路径 (e.g. 程序控制类型/指令/提示词); data-type 仍存叶子名, drawer 查找不受影响.
+    # case-specific 类型 (不在字典树) 显示原名.
+    disp = TYPE_PATHS.get(type_name, type_name)
+    return f'<span class="chip" data-type="{he(type_name)}">{he(disp)}</span>'
+
+
+def render_path(prefix, value):
+    if not value:
+        return ''
+    if isinstance(value, list):
+        spans = []
+        for val in value:
+            if val:
+                spans.append(f'<span data-prefix="{prefix}" data-value="{he(val)}">{he(val)}</span>')
+        return '\n'.join(spans)
+    if isinstance(value, str):
+        if '+' in value:
+            parts = [p.strip() for p in value.split('+') if p.strip()]
+            spans = []
+            for val in parts:
+                spans.append(f'<span data-prefix="{prefix}" data-value="{he(val)}">{he(val)}</span>')
+            return '\n'.join(spans)
+        return f'<span data-prefix="{prefix}" data-value="{he(value)}">{he(value)}</span>'
+    return ''
+
+
+_VALUE_DESC_RE = re.compile(r'^<(.+)>$', re.DOTALL)
+
+
+def render_value(vl):
+    """值列渲染:
+      - 若整段以 `<...>` 括起 → 渲染为斜体浅灰背景, 表示"这是对内容的描述, 不是内容本身"
+        (适用于无法在 cell 中直接嵌入的非文本数据: 视频/图像/音频).
+      - 否则 → 渲染为普通文本 (适用于文本数据本身, 如 prompt 全文).
+    """
+    if vl is None:
+        return ''
+    s = str(vl).strip()
+    m = _VALUE_DESC_RE.match(s)
+    if m:
+        inner = m.group(1)
+        return f'<span class="value-desc">&lt;{he(inner)}&gt;</span>'
+    return f'<span class="natural">{he(s)}</span>'
+
+
+def render_focus_class(cell_key, focus_list):
+    return ' row-focus' if cell_key in (focus_list or []) else ''
+
+
+def cell_attrs(field_key, focus, io_reason=None, is_empty=False):
+    """组合 cell 的额外 class 和属性 (focus + 推断补全).
+
+    field_key 例: 'action', 'in-value-0', 'out-type-1', etc.
+    io_reason: 当前 cell 所属 IO item 整体被标 inferred 时, 传入 reason 字符串.
+    is_empty: 该 cell 内容是否为空 (留空的推断 cell 角标变 推?).
+    返回 (class_suffix_str, extra_attrs_str).
+    """
+    cls = render_focus_class(field_key, focus)
+    extra = ''
+    if io_reason:
+        cls += ' is-inferred'
+        if is_empty:
+            cls += ' is-low-confidence'
+        extra = f' title="推断补全: {he(io_reason)}"'
+    return cls, extra
+
+
+def render_io_value(item):
+    """IO 值列: output 的 id 作为小标签贴在值前 (供 anchor 1:1 引用对照); input 无 id."""
+    iid = item.get('id')
+    id_tag = f'<span class="io-id" data-io-id="{he(iid)}">{he(iid)}</span> ' if iid else ''
+    return id_tag + render_value(item.get('value'))
+
+
+def render_step_row(step, idx_label, type_reg=None):
+    """渲染一个 step (kind: step / block / nested) 为一组 tr 行 (14 列).
+
+    需求组 (rowspan): # / 目的 / 作用 / 实质 / 形式 (后两者 step 级).
+    输入/输出 (逐 IO): 类型 / 值 / 来源(去处). 实现组 (rowspan): 外部工具 / 动作 / 指令.
+    type_reg: 已合并 STDLIB + case-specific 的类型注册表 (用于 chip in_tree 标记).
+    """
+    inputs = step.get('inputs', [])
+    outputs = step.get('outputs', [])
+    N = max(len(inputs), len(outputs), 1)
+    focus = step.get('focus', [])
+
+    is_nested = step['kind'] == 'nested'
+    is_block = step['kind'] == 'block'
+
+    main_cls = 'step step-main'
+    if is_block:
+        main_cls = 'step block-header'
+    if is_nested:
+        main_cls = 'step step-main step-nested'
+    sub_cls = 'step step-sub'
+
+    data_step = step['id']
+    data_group = step.get('group', '')
+
+    rows = []
+    for k in range(N):
+        tr_cls = main_cls if k == 0 else sub_cls
+        attrs = f' data-step="{data_step}"'
+        if data_group:
+            attrs += f' data-group="{data_group}"'
+        attrs += f' data-focus="{",".join(focus)}"'
+        if k == 0:
+            attrs = f' id="{data_step}"' + attrs
+
+        cells = []
+        if k == 0:
+            rs = f' rowspan="{N}"' if N > 1 else ''
+            arrow = '<span class="arrow">▼</span> ' if is_block else ''
+            indent = '  └ ' if is_nested else ''
+            cells.append(f'<td class="idx{render_focus_class("idx", focus)}"{rs}>{arrow}{indent}{he(idx_label)}</td>')
+            intent_html = render_intent(step.get('intent', ''))
+            c, a = cell_attrs('intent', focus)
+            cells.append(f'<td class="intent{c}"{a}{rs}><div class="intent-text">{intent_html}</div></td>')
+            c, a = cell_attrs('effect', focus)
+            cells.append(f'<td class="effect{c}"{a}{rs}>{render_path("作用", step.get("effect", ""))}</td>')
+            c, a = cell_attrs('substance', focus)
+            cells.append(f'<td class="substance{c}"{a}{rs}>{render_path("实质", step.get("substance")) if step.get("substance") else ""}</td>')
+            c, a = cell_attrs('form', focus)
+            cells.append(f'<td class="form{c}"{a}{rs}>{render_path("形式", step.get("form")) if step.get("form") else ""}</td>')
+
+        in_item = inputs[k] if k < len(inputs) else None
+        if in_item:
+            tp = in_item.get('type'); vl = in_item.get('value'); ac = in_item.get('anchor')
+            io_inf = in_item.get('inferred_reason') if in_item.get('inferred') else None
+            c, a = cell_attrs(f'in-type-{k}', focus, io_inf, is_empty=not tp)
+            cells.append(f'<td class="in-type{c}"{a}>{render_chip(tp)}</td>')
+            c, a = cell_attrs(f'in-value-{k}', focus, io_inf, is_empty=not vl)
+            cells.append(f'<td class="in-value{c}"{a}>{render_io_value(in_item)}</td>')
+            c, a = cell_attrs(f'in-anchor-{k}', focus, io_inf, is_empty=not ac)
+            cells.append(f'<td class="in-anchor{c}"{a}><span class="flow">{he(ac)}</span></td>')
+        else:
+            cells += ['<td class="in-type"></td>', '<td class="in-value"></td>', '<td class="in-anchor"></td>']
+
+        if k == 0:
+            rs = f' rowspan="{N}"' if N > 1 else ''
+            c, a = cell_attrs('via', focus)
+            cells.append(f'<td class="via{c}"{a}{rs}>{he(step.get("via", ""))}</td>')
+            c, a = cell_attrs('action', focus)
+            cells.append(f'<td class="action{c}"{a}{rs}>{render_path("动作", step.get("action", ""))}</td>')
+            c, a = cell_attrs('directive', focus)
+            directive = step.get('directive', '') or ''
+            inner = f'<span class="natural">{he(directive)}</span>' if directive else ''
+            cells.append(f'<td class="directive{c}"{a}{rs}>{inner}</td>')
+
+        out_item = outputs[k] if k < len(outputs) else None
+        if out_item:
+            tp = out_item.get('type'); vl = out_item.get('value'); ac = out_item.get('anchor')
+            io_inf = out_item.get('inferred_reason') if out_item.get('inferred') else None
+            c, a = cell_attrs(f'out-type-{k}', focus, io_inf, is_empty=not tp)
+            cells.append(f'<td class="out-type{c}"{a}>{render_chip(tp)}</td>')
+            c, a = cell_attrs(f'out-value-{k}', focus, io_inf, is_empty=not vl)
+            cells.append(f'<td class="out-value{c}"{a}>{render_io_value(out_item)}</td>')
+            c, a = cell_attrs(f'out-anchor-{k}', focus, io_inf, is_empty=not ac)
+            cells.append(f'<td class="out-anchor{c}"{a}><span class="flow">{he(ac)}</span></td>')
+        else:
+            cells += ['<td class="out-type"></td>', '<td class="out-value"></td>', '<td class="out-anchor"></td>']
+
+        rows.append(f'<tr class="{tr_cls}"{attrs}>{"".join(cells)}</tr>')
+    return '\n      '.join(rows)
+
+
+def render_declarations(case_data, procedure=None):
+    """工序头部 + declare 块 (输入/资源/返回), 可折叠.
+
+    procedure: 该工序的 dict (新 schema 下 case_data.procedures[i]). 不传时退化到
+    老 case_data.procedure (兼容老 case 直到全部迁移完).
+    """
+    proc = procedure if procedure is not None else case_data.get('procedure', {})
+    decls = proc.get('declarations') if procedure is not None else case_data.get('declarations', {})
+    decls = decls or {}
+    parts = []
+    parts.append('<details class="declarations" open>')
+    parts.append('<summary class="decl-summary">')
+    parts.append(f'  <span class="kw">工序</span> <b class="proc-name">{he(proc.get("name", ""))}</b>')
+    if proc.get('purpose'):
+        parts.append(f'  <span class="decl-purpose">#目的: {he(proc["purpose"])}</span>')
+    if proc.get('category'):
+        parts.append(f'  <span class="tag-mini">类别: {he(proc["category"])}</span>')
+    meta_bits = []
+    for label, key in [('平台', 'platform'), ('作者', 'author')]:
+        if proc.get(key):
+            meta_bits.append(f'#{label}: {he(proc[key])}')
+    if case_data.get('case_id') is not None:
+        meta_bits.append(f'case: {he(case_data["case_id"])}')
+    if meta_bits:
+        parts.append(f'  <span class="decl-meta">{" · ".join(meta_bits)}</span>')
+    parts.append('</summary>')
+    parts.append('<div class="decl-body">')
+
+    def section(label, items, renderer):
+        out = [f'<div class="decl-section"><div class="decl-label">{label}</div>']
+        for it in items:
+            out.append(renderer(it))
+        out.append('</div>')
+        return '\n'.join(out)
+
+    def render_io(it):
+        chip = render_chip(it.get('type', ''))
+        name = he(it.get('name', ''))
+        default = it.get('default')
+        line = f'<div class="decl-row">{chip} <span class="name" data-var="{name}">{name}</span>'
+        if default:
+            line += f'  <span class="decl-default">= {he(default)}</span>'
+        if it.get('desc'):
+            line += f'  <span class="decl-desc">— {he(it["desc"])}</span>'
+        return line + '</div>'
+
+    if decls.get('inputs'):
+        parts.append(section('输入', decls['inputs'], render_io))
+    if decls.get('resources'):
+        parts.append(section('资源 (跨 case 长期资产)', decls['resources'], render_io))
+    if decls.get('returns'):
+        ret = decls['returns']
+        chip = render_chip(ret.get('type', ''))
+        line = f'<div class="decl-row">{chip}'
+        if ret.get('note'):
+            line += f'  <span class="decl-desc">— {he(ret["note"])}</span>'
+        line += '</div>'
+        parts.append(f'<div class="decl-section"><div class="decl-label">返回</div>{line}</div>')
+
+    parts.append('</div>')
+    parts.append('</details>')
+    return '\n'.join(parts)
+
+
+_INLINE_MEDIA_RE = re.compile(r'\[(image|video):\s*(https?://[^\s\]]+)\]')
+
+
+def render_source_body(body_text):
+    """把 body_text 渲染为 HTML: [image:URL] → <img>, [video:URL] → <a>, 其他按 \\n 分段."""
+    if not body_text:
+        return ''
+    pieces = []
+    last = 0
+    for m in _INLINE_MEDIA_RE.finditer(body_text):
+        seg = body_text[last:m.start()]
+        if seg.strip():
+            for para in seg.split('\n'):
+                p = para.strip()
+                if p:
+                    pieces.append(f'<p class="src-p">{he(p)}</p>')
+        kind, url = m.group(1), m.group(2)
+        if kind == 'image':
+            pieces.append(f'<div class="src-img-wrap"><img class="src-img" src="{he(url)}" loading="lazy" referrerpolicy="no-referrer" alt=""></div>')
+        else:
+            pieces.append(f'<div class="src-video"><a href="{he(url)}" target="_blank" rel="noopener">▶ 视频</a></div>')
+        last = m.end()
+    tail = body_text[last:]
+    if tail.strip():
+        for para in tail.split('\n'):
+            p = para.strip()
+            if p:
+                pieces.append(f'<p class="src-p">{he(p)}</p>')
+    return '\n'.join(pieces)
+
+
+def render_source(case_data):
+    """原文 折叠块: 元信息 + body_text 完整正文 (含内嵌图片/视频)."""
+    src = case_data.get('source')
+    if not src:
+        return ''
+    url = src.get('url', '')
+    title = src.get('title', '')
+    excerpt = src.get('excerpt', '')
+    body_text = src.get('body_text', '')
+    cover = src.get('cover_image', '')
+    meta_bits = [b for b in [src.get('platform'), src.get('author'), src.get('date')] if b]
+    parts = ['<details class="source-block">']
+    parts.append(f'<summary>原文: <b>{he(title or "(无标题)")}</b></summary>')
+    parts.append('<div class="source-body">')
+    if url:
+        parts.append(f'<div class="source-url"><a href="{he(url)}" target="_blank" rel="noopener">{he(url)}</a></div>')
+    if meta_bits:
+        parts.append(f'<div class="source-meta">{" · ".join(he(b) for b in meta_bits)}</div>')
+    if excerpt:
+        parts.append(f'<p class="source-excerpt"><b>摘要</b>: {he(excerpt)}</p>')
+    if cover:
+        parts.append(f'<div class="src-cover"><img class="src-img" src="{he(cover)}" loading="lazy" referrerpolicy="no-referrer" alt=""></div>')
+    if body_text:
+        parts.append('<hr class="src-divider">')
+        parts.append('<div class="source-full">')
+        parts.append(render_source_body(body_text))
+        parts.append('</div>')
+    parts.append('</div></details>')
+    return '\n'.join(parts)
+
+
+def render_thead():
+    return '''<thead>
+  <tr>
+    <th colspan="5" class="col-group-demand">需求</th>
+    <th colspan="3" class="col-group-input">输入</th>
+    <th colspan="3" class="col-group-impl">实现</th>
+    <th colspan="3" class="col-group-output">输出</th>
+  </tr>
+  <tr>
+    <th class="col-idx">#</th>
+    <th class="col-intent">目的</th>
+    <th class="col-effect">作用</th>
+    <th class="col-substance">实质</th>
+    <th class="col-form">形式</th>
+    <th class="col-in-type">类型</th>
+    <th class="col-in-value">值</th>
+    <th class="col-in-anchor">来源</th>
+    <th class="col-via">外部工具</th>
+    <th class="col-action">动作</th>
+    <th class="col-directive">指令</th>
+    <th class="col-out-type">类型</th>
+    <th class="col-out-value">值</th>
+    <th class="col-out-anchor">去处</th>
+  </tr>
+</thead>'''
+
+
+def render_legend():
+    return '''<div class="legend">
+    <div class="group gray">
+      <span class="gh">需求</span>
+      <span class="col-toggle" data-col="idx">#</span>
+      <span class="col-toggle" data-col="intent">目的</span>
+      <span class="col-toggle" data-col="effect">作用</span>
+      <span class="col-toggle" data-col="substance">实质</span>
+      <span class="col-toggle" data-col="form">形式</span>
+    </div>
+    <div class="group yellow">
+      <span class="gh">输入</span>
+      <span class="col-toggle" data-col="in-type">类型</span>
+      <span class="col-toggle" data-col="in-value">值</span>
+      <span class="col-toggle" data-col="in-anchor">来源</span>
+    </div>
+    <div class="group green">
+      <span class="gh">实现</span>
+      <span class="col-toggle" data-col="via">外部工具</span>
+      <span class="col-toggle" data-col="action">动作</span>
+      <span class="col-toggle" data-col="directive">指令</span>
+    </div>
+    <div class="group blue">
+      <span class="gh">输出</span>
+      <span class="col-toggle" data-col="out-type">类型</span>
+      <span class="col-toggle" data-col="out-value">值</span>
+      <span class="col-toggle" data-col="out-anchor">去处</span>
+    </div>
+    <span class="inferred-toggle" id="inferred-toggle" title="高亮所有标为推断补全的 cell">高亮推断</span>
+    <span class="legend-hint">点击列名 ↔ 显示/隐藏 · 点击组名 ↔ 整组切换 · 「推」角标 hover 看推断理由</span>
+  </div>'''
+
+
+# =============================================================================
+# CSS
+# =============================================================================
+CSS = (Path(__file__).resolve().parent / "styles.css").read_text(encoding="utf-8")
+
+# =============================================================================
+# JS
+# =============================================================================
+JS_TEMPLATE = (Path(__file__).resolve().parent / "script.js").read_text(encoding="utf-8")
+
+
+# =============================================================================
+# build_html — 主入口
+# =============================================================================
+def build_html(case_data: dict) -> str:
+    """从 case_data 构建完整 HTML.
+
+    case_data 结构 (新 schema):
+        page_title:    str
+        case_id:       int | str | None
+        source:        {platform, author, date, url, title, excerpt, body_text?, cover_image?}
+        procedures: [
+            {
+                id:            str (e.g. 'p1-simple' / 'p1')
+                name:          str
+                purpose:       str
+                category:      str
+                platform:      str
+                author:        str
+                declarations:  {inputs[], resources[], returns{}}
+                type_registry: dict (该工序的 case-specific 类型, 跟 STDLIB 合并)
+                steps:         [{id, kind, effect, via, action, ...}]
+                return_row:    {arrow, text}
+            },
+            ...
+        ]
+
+    """
+    # type_registry 合并: STDLIB + 所有 procedures.type_registry (跨工序合并)
+    type_reg = dict(STDLIB_TYPE_REGISTRY)
+    for proc in case_data.get('procedures', []):
+        type_reg.update(proc.get('type_registry') or {})
+
+    # 补齐 type.json $leaves: 两类问题都要修
+    #   (a) 缺 entry: STDLIB 跟 type.json 不同步, 21 个叶子在字典树但 STDLIB 没条目
+    #       → 补 stub {in_tree: True}
+    #   (b) 有 entry 但缺 in_tree 标记: e.g. type.json.type_metadata 里"提示词" 有 metadata 但没 in_tree,
+    #       同时它又是 $leaves 之一. STDLIB 直接复制 type_metadata 段就没带 in_tree.
+    #       → in-place 加 in_tree=True
+    # 这是 script.js isInTypeTree() 正确返 true 的硬要求.
+    try:
+        leaves_file = Path(__file__).resolve().parent.parent / 'taxonomy' / 'type.json'
+        if leaves_file.exists():
+            leaves_data = json.loads(leaves_file.read_text(encoding='utf-8'))
+            for leaf in leaves_data.get('$leaves', []):
+                if leaf not in type_reg:
+                    type_reg[leaf] = {'in_tree': True}
+                elif isinstance(type_reg[leaf], dict) and not type_reg[leaf].get('in_tree'):
+                    type_reg[leaf] = {**type_reg[leaf], 'in_tree': True}
+    except Exception:
+        pass    # 兜底失败不阻塞渲染
+
+    # build thead 一次 (24 列结构跨 procedures 共享)
+    thead = render_thead()
+
+    # 逐 procedure 渲染: 每个 procedure 出一段 (declarations 折叠 + 工序表)
+    procedure_blocks: list[str] = []
+    for proc in case_data.get('procedures', []):
+        proc_decl_html = render_declarations(case_data, procedure=proc)
+
+        body_rows = []
+        for step in proc.get('steps', []):
+            body_rows.append(render_step_row(step, step['id'], type_reg))
+        rr = proc.get('return_row') or {}
+        if rr:
+            body_rows.append(f'<tr class="return-row"><td class="idx">{rr.get("arrow", "↩")}</td><td colspan="13">{rr.get("text", "")}</td></tr>')
+        proc_tbody = '<tbody>\n      ' + '\n      '.join(body_rows) + '\n    </tbody>'
+
+        proc_id_attr = he(proc.get('id', ''))
+        procedure_blocks.append(f'''<section class="procedure" id="proc-{proc_id_attr}">
+    {proc_decl_html}
+    <div class="table-wrap">
+      <table class="proc">
+        {thead}
+        {proc_tbody}
+      </table>
+    </div>
+  </section>''')
+
+    procedures_html = '\n  '.join(procedure_blocks)
+
+    # taxonomy for JS
+    taxonomy_js = {
+        '作用': EFFECT_TREE,
+        '动作': ACTION_TREE,
+        '类型': TYPE_TREE,
+        '实质': EXTERNAL_TAXONOMIES['实质'],
+        '形式': EXTERNAL_TAXONOMIES['形式'],
+    }
+
+    js = (JS_TEMPLATE
+          .replace('__TYPE_REGISTRY__', json.dumps(type_reg, ensure_ascii=False, indent=2))
+          .replace('__TAXONOMY__', json.dumps(taxonomy_js, ensure_ascii=False, indent=2)))
+
+    page_title = case_data.get('page_title', 'Procedure DSL 可视化')
+    source_html = render_source(case_data)
+    legend_html = render_legend()
+
+    return f'''<!doctype html>
+<html lang="zh">
+<head>
+  <meta charset="utf-8">
+  <title>{he(page_title)}</title>
+  <style>{CSS}</style>
+</head>
+<body>
+  <div class="scroll-area">
+    <header class="page-header">
+      <h1>{he(page_title)}</h1>
+    </header>
+    {source_html}
+    {legend_html}
+    {procedures_html}
+  </div>
+  <div class="drawer-overlay" id="drawer-overlay"></div>
+  <aside class="drawer" id="drawer" aria-hidden="true">
+    <header>
+      <h2>详情</h2>
+      <button class="close" aria-label="关闭">×</button>
+    </header>
+    <div class="content"></div>
+  </aside>
+  <script>{js}</script>
+</body>
+</html>
+'''

+ 194 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/script.js

@@ -0,0 +1,194 @@
+const typeRegistry = __TYPE_REGISTRY__;
+const taxonomy = __TAXONOMY__;
+
+function isInTypeTree(name) {
+  const t = typeRegistry[name];
+  if (!t) return false;
+  if (t.in_tree) return true;
+  if (t.extends) return isInTypeTree(t.extends);
+  return false;
+}
+
+const drawer = document.getElementById('drawer');
+const overlay = document.getElementById('drawer-overlay');
+const drawerTitle = drawer.querySelector('h2');
+const drawerContent = drawer.querySelector('.content');
+
+function openDrawer(title, htmlContent) {
+  drawerTitle.textContent = title;
+  drawerContent.innerHTML = htmlContent;
+  drawer.classList.add('open');
+  overlay.classList.add('open');
+}
+function closeDrawer() {
+  drawer.classList.remove('open');
+  overlay.classList.remove('open');
+}
+drawer.querySelector('.close').addEventListener('click', closeDrawer);
+overlay.addEventListener('click', closeDrawer);
+
+function escapeHtml(s) {
+  return String(s).replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[m]));
+}
+function renderTree(tree, highlight, depth = 0) {
+  if (typeof tree === 'string') {
+    return `<div class="node" style="margin-left:${depth*16}px; color:#6b7280;">${escapeHtml(tree)}</div>`;
+  }
+  let out = '';
+  for (const k of Object.keys(tree)) {
+    const v = tree[k];
+    const isHL = (highlight && (k === highlight || k.endsWith('/'+highlight)));
+    const cls = isHL ? 'node highlight' : 'node';
+    out += `<div class="${cls}" style="margin-left:${depth*16}px;">${escapeHtml(k)}${(typeof v === 'string') ? ' — ' + escapeHtml(v) : ''}</div>`;
+    if (typeof v === 'object') {
+      out += renderTree(v, highlight, depth + 1);
+    }
+  }
+  return out;
+}
+
+// type chip click
+document.querySelectorAll('.chip[data-type]').forEach(c => {
+  c.addEventListener('click', () => {
+    const tp = c.getAttribute('data-type');
+    const t = typeRegistry[tp] || {};
+    let parts = [];
+    parts.push(`<div class="row"><b>类型名</b>: ${escapeHtml(tp)}</div>`);
+    if (t.extends) parts.push(`<div class="row"><b>extends</b>: ${escapeHtml(t.extends)}</div>`);
+    if (t.desc) parts.push(`<div class="row"><b>描述</b>: ${escapeHtml(t.desc)}</div>`);
+    parts.push(`<h3>字典树 (§A.3 类型词表)</h3>`);
+    if (t && t.in_tree) {
+      parts.push(`<div class="row" style="color:#047857;">✓ <b>${escapeHtml(tp)}</b> 是字典树叶子</div>`);
+    } else if (t && t.extends && isInTypeTree(t.extends)) {
+      parts.push(`<div class="row" style="color:#0369a1;">✓ <b>${escapeHtml(tp)}</b> 是自定义拓展节点 (继承自: <b>${escapeHtml(t.extends)}</b>)</div>`);
+    } else {
+      parts.push(`<div class="warning">${escapeHtml(tp)} 不在字典树叶子, 也无合法的 extends 桥接.</div>`);
+    }
+    parts.push(`<div class="tree">${renderTree(taxonomy['类型'].tree, tp)}</div>`);
+    openDrawer(`类型 · ${tp}`, parts.join(''));
+  });
+});
+
+// 作用 / 动作 / 特性 / 实质 / 形式 click
+document.querySelectorAll('[data-prefix]').forEach(el => {
+  el.addEventListener('click', (e) => {
+    e.stopPropagation();
+    const prefix = el.getAttribute('data-prefix');
+    const value = el.getAttribute('data-value');
+    const tx = taxonomy[prefix];
+    if (!tx) {
+      openDrawer(`${prefix}`, `<div class="warning">无字典树定义</div>`);
+      return;
+    }
+    let body = '';
+    body += `<div class="row"><b>${escapeHtml(prefix)}</b>: ${escapeHtml(tx.title || '')}</div>`;
+    if (tx.desc) body += `<div class="row" style="color:#6b7280;">${escapeHtml(tx.desc)}</div>`;
+    if (tx.source === 'external') {
+      body += `<div class="warning"><b>${escapeHtml(prefix)}</b> 维度词表过大, 维护在外部 JSON: <code>${escapeHtml(tx.file || '')}</code>. 查询: <code>spec/tools/taxonomy-lookup.py --dim ${escapeHtml(prefix)} --subtree &lt;path&gt;</code>.</div>`;
+      body += `<h3>当前值</h3><div class="row" style="font-family:ui-monospace,monospace;">${escapeHtml(value)}</div>`;
+    } else if (tx.tree) {
+      body += `<h3>字典树 (当前值: <span class="highlight">${escapeHtml(value)}</span> 已高亮)</h3>`;
+      body += `<div class="tree">${renderTree(tx.tree, value)}</div>`;
+    }
+    openDrawer(`${prefix} · ${value}`, body);
+  });
+});
+
+// variable hover
+document.querySelectorAll('.name[data-var]').forEach(n => {
+  n.addEventListener('mouseenter', () => {
+    const v = n.getAttribute('data-var');
+    document.querySelectorAll(`.name[data-var="${v}"]`).forEach(x => x.classList.add('var-highlight'));
+  });
+  n.addEventListener('mouseleave', () => {
+    document.querySelectorAll('.name.var-highlight').forEach(x => x.classList.remove('var-highlight'));
+  });
+});
+
+// block toggle (含 nested step-sub: 用 data-group 选)
+document.querySelectorAll('tr.block-header').forEach(b => {
+  b.addEventListener('click', (e) => {
+    if (e.target.closest('.chip, [data-prefix], .name')) return;
+    const group = b.getAttribute('data-step');
+    const arrow = b.querySelector('.arrow');
+    const nested = document.querySelectorAll(`tr[data-group="${group}"]`);
+    const collapsed = arrow.textContent.trim() === '▶';
+    nested.forEach(n => n.style.display = collapsed ? '' : 'none');
+    arrow.textContent = collapsed ? '▼' : '▶';
+  });
+});
+
+// ───────── column visibility (legend toggle) ─────────
+const COL_GROUPS = {
+  'demand': { headerSel: 'th.col-group-demand', cols: ['idx','intent','effect','substance','form'] },
+  'input':  { headerSel: 'th.col-group-input',  cols: ['in-type','in-value','in-anchor'] },
+  'impl':   { headerSel: 'th.col-group-impl',   cols: ['via','action','directive'] },
+  'output': { headerSel: 'th.col-group-output', cols: ['out-type','out-value','out-anchor'] },
+};
+
+function setColVisible(col, visible) {
+  document.querySelectorAll(`th.col-${col}, td.${col}`).forEach(el => {
+    el.classList.toggle('col-hidden', !visible);
+  });
+  document.querySelectorAll(`.col-toggle[data-col="${col}"]`).forEach(b => {
+    b.classList.toggle('off', !visible);
+  });
+  recomputeGroupColspans();
+  if (typeof updateGroupHeadState === 'function') updateGroupHeadState();
+}
+
+function recomputeGroupColspans() {
+  for (const [, g] of Object.entries(COL_GROUPS)) {
+    const visibleCount = g.cols.filter(c => {
+      const th = document.querySelector(`th.col-${c}`);
+      return th && !th.classList.contains('col-hidden');
+    }).length;
+    const groupTh = document.querySelector(g.headerSel);
+    if (!groupTh) continue;
+    if (visibleCount === 0) {
+      groupTh.classList.add('col-hidden');
+    } else {
+      groupTh.classList.remove('col-hidden');
+      groupTh.setAttribute('colspan', String(visibleCount));
+    }
+  }
+}
+
+document.querySelectorAll('.col-toggle').forEach(btn => {
+  btn.addEventListener('click', () => {
+    const col = btn.getAttribute('data-col');
+    const isOff = btn.classList.contains('off');
+    setColVisible(col, isOff);
+  });
+});
+
+document.querySelectorAll('.legend .group .gh').forEach(gh => {
+  gh.addEventListener('click', () => {
+    const grpEl = gh.closest('.group');
+    const toggles = Array.from(grpEl.querySelectorAll('.col-toggle'));
+    const anyVisible = toggles.some(t => !t.classList.contains('off'));
+    toggles.forEach(t => setColVisible(t.getAttribute('data-col'), !anyVisible));
+    updateGroupHeadState();
+  });
+});
+
+function updateGroupHeadState() {
+  document.querySelectorAll('.legend .group').forEach(grpEl => {
+    const toggles = Array.from(grpEl.querySelectorAll('.col-toggle'));
+    const allOff = toggles.every(t => t.classList.contains('off'));
+    grpEl.querySelector('.gh').classList.toggle('all-off', allOff);
+  });
+}
+
+recomputeGroupColspans();
+updateGroupHeadState();
+
+// 推断补全 toggle (legend 上的"高亮推断")
+const infBtn = document.getElementById('inferred-toggle');
+if (infBtn) {
+  infBtn.addEventListener('click', () => {
+    document.body.classList.toggle('show-inferred');
+    infBtn.classList.toggle('on');
+  });
+}
+

+ 306 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/styles.css

@@ -0,0 +1,306 @@
+* { box-sizing: border-box; }
+html, body { margin: 0; padding: 0; font-family: -apple-system, "PingFang SC", "Helvetica Neue", "Microsoft YaHei", sans-serif; font-size: 13px; color: #111827; background: #f5f5f7; }
+/* case 页布局: body 固定 viewport 高 + overflow hidden, 唯一的滚动容器是 .scroll-area; 页头 / declarations / source / legend / 表格全装在里面.
+   滚动时它们一起向上滚走, 只有 thead 因 position: sticky 留在顶 — 这是用户要求的"只冻结表头两行". */
+body { height: 100vh; overflow: hidden; }
+header.page-header { padding: 14px 20px 8px; background: #fff; border-bottom: 1px solid #e5e7eb; }
+header.page-header h1 { margin: 0 0 6px; font-size: 16px; font-weight: 600; }
+header.page-header .meta { color: #6b7280; font-size: 12px; line-height: 1.5; }
+
+/* 工序头部 + declare 块 */
+details.declarations { margin: 12px 20px 0; background: #fff; border: 1px solid #e2e8f0; border-radius: 6px; }
+details.declarations[open] summary { border-bottom: 1px solid #e2e8f0; }
+details.declarations summary { padding: 10px 14px; cursor: pointer; font-size: 13px; line-height: 1.65; list-style: none; }
+details.declarations summary::-webkit-details-marker { display: none; }
+details.declarations summary::before { content: '▼ '; color: #94a3b8; font-size: 10px; margin-right: 4px; }
+details.declarations:not([open]) summary::before { content: '▶ '; }
+details.declarations .proc-name { color: #1f2937; font-size: 14px; }
+details.declarations .decl-purpose { color: #475569; margin-left: 12px; font-size: 12px; }
+details.declarations .decl-meta { color: #6b7280; font-size: 11.5px; margin-left: 16px; }
+details.declarations .tag-mini { display: inline-block; padding: 1px 7px; font-size: 11px; background: #fef3c7; border-radius: 3px; color: #92400e; margin-left: 8px; }
+.decl-body { padding: 12px 18px 14px; display: flex; flex-wrap: wrap; gap: 14px 32px; }
+.decl-section { min-width: 260px; flex: 1 1 280px; }
+.decl-label { color: #475569; font-size: 11.5px; font-weight: 600; margin-bottom: 6px; padding-bottom: 4px; border-bottom: 1px dashed #e2e8f0; }
+.decl-row { padding: 3px 0; font-size: 12.5px; line-height: 1.65; }
+.decl-row .name { font-weight: 500; color: #1f2937; margin-left: 4px; }
+.decl-row .decl-default { color: #6b7280; font-size: 11.5px; margin-left: 6px; }
+.decl-row .decl-desc { color: #6b7280; font-size: 11.5px; margin-left: 6px; }
+
+/* 原文 */
+details.source-block { margin: 8px 20px 12px; background: #fff; border: 1px solid #e2e8f0; border-radius: 6px; }
+details.source-block summary { padding: 8px 14px; cursor: pointer; font-size: 12px; color: #475569; list-style: none; }
+details.source-block summary::-webkit-details-marker { display: none; }
+details.source-block summary::before { content: '▶ '; color: #94a3b8; font-size: 10px; margin-right: 4px; }
+details.source-block[open] summary::before { content: '▼ '; }
+.source-body { padding: 6px 18px 12px; font-size: 12.5px; line-height: 1.65; }
+.source-body a { color: #2563eb; word-break: break-all; }
+.source-body .source-meta { color: #94a3b8; font-size: 11px; margin-top: 4px; }
+.source-body .source-excerpt { color: #1f2937; margin: 8px 0; padding: 8px 10px; background: #f8fafc; border-left: 3px solid #94a3b8; font-size: 12px; }
+.source-body hr.src-divider { border: 0; border-top: 1px dashed #cbd5e1; margin: 10px 0; }
+.source-body .src-p { margin: 6px 0; color: #1f2937; }
+.source-body .src-img-wrap, .source-body .src-cover { text-align: center; margin: 8px 0; }
+.source-body .src-img { max-width: 100%; max-height: 480px; border-radius: 4px; border: 1px solid #e2e8f0; }
+.source-body .src-video { margin: 8px 0; }
+.source-body .src-video a { display: inline-block; padding: 4px 10px; background: #fef3c7; color: #78350f; text-decoration: none; border-radius: 3px; font-size: 11.5px; }
+.source-body .source-full { max-height: 720px; overflow-y: auto; padding: 6px 12px; background: #fff; border: 1px solid #e2e8f0; border-radius: 4px; }
+
+/* Legend */
+.legend { padding: 10px 20px; background: #fff; border-bottom: 1px solid #e5e7eb; font-size: 11.5px; color: #6b7280; display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center; }
+.legend .group { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
+.legend .group .gh { display: inline-block; padding: 2px 8px; border-radius: 3px; color: #1f2937; font-weight: 600; cursor: pointer; user-select: none; }
+.legend .group .gh:hover { filter: brightness(0.92); }
+.legend .group .gh.all-off { opacity: 0.45; text-decoration: line-through; }
+.legend .group.gray  .gh { background: #e2e8f0; }
+.legend .group.yellow .gh { background: #fde68a; }
+.legend .group.green .gh { background: #bbf7d0; }
+.legend .group.blue  .gh { background: #bfdbfe; }
+.legend .col-toggle { display: inline-block; padding: 2px 7px; border: 1px solid #cbd5e1; border-radius: 3px; background: #fff; cursor: pointer; font-size: 11.5px; color: #334155; user-select: none; }
+.legend .col-toggle:hover { background: #f1f5f9; }
+.legend .col-toggle.off { color: #94a3b8; background: #f1f5f9; text-decoration: line-through; border-color: #e2e8f0; }
+.legend .inferred-toggle { display: inline-block; padding: 2px 8px; border: 1px solid #d97706; border-radius: 3px;
+                           background: #fffbeb; color: #92400e; cursor: pointer; font-size: 11.5px;
+                           font-weight: 600; user-select: none; margin-left: 8px; }
+.legend .inferred-toggle.on { background: #fef3c7; box-shadow: inset 0 0 0 1px #d97706; }
+.legend .legend-hint { color: #94a3b8; font-size: 11px; margin-left: auto; }
+
+/* 表格容器 */
+.table-wrap { background: #fff; }
+/* case 页 .scroll-area: 占满 body, 自身承担两轴滚动. 内部不嵌套 overflow 容器, 否则 sticky 锚点会被抢走.
+   (browser 页不会走这条 — 它在 .browser-main 内, 不直接挂 body 下) */
+body > .scroll-area { height: 100%; overflow: auto; background: #f5f5f7; }
+table.proc { width: max-content; min-width: 100%; border-collapse: collapse; background: #fff; table-layout: auto; font-size: 12px; }
+table.proc th, table.proc td { border: 1px solid #e5e7eb; padding: 6px 8px; vertical-align: top; line-height: 1.5; }
+table.proc thead th { font-weight: 600; text-align: center; font-size: 12.5px; padding: 8px 6px; }
+table.proc tbody td { font-size: 12px; }
+
+/* 列宽 (需求 3 列固定 width, 其他 min-width) */
+table.proc th.col-idx,    table.proc td.idx    { width: 38px;  min-width: 38px;  max-width: 38px;  text-align: center; }
+table.proc th.col-intent, table.proc td.intent { width: 240px; min-width: 240px; max-width: 240px; }
+table.proc th.col-effect, table.proc td.effect { width: 80px;  min-width: 80px;  max-width: 80px; }
+table.proc th.col-via       { min-width: 110px; }
+table.proc th.col-action    { min-width: 130px; }
+table.proc th.col-directive { min-width: 200px; }
+table.proc th.col-config    { min-width: 150px; }
+table.proc th.col-decorator { min-width: 130px; }
+table.proc th.col-memo      { min-width: 220px; }
+table.proc th.col-control   { min-width: 80px; }
+table.proc th.col-feature   { min-width: 80px; }
+
+/* 值列整段 <...> — 表示该值是对内容的描述, 不是内容本身. 整段 inline italic gray bg. */
+.value-desc { display: inline; padding: 1px 4px; border-radius: 3px;
+              background: rgba(241, 245, 249, 0.7); color: #475569; font-style: italic; }
+
+/* 值列不允许截断 */
+table.proc td.in-value, table.proc td.out-value {
+  white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere;
+  max-width: 320px;
+}
+table.proc td.directive, table.proc td.config,
+table.proc td.decorator, table.proc td.memo {
+  white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere;
+  max-width: 280px;
+}
+/* 实质/形式 列 (step 级) — 内容是短路径, 收窄列宽强制换行 (避免空旷低信息密度) */
+table.proc th.col-substance, table.proc td.substance,
+table.proc th.col-form, table.proc td.form { width: 90px; min-width: 90px; max-width: 90px;
+  word-break: break-all; overflow-wrap: anywhere; }
+table.proc th.col-in-type, table.proc th.col-out-type           { min-width: 90px;  }
+table.proc th.col-in-name, table.proc th.col-out-name           { min-width: 110px; }
+table.proc th.col-in-value, table.proc th.col-out-value         { min-width: 180px; }
+table.proc th.col-in-anchor, table.proc th.col-out-anchor       { min-width: 110px; }
+
+/* 冻结 需求 组 (idx + 目的 + 作用) — left 累计 = 0 / 38 / 278 */
+table.proc th.col-idx,    table.proc td.idx    { position: sticky; left: 0;     z-index: 2; }
+table.proc th.col-intent, table.proc td.intent { position: sticky; left: 38px;  z-index: 2; }
+table.proc th.col-effect, table.proc td.effect { position: sticky; left: 278px; z-index: 2; }
+table.proc thead th.col-group-demand          { position: sticky; left: 0;     z-index: 3; }
+table.proc thead th.col-idx, table.proc thead th.col-intent, table.proc thead th.col-effect { z-index: 3; }
+table.proc td.effect, table.proc thead th.col-effect, table.proc thead th.col-group-demand {
+  box-shadow: 6px 0 8px -4px rgba(0,0,0,0.18);
+}
+
+/* 冻结 表头 — 滚动时组名/列名行 stick to top */
+table.proc thead th { position: sticky; top: 0; z-index: 3; }
+table.proc thead tr:nth-child(2) th { top: 33px; }
+/* 4 个 corner cell (sticky-left + sticky-top 同时生效) z-index 加高, 避免被 tbody sticky-left 列覆盖 */
+table.proc thead th.col-group-demand,
+table.proc thead th.col-idx,
+table.proc thead th.col-intent,
+table.proc thead th.col-effect { z-index: 5; }
+
+/* 颜色分组背景 */
+table.proc td.idx, table.proc td.intent, table.proc td.effect, table.proc td.substance, table.proc td.form { background: #f8fafc; }
+table.proc thead th.col-group-demand { background: #1e293b; color: #fff; }
+table.proc thead tr:nth-child(2) th.col-idx,
+table.proc thead tr:nth-child(2) th.col-intent,
+table.proc thead tr:nth-child(2) th.col-effect,
+table.proc thead tr:nth-child(2) th.col-substance,
+table.proc thead tr:nth-child(2) th.col-form { background: #475569; color: #fff; }
+table.proc td.in-substance, table.proc td.in-form, table.proc td.in-type, table.proc td.in-name, table.proc td.in-value, table.proc td.in-anchor { background: #fefce8; }
+table.proc thead th.col-group-input { background: #b45309; color: #fff; }
+table.proc thead tr:nth-child(2) th.col-in-substance,
+table.proc thead tr:nth-child(2) th.col-in-form,
+table.proc thead tr:nth-child(2) th.col-in-type,
+table.proc thead tr:nth-child(2) th.col-in-name,
+table.proc thead tr:nth-child(2) th.col-in-value,
+table.proc thead tr:nth-child(2) th.col-in-anchor { background: #d97706; color: #fff; }
+table.proc td.via, table.proc td.action, table.proc td.directive, table.proc td.config,
+table.proc td.decorator, table.proc td.memo, table.proc td.control, table.proc td.feature { background: #f0fdf4; }
+table.proc thead th.col-group-impl { background: #065f46; color: #fff; }
+table.proc thead tr:nth-child(2) th.col-via,
+table.proc thead tr:nth-child(2) th.col-action,
+table.proc thead tr:nth-child(2) th.col-directive,
+table.proc thead tr:nth-child(2) th.col-config,
+table.proc thead tr:nth-child(2) th.col-decorator,
+table.proc thead tr:nth-child(2) th.col-memo,
+table.proc thead tr:nth-child(2) th.col-control,
+table.proc thead tr:nth-child(2) th.col-feature { background: #047857; color: #fff; }
+table.proc td.out-substance, table.proc td.out-form, table.proc td.out-type, table.proc td.out-name, table.proc td.out-value, table.proc td.out-anchor { background: #eff6ff; }
+table.proc thead th.col-group-output { background: #1e40af; color: #fff; }
+table.proc thead tr:nth-child(2) th.col-out-substance,
+table.proc thead tr:nth-child(2) th.col-out-form,
+table.proc thead tr:nth-child(2) th.col-out-type,
+table.proc thead tr:nth-child(2) th.col-out-name,
+table.proc thead tr:nth-child(2) th.col-out-value,
+table.proc thead tr:nth-child(2) th.col-out-anchor { background: #2563eb; color: #fff; }
+
+/* 组间分隔粗线 (需求|输入 在 form 后; 输入|实现 在 来源后; 实现|输出 在 指令后) */
+table.proc th.col-form, table.proc td.form,
+table.proc th.col-in-anchor, table.proc td.in-anchor,
+table.proc th.col-directive, table.proc td.directive { border-right: 3px solid #94a3b8; }
+
+/* 行边框 / 块头 / nested */
+table.proc tr.step-main > td { border-top: 1.5px solid #94a3b8; }
+table.proc tr.step-sub > td { border-top: 1px dashed #cbd5e1; }
+table.proc tr.block-header { font-weight: 600; }
+table.proc tr.block-header > td.intent { background: #e2e8f0; }
+table.proc tr.step-nested > td.idx { color: #6b7280; }
+
+/* :target 高亮 — 从其他页跳转过来时让对应 step 行闪烁定位 */
+table.proc tr:target > td {
+  animation: rowTargetFlash 1.6s ease-out;
+  box-shadow: inset 4px 0 0 #6d28d9;
+}
+@keyframes rowTargetFlash {
+  0%   { background-color: #fef3c7 !important; }
+  100% { background-color: inherit; }
+}
+
+/* output 的 id 小标签 (贴在值前, 供 anchor 1:1 引用对照) */
+.io-id {
+  display: inline-block; margin-right: 4px; padding: 0 4px;
+  font-size: 10px; font-family: ui-monospace, "SF Mono", monospace;
+  color: #475569; background: #e2e8f0; border-radius: 3px; vertical-align: top;
+}
+
+/* 返回行 */
+tr.return-row > td { background: #fde68a !important; font-weight: 600; padding: 8px; }
+
+/* chip — 中性灰底 (供 declaration / drawer / 返回行); 表格内 type chip 由下方列色覆盖 */
+.chip { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11.5px; color: #1f2937; background: #d1d5db; cursor: pointer; user-select: none; }
+.chip:hover { filter: brightness(0.95); box-shadow: 0 0 0 1px #1e293b; }
+
+/* 表格 in-type / out-type 列内 chip 统一列色 (黄/蓝区分输入输出) */
+table.proc td.in-type .chip  { background: #fde68a !important; color: #78350f; }
+table.proc td.out-type .chip { background: #bfdbfe !important; color: #1e3a8a; }
+
+/* keyword / name / flow */
+.kw { color: #6d28d9; font-weight: 600; }
+.name { color: #0f172a; }
+.name:hover, .name.var-highlight { background: #fef3c7; cursor: pointer; }
+.flow { color: #6b7280; font-size: 11.5px; font-style: italic; }
+
+/* intent tokens */
+.intent-text { color: #1f2937; line-height: 1.55; }
+.intent-tok { display: inline-block; padding: 1px 5px; border-radius: 3px; margin: 0 1px; font-size: 11.5px; }
+/* intent token: 底色对应其引用的列. 输入列黄, 输出列蓝, 实现列绿, 需求列灰. */
+/* 需求 (灰) */
+.intent-tok.ik-effect    { background: #cbd5e1; color: #1f2937; }
+/* 实现 (绿系) — 3 个不同饱和度区分 */
+.intent-tok.ik-via       { background: #d1fae5; color: #064e3b; font-family: ui-monospace, "SF Mono", monospace; font-size: 11px; }
+.intent-tok.ik-act       { background: #86efac; color: #14532d; }
+.intent-tok.ik-control   { background: #99f6e4; color: #134e4a; }
+/* feature 禁止 intent 引用; 用 ik-other 警告色 */
+.intent-tok.ik-other     { background: #fee2e2; color: #991b1b; text-decoration: line-through; }
+/* 输入·类型 (黄圆胶囊) / 输出·类型 (蓝圆胶囊) */
+.intent-tok.ik-in-type   { background: #fde68a; color: #78350f; border-radius: 10px; padding: 1px 8px; font-weight: 500; }
+.intent-tok.ik-out-type  { background: #bfdbfe; color: #1e3a8a; border-radius: 10px; padding: 1px 8px; font-weight: 500; }
+/* 输入·实质 / 输出·实质 (矩形 tag) */
+.intent-tok.ik-in-sub    { background: #fef3c7; color: #92400e; }
+.intent-tok.ik-out-sub   { background: #dbeafe; color: #1e40af; }
+/* 输入·形式 / 输出·形式 (矩形 tag 斜体) */
+.intent-tok.ik-in-form   { background: #fef3c7; color: #92400e; font-style: italic; }
+.intent-tok.ik-out-form  { background: #dbeafe; color: #1e40af; font-style: italic; }
+
+/* substance/form 路径文本 */
+td.substance > span, td.form > span {
+  display: inline-block; padding: 1px 4px; border-radius: 2px; font-size: 11px;
+  color: #1f2937; background: rgba(255,255,255,0.6); border: 1px solid rgba(0,0,0,0.06);
+  word-break: break-all; line-height: 1.4; cursor: pointer;
+}
+td.effect > span, td.action > span {
+  display: inline-block; padding: 1px 5px; border-radius: 2px; font-size: 11.5px;
+  color: #0f172a; background: rgba(255,255,255,0.7); cursor: pointer; border: 1px solid rgba(0,0,0,0.06);
+}
+
+/* 指令/配置/运行/备注 列 — 多条目 vertical 堆叠 */
+td.directive .instr-item, td.config .instr-item, td.decorator .instr-item, td.memo .instr-item {
+  display: block; font-size: 11.5px; color: #1f2937; margin: 2px 0; line-height: 1.5;
+}
+
+/* row-focus 加深底色 */
+td.row-focus { font-weight: 600; color: #0f172a; }
+td.idx.row-focus, td.intent.row-focus, td.effect.row-focus, td.substance.row-focus, td.form.row-focus { background: #e2e8f0 !important; }
+td.in-substance.row-focus, td.in-form.row-focus, td.in-type.row-focus, td.in-name.row-focus, td.in-value.row-focus, td.in-anchor.row-focus { background: #fde68a !important; }
+td.via.row-focus, td.action.row-focus, td.directive.row-focus, td.config.row-focus,
+td.decorator.row-focus, td.memo.row-focus, td.control.row-focus, td.feature.row-focus { background: #bbf7d0 !important; }
+td.out-substance.row-focus, td.out-form.row-focus, td.out-type.row-focus, td.out-name.row-focus, td.out-value.row-focus, td.out-anchor.row-focus { background: #bfdbfe !important; }
+
+/* inferred 角标 */
+sup.inferred { color: #b45309; font-size: 10px; font-weight: bold; padding: 0 2px; cursor: help; }
+
+/* 任意 cell 推断补全标记 — 「推」角标 + hover 显示 reason (不再加虚线下划线, 由角标承担识别) */
+td.is-inferred {
+  cursor: help;
+}
+td.is-inferred::after {
+  content: '推';
+  display: inline-block;
+  font-size: 9px;
+  color: #92400e;
+  background: rgba(254, 243, 199, 0.9);
+  padding: 0 3px;
+  border-radius: 2px;
+  margin-left: 4px;
+  vertical-align: top;
+  font-weight: 600;
+  border: 1px solid #fbbf24;
+}
+/* 低置信留空变体: AI 想过但拿不准, 故意留空; 角标变 推? 与高置信 推 区分 (spec §推断补全标记 C) */
+td.is-inferred.is-low-confidence::after { content: '推?'; }
+/* 高亮模式: legend 点击"高亮推断" 时, body 加 show-inferred 类, 所有推断 cell 加重底色 */
+body.show-inferred td.is-inferred {
+  background: #fef3c7 !important;
+  box-shadow: inset 0 0 0 1px #d97706;
+}
+
+/* 列隐藏 */
+.col-hidden { display: none !important; }
+
+/* drawer */
+.drawer-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.35); display: none; z-index: 100; }
+.drawer-overlay.open { display: block; }
+.drawer { position: fixed; right: 0; top: 0; bottom: 0; width: 520px; max-width: 90vw; background: #fff; box-shadow: -4px 0 16px rgba(0,0,0,0.15); z-index: 101; overflow-y: auto; transform: translateX(100%); transition: transform 0.2s ease-out; }
+.drawer.open { transform: translateX(0); }
+.drawer header { padding: 14px 18px; background: #1e293b; color: #fff; border-bottom: 0; position: sticky; top: 0; z-index: 2; }
+.drawer header h2 { margin: 0; font-size: 14px; }
+.drawer .close { position: absolute; right: 12px; top: 12px; background: transparent; color: #fff; border: 0; cursor: pointer; font-size: 18px; }
+.drawer .content { padding: 14px 18px; font-size: 12.5px; line-height: 1.6; color: #1f2937; }
+.drawer .content h3 { margin: 14px 0 6px; font-size: 12.5px; color: #047857; }
+.drawer .content pre { background: #f3f4f6; padding: 8px; border-radius: 3px; font-size: 11.5px; overflow-x: auto; line-height: 1.5; white-space: pre-wrap; }
+.drawer .content .row { margin: 4px 0; }
+.drawer .content .row b { color: #374151; }
+.drawer .tree { font-family: ui-monospace, "SF Mono", monospace; font-size: 11.5px; }
+.drawer .tree .node { padding: 1px 0; }
+.drawer .tree .highlight { background: #fde68a; padding: 1px 4px; border-radius: 2px; font-weight: 600; }
+.drawer .warning { background: #fef3c7; border-left: 3px solid #f59e0b; padding: 8px 10px; margin: 8px 0; font-size: 12px; }

+ 0 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/taxonomy-lookup.py → examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/taxonomy-lookup.py


+ 672 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec-back/tools/wf-patch.py

@@ -0,0 +1,672 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+wf-patch.py — workflow.json 的安全批量字段设置器.
+
+为什么有这个工具:
+  workflow.json 由各 phase **直接 Write 骨架 + 逐字段填充** 演化. 但「给几十个 IO
+  逐个加 anchor」「给每个 step 填 effect/action/type」这类批量字段赋值, 用 Edit
+  一处一处改太碎, 手写整段 JSON 又极易踩转义 / 控制字符坑 (把文件搞坏).
+  wf-patch 卡在中间: **你只负责语义决策 (path=value), 工具负责安全落盘 + 合法性校验**.
+
+  - 安全 IO: 工具自己 json.load -> 改 -> json.dump(ensure_ascii=False), 你永远不手写 JSON.
+  - 写入即校验 (fail-fast): 每条赋值立刻对照字典树 / type_registry / anchor 格式校验,
+    **任何一条非法 -> 报具体哪条错, 整批不写** (不产出悄悄错的文件). lint 仍做全局兜底.
+
+用法:
+    # 单条 / 多条 --set (path=value, 只在第一个 '=' 处切, value 可含 '=' 和空格)
+    python spec/tools/wf-patch.py --workflow outputs/case-N/workflow.json \
+        --set 'p1.s1.inputs[0].anchor=← s0.主角图' \
+        --set 'p1.s2.effect=主体生成' \
+        --set 'p1.s2.action=生成/图像生成/文生图'
+
+    # 或一次性喂一份 patch 清单 (适合 1.3 加 anchor / 2A 填字段这种几十处批量)
+    python spec/tools/wf-patch.py --workflow outputs/case-N/workflow.json --patch _scratch/anchors.json
+    # anchors.json = [{"path": "p1.s1.inputs[0].anchor", "value": "← s0.x"}, ...]
+
+    # 只校验不写
+    python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
+
+    # 删字段 (取代手 Edit 删; 字段不存在则幂等跳过)
+    python spec/tools/wf-patch.py --workflow ... --unset 'p1.declarations.inputs[0].inferred'
+
+    # 只校验不写
+    python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
+
+路径语法 (proc / step 按 id 寻址, 不是下标; 只有真列表才用 [i]; 嵌套步 id 带点 s2.1 也支持):
+    p1.s2.effect                      step 标量字段 (effect/substance/form/via/action/directive/kind/intent/group)
+    p1.s1.inputs[0].anchor            IO 字段 (anchor/type/value/id)
+    p1.s2.focus                       step 的 focus 数组 (逗号分隔: focus=via,action,out-type-0)
+    p1.purpose                        procedure 头部字段 (name/purpose/category/platform/author)
+    p1.declarations.inputs[0].desc    declarations 内任意字段 (通用下钻)
+    source.url                        case-level 原帖信息 (platform/author/date/url/title/excerpt)
+    p1.type_registry.场景图.extends    注册 case-specific 类型 (会自动建 type_registry 段)
+
+value 特殊取值:
+    __null__   -> JSON null (用于 substance/form/url 可空)
+
+仍用 Write / Edit 的只剩 (尽量别碰生 JSON):
+    - workflow.json 骨架的首次创建 (Phase 1.2 从 template Write)
+    - instruction (列表套列表, 手动 Edit; 透传 directive 用 --resolve-passthrough)
+    改字段/删字段/改 source 现在都走本工具, 不要再 Read→Edit 改 workflow.json (会反复重读、烧 token).
+
+自动修引号 (load 时兜底):
+    workflow.json 由模型直 Write, 偶尔把中文引号写成未转义的 ASCII " → JSON 崩.
+    本工具 load 失败时会自动把这类误引号修成「」再 parse; 修成功则继续 patch, 并把
+    修复随本次写回落盘 (--dry-run 不写). 修不回才按 exit 2 报错. 不用再手写 _scratch 修复脚本.
+
+退出码:
+    0  全部校验通过并写入 (--dry-run 时为校验通过)
+    1  有校验失败 (整批未写) / 路径解析失败
+    2  CLI 参数错误 / 文件不存在 / JSON 损坏 (且自动修引号也救不回)
+"""
+from __future__ import annotations
+
+import argparse
+import json
+import re
+import subprocess
+import sys
+from pathlib import Path
+
+# spec/tools/wf-patch.py -> procedure-dsl/
+DSL_ROOT = Path(__file__).resolve().parent.parent.parent
+TAX_DIR = DSL_ROOT / 'spec' / 'taxonomy'
+LOOKUP = DSL_ROOT / 'spec' / 'tools' / 'taxonomy-lookup.py'
+
+# Windows 控制台 UTF-8
+for _s in (sys.stdout, sys.stderr):
+    if hasattr(_s, 'reconfigure'):
+        try:
+            _s.reconfigure(encoding='utf-8', errors='replace')
+        except Exception:
+            pass
+
+KIND_VOCAB = {'step', 'block', 'nested'}
+
+# value/directive 里的「引用占位」文案 — 这些是 anchor 的活, value 应填数据本身.
+# 命中即视为「未真正回填」(--resolve-passthrough 会尝试填, lint 会报警).
+META_REF = re.compile(r'[((]?\s*同\s*s[\d]|见\s*s[\d]|←\s*s[\d]|同上')
+
+
+# ===========================================================================
+# 自动修引号: 模型直 Write workflow.json 时常把中文引号写成 ASCII " (未转义) → JSON 崩.
+# 仅在 json.loads 失败时兜底调用 (合法文件零开销). 判别: 串内一个 ASCII " 之后第一个
+# 非空白字符 ∈ {,:}]} 或 EOF → 真·字符串定界符 (保留); 否则是误写的内容引号 → 换直角
+# 引号「」(串内交替 开「/闭」). 逻辑独立内置于本文件 (不 import 任何外部模块);
+# scratch/repair_workflow_quotes.py 是同款独立实现, 二者无依赖关系. 改完必须能 parse 才用.
+# ===========================================================================
+
+_STRUCT_AFTER = set(',:}]')
+
+
+def repair_ascii_quotes(raw: str):
+    """→ (修后文本, 改动的内容引号数). 纯走字符, 不依赖能否 parse."""
+    out, i, n = [], 0, len(raw)
+    in_str = esc = False
+    open_q = True
+    changes = 0
+    while i < n:
+        c = raw[i]
+        if not in_str:
+            out.append(c)
+            if c == '"':
+                in_str, esc, open_q = True, False, True
+            i += 1
+            continue
+        if esc:
+            out.append(c); esc = False; i += 1; continue
+        if c == '\\':
+            out.append(c); esc = True; i += 1; continue
+        if c == '"':
+            j = i + 1
+            while j < n and raw[j] in ' \t\r\n':
+                j += 1
+            nxt = raw[j] if j < n else ''
+            if nxt == '' or nxt in _STRUCT_AFTER:
+                out.append(c); in_str = False          # 真·结束符
+            else:
+                out.append('「' if open_q else '」')     # 误写的内容引号
+                open_q = not open_q
+                changes += 1
+            i += 1
+            continue
+        out.append(c); i += 1
+    return ''.join(out), changes
+
+
+class PathError(Exception):
+    """路径无法解析到 workflow.json 里的目标位置."""
+
+
+# ===========================================================================
+# 字典树加载: leaf 集 + {leaf: 全路径} + 全叶路径集 (与 lint 同款叶子派生)
+# ===========================================================================
+
+def _load_tree(name: str):
+    """读 spec/taxonomy/{name}.json. 返回 (leaves:set, leaf2path:dict, control:list)."""
+    f = TAX_DIR / f'{name}.json'
+    if not f.exists():
+        return set(), {}, []
+    d = json.loads(f.read_text(encoding='utf-8'))
+    leaf2path: dict[str, str] = {}
+
+    def walk(node: dict, prefix: list[str]):
+        nm = node.get('分类名称')
+        if not nm:
+            return
+        p = prefix + [nm]
+        kids = node.get('子分类') or []
+        if not kids:                       # 无子分类 = 叶子
+            leaf2path[nm] = '/'.join(p)
+        for c in kids:
+            walk(c, p)
+
+    for top in d.get('最终分类树') or []:
+        walk(top, [])
+    leaves = set(d.get('$leaves') or leaf2path.keys())
+    return leaves, leaf2path, (d.get('$control') or [])
+
+
+EFFECT_LEAVES, EFFECT_PATHS, _ = _load_tree('effect')
+ACTION_LEAVES, ACTION_PATHS, ACTION_CONTROL = _load_tree('action')
+TYPE_LEAVES, TYPE_PATHS, _ = _load_tree('type')
+
+# substance/form 校验结果缓存 (subprocess 较慢)
+_taxo_cache: dict[tuple[str, str], bool] = {}
+
+
+def _taxo_valid(dim: str, path: str) -> bool:
+    """调 taxonomy-lookup.py --validate, exit 0 = 合法. 结果缓存."""
+    key = (dim, path)
+    if key in _taxo_cache:
+        return _taxo_cache[key]
+    try:
+        import os
+        env = os.environ.copy()
+        env['PYTHONIOENCODING'] = 'utf-8'
+        r = subprocess.run(
+            [sys.executable, str(LOOKUP), '--dim', dim, '--validate', path],
+            capture_output=True, text=True, encoding='utf-8', errors='replace', env=env,
+        )
+        ok = (r.returncode == 0)
+    except Exception:
+        ok = False                          # 校验器跑不起来时, 保守判非法
+    _taxo_cache[key] = ok
+    return ok
+
+
+
+def _closest(name: str, leaves) -> str:
+    """给个最接近的叶子名做提示 (子串/前缀朴素匹配, 仅供报错文案)."""
+    cands = [lf for lf in leaves if name and (name in lf or lf in name)]
+    return (' 最接近: ' + '/'.join(cands[:3])) if cands else ''
+
+
+# ===========================================================================
+# 字段校验 -> (ok, normalized_value, err_msg)
+# ===========================================================================
+
+def validate_field(field: str, value, proc: dict, pending_types: set[str] = None):
+    # null 哨兵 (substance/form/url 可空)
+    if value == '__null__':
+        if field in ('substance', 'form', 'url'):
+            return True, None, ''
+        return False, value, f'__null__ 只对 substance/form/url 有意义, {field} 不可为 null'
+
+    # focus 是数组: 逗号分隔 → list ('via,action,out-type-0'); 空串 → []
+    if field == 'focus':
+        items = [t.strip() for t in str(value).split(',') if t.strip()]
+        return True, items, ''
+
+    if field == 'effect':
+        if value in EFFECT_LEAVES:
+            return True, value, ''
+        # 给了全路径 -> 归一到叶名 (schema 存叶名)
+        for leaf, path in EFFECT_PATHS.items():
+            if value == path:
+                return True, leaf, ''
+        return False, value, f'effect={value!r} 不是 effect.json 叶子(存叶名).{_closest(value, EFFECT_LEAVES)}'
+
+    if field == 'action':
+        # action 存全路径; 给叶名自动展开, 给全叶路径原样接受
+        if value in ACTION_PATHS:                 # 是叶名
+            return True, ACTION_PATHS[value], ''
+        if value in ACTION_PATHS.values():        # 是合法叶路径
+            return True, value, ''
+        return False, value, (f'action={value!r} 不是合法动作叶子/叶路径 '
+                              f'(形如 生成/图像生成/文生图).{_closest(value.split("/")[-1], ACTION_LEAVES)}')
+
+    if field == 'type':
+        if value in TYPE_LEAVES:
+            return True, value, ''
+        reg = proc.get('type_registry') or {}
+        if value in reg:
+            return True, value, ''
+        if pending_types and value in pending_types:
+            return True, value, ''
+        return False, value, (f'type={value!r} 不是 type.json 叶子, 也没在本工序 type_registry 注册. '
+                              f'先 --set {proc.get("id")}.type_registry.{value}.extends=<叶子> 再用.{_closest(value, TYPE_LEAVES)}')
+
+    if field == 'extends':                        # type_registry entry 的 extends 必须桥到 stdlib 叶子
+        if value in TYPE_LEAVES:
+            return True, value, ''
+        return False, value, f'type_registry extends={value!r} 必须是 type.json 叶子.{_closest(value, TYPE_LEAVES)}'
+
+    if field == 'substance':
+        if isinstance(value, str):
+            if '+' in value:
+                paths = [p.strip() for p in value.split('+') if p.strip()]
+            else:
+                paths = [value.strip()]
+        elif isinstance(value, list):
+            paths = [str(p).strip() for p in value if str(p).strip()]
+        else:
+            return False, value, 'substance 必须是字符串或数组'
+
+        invalid_paths = []
+        for p in paths:
+            if not _taxo_valid('实质', p):
+                invalid_paths.append(p)
+        if invalid_paths:
+            return False, value, f'以下 substance 路径不在实质词表: {invalid_paths}'
+        
+        norm_val = paths if (isinstance(value, list) or (isinstance(value, str) and '+' in value)) else paths[0]
+        return True, norm_val, ''
+
+    if field == 'form':
+        if isinstance(value, str):
+            if '+' in value:
+                paths = [p.strip() for p in value.split('+') if p.strip()]
+            else:
+                paths = [value.strip()]
+        elif isinstance(value, list):
+            paths = [str(p).strip() for p in value if str(p).strip()]
+        else:
+            return False, value, 'form 必须是字符串或数组'
+
+        invalid_paths = []
+        for p in paths:
+            if not _taxo_valid('形式', p):
+                invalid_paths.append(p)
+        if invalid_paths:
+            return False, value, f'以下 form 路径不在形式词表: {invalid_paths}'
+        
+        norm_val = paths if (isinstance(value, list) or (isinstance(value, str) and '+' in value)) else paths[0]
+        return True, norm_val, ''
+
+    if field == 'anchor':
+        if re.match(r'^\s*(←|→)', str(value)):
+            return True, value, ''
+        return False, value, f'anchor={value!r} 须以 ← (输入引用) 或 → (输出去向) 开头'
+
+    if field == 'kind':
+        if value in KIND_VOCAB:
+            return True, value, ''
+        return False, value, f'kind={value!r} 不在 {sorted(KIND_VOCAB)}'
+
+    # 自由文本字段 (name/value/intent/via/purpose/category/platform/author/desc/group...)
+    return True, value, ''
+
+
+# ===========================================================================
+# 路径解析 -> (parent_container, key, proc, field_name)
+# ===========================================================================
+
+_SEG = re.compile(r'^([^\[]+)(?:\[(\d+)\])?$')
+
+
+def _split_seg(seg: str):
+    m = _SEG.match(seg)
+    if not m:
+        raise PathError(f'非法路径段 {seg!r}')
+    return m.group(1), (int(m.group(2)) if m.group(2) is not None else None)
+
+
+def _descend(container, segs):
+    """沿 segs 走进 container, 返回 (parent, last_key). 中间节点必须已存在.
+
+    segs 每段可带 [i] 下标. last_key 是 dict 键 (str) 或列表下标 (int);
+    设置即 parent[last_key]=value, 删除即 del parent[last_key].
+    用于 source.* / declarations.* 等通用路径 (proc/step 的 id 寻址不走这里).
+    """
+    cur = container
+    for i, seg in enumerate(segs):
+        name, idx = _split_seg(seg)
+        last = (i == len(segs) - 1)
+        if last and idx is None:
+            if not isinstance(cur, dict):
+                raise PathError(f'{name!r} 的父级不是对象')
+            return cur, name
+        if not isinstance(cur, dict) or name not in cur:
+            raise PathError(f'路径段 {name!r} 不存在, 无法下钻')
+        nxt = cur[name]
+        if idx is not None:
+            if not isinstance(nxt, list) or idx >= len(nxt):
+                raise PathError(f'{name}[{idx}] 越界或非列表')
+            if last:
+                return nxt, idx
+            cur = nxt[idx]
+        else:
+            cur = nxt
+    raise PathError('路径为空')
+
+
+def locate(data: dict, path: str):
+    """把 path 解析到目标. 返回 (parent, key, proc, field_name).
+
+    设置即 parent[key] = value. proc 给校验提供 type_registry 上下文.
+    proc / step 按 id 寻址 (不是下标); inputs/outputs 用 [i] 下标.
+    step id 可能带点 (嵌套步 s2.1) — 用最长前缀匹配消歧 (s2.1 优先于 s2).
+    """
+    if '.' not in path:
+        raise PathError(f'路径太短 {path!r}, 至少 <proc>.<字段> 或 source.<字段>')
+
+    proc_id, remainder = path.split('.', 1)
+
+    # --- source.* 分支 (case-level 原帖信息, 无 proc 上下文) ---
+    if proc_id == 'source':
+        src = data.setdefault('source', {})
+        parent, key = _descend(src, remainder.split('.'))
+        return parent, key, None, (key if isinstance(key, str) else '')
+
+    proc = next((p for p in (data.get('procedures') or []) if p.get('id') == proc_id), None)
+    if proc is None:
+        ids = [p.get('id') for p in (data.get('procedures') or [])]
+        raise PathError(f'找不到 procedure id={proc_id!r} (现有: {ids})')
+
+    # --- type_registry 分支 (允许自动建段/条目) ---
+    if remainder == 'type_registry' or remainder.startswith('type_registry.'):
+        parts = remainder.split('.')
+        if len(parts) == 3:
+            reg = proc.setdefault('type_registry', {})
+            entry = reg.setdefault(parts[1], {})
+            return entry, parts[2], proc, parts[2]
+        raise PathError('type_registry 路径形如 p1.type_registry.<类型名>.<extends|desc>')
+
+    # --- step 分支 (最长前缀匹配 step id, 兼容带点的嵌套步 id) ---
+    matched = None
+    for s in (proc.get('steps') or []):
+        sid = s.get('id')
+        if not sid:
+            continue
+        if remainder == sid:
+            raise PathError(f'step 路径要带字段, 形如 {proc_id}.{sid}.effect')
+        if remainder.startswith(sid + '.') and (matched is None or len(sid) > len(matched['id'])):
+            matched = s
+    if matched is not None:
+        sid = matched['id']
+        field_part = remainder[len(sid) + 1:]      # 'sid.' 之后
+        fsegs = field_part.split('.')
+        name2, idx2 = _split_seg(fsegs[0])
+        if name2 in ('inputs', 'outputs'):
+            if idx2 is None:
+                raise PathError(f'{name2} 要带下标, 形如 {name2}[0]')
+            lst = matched.get(name2)
+            if not isinstance(lst, list) or idx2 >= len(lst):
+                raise PathError(f'{proc_id}.{sid}.{name2}[{idx2}] 越界 (该 step 有 {len(lst or [])} 个 {name2})')
+            if len(fsegs) != 2:
+                raise PathError(f'IO 路径形如 {proc_id}.{sid}.{name2}[{idx2}].anchor')
+            return lst[idx2], fsegs[1], proc, fsegs[1]
+        else:
+            if len(fsegs) != 1:
+                raise PathError(f'step 标量字段形如 {proc_id}.{sid}.{name2}')
+            return matched, name2, proc, name2
+
+    # --- proc 内其余路径: 头部字段 / declarations.* / return_row.* 等, 走通用下钻 ---
+    parent, key = _descend(proc, remainder.split('.'))
+    return parent, key, proc, (key if isinstance(key, str) else '')
+
+
+# ===========================================================================
+# 透传回填: anchor 为纯 ← sN.varname 的 IO, 从源 output 抄 value (逐字回填)
+# ===========================================================================
+
+def _is_fillable(value) -> bool:
+    """该 value 算「还没真正回填」吗 — 空 / 占位符 / 引用文案."""
+    if value in (None, '', '-'):
+        return True
+    return bool(META_REF.search(str(value)))
+
+
+def _passthrough_id(anchor):
+    """anchor 为 `← <output-id>` (可带 [i] 容器索引) → 返回 output id; 否则 None.
+
+    `← 工序输入` / `← s6 (链)` 等非纯 id 引用返回 None (无法确定唯一源 value).
+    """
+    m = re.match(r'^\s*←\s*([^\s\[((]+)', str(anchor or ''))
+    if not m:
+        return None
+    return m.group(1) or None
+
+
+def resolve_passthrough(data: dict):
+    """把 anchor 为纯透传 (← <output-id>)、value 仍空或占位的 input, 用源 output 的 value 逐字填上.
+
+    迭代到不动点 (处理链式透传). 返回 (filled_msgs, warn_msgs).
+    """
+    out_index = {}          # output id -> output item (读 value)
+    for p in data.get('procedures') or []:
+        for s in p.get('steps') or []:
+            for o in s.get('outputs') or []:
+                if isinstance(o, dict) and o.get('id'):
+                    out_index[o['id']] = o
+
+    def _src_value(rid):
+        src = out_index.get(rid)
+        if src is None or _is_fillable(src.get('value')):
+            return None
+        return src['value']
+
+    filled: list[str] = []
+    changed, rounds = True, 0
+    while changed and rounds < 20:
+        changed, rounds = False, rounds + 1
+        for p in data.get('procedures') or []:
+            for s in p.get('steps') or []:
+                for idx, io in enumerate(s.get('inputs') or []):
+                    if not isinstance(io, dict) or not _is_fillable(io.get('value')):
+                        continue
+                    rid = _passthrough_id(io.get('anchor'))
+                    val = _src_value(rid) if rid else None
+                    if val is None:
+                        continue
+                    io['value'] = val
+                    filled.append(
+                        f"{p.get('id')}.{s.get('id')}.inputs[{idx}].value "
+                        f"← 复制自 {rid} ({len(str(val))} 字)"
+                    )
+                    changed = True
+
+    # 仍填不动的透传 (源 id 找不到) → warn
+    warns: list[str] = []
+    for p in data.get('procedures') or []:
+        for s in p.get('steps') or []:
+            for idx, io in enumerate(s.get('inputs') or []):
+                if not isinstance(io, dict) or not _is_fillable(io.get('value')):
+                    continue
+                rid = _passthrough_id(io.get('anchor'))
+                if rid and out_index.get(rid) is None:
+                    warns.append(
+                        f"{p.get('id')}.{s.get('id')}.inputs[{idx}] anchor 指向 "
+                        f"{rid} 但找不到该 output id (检查 anchor / output id)"
+                    )
+    return filled, warns
+
+
+# ===========================================================================
+# 应用
+# ===========================================================================
+
+def load_patches(args) -> list[tuple[str, str]]:
+    """汇总 --set、--patch 与 --set-file 成 [(path, value), ...]."""
+    def _norm(v):
+        if isinstance(v, str):
+            # 将中文全角双角/单引号自动归一化为标准半角引号,更利于 AI 生图引擎和 Prompt 语法识别
+            v = v.replace('“', '"').replace('”', '"').replace('‘', "'").replace('’', "'")
+        return v
+
+    out: list[tuple[str, str]] = []
+    for s in args.set or []:
+        if '=' not in s:
+            raise SystemExit(f'wf-patch: --set 缺 "=" : {s!r} (形如 path=value)')
+        path, value = s.split('=', 1)        # 只切第一个 '='
+        out.append((path.strip(), _norm(value)))
+
+    # 🟢 新增:从外部文件读取值注入
+    for sf in getattr(args, 'set_file', None) or []:
+        if '=' not in sf:
+            raise SystemExit(f'wf-patch: --set-file 缺 "=" : {sf!r} (形如 path=file_path)')
+        path, fpath_str = sf.split('=', 1)
+        fpath = Path(fpath_str.strip())
+        if not fpath.exists():
+            raise SystemExit(f'wf-patch: --set-file 指定的文件不存在: {fpath_str}')
+        try:
+            value = fpath.read_text(encoding='utf-8')
+        except Exception as e:
+            raise SystemExit(f'wf-patch: 无法读取 --set-file 指定的文件 {fpath_str}: {e}')
+        out.append((path.strip(), _norm(value)))
+
+    if args.patch:
+        if not args.patch.exists():
+            raise SystemExit(f'wf-patch: --patch 文件不存在 {args.patch}')
+        try:
+            items = json.loads(args.patch.read_text(encoding='utf-8'))
+        except json.JSONDecodeError as e:
+            raise SystemExit(f'wf-patch: --patch 不是合法 JSON: {e}')
+        for it in items:
+            out.append((it['path'], _norm(it['value'])))
+    return out
+
+
+def main() -> None:
+    ap = argparse.ArgumentParser(
+        prog='wf-patch.py',
+        description='workflow.json 安全批量字段设置器 (写入即校验, 任何一条非法整批不写)',
+    )
+    ap.add_argument('--workflow', type=Path, required=True, help='目标 workflow.json')
+    ap.add_argument('--set', action='append', metavar='PATH=VALUE',
+                    help='单条赋值, 可重复. 只在第一个 = 处切; value 可含 = 和空格 (记得整体加引号)')
+    ap.add_argument('--patch', type=Path, default=None,
+                    help='批量赋值清单 .json: [{"path":..,"value":..}, ...]')
+    ap.add_argument('--set-file', action='append', metavar='PATH=FILE_PATH', default=None,
+                    help='从外部文件读取内容注入指定字段. e.g. p1.s1.outputs[0].value=_scratch/prompt.txt')
+    ap.add_argument('--unset', action='append', metavar='PATH', default=None,
+                    help='删字段, 可重复. e.g. p1.declarations.inputs[0].inferred (字段不存在则跳过). 取代手 Edit 删字段')
+    ap.add_argument('--resolve-passthrough', action='store_true',
+                    help='把 anchor 为纯透传 (← sN.varname)、value 仍空/占位的 IO, 顺 anchor 从源 output 逐字抄 value. 可单独跑, 也可跟在 --set/--patch 后 (先赋值再解析). 迭代处理链式透传')
+    ap.add_argument('--dry-run', action='store_true', help='只校验/预演, 不写')
+    args = ap.parse_args()
+
+    wf = args.workflow
+    if not wf.exists():
+        print(f'wf-patch: 文件不存在 {wf}', file=sys.stderr)
+        sys.exit(2)
+    raw = wf.read_text(encoding='utf-8')
+    repaired = 0
+    try:
+        data = json.loads(raw)
+    except json.JSONDecodeError as e:
+        # 兜底: 试着把误写成 ASCII 的中文引号修成「」再 parse (模型直 Write 常见崩因)
+        fixed, repaired = repair_ascii_quotes(raw)
+        try:
+            data = json.loads(fixed)
+        except json.JSONDecodeError:
+            print(f'wf-patch: {wf} 不是合法 JSON (自动修引号也救不回): {e}', file=sys.stderr)
+            sys.exit(2)
+        print(f'[wf-patch] ⚠️ 原文件 JSON 非法 ({e.msg} @ line {e.lineno}); 已自动把 '
+              f'{repaired} 处误写的 ASCII 引号修成「」→ 解析成功, 修复将随本次写回落盘',
+              file=sys.stderr)
+
+    patches = load_patches(args)
+    unsets = args.unset or []
+    if not patches and not unsets and not args.resolve_passthrough:
+        print('wf-patch: 没有 --set / --patch / --unset / --resolve-passthrough, 啥也没干', file=sys.stderr)
+        sys.exit(2)
+
+    # 解析 + 校验; 任何一条失败 -> 整批不写
+    pending_types = set()
+    for path, _ in patches:
+        m = re.match(r'^p\d+\.type_registry\.([^.]+)\.(extends|desc)$', path)
+        if m:
+            pending_types.add(m.group(1))
+
+    plan = []          # set: (parent, key, normalized_value, path, display)
+    del_plan = []      # unset: (parent, key, path)
+    skipped = []       # unset 跳过 (字段本就不在)
+    errors = []        # (path, msg)
+    for path, value in patches:
+        try:
+            parent, key, proc, field = locate(data, path)
+        except PathError as e:
+            errors.append((path, str(e)))
+            continue
+        ok, norm, msg = validate_field(field, value, proc, pending_types)
+        if not ok:
+            errors.append((path, msg))
+            continue
+        plan.append((parent, key, norm, path, norm if norm is not None else 'null'))
+    for path in unsets:
+        try:
+            parent, key, _proc, _field = locate(data, path)
+        except PathError as e:
+            errors.append((path, str(e)))
+            continue
+        present = (isinstance(parent, dict) and key in parent) or \
+                  (isinstance(parent, list) and isinstance(key, int) and key < len(parent))
+        (del_plan if present else skipped).append((parent, key, path) if present else path)
+
+    if patches or unsets:
+        print(f'[wf-patch] {wf.name} — set {len(plan)}/{len(patches)} 通过, '
+              f'unset {len(del_plan)} 删/{len(skipped)} 跳过, {len(errors)} 失败')
+        for _p, _k, _n, path, disp in plan:
+            print(f'  ✓ set   {path} = {disp}')
+        for _p, _k, path in del_plan:
+            print(f'  ✓ unset {path}')
+        for path in skipped:
+            print(f'  · skip  {path} (字段本就不存在)')
+        for path, msg in errors:
+            print(f'  ✗ {path}  — {msg}')
+        if errors:
+            print(f'\n有 {len(errors)} 条失败, 整批未写入 (修正后重跑).', file=sys.stderr)
+            sys.exit(1)
+
+    # 应用到内存 data (set 先 unset 后; resolve 要看到这些改动). 是否持久化由 dry-run 决定.
+    for parent, key, norm, _, _ in plan:
+        parent[key] = norm
+    for parent, key, _path in sorted(del_plan, key=lambda d: -d[1] if isinstance(d[1], int) else 0):
+        if isinstance(parent, list):
+            parent.pop(key)
+        else:
+            del parent[key]
+
+    # 透传回填
+    filled, warns = [], []
+    if args.resolve_passthrough:
+        filled, warns = resolve_passthrough(data)
+        print(f'[resolve-passthrough] 回填 {len(filled)} 处透传 value, {len(warns)} 处填不动')
+        for m in filled:
+            print(f'  ✓ {m}')
+        for w in warns:
+            print(f'  ⚠ {w}')
+
+    n_changes = len(plan) + len(del_plan) + len(filled)
+    if args.dry_run:
+        extra = f' (+ 自动修复 {repaired} 处引号, dry-run 同样不写)' if repaired else ''
+        print(f'\n--dry-run: 预演 {n_changes} 处改动{extra}, 未写入.')
+        sys.exit(0)
+
+    # repaired>0 时即便无字段改动也要落盘 (否则修好的引号没存下来, 文件还是坏的)
+    if n_changes == 0 and not repaired:
+        print('\n没有改动 (透传 value 都已填好 / 无可赋值), 未写文件.')
+        sys.exit(0)
+
+    # 落盘 (安全序列化, 你从不手写 JSON)
+    wf.write_text(json.dumps(data, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
+    tail = f' (含自动修复 {repaired} 处引号→「」)' if repaired else ''
+    print(f'\n已写入 {n_changes} 处到 {wf.name}{tail}.')
+    sys.exit(0)
+
+
+if __name__ == '__main__':
+    main()

+ 93 - 163
examples/process_pipeline/script/search_eval/procedure-dsl/spec/README.md

@@ -1,213 +1,148 @@
-# Procedure DSL · 语法 + 提取 SKILL
+# 工序提取 SKILL · 总览
 
-> Procedure DSL 的语法 reference 和从原始 case 提取的操作 SKILL
+> 这道 skill 做一件事:**读一篇 AI 创作教程/案例,把它背后的"做法"还原成一张工序表,存成 `workflow.json`,再渲染成一个网页**
 >
-> 两部分: **语法定义** (顶层 [`syntax.md`](syntax.md), 干货不论证) + **提取流程** (子目录 [`extraction/`](extraction/), 三阶段操作步骤)。
->
-> 本目录各文件完整自洽; 需要 .md 样板时参考 `outputs/` 下已产出的 case-*.md。
->
-> ⚠ **路径提示**: 语法在 `spec/syntax.md` 顶层文件 (不在 `spec/part1-syntax/`!), 提取流程在 `spec/extraction/` 子目录. 没有 `part1-` / `part2-` 这种命名 — 不要脑补对称目录.
+> 本文是总览。具体操作和字段规则在 [extraction/](extraction/) 子目录的三个阶段文件里,按阶段读即可。
 
 ---
 
-**本目录 = 一个自包含 skill**: Agent 跑提取流程时, **所有 spec 信息都在本目录内**. 外部 case 数据 (`input/case-N-raw.json`) 和工作产物 (`outputs/case-N/`) 由 Agent 各自读写, 不算 spec.
+**本目录是一个自包含的 skill**:跑提取流程时需要的所有说明都在这里。外部的案例原文(`input/case-N-raw.json`)和你产出的成果(`outputs/case-N/`)不算 skill 的一部分。
 
 ## 输入 / 输出
 
-**输入** — 任一原始 case 素材: 公众号 / 小红书 / 推文 / 博客 (正文 + 配图)、视频教程 (含转写)、自己的工作回顾。
-
-**输出** (两份, 路径 `outputs/case-{N}/case-{N}-<slug>.{md,html}`):
-- `.md` — DSL 文本版 (按 [format/md-structure.md](format/md-structure.md) §11 结构)
-- `.html` — 可视化 (按 [format/procedure-table.md](format/procedure-table.md) 工序表规范)
-
-## 章节地图
+**输入**:任意一篇创作案例——公众号 / 小红书 / 推文 / 博客(正文 + 配图)、视频教程(带转写)、或你自己的工作复盘。
 
-### 概念模型 ([syntax.md](syntax.md))
+**输出**:一个网页 `outputs/case-{N}/case-{N}-<slug>.html`。
 
-DSL 的**概念模型 + 字段语义速览** (Phase 1 一次性加载). 不含逐构造的文本语法 —— 产物是 workflow.json + HTML, 不手写 DSL 文本.
+---
 
-| 内容 | § |
-|---|---|
-| 5 层架构 (L0 类型库 / L1 外部函数 / L2 抽象动作 / L3 工序模板 / L4 工序实例) + workflow.json 字段映射 | §1 |
-| 类型系统 (字典树叶子命名 + case-specific extends; 实质/形式 挂 IO item) | §2 |
-| 动作模型 (`via / action / feature / control / effect` 五字段) | §3 |
-| 工序结构 (L3 模板 = procedure; L4 实例 = 实际值回填) | §4 |
-| 命名规范 | §5 |
-| 标注速览 (step + IO 字段, 详见 [extraction/fields.md](extraction/fields.md)) | §6 |
+## 概念速览
 
-### 提取 SKILL ([extraction/](extraction/))
+读懂这几条,就能看懂工序表在表达什么。
 
-从 case 原文到 DSL + 可视化的提取流程. 按 phase 加载.
+**工序表把"一步操作"拆成几个层面**(对应 `workflow.json` 里的字段):
 
-| 文件 | 内容 | 加载时机 |
+| 层面 | 通俗讲 | 在 workflow.json 里 |
 |---|---|---|
-| [extraction/fields.md](extraction/fields.md) | 23 字段定义 + 推断补全标记 (三阶段共享) | Phase 1 起手 |
-| [extraction/control-flow.md](extraction/control-flow.md) | 控制流 → block/nested 结构建模 (循环/并行/分支怎么不拍平) | Phase 1 |
-| [extraction/phase1-skeleton.md](extraction/phase1-skeleton.md) | 阶段一执行 (1.1/1.2/1.3 骨架提取 + 多工序判断) | Phase 1 |
-| [extraction/phase2-normalize.md](extraction/phase2-normalize.md) | 阶段二归一化与标注 (fan-out 2A / 2B 子 Agent) | Phase 2 |
-| [extraction/phase3-finalize.md](extraction/phase3-finalize.md) | 阶段三检查收尾 (lint + 目的列 + 落盘) | Phase 3 |
-
-### Output · 产物规约 ([format/](format/))
+| 数据类型 | 这份数据算什么角色(参考图/提示词…) | 输入输出的 `type` |
+| 用的工具 | 哪个具体产品(manus/nano_banana…) | 步骤的 `via` |
+| 做的动作 | 干了什么(生成/反推…) | 步骤的 `action` |
+| 工序位置 | 处在流水线哪个环节(预处理/主体生成…) | 步骤的 `effect` |
+| 内容实质 | 这步本质上涉及什么(人物/场景/观念…) | 步骤的 `substance` |
+| 呈现形式 | 内容怎么组织(光影/构图/叙事…) | 步骤的 `form` |
+| 工序模板 | 一整套可复用的做法 | 一个 `procedure` |
+| 实际内容 | 这次具体填进去的真实值 | 输入输出的 `value` |
+| 目的 | 一句话概括这步在干嘛 | 步骤的 `intent` |
 
-`.md` 和 `.html` 两种产物的固定结构 + 数据契约.
+**一篇案例可以有多个工序**:比如一篇文章同时讲"简单做法"和"进阶做法",那就是两个工序,放在顶层 `procedures: []` 数组里(只有一个时也用长度 1 的数组)。
 
-| 文件 | 内容 |
-|---|---|
-| [md-structure.md](format/md-structure.md) | .md 输出固定章节 (工序梗概 / 引用类型 / L1-L4 / 关键启发) |
-| [procedure-table.md](format/procedure-table.md) | 工序表创作规范 (23 列字段语义 + intent token 规则 + chip 视觉 + 审美约束) |
-| [case-data.schema.json](format/case-data.schema.json) | `render-case.py` 的输入 JSON Schema (Draft 2020-12) |
+**自造的类型要"挂靠"**:类型词表里没有的词,要在这个工序的 `type_registry` 里写明它"算作"哪个标准词,例如 `主角图` 挂靠 `参考图`。这样既能自由起名,又不弄乱标准词表。
 
-### Taxonomy · 字典树受控词表 ([taxonomy/](taxonomy/))
+**命名约定**:类型名、动作名用中文;工具品牌名用英文(`nano_banana_pro`);每个输出都要有不重复的编号(如 `s2o1`)供后面引用。其中"作用 / 实质 / 形式 / 动作 / 目的"是**整步一个**,"类型 / 值 / 来源 / 编号"是**每个输入输出各一个**。
 
-5 维标注体系 (作用 / 动作 / 类型 / 实质 / 形式) 全部 bundled 在本目录, skill 自包含.
+> 三个分类词表(作用/动作/类型 要对到它们):作用 = [effect.json](taxonomy/effect.json)、动作 = [action.json](taxonomy/action.json)、类型 = [type.json](taxonomy/type.json)。**实质/形式 没有词表**——读懂步骤后直接提炼,不查词表。
 
-| 文件 | 维度 | 规模 | Agent 加载方式 |
-|---|---|---:|---|
-| [taxonomy/README.md](taxonomy/README.md) | — | — | **仅子 Agent 读取**(主 Agent 绝对禁止加载) |
-| [effect.json](taxonomy/effect.json) | 作用 | 9 叶子 | **仅 `phase-2a-normalizer` 自动加载并读取**(主 Agent 绝不加载,以维持极简 Context) |
-| [action.json](taxonomy/action.json) | 动作 | 30 叶子 + 5 control | 同上 |
-| [type.json](taxonomy/type.json) | 类型 | 50 叶子 | 同上。每节点含 `分类说明`;case-specific 类型自动写入 `workflow.json` 的 `type_registry` |
-| [type_suggestions.md](taxonomy/type_suggestions.md) | 类型升级提案 | append-only | 阶段三跑 `lint-case.py` 时**由工具自动同步 append**,Agent 无需手工编辑 |
-| `taxonomy/分类库导出_实质_*.json` | 实质 | 911 路径 | **仅由 `phase-2b-matcher` 内部通过脚本查询**(主 Agent 绝不读取和查询) |
-| `taxonomy/分类库导出_形式_*.json` | 形式 | 565 路径 | 同上 |
+---
 
-> ⚠ **主 Agent 绝对隔离原则**:上述所有分类树文件和查询脚本均**只对子 Agent 开放**。主 Agent 在整个流程中**绝对不要直接 Read 它们,也绝对不要直接调用 `taxonomy-lookup.py`**!主 Agent 唯一的职责是运行物理切片脚本 `prepare-subtask.py` 并分发 `Agent` 任务,以此彻底杜绝主 Agent 发生 Context 膨胀或违背隔离架构手动通关。
+## 目录里有什么
 
-### Templates · 渲染模板 ([templates/](templates/))
+### 操作流程(extraction/ —— 分三阶段,按阶段读)
 
-| 文件 | 用途 |
-|---|---|
-| [templates/workflow.template.json](templates/workflow.template.json) | `workflow.json` 填充骨架 (多工序 `procedures:[]`). 复制到 `outputs/case-{N}/workflow.json` 后填 `<填:...>` 占位符, 各 phase in-place Edit, Phase 3 跑 `spec/tools/render-case.py --workflow` 校验+渲染 |
-
-### Tools · 工具脚本 ([tools/](tools/))
+| 文件 | 内容 | 什么时候读 |
+|---|---|---|
+| [extraction/phase1-skeleton.md](extraction/phase1-skeleton.md) | 第一阶段:搭骨架(判断有几个工序 / 切步骤 / 连数据流);含第一阶段字段说明 | 第一阶段 |
+| [extraction/phase2-normalize.md](extraction/phase2-normalize.md) | 第二阶段:归类标注 + 填目的列;含第二阶段字段说明 | 第二阶段 |
+| [extraction/phase3-finalize.md](extraction/phase3-finalize.md) | 第三阶段:检查 + 渲染出网页 | 第三阶段 |
 
-Agent 跑提取时**通过 Bash 调用**的脚本. **Agent 不需要 Read 这些脚本源代码**, 接口手册见 [tools.md](tools.md).
+### 格式契约(format/)
 
-| 工具 | 用途 |
+| 文件 | 内容 |
 |---|---|
-| [tools/taxonomy-lookup.py](tools/taxonomy-lookup.py) | 实质/形式 词表查询 (阶段二 2B 用) |
-| [tools/render-case.py](tools/render-case.py) | case_data → HTML 渲染 + JSON Schema 校验 (阶段三用) |
-| [tools/renderer.py](tools/renderer.py) | render-case.py 内部 import 的渲染主模板 (**Agent 不要 Read 源码**, 通过 render-case.py 间接调用) |
-| [tools/styles.css](tools/styles.css) + [tools/script.js](tools/script.js) | renderer 注入到 HTML 的样式 + 交互. 视觉规范见 [format/procedure-table.md](format/procedure-table.md), 实施以这两文件为准 |
+| [case-data.schema.json](format/case-data.schema.json) | **给机器看的字段清单**(必填项/可选值的最终裁判) |
 
----
-
-## 三语言协作原则
+### 分类词表(taxonomy/ —— 作用/动作/类型 三个受控词表)
 
-本目录内不同类型内容按读者类型分语言:
-
-| 语言 | 负责 | 文件示例 | 谁读 |
+| 文件 | 维度 | 规模 | 怎么用 |
 |---|---|---|---|
-| **JSON** | 结构化定义 (字段 / 受控词表 / 树结构) | `taxonomy/*.json`, `format/case-data.schema.json` | 程序 + LLM (直接 import 当 context) |
-| **Python** | 程序性校验 + 规则定义 (lint, 路径合法性) | `taxonomy/validate.py` (TBD), `tools/taxonomy-lookup.py` | 程序 + 程序员 |
-| **Markdown** | 内容定义 (设计动机 / 边界判断 / 跨模块关系 / narrative) | 本目录绝大多数文件 | 人 + LLM (吸收 narrative context) |
+| [effect.json](taxonomy/effect.json) | 作用 | 9 个词 | 第二阶段读,把每步的作用对上 |
+| [action.json](taxonomy/action.json) | 动作 | 30+ 个词 | 同上 |
+| [type.json](taxonomy/type.json) | 类型 | 50 个词 | 同上;自造类型写进 `workflow.json` 的 `type_registry` |
+| [type_suggestions.md](taxonomy/type_suggestions.md) | 新类型登记 | 只增不改 | 第三阶段跑 `lint-case.py` 时**工具自动登记**,不用手写 |
 
-数据流单向: JSON (ground truth) → Python (import + 加规则) → MD (人写, 解释 why). 不三方互改
+> **实质/形式 没有词表**:第二阶段直接提炼,不查词表
 
-> 当前只有 `taxonomy/` 完全实施了三语言分工; `syntax.md` / `extraction/` / `format/` 是纯 markdown 规范, 内部尚未做 JSON/Python 抽离 — 这些内容主要是 prose, 没有需要程序消费的结构.
+### 工具(tools/)
 
----
+[tools.md](tools.md) 是各脚本(批量改 / 渲染 / 检查)的**接口手册**。脚本本身**不用读源码**,会用就行;渲染网页的样式(`renderer.py`/`styles.css`/`script.js`)也不用碰。
 
-## Agent 自驱加载指南 (累积式)
+---
 
-> **本节是给 Agent 看的执行手册**. Agent 是 self-driven — 没有 Driver 显式切 phase, 按下面顺序自行加载 + 自行判断转移. 关键原则: **context 累积, 已读不要再读**.
+## 操作流程
 
-**总览** (单一中间产物 `workflow.json`, Phase 1.2 起 in-place Edit 演化, 不写多个快照):
+整个流程围绕**一个文件 `workflow.json`** 滚动演化——从第一阶段搭好骨架,后面每阶段都在它上面**就地补字段**,不另存新文件。
 
 ```
-[阶段一] 骨架提取 ── 主 Agent 全程在场
-           1.1 心智模型 (多工序判断)  → understanding.md
-           1.2 步骤切片 + 单步骨架     → Write workflow.json
-           1.3 跨步引用闭合 (anchor)   → Edit workflow.json
-[阶段二] 归一化标注 ── fan-out 2 子 Agent, 都 Edit workflow.json
-           2A 作用/动作/类型归一化 (字典树整进 context)
-           2B 实质/形式 匹配 (走 taxonomy-lookup.py)
-           2C case-specific type 注册 → procedures[i].type_registry
-[阶段三] 检查收尾 ── 主 Agent 调脚本
-           3.1 render-case.py --workflow → HTML
-           3.2 lint-case.py --workflow   → type 完整性
-           3.3 写 case-N-<slug>.md (md-structure §11)
+第一阶段 · 搭骨架
+   1.1 读懂案例, 判断有几个工序   → understanding.md
+   1.2 切步骤 + 填单步骨架        → 写出 workflow.json
+   1.3 把步骤间的数据流连起来      → 改 workflow.json(补"来源/去处")
+第二阶段 · 归类标注
+   · 作用/动作/类型 归到分类词表
+   · 实质/形式 直接提炼元素点(不查词表)
+   · 自造类型登记 → 写进 type_registry
+   · 每步填目的列(intent)
+第三阶段 · 检查收尾
+   · 跑 lint-case.py 检查
+   · 跑 render-case.py 渲染出网页
 ```
 
-### 起手 (只做一次)
+### 起手(只做一次)
 
-读本 README **一遍**, 之后**永远不要再 Read 本文件**. 你需要 phase 细节时直接读 phase 对应的 spec 模块, 不要回来翻 README.
+把本文读**一遍**,之后**别再回头读它**——需要某阶段细节时直接读对应的阶段文件。再把 [tools.md](tools.md) 读一遍(后面要调的脚本接口都在那),也别重读。
 
-也请把 [`tools.md`](tools.md) 读一遍 — 你后续要调的外部脚本接口都在那, 之后**不要重读**。
+### 重要:读过的文件别重复读
 
-### 🛑 绝对禁止重复读取 (ZERO REPEATED READS RULE)
-由于 Context 是持续累积的,**你读取过的所有文件(README.md, tools.md, phase2-normalize.md 等)内容会永远保留在你的 Context 记忆中**。
-请**绝对不要**再次调用 `Read` 读取它们!重复读取会导致巨大的 Token 浪费与回合预算超限。
-- **严禁**:因为看到 spec 里写了 `详见 [tools.md §2]` 就去重复 `Read(file_path="spec/tools.md")`。
-- **严禁**:因为进入了 Phase 2B 就去重复 `Read(file_path="spec/extraction/phase2-normalize.md")`。
-- 检索你的前置 Turn 历史,直接从记忆中查找对应规格!
+上下文是累积的,**你读过的文件内容会一直留在记忆里**。**不要**因为某处写了"详见 tools.md"就又去读一遍;**不要**进了第二阶段又去重读阶段文件。需要时从记忆里翻,别重复 Read——那会白白浪费预算。
 
-### Phase 1 · 骨架提取 (新增加载)
+### 第一阶段 · 搭骨架(新读这些)
 
-工作: 通读 case 原文 → 建立工序心智模型 → 切片 → 抽骨架 → 闭合引用.
+要做的事:通读案例 → 想清楚有几个工序、每个工序怎么走 → 切步骤 → 填骨架 → 把数据流连起来。
 
-| 必读 (尚未读过) | 用途 |
+| 该读(还没读过的) | 干嘛用 |
 |---|---|
-| [`syntax.md`](syntax.md) | DSL 概念模型 + 字段语义 |
-| [`extraction/fields.md`](extraction/fields.md) | 23 字段定义 + 推断补全标记 (三阶段共享) |
-| [`extraction/control-flow.md`](extraction/control-flow.md) | 控制流 → block/nested 建模 (循环/并行/分支怎么表达, **必读** — 切片时就要会) |
-| [`extraction/phase1-skeleton.md`](extraction/phase1-skeleton.md) | 阶段一执行 (1.1/1.2/1.3 骨架提取 + 多工序判断) |
-| [`format/md-structure.md`](format/md-structure.md) | .md 产物结构 (后面要按这个写) |
-| `input/case-{N}-raw.json` (case 原文) | 你的工作素材 |
-
-Phase 1 结束累积: **~30-50k context**
-
-产物 (写到 `outputs/case-{N}/`):
-- `understanding.md` (1.1 心智模型, 含多 procedures 判断)
-- `workflow.json` (1.2 **Write** 骨架: 顶层 `procedures: [{id, name, purpose, declarations, steps}]`, 之后 1.3 **Edit** 加 anchor)
+| [extraction/phase1-skeleton.md](extraction/phase1-skeleton.md) | 第一阶段具体怎么做 + 字段填写规则 |
+| `input/case-{N}-raw.json` | 案例原文(你的素材) |
 
-转移条件: workflow.json 自检通过 (引用闭合 / 命名归一 / 类型一致) → 进 Phase 2.
+产物(写到 `outputs/case-{N}/`):`understanding.md`(想清楚有几个工序)+ `workflow.json`(先 Write 骨架,再 Edit 补"来源/去处")。
+过关条件:workflow.json 自查通过(数据流都连上了、类型一致)→ 进第二阶段。
 
-⚠ **新工作流**: 中间产物从原来"5 个 JSON 快照" → **1 个 workflow.json + understanding.md**. 各 phase 都 in-place Edit workflow.json (不写新文件). 减少冗余 + 降低 LLM 长 JSON 输出错误率.
+### 第二阶段 · 归类标注(新读这些)
 
-### Phase 2 · 归一化 + 标注 (新增加载)
+要做的事:把"作用/动作/类型"归到分类词表;把"实质/形式"直接提炼成元素点;填每步的目的列。
 
-工作: 归一化 作用 / 动作 / 类型 (查字典树) + 实质 / 形式 (走 `spec/tools/taxonomy-lookup.py` 查外部词表).
-
-| 新增 Read | 用途 |
+| 新读 | 干嘛用 |
 |---|---|
-| [`extraction/phase2-normalize.md`](extraction/phase2-normalize.md) | 阶段二 2A + 2B 执行细节 |
-| [`taxonomy/effect.json`](taxonomy/effect.json) | 作用树 + 边界判断 (节点 `分类说明`) |
-| [`taxonomy/action.json`](taxonomy/action.json) | 动作树 + 边界判断 (节点 `分类说明`) |
-| [`taxonomy/type.json`](taxonomy/type.json) | 类型树 + 边界判断 (节点 `分类说明`) |
-| [`taxonomy/type_suggestions.md`](taxonomy/type_suggestions.md) | 跨 case 累积的类型升级提案 (Read 一遍知道格式; 走 §2A 候选→extends 桥接时 **append** 一条) |
-
-**不要 Read**:
-- 已读: 全部 Phase 1 list (`syntax.md`, `extraction/fields.md`, `extraction/control-flow.md`, `extraction/phase1-skeleton.md`, `format/md-structure.md`, README, tools.md)
-- 永远不要: `分类库导出_*.json` (词表太大, 走 `spec/tools/taxonomy-lookup.py` query — 接口见 tools.md)
-
-Phase 2 结束累积: **~40-60k** (并行子 Agent 各自: 2A ~8-15k, 2B ~5-10k)
-
-产物:
-- `outputs/case-{N}/workflow.json` (**Edit** 加 effect/action/type/feature/control + substance/form + procedures[i].type_registry)
+| [extraction/phase2-normalize.md](extraction/phase2-normalize.md) | 第二阶段怎么做 |
+| [taxonomy/effect.json](taxonomy/effect.json) / [action.json](taxonomy/action.json) / [type.json](taxonomy/type.json) | 三张分类词表 |
 
-⚠ **不写新文件** — Phase 2 是 Read workflow.json + Edit 加字段 in-place. 不要 Write 重写整个 JSON.
+产物:在 `workflow.json` 上 **Edit**(或用 `wf-patch.py`)补 作用/动作/类型 + 实质/形式 + 自造类型登记 + 目的列。**不要另存新文件**。
+过关条件:每步的作用/动作都命中标准词、每个类型要么命中词表要么登记了挂靠、每步该有的实质/形式都提炼好、每步都有目的列 → 进第三阶段。
 
-转移条件: 每个 step 的 effect/action 命中字典树叶子 + 每个 IO item 的 substance/form 走 `spec/tools/taxonomy-lookup.py --validate` 通过 → 进 Phase 3.
+### 第三阶段 · 检查 + 渲染(新读这些)
 
-### Phase 3 · 收尾 + 渲染 (新增加载)
+要做的事:跑检查 → 渲染出网页(脚本自动组装,不另存中间文件)。
 
-工作: 跑 lint + 渲染 HTML (脚本自动) + 写 .md (Agent). renderer 内存组装 case_data 直接渲染, 不落盘中间 JSON.
-
-| 新增 Read | 用途 |
+| 新读 | 干嘛用 |
 |---|---|
-| [`extraction/phase3-finalize.md`](extraction/phase3-finalize.md) | lint 清单 + 目的列填法 |
-| [`format/procedure-table.md`](format/procedure-table.md) | 工序表创作规范 (字段语义 + intent + chip 视觉 + 审美) |
-| [`format/case-data.schema.json`](format/case-data.schema.json) | workflow.json 的契约 (顶层 procedures 数组, 每 procedure 含 declarations/steps/type_registry) |
-
-Phase 3 结束累积: **~50-78k**
+| [extraction/phase3-finalize.md](extraction/phase3-finalize.md) | 检查清单 + 脚本命令 |
+| [format/case-data.schema.json](format/case-data.schema.json) | 字段的机器清单(最终裁判) |
 
-工具调用:
+脚本命令:
 ```bash
-# 1. lint + 自动 record 新 type (轻量, 不卡 exit)
+# 1. 检查 + 自动登记新类型(轻量, 不卡流程)
 python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N}
 
-# 2. 渲染 HTML (renderer 内存组装 case_data, 不落盘)
+# 2. 渲染网页(脚本在内存里组装好数据直接出 HTML)
 python spec/tools/render-case.py \
     --workflow outputs/case-{N}/workflow.json \
     --source-input input/case-{N}-raw.json \
@@ -216,20 +151,15 @@ python spec/tools/render-case.py \
     --out outputs/case-{N}/case-{N}-<slug>.html
 ```
 
-产物:
-- `outputs/case-{N}/case-{N}-<slug>.md` (DSL 文本版, 你 Write)
-- `outputs/case-{N}/case-{N}-<slug>.html` (跑 render-case.py --workflow 自动生成)
-
-⚠ **Phase 3 不落盘中间 JSON** — renderer 在内存组装 case_data = workflow.json + source-input merge + page_title + case_id, 直接渲染.
+产物:`outputs/case-{N}/case-{N}-<slug>.html`(唯一产物)。
 
-### 自查清单 (每次 Read 前)
+### 每次 Read 前自查
 
-- [ ] 这个文件**之前读过吗**? 如果读过, 不要再 Read (context 累积, 重读浪费 5-15% budget)
-- [ ] 我只是想确认某概念**有没有提过**? 用 Grep, 不要 Read 完整文件
-- [ ] 我只是想看**目录里有啥**? 用 Glob, 不要 ls 后再 Read
-- [ ] resume 后: 用户**改过**的产物 (understanding.md / workflow.json) **要重读**; spec 不变, 不要重读
-- [ ] 想知道某外部脚本接口? 看 [`tools.md`](tools.md) (已读), 不要去 Read 脚本源码
+- 这个文件**之前读过吗**?读过就别再读。
+- 只想确认"提没提过某概念"?用 Grep,别整篇 Read。
+- 只想看"目录里有啥"?用 Glob。
+- 中断后接着做:用户**可能改过**的产物(understanding.md / workflow.json)要重读;spec 没变,不用重读。
 
-### 转移失败处理
+### 卡住了怎么办
 
-任一 phase 的转移条件不过 → **不要硬进下一 phase**. 回当前 phase 修产物再自查. 重做 2 次还过不去 → 在产物里挂 `inferred: true, inferred_reason: "lint 反复不过, 需人工审"` 标记, 再向下推进.
+某阶段的过关条件过不去 → **别硬闯下一阶段**,回当前阶段修。修两次还过不去 → 在产物里挂个 `inferred: true, inferred_reason: "反复过不去, 需人工看"` 标记,再往下走。

+ 0 - 51
examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/control-flow.md

@@ -1,51 +0,0 @@
-## 控制流与结构建模 (workflow.json)
-
-> 源里出现**循环 / 并行 / 分支 / 抽样 / 多返回**时,**不要拍平成单个标记步** —— 用 workflow.json 的 block/nested 结构把这套"程序结构"如实表达出来。schema + renderer 都支持,渲染成带层级的工序表。`kind` / `control` / `group` 在 **Phase 1.2 切片**时定,anchor 在 **1.3 闭合**。
-
-### 控制块 = `kind:block` 父步 + `kind:nested` 子步
-
-源里的 `遍历 / 并行 / 分支` 是一个**控制块**:
-- 父步 `kind:block` + `control:遍历|并行|分支`,`via` 用 `-`(块不调工具)
-- 块体里每一步 `kind:nested` + `group=父步id`;id 用点号(父 `s5` → 子 `s5.1`)
-- **块本身带自己的 `inputs/outputs/intent`** —— 表达"高层意图"(这个循环整体在做什么),子步表达"每次具体执行"
-
-`遍历` 完整例子(对应原 DSL 文本 `遍历 场景 ∈ 分镜序列: { 分镜图 = @采样(n=4){生成图像(...)}; 分镜图列表.追加(分镜图) }`):
-
-```json
-{
-  "id": "s5", "kind": "block", "control": "遍历", "via": "-",
-  "intent": "遍历每个场景生成分镜图",
-  "inputs":  [{"type": "分镜脚本", "name": "分镜序列", "anchor": "← s4.分镜序列"}],
-  "outputs": [{"type": "分镜图",   "name": "分镜图列表", "anchor": "→ s6"}]
-}
-{
-  "id": "s5.1", "kind": "nested", "group": "s5",
-  "via": "nano_banana", "action": "生成/元素生成", "effect": "主体生成",
-  "inputs":  [{"type": "提示词", "name": "场景提示词", "anchor": "← 分镜序列[i]"},
-              {"type": "参考图", "name": "主角图",   "anchor": "← 分镜图列表[-1]"}],
-  "outputs": [{"type": "分镜图", "name": "分镜图",    "anchor": "→ 分镜图列表.追加"}],
-  "instruction": [["decorator", "@采样(n=4, pick=人工)"]]
-}
-```
-
-### 容器与索引 (走 `anchor` 字符串)
-
-- 循环取元素:input anchor `← 分镜序列[i]`(正索引)/ `← 分镜图列表[-1]`(取上一项,做链式参考)
-- 累加进容器:output anchor `→ 分镜图列表.追加`
-- 取子部分(属性访问):`← s1.正向提示词.人物`(引用某变量的子块 / 字段,而非整体)
-- 普通上下游:`← sN.var` / `→ sN`
-
-### caller-side 修饰 (抽样 / 重试 / 缓存)
-
-不改动作本身,挂在 step 的 `instruction` 里:
-- `["decorator", "@采样(n=4, pick=人工)"]` —— 抽 N 个候选按策略挑一个;`pick` ∈ `人工 / judge_fn / first`
-- `@重试(max=3)` / `@缓存` / `@限流`(留 placeholder)
-
-### 多返回值
-
-一步产出多个东西 → 多个 `outputs[]` 项(如 反推提示词 同时出 `正向` + `负向` 两个 `type:提示词`),不要合并成一项。
-
-### 边界
-
-- 控制流 minimal:无 exception / continuation / coroutine;分支用 `control:分支`。
-- 一个 step 自己就是控制(非块,无子步)时可直接挂 `control`,不强制建块;但**有循环体 / 并列体时务必展开成 block + nested**,别拍平成单标记步。

+ 0 - 136
examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/fields.md

@@ -1,136 +0,0 @@
-## 提取字段定义与标注约定 (三阶段共享)
-
-> 本文是**跨阶段共享的字段引用** —— 每行 23 个字段的语义 + 推断补全标记约定。Phase 1 起手加载,之后累积在 context;phase2/3 填字段(effect/action/type/substance/form/intent)时都依据本表。各字段在哪个 phase 填,见 [README](../README.md) 加载指南。
-
-### 推断补全标记 (重要)
-
-抽取时, 主 Agent **必须补全自然语言中的逻辑疏漏** — 主要指**原文未列出但工艺必经的输入 / 输出**.
-
-> 典型场景: 某一步实际需要中间产出 A 和 B, 但原始帖子只提到了 A; 抽取时要补出 B, 并显式标注它是推断来的.
-
-> ⚠ **`inferred` / `inferred_reason` 只能标在 step 的 IO item 上 (`steps[].inputs/outputs[]`)**, **不要标在 `declarations.inputs/resources/returns` 上** —— schema 的 DeclareItem 是 `additionalProperties:false`, 只收 `type/name/desc`, 加 inferred 会校验失败. 工序级声明若是推断的, 把推断说明写进 `desc`, 或在对应的 step IO 上标 inferred.
-
-**两种推断标记方式** (按粒度):
-
-#### A. IO 级 (主要场景, 推荐) — 标在 IO item 上
-
-整个 input / output item 是推断补全的 (源文本完全没列, 但工艺需要):
-
-```python
-{
-    'id': 's5', 'kind': 'step',
-    'via': 'human',
-    'action': '生成/关系生成/数组生成',
-    'inputs': [
-        {
-            'substance': '...', 'form': '...',
-            'type': '参考图', 'name': '主角图',
-            'value': '<AI 生成的人物肖像静态图: 中景特写, 年轻亚洲女性...>',
-            'anchor': '← s2.主角图',
-            'inferred': True,  # ← 整个 IO item 是推断的
-            'inferred_reason': '原文方法 3 只说"自己写动作", 没明示主角图是输入; 但写动作序列需要主角图作角色 context, 属工艺补全',
-        },
-    ],
-    # ...
-}
-```
-
-#### B. field 级 (次要场景) — 标在 step.inferred_marks dict
-
-某个字段值是推断的, 但所属 IO item 本身源文本已列出 (如工具名未指名只给 generic 占位):
-
-```python
-{
-    'id': 's2',
-    'via': '(AI 生图工具)',
-    # ...
-    'inferred_marks': {
-        'via': '原文用"AI 生图"未指名具体工具',
-    },
-}
-```
-
-**field_key 命名规则** (IO 级用 `inferred: True` 标在 item 上即可, 不用 field_key):
-- step 级字段: `'intent'` / `'effect'` / `'via'` / `'action'` / `'directive'` / `'config'` / `'decorator'` / `'memo'` / `'control'` / `'feature'`
-- IO 子字段 (仅在需要标某个 IO item 中特定字段时, 如 inferred 整 item 太重): `'in-substance-N'` / `'in-form-N'` / `'in-type-N'` / `'in-name-N'` / `'in-value-N'` / `'in-anchor-N'` (out-)
-
-#### C. 低置信度推断 — 留空 + 「推?」
-
-整个 IO item 标了 `inferred: True`, 但某个字段判断不出 (原文无线索, 工艺也没有强约束), **不要硬编值**. 把该字段设为 `None` 或不填即可 — 渲染时该 cell 显示空 + `推?` 角标 (vs. 高置信度的 `推`), hover 仍显示 `inferred_reason`.
-
-```python
-{
-    'id': 's7',
-    'inputs': [
-        {
-            'substance': '/表象/视觉/...',
-            'form': None,                       # ← 低置信: 形式不明, 留空
-            'type': '参考图',
-            'name': '主角图',
-            'value': None,                      # ← 低置信: 值不明, 留空
-            'anchor': '← s2.主角图',
-            'inferred': True,
-            'inferred_reason': '原文未说本步用什么参考; 可能是 s2 主角图也可能没用, 留空待人工确认',
-        },
-    ],
-}
-```
-
-**渲染规则**: cell 显示 `空 + 推?` 当且仅当 `(item.inferred=True 或 field 在 inferred_marks 中)` **且** 字段值为 `None/''`. 填了值则仍是普通 `推`. 这给读者明确信号 — "AI 知道这里该有东西但选择不猜", 既不是数据缺失也不是高置信补全.
-
-**何时用 C 而非 A**: A 是"原文没说但工艺必然" (高置信, 该补); C 是"原文没说且工艺也不必然" (低置信, 不该猜). 不确定就用 C, 不要为了消除"空 cell"硬填一个貌似合理的值.
-
-**可视化效果** (spec/tools/renderer.py 自动渲染):
-- 推断 cell 加「推」角标 (右上); 低置信留空的 cell 角标变成「推?」
-- hover 角标显示推断理由 (tooltip), 高 / 低置信用同一个 `inferred_reason` 字段
-- legend "高亮推断" 一键开关: body 加 `.show-inferred` 类, 所有推断 cell 加重底色 + 边框
-- IO 级推断: 整行 6 个 cell 同时染色, 一眼看出"这条输入 / 输出是补出来的"
-
-**何时标 vs 不标**:
-- ✓ **标 A (IO 级, 高置信)**: 原文未列的中间产出输入 / 必然输出 (如 s5 写动作时需要主角图作 context, 源未说)
-- ✓ **标 A (IO 级, 高置信)**: 源文本用了复数指代 ("这些知识库") 但具体列了一个, 补出其他的 (如 s4 加 人物库 + 运镜库)
-- ✓ **标 B (field 级)**: 工具未指名只给 generic 描述 (`(AI 生图工具)`)
-- ✓ **标 C (低置信留空)**: IO item 整体确定要标 inferred, 但内部某字段拿不准 — 留空比硬编更诚实
-- ✗ **不标**: 归一化标注 (实质 / 形式 / 作用 / 动作 / 类型 映射到 taxonomy) — 这是 Phase 2 的常规工作, 不属于"逻辑疏漏补全"
-- ✗ **不标**: 直接 paraphrase 原文 (原文已明示, 只是换了说法)
-- ✗ **不标**: prompt 文本细节缺失但已尽力描述 (这是 content extraction limitation, 不是 logical 补全)
-
----
-
-### 字段定义与提取指示 (canonical)
-
-抽取每一行 23 个字段时, 严格按下表语义填. **字段语义被反复误用是抽取阶段最大坑**: 把步骤说明塞进 `指令`, 把工具账户事实塞进 `配置`, 把分析评论塞进 `备注`, 把来源引用塞进 `值` 等. 此表为权威定义.
-
-#### 需求组 (3 列, 灰)
-
-| 列 | 含义 | 取值来源 | 提取规则 | 反例 |
-|---|---|---|---|---|
-| **#** (idx) | 步骤编号 | 顺序生成 | `s1` / `s2` / `s6.1` (块下嵌套用点号) | — |
-| **目的** (intent) | 这一步在做什么的简短自然语言句 | 该行其他 cells 的值 | 句中能 token 化的概念都做成 `{kind:value}` token (色底对应所引用的列, 见 procedure-table 目的列规则); 胶水文字 ≤ 8 字 | dataflow 公式; case-specific 简写 (锚/链); 变量名 token |
-| **作用** (effect) | 这一步在 AIGC 工序链中的位置 + 角色 | §A.1 字典树叶子 | 主 Agent 选最贴近叶子 (预处理/主体生成/装配/后期/工艺规约 等) | 自造词; 把动作当作用 (反推 ≠ 作用) |
-
-#### 数据流·输入 / 输出 (各 6 列, 黄 / 蓝, 输入输出**字段语义完全一致**)
-
-| 列 | 含义 | 取值来源 | 提取规则 | 反例 |
-|---|---|---|---|---|
-| **实质** (substance) | 数据内容是什么 (理念 / 表象 层面) | 外部词表 `分类库导出_实质_*.json` | 找最匹配的叶子路径; 不命中叶子选高层抽象 | 自由文本; 非合法路径 |
-| **形式** (form) | 内容怎么呈现 (呈现 / 架构 层面) | 外部词表 `分类库导出_形式_*.json` | 同上 | 同上 |
-| **类型** (type) | 领域语义类型 (按功能角色分类) | §A.3 字典树叶子 或 case-specific extends | 命中叶子优先; 否则用 case extends 桥接 | 不在字典树且无 extends 桥接的自造名 |
-| **变量名** (name) | 该步内的数据流标识 | case-specific 命名, 按内容含义起 | 同一概念在不同 step 必须用同一名 (lint: 命名归一) | 同名变量在不同 step 类型不一致 |
-| **值** (value) | **数据本身的内容** | 原文 / 上下文中的实际数据 | 文本数据写完整 prose; **关于内容本身的提示词**(如具体的画面描述、场景风格、角色特征、服装细节等)作为数据本身内容,**必须**在此回填;非文本数据用 `<整段描述>` 包起 | 含 meta ("同 sX:" / "(从 X 切出)" / "供后续复用" / "保连续" / "人工挑 1") — 这些归 anchor / decorator / memo / config; **与内容本身不相关的工具指令/工作流命令**(该归入指令列 ❌) |
-| **来源** (anchor, 输入) / **去处** (anchor, 输出) | 输入侧: 上游引用 + 容器索引; 输出侧: 下游去向 + 容器索引 | 上游 step output / declare / 字面量 / 下游 step | 输入: `← 工序输入` / `← sN.varname` / `← s6 (链, 上一张)` / `← 分镜序列[i]`; 输出: `→ s7` / `→ 视频片段列表.追加` / `→ 返回 短剧` | 描述内容 (那是 value); 描述用法 |
-
-> ⚠ **value 必须逐字回填数据本身, 禁止引用占位**: 即使某输入就是上游输出**原样透传** (anchor 已是 `← sN.x`), value 也要填该数据**全文**, 不能写「(同 sN 输出)」「见 sN」「← sN」这类引用 —— 那是 anchor 的活, value 写了占位等于丢内容 (directive 同理: 必须是实际喂给工具的 prompt 原文). **不想手抄 N 遍**: 只在源头 (sN 的 output) 填一次真值, 透传位置设好 anchor 后跑 `wf-patch.py --resolve-passthrough`, 工具顺 anchor 把源 value 逐字抄到所有透传 value/directive (见 [tools.md §2](../tools.md)). lint 会扫这类占位报警.
-
-#### 实现组 (8 列, 绿)
-
-| 列 | 含义 | 取值来源 | 提取规则 | 反例 |
-|---|---|---|---|---|
-| **外部工具** (via) | L1 canonical 工具名 | 工序作者指定 | `manus` / `nano_banana_pro` / `<llm-agent>` / `human`; 原文未指名用 `(generic 描述)` 占位 (如 `(AI 生图工具)`); 控制流块用 `-` | 描述性短语 (该归 directive) |
-| **动作** (action) | 工具的内容动作 kind | §A.2 字典树路径 | `提取/化学提取/反推`, `生成/元素生成`, `修改/增/添加`; 控制类已分流到 `逻辑控制`, 这里不放 | 自造动词 |
-| **指令** (directive) | **字面 prompt 文本** — 真正喂给工具的 prompt 字符串 | 原文中的 prompt 引文; 没引文则按工艺反推一段合理 prompt | 祈使句, 像直接复制粘贴的 prompt. 引号包裹原文 quote: `"反推这个视频的提示词, 拆解出 9 个维度: 审美/运镜/拍摄/..."`. **关于工具指令、流程控制、或者和生成内容本身没有直接关系的指示**(如 “反推提示词”、“请用 SD 进行重绘”、“比例 2:3”、“帮我生成图片:”等命令描述)作为实现手段,**必须**归入此列而非输入 value 列 | "上传文件, 让 manus 反推" (这是步骤说明 ❌); "智能体外层 prompt: 按..." (描述工艺逻辑 ❌); **纯画面内容描述词**(应归入输入数据流的值 value ❌). **人工 / 控制流 step 无 prompt, directive 应空** |
-| **配置** (config) | **工具运行参数** (单次调用可设的数值/枚举) | 工具 UI / API 参数 | 例: `{ 2K · 1:1 · 4 张 · 模式=智能参考 }` / `aspect=16:9, dur=12s` / `UI audio=开` | "免费配额: 免登录视频 4 / 图片 10" (账户层事实, 非运行参数 ❌, 该归 memo 或工序级 declarations); 描述性句子 |
-| **运行** (decorator) | **caller-side 调用修饰** — `@` 装饰器 | 工序作者添加 | `@采样(n=4, pick=人工)` / `@重试(max=3)` / `@缓存` / `@限流` | 工具本身参数 (那归 config); 描述工艺 |
-| **备注** (memo) | **其他列没承载的实现方式信息** — 工艺级 wisdom | 工艺经验总结 | (1) 经验性招法 trick: "动作不连贯时优先用上一张作链参考"; (2) 替代 variant 说明: "本 case 走方法 3 手写; 替代: 方法 1 让 manus 拆视频"; (3) 工具选型理由: "工具选型唯一硬约束: 必须免费"; (4) 适用条件 / 边界 / 已知坑 | "本步独立, 不进入主流程" (analytical commentary ❌); "原文: '...'" (溯源引文 ❌); "拆 3 维度的本质是 prompt 块复用" (analytical, 非实现方式 ❌); 工具账户层运营事实 (那是工序级别, 非本 step 实现) |
-| **逻辑控制** (control) | 本步的控制流类型 | 工艺分析 | `并行` / `遍历` / `分支` / `请求` / `等待`; 普通 step 留 `-`. **可在目的列引用** (`{control:并行}` 等), 因为控制流形塑步骤外观 | 把控制流塞进 `动作` 列 ❌; 把控制流塞进 `特性` ❌ |
-| **特性** (feature) | **执行特征** (仅) — 内部执行属性 | 工艺分析 | `随机` / `幂等` / `人工` / `本地` / `写外部` / `读外部`; 普通块 step 留 `-` | 混入控制流 (那归 `逻辑控制`) ❌; **目的列不允许引用 `{feature:X}`** (执行特征是内部属性, 不在用户面向描述里出现) |

+ 228 - 35
examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/phase1-skeleton.md

@@ -1,50 +1,243 @@
-## 阶段 · 骨架提取 (Phase 1)
+## 第一阶段 · 骨架
 
-> 整体三阶段流程 + 文件清单见 [README](../README.md) 的"加载指南 · 总览";字段定义 + 推断补全标记见 [fields.md](fields.md)。本文只讲阶段一执行。
+### 步骤
 
-主 Agent 不切换的理由: 切片决策、抽取的逻辑补全、跨步引用闭合三件事**认知耦合**, 同一份"工序心智模型"贯穿三步; 换 Agent 要重读源材料 + 重建模型, 浪费 context, 且易在切片/补全决策上不一致。
 
-| 子步 | 任务 | 关键产物 |
-|------|------|---------|
-| **1.1** | **思考分析 + 多工序判断** — 通读原文 (含图片) 建立心智模型: (a) **判断本 case 含几个独立工序** (单/多),  多工序时列出每个 procedure 名字 + 终态产物 + 大致步骤数 + 工艺类型; (b) 识别终态产物、外部工具依赖、隐含的工艺规约/预准备需求 | `understanding.md` (按 procedure 分章节) |
-| **1.2** | **步骤切片 + 单步骨架** — 一次 Write `workflow.json` 骨架. 顶层 `{procedures: [...]}`, 每个 procedure 含 `{id (e.g. p1-simple/p1), name, purpose, category, platform, author, declarations, steps}`. 每个 step 抽: id / kind / action (自然语言) / via / inputs[] / outputs[] (含 type/name/value, anchor 暂留空) / instruction / feature / control / intent / focus. 推断隐含 IO 标 `inferred: True, inferred_reason: "..."`. **effect/类型归一/substance/form 留到 Phase 2**, 不要在 Phase 1.2 就填. | `workflow.json` (Write 骨架版, 不含 anchor/effect/type/sub/form) |
-| **1.3** | **跨步引用闭合** (quality gate) — 给每个 IO.anchor 字段加引用: input.anchor=`← sN.var` / `← 工序输入` / `← 容器[i]`; output.anchor=`→ sN.var` / `→ 容器.追加`. 命名归一, 失败回 1.2 改 step. **几十处 anchor 用 `wf-patch.py --patch` 一次过** (见下), 不要写 Python 脚本批量塞. | `workflow.json` (wf-patch 加 anchor) |
+| 小步      | 做什么                                                                                                                                                                                       | 产出                          |
+| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
+| **1.1** | **读懂 + 判断有几个工序** —— 通读原文(含配图)想清楚:(a) 这篇案例里有**几条独立的做法**(一条还是多条);多条时,把每条的名字、最终产物、大概几步、属于什么工艺各列出来。(b) 认出最终产物、用到的外部工具、以及那些"没明说但少不了"的前置准备。                                                     | `understanding.md`(按工序分章节写) |
+| **1.2** | **切步骤 + 填单步骨架** —— 一次性写出 `workflow.json` 骨架                                                                                                                                               | `workflow.json`(骨架版)        |
+| **1.3** | **把数据流连起来** —— 给每个输入输出补上"来源/去处":输入写 `← 上游某输出的编号`(如 `← s2o1`)、`← 工序输入`、`← 某编号[i]`(循环里逐个取);输出写 `→ sN`、`→ 某列表.追加`。连完自查:每个输入引用的编号都能在前面找到对应输出。连错就回 1.2 改。几十处要连时用 `wf-patch.py` 一次过(见下),别写脚本硬塞。 | `workflow.json`(补好"来源/去处")  |
 
-**1.1 多工序的判断标准**
 
-⚠️ 判断与原文段落角色无关:不论原文把它定位为"案例示范"、"方法论说明"、"案例欣赏"还是"进阶玩法",只要满足下列三条,即为一个独立工序。**工序的识别单元是一条完整的输入→终态产出链,不是原文的章节结构。**
+---
 
-**扫描单元**:以原文中**每一张出现的成品图**(或明确描述的终态产物)为起点,逐一检查它是否有对应的独立输入→做法链条。有则记为一个候选工序,再用下列三条标准过滤。**不要以章节/段落为扫描单元。**
+## workflow.json 整体结构
 
-1. 有明确产出物:该步骤能产出一个可见结果(图片、素材、成品等)
-2. 有具体做法:该输入→输出链条中存在可操作的方法(Prompt、框架、流程步骤等)
-3. 产出物或做法有差异:与其他工序相比,产出物不同,或做法(框架/方法论)不同,两者满足其一即可;即便产出物类型相同(同为场景图、同为宣传图),只要 Prompt 文本不同,即视为不同工序,不得合并。
+一个 `workflow.json` 描述一篇案例,里面可以有一个或多个工序(比如一篇文章同时讲了"简单做法"和"进阶做法",那就是两个工序)。
 
-判断边界:
-- 同一输入→输出链条内部的中间步骤,归入该工序,不单独拆分(如:同一张海报的生成过程中,背景图生成是中间步骤而非终态产物)
-- 有终态产物但完全没有输入描述或做法描述(仅展示结果图)不算工序
-- 同类产出物但方法不同,算两个工序
-- 相似产出物 ≠ 同一工序:两张同类型的图(如都是冲锋衣场景图),只要生成它们的 Prompt 或方法有任何实质差异,必须拆为两个独立工序。不得以"产出物类型相同"或"方法论相似"为由合并。
+```
+{
+  "source":     原帖信息,            # 平台/作者/日期/标题/摘要;正文和配图由 --source-input 自动补
+  "procedures": [ 一个或多个工序 ]   # 只有一个工序时也用长度为 1 的数组
+}
+# page_title 不写进文件,由第三阶段 --page-title 命令传入
+```
 
-**1.2 的逻辑补全**: 原文常省略隐含输入/输出, 抽取者要主动补:
-- 工具领域知识 (生成模型必带 model checkpoint + LoRA + 采样参数; 召回必带索引依据; 视频生成必带主角图/分镜图作 reference)
-- 跨步 contract 推理 (下游用 X 但上游没产 → 漏抽?; 当前输出后续没消费 → 是否漏抽 inferred consumer?)
-- 工艺范式知识 (短剧 = 分镜图 → 视频片段 → 拼接; 建库 = 收集 + 入库 + 索引)
+每个**工序**长这样:
 
-补全的 IO item 标 `inferred: True, inferred_reason: "原文方法 3 只说..., 但工艺需要..."`, 让 review 阶段确认; 不要默默插入. 标记方式详见 [fields.md](fields.md) "推断补全标记"。
+```
+{
+  "id":           "p1",
+  "name":         工序名字,
+  "purpose":      一句话说明这个工序在做什么,
+  "category":     类别(产物创造 / 资产建设 / 自动化 / 分析 / 学习),
+  "platform":     平台,  "author": 作者,
+  "declarations": 这个工序需要哪些外部输入和长期资源,最后返回什么,
+  "type_registry": 这个工序自己造的类型词(没有可不写),第二阶段归类时填,
+  "steps":        [ 一步步的操作 ],
+  "return_row":   表格最后一行,写明最终交付什么(可不写)
+}
+```
 
-**1.2 控制流建模**: 源里有循环 / 并行 / 分支 / 抽样时, 切片要展开成 `block + nested` 结构 (不要拍平成单个标记步), 容器流走 anchor `[i]` / `.追加`。详见 [control-flow.md](control-flow.md)。
+---
 
-**1.3 闭合检查项**:
-- 每个 input 能 trace 到上游 output / declare / 字面量
-- 同名变量在不同 step 的 type 一致
-- 容器索引在合理范围 (`[i]` 在循环内, `[-1]` 指最近一项)
-- 锚/链关系正确
+## 第一阶段要填的字段
 
-**1.3 怎么批量加 anchor (重要)**: workflow.json 由你**直接演化, 绝不写 Python 脚本生成 / 批改它** (脚本拼 JSON 易踩转义坑把文件搞坏). 几十个 anchor 用 `wf-patch.py` 一次过:
-1. 写一份 patch 清单到 `_scratch/anchors.json` —— `[{"path":"p1.s1.inputs[0].anchor","value":"← s0.x"}, ...]`, **每条都是你的显式决策** (anchor 指向谁是语义判断, 不是机械映射);
-2. `python spec/tools/wf-patch.py --workflow workflow.json --patch _scratch/anchors.json`。
+每个工序填:`id` / `name` / `purpose` / `category` / `platform` / `author` / `declarations` / `steps`。
 
-工具负责安全写 JSON + 校验 anchor 格式 (非法整批不写), 你从不碰 JSON 序列化。零星单处改用 Edit 即可。完整路径语法见 [tools.md §2](../tools.md)。
+### 步骤级字段
+
+
+| 字段          | 什么意思          | 怎么填                                                                          | 别这样                       |
+| ----------- | ------------- | ---------------------------------------------------------------------------- | ------------------------- |
+| `id`        | 第几步           | `s1`、`s2`;控制块子步用点号 `s6.1`                                                    | —                         |
+| `kind`      | 步骤类型          | 普通步写 `step`;控制块用 `block` / `nested`(见下)                                      | —                         |
+| `via`       | 用了哪个具体工具/产品   | 写工具标准名:`manus`、`nano_banana_pro`、`human`(人工);原文没点名就括号占位 `(AI 生图工具)`;控制块写 `-` | 写一句话描述(那是 `directive` 的活) |
+| `directive` | 真正喂给工具的提示词/命令 | 把原文里的提示词原样引过来;"给工具的指示"(如"严格反推,别发挥"、"比例 2:3")也归这里;纯人工/控制块步留空                  | 把画面内容描述写进来(那是输入的 `value`) |
+
+
+### 输入 / 输出的字段
+
+
+| 字段         | 什么意思                | 怎么填                                                                         | 别这样                       |
+| ---------- | ------------------- | --------------------------------------------------------------------------- | ------------------------- |
+| `type`     | 这份数据是什么角色(参考图?提示词?) | 从类型词表里挑;词表没有就自造,但要在工序 `type_registry` 里说明它"算作"哪个标准词                         | 既不在词表、又没挂靠                |
+| `value`    | 数据内容本身              | 文字类完整写出;图片/视频用尖括号写描述 `<一张床上女性的人像>`                                          | 写"见上一步"这种引用;写"[图3显示]"这种说明 |
+| `anchor`   | 来源 / 去处             | 输入写来源:`← 工序输入`、`← s2o1`、`← s2o1[i]`(循环逐个取);输出写去处:`→ s7`、`→ 某列表.追加`、`→ 返回 X` | 在这里描述内容(那是 `value` 的活)    |
+| `id`(输出专属) | 输出的编号               | 工序内唯一,如 `s2o1`;只有一个输出时 `s2` 也行                                              | 重复编号                      |
+
+
+> ⚠ **值一定要写真实内容**:哪怕某个输入就是上一步输出原样传过来的,"值"里也要把内容**完整抄一遍**,不能写"(同上)""见 s2o1"。嫌麻烦的话:只在源头填一次真内容,其余地方把"来源"写对,然后跑一次 `wf-patch.py --resolve-passthrough`,它会顺着编号自动把内容抄过去。
+
+**输入不用编号**——没人会反过来引用一个输入。
+
+### 命名约定
+
+- 类型名用**中文**;工具品牌名用**英文标准写法**(`seedream_4_5`,不要写成 `ByteDance-Seedream-4.5`)。
+- 每个输出都要有编号(工序内不重复),供后续步骤按编号引用。
+- 自造的类型要挂靠:在工序的 `type_registry` 里写明它"算作"哪个标准词 + 一句说明,例如 `"主角图": {"extends": "参考图", "desc": "本案例的女主肖像"}`。
+
+---
+
+### 1.1 怎么判断"有几个工序"
+
+⚠ 跟原文的章节标题无关:不管原文把某段叫"案例示范"还是"进阶玩法",只要满足下面三条,就算一条独立工序。**判断的单位是"一条完整的 输入→最终产物 链",不是原文的段落结构。**
+
+**怎么扫**:以原文里**每一张出现的成品图**(或明确写出的最终产物)为起点,逐个看它有没有对应的"输入→做法"链条。有就记为一个候选工序,再用下面三条筛。**别按段落扫。**
+
+1. 有明确产物:这条链能产出一个看得见的结果(图、素材、成品)。
+2. 有具体做法:链条里有可操作的方法(提示词、框架、流程)。
+3. 产物或做法有差异:跟别的工序比,产物不同 **或** 做法不同,满足一条即可。哪怕产物类型一样(都是场景图),只要提示词不同,就算两个工序,**不能合并**。
+
+边界判断:
+
+- 同一条链内部的中间步骤,归进这条工序,不单拆(比如做海报时先生成背景图,背景图是中间步骤,不是独立工序)。
+- 只展示了成品、完全没讲输入和做法的,不算工序。
+- 产物类似但做法不同 → 算两个工序。**不能**因为"产物类型相同""方法论相似"就合并。
+
+### 1.2 哪些"没写出来"的要主动补
+
+真实教程经常会省略一些理所当然的中间产物。比如某步要"自己写动作序列",原文没提它得先有一张主角图当参考——但工艺上这张图必不可少。这种**该有却没写出来**的输入/输出,要主动补上并标注推断原因;某个字段实在判断不出就留空,**不要硬编一个假的**。
+
+原文常省略的几类:
+
+- **工具常识**:生成模型一般要带模型/参数;召回要有检索依据;视频生成要有主角图/分镜图当参考。
+- **前后对不上**:下游用到了 X 但上游没产出 X → 是不是漏抽了?某个输出后面没人用 → 是不是漏了使用它的步骤?
+- **工艺常识**:短剧 = 分镜图 → 视频片段 → 拼接;建素材库 = 收集 + 入库 + 建索引。
+
+补出来的输入输出标上 `inferred: true` 和原因(让后面复核),别悄悄塞进去:
+
+```json
+{
+  "type": "参考图",
+  "value": "<一张主角肖像>",
+  "anchor": "← s2o1",
+  "inferred": true,
+  "inferred_reason": "原文只说'自己写动作',没提主角图;但写动作序列需要它当角色参考"
+}
+```
+
+- ✅ **该补**:工艺上必然需要的中间产物;原文用了复数("这些素材库")但只列了一个,把其余补全。
+- ❌ **不用补**:归一化分类(那是第二阶段的常规活);只是把原文换个说法;原文细节确实没写全(那是信息缺失,不算"推断")。
+- ⚠ 推断标记只能加在**步骤的输入/输出**上,不要加在工序的 `declarations` 上(那里只收 `type`/`name`/`desc` 三个字段)。
+
+### 1.2 有循环/并行/分支怎么切
+
+原文里如果有"对每个 X 重复""同时做几个版本""分情况",切步骤时要展开成**控制块 + 子步**,别硬压成一个步骤:
+
+- **块本身**(`"kind": "block"`):`via` 写 `-`,块的输入输出表达"整个循环在做什么"。
+- **块里的每一步**(`"kind": "nested"`,并写上 `"group": "块的编号"`):编号带点号(块是 `s5`,子步就是 `s5.1`),表达"每一次具体怎么做"。
+
+```json
+{ "id":"s5", "kind":"block", "via":"-",
+  "inputs": [{"type":"分镜脚本","value":"...","anchor":"← s4o1"}],
+  "outputs":[{"id":"s5o1","type":"分镜图列表","value":"...","anchor":"→ s6"}] }
+{ "id":"s5.1", "kind":"nested", "group":"s5",
+  "via":"nano_banana", "directive":"按场景提示词生成,保持主角一致",
+  "inputs": [{"type":"提示词","value":"...","anchor":"← s4o1[i]"},
+             {"type":"参考图","value":"...","anchor":"← s5o1[-1]"}],
+  "outputs":[{"id":"s5.1o1","type":"分镜图","value":"...","anchor":"→ 分镜图列表.追加"}] }
+```
+
+- **循环里取数据**:来源写 `← s4o1[i]`(逐个取)、`← s5o1[-1]`(取上一次的产出,做"接力"参考)。
+- **往列表里攒结果**:去处写 `→ 分镜图列表.追加`。
+- **一步产出好几样东西**:就写好几个输出(每个都有自己的编号),别合并成一个。
+- 抽样、重试这类小修饰,直接写进 `directive` 里说明即可。
+
+### 1.3 连数据流时自查这几条
+
+- 每个输入的"来源"(`← 某编号`)都能找到已存在的输出编号,或是 `← 工序输入`、字面量。
+- 输入的类型,和它"来源"指向的那个输出的类型一致。
+- 循环索引用在合理位置(`[i]` 在循环里,`[-1]` 指最近一项)。
+- 接力/链式引用关系正确。
+
+### 1.3 怎么批量连(重要)
+
+`workflow.json` 由你**直接演化,绝不写 Python 脚本去生成/批改它**(脚本拼 JSON 容易踩转义坑、把文件弄坏)。几十处"来源/去处"用 `wf-patch.py` 一次搞定:
+
+1. 把要改的清单写到 `_scratch/anchors.json` —— `[{"path":"p1.s1.inputs[0].anchor","value":"← s0o1"}, ...]`,**每条都是你的判断**(连到哪个编号是语义决定,不是机械套用);
+2. 跑 `python spec/tools/wf-patch.py --workflow workflow.json --patch _scratch/anchors.json`。
+
+工具负责安全写 JSON + 检查格式(有一条不合法就整批不写),你从不直接碰 JSON 文本。零星单处改,用 Edit 就行。路径写法见 [tools.md](../tools.md)。
+
+### 1.3 内容自动抄写
+
+"来源"连好后,跑一次 `python spec/tools/wf-patch.py --workflow workflow.json --resolve-passthrough`。对那些"原样接收上游输出"的输入(来源是 `← 某编号`),你**不用手抄上游内容**——只在源头那个输出里填一次真内容,工具会顺着编号把它逐字抄到所有引用处("值"先留空即可)。**别把"(同上)"这种引用当最终内容留着**(检查会报)。
+
+### 输出格式要求
+
+复制下方模板改即可。
+
+```json
+{
+  "source": {
+    "platform": "<填:原文平台 e.g. wechat-gzh>",
+    "author":   "<填:原文作者>",
+    "date":     "<填:发布日期 e.g. 2026 上半年>",
+    "url":      "<填:原文 URL>",
+    "title":    "<填:原文标题>",
+    "excerpt":  "<填:摘要 1-3 句>"
+  },
+  "procedures": [
+    {
+      "id":       "p1",
+      "name":     "<填:工序名 e.g. 产品场景图生成>",
+      "purpose":  "<填:一句话目的>",
+      "category": "<填:产物创造|资产建设|自动化|分析|学习>",
+      "platform": "<填:平台>",
+      "author":   "<填:作者>",
+      "declarations": {
+        "inputs":    [{ "type": "<填:类型>", "name": "<填:声明名>", "desc": "<填:说明 (可选)>" }],
+        "resources": [],
+        "returns":   { "type": "<填:返回类型>" }
+      },
+      "steps": [
+        {
+          "id":        "s1",
+          "kind":      "step",
+          "via":       "<填:工具名 e.g. human / nano_banana / (AI 生图工具)>",
+          "directive": "<填:给工具的 prompt 文本 (可选;人工/控制流步留空)>",
+          "inputs": [
+            {
+              "type":   "<填:类型>",
+              "value":  "<填:数据内容本身>",
+              "anchor": "<填:← 工序输入 / ← s1o1>"
+            }
+          ],
+          "outputs": [
+            {
+              "id":     "s1o1",
+              "type":   "<填:类型>",
+              "value":  "<填:数据内容本身>",
+              "anchor": "<填:→ s2 / → 返回 X>"
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}
+```
+
+有循环 / 并行 / 分支时,用控制块写法(无则不需要):
+
+```json
+{
+  "id":   "s1",
+  "kind": "block",
+  "via":  "-",
+  "inputs":  [{ "type": "<填:类型>", "value": "<填>", "anchor": "<填:← 上游 id>" }],
+  "outputs": [{ "id": "s1o1", "type": "<填:类型>", "value": "<填:累积结果>", "anchor": "<填:→ sN>" }]
+},
+{
+  "id":    "s1.1",
+  "kind":  "nested",
+  "group": "s1",
+  "via":       "<填:工具名>",
+  "directive": "<填:给工具的 prompt (可选)>",
+  "inputs":  [{ "type": "<填:类型>", "value": "<填>", "anchor": "<填:← 被遍历序列 id[i]>" }],
+  "outputs": [{ "id": "s1.1o1", "type": "<填:类型>", "value": "<填:单次产出>", "anchor": "<填:→ 累积结果.追加>" }]
+}
+```
 
-**1.3 透传 value 自动回填**: anchor 闭合后, 跑 `python spec/tools/wf-patch.py --workflow workflow.json --resolve-passthrough`。原样透传的输入/directive (anchor `← sN.x`) 你**不用手抄上游 prompt 全文** —— 只在源头 step 的 output 填一次真值, 工具顺 anchor 把它逐字抄到所有透传位置 (`value` 留空或先写引用占位都行, 工具会替换)。**禁止把「(同 sN 输出)」这类引用占位当最终 value 留着** (lint 会报, 见 [fields.md](fields.md) value 行)。

+ 189 - 117
examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/phase2-normalize.md

@@ -1,125 +1,197 @@
-#### 阶段二 · 归一化与标注 (主 Agent fan-out 2 个子 Agent)
-
-**工作模式 (并行子 Agent 架构)**:
-为了彻底隔离重负载上下文(含 Base64 图片和 Phase 1 漫长推理历史)并最大化提取效率,**主 Agent 必须使用 `Task` 工具将 Phase 2 任务分流给 2 个并行的子 Agent**。
-* 主 Agent **绝对不要**自己去跑这几十次 `taxonomy-lookup` 查询和 `wf-patch` 校验。
-* **物理切片与图片分流**:主 Agent 在启动 Phase 2 时,必须先运行物理切片脚本:
-  ```bash
-  python spec/tools/prepare-subtask.py --workflow outputs/case-N/workflow.json --source input/case-N.json --out-dir outputs/case-N/_scratch
-  ```
-  该脚本会自动在 `outputs/case-N/_scratch` 目录下生成最小化的子任务定义文件 `task_2a.json` 与 `task_2b.json`。
-* **图片及数据无缝对齐**:为了让子 Agent 具备完美的上下文感知能力,`task_2a.json` 和 `task_2b.json` 不仅包含了精简的 IO 变量与步骤信息,还在根节点内置了当前 Case 的完整图集 `image_url_list`,并为每一个具体的 IO 变量对象级关联了其对应的 `related_images` 引用数组(如识别 `图05` 等关联图片)。
-* 子 Agent 采用极简 Context(2k tokens,不载入大图),只读取当前 `{case_dir}/_scratch/task_2a.json` 或 `task_2b.json`,跑完查询后只返回标准的 `patch_2a.json` 或 `patch_2b.json` 补丁内容。
-* 主 Agent 只负责运行切片脚本、唤醒子 Agent 并行作业,最后收集子 Agent 返回的补丁文件(或 patch 文本段),通过 `wf-patch.py --patch` 一体化应用落盘。
-
-**子 Agent 召唤机制与指令示范 (主 Agent 必看)**:
-在 `run_procedure_dsl.py` 环境中,我们已通过编程式(`agents` 字段)在 Claude SDK 中**预先注册**了两个常驻子 Agent 角色:
-1. `phase-2a-normalizer` (作用/动作/类型归一化专家)
-2. `phase-2b-matcher` (实质/形式词表精确匹配专家)
-
-主 Agent 在运行中可通过以下两种极其优雅的方式激活并分流任务:
-
-### 🟢 方式一:显式指定调用(推荐,指向性极强)
-直接在 prompt 里命令子 Agent 工作,或在 Tool call 中指定其名称调用:
-```json
-// 1. P2A 子 Agent 显式召唤示例:
-Agent(
-  subagent_type="Explore",
-  description="召唤 phase-2a-normalizer 专家处理 2A 任务",
-  prompt="请 phase-2a-normalizer 子 agent 立即读取 outputs/case-N/_scratch/task_2a.json 任务文件,结合 spec/ 里的 effect.json、action.json、type.json,为各步骤和 IO 变量完成作用/动作/类型归一化。完成后请在 outputs/case-N/_scratch/ 下写入标准的 patch_2a.json 并向我汇报具体修改项。"
-)
-
-// 2. P2B 子 Agent 显式召唤示例:
-Agent(
-  subagent_type="Explore",
-  description="召唤 phase-2b-matcher 专家处理 2B 任务",
-  prompt="请 phase-2b-matcher 子 agent 立即读取 outputs/case-N/_scratch/task_2b.json 任务文件,使用 spec/tools/taxonomy-lookup.py 工具查询词表,查出各 IO 变量最精准的 substance/form 路径。完成后请在 outputs/case-N/_scratch/ 下写入标准的 patch_2b.json 并向我汇报具体修改项。"
-)
-```
+## 第二阶段 · 归类标注
 
-### 🔵 方式二:自动触发(编程式 description 自动匹配)
-由于 SDK 在后台配置了 `AgentDefinition`,主 Agent 在发起一般的 prompt 对话时如果提到相关职责,Claude SDK 也会基于 descriptions 自动路由调用:
-```
-Use the phase-2b-matcher agent to run taxonomy lookup for task_2b.json and generate patch_2b.json
-```
+基于第一阶段产出的骨架,给每个步骤补充分类和标注字段。
+
+要补五样东西:
+
+1. **作用(effect)** —— 每步对到作用词表的一个标准词。
+2. **动作(action)** —— 每步对到动作词表的一条路径。
+3. **类型(type)** —— 每个输入输出对到类型词表;词表没有的自造词要"挂靠"。
+4. **实质 / 形式(substance / form)** —— **每步直接提炼几个元素点**。
+5. **目的列(intent)** —— 每步一句话概括,≤25 字,跨步骤一起看再填。
+
+### 起手:把三张分类词表读进来
+
+`taxonomy/effect.json`(作用)、`taxonomy/action.json`(动作)、`taxonomy/type.json`(类型)——三个都不大,整读;每个词条带 `分类说明` 帮你判断边界。读一遍即可,后面别重读。
+
+
+### 1. 作用(effect)
+
+每步"处在什么工艺环节"对到 effect.json 的一个标准词:工艺规约 / 预准备 / 预处理 / 主体生成 / 装配 / 后期 / 配套伴生 / 检验 / 交付。**必须命中**;实在对不上,说明第一阶段这步抽错了,回去改。
+
+❌ 别这样:自己造词;把"动作"当成"作用"——"反推"是动作不是作用。
+
+### 2. 动作(action)
+
+每步的动作(第一阶段写的大白话)对到 action.json 的路径,如 `提取/化学提取/反推`、`生成/元素生成`。
+
+❌ 别这样:自己造动词,不对到词表路径。
+
+### 3. 类型(type)——漏斗式,别跳步
+
+对每个输入输出的类型:
+
+1. **先列候选**:根据这份数据的内容,列 3-5 个候选类型词(覆盖不同抽象层:通用 + 具体 + 邻近)。
+   - 例:内容是"苏晚 25 岁女性肖像,卧室床上" → 候选 `[参考图, 主角图, 人物肖像, 人物参考, 分镜图]`。
+2. **匹配词表**(命中即停):
+   - 候选里有直接命中 type.json 标准词的(如"参考图")→ 用它。
+   - 都没命中、但某候选很贴近某个标准词 → 挑最近的标准词做"挂靠",在这个工序的 `type_registry` 里登记:`"主角图": {"extends": "参考图", "desc": "本案例的女主肖像"}`。⚠ 登记在 **procedure 顶层的 `type_registry`**,不要写在输入输出里面。
+3. **自查**:每个类型要么是标准词、要么在 `type_registry` 里有挂靠 + 说明。**不允许**写个自造词却不登记(第三阶段 `lint-case.py` 会抓出来)。
 
-这样:
-- 单一真理源, 没有 phase 间复制 → 零冗余
-- 主 Agent 只出并行分发与合并决策,极速降本 90%+,速度提升 10x
-- Resume 中断时看 workflow.json 里某 step 是否有 effect 字段就知道 Phase 2A 做没做
-
-##### 2A 子 Agent — 作用 / 动作 / 类型 归一化
-
-**context**: `workflow.json` + spec §A.1 (作用树, 9 叶) + §A.2 (动作树, 5 L1 + 控制) + §A.3 (类型树, 4 大类) + 现有 type_registry — 全部小, 整体进 context。
-
-**任务**:
-- **作用归一**: 每步的"在哪个工艺位置"映射到 §A.1 叶子之一 (工艺规约 / 预准备 / 预处理 / 主体生成 / 装配 / 后期 / 配套伴生 / 检验 / 交付)。必须命中, 不命中 = 抽错回 1.3
-- **动作归一**: 每步的 action 自然语言映射到 §A.2 树路径 (e.g. `提取/化学提取/反推`、`生成/元素生成`); 控制类 `控制/并行` `控制/遍历` 自动转到 `特性` 字段
-- **类型归一** (对每个 input/output 的 type, 走以下 funnel 不要省步骤):
-
-  1. **候选扩展**: 基于 IO 的 `name` + `value` 描述, 显式列出 **3-5 个候选 type 词** (不是只猜一个).
-     - e.g. value=`<图: 苏晚 25 岁年轻女性肖像, 卧室床上>` →
-       候选: `[参考图, 主角图, 人物肖像, 人物参考, 分镜图]`
-     - 候选要覆盖**不同抽象层**: 通用 (参考图) + 具体 (主角图) + 邻近 (分镜图), 让匹配有挑选余地
-
-  2. **字典匹配** (按优先级, 命中即停):
-     - **a. 命中 §A.3 字典树叶子**: 候选里有哪个直接命中叶子 (type.json `$leaves`)? 用它 (e.g. 候选含"参考图" → 命中)
-     - **b. extends 桥接**: 都没命中, 但有候选语义贴近某叶子 → 选最近 leaf 做 extends. **Edit workflow.json**, 在该 procedure 顶层加 `type_registry` 段 (每个 procedure 独立 type_registry, 单 case 多工序时不冲突). 格式:
-       ```json
-       // workflow.json (部分)
-       {
-         "procedures": [
-           {
-             "id": "p1-simple",
-             "name": "...",
-             "type_registry": {
-               "主角图": {"extends": "参考图", "desc": "case-specific 主角肖像"}
-             },
-             "steps": [ ... ]
-           }
-         ]
-       }
-       ```
-       ⚠ **不要只在 IO item 内 inline 写 extends 子字段** — renderer 走 procedure 顶层 `type_registry` 找, IO inline 字段它不读.
-
-  3. **不必手工写 type_suggestions.md**:
-     Phase 3 跑 `bin/lint-case.py --workflow` 时, 会自动扫每个 procedure 的 `type_registry` 把所有 case-specific entry record 到 `spec/taxonomy/type_suggestions.md` (幂等, 同 (type_name, case_id) 只写一次). 你**只要**保证 `procedure.type_registry` 每个 entry 含 extends + desc 就行, suggestions 文件让工具维护.
-
-  4. **lint 自查** (轻量自检, 真正校验由 Phase 3 lint-case.py 跑):
-     - [ ] 每个 IO 的 type 要么命中 §A.3 叶子 (type.json `$leaves`), 要么所在 procedure 的 `type_registry` 段里有该 type 的 extends + desc 项
-     - [ ] 走 2b 的所有新 type 都在对应 procedure 的 `type_registry` 段出现
-     - [ ] **不允许** type 字段写"自由名"但所在 procedure 的 `type_registry` 缺对应 entry — 这种 silent gap 会让 Phase 3 渲染 HTML 时 drawer metadata 全丢, Phase 3 lint-case.py 会捕捉到
-
-**输出**: **写回 workflow.json** (几十个字段批量用 `wf-patch.py --patch`, 见开头工作模式; type_registry 也能 `--set p1.type_registry.X.extends=...` 注册), 给每个 step 加 `effect / action / feature / control` 字段 + 给每个 IO 加 `type` 字段 (Phase 1.2 已有则归一, 没有则填). 不写新文件, 不写生成脚本.
-
-##### 2B 子 Agent — 实质 / 形式 匹配
-
-**context**: `workflow.json` 中所有 input/output 的 name + value + 上下文 + 调 `spec/tools/taxonomy-lookup.py` tool. 实质·形式 JSON 词表本身**不进 context**, 完全通过 tool 查询。
-
-**tool 接口**:
-```
-spec/tools/taxonomy-lookup.py --dim {实质|形式} --list-l2                  # 列二级路径
-spec/tools/taxonomy-lookup.py --dim {实质|形式} --subtree <path>           # 返回子树 (叶子 + alias)
-spec/tools/taxonomy-lookup.py --dim {实质|形式} --match "<tok1 tok2 ...>"  # 多 token 拆词聚合 (推荐用法)
-spec/tools/taxonomy-lookup.py --dim {实质|形式} --narrow "<tok1 tok2 ...>" # 层级下钻 (--match miss 兜底)
-spec/tools/taxonomy-lookup.py --dim {实质|形式} --validate <path>          # 校验路径存在
-```
 
-**任务** (对每个 input/output value):
-1. **从 value 抽 2-5 个 ≥2 字描述性 token**, 一次调用 `--match "tok1 tok2 tok3"` (空格分隔, tool 自动拆词聚合)
-   - 好例: value=`<图: 苏晚 25 岁年轻女性肖像, 卧室床上>` → `--match "年轻女性 卧室 床上 肖像"`
-   - 不要再一个个单 token 试错 — tool 内部已经做了拆词聚合 + coverage bonus
-2. **若 `--match` 返 (无匹配)** → 同 query 切 `--narrow` 走层级下钻 (按子树整体语义打分)
-3. 上面拿到 top 候选后, 用 `--subtree <候选>` 列叶子细节, 选最贴的
-4. `--validate <chosen_leaf>` 确认前再写回; 完全无法匹配 → `unmatched`
-5. 抽象容器/纯工具参数 → null (不标)
-   - ⚠ **警惕过度标注 null**:诸如 `产品需求`、`结构化提示词`、`分层提示词` 等文本,虽然物理形式上是“文本”,但它们在**实质(Substance)上承载了具体的业务内容**(例如:提示词若描述冲锋衣,实质即为 `/理念/知识/商业/产品服务/产品特征`;若描述登山场景,则为 `/理念/知识/商业/产品服务/使用场景`)。**它们决非纯工具参数**,必须为其匹配对应的实质路径。
-   - **仅有完全不含具体业务实体、纯粹的技术参数**(如逻辑判断布尔值、循环索引 `i`、纯控制流指令等)才允许设为 `null`。
+### 4. 实质 / 形式(substance / form)
 
-> ⚠ **避坑**: 不要把整段 value 描述塞进 `--match` (e.g. `--match "苏晚 25 岁年轻女性, 卧室床上, 湿发素颜"`),
-> 标点会被当 token 一部分干扰拆词. 提炼 2-5 个干净的描述性词组就够.
+对**每一步**,提炼出简短的名词:
 
-**输出**: **写回 workflow.json** (几十个 IO 批量用 `wf-patch.py --patch`, 见开头工作模式; substance/form 会自动走 taxonomy-lookup 校验, 设 null 传 `__null__`), 给每个 IO 加 `substance: /xxx/yyy` 或数组 `["/xxx/yyy", "/zzz"]` + `form: /xxx/yyy` 或数组 (或 null). 不写新文件, 不写生成脚本。对于复杂内容,推荐在 CLI 传入时用 `+` 连接多条路径 (如 `/表象/视觉/人物 + /表象/视觉/空间`),`wf-patch.py` 会自动校验并将其作为 JSON 数组保存至 `workflow.json` 中。
+- **实质**(`substance`):这一步的内容**本质上是什么**。填**简短名词**,一到几个词,如 `人物`、`视觉风格`、`古风背景`。❌ 不要写描述性长句,如"图片视觉风格(颜色、光影、质感)"→ 应改为 `视觉风格`。
+- **形式**(`form`):内容**怎么呈现**。同样填简短名词,如 `氛围感`、`古风`。没有明显形式特征可留空(null)。
+
+多个维度都重要时用顿号并列:`人物、古风背景`。纯技术性步骤(无业务内容,如纯循环/纯参数配置)两者均可留空。
+
+**关键:基于方法,不是基于举例。**
+
+提炼前先判断:这篇文章在讲**通用方法**,还是分享**一个具体案例**?
+
+- **通用方法文**:作者用古风美女举例,但讲的是"如何反推提示词"这套方法(可以用到任何图片)→ 实质填方法适用的宽泛范围(如 `图片`),形式可为 null。不要填 `古风美女`。
+- **具体案例文**:作者只是复盘自己这一次怎么做,没有暗示推广 → 实质填案例实际涉及的内容(如 `人物`、`古风`)。
+
+判断依据:文章有无"这个方法可以用于……""换个对象也能用"这类泛化表述?有 → 通用方法;没有、纯流水账 → 具体案例。如果完全判断不清,偏向宽泛,形式留空。
+
+### 5. 目的列(intent)——跨步骤一起看再填
+
+每步补一个 `intent`:一句话概括这一步在做什么,≤25 字。**跨步骤一起看**(为了让每行各有侧重,避免都写成一个模子),不要逐步孤立地填。
+
+写法规则:
+
+1. **像句人话**(≤25 字),读出来通顺。**别写成公式**(不要出现 `→`、`:` 这种符号串、不要 `A: B → C` 这种结构)。
+2. **关键词用 `{类别:值}` 标出来**,直接用这一行其他列已经有的值。中间可以加"用、把、到、和、得到、为参考"这类连接词。**别用只有你懂的简写**(锚、链、抽卡这种)。
+3. **同类的几个值各标各的**:写"得到 `{out-type:提示词}` 和 `{out-type:负向提示词}`",别揉成"得到正负 `{out-type:提示词}`"。
+4. **能用的类别只有 5 个**:`{effect:}`、`{via:}`、`{act:}`、`{in-type:}`、`{out-type:}`。类型必须带 `in-`/`out-` 前缀区分输入输出。
+5. **不要用变量名当标记**(`{in:参考视频}` ❌ → 改 `{in-type:参考视频}`);标的词必须在这一行真实出现过。
+
+例子:
+- ✅ 用 `{via:manus}` `{act:反推}` `{in-type:参考视频}`,得到 `{out-type:提示词}` 和 `{out-type:负向提示词}`
+- ✅ 以 `{in-type:参考图}` 和上一张 `{in-type:分镜图}` 为参考,`{act:元素生成}` 当前 `{out-type:分镜图}`
+- ❌ `{act:反推}: {in-type:视频} → {out-type:提示词}`(写成了公式)
+- ❌ 得到正负 `{out-type:提示词}`(揉成一个了)
+
+### 怎么落盘
+
+逐字段填用 `wf-patch.py`(它边写边校验作用/动作/类型,有错整批不写):
+
+```bash
+python spec/tools/wf-patch.py --workflow outputs/case-N/workflow.json \
+    --set 'p1.s1.effect=预处理' \
+    --set 'p1.s1.action=提取/化学提取/反推' \
+    --set 'p1.s1.inputs[0].type=参考图' \
+    --set 'p1.s1.substance=人物、卧室场景' \
+    --set 'p1.s1.form=特写构图、低光影调' \
+    --set 'p1.type_registry.主角图.extends=参考图' \
+    --set 'p1.type_registry.主角图.desc=本案例的女主肖像'
+```
+
+几十处一起改,把清单写到 `_scratch/patch2.json`(`[{"path":...,"value":...}, ...]`)再 `--patch` 一次过。**不要写 Python 脚本去拼/改 workflow.json。**
+
+过关条件:每步的作用/动作都命中标准词、每个类型要么命中词表要么登记了挂靠、每步该有的实质/形式都提炼好了、每步都有目的列 → 进第三阶段。
 
 ---
 
+## 完整 workflow.json 模板(第二阶段完成后)
+
+第一阶段已填字段以 `Phase 1` 注释标出;第二阶段新增字段带占位符。
+
+```json
+{
+  "source": {
+    "platform": "<Phase 1 填>",
+    "author":   "<Phase 1 填>",
+    "date":     "<Phase 1 填>",
+    "url":      "<Phase 1 填>",
+    "title":    "<Phase 1 填>",
+    "excerpt":  "<Phase 1 填>"
+  },
+  "procedures": [
+    {
+      "id":       "p1",
+      "name":     "<Phase 1 填>",
+      "purpose":  "<Phase 1 填>",
+      "category": "<Phase 1 填>",
+      "platform": "<Phase 1 填>",
+      "author":   "<Phase 1 填>",
+      "declarations": {
+        "inputs":    [{ "type": "<Phase 1 填>", "name": "<Phase 1 填>", "desc": "<Phase 1 填>" }],
+        "resources": [],
+        "returns":   { "type": "<Phase 1 填>" }
+      },
+      "type_registry": {
+        "主角图": { "extends": "参考图", "desc": "<填:case-specific 说明>" }
+      },
+      "steps": [
+        {
+          "id":        "s1",
+          "kind":      "step",
+          "effect":    "<填:作用词表叶子之一>",
+          "substance": "<填:自由提炼,如 人物、卧室场景,或 null>",
+          "form":      "<填:自由提炼,如 古风、特写构图,或 null>",
+          "via":       "<Phase 1 填>",
+          "action":    "<填:动作路径 e.g. 提取/化学提取/反推>",
+          "directive": "<Phase 1 填>",
+          "inputs": [
+            {
+              "type":   "<填:归一化后类型>",
+              "value":  "<Phase 1 填>",
+              "anchor": "<Phase 1 填>"
+            }
+          ],
+          "outputs": [
+            {
+              "id":     "s1o1",
+              "type":   "<填:归一化后类型>",
+              "value":  "<Phase 1 填>",
+              "anchor": "<Phase 1 填>"
+            }
+          ],
+          "intent": "<填:目的列,e.g. 用 {via:X} {act:Y} 从 {in-type:Z} 得到 {out-type:W}>"
+        }
+      ]
+    },
+    {
+      "id":       "p2",
+      "name":     "<填:第二工序名 — 此 p2 示范控制块写法。单工序删整个 p2>",
+      "purpose":  "<填:一句话目的>",
+      "category": "<填:类别>",
+      "platform": "<填:平台>",
+      "author":   "<填:作者>",
+      "declarations": {
+        "inputs":    [{ "type": "<填:类型>", "name": "<填:声明名>" }],
+        "resources": [],
+        "returns":   { "type": "<填:返回类型>" }
+      },
+      "steps": [
+        {
+          "id":   "s1",
+          "kind": "block",
+          "via":  "-",
+          "intent":  "<填:控制块整体在做什么>",
+          "inputs":  [{ "type": "<填:类型>", "value": "<填>", "anchor": "<填:← 上游 id>" }],
+          "outputs": [{ "id": "s1o1", "type": "<填:类型>", "value": "<填:累积结果>", "anchor": "<填:→ sN>" }]
+        },
+        {
+          "id":    "s1.1",
+          "kind":  "nested",
+          "group": "s1",
+          "effect":    "<填:作用叶子>",
+          "substance": "<填:自由提炼>",
+          "form":      "<填:自由提炼>",
+          "via":       "<填:工具名>",
+          "action":    "<填:动作路径>",
+          "directive": "<填:给工具的 prompt (可选)>",
+          "inputs":  [{ "type": "<填:类型>", "value": "<填>", "anchor": "<填:← 被遍历序列 id[i]>" }],
+          "outputs": [{ "id": "s1.1o1", "type": "<填:类型>", "value": "<填:单次产出>", "anchor": "<填:→ 累积结果.追加>" }],
+          "intent": "<填:这一次迭代在做什么>"
+        }
+      ]
+    }
+  ]
+}
+```

+ 24 - 24
examples/process_pipeline/script/search_eval/procedure-dsl/spec/extraction/phase3-finalize.md

@@ -1,30 +1,30 @@
-#### 阶段三 · 检查收尾 (主 Agent 调脚本)
+## 第三阶段 · 检查 + 渲染
 
-| 子步 | 任务 | 备注 |
-|------|------|------|
-| **3.1** | **lint + 渲染** — 跑两个命令: (a) `python spec/tools/lint-case.py --workflow outputs/case-N/workflow.json --case-id N` 校 type 完整性 + 自动 record 新 type 到 `spec/taxonomy/type_suggestions.md`; (b) `python spec/tools/render-case.py --workflow outputs/case-N/workflow.json --source-input input/case-N.json --page-title "Case N · 主题" --case-id N --out outputs/case-N/case-N-<slug>.html` 渲染 HTML (内存组装 case_data, **不落盘 case_data.json**) | lint 失败 → 主 Agent 看 stdout 决定回阶段二哪步重 Edit workflow.json |
-| **3.2** | **目的列填写** — **Edit workflow.json**, per step 加 `intent` 字段 (≤ 20 字自然语言). 跨 step 一次性填 (差异化需要跨步视图). 以已有结构化元素 (其他列) 作 `{kind:value}` token, 允许调整语序 + 少量胶水. 合法 kind: `{effect/via/act/control/in-type/out-type/in-sub/out-sub/in-form/out-form}`. **严禁变量名** (no `{in:X}` / `{out:X}`). **严禁引用特性列** (`{feature:X}` 不允许). **严禁 "X: Y → Z" 这种伪代码结构** | 不可子 Agent 化, 因为差异化判断需要跨步视图 |
-| **3.3** | **.md 落盘** — Write `outputs/case-N/case-N-<slug>.md` (DSL 文本版, 按 md-structure §11 结构) | Agent 写, 不脚本化 |
+> 前两阶段已经把内容都填进了 `workflow.json`,这里只做两件事:跑检查、渲染出网页。**产物只有网页(HTML)。**
 
-##### 阶段三 · lint 检查清单
+| 小步 | 做什么 |
+|------|------|
+| **3.1 检查 + 渲染** | 跑两个脚本:① `lint-case.py` 检查类型完整性、内容有没有偷懒写引用,并自动登记新类型;② `render-case.py` 渲染出网页(脚本在内存里组装数据,不另存中间文件)。检查报问题就回对应阶段改。 |
 
-最终产物必须满足以下规则, 任一失败 → 回阶段一对应步骤修:
+```bash
+python spec/tools/lint-case.py --workflow outputs/case-N/workflow.json --case-id N
+python spec/tools/render-case.py --workflow outputs/case-N/workflow.json \
+    --source-input input/case-N-raw.json --page-title "Case N · 主题" --case-id N \
+    --out outputs/case-N/case-N-<slug>.html
+```
 
-| 检查项 | 规则 | 失败示例 |
-|------|------|------|
-| **命名归一** | 同一概念在不同 step 用同一变量名 | "正向提示词" vs "提示词.正向" 混用 |
-| **类型一致** | 同名变量在不同 step 的 type 一致 | s1 的 `主角图: 参考图` 但 s5 写成 `主角图: 分镜图` |
-| **引用闭合** | 每个 input 能 trace 到上游 output / declare / 字面量 | 引用了 `s2.角色图` 但 s2 实际 output 是 `s2.主角图` |
-| **容器索引合法** | `[i]/[i+1]/[-1]` 在循环或合理位置内 | 在非 loop 内引用 `[i]` |
-| **值 vs 来源分离** | `值` 列**不能**只放 `← sN.x` 这种来源引用 (来源信息归 `来源` 列). `值` 必须是数据本身的描述/字面量 (允许 "(同上游) ...short excerpt..." 形式) | 值=`← s1.正向提示词` ❌ → 值=`(同上游) "中景特写..."` + 来源=`← s1.正向提示词` ✓ |
-| **值不允许截断** | `值` 列即使内容长, 也要 CSS 多行换行完整展示, 不允许 `text-overflow: ellipsis` / `overflow: hidden` 截断. 引文带省略号 ("...") 必须是源材料本身就截断, 不是 UI 截断 | UI 强制裁掉 prompt 文本结尾 ❌ |
-| **值是内容本身, 非元描述** | `值` 列写**数据本身的内容**, 不写 "[图 N 显示]" / "原文: ..." 等溯源/元数据. **文本数据** (提示词/分镜脚本/描述 等) 直接写完整 prose 内容 (生动详尽, 不加任何包裹标记); **非文本数据** (视频/图像/音频) 无法在 cell 中直接嵌入, 用 `<整段描述用尖括号括起>` 标识 (注意: 是**整段**包在 `<...>` 内, 不是 `<描述>` 前缀). **值列写数据内容本身, 不写 `[视频]/[图像]` 这种载体标签** | "`[图 2 显示] 含 ...`" ❌; "`<描述> AI 生成 10s 视频`" ❌ (是 `<描述>` 前缀格式); "提示词内容: `一个中景特写的年轻亚洲女性, 坐在低光的卧室床上, 湿长发素颜雀斑, 缓慢举手机...`" ✓ (文本直接写); "视频内容: `<AI 生成的 10s 视频, 床上女性举手机场景, 含 AI generated 水印>`" ✓ (整段括起) |
-| **目的列以结构化元素为骨架** | 简短自然语言 (≤ 20 字). **尽量直接使用已有的结构化元素** (其他列的值) 作为 token; 允许少量胶水文字 (动词 / 连接词) 串联. 多个同列值要独立 token, 不用胶水词合并. 合法 kind: `{effect/via/act/control/in-type/out-type/in-sub/out-sub/in-form/out-form}` (in-/out- 区分输入输出, 自动染色). 严禁变量名 token; 严禁引用特性 (`{feature:X}` ❌); 严禁 dataflow 公式 | "`{act:反推}: {form:景别} → {form:纪实}`" ❌ (公式); "得到正负 `{out-type:提示词}`" ❌ (胶水词合并); "得到 `{out-type:提示词}` 和 `{out-type:负向提示词}`" ✓ (2 个独立 token) |
-| **作用 / 动作 命中字典树** | `作用` 必须是 §A.1 L3 叶子; `动作` 必须是 §A.2 树路径 | `作用:开端` ❌ (不在树里) |
-| **类型命中字典树或 extends** | `类型` chip 必须是 §A.3 叶子, 或 case 自定义但 `extends` 一个叶子 | `类型:小品` ❌ → 需补 `extends 视频成品` |
-| **case-specific type 完整性** (调 `spec/tools/lint-case.py` 自动校验) | 跑 `python spec/tools/lint-case.py --workflow outputs/case-N/workflow.json --case-id N` — 输出"type 完整性: N 个提示" 时, 表示有 IO 用了 case-specific type 但该 procedure 的 type_registry 漏注册 / 缺 extends / 缺 desc. 工具同时会把所有 procedure.type_registry 里的 case-specific entry 自动 record 到 `spec/taxonomy/type_suggestions.md`. Agent 看 stdout 决定是否回 Phase 2 Edit workflow.json 补 type_registry | lint-case 输出 `[p1-simple] step[1].outputs[0].type='主角图' 是 case-specific 但 type_registry 没注册` → 回 Phase 2 Edit workflow.json 在 p1-simple.type_registry 加 `主角图: {extends:"参考图", desc:"..."}`, 重跑 lint |
-| **实质·形式 路径合法** | 调 `spec/tools/taxonomy-lookup.py --validate <path>` 校验; 不命中标 `unmatched` 待人工审 | `/视觉/人物` ❌ (缺 L1 顶层) |
-| **指令归类正确** | 工具组的 4 个子列各司其职: `指令`=directive 文本片段; `配置`=工具运行参数 (采样/cfg/aspect/...); `运行`=caller-side decorator (`@采样` 等); `备注`=**其他结构化字段没能包含的实现方法信息** (经验性招法 / 替代 variant / 选型理由 / 适用条件 等). data 端用单一 kind `('memo', txt)`. 不混 | 把采样参数放到 `指令` 列 ❌; 备注里写"原文: ..."这种溯源 ❌ (备注是工艺信息, 非引文) |
+### 收尾检查清单
 
----
+下面每条都要过,过不去就回对应步骤改:
 
+| 检查 | 规则 | 反面例子 |
+|------|------|------|
+| **输出编号唯一** | 每个输出都有编号,且工序内不重复 | 两个输出都叫 `s2o1` |
+| **数据流连得上** | 每个输入的"来源"(`← 某编号`)都能找到已存在的输出编号(或 `← 工序输入`、字面量) | 引用了 `← s2o9` 但根本没有这个编号 |
+| **类型对得上** | 输入的类型,和它"来源"指向的那个输出的类型一致 | 输入写 `分镜图` 但来源那个输出是 `参考图` |
+| **循环索引合理** | `[i]`/`[-1]` 用在循环里或合理位置 | 不是循环却用了 `[i]` |
+| **"值"写真内容** | "值"写数据本身(文字写全文;图片视频用 `<整段描述>`);不写 `← sN` 引用、不写 `[图N显示]` 这种说明 | 值 = `← s1o1`;值 = `<描述>开头的` |
+| **作用/动作命中词表** | 作用是 9 个标准词之一;动作是动作词表里的路径 | 作用写成"开端"(词表里没有) |
+| **类型命中词表或挂靠** | 类型是词表里的词,或自造但在本工序 `type_registry` 里写了"算作"哪个标准词 | 类型写"小品"却没说挂靠 `视频成品` |
+| **自造类型登记齐全**(脚本自动查) | 跑 `lint-case.py`,若提示"类型完整性 N 个问题",说明有自造类型没在 `type_registry` 登记 / 缺挂靠 / 缺说明 → 回去补 | `s1 输出的 type='主角图' 是自造但没登记` |
+| **"目的"列规范** | ≤25 字一句话;标记取自本行真实有的值;合法类别 5 个;别写成公式 | `{act:反推}: {in-type:视频} → {out-type:提示词}`(写成公式了) |

+ 33 - 92
examples/process_pipeline/script/search_eval/procedure-dsl/spec/format/case-data.schema.json

@@ -132,46 +132,39 @@
 
     "Step": {
       "type": "object",
-      "description": "One row group in the 25-column procedure table. Renders to N <tr> where N = max(len(inputs), len(outputs), 1). The dictionary-tree fields (effect/via/action/feature/control) MUST hit canonical leaves per spec §A. NOTE: kind=block 是控制容器, 只带 control + intent + via='-' + feature='-' + io; effect/action/focus 由其下 kind=nested 执行步承担 (见下方 allOf 条件: 仅 step/nested/atom 要求 effect/action/focus).",
-      "required": ["id", "kind", "via", "feature", "inputs", "outputs", "intent"],
+      "description": "One row group in the 14-column procedure table. Renders to N <tr> where N = max(len(inputs), len(outputs), 1). effect/action MUST hit canonical leaves per spec §A; substance/form are STEP-LEVEL taxonomy paths (whole step's content, not per-IO). kind=block is a control container (effect/action/substance/form may be omitted; carries intent + via='-' + io); kind=nested/step are execution steps.",
+      "required": ["id", "kind", "via", "inputs", "outputs", "intent"],
       "additionalProperties": false,
       "properties": {
         "id": {
           "type": "string",
-          "pattern": "^(s\\d+(\\.\\d+)*|a\\d+)$",
-          "description": "Step id. Plain step / block / nested use 's' prefix (block children dotted, e.g. 's3.1'); atoms use 'a' prefix (e.g. 'a1') scoped under their parent step."
+          "pattern": "^s\\d+(\\.\\d+)*$",
+          "description": "Step id. Plain step / block / nested use 's' prefix (block children dotted, e.g. 's3.1')."
         },
         "kind": {
-          "enum": ["step", "block", "nested", "atom"],
-          "description": "step=plain; block=control-flow parent; nested=child of a block; atom=experimental dimensional projection (only used in case1)."
+          "enum": ["step", "block", "nested"],
+          "description": "step=plain; block=control-flow parent (grouping container); nested=child of a block."
         },
         "group": {
           "type": "string",
           "description": "When kind=nested, the parent block's id (e.g. 's3')."
         },
-        "parent_step": {
-          "type": "string",
-          "description": "When kind=atom, the host step's id."
-        },
-        "name": {
-          "type": "string",
-          "description": "Only meaningful for kind=atom (displayed above the intent text)."
-        },
-        "key_dim": {
-          "type": "string",
-          "description": "atom-only: the dimension this atom projects (e.g. '实质' / '形式')."
-        },
-        "key_value": {
-          "type": "string",
-          "description": "atom-only: the specific path within the key_dim (e.g. '/表象/视觉/.../形象呈现')."
-        },
-
         "effect": {
           "enum": [
             "预处理", "主体生成", "装配", "后期",
             "工艺规约", "预准备", "配套伴生", "检验", "交付"
           ],
-          "description": "§A.1 L3 leaf. Required to hit a leaf — non-leaf = extraction error."
+          "description": "§A.1 L3 leaf. Required on step/nested — non-leaf = extraction error."
+        },
+        "substance": {
+          "type": ["string", "array", "null"],
+          "items": { "type": "string" },
+          "description": "STEP-LEVEL. What this step's content IS (理念 vs 表象 layer). Path from `分类库导出_实质_*.json`. Single path string, array of path strings, or null."
+        },
+        "form": {
+          "type": ["string", "array", "null"],
+          "items": { "type": "string" },
+          "description": "STEP-LEVEL. How this step's content is PRESENTED (呈现 vs 架构 layer). Path from `分类库导出_形式_*.json`. Single path string, array of path strings, or null."
         },
         "via": {
           "type": "string",
@@ -180,37 +173,12 @@
         "action": {
           "type": "string",
           "pattern": "^[^/]+(/[^/]+)*$",
-          "description": "§A.2 path, e.g. '生成/元素生成', '提取/化学提取/反推'. Control-flow already routed to `control` field."
+          "description": "§A.2 path, e.g. '生成/元素生成', '提取/化学提取/反推'."
         },
-        "feature": {
+        "directive": {
           "type": "string",
-          "enum": ["随机", "幂等", "人工", "本地", "写外部", "读外部", "-"],
-          "description": "Execution attribute (internal). Block-level steps use '-'. NEVER referenced in intent column."
-        },
-        "control": {
-          "type": "string",
-          "enum": ["并行", "遍历", "分支", "请求", "等待", "", "-"],
-          "description": "Control-flow kind. Typically on kind=block; may appear on a regular step that itself is a control. Empty string or '-' = no control flow (kept for atom rows and plain steps that explicitly set the field)."
-        },
-
-        "instruction": {
-          "type": "array",
-          "description": "Heterogeneous list of (kind, text) tuples. Order is preserved; any subset of kinds is allowed; control-flow blocks usually only carry memo entries.",
-          "items": {
-            "type": "array",
-            "prefixItems": [
-              {
-                "enum": ["directive", "config", "decorator", "memo"],
-                "description": "directive=literal prompt text; config=tool runtime params; decorator=caller-side @decorator; memo=engineering wisdom not captured elsewhere."
-              },
-              { "type": "string" }
-            ],
-            "items": false,
-            "minItems": 2,
-            "maxItems": 2
-          }
+          "description": "字面 prompt 文本 — 真正喂给工具的 prompt 字符串. 人工/控制流 step 无 prompt 时省略或空串."
         },
-
         "inputs":  {
           "type": "array",
           "items": { "$ref": "#/$defs/IOItem" }
@@ -219,81 +187,54 @@
           "type": "array",
           "items": { "$ref": "#/$defs/IOItem" }
         },
-
         "intent": {
           "type": "string",
-          "description": "≤ ~20 chars natural-language sentence. Tokens `{kind:value}` with kind ∈ {effect, via, act, control, in-type, out-type, in-sub, out-sub, in-form, out-form}. NEVER reference {feature:X}, NEVER use variable-name tokens, NEVER use 'X: Y → Z' pseudo-code."
+          "description": "≤ ~25 chars natural-language sentence. Tokens `{kind:value}` with kind ∈ {effect, via, act, in-type, out-type}. NEVER use variable-name tokens, NEVER use 'X: Y → Z' pseudo-code."
         },
         "focus": {
           "type": "array",
           "items": { "type": "string" },
-          "description": "Column-cell keys to highlight on this row. Format: bare key for step-level cells ('via', 'action', 'effect', 'idx', 'intent'), or '<col>-<io_index>' for IO cells ('in-type-0', 'out-substance-1', etc.)."
-        },
-
-        "inferred_marks": {
-          "type": "object",
-          "description": "Step-level field-by-field inference annotations (single cells, not whole rows). Maps column key → reason string. Used when only a specific field was filled by 工艺补全, not the whole row.",
-          "additionalProperties": { "type": "string" }
-        },
-
-        "atoms": {
-          "type": "array",
-          "description": "EXPERIMENTAL extension (case1-only). Dimensional projections of this step; each atom mirrors a Step shape with kind='atom' + parent_step + name + key_dim + key_value.",
-          "items": { "$ref": "#/$defs/Step" }
+          "description": "Column-cell keys to highlight on this row. Format: bare key for step-level cells ('via', 'action', 'effect', 'substance', 'form', 'idx', 'intent'), or '<col>-<io_index>' for IO cells ('in-type-0', 'out-type-1', etc.)."
         }
       },
 
       "allOf": [
         {
-          "if": { "properties": { "kind": { "enum": ["step", "nested", "atom"] } } },
-          "then": { "required": ["effect", "action", "focus"] }
+          "if": { "properties": { "kind": { "enum": ["step", "nested"] } } },
+          "then": { "required": ["effect", "action"] }
         },
         {
           "if": { "properties": { "kind": { "const": "nested" } } },
           "then": { "required": ["group"] }
-        },
-        {
-          "if": { "properties": { "kind": { "const": "atom" } } },
-          "then": { "required": ["parent_step", "name", "key_dim", "key_value"] }
         }
       ]
     },
 
     "IOItem": {
       "type": "object",
-      "description": "One row in inputs[] or outputs[]. Input and output items share the same shape (anchor points up for inputs, down for outputs).",
-      "required": ["type", "name", "value", "anchor"],
+      "description": "One row in inputs[] or outputs[]. Outputs carry an `id` (the 1:1 reference handle other steps point to); inputs reference an upstream output's id in their anchor.",
+      "required": ["type", "value", "anchor"],
       "additionalProperties": false,
       "properties": {
-        "substance": {
-          "type": ["string", "array", "null"],
-          "items": { "type": "string" },
-          "description": "What the content IS (理念 vs 表象 layer). Path from `分类库导出_实质_*.json`. Can be a single path string, an array of path strings, or null for abstract containers / pure tool params."
-        },
-        "form": {
-          "type": ["string", "array", "null"],
-          "items": { "type": "string" },
-          "description": "How the content is PRESENTED (呈现 vs 架构 layer). Path from `分类库导出_形式_*.json`. Can be a single path string, an array of path strings, or null when not applicable."
+        "id": {
+          "type": "string",
+          "description": "Short machine handle, unique within the procedure. REQUIRED on outputs (the reference target). Convention: 's<step>o<n>' (e.g. 's2o1'); single-output step may use 's<step>'. Inputs omit it. NOT a display column — surfaces only inside anchors."
         },
         "type": {
           "type": "string",
           "description": "§A.3 leaf or case-extended type name."
         },
-        "name": {
-          "type": "string",
-          "description": "Variable identifier within this step. Same concept across steps MUST use the same name (lint enforces this)."
-        },
         "value": {
           "type": "string",
-          "description": "Content itself. Text data: full prose, no wrappers. Non-text data: '<整段描述>' (the whole description angle-bracketed). NEVER metadata ('[图 N 显示]', '原文: ...') or upstream refs ('← sN.x' — those go in anchor)."
+          "description": "Content itself. Text data: full prose, no wrappers. Non-text data: '<整段描述>' (the whole description angle-bracketed). NEVER metadata ('[图 N 显示]', '原文: ...') or upstream refs ('← s2o1' — those go in anchor)."
         },
         "anchor": {
           "type": "string",
-          "description": "Inputs: upstream ref ('← 工序输入', '← sN.varname', '← 容器[i]'). Outputs: downstream destination ('→ sN', '→ 视频片段列表.追加', '→ 返回 X')."
+          "description": "Data-flow link by id. Inputs: upstream ref ('← 工序输入', '← s2o1' 指向某 output 的 id, '← s2o1[i]' 容器索引). Outputs: downstream destination ('→ s5', '→ 视频片段列表.追加', '→ 返回 X')."
         },
         "inferred": {
           "type": "boolean",
-          "description": "True when this whole IO item was filled by 工艺补全 (not in source material). Renderer dyes the entire row's 6 data-flow cells."
+          "description": "True when this whole IO item was filled by 工艺补全 (not in source material). Renderer dyes the row's data-flow cells."
         },
         "inferred_reason": {
           "type": "string",
@@ -319,7 +260,7 @@
         },
         "text": {
           "type": "string",
-          "description": "May contain inline HTML fragments (chip / name / em spans) — emitted verbatim into a colspan=24 cell."
+          "description": "May contain inline HTML fragments (chip / name / em spans) — emitted verbatim into a colspan cell."
         }
       }
     }

+ 0 - 43
examples/process_pipeline/script/search_eval/procedure-dsl/spec/format/md-structure.md

@@ -1,43 +0,0 @@
-### §11 .md 输出结构 (固定章节)
-
-按这个目录写, 顺序固定, 便于后续 dedup / 跨 case 比较。
-
-workflow.json 是 `procedures: [P1, P2, ...]` 模型。**多工序时按 procedure 分节**; **单工序时省略 P 层级** (见末尾兼容说明)。
-
-```
-# Case N: <主题>
-
-**Source / URL / 主题**
-
-## 工序梗概 (人话)
-### P1 · <工序名>
-### P2 · <工序名>
-## 引用的类型 (stdlib + 自定义)
-### stdlib 类型 (直接引用)
-### case-specific 类型 (type_registry)
-## L1 外部函数库
-## L2 抽象动作 + impl 关系
-## L3 工序模板
-### 模板 A:<名> (对应 P1)
-### 模板 B:<名> (对应 P2)
-## L4 工序实例
-### P1 实例 — <名>
-  - inputs (本次实际值)
-  - bindings (本次工具选择, `sN.via = ...`)
-  - extracted_values (本次中间产物 — prompt 原文回填)
-  - trace (timing / cost / retry_log, 可空)
-### P2 实例 — <名>
-  - (同上四子块: inputs / bindings / extracted_values / trace)
-## 这个 case 对 DSL 设计的关键启发
-```
-
-**分节规则** (多工序时):
-
-- **共享层不拆** (`L1 外部函数库` / `L2 抽象动作`): 外部函数、抽象动作跨工序复用, 整 case 一份, 不按 procedure 切分。
-- **按工序拆** (`工序梗概` / `L3 工序模板` / `L4 工序实例`): 每个 procedure 一个子节。**L3 模板与 L4 实例一一对应** (模板 A ↔ P1, 模板 B ↔ P2)。
-- **L4 实例的四子块** (inputs / bindings / extracted_values / trace) 落在**各 procedure 子节内部**, 不要跨工序拍扁挤在一起 — 拍扁会丢掉"哪个值属于哪个工序", 破坏跨 case 比较。
-- **引用的类型分两子节**: `stdlib 类型` (命中 §A.3 字典叶子的, 直接引用) + `case-specific 类型 (type_registry)` (走 `procedure.type_registry` 的 `extends` / `desc`)。
-
-**单工序兼容**: 只有一个 procedure 时, 省略 `### P1` 这层 —— `## 工序梗概` / `## L3 工序模板` 直接写正文, `## L4 工序实例` 底下直接写 inputs / bindings / extracted_values / trace 四子块。
-
-**extracted_values 是核心** — 把图里读到的 prompt 原文、工具配置、Shot 拆解、视频参数等**逐字回填**, 不要凭印象写。图里截断不全就标 `note: "图中文本截断, ..."`, 不要自补。

+ 0 - 329
examples/process_pipeline/script/search_eval/procedure-dsl/spec/format/procedure-table.md

@@ -1,329 +0,0 @@
-### 工序表 (procedure-table) 规范
-
-可视化页面是一个**单文件 HTML**, 含 inline `<style>` + `<table class="proc">` + `<script>` 交互。下面给出**结构规范** — 按此命名 + 交互填表即可。
-
-##### 模板与数据分离 (重要)
-
-可视化是 **共享模板 + per-case 数据**:
-
-| 文件 | 角色 | 内容 |
-|---|---|---|
-| `spec/tools/renderer.py` | 共享模板 (renderer) | CSS / JS / 渲染 helpers / 字典树 / build_html(case_data) 主入口 |
-| `spec/tools/render-case.py` | 渲染 + 校验 CLI | 接 `workflow.json` (`--workflow`), 内存组装 case_data + 跑 JSON Schema 校验, 调 renderer.build_html, 输出 HTML |
-| `tests/case-{N}/workflow.json` | per-case 数据 | 按 `spec/templates/workflow.template.json` 填; 顶层 `{source, procedures:[]}`, 每个 procedure 含 declarations / type_registry / steps / return_row. page_title 由 `--page-title` 提供 |
-| `tests/case-{N}/case-{N}-<slug>.html` | 生成产物 | 跑 `python spec/tools/render-case.py --workflow tests/case-{N}/workflow.json --source-input input/case-{N}-raw.json --page-title "..." --case-id {N} --out ...` 输出 |
-
-**case_data 结构** (build_html 输入契约 — renderer 由 workflow.json + `--source-input` + `--page-title` + `--case-id` 在内存组装):
-```python
-{
-    'page_title':    str,                   # 页面 <title> + h1 (来自 --page-title)
-    'case_id':       int | str | None,
-    'source':        {platform, author, date, url, title, excerpt},   # case 级原文 (折叠块), 跨所有 procedures 共享
-    'procedures':    [                                                 # 1 ~ N 个独立工序; 单工序也用长度-1 数组
-        {
-            'id':            str,                                       # 'p1' / 'p2' ...
-            'name': str, 'purpose': str, 'category': str, 'platform': str, 'author': str,   # 工序头部
-            'declarations':  {                                          # declare 块
-                'inputs':    [{type, name, default?, desc?}, ...],
-                'resources': [{type, name, desc?}, ...],
-                'returns':   {type, note?},
-            },
-            'type_registry': {<typename>: {...}},                       # 本工序 case-specific, 与 STDLIB_TYPE_REGISTRY 合并
-            'steps':         [{id, kind, effect, via, action, instruction, feature, inputs[], outputs[], intent, focus, group?}],
-            'return_row':    {arrow, text},                             # 该工序表底返回行
-        },
-        # ... 多工序再加 procedure
-    ],
-}
-```
-
-新增 case 流程: 复制 [`spec/templates/workflow.template.json`](../templates/workflow.template.json) → `tests/case-{N}/workflow.json` → 替换 `<填:...>` 占位符 (各 phase in-place Edit) → 跑 `python spec/tools/render-case.py --workflow tests/case-{N}/workflow.json --source-input input/case-{N}-raw.json --page-title "Case {N} · <主题>" --case-id {N} --out tests/case-{N}/case-{N}-<slug>.html`. 渲染主模板 `spec/tools/renderer.py` 由 render-case.py 内部 import, **Agent 不要 Read 它**. **唯一 canonical 模板是 `spec/templates/workflow.template.json`, 不要 Read 其他 `tests/case-*/` 下文件** — 那些是 case-specific 产物, 不是模板. 输入契约见 [`spec/format/case-data.schema.json`](case-data.schema.json).
-
-##### 页面结构 (从上到下)
-
-```
-<header class="page-header">     · 页面标题
-<details class="declarations">    · 工序头部 + declare 块 (折叠, 默认 open)
-<details class="source-block">    · 原文 (折叠, 默认 closed)
-<div class="legend">              · 列控制器 (4 个组的 toggle 按钮)
-<div class="table-wrap">          · 横向滚动容器
-  <table class="proc">            · 23 列工序表
-<aside class="drawer">            · 详情侧拉抽屉 (chip / 字典树点击)
-```
-
-##### 整体布局
-
-23 列 table, 2 行 thead, 4 个 group (需求 colspan=3 / 输入 colspan=6 / 实现 colspan=8 / 输出 colspan=6). 行 1 是 group 头, 行 2 是 sub 列细分.
-
-```
-[需求/灰 ───►]   [输入/黄 ────────►]                    [实现/绿 ────────────────►]                          [输出/蓝 ────────►]
-# / 目的 / 作用 / 实质 / 形式 / 类型 / 变量名 / 值 / 来源 / 外部工具 / 动作 / 指令 / 配置 / 运行 / 备注 / 逻辑控制 / 特性 / 实质 / 形式 / 类型 / 变量名 / 值 / 去处
-```
-
-列从左到右近似一个自然语言句: 「第 N 步 · 为了 X(目的) · 起 Y(作用) · 给定 Z(数据流·输入) · 由 W(外部工具) 做 K(动作) 用 D(指令) 控制 F(特性) · 得到 V(数据流·输出)」。**需求面/数据流 vs 工具组的分割**: 需求面 + 数据流 (实质/形式/类型/值/...) 描述"内容生产意图与素材", 工具组 (via/action/指令/特性) 描述"用工具怎么做"; prompt 必须按这条边界拆 — 内容描述部分进数据流的"值"列, 写给工具的 directive (e.g. "严格反推不要发挥") 与工具运行参数 (采样步数 / cfg / LoRA / aspect / 时长) 进工具组的"指令"列。
-
-列分组与模式归属:
-
-| 分组 | 列 | 内容性质 | 模式切换 | 底色 |
-|------|---|---------|---------|------|
-| 摘要句 (caller why) | `目的` | **selector + summarizer 摘要句** — 每行选最有信号的 2-3 维度组一句易懂话, 被选中的维度在本行内高亮 | 结构化模式整列隐藏 | 灰组 |
-| 结构化标签 (caller meta) | `作用` | 纯文本 (无 tag chip 装饰, 保留 data-prefix/value 供 drawer); 取值受字典树 §A.1 规范 | 自然语言模式整列隐藏 | 灰组 |
-| 数据流·输入 (始终) | `输入·实质` / `输入·形式` / `输入·类型` / `输入·变量名` / `输入·值` / `输入·来源` | 实质/形式 路径 (从外部 JSON 词表取) / type chip / name / flow + 字面量值 / 锚链或容器索引 | 实质·形式 列在自然语言模式整列隐藏, 类型 始终显示 | 黄组 |
-| 工具实体 | `外部工具` | L1 canonical 名 (e.g. `seedream_4_5`) 或占位 `<llm>` / `-` | 不参与模式切换 | 绿组 |
-| 工具动作 kind | `动作` | 纯标签值 (字典树 §A.2 叶子路径); 控制类 `控制/X` 已分流到 `逻辑控制`列 | 自然语言模式整列隐藏 | 绿组 |
-| 工具指令 | `指令` | **字面 prompt 文本** — 真正喂给工具的 prompt 字符串 (祈使句; 不是步骤说明) | 始终显示, 内部 `.natural` 子段可隐 | 绿组 |
-| 工具配置 | `配置` | 工具运行参数 (采样步数 / cfg / LoRA / 模型权重 / aspect / 时长 / 帧率) | 同上 | 绿组 |
-| 调用修饰 | `运行` | caller-side decorator (`@采样` / `@重试` / `@缓存` / `@限流` 等) | 同上 | 绿组 |
-| 备注 | `备注` (`memo`) | **其他结构化字段没能包含的实现方法信息**: 经验性招法 (如 "去 BGM" 双重保险) / 替代 variant 说明 / 工具选型理由 / 适用条件 / 已知坑. 数据端用单一 kind `('memo', txt)` | 同上 | 绿组 |
-| 逻辑控制 | `逻辑控制` (control) | 本步的控制流类型: `并行 / 遍历 / 分支 / 请求 / 等待`; 普通 step 留 `-`. 可在 intent 引用 (`{control:并行}`) | 同上 | 绿组 |
-| 工具特性 (纯执行特征) | `特性` | 执行特征 (`随机 / 幂等 / 写外部 / 读外部 / 人工 / 本地`); **不含控制流** (那归 `逻辑控制`列). intent 中不允许引用 (`{feature:X}` ❌) | 自然语言模式整列隐藏 | 绿组 |
-| 数据流·输出 (始终) | `输出·实质` / `输出·形式` / `输出·类型` / `输出·变量名` / `输出·值` / `输出·去处` | 同输入侧, `去处` 表达下游引用与容器索引 | 实质·形式 列在自然语言模式整列隐藏, 类型 始终显示 | 蓝组 |
-
-> **目的列是 selector + summarizer**: 不复读其他列的全部信息, 而是 selector 选这一行最差异化的 2-3 个维度 (默认信号: 主动作 / 实质或形式的关键变化 / 控制流特性), 用它们组一句易懂话; 被选中的格在它们各自列里加 `.row-focus` 加深底色高亮 (不用方框)。每行的"高亮形状"不同, 一眼能看出"这一步的关键在哪几格"。
->
-> **目的列内容规则 (重要)**:
->
-> 1. **形式**: **简短自然语言句** (≤ 25 字), 读出来像一句话。**严禁** 任何 dataflow / 伪代码痕迹: 不许出现 `→` / `:` 这类符号化连接, 不许 "X: Y → Z" 公式结构。
-> 2. **以结构化元素为骨架**: **直接使用其他列已有的结构化值** 作为 `{kind:value}` token, 自动获得对应底色; **允许动词 / 连接词等少量自然胶水** ("用 / 把 / 给 / 到 / 和 / 形成 / 得到 / 为参考 / 当前 / 上一张" 等) 串成连贯句; **严禁 case-specific 简写或 jargon** (如 "锚 / 链 / 抽卡 / 喂" 这种没在其他列出现的概念词)。
-> 3. **同行有多个相同列的值时, 各自做独立 token, 不用胶水词聚合**: 例如 s1 有两个输出 `正向提示词 (type=提示词)` + `负向提示词 (type=负向提示词)`, **不要**写 "得到正负 `{type:提示词}`" (合并 + 加"正负"胶水), **应该**写 "得到 `{type:提示词}` 和 `{type:负向提示词}`" (两个 type token 独立, 类型名本身已含"负向"语义)。
-> 4. **合法 kind** (色底完全对应所引用的列, **输入用黄, 输出用蓝, 实现用绿, 需求用灰**):
->
->    | kind | 引用列 | 底色 / 形状 |
->    |------|------|------|
->    | `{effect:XX}` | 作用 (需求组) | 灰 矩形 |
->    | `{via:XX}` | 外部工具 (实现组) | 浅绿 矩形 + 等宽字体 |
->    | `{act:XX}` | 动作 (实现组) | 绿 矩形 |
->    | `{control:XX}` | 逻辑控制 (实现组) — `并行/遍历/分支/请求/等待` | 浅青 矩形 |
->    | `{in-type:XX}` | 输入·类型 | **黄圆胶囊 chip** |
->    | `{out-type:XX}` | 输出·类型 | **蓝圆胶囊 chip** |
->    | `{in-sub:XX}` | 输入·实质 (叶子短名) | **黄矩形 tag** |
->    | `{out-sub:XX}` | 输出·实质 (叶子短名) | **蓝矩形 tag** |
->    | `{in-form:XX}` | 输入·形式 (叶子短名) | **黄矩形 tag 斜体** |
->    | `{out-form:XX}` | 输出·形式 (叶子短名) | **蓝矩形 tag 斜体** |
->
->    `type/sub/form` 必须带 `in-` / `out-` 前缀, 因为这些列在输入和输出组都有, 引用方向决定颜色 (同一个值如 `提示词` 作输入时黄, 作输出时蓝).
->
->    **`{feature:XX}` 不允许在 intent 中出现**: 特性 (随机/幂等/人工/读写外部/本地) 是步骤内部执行属性, 不是用户面向的描述要素; 写到 intent 中等于污染. 若必须表达"人工", 改用胶水词 "手写"/"人工" 或 `{via:human}` token.
-> 5. **严禁变量名 token** — `{in:参考视频}` / `{out:正向提示词}` ❌, 改用 `{type:参考视频}` / `{type:提示词}`。
-> 6. **token 内容必须能在该行实际 cell 中找到来源**, 不允许新造。
->
-> 示例:
-> - ✓ "用 `{via:manus}` `{act:反推}` `{in-type:参考视频}`, 得到 `{out-type:提示词}` 和 `{out-type:负向提示词}`"
-> - ✓ "把 `{in-type:提示词}` 按动作/人物/运镜 `{control:并行}` `{act:添加}` 到 `{out-type:提示词库}`"
-> - ✓ "以 `{in-type:参考图}` 和上一张 `{in-type:分镜图}` 为参考, `{act:元素生成}` 当前 `{out-type:分镜图}`"
-> - ✗ "`{act:反推}: {in-form:景别角度} → {out-form:纪实记录}`" (dataflow 公式)
-> - ✗ "`{in-type:提示词}` → `{out-type:提示词库}`" (用 `→` 符号化, 应改"到")
-> - ✗ "锚+链 `{act:元素生成}` 累积 `{out-type:分镜图}`" (case-specific 简写"锚 / 链 / 累积"读不懂, 应用真实结构化值)
-> - ✗ "得到正负 `{out-type:提示词}`" (用胶水词合并 2 个变量, 应拆成独立 token)
-> - ✗ "`{feature:人工}` 手写..." (feature 不能在 intent 引用; 改为胶水词 "手写" 或 `{via:human}`)
->
-> **作用/动作/特性 列只放标签值**: 无 `<span class="tag">` 灰底 chip 装饰, 无 `xxx:` 前缀。保留 `data-prefix` / `data-value` 属性以触发 taxonomy drawer。
->
-> **动作列纯标签值**: 只放 `动作:` kind 值 (e.g. `提取/化学提取/反推` / `生成/元素生成` / `控制/并行`)。块头的 ▼ 折叠箭头**放 `#` 列**, 动作列不挤。
->
-> **指令列内容范围**: (1) directive 文本片段 — 给工具的指令性 prompt 段落, 如"严格遵循源结构反推, 不要发挥"、"维持人物特征一致"; (2) 工具运行参数 — 采样步数 / cfg / LoRA / 模型权重 / aspect ratio / 时长 / 帧率 / `@采样(n=4, pick=人工)` 等。case-specific 字面量挂 `.natural` 类。
->
-> **数据流 IO 6 子列**: 输入侧 实质/形式/类型/变量名/值/来源; 输出侧 实质/形式/类型/变量名/值/去处. 每 step 多 IO 项时, 同列内 vertical 堆叠 (跨列位置对应)。
-
-`<thead>` (2 行, 行 1 是 4 个 group 头 colspan=3/6/8/6, 行 2 是 23 个 sub 列):
-```html
-<thead>
-  <tr>
-    <th colspan="3" class="col-group-demand">需求</th>
-    <th colspan="6" class="col-group-input">输入</th>
-    <th colspan="8" class="col-group-impl">实现</th>
-    <th colspan="6" class="col-group-output">输出</th>
-  </tr>
-  <tr>
-    <th class="col-idx">#</th>
-    <th class="col-intent">目的</th>
-    <th class="col-effect">作用</th>
-    <th class="col-in-substance">实质</th>
-    <th class="col-in-form">形式</th>
-    <th class="col-in-type">类型</th>
-    <th class="col-in-name">变量名</th>
-    <th class="col-in-value">值</th>
-    <th class="col-in-anchor">来源</th>
-    <th class="col-via">外部工具</th>
-    <th class="col-action">动作</th>
-    <th class="col-directive">指令</th>
-    <th class="col-config">配置</th>
-    <th class="col-decorator">运行</th>
-    <th class="col-memo">备注</th>
-    <th class="col-control">逻辑控制</th>
-    <th class="col-feature">特性</th>
-    <th class="col-out-substance">实质</th>
-    <th class="col-out-form">形式</th>
-    <th class="col-out-type">类型</th>
-    <th class="col-out-name">变量名</th>
-    <th class="col-out-value">值</th>
-    <th class="col-out-anchor">去处</th>
-  </tr>
-</thead>
-```
-
-> **数据流 vs 工具组视觉分割**: `col-effect` 右边界、`col-in-anchor`/`col-via` 之间、`col-feature`/`col-out-substance` 之间各加一条粗竖线 (`border-right: 3px solid #94a3b8`) 划分需求面 / 数据流·输入 / 工具组 / 数据流·输出 四段。
-
-##### 每个 step 一个 `<tr>` (示例骨架)
-
-输入组 6 列: 实质·形式·类型·变量名·值·来源. 输出组 6 列: 实质·形式·类型·变量名·值·去处. 实现组 8 列: 外部工具 · 动作 · 指令 · 配置 · 运行 · 备注 · 逻辑控制 · 特性 (`备注` = 其他列没能包含的工艺信息; `逻辑控制` = 并行/遍历/分支; `特性` = 仅执行特征如随机/幂等/人工).
-
-```html
-<tr class="step step-main" data-step="s1" data-focus="action,out-form-0,out-form-1">
-  <td class="idx">1</td>
-  <td class="intent">
-    <div class="intent-text">用 manus 反推参考视频, 得到 9 维 {type:提示词}</div>
-  </td>
-  <td class="effect" data-prefix="作用" data-value="预处理">预处理</td>
-  <td class="in-substance" data-prefix="实质" data-value="/表象/视觉/视频">/表象/视觉/视频</td>
-  <td class="in-form" data-prefix="形式" data-value="/呈现/视觉">/呈现/视觉</td>
-  <td class="in-type"><span class="chip" data-type="参考视频">参考视频</span></td>
-  <td class="in-name"><span class="name" data-var="参考视频">参考视频</span></td>
-  <td class="in-value"><span class="natural">&lt;10s 床上女性参考视频&gt;</span></td>
-  <td class="in-anchor"><span class="flow">← 工序输入</span></td>
-  <td class="via">manus</td>
-  <td class="action row-focus" data-prefix="动作" data-value="提取/化学提取/反推">提取/化学提取/反推</td>
-  <td class="instruction"><span class="natural">"严格反推视频的人物/场景/动作/运镜/光照/色调/风格, 不要发挥"</span></td>
-  <td class="feature" data-prefix="特性" data-value="随机">随机</td>
-  <td class="out-substance" data-prefix="实质" data-value="/理念/知识/具体内容">/理念/知识/具体内容</td>
-  <td class="out-form" data-prefix="形式" data-value="/架构/叙事">/架构/叙事</td>
-  <td class="out-type"><span class="chip" data-type="提示词">提示词</span></td>
-  <td class="out-name row-focus"><span class="name" data-var="正向提示词">正向提示词</span></td>
-  <td class="out-value"></td>
-  <td class="out-anchor"><span class="flow">→ s2 / s3</span></td>
-</tr>
-```
-
-> **输入侧 `来源` / 输出侧 `去处` 列**: 表达数据流的"上游引用 / 下游引用 + 容器索引". 输入: `← 工序输入` / `← sN.varname` / `← s6.分镜图列表[i]` / `← 分镜序列[i]`. 输出: `→ sN` / `→ 视频片段列表.追加` / `→ 返回 短剧`.
->
-> **实质/形式 取值**: 路径字符串 (e.g. `/表象/视觉/人物`, `/呈现/视觉/特写`), 来自外部 JSON 词表 (`分类库导出_实质.json` / `分类库导出_形式.json`). 详见 syntax §2.1 (实质/形式).
->
-> **推断补全可视化** (详见 上方 "推断补全标记" 章节): IO 级推断在 item 上标 `inferred: True, inferred_reason: "..."`, 整行 6 个 cell 自动加橙色虚线下划线 + 「推」角标 + tooltip; field 级在 step.inferred_marks dict 标. legend "高亮推断" 一键凸显所有推断 cell.
-
-##### 复合 step (块头) — 列对齐
-
-块头 (并行 / 遍历) 的 ▼ 折叠箭头放 `#` 列, 控制流 kind 已分流到 `逻辑控制` 列, 动作列展示父动作 (如 `修改/增/添加`) 或留空:
-
-```html
-<tr class="block-header" data-target="step-3">
-  <td class="idx"><span class="arrow">▼</span> 3</td>
-  <td class="intent">...</td>
-  <td class="effect" data-prefix="作用" data-value="工艺规约">工艺规约</td>
-  <td class="in-substance">...</td>
-  <td class="in-form">...</td>
-  <td class="in-type">...</td>
-  <td class="in-name">...</td>
-  <td class="in-value">...</td>
-  <td class="in-anchor">...</td>
-  <td class="via">-</td>
-  <td class="action" data-prefix="动作" data-value="修改/增/添加">修改/增/添加</td>
-  <td class="instruction">-</td>
-  <td class="feature" data-prefix="特性" data-value="控制/并行">控制/并行</td>
-  <td class="out-substance">...</td>
-  <td class="out-form">...</td>
-  <td class="out-type">...</td>
-  <td class="out-name">...</td>
-  <td class="out-value">...</td>
-  <td class="out-anchor">...</td>
-</tr>
-<tr class="nested step" data-group="step-3">...</tr>
-```
-
-##### 返回行
-
-```html
-<tr class="return-row">
-  <td class="idx">↩</td>
-  <td colspan="24"><span class="kw">返回</span> <span class="chip" data-type="视频成品">视频成品</span> 短剧</td>
-</tr>
-<!-- colspan=22: 总 23 列减去 idx 列 -->
-
-```
-
-##### Type chip 设计 (点击看字典树位置 + extends 桥接)
-
-chip 写法:
-
-```html
-<span class="chip" data-type="分镜图">分镜图</span>           <!-- stdlib 叶子 -->
-<span class="chip" data-type="主角图">主角图</span>           <!-- case-specific (extends 参考图), drawer 显示桥接 -->
-```
-
-`data-type` 是**真实 type 名**。chip 统一色不分类: 表格 `类型` 列内 chip 用列色 (输入黄 / 输出蓝), declaration / drawer / 返回行的 chip 用中性灰底。点击 chip → drawer 显示该 type 在字典树里的位置 + `分类说明` + extends 信息。
-
-**作用 / 动作 / 特性 / 实质 / 形式 列内无 chip 装饰** — 纯文本展示 (无 `class="tag"` 灰底, 无 `xxx:` 前缀), 但 span 保留 `data-prefix` / `data-value` 属性触发 taxonomy drawer。点击 `作用` cell → drawer 显示 §A.1 作用字典树 (当前值高亮); 点击 `动作` cell → drawer 显示 §A.2 动作字典树; 点击 `实质` / `形式` cell → drawer 显示对应外部 JSON 词表的子树 (按当前值的路径展开)。
-
-紫色 (`#6d28d9`) 专属**逻辑控制流**关键字: `工序 / 输入 / 资源 / 返回 / 并行 / 遍历`, CSS class `.kw` / `.block-kw` — 与 `.chip` 颜色互不冲突。
-
-
-##### CSS / JS 实施 (移到代码层)
-
-CSS 类目录 + 列宽 + 列组着色 + 显示模式切换 — 全部代码在 [`spec/tools/styles.css`](../tools/styles.css), **以那里为 ground truth**, 本规范不再列 CSS 代码细节.
-
-JS 交互行为 (drawer 点 chip 弹字典树 / hash 锚跳 / atom 展开 / 列控制器 toggle / 模式切换 / 跨页跳转 / placeholder 替换) — 全部代码在 [`spec/tools/script.js`](../tools/script.js), 同上.
-
-JS 启动时通过 placeholder 注入两个数据对象:
-- `typeRegistry` — case-specific 类型表 (workflow.json 各 procedure 的 `type_registry` 合并; stdlib 叶子的 in_tree 由 type.json `$leaves` 标记)
-- `taxonomy` — 字典树 (effect / action / type / feature 各自 `_load_drawer_tree()` 产出)
-
-drawer / chip / scroll 等用户交互**视觉规范** (颜色 / 显示模式 / row-focus 高亮) 见上一节"Type chip 设计" + 下面 IO td 段; 实施靠 CSS/JS 自己保证, 本规范只说**应该长啥样**, 不说**怎么实现**.
-
-
-##### 输入/输出 td 结构补充
-
-- 输入组 6 列 (`in-substance` / `in-form` / `in-type` / `in-name` / `in-value` / `in-anchor`) 紧贴, 输出组 6 列 (`out-substance` / `out-form` / `out-type` / `out-name` / `out-value` / `out-anchor`) 紧贴, 顺序固定 — 数据流"内容性质"列 (实质·形式) 在前, 物理标识 (类型·变量·值·锚链) 在后
-- 多 IO 项时, **每 step 用 N 个 tr 表示**, N = max(输入项数, 输出项数), 用 native table `rowspan` 让数据流列横向严格对齐:
-  - `tr.step-main`: 主行, 包含全部 23 列; 需求组 3 列 (idx/intent/effect) + 实现组 8 列 (via/action/directive/config/decorator/memo/control/feature) 都挂 `rowspan="N"` 跨整个 step
-  - `tr.step-sub`: 子行 N-1 个, 只含 IO 12 列 (输入 6 + 输出 6)
-  - 所有同 step 的 tr 共享 `data-step="step-N"` 属性, 供 JS 折叠 / hover 高亮分组
-  - 视觉: step 之间用 `1.5px solid` 粗分隔线 (`tr.step-main > td { border-top: ... }`), 子行内部用 `1px dashed` 细分隔
-- 块头 (并行/遍历) 和 nested step 同样适用多子行规则; 折叠 click 通过 `tr.nested[data-step="X"]` 选所有 nested 行 (含子行)
-- **实质·形式 取值** = 外部 JSON 词表的路径字符串 (e.g. `/表象/视觉/人物/特写`); 详见 syntax §2.1 (实质/形式); 不要写 "全维" / 实质·人物 等单标签 (旧格式)
-- 变量名 (`<span class="name">`) 可点击触发 prompt 抽屉; 类型 chip 可点击触发 type 抽屉; 实质/形式/作用/动作/特性 文本可点击触发 taxonomy drawer
-- **caller-side decorator (`@采样` 等) 归位到 `指令` 列** — DSL 文本里 `@采样(n=4, pick=人工) { 生成图像(...) }` 是 caller-side 调用修饰, 落到工具组的 `指令` 列, 与工具运行参数 (采样步数 / cfg / LoRA / aspect / 时长) 并列:
-  ```html
-  <td class="via">seedream_4_5</td>
-  <td class="action">生成/元素生成</td>
-  <td class="instruction">
-    <span class="natural">{ 2K · 1:1 · 4 张 }</span>
-    <span class="natural">@采样(n=4, pick=人工)</span>
-  </td>
-  ```
-  好处: `动作` 列只放 kind 标签值, 不混入 caller decorator; "这次 step 工具怎么跑的运行参数" (config + sampling + directive) 集中在 `指令` 一处看. 工序的"数据流输入"列只保留真正的内容素材 (参考视频 / 参考图 / prompt 文本等)
-- **prompt 文本拆为 数据 vs 指令两部分**:
-  - 描述内容的部分 (e.g. "卧室床上, 年轻亚洲女性, 湿长发") → 数据流的 `in-value` 列 (变量 = `参考提示词` / `分镜提示词` 等)
-  - 写给工具的 directive 文本 (e.g. "严格反推视频结构, 不要发挥" / "维持人物特征一致" / "去掉 BGM") → 工具组的 `instruction` 列
-  - 同一来源 prompt 也要按这条边界拆 (即同一段 prompt 文本里有 directive 句也有内容句的, 拆到两列)
-- **目的文本要简短** — 每个 step 的 `intent-text` 一行话, 内嵌 1-3 个 `{kind:text}` token (kind ∈ in/out/act/via/effect/feature), token 取自该行实际 cell 内容, 不允许新造
-- **`<配置>` 已不作为 in-type chip** — 工具运行参数挪到 `指令` 列; 数据流的 `in-type` 只承载真正的内容素材类型 (来自字典树 §A.3, 如 参考视频 / 提示词 / 参考图)
-- **`via` 列只放 L1 工具的 canonical name** (e.g. `seedream_4_5`, 不是 `ByteDance-Seedream-4.5`), 不带 config / 参数 hint
-- **`动作` 列只放标签值** (e.g. `提取/化学提取/反推` / `生成/元素生成`), 不放动作名 / 函数调用 / 参数值 / 自然语言描述; 控制类 (`并行 / 遍历 / 分支`) 已分流到 `特性` 列
-
----
-
-### 容易踩的坑
-
-- ❌ **只读文本不读图** — 文章配图里的 prompt 原文、工具配置、UI 参数往往是关键信息
-- ❌ **凭印象写 prompt** — 必须从图里逐字回填, 截断了就标 `note`, 不要自补
-- ❌ **`#输入 / #输出` 写"全维"** — 偷懒, 改成具体子项列举 (实质·人物 + 实质·场景 + 形式·光照 + ...)
-- ❌ **L1 写成抽象动作** — `external manus(...)` 是具体工具 (L1), `动作 反推提示词(...)` 是抽象 (L2), 两层别混
-- ❌ **tag 与 type 重复** — 领域语义已在 type 名里, tag 不再标
-- ❌ **变体写在动作名里** — 不写 `生成分镜提示词_按视频拆解`, 写 `生成分镜提示词.按视频拆解` 走 `impl A.variant via B`
-- ❌ **config 一刀切** — 同一工序内不同 step 的 config 可能不同 (e.g. 两段视频 16:9/12s vs 4:3/5s), 按 step 独立绑定
-- ❌ **config 串到 via 或动作列文本里** — `<配置>` 是普通输入参数, 跟 prompt / image 一样挂在 `io-in`, 不写到 `via` 的工具名后面也不内联在动作函数调用括号里 (那是 L3/L4 混层)
-- ❌ **via 写工具的人写品牌名** — `via` 是 L1 引用, 用 canonical `seedream_4_5` 不写 `ByteDance-Seedream-4.5`; 人写形式留在 L1 external 定义的注释里就好
-
----
-
-### 与 dedup / 训练的衔接 (未来)
-
-DSL 既是描述, 也是数据归一化载体。多 case 累积后:
-
-- **dedup** — 同一 prompt block content (除空白差异) 跨 case 出现 → 抽到 stdlib `prompt_fragment`;同一 step 序列模式跨 case 出现 → 抽到 stdlib `procedure_template`
-- **训练** — case 文本 (L3 模板) 作为代码 LM 训练语料;L4 实例的 extracted_values 作为 grounding;`#目的 / #输入 / #输出` 作为弱监督信号
-- **检索** — 跨 case 的 `#目的 / 动作 / #输入 / #输出` 组合作为检索键 (e.g. "找所有 动作:生成/合成 + #输出 含 实质·动作 的 step")
-
-这些不在当前阶段做, 但 DSL 的归一化倾向就是为它们留口子。
-
----
-

+ 0 - 110
examples/process_pipeline/script/search_eval/procedure-dsl/spec/syntax.md

@@ -1,110 +0,0 @@
-# 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` / 占位 `<llm>` / `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,本文不附录)。

+ 13 - 0
examples/process_pipeline/script/search_eval/procedure-dsl/spec/taxonomy/type_suggestions.md

@@ -307,3 +307,16 @@
 - `完整提示词方案`: 包含正向提示词(含参考系、构图控制词)与负向提示词的完整 AI 生图提示词集合,可直接粘贴至生图工具  (来自 case-C_zhihu_19056944, extends `提示词`)
 - `出片规划`: 二段式出片的操作计划:草图阶段(先对构图)→ 细节强化阶段(皮肤/眼睛/材质/背景)  (来自 case-C_zhihu_19056944, extends `脚本`)
 - `一致性配置`: 用于系列图输出的一致性策略配置:参考图上传设置 + 固定 Seed + 单变量迭代规则  (来自 case-C_zhihu_19056944, extends `生成参数`)
+
+- `视觉风格JSON`: 多模态AI对图片视觉风格的结构化JSON分析结果,含颜色/构图/排版/主体/质感/光影/特效/氛围/复刻关键词等字段,用作后续生图步骤的引导输入  (来自 case-aaa_test_1, extends `提示词`)
+- `生成图`: 由生成模型按提示词产出的终态图像,不再进入后续加工,直接作为本次工序的交付成品  (来自 case-aaa_test_1, extends `成品图`)
+- `分镜分析列表`: Qwen3-VL对视频各分镜的结构化分析结果列表,每项含画面风格/主体特征/服装/动作/镜头变化/构图/光影/台词/音效/画质参数等,作为逐镜视频生成的批量输入  (来自 case-aaa_test_1, extends `提示词`)
+- `分镜分析`: 单个分镜的详细分析数据,包含画面风格、主体特征、服装物品、动作描述、镜头变化、构图、光影、台词旁白、音效、画质参数和时长,作为单段视频生成的引导指令  (来自 case-aaa_test_1, extends `提示词`)
+
+- `故事主题`: 用'某主要角色在某地/某时做某事或遇到某事'公式写成的一句话主题陈述  (来自 case-create-2, extends `描述`)
+- `背景资料`: 按时代背景/时间/地点/相关事件/角色五方面条目化整理的故事背景资料  (来自 case-create-2, extends `大纲`)
+- `角色清单`: 按主要角色/次要角色/对立角色分类列出的角色简述列表  (来自 case-create-2, extends `描述`)
+- `角色传记`: 单个角色的完整传记,含观念链条/内在需求/外在动作/出生到故事发生前的经历  (来自 case-create-2, extends `描述`)
+- `角色传记集`: 三类角色(主要/次要/对立)传记的合集  (来自 case-create-2, extends `描述`)
+- `冲突矩阵`: 四类角色间冲突的结构化分析(主次/主对立/次对立/主角内在冲突),含冲突橡皮球模型  (来自 case-create-2, extends `描述`)
+- `三幕框架`: 三幕式故事骨架,含建置/对抗/结局三幕及情节点1/中间点/紧要关头/情节点2等关键节点  (来自 case-create-2, extends `大纲`)

+ 28 - 296
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools.md

@@ -1,252 +1,14 @@
-# 外部脚本与工具参考
+# 脚本怎么用(工具手册)
 
-> Agent 跑 spec/ skill 时通过 Bash 调用的脚本接口手册. **所有工具现在都在 `spec/tools/` 下**, skill 完全自包含 — Agent 不需要 Read 任何 spec/ 外的脚本源码, 只需要知道接口.
+> 跑这道 skill 时会用命令行调用几个脚本,这里讲它们**怎么用**。脚本都在 `spec/tools/` 下,**你不用读脚本源码,会调就行**。
 
-## 1. `spec/tools/taxonomy-lookup.py` — 实质/形式 词表查询
+## 1. `spec/tools/wf-patch.py` — workflow.json 安全批量字段设置器
 
-**用途**: 阶段二 2B 子任务. 查询外部 JSON 词表 (`分类库导出_实质_*.json` / `分类库导出_形式_*.json`, 911 + 565 条路径). 词表本身**不进 LLM context**, 完全走 tool query.
+**做什么**:批量给 `workflow.json` 的步骤/输入输出填字段(第一阶段连"来源",第二阶段填作用/动作/类型/实质/形式)。**凡是"给一批字段赋值"都用它,别写 Python 脚本去拼/改 workflow.json**(脚本拼 JSON 容易把文件弄坏)。分工:**你出判断(哪个字段填什么),工具负责安全写入 + 当场检查对错**。
 
-**子命令**:
-
-| 子命令 | 用法 | 返回 |
-|---|---|---|
-| 列二级路径 | `python spec/tools/taxonomy-lookup.py --dim 实质 --list-l2` | 各 L2 路径 + 该子树叶子数 |
-| 看子树 | `python spec/tools/taxonomy-lookup.py --dim 实质 --subtree /表象/视觉` | 该子树所有叶子 |
-| 字符串匹配 | `python spec/tools/taxonomy-lookup.py --dim 形式 --match "中景特写"` | 排序候选路径 (单 token 行为) |
-| 多 token 聚合 | `python spec/tools/taxonomy-lookup.py --dim 实质 --match "年轻女性 卧室 床上"` | 各 token 各自打分聚合, 覆盖多 token 的 path bonus |
-| 层级下钻 | `python spec/tools/taxonomy-lookup.py --dim 实质 --narrow "AI生成 提示词"` | 从 L2 起按子树语义打分逐层下钻 top-K (兜底 match miss) |
-| 校验路径存在 | `python spec/tools/taxonomy-lookup.py --dim 实质 --validate /理念/知识/化学` | OK / PARTIAL / MISS (exit 0/1) |
-
-**关于 `--match` 的多 token 行为** (2026-05-22 起):
-- query **含空白** 自动拆 token, 每个 token (≥2 字, 单字噪声大被丢) 独立打分, path 级聚合 score
-- 命中 ≥2 token 的 path 给 coverage bonus (score ×= 1 + 0.3·(cov-1)), 防止单 token 大量命中压死多 token 弱命中
-- **单 token** (无空白) 行为跟旧版完全一致, 不影响已有 query
-- 全 miss 时输出提示, 引导转 `--narrow` 兜底
-
-**关于 `--narrow` 的层级下钻** (2026-05-22 新增):
-- 从所有 L2 出发, 对每个候选子树计算 `(token 命中次数, 命中的 token 数)`, 按 cov ↘ hits ↘ 排序
-- 每层取 `--top-per-level` (默认 3), 进下一层只展开这些候选的直接子节点
-- 直到 `--depth` (默认 3 层, L2→L3→L4→L5) 或全部到叶子
-- 比 `--match` 容错更强: alias 完全没覆盖但路径段语义沾边的 case 也能召回 (e.g. "镜头语言" 不在 alias 但 `/呈现/视觉/视觉制作/构图编排` 路径段直接对路)
-
-**Agent 用法 (典型 funnel)**:
-1. `--list-l2` 决定大致 domain (实质先选 /理念 vs /表象, 形式先选 /呈现 vs /架构)
-2. `--match <query>` 多 token 召回候选 (大概率一步搞定)
-3. **若 `--match` 返 (无匹配)** → `--narrow <query>` 按子树语义下钻
-4. `--subtree <chosen_path>` 看候选 leaf
-5. `--validate <leaf>` 确认后写回 workflow.json 对应 IO 的 substance/form 字段
-
-**词表文件路径** (按优先级 fallback):
-1. `$TAXONOMY_DIR/分类库导出_{实质|形式}_*.json` (env override)
-2. `procedure-dsl/data/分类库导出_*.json`
-3. `examples/process_pipeline/script/resource/分类库导出_*.json`
-4. `examples/process_pipeline/test_script/procedure_dsl_agent/data/分类库导出_*.json`
-5. `~/Downloads/分类库导出_*.json`
-
----
-
-## 2. `spec/tools/wf-patch.py` — workflow.json 安全批量字段设置器
-
-**用途**: Phase 1.3 (批量加 anchor) + Phase 2 (批量填 effect/action/type/substance/form). **凡是「给一批 step / IO 设结构化字段」的活都用它, 不要写 Python 脚本去生成 / 批改 workflow.json** —— 脚本拼 JSON 易踩转义 / 控制字符坑 (会把文件搞坏), 还把本该逐 step 的语义判断埋进一次性脚本. 分工: **你只出语义决策 (path=value), 工具负责安全 json.dump + 写入即校验**.
-
-**核心保证**:
-- **安全 IO**: 工具自己 load → 改 → dump(ensure_ascii=False), 你永远不手写 JSON, 不会写坏文件
-- **写入即校验 (fail-fast)**: 每条赋值立刻对照字典树 / 本工序 type_registry / anchor 格式校验; **任何一条非法 → 报具体哪条错, 整批不写** (不产出悄悄错的文件). 校验规则跟 lint 同源 (同款叶子派生), **patch 通过 = lint 必过**
-
-**用法**:
-```bash
-# 单条 / 多条 --set (path=value, 只在第一个 = 处切; value 可含 = 和空格, 整体加引号)
-python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json \
-    --set 'p1.s1.inputs[0].anchor=← s0.主角图' \
-    --set 'p1.s2.effect=主体生成' \
-    --set 'p1.s2.action=生成/图像生成/文生图'
-
-# 批量: 几十处 anchor / 字段一次过 — 写一份 patch 清单 (你仍逐条显式决策每个值), 一条命令应用
-python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --patch _scratch/anchors.json
-#   anchors.json = [{"path":"p1.s1.inputs[0].anchor","value":"← s0.x"}, ...]
-
-# 只校验不写
-python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
-
-# 透传回填: anchor 设好后, 自动把"原样透传"的 value/directive 从源逐字抄过来
-python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --resolve-passthrough
-```
-
-**`--resolve-passthrough` (重要, 省掉重复抄写)**: spec 要求 `value` **逐字回填数据本身**, 不能写「(同 sN 输出)」「见 sN」这类引用占位 (那是 anchor 的活, lint 会报). 但一个 prompt 被下游 N 步原样复用时, 手抄 N 遍既烦又是 agent 写占位偷懒的根源. 这个模式让你**只在源头 (s1 的 output) 填一次真值**, 其余透传位置只管设 anchor (`← s1.xxx`), 然后工具顺 anchor 把源 value **逐字抄到**每个 value 空/占位的 IO + 每个「同 sN.x」的 directive, **迭代到不动点** (链式透传也覆盖). 源找不到的会 `⚠` 报出来. 可单独跑, 也可跟在 `--set/--patch` 后 (先赋值再回填).
-
-**路径语法** (proc / step 按 **id** 寻址, 不是下标; 只有真列表才用 `[i]`; 嵌套步 id 带点如 `s2.1` 也支持):
-
-| 路径 | 设的字段 |
-|---|---|
-| `p1.s2.effect` | step 标量 (effect / via / action / feature / control / kind / intent / group) |
-| `p1.s1.inputs[0].anchor` | IO 字段 (anchor / type / substance / form / name / value) |
-| `p1.s2.1.outputs[0].type` | 嵌套步的 IO |
-| `p1.s2.focus` | step 的 focus 数组 (逗号分隔: `focus=via,action,out-type-0`) |
-| `p1.purpose` | procedure 头部 (name / purpose / category / platform / author) |
-| `p1.declarations.inputs[0].desc` | declarations 内任意字段 (通用下钻) |
-| `source.url` | case-level 原帖信息 (platform / author / date / url / title / excerpt) |
-| `p1.type_registry.场景图.extends` | 注册 case-specific 类型 (自动建 type_registry 段) |
-
-**`--unset PATH`** (删字段, 可重复): 删掉某字段, 取代手 Edit 删. e.g. `--unset p1.declarations.inputs[0].inferred` (declarations 不收 inferred, schema 会拒). 字段本就不存在 → 跳过 (幂等, 不报错).
-
-**各字段校验规则**:
-- `effect` → effect.json 叶子 (给全路径会自动归一到叶名)
-- `action` → action.json 叶子 / 叶路径 (给叶名自动展开成全路径)
-- `type` → type.json 叶子 **或** 本 procedure 已注册的 type_registry 名 (没注册会提示先 `--set p.type_registry.X.extends=<叶子>`)
-- `extends` → 必须桥到 type.json 叶子
-- `substance` / `form` / `url` → substance/form 走 taxonomy-lookup `--validate`; 三者均可传 `__null__` 设 JSON null
-- `anchor` → 必须 `←` (输入引用) 或 `→` (输出去向) 开头
-- `feature` → 受控词 {随机 / 幂等 / 人工 / 本地 / 写外部 / 读外部 / -}
-- `control` → 受控词 {并行 / 遍历 / 分支 / 请求 / 等待 / -}
-- `kind` → {step / block / nested / atom}
-- `focus` → 逗号分隔 → 数组 (空串 → `[]`)
-- 其余 (name / value / intent / via / desc / purpose / ...) → 自由文本, 不校验
-
-**仍用 Write / Edit 的只剩** (尽量别碰生 JSON, 这两类才用): 骨架首次创建 (Phase 1.2 从 template Write); `instruction` 列表 (套列表结构, 手动 Edit; 透传 directive 用 `--resolve-passthrough`). 改字段 / 删字段 / 改 source 现在都走 wf-patch, **不要再 Read→Edit 改 workflow.json** (那会反复重读、烧 token).
-
-**退出码**: `0` 全通过并写入 (或 `--dry-run` 通过) / `1` 有校验失败 (整批未写) / `2` CLI 错 / 文件不存在 / JSON 损坏.
-
----
-
-## 3. `spec/tools/render-case.py` — 阶段三 workflow.json → HTML 渲染 + schema 校验
-
-**用途**: 阶段三. 接收 `workflow.json` (多工序 `procedures:[]`), 在内存组装成 case_data (merge `--source-input` 原帖 + `--page-title` + `--case-id`), 跑 schema 校验, 渲染输出 HTML. **不落盘 case_data.json**.
-
-**Agent 用法** (推荐): workflow.json 已含全部 procedures + 标注后:
-
-```bash
-# 1. 只校验, 看 schema 错 (建议带 --source-input, 让校验看到的就是 merge 后的最终版)
-python spec/tools/render-case.py \
-    --workflow outputs/case-{N}/workflow.json \
-    --source-input input/case-{N}-raw.json \
-    --page-title "Case {N} · <主题>" \
-    --case-id {N} \
-    --validate
-
-# 2. 校验通过后渲染输出 (--source-input 必带, 否则 HTML 折叠原文区只剩 60 字 excerpt)
-python spec/tools/render-case.py \
-    --workflow outputs/case-{N}/workflow.json \
-    --source-input input/case-{N}-raw.json \
-    --page-title "Case {N} · <主题>" \
-    --case-id {N} \
-    --out outputs/case-{N}/case-{N}-<slug>.html
-```
-
-**关于 `--source-input`** (2026-05-22 新增): renderer 直接从原帖 raw json 抽 `body_text` + 封面 + 图集兜底, in-place 填到 `case_data.source` —— Agent 不必手工复制原文内容. 行为:
-- `body_text` / `cover_image` 直接覆盖 case_data 同字段
-- `title` / `url` 仅在 case_data 缺时填
-- `excerpt` / `author` / `date` / `platform` **不动** (那些是 Agent 推断的友好版本)
-- **图集兜底**: 检查 raw.body_text 已 inline 的 `[image:URL]` 标记, 把 raw.image_url_list 里没 inline 也不是封面的图 append 到 body 末尾 (加 `--- 附图 ---` 分隔符). 适配"小红书短文 + 多图独立列" 和 "微信公众号长文 + inline 图" 两种平台
-
-**输入契约**: 见 [`spec/format/case-data.schema.json`](format/case-data.schema.json) (canonical JSON Schema Draft 2020-12, 受控字段 + enum + 条件约束 `if/then`).
-
-**模板**: [`spec/templates/workflow.template.json`](templates/workflow.template.json) (复制到 `outputs/case-{N}/workflow.json` 后替换 `<填:...>` 占位符).
-
-⚠ **绝对不要参考其他 `outputs/case-*/build_html.py` 或 `outputs/case-*/*.json`** — 那些是 case-specific 产物, 不是模板. 唯一 canonical 模板是 `spec/templates/workflow.template.json`.
-
-**输出码**:
-- `0` — 成功 (渲染或校验通过)
-- `1` — IO / schema / 渲染异常
-- `2` — CLI 参数错误
-
-**依赖**:
-- 必需: `spec/tools/renderer.py` (跟本脚本同目录, 自动 import)
-- 可选: `jsonschema` (装了用 Draft 2020-12 完整校验; 没装走 minimal check fallback)
-
----
-
-## 4. `spec/tools/lint-case.py` — 轻量 lint + 自动 record 新 type
-
-**用途**: 阶段三. 跑完 `render-case.py` 后跑一次. 干三件事:
-1. **type 完整性 hint**: 扫 workflow.json 各 procedure 的 IO type 字段, 找出"用了 case-specific type 但该 procedure 的 `type_registry` 漏注册 / 缺 extends / 缺 desc"的情况, 打 stdout 给 Agent / 用户看
-2. **value 自包含 hint**: 扫每个 IO 的 value + 每个 directive, 揪出「(同 sN 输出)」「见 sN」「← sN」这类**引用占位** —— spec 要求 value 逐字回填数据本身 (引用归 anchor), 这种占位 schema/type 检查抓不到. 命中会提示跑 `wf-patch.py --resolve-passthrough` 自动回填
-3. **副作用: auto-record**: 把各 procedure.type_registry 里的 case-specific entry 自动 append 到 `spec/taxonomy/type_suggestions.md` 累积条目段 (Agent **不必手工 Write** suggestions, 工具代劳)
-
-**幂等**: dedup key = `(type_name, case_id)` 二元组. 同 case 重跑不重复; 不同 case 同名允许 (跨 case 频次是升级信号).
-
-**用法**:
-```bash
-# 默认: 检测 + 自动 record
-python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N}
-
-# 只检测不写
-python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-id {N} --no-record
-```
-
-**输出范例** (case 含 silent gap 的情况):
-```
-[lint] case-1 (workflow.json)
-  · type 完整性: 2 个提示
-      - [p1] step[1].outputs[0].type='主角图' 是 case-specific 但该 procedure 的 type_registry 没注册
-      - [p1] step[8].inputs[1].type='主角图' 是 case-specific 但该 procedure 的 type_registry 没注册
-  · 无新 type 可 record (type_registry 为空 — 全部 type 命中字典叶子)
-```
-
-**退出码**: 始终 0 (不阻塞流程). 解析 2 = CLI 参数错 / 文件不存在.
-
-**设计哲学**: 不严格. 检测项是 hint 不是 fail; record 是副作用不是核心契约. Agent 看 stdout 决定回不回去补 case_data.type_registry.
-
----
-
-## 5. `spec/tools/renderer.py` — HTML 渲染主模板 (Python 模块)
-
-**用途**: `render-case.py` 内部 import 的渲染主模板, 1379 行. 提供 `build_html(case_data: dict) -> str` 入口.
-
-**Agent 不直接 Read 它** — 太长, 走 `render-case.py` 调用即可. 直接 Read 它源码会浪费 ~18k context, 没意义.
-
-**Agent 唯一应该看的接口**: [`spec/format/case-data.schema.json`](format/case-data.schema.json) (输入契约) + [`spec/format/procedure-table.md`](format/procedure-table.md) (输出 HTML 的结构规范).
-
----
-
-## 6. `run_procedure_dsl.py` — runner 本身 (不在 skill 内)
-
-跑 Agent 的入口脚本. **Agent 不读它** — 它在跑 Agent. 但 Agent 可能想知道**自己被怎么起的**:
-
-- OAuth Max 模式 (走 ~/.claude 凭证, 不计 API 费)
-- `allowed_tools = ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task"]`  # 🟢 包含 Task 召唤子 Agent 工具
-- `permission_mode = "bypassPermissions"` (Agent 全自动, 不停下来问)
-- `cwd = procedure-dsl/` (Agent 的工作目录)
-- `--resume` 支持 (中断后续跑)
-- runner 实时把每 turn 写到 `outputs/case-{N}/_trace.md`
-
----
-
-## 7. 文件路径约定 (per case)
-
-| 路径 | 内容 | 谁负责 |
-|---|---|---|
-| `input/case-{N}-raw.json` | 原 case 素材 (title / link / body_text / image_url_list / ...) | 人 (Agent 读, 不写) |
-| `outputs/case-{N}/` | Agent 工作目录 (一 case 一目录) | Agent (写产物) |
-| `outputs/case-{N}/.session_id` | SDK session UUID, 用于 `--resume` | runner 写, Agent 不动 |
-| `outputs/case-{N}/_trace.md` | runner 写的实时执行流水 | runner (Agent 别 Read) |
-| `outputs/case-{N}/_scratch/` | **sanctioned scratch 区** — 只用于 dump 大 Bash 输出 (taxonomy --subtree 长结果 / find 结果) 之后 Read 切片, 或一次性 smoke test. runner 预创建. **不要用项目根的 `scratch/`**. ⚠ **不是写 build/normalize 脚本生成 workflow.json 的地方** —— 那个用 §2 `wf-patch.py` | Agent (随便 dump, 跟着 case 一起清理) |
-| `outputs/case-{N}/understanding.md` | 阶段一 1.1 心智模型 (含多工序判断) | Agent |
-| `outputs/case-{N}/workflow.json` | **唯一中间产物** — Phase 1.2 Write 骨架 (从 template), 之后**逐字段演化**: 单处用 Edit, 批量结构化字段 (1.3 anchor / 2 effect·action·type·substance·form) 用 §2 `wf-patch.py`. **绝不写 Python 脚本生成 / 批改它**. 符合 case-data.schema.json (`procedures:[]`) | Agent |
-| `outputs/case-{N}/case-{N}-<slug>.md` | 阶段三 .md 输出 (按 spec/format/md-structure.md) | Agent |
-| `outputs/case-{N}/case-{N}-<slug>.html` | 阶段三 .html 输出 (跑 render-case.py 生成) | render-case.py |
-
----
-
-## 8. 外部 JSON 词表 (实质 / 形式) 不进 spec/
-
-`分类库导出_*.json` 词表为什么不放 spec/:
-
-- **太大**: 实质 911 条 + 形式 565 条路径, 进 LLM context 占 30k+ tokens
-- **变化频率不同**: spec 演化慢, 词表演化快 (随分类学的迭代)
-- **走 tool 比走 Read 更经济**: 配 `spec/tools/taxonomy-lookup.py` 的 funnel API (`--list-l2 / --subtree / --match`), 一次 query 几百 tokens, 比整树 Read 省 50-100x
-
-Agent 阶段二 2B 完全通过 tool 查, 不要 Read 词表 JSON 本身.
-
----
-
-## 9. `Agent` (或 `Task`) — Claude Agent SDK 子 Agent 召唤工具
-
-**用途**: 用于在 Phase 2 (归一化与标注) 中将庞大重负载的主 Agent 上下文(含 14+ Base64 图片及 40k+ 规格说明书)与细碎耗费 Token 的高频分类查询进行**上下文隔离与并发分流**。
-
-**工作原理**:
-- 允许主 Agent 创建并行的、无图片和规格历史包袱的轻量化子 Agent。
-- **安全 IO**: 工具自己 load → 改 → dump(ensure_ascii=False), 你永远不手写 JSON, 不会写坏文件
-- **写入即校验 (fail-fast)**: 每条赋值立刻对照字典树 / 本工序 type_registry / anchor 格式校验; **任何一条非法 → 报具体哪条错, 整批不写** (不产出悄悄错的文件). 校验规则跟 lint 同源 (同款叶子派生), **patch 通过 = lint 必过**
+**两个保证**:
+- **不会写坏文件**:由工具读取→修改→写回,你从不直接碰 JSON 文本。
+- **当场检查,有错全不写**:每条赋值都立刻对照词表/类型登记/格式校验;**只要有一条不合法,就报出是哪条、整批都不写**(不会产出悄悄出错的文件)。检查规则和最后的 lint 一致——**这里通过了,lint 一定过**。
 
 **用法**:
 ```bash
@@ -267,14 +29,14 @@ python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
 python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --resolve-passthrough
 ```
 
-**`--resolve-passthrough` (重要, 省掉重复抄写)**: spec 要求 `value` **逐字回填数据本身**, 不能写「(同 sN 输出)」「见 sN」这类引用占位 (那是 anchor 的活, lint 会报). 但一个 prompt 被下游 N 步原样复用时, 手抄 N 遍既烦又是 agent 写占位偷懒的根源. 这个模式让你**只在源头 (s1 的 output) 填一次真值**, 其余透传位置只管设 anchor (`← s1.xxx`), 然后工具顺 anchor 把源 value **逐字抄到**每个 value 空/占位的 IO + 每个「同 sN.x」的 directive, **迭代到不动点** (链式透传也覆盖). 源找不到的会 `⚠` 报出来. 可单独跑, 也可跟在 `--set/--patch` 后 (先赋值再回填).
+**`--resolve-passthrough`(省得重复抄内容)**:规矩是"值"要写真实内容,不能写"(同上)""见 s1o1"这类引用(那是"来源"该干的,lint 会报)。但同一段内容被后面好几步原样复用时,手抄好几遍很烦。用这个:**只在源头那个输出里填一次真内容**,其余引用处把"来源"设成 `← 源的编号`,工具就顺着编号把真内容**逐字抄到**每个"值"还空着的输入(链式引用也会一路抄到底)。源头找不到的会用 `⚠` 提示。可单独跑,也可跟在 `--set/--patch` 后面。
 
 **路径语法** (proc / step 按 **id** 寻址, 不是下标; 只有真列表才用 `[i]`; 嵌套步 id 带点如 `s2.1` 也支持):
 
 | 路径 | 设的字段 |
 |---|---|
-| `p1.s2.effect` | step 标量 (effect / via / action / feature / control / kind / intent / group) |
-| `p1.s1.inputs[0].anchor` | IO 字段 (anchor / type / substance / form / name / value) |
+| `p1.s2.effect` | step 标量 (effect / substance / form / via / action / directive / kind / intent / group) |
+| `p1.s1.inputs[0].anchor` | IO 字段 (anchor / type / value / id) |
 | `p1.s2.1.outputs[0].type` | 嵌套步的 IO |
 | `p1.s2.focus` | step 的 focus 数组 (逗号分隔: `focus=via,action,out-type-0`) |
 | `p1.purpose` | procedure 头部 (name / purpose / category / platform / author) |
@@ -289,21 +51,19 @@ python spec/tools/wf-patch.py --workflow outputs/case-{N}/workflow.json --resolv
 - `action` → action.json 叶子 / 叶路径 (给叶名自动展开成全路径)
 - `type` → type.json 叶子 **或** 本 procedure 已注册的 type_registry 名 (没注册会提示先 `--set p.type_registry.X.extends=<叶子>`)
 - `extends` → 必须桥到 type.json 叶子
-- `substance` / `form` / `url` → substance/form 走 taxonomy-lookup `--validate`; 三者均可传 `__null__` 设 JSON null
-- `anchor` → 必须 `←` (输入引用) 或 `→` (输出去向) 开头
-- `feature` → 受控词 {随机 / 幂等 / 人工 / 本地 / 写外部 / 读外部 / -}
-- `control` → 受控词 {并行 / 遍历 / 分支 / 请求 / 等待 / -}
-- `kind` → {step / block / nested / atom}
+- `substance` / `form` → 自由提炼的元素点 (字符串或数组), **不查词表、不校验**; `url` → 自由文本; 三者均可传 `__null__` 设 JSON null
+- `anchor` → 必须 `←` (输入引用, 指向某 output id) 或 `→` (输出去向) 开头
+- `kind` → {step / block / nested}
 - `focus` → 逗号分隔 → 数组 (空串 → `[]`)
 - 其余 (name / value / intent / via / desc / purpose / ...) → 自由文本, 不校验
 
-**仍用 Write / Edit 的只剩** (尽量别碰生 JSON, 这两类才用): 骨架首次创建 (Phase 1.2 从 template Write); `instruction` 列表 (套列表结构, 手动 Edit; 透传 directive 用 `--resolve-passthrough`). 改字段 / 删字段 / 改 source 现在都走 wf-patch, **不要再 Read→Edit 改 workflow.json** (那会反复重读、烧 token).
+**仍用 Write / Edit 的只剩**: 骨架首次创建 (Phase 1.2 从 template Write). 改字段 / 删字段 / 改 source 现在都走 wf-patch (`directive` 也是普通标量字段, 直接 `--set`), **不要再 Read→Edit 改 workflow.json** (那会反复重读、烧 token).
 
 **退出码**: `0` 全通过并写入 (或 `--dry-run` 通过) / `1` 有校验失败 (整批未写) / `2` CLI 错 / 文件不存在 / JSON 损坏.
 
 ---
 
-## 3. `spec/tools/render-case.py` — 阶段三 workflow.json → HTML 渲染 + schema 校验
+## 2. `spec/tools/render-case.py` — 阶段三 workflow.json → HTML 渲染 + schema 校验
 
 **用途**: 阶段三. 接收 `workflow.json` (多工序 `procedures:[]`), 在内存组装成 case_data (merge `--source-input` 原帖 + `--page-title` + `--case-id`), 跑 schema 校验, 渲染输出 HTML. **不落盘 case_data.json**.
 
@@ -335,9 +95,9 @@ python spec/tools/render-case.py \
 
 **输入契约**: 见 [`spec/format/case-data.schema.json`](format/case-data.schema.json) (canonical JSON Schema Draft 2020-12, 受控字段 + enum + 条件约束 `if/then`).
 
-**模板**: [`spec/templates/workflow.template.json`](templates/workflow.template.json) (复制到 `outputs/case-{N}/workflow.json` 后替换 `<填:...>` 占位符).
+**模板**: 见 [`format/workflow-format.md`](format/workflow-format.md) 末尾「附:骨架模板」, 复制后替换 `<填:...>` 占位符.
 
-⚠ **绝对不要参考其他 `outputs/case-*/build_html.py` 或 `outputs/case-*/*.json`** — 那些是 case-specific 产物, 不是模板. 唯一 canonical 模板是 `spec/templates/workflow.template.json`.
+⚠ **绝对不要参考其他 `outputs/case-*/` 下的产物文件当模板** — 那些是 case-specific 产物. 唯一 canonical 骨架在 `format/workflow-format.md` 末尾.
 
 **输出码**:
 - `0` — 成功 (渲染或校验通过)
@@ -350,7 +110,7 @@ python spec/tools/render-case.py \
 
 ---
 
-## 4. `spec/tools/lint-case.py` — 轻量 lint + 自动 record 新 type
+## 3. `spec/tools/lint-case.py` — 轻量 lint + 自动 record 新 type
 
 **用途**: 阶段三. 跑完 `render-case.py` 后跑一次. 干三件事:
 1. **type 完整性 hint**: 扫 workflow.json 各 procedure 的 IO type 字段, 找出"用了 case-specific type 但该 procedure 的 `type_registry` 漏注册 / 缺 extends / 缺 desc"的情况, 打 stdout 给 Agent / 用户看
@@ -383,22 +143,20 @@ python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-
 
 ---
 
-## 5. `spec/tools/renderer.py` — HTML 渲染主模板 (Python 模块)
-
-**用途**: `render-case.py` 内部 import 的渲染主模板, 1379 行. 提供 `build_html(case_data: dict) -> str` 入口.
+## 4. `spec/tools/renderer.py` — HTML 渲染主模板 (Python 模块)
 
-**Agent 不直接 Read 它** — 太长, 走 `render-case.py` 调用即可. 直接 Read 它源码会浪费 ~18k context, 没意义.
+**做什么**:把数据渲染成网页的主程序,被 `render-case.py` 在内部调用。
 
-**Agent 唯一应该看的接口**: [`spec/format/case-data.schema.json`](format/case-data.schema.json) (输入契约) + [`spec/format/procedure-table.md`](format/procedure-table.md) (输出 HTML 的结构规范).
+**你不用读它**——通过 `render-case.py` 调用即可。要了解格式,看 [`format/case-data.schema.json`](format/case-data.schema.json)(机器清单)和 [`format/workflow-format.md`](format/workflow-format.md)(格式说明)就够了。
 
 ---
 
-## 6. `run_procedure_dsl.py` — runner 本身 (不在 skill 内)
+## 5. `run_procedure_dsl.py` — runner 本身 (不在 skill 内)
 
 跑 Agent 的入口脚本. **Agent 不读它** — 它在跑 Agent. 但 Agent 可能想知道**自己被怎么起的**:
 
 - OAuth Max 模式 (走 ~/.claude 凭证, 不计 API 费)
-- `allowed_tools = ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task"]`  # 🟢 包含 Task 召唤子 Agent 工具
+- `allowed_tools = ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "Task", "Agent"]`  # 🟢 Task / Agent 均可召唤子 Agent (新旧标识符)
 - `permission_mode = "bypassPermissions"` (Agent 全自动, 不停下来问)
 - `cwd = procedure-dsl/` (Agent 的工作目录)
 - `--resume` 支持 (中断后续跑)
@@ -406,7 +164,7 @@ python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-
 
 ---
 
-## 7. 文件路径约定 (per case)
+## 6. 文件路径约定 (per case)
 
 | 路径 | 内容 | 谁负责 |
 |---|---|---|
@@ -416,38 +174,12 @@ python spec/tools/lint-case.py --workflow outputs/case-{N}/workflow.json --case-
 | `outputs/case-{N}/_trace.md` | runner 写的实时执行流水 | runner (Agent 别 Read) |
 | `outputs/case-{N}/_scratch/` | **sanctioned scratch 区** — 只用于 dump 大 Bash 输出 (taxonomy --subtree 长结果 / find 结果) 之后 Read 切片, 或一次性 smoke test. runner 预创建. **不要用项目根的 `scratch/`**. ⚠ **不是写 build/normalize 脚本生成 workflow.json 的地方** —— 那个用 §2 `wf-patch.py` | Agent (随便 dump, 跟着 case 一起清理) |
 | `outputs/case-{N}/understanding.md` | 阶段一 1.1 心智模型 (含多工序判断) | Agent |
-| `outputs/case-{N}/workflow.json` | **唯一中间产物** — Phase 1.2 Write 骨架 (从 template), 之后**逐字段演化**: 单处用 Edit, 批量结构化字段 (1.3 anchor / 2 effect·action·type·substance·form) 用 §2 `wf-patch.py`. **绝不写 Python 脚本生成 / 批改它**. 符合 case-data.schema.json (`procedures:[]`) | Agent |
-| `outputs/case-{N}/case-{N}-<slug>.md` | 阶段三 .md 输出 (按 spec/format/md-structure.md) | Agent |
-| `outputs/case-{N}/case-{N}-<slug>.html` | 阶段三 .html 输出 (跑 render-case.py 生成) | render-case.py |
+| `outputs/case-{N}/workflow.json` | **唯一中间产物** — Phase 1.2 Write 骨架 (从 template), 之后**逐字段演化**: 单处用 Edit, 批量结构化字段 (1.3 anchor / 2 effect·action·type + step 级 substance·form) 用 §2 `wf-patch.py`. **绝不写 Python 脚本生成 / 批改它**. 符合 case-data.schema.json (`procedures:[]`) | Agent |
+| `outputs/case-{N}/case-{N}-<slug>.html` | 阶段三 .html 输出 (跑 render-case.py 生成; **唯一产物, .md 已取消**) | render-case.py |
 
 ---
 
-## 8. 外部 JSON 词表 (实质 / 形式) 不进 spec/
+## 7. 第二阶段不再用子助手
 
-`分类库导出_*.json` 词表为什么不放 spec/:
+第二阶段(作用/动作/类型 归类 + 实质/形式 提炼)现在**由主流程自己一趟做完**——不再切任务、不再召唤子助手、不再查"实质/形式"大词表(实质/形式 改为自由提炼元素点)。具体见 [phase2-normalize.md](extraction/phase2-normalize.md)。
 
-- **太大**: 实质 911 条 + 形式 565 条路径, 进 LLM context 占 30k+ tokens
-- **变化频率不同**: spec 演化慢, 词表演化快 (随分类学的迭代)
-- **走 tool 比走 Read 更经济**: 配 `spec/tools/taxonomy-lookup.py` 的 funnel API (`--list-l2 / --subtree / --match`), 一次 query 几百 tokens, 比整树 Read 省 50-100x
-
-Agent 阶段二 2B 完全通过 tool 查, 不要 Read 词表 JSON 本身.
-
----
-
-## 9. `Agent` (或 `Task`) — Claude Agent SDK 子 Agent 召唤工具
-
-**用途**: 用于在 Phase 2 (归一化与标注) 中将庞大重负载的主 Agent 上下文(含 14+ Base64 图片及 40k+ 规格说明书)与细碎耗费 Token 的高频分类查询进行**上下文隔离与并发分流**。
-
-**工作原理**:
-- 允许主 Agent 创建并行的、无图片和规格历史包袱的轻量化子 Agent。
-- 子 Agent 具有极其干净的小型 Context 窗口(约 2k tokens),它专门携带 `taxonomy-lookup.py` 工具链去查字典,并返回标准的 `patch_2a.json` 或 `patch_2b.json` 回归主 Agent,由主 Agent 通过 `wf-patch.py` 写入 `workflow.json`。
-- **降本 90% 以上,速度提升 100% 以上 (多路并发)**!
-
-**召唤语法与参数**:
-```json
-Agent(
-  subagent_type="Explore",  // 固定为 "Explore" (用于分析与工具调用) 或 "Write" (用于产物生成)
-  description="子任务标题: 例如 Phase 2B 变量实质与形式词表查询",
-  prompt="[给子 Agent 的明确任务书] 例如: 读 outputs/case-N/_scratch/task_2b.json 任务文件,然后为其中各变量调用 taxonomy-lookup.py 查出实质与形式路径,生成标准的 patch_2b.json 并把其具体内容写回给我。"
-)
-```

+ 4 - 6
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/lint-case.py

@@ -110,7 +110,7 @@ META_REF = re.compile(r'[((]?\s*同\s*s[\d]|见\s*s[\d]|←\s*s[\d]|同上')
 def check_value_selfcontained(case_data: dict) -> list[str]:
     """扫每个 IO 的 value + 每个 directive, 找「引用占位」文案 (同 sX / 见 sX / ← sX ...).
 
-    spec: value 逐字回填数据本身, 引用归 anchor (fields.md 数据流组 + syntax §6).
+    spec: value 逐字回填数据本身, 引用归 anchor (workflow-format.md §2 数据流).
     这种占位 schema/type 检查抓不到, 专门一条. 只 hint. 可用
     `wf-patch.py --resolve-passthrough` 自动从源回填.
     """
@@ -126,11 +126,9 @@ def check_value_selfcontained(case_data: dict) -> list[str]:
                     v = item.get('value')
                     if isinstance(v, str) and META_REF.search(v):
                         hints.append(f"[{proc_label}] step[{i}].{kind}[{j}].value 是引用占位 {v[:24]!r} — 应逐字回填数据本身")
-            for di, pair in enumerate(step.get('instruction') or []):
-                if isinstance(pair, list) and len(pair) == 2 and pair[0] == 'directive':
-                    t = pair[1]
-                    if isinstance(t, str) and META_REF.search(t):
-                        hints.append(f"[{proc_label}] step[{i}].instruction[{di}](directive) 是引用占位 {t[:24]!r} — 应填实际 prompt 原文")
+            t = step.get('directive')
+            if isinstance(t, str) and META_REF.search(t):
+                hints.append(f"[{proc_label}] step[{i}].directive 是引用占位 {t[:24]!r} — 应填实际 prompt 原文")
     return hints
 
 

+ 4 - 4
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/render-case.py

@@ -173,10 +173,10 @@ def _minimal_check(d: dict) -> list[str]:
     if not isinstance(d.get('steps'), list):
         errs.append('$.steps: 必须是 array')
         return errs
-    # 所有 step 都要的基础字段; effect/action/focus 仅非 block 步要 (block 是控制容器)
-    step_required = ['id', 'kind', 'via', 'feature', 'inputs', 'outputs', 'intent']
-    exec_only = ['effect', 'action', 'focus']      # kind != block 才要
-    io_required = ['type', 'name', 'value', 'anchor']
+    # 所有 step 都要的基础字段; effect/action 仅非 block 步要 (block 是控制容器)
+    step_required = ['id', 'kind', 'via', 'inputs', 'outputs', 'intent']
+    exec_only = ['effect', 'action']               # kind != block 才要
+    io_required = ['type', 'value', 'anchor']
     for i, step in enumerate(d['steps']):
         if not isinstance(step, dict):
             errs.append(f'$.steps[{i}]: 必须是 object'); continue

+ 56 - 125
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/renderer.py

@@ -160,10 +160,7 @@ def render_intent(text):
             'effect': 'ik-effect',
             'via': 'ik-via',
             'act': 'ik-act',
-            'control': 'ik-control',
             'in-type': 'ik-in-type', 'out-type': 'ik-out-type',
-            'in-sub': 'ik-in-sub',  'out-sub':  'ik-out-sub',
-            'in-form': 'ik-in-form', 'out-form': 'ik-out-form',
         }.get(kind, 'ik-other')
         return f'<span class="intent-tok {kc}">{he(val)}</span>'
     return re.sub(r'\{([\w-]+):([^}]+)\}', sub, text or '')
@@ -223,55 +220,55 @@ def render_focus_class(cell_key, focus_list):
     return ' row-focus' if cell_key in (focus_list or []) else ''
 
 
-def cell_attrs(field_key, focus, inferred_marks, io_reason=None, is_empty=False):
+def cell_attrs(field_key, focus, io_reason=None, is_empty=False):
     """组合 cell 的额外 class 和属性 (focus + 推断补全).
 
-    field_key 例: 'action', 'in-value-0', 'out-substance-1', etc.
-    inferred_marks: step 级 {field_key: 推断理由} dict (field 级推断, 如 "工具未指名").
-    io_reason: 当前 cell 所属 IO item 整体被标 inferred 时, 传入 reason 字符串
-                (优先级低于 inferred_marks 显式 field-level 标注).
-    is_empty: 该 cell 的内容是否为空. 在推断模式下空 cell 转为低置信变体 (角标 推?), 表示
-              "AI 想过但拿不准, 故意留空", 区别于硬补值的高置信「推」. 参 spec §推断补全标记 C.
+    field_key 例: 'action', 'in-value-0', 'out-type-1', etc.
+    io_reason: 当前 cell 所属 IO item 整体被标 inferred 时, 传入 reason 字符串.
+    is_empty: 该 cell 内容是否为空 (留空的推断 cell 角标变 推?).
     返回 (class_suffix_str, extra_attrs_str).
     """
     cls = render_focus_class(field_key, focus)
     extra = ''
-    reason = (inferred_marks or {}).get(field_key) or io_reason
-    if reason:
+    if io_reason:
         cls += ' is-inferred'
         if is_empty:
             cls += ' is-low-confidence'
-        extra = f' title="推断补全: {he(reason)}"'
+        extra = f' title="推断补全: {he(io_reason)}"'
     return cls, extra
 
 
+def render_io_value(item):
+    """IO 值列: output 的 id 作为小标签贴在值前 (供 anchor 1:1 引用对照); input 无 id."""
+    iid = item.get('id')
+    id_tag = f'<span class="io-id" data-io-id="{he(iid)}">{he(iid)}</span> ' if iid else ''
+    return id_tag + render_value(item.get('value'))
+
+
 def render_step_row(step, idx_label, type_reg=None):
-    """渲染一个 step (kind: step / block / nested) 为一组 tr 行.
+    """渲染一个 step (kind: step / block / nested) 为一组 tr 行 (14 列).
 
-    type_reg: 已合并 STDLIB + case-specific 的类型注册表 (用于 in_tree 标记 + case-specific chip 区分).
+    需求组 (rowspan): # / 目的 / 作用 / 实质 / 形式 (后两者 step 级).
+    输入/输出 (逐 IO): 类型 / 值 / 来源(去处). 实现组 (rowspan): 外部工具 / 动作 / 指令.
+    type_reg: 已合并 STDLIB + case-specific 的类型注册表 (用于 chip in_tree 标记).
     """
     inputs = step.get('inputs', [])
     outputs = step.get('outputs', [])
     N = max(len(inputs), len(outputs), 1)
     focus = step.get('focus', [])
-    infm = step.get('inferred_marks', {})
 
     is_nested = step['kind'] == 'nested'
     is_block = step['kind'] == 'block'
-    is_atom = step.get('kind') == 'atom'
 
     main_cls = 'step step-main'
     if is_block:
         main_cls = 'step block-header'
     if is_nested:
         main_cls = 'step step-main step-nested'
-    if is_atom:
-        main_cls = 'step atom-row'
-    sub_cls = 'step step-sub atom-row' if is_atom else 'step step-sub'
+    sub_cls = 'step step-sub'
 
     data_step = step['id']
     data_group = step.get('group', '')
-    parent_step = step.get('parent_step', '')
 
     rows = []
     for k in range(N):
@@ -279,107 +276,62 @@ def render_step_row(step, idx_label, type_reg=None):
         attrs = f' data-step="{data_step}"'
         if data_group:
             attrs += f' data-group="{data_group}"'
-        if parent_step:
-            attrs += f' data-atom-of="{parent_step}"'
         attrs += f' data-focus="{",".join(focus)}"'
-        # anchor id 给主行 (k=0), 用于跨页跳转 (能力浏览页 → 工序页特定 step/atom)
         if k == 0:
-            row_id = f'{parent_step}-{data_step}' if (is_atom and parent_step) else data_step
-            attrs = f' id="{row_id}"' + attrs
+            attrs = f' id="{data_step}"' + attrs
 
         cells = []
         if k == 0:
             rs = f' rowspan="{N}"' if N > 1 else ''
-            if is_atom:
-                cells.append(f'<td class="idx atom-idx"{rs}>↳ {he(idx_label)}</td>')
-            else:
-                arrow = '<span class="arrow">▼</span> ' if is_block else ''
-                indent = '  └ ' if is_nested else ''
-                badge = ''
-                if step.get('atoms'):
-                    n_atoms = len(step['atoms'])
-                    badge = f'<br><span class="atom-badge" data-step="{he(data_step)}" title="显示/隐藏 {n_atoms} 个原子能力">⚛{n_atoms} <span class="atom-arrow">▸</span></span>'
-                cells.append(f'<td class="idx{render_focus_class("idx", focus)}"{rs}>{arrow}{indent}{he(idx_label)}{badge}</td>')
+            arrow = '<span class="arrow">▼</span> ' if is_block else ''
+            indent = '  └ ' if is_nested else ''
+            cells.append(f'<td class="idx{render_focus_class("idx", focus)}"{rs}>{arrow}{indent}{he(idx_label)}</td>')
             intent_html = render_intent(step.get('intent', ''))
-            c, a = cell_attrs('intent', focus, infm)
-            if is_atom:
-                atom_name = he(step.get('name', ''))
-                cells.append(f'<td class="intent{c}"{a}{rs}><div class="atom-name">{atom_name}</div><div class="intent-text">{intent_html}</div></td>')
-            else:
-                cells.append(f'<td class="intent{c}"{a}{rs}><div class="intent-text">{intent_html}</div></td>')
-            c, a = cell_attrs('effect', focus, infm)
+            c, a = cell_attrs('intent', focus)
+            cells.append(f'<td class="intent{c}"{a}{rs}><div class="intent-text">{intent_html}</div></td>')
+            c, a = cell_attrs('effect', focus)
             cells.append(f'<td class="effect{c}"{a}{rs}>{render_path("作用", step.get("effect", ""))}</td>')
+            c, a = cell_attrs('substance', focus)
+            cells.append(f'<td class="substance{c}"{a}{rs}>{render_path("实质", step.get("substance")) if step.get("substance") else ""}</td>')
+            c, a = cell_attrs('form', focus)
+            cells.append(f'<td class="form{c}"{a}{rs}>{render_path("形式", step.get("form")) if step.get("form") else ""}</td>')
 
         in_item = inputs[k] if k < len(inputs) else None
         if in_item:
-            sub = in_item.get('substance'); frm = in_item.get('form')
-            tp = in_item.get('type'); nm = in_item.get('name')
-            vl = in_item.get('value'); ac = in_item.get('anchor')
+            tp = in_item.get('type'); vl = in_item.get('value'); ac = in_item.get('anchor')
             io_inf = in_item.get('inferred_reason') if in_item.get('inferred') else None
-            c, a = cell_attrs(f'in-substance-{k}', focus, infm, io_inf, is_empty=not sub)
-            cells.append(f'<td class="in-substance{c}"{a}>{render_path("实质", sub) if sub else ""}</td>')
-            c, a = cell_attrs(f'in-form-{k}', focus, infm, io_inf, is_empty=not frm)
-            cells.append(f'<td class="in-form{c}"{a}>{render_path("形式", frm) if frm else ""}</td>')
-            c, a = cell_attrs(f'in-type-{k}', focus, infm, io_inf, is_empty=not tp)
+            c, a = cell_attrs(f'in-type-{k}', focus, io_inf, is_empty=not tp)
             cells.append(f'<td class="in-type{c}"{a}>{render_chip(tp)}</td>')
-            c, a = cell_attrs(f'in-name-{k}', focus, infm, io_inf, is_empty=not nm)
-            cells.append(f'<td class="in-name{c}"{a}><span class="name" data-var="{he(nm)}">{he(nm)}</span></td>')
-            c, a = cell_attrs(f'in-value-{k}', focus, infm, io_inf, is_empty=not vl)
-            cells.append(f'<td class="in-value{c}"{a}>{render_value(vl)}</td>')
-            c, a = cell_attrs(f'in-anchor-{k}', focus, infm, io_inf, is_empty=not ac)
+            c, a = cell_attrs(f'in-value-{k}', focus, io_inf, is_empty=not vl)
+            cells.append(f'<td class="in-value{c}"{a}>{render_io_value(in_item)}</td>')
+            c, a = cell_attrs(f'in-anchor-{k}', focus, io_inf, is_empty=not ac)
             cells.append(f'<td class="in-anchor{c}"{a}><span class="flow">{he(ac)}</span></td>')
         else:
-            cells += ['<td class="in-substance"></td>', '<td class="in-form"></td>',
-                     '<td class="in-type"></td>', '<td class="in-name"></td>', '<td class="in-value"></td>',
-                     '<td class="in-anchor"></td>']
+            cells += ['<td class="in-type"></td>', '<td class="in-value"></td>', '<td class="in-anchor"></td>']
 
         if k == 0:
             rs = f' rowspan="{N}"' if N > 1 else ''
-            c, a = cell_attrs('via', focus, infm)
+            c, a = cell_attrs('via', focus)
             cells.append(f'<td class="via{c}"{a}{rs}>{he(step.get("via", ""))}</td>')
-            c, a = cell_attrs('action', focus, infm)
+            c, a = cell_attrs('action', focus)
             cells.append(f'<td class="action{c}"{a}{rs}>{render_path("动作", step.get("action", ""))}</td>')
-            # 指令列拆为 4 个子列: directive / config / decorator / memo
-            # memo = 其他结构化字段没能包含的实现方法信息 (经验性招法 / variant 说明 / 选型理由 等)
-            instr_by_kind = {'directive': [], 'config': [], 'decorator': [], 'memo': []}
-            for kind, txt in step.get('instruction', []):
-                if kind in instr_by_kind:
-                    instr_by_kind[kind].append(txt)
-                else:
-                    # 历史 tag (trick/note) 兼容: 一并合并到 memo
-                    instr_by_kind['memo'].append(txt)
-            for col_name in ('directive', 'config', 'decorator', 'memo'):
-                items = instr_by_kind[col_name]
-                inner = ''.join(f'<div class="instr-item"><span class="natural">{he(t)}</span></div>' for t in items)
-                c, a = cell_attrs(col_name, focus, infm)
-                cells.append(f'<td class="{col_name}{c}"{a}{rs}>{inner}</td>')
-            c, a = cell_attrs('control', focus, infm)
-            cells.append(f'<td class="control{c}"{a}{rs}>{render_path("逻辑控制", step.get("control", ""))}</td>')
-            c, a = cell_attrs('feature', focus, infm)
-            cells.append(f'<td class="feature{c}"{a}{rs}>{render_path("特性", step.get("feature", ""))}</td>')
+            c, a = cell_attrs('directive', focus)
+            directive = step.get('directive', '') or ''
+            inner = f'<span class="natural">{he(directive)}</span>' if directive else ''
+            cells.append(f'<td class="directive{c}"{a}{rs}>{inner}</td>')
 
         out_item = outputs[k] if k < len(outputs) else None
         if out_item:
-            sub = out_item.get('substance'); frm = out_item.get('form')
-            tp = out_item.get('type'); nm = out_item.get('name')
-            vl = out_item.get('value'); ac = out_item.get('anchor')
+            tp = out_item.get('type'); vl = out_item.get('value'); ac = out_item.get('anchor')
             io_inf = out_item.get('inferred_reason') if out_item.get('inferred') else None
-            c, a = cell_attrs(f'out-substance-{k}', focus, infm, io_inf, is_empty=not sub)
-            cells.append(f'<td class="out-substance{c}"{a}>{render_path("实质", sub) if sub else ""}</td>')
-            c, a = cell_attrs(f'out-form-{k}', focus, infm, io_inf, is_empty=not frm)
-            cells.append(f'<td class="out-form{c}"{a}>{render_path("形式", frm) if frm else ""}</td>')
-            c, a = cell_attrs(f'out-type-{k}', focus, infm, io_inf, is_empty=not tp)
+            c, a = cell_attrs(f'out-type-{k}', focus, io_inf, is_empty=not tp)
             cells.append(f'<td class="out-type{c}"{a}>{render_chip(tp)}</td>')
-            c, a = cell_attrs(f'out-name-{k}', focus, infm, io_inf, is_empty=not nm)
-            cells.append(f'<td class="out-name{c}"{a}><span class="name" data-var="{he(nm)}">{he(nm)}</span></td>')
-            c, a = cell_attrs(f'out-value-{k}', focus, infm, io_inf, is_empty=not vl)
-            cells.append(f'<td class="out-value{c}"{a}>{render_value(vl)}</td>')
-            c, a = cell_attrs(f'out-anchor-{k}', focus, infm, io_inf, is_empty=not ac)
+            c, a = cell_attrs(f'out-value-{k}', focus, io_inf, is_empty=not vl)
+            cells.append(f'<td class="out-value{c}"{a}>{render_io_value(out_item)}</td>')
+            c, a = cell_attrs(f'out-anchor-{k}', focus, io_inf, is_empty=not ac)
             cells.append(f'<td class="out-anchor{c}"{a}><span class="flow">{he(ac)}</span></td>')
         else:
-            cells += ['<td class="out-substance"></td>', '<td class="out-form"></td>',
-                     '<td class="out-type"></td>', '<td class="out-name"></td>', '<td class="out-value"></td>',
-                     '<td class="out-anchor"></td>']
+            cells += ['<td class="out-type"></td>', '<td class="out-value"></td>', '<td class="out-anchor"></td>']
 
         rows.append(f'<tr class="{tr_cls}"{attrs}>{"".join(cells)}</tr>')
     return '\n      '.join(rows)
@@ -514,33 +466,24 @@ def render_source(case_data):
 def render_thead():
     return '''<thead>
   <tr>
-    <th colspan="3" class="col-group-demand">需求</th>
-    <th colspan="6" class="col-group-input">输入</th>
-    <th colspan="8" class="col-group-impl">实现</th>
-    <th colspan="6" class="col-group-output">输出</th>
+    <th colspan="5" class="col-group-demand">需求</th>
+    <th colspan="3" class="col-group-input">输入</th>
+    <th colspan="3" class="col-group-impl">实现</th>
+    <th colspan="3" class="col-group-output">输出</th>
   </tr>
   <tr>
     <th class="col-idx">#</th>
     <th class="col-intent">目的</th>
     <th class="col-effect">作用</th>
-    <th class="col-in-substance">实质</th>
-    <th class="col-in-form">形式</th>
+    <th class="col-substance">实质</th>
+    <th class="col-form">形式</th>
     <th class="col-in-type">类型</th>
-    <th class="col-in-name">变量名</th>
     <th class="col-in-value">值</th>
     <th class="col-in-anchor">来源</th>
     <th class="col-via">外部工具</th>
     <th class="col-action">动作</th>
     <th class="col-directive">指令</th>
-    <th class="col-config">配置</th>
-    <th class="col-decorator">运行</th>
-    <th class="col-memo">备注</th>
-    <th class="col-control">逻辑控制</th>
-    <th class="col-feature">特性</th>
-    <th class="col-out-substance">实质</th>
-    <th class="col-out-form">形式</th>
     <th class="col-out-type">类型</th>
-    <th class="col-out-name">变量名</th>
     <th class="col-out-value">值</th>
     <th class="col-out-anchor">去处</th>
   </tr>
@@ -554,13 +497,12 @@ def render_legend():
       <span class="col-toggle" data-col="idx">#</span>
       <span class="col-toggle" data-col="intent">目的</span>
       <span class="col-toggle" data-col="effect">作用</span>
+      <span class="col-toggle" data-col="substance">实质</span>
+      <span class="col-toggle" data-col="form">形式</span>
     </div>
     <div class="group yellow">
       <span class="gh">输入</span>
-      <span class="col-toggle" data-col="in-substance">实质</span>
-      <span class="col-toggle" data-col="in-form">形式</span>
       <span class="col-toggle" data-col="in-type">类型</span>
-      <span class="col-toggle" data-col="in-name">变量名</span>
       <span class="col-toggle" data-col="in-value">值</span>
       <span class="col-toggle" data-col="in-anchor">来源</span>
     </div>
@@ -569,18 +511,10 @@ def render_legend():
       <span class="col-toggle" data-col="via">外部工具</span>
       <span class="col-toggle" data-col="action">动作</span>
       <span class="col-toggle" data-col="directive">指令</span>
-      <span class="col-toggle" data-col="config">配置</span>
-      <span class="col-toggle" data-col="decorator">运行</span>
-      <span class="col-toggle" data-col="memo">备注</span>
-      <span class="col-toggle" data-col="control">逻辑控制</span>
-      <span class="col-toggle" data-col="feature">特性</span>
     </div>
     <div class="group blue">
       <span class="gh">输出</span>
-      <span class="col-toggle" data-col="out-substance">实质</span>
-      <span class="col-toggle" data-col="out-form">形式</span>
       <span class="col-toggle" data-col="out-type">类型</span>
-      <span class="col-toggle" data-col="out-name">变量名</span>
       <span class="col-toggle" data-col="out-value">值</span>
       <span class="col-toggle" data-col="out-anchor">去处</span>
     </div>
@@ -662,11 +596,9 @@ def build_html(case_data: dict) -> str:
         body_rows = []
         for step in proc.get('steps', []):
             body_rows.append(render_step_row(step, step['id'], type_reg))
-            for atom in step.get('atoms', []):
-                body_rows.append(render_step_row(atom, atom['id'], type_reg))
         rr = proc.get('return_row') or {}
         if rr:
-            body_rows.append(f'<tr class="return-row"><td class="idx">{rr.get("arrow", "↩")}</td><td colspan="24">{rr.get("text", "")}</td></tr>')
+            body_rows.append(f'<tr class="return-row"><td class="idx">{rr.get("arrow", "↩")}</td><td colspan="13">{rr.get("text", "")}</td></tr>')
         proc_tbody = '<tbody>\n      ' + '\n      '.join(body_rows) + '\n    </tbody>'
 
         proc_id_attr = he(proc.get('id', ''))
@@ -687,7 +619,6 @@ def build_html(case_data: dict) -> str:
         '作用': EFFECT_TREE,
         '动作': ACTION_TREE,
         '类型': TYPE_TREE,
-        '特性': FEATURE_TAXONOMY,
         '实质': EXTERNAL_TAXONOMIES['实质'],
         '形式': EXTERNAL_TAXONOMIES['形式'],
     }

+ 4 - 40
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/script.js

@@ -120,10 +120,10 @@ document.querySelectorAll('tr.block-header').forEach(b => {
 
 // ───────── column visibility (legend toggle) ─────────
 const COL_GROUPS = {
-  'demand': { headerSel: 'th.col-group-demand', cols: ['idx','intent','effect'] },
-  'input':  { headerSel: 'th.col-group-input',  cols: ['in-substance','in-form','in-type','in-name','in-value','in-anchor'] },
-  'impl':   { headerSel: 'th.col-group-impl',   cols: ['via','action','directive','config','decorator','memo','control','feature'] },
-  'output': { headerSel: 'th.col-group-output', cols: ['out-substance','out-form','out-type','out-name','out-value','out-anchor'] },
+  'demand': { headerSel: 'th.col-group-demand', cols: ['idx','intent','effect','substance','form'] },
+  'input':  { headerSel: 'th.col-group-input',  cols: ['in-type','in-value','in-anchor'] },
+  'impl':   { headerSel: 'th.col-group-impl',   cols: ['via','action','directive'] },
+  'output': { headerSel: 'th.col-group-output', cols: ['out-type','out-value','out-anchor'] },
 };
 
 function setColVisible(col, visible) {
@@ -192,39 +192,3 @@ if (infBtn) {
   });
 }
 
-// ───────── 原子能力 atom badge toggle ─────────
-// 点击 step 行 idx 列的 ⚛N 徽章, 展开/收起该 step 下的 atom 子行 (默认全收起)
-document.querySelectorAll('.atom-badge').forEach(b => {
-  b.addEventListener('click', (e) => {
-    e.stopPropagation();
-    const step = b.getAttribute('data-step');
-    const atoms = document.querySelectorAll(`tr.atom-row[data-atom-of="${step}"]`);
-    const open = b.classList.toggle('open');
-    atoms.forEach(a => a.classList.toggle('show', open));
-    const arrow = b.querySelector('.atom-arrow');
-    if (arrow) arrow.textContent = open ? '▾' : '▸';
-  });
-});
-
-// ───────── 跨页跳转: 处理 URL hash 指向 atom ─────────
-// 当 URL 是 case-N.html#sX-aY 时, 自动展开该 atom 的全部子行 + 打开父 step 徽章
-// (单独的 :target CSS 只对主行生效, sub-rows 仍隐藏, 需 JS 补)
-function expandTargetAtom() {
-  const hash = decodeURIComponent(location.hash.slice(1));
-  if (!hash) return;
-  const target = document.getElementById(hash);
-  if (!target || !target.classList.contains('atom-row')) return;
-  const step = target.getAttribute('data-step');
-  const parent = target.getAttribute('data-atom-of');
-  document.querySelectorAll(`tr.atom-row[data-step="${step}"][data-atom-of="${parent}"]`)
-    .forEach(r => r.classList.add('show'));
-  const badge = document.querySelector(`.atom-badge[data-step="${parent}"]`);
-  if (badge) {
-    badge.classList.add('open');
-    const arrow = badge.querySelector('.atom-arrow');
-    if (arrow) arrow.textContent = '▾';
-  }
-  setTimeout(() => target.scrollIntoView({behavior: 'smooth', block: 'center'}), 80);
-}
-expandTargetAtom();
-window.addEventListener('hashchange', expandTargetAtom);

+ 19 - 58
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/styles.css

@@ -100,11 +100,9 @@ table.proc td.decorator, table.proc td.memo {
   white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere;
   max-width: 280px;
 }
-/* 实质/形式 列 — 内容是短路径, 收窄列宽强制换行 (避免空旷低信息密度) */
-table.proc th.col-in-substance, table.proc td.in-substance,
-table.proc th.col-out-substance, table.proc td.out-substance,
-table.proc th.col-in-form, table.proc td.in-form,
-table.proc th.col-out-form, table.proc td.out-form { width: 90px; min-width: 90px; max-width: 90px;
+/* 实质/形式 列 (step 级) — 内容是短路径, 收窄列宽强制换行 (避免空旷低信息密度) */
+table.proc th.col-substance, table.proc td.substance,
+table.proc th.col-form, table.proc td.form { width: 90px; min-width: 90px; max-width: 90px;
   word-break: break-all; overflow-wrap: anywhere; }
 table.proc th.col-in-type, table.proc th.col-out-type           { min-width: 90px;  }
 table.proc th.col-in-name, table.proc th.col-out-name           { min-width: 110px; }
@@ -131,11 +129,13 @@ table.proc thead th.col-intent,
 table.proc thead th.col-effect { z-index: 5; }
 
 /* 颜色分组背景 */
-table.proc td.idx, table.proc td.intent, table.proc td.effect { background: #f8fafc; }
+table.proc td.idx, table.proc td.intent, table.proc td.effect, table.proc td.substance, table.proc td.form { background: #f8fafc; }
 table.proc thead th.col-group-demand { background: #1e293b; color: #fff; }
 table.proc thead tr:nth-child(2) th.col-idx,
 table.proc thead tr:nth-child(2) th.col-intent,
-table.proc thead tr:nth-child(2) th.col-effect { background: #475569; color: #fff; }
+table.proc thead tr:nth-child(2) th.col-effect,
+table.proc thead tr:nth-child(2) th.col-substance,
+table.proc thead tr:nth-child(2) th.col-form { background: #475569; color: #fff; }
 table.proc td.in-substance, table.proc td.in-form, table.proc td.in-type, table.proc td.in-name, table.proc td.in-value, table.proc td.in-anchor { background: #fefce8; }
 table.proc thead th.col-group-input { background: #b45309; color: #fff; }
 table.proc thead tr:nth-child(2) th.col-in-substance,
@@ -164,10 +164,10 @@ table.proc thead tr:nth-child(2) th.col-out-name,
 table.proc thead tr:nth-child(2) th.col-out-value,
 table.proc thead tr:nth-child(2) th.col-out-anchor { background: #2563eb; color: #fff; }
 
-/* 组间分隔粗线 */
-table.proc th.col-effect, table.proc td.effect,
+/* 组间分隔粗线 (需求|输入 在 form 后; 输入|实现 在 来源后; 实现|输出 在 指令后) */
+table.proc th.col-form, table.proc td.form,
 table.proc th.col-in-anchor, table.proc td.in-anchor,
-table.proc th.col-feature, table.proc td.feature { border-right: 3px solid #94a3b8; }
+table.proc th.col-directive, table.proc td.directive { border-right: 3px solid #94a3b8; }
 
 /* 行边框 / 块头 / nested */
 table.proc tr.step-main > td { border-top: 1.5px solid #94a3b8; }
@@ -176,12 +176,7 @@ table.proc tr.block-header { font-weight: 600; }
 table.proc tr.block-header > td.intent { background: #e2e8f0; }
 table.proc tr.step-nested > td.idx { color: #6b7280; }
 
-/* ───────── 原子能力 atom rows + badge ─────────
-   atom = step 沿单个 (实质 OR 形式) 维度的投影. 默认全收起, 点击 step 行 idx 列的 ⚛N 徽章展开/收起. */
-table.proc tr.atom-row { display: none; }
-table.proc tr.atom-row.show, table.proc tr.atom-row:target { display: table-row; }
-
-/* :target 高亮 — 从能力浏览页跳转过来时让对应 step/atom 行闪烁定位 */
+/* :target 高亮 — 从其他页跳转过来时让对应 step 行闪烁定位 */
 table.proc tr:target > td {
   animation: rowTargetFlash 1.6s ease-out;
   box-shadow: inset 4px 0 0 #6d28d9;
@@ -190,46 +185,13 @@ table.proc tr:target > td {
   0%   { background-color: #fef3c7 !important; }
   100% { background-color: inherit; }
 }
-table.proc tr.atom-row > td { border-top: 1px dotted #d8b4fe !important; }
-/* atom 行整体淡紫底, sticky 三列 (idx/intent/effect) 加深一档 */
-table.proc tr.atom-row > td.in-substance, table.proc tr.atom-row > td.in-form,
-table.proc tr.atom-row > td.in-type, table.proc tr.atom-row > td.in-name,
-table.proc tr.atom-row > td.in-value, table.proc tr.atom-row > td.in-anchor {
-  background: #fdf4ff !important;
-}
-table.proc tr.atom-row > td.via, table.proc tr.atom-row > td.action,
-table.proc tr.atom-row > td.directive, table.proc tr.atom-row > td.config,
-table.proc tr.atom-row > td.decorator, table.proc tr.atom-row > td.memo,
-table.proc tr.atom-row > td.control, table.proc tr.atom-row > td.feature {
-  background: #faf5ff !important;
-}
-table.proc tr.atom-row > td.out-substance, table.proc tr.atom-row > td.out-form,
-table.proc tr.atom-row > td.out-type, table.proc tr.atom-row > td.out-name,
-table.proc tr.atom-row > td.out-value, table.proc tr.atom-row > td.out-anchor {
-  background: #fdf4ff !important;
-}
-table.proc tr.atom-row > td.idx, table.proc tr.atom-row > td.intent,
-table.proc tr.atom-row > td.effect {
-  background: #f3e8ff !important;
-}
-table.proc tr.atom-row > td.idx.atom-idx {
-  color: #6d28d9; font-style: italic; text-align: center; font-size: 11px;
-}
-table.proc tr.atom-row .atom-name {
-  color: #6d28d9; font-weight: 600; font-size: 11.5px; margin-bottom: 4px;
-  padding: 1px 6px; background: #ede9fe; border-radius: 3px; display: inline-block;
-}
 
-/* atom badge — 挂在 step 行 idx 列下方, 点击展开/收起该 step 的 atoms */
-.atom-badge {
-  display: inline-block; margin-top: 4px; padding: 1px 5px;
-  font-size: 9.5px; background: #ede9fe; color: #6d28d9;
-  border-radius: 8px; cursor: pointer; user-select: none;
-  font-weight: 600; white-space: nowrap; line-height: 1.3;
+/* output 的 id 小标签 (贴在值前, 供 anchor 1:1 引用对照) */
+.io-id {
+  display: inline-block; margin-right: 4px; padding: 0 4px;
+  font-size: 10px; font-family: ui-monospace, "SF Mono", monospace;
+  color: #475569; background: #e2e8f0; border-radius: 3px; vertical-align: top;
 }
-.atom-badge:hover { background: #ddd6fe; }
-.atom-badge.open { background: #6d28d9; color: #fff; }
-.atom-badge .atom-arrow { font-size: 8px; }
 
 /* 返回行 */
 tr.return-row > td { background: #fde68a !important; font-weight: 600; padding: 8px; }
@@ -271,13 +233,12 @@ table.proc td.out-type .chip { background: #bfdbfe !important; color: #1e3a8a; }
 .intent-tok.ik-out-form  { background: #dbeafe; color: #1e40af; font-style: italic; }
 
 /* substance/form 路径文本 */
-td.in-substance > span, td.in-form > span,
-td.out-substance > span, td.out-form > span {
+td.substance > span, td.form > span {
   display: inline-block; padding: 1px 4px; border-radius: 2px; font-size: 11px;
   color: #1f2937; background: rgba(255,255,255,0.6); border: 1px solid rgba(0,0,0,0.06);
   word-break: break-all; line-height: 1.4; cursor: pointer;
 }
-td.effect > span, td.action > span, td.feature > span {
+td.effect > span, td.action > span {
   display: inline-block; padding: 1px 5px; border-radius: 2px; font-size: 11.5px;
   color: #0f172a; background: rgba(255,255,255,0.7); cursor: pointer; border: 1px solid rgba(0,0,0,0.06);
 }
@@ -289,7 +250,7 @@ td.directive .instr-item, td.config .instr-item, td.decorator .instr-item, td.me
 
 /* row-focus 加深底色 */
 td.row-focus { font-weight: 600; color: #0f172a; }
-td.idx.row-focus, td.intent.row-focus, td.effect.row-focus { background: #e2e8f0 !important; }
+td.idx.row-focus, td.intent.row-focus, td.effect.row-focus, td.substance.row-focus, td.form.row-focus { background: #e2e8f0 !important; }
 td.in-substance.row-focus, td.in-form.row-focus, td.in-type.row-focus, td.in-name.row-focus, td.in-value.row-focus, td.in-anchor.row-focus { background: #fde68a !important; }
 td.via.row-focus, td.action.row-focus, td.directive.row-focus, td.config.row-focus,
 td.decorator.row-focus, td.memo.row-focus, td.control.row-focus, td.feature.row-focus { background: #bbf7d0 !important; }

+ 32 - 95
examples/process_pipeline/script/search_eval/procedure-dsl/spec/tools/wf-patch.py

@@ -34,8 +34,8 @@ wf-patch.py — workflow.json 的安全批量字段设置器.
     python spec/tools/wf-patch.py --workflow ... --set '...' --dry-run
 
 路径语法 (proc / step 按 id 寻址, 不是下标; 只有真列表才用 [i]; 嵌套步 id 带点 s2.1 也支持):
-    p1.s2.effect                      step 标量字段 (effect/via/action/feature/control/kind/intent/group)
-    p1.s1.inputs[0].anchor            IO 字段 (anchor/type/substance/form/name/value)
+    p1.s2.effect                      step 标量字段 (effect/substance/form/via/action/directive/kind/intent/group)
+    p1.s1.inputs[0].anchor            IO 字段 (anchor/type/value/id)
     p1.s2.focus                       step 的 focus 数组 (逗号分隔: focus=via,action,out-type-0)
     p1.purpose                        procedure 头部字段 (name/purpose/category/platform/author)
     p1.declarations.inputs[0].desc    declarations 内任意字段 (通用下钻)
@@ -82,9 +82,7 @@ for _s in (sys.stdout, sys.stderr):
         except Exception:
             pass
 
-# 受控词 (与 syntax.md §3 / action.json $control 对齐)
-FEATURE_VOCAB = {'随机', '幂等', '人工', '本地', '写外部', '读外部', '-'}
-KIND_VOCAB = {'step', 'block', 'nested', 'atom'}
+KIND_VOCAB = {'step', 'block', 'nested'}
 
 # value/directive 里的「引用占位」文案 — 这些是 anchor 的活, value 应填数据本身.
 # 命中即视为「未真正回填」(--resolve-passthrough 会尝试填, lint 会报警).
@@ -173,7 +171,6 @@ def _load_tree(name: str):
 EFFECT_LEAVES, EFFECT_PATHS, _ = _load_tree('effect')
 ACTION_LEAVES, ACTION_PATHS, ACTION_CONTROL = _load_tree('action')
 TYPE_LEAVES, TYPE_PATHS, _ = _load_tree('type')
-CONTROL_VOCAB = set(ACTION_CONTROL) | {'-'}
 
 # substance/form 校验结果缓存 (subprocess 较慢)
 _taxo_cache: dict[tuple[str, str], bool] = {}
@@ -303,16 +300,6 @@ def validate_field(field: str, value, proc: dict, pending_types: set[str] = None
             return True, value, ''
         return False, value, f'anchor={value!r} 须以 ← (输入引用) 或 → (输出去向) 开头'
 
-    if field == 'feature':
-        if value in FEATURE_VOCAB:
-            return True, value, ''
-        return False, value, f'feature={value!r} 不在受控词 {sorted(FEATURE_VOCAB)}'
-
-    if field == 'control':
-        if value in CONTROL_VOCAB:
-            return True, value, ''
-        return False, value, f'control={value!r} 不在受控词 {sorted(CONTROL_VOCAB)}'
-
     if field == 'kind':
         if value in KIND_VOCAB:
             return True, value, ''
@@ -442,62 +429,31 @@ def _is_fillable(value) -> bool:
     return bool(META_REF.search(str(value)))
 
 
-def _parse_passthrough(anchor, step_ids: list[str]):
-    """把 anchor 解析成纯透传源 (src_step, src_name); 非干净透传返回 None.
+def _passthrough_id(anchor):
+    """anchor 为 `← <output-id>` (可带 [i] 容器索引) → 返回 output id; 否则 None.
 
-    只认 `← sN.varname` 形式 (sN 按已知 step id 最长前缀匹配, 兼容 s2.1);
-    `← 工序输入` / `← s6 (链, 上一张)` / 带容器索引等不算 (无法确定唯一源 value).
-    varname 末尾的 [i] / (...) 注释会被剥掉再查.
+    `← 工序输入` / `← s6 (链)` 等非纯 id 引用返回 None (无法确定唯一源 value).
     """
-    m = re.match(r'^\s*←\s*(.+)$', str(anchor or ''))
+    m = re.match(r'^\s*←\s*([^\s\[((]+)', str(anchor or ''))
     if not m:
         return None
-    body = m.group(1).strip()
-    for sid in sorted(step_ids, key=len, reverse=True):
-        if body.startswith(sid + '.'):
-            name = body[len(sid) + 1:].strip()
-            name = re.sub(r'\s*[\[((].*$', '', name).strip()   # 剥掉 [i] / (注释)
-            return (sid, name) if name else None
-    return None
-
-
-def _extract_ref(text, step_ids: list[str]):
-    """从 directive/文案里抽 (src_step, src_name) 引用; 抽不出返回 None.
-
-    认「同 sN.name」「(同 sN.name 全文)」「见 sN.name」等. sN 按已知 step id
-    最长前缀匹配 (兼容 s2.1).
-    """
-    m = re.search(r'[同见]\s*([^\s)),,。]+)', str(text or ''))
-    if not m:
-        return None
-    body = m.group(1)
-    for sid in sorted(step_ids, key=len, reverse=True):
-        if body.startswith(sid + '.'):
-            name = re.sub(r'\s*[\[((].*$', '', body[len(sid) + 1:]).strip()
-            return (sid, name) if name else None
-    return None
+    return m.group(1) or None
 
 
 def resolve_passthrough(data: dict):
-    """把 anchor 为纯透传、value/directive 仍空或占位的位置, 用源 output 的 value 逐字填上.
+    """把 anchor 为纯透传 (← <output-id>)、value 仍空或占位的 input, 用源 output 的 value 逐字填上.
 
-    覆盖两类: (a) IO 的 value (anchor=← sN.varname); (b) instruction 的 directive
-    (文案里「同 sN.varname」). 迭代到不动点 (处理链式透传). 返回 (filled_msgs, warn_msgs).
+    迭代到不动点 (处理链式透传). 返回 (filled_msgs, warn_msgs).
     """
-    out_index = {}          # (step_id, name) -> output item (读 value)
-    step_ids: list[str] = []
+    out_index = {}          # output id -> output item (读 value)
     for p in data.get('procedures') or []:
         for s in p.get('steps') or []:
-            sid = s.get('id')
-            if sid:
-                step_ids.append(sid)
             for o in s.get('outputs') or []:
-                if isinstance(o, dict) and o.get('name'):
-                    out_index[(sid, o['name'])] = o
+                if isinstance(o, dict) and o.get('id'):
+                    out_index[o['id']] = o
 
-    def _src_value(ref):
-        """源存在且自己已填好 → 返回其 value; 否则 None."""
-        src = out_index.get(ref)
+    def _src_value(rid):
+        src = out_index.get(rid)
         if src is None or _is_fillable(src.get('value')):
             return None
         return src['value']
@@ -508,52 +464,33 @@ def resolve_passthrough(data: dict):
         changed, rounds = False, rounds + 1
         for p in data.get('procedures') or []:
             for s in p.get('steps') or []:
-                # (a) IO value
-                for kind in ('inputs', 'outputs'):
-                    for idx, io in enumerate(s.get(kind) or []):
-                        if not isinstance(io, dict) or not _is_fillable(io.get('value')):
-                            continue
-                        pt = _parse_passthrough(io.get('anchor'), step_ids)
-                        val = _src_value(pt) if pt else None
-                        if val is None:
-                            continue
-                        io['value'] = val
-                        filled.append(
-                            f"{p.get('id')}.{s.get('id')}.{kind}[{idx}].value "
-                            f"← 复制自 {pt[0]}.{pt[1]} ({len(str(val))} 字)"
-                        )
-                        changed = True
-                # (b) instruction directive (喂给工具的 prompt = 引用的 output 原文)
-                for di, pair in enumerate(s.get('instruction') or []):
-                    if not (isinstance(pair, list) and len(pair) == 2 and pair[0] == 'directive'):
-                        continue
-                    if not _is_fillable(pair[1]):
+                for idx, io in enumerate(s.get('inputs') or []):
+                    if not isinstance(io, dict) or not _is_fillable(io.get('value')):
                         continue
-                    ref = _extract_ref(pair[1], step_ids)
-                    val = _src_value(ref) if ref else None
+                    rid = _passthrough_id(io.get('anchor'))
+                    val = _src_value(rid) if rid else None
                     if val is None:
                         continue
-                    pair[1] = val
+                    io['value'] = val
                     filled.append(
-                        f"{p.get('id')}.{s.get('id')}.instruction[{di}](directive) "
-                        f"← 复制自 {ref[0]}.{ref[1]} ({len(str(val))} 字)"
+                        f"{p.get('id')}.{s.get('id')}.inputs[{idx}].value "
+                        f"← 复制自 {rid} ({len(str(val))} 字)"
                     )
                     changed = True
 
-    # 仍填不动的透传 (源找不到) → warn
+    # 仍填不动的透传 (源 id 找不到) → warn
     warns: list[str] = []
     for p in data.get('procedures') or []:
         for s in p.get('steps') or []:
-            for kind in ('inputs', 'outputs'):
-                for idx, io in enumerate(s.get(kind) or []):
-                    if not isinstance(io, dict) or not _is_fillable(io.get('value')):
-                        continue
-                    pt = _parse_passthrough(io.get('anchor'), step_ids)
-                    if pt and out_index.get(pt) is None:
-                        warns.append(
-                            f"{p.get('id')}.{s.get('id')}.{kind}[{idx}] anchor 指向 "
-                            f"{pt[0]}.{pt[1]} 但找不到该 output (检查 anchor / 变量名)"
-                        )
+            for idx, io in enumerate(s.get('inputs') or []):
+                if not isinstance(io, dict) or not _is_fillable(io.get('value')):
+                    continue
+                rid = _passthrough_id(io.get('anchor'))
+                if rid and out_index.get(rid) is None:
+                    warns.append(
+                        f"{p.get('id')}.{s.get('id')}.inputs[{idx}] anchor 指向 "
+                        f"{rid} 但找不到该 output id (检查 anchor / output id)"
+                    )
     return filled, warns
 
 

+ 15065 - 221
examples/process_pipeline/script/search_eval/runs_full/forms_preview.json

@@ -200,20 +200,20 @@
   "33": {
     "idx": 33,
     "A": "在线 元素生成 提示词 技巧",
-    "B": "在线生成元素提示词的技巧",
-    "C": "网页版 创作 prompt 方法"
+    "B": "怎么写出更好的元素生成提示词",
+    "C": "在线 生成 咒语 步骤"
   },
   "34": {
     "idx": 34,
     "A": "代码 元素生成 提示词 技巧",
-    "B": "代码生成元素提示词的技巧",
-    "C": "命令行 怎么做 提示词 流程"
+    "B": "代码时如何优化元素生成提示词",
+    "C": "代码 制作 提示词 教学"
   },
   "35": {
     "idx": 35,
     "A": "插件 元素生成 提示词 技巧",
-    "B": "插件生成元素提示词的技巧",
-    "C": "插件 生成 提示词 教程"
+    "B": "使用扩展功能时怎么写元素生成提示词",
+    "C": "插件 创作 提示词 方法"
   },
   "36": {
     "idx": 36,
@@ -230,92 +230,92 @@
   "38": {
     "idx": 38,
     "A": "软件 风格化 提示词 教程",
-    "B": "软件制作风格化提示词的教程",
-    "C": "软件 转风格 咒语 怎么做"
+    "B": "如何使用软件进行风格化提示词设置的教程",
+    "C": "软件 风格化 咒语 步骤"
   },
   "39": {
     "idx": 39,
     "A": "在线 风格化 提示词 教程",
-    "B": "在线制作风格化提示词的教程",
-    "C": "在线 怎么转风格 prompt 方法"
+    "B": "在线进行风格化提示词设置的教程",
+    "C": "在线 转风格 提示词 教学"
   },
   "40": {
     "idx": 40,
     "A": "代码 风格化 提示词 教程",
-    "B": "代码制作风格化提示词的教程",
-    "C": "命令行 风格迁移 咒语 教程"
+    "B": "通过代码实现风格化提示词的教程",
+    "C": "代码 风格化 咒语 怎么做"
   },
   "41": {
     "idx": 41,
     "A": "插件 风格化 提示词 教程",
-    "B": "插件制作风格化提示词的教程",
-    "C": "插件 风格迁移 咒语 步骤"
+    "B": "风格化提示词插件使用教程",
+    "C": "插件 风格化 提示词 流程"
   },
   "43": {
     "idx": 43,
     "A": "AI 风格化 提示词 工具",
-    "B": "智能风格化提示词生成工具",
-    "C": "AI 风格迁移 prompt 流程"
+    "B": "好用的风格化提示词生成工具",
+    "C": "AI 风格化 咒语 流程"
   },
   "44": {
     "idx": 44,
     "A": "软件 风格化 提示词 工具",
-    "B": "软件风格化提示词生成工具",
-    "C": "电脑端 风格化 咒语 教学"
+    "B": "适合风格化提示词的软件工具",
+    "C": "电脑端 转风格 prompt 方法"
   },
   "45": {
     "idx": 45,
     "A": "在线 风格化 提示词 工具",
-    "B": "在线风格化提示词生成工具",
-    "C": "网页版 转风格 咒语 教程"
+    "B": "在线生成风格化提示词的工具",
+    "C": "网页版 风格化 提示词 教学"
   },
   "46": {
     "idx": 46,
     "A": "代码 风格化 提示词 工具",
-    "B": "代码风格化提示词生成工具",
-    "C": "命令行 转风格 提示词 步骤"
+    "B": "用于风格化提示词的代码工具",
+    "C": "命令行 风格迁移 prompt 流程"
   },
   "47": {
     "idx": 47,
     "A": "插件 风格化 提示词 工具",
-    "B": "插件风格化提示词生成工具",
-    "C": "插件 风格化 咒语 步骤"
+    "B": "风格化提示词插件工具",
+    "C": "插件 风格迁移 提示词 教程"
   },
   "49": {
     "idx": 49,
     "A": "AI 风格化 提示词 技巧",
-    "B": "智能风格化提示词的编写技巧",
-    "C": "AI 风格化 提示词 步骤"
+    "B": "提升风格化提示词效果的技巧",
+    "C": "AI 风格化 prompt 步骤"
   },
   "50": {
     "idx": 50,
     "A": "软件 风格化 提示词 技巧",
-    "B": "软件风格化提示词的编写技巧",
-    "C": "电脑端 转风格 提示词 流程"
+    "B": "软件中设置风格化提示词的技巧",
+    "C": "电脑端 风格化 咒语 怎么做"
   },
   "51": {
     "idx": 51,
     "A": "在线 风格化 提示词 技巧",
-    "B": "在线风格化提示词的编写技巧",
-    "C": "在线 风格化 咒语 怎么做"
+    "B": "在线编辑风格化提示词的技巧",
+    "C": "在线 怎么转风格 提示词 方法"
   },
   "52": {
     "idx": 52,
     "A": "代码 风格化 提示词 技巧",
-    "B": "代码风格化提示词的编写技巧",
-    "C": "代码 转风格 提示词 教学"
+    "B": "编写风格化提示词的代码技巧",
+    "C": "命令行 风格迁移 咒语 流程"
   },
   "53": {
     "idx": 53,
     "A": "插件 风格化 提示词 技巧",
-    "B": "插件风格化提示词的编写技巧",
-    "C": "插件 转风格 prompt 方法"
+    "B": "使用风格化提示词插件的技巧",
+    "C": "插件 风格化 咒语 流程"
   },
   "54": {
     "idx": 54,
     "A": "键入 负向提示词 教程",
-    "B": "怎么输入负向提示词的教程",
-    "C": "编写 负向提示词 方法"
+    "B": "如何输入负向提示词的教程",
+    "C": "怎么写 负向提示词 流程"
   },
   "55": {
     "idx": 55,
@@ -326,92 +326,92 @@
   "56": {
     "idx": 56,
     "A": "软件 键入 负向提示词 教程",
-    "B": "软件输入负向提示词的教程",
-    "C": "软件 怎么写 反向提示词 教学"
+    "B": "软件输入负向提示词的教程",
+    "C": "软件 编写 反向提示词 怎么做"
   },
   "57": {
     "idx": 57,
     "A": "在线 键入 负向提示词 教程",
     "B": "在线输入负向提示词的教程",
-    "C": "网页版 编写 negative prompt 怎么做"
+    "C": "网页版 输入 反向提示词 步骤"
   },
   "58": {
     "idx": 58,
     "A": "代码 键入 负向提示词 教程",
-    "B": "代码输入负向提示词的教程",
-    "C": "代码 输入 负向提示词 教程"
+    "B": "通过代码输入负向提示词的教程",
+    "C": "代码 怎么写 negative prompt 教学"
   },
   "59": {
     "idx": 59,
     "A": "插件 键入 负向提示词 教程",
-    "B": "插件输入负向提示词的教程",
-    "C": "插件 写 negative prompt 方法"
+    "B": "负向提示词插件使用教程",
+    "C": "插件 输入 negative prompt 教学"
   },
   "60": {
     "idx": 60,
     "A": "键入 负向提示词 工具",
-    "B": "输入负向提示词的工具推荐",
-    "C": "输入 negative prompt 流程"
+    "B": "好用的负向提示词输入工具",
+    "C": "输入 负向提示词 怎么做"
   },
   "61": {
     "idx": 61,
     "A": "AI 键入 负向提示词 工具",
     "B": "智能输入负向提示词的工具",
-    "C": "AI 写 negative prompt 教学"
+    "C": "AI 怎么写 negative prompt 教学"
   },
   "62": {
     "idx": 62,
     "A": "软件 键入 负向提示词 工具",
-    "B": "软件输入负向提示词的工具",
-    "C": "软件 输入 负向提示词 教程"
+    "B": "软件配套的负向提示词输入工具",
+    "C": "软件 怎么写 负向提示词 流程"
   },
   "63": {
     "idx": 63,
     "A": "在线 键入 负向提示词 工具",
     "B": "在线输入负向提示词的工具",
-    "C": "网页版 写 negative prompt 流程"
+    "C": "在线 怎么写 反向提示词 步骤"
   },
   "64": {
     "idx": 64,
     "A": "代码 键入 负向提示词 工具",
-    "B": "代码输入负向提示词的工具",
-    "C": "命令行 编写 负向提示词 方法"
+    "B": "负向提示词代码编写工具",
+    "C": "代码 输入 negative prompt 教学"
   },
   "65": {
     "idx": 65,
     "A": "插件 键入 负向提示词 工具",
-    "B": "插件输入负向提示词的工具",
-    "C": "插件 编写 负向提示词 怎么做"
+    "B": "负向提示词插件工具",
+    "C": "插件 输入 negative prompt 怎么做"
   },
   "66": {
     "idx": 66,
     "A": "键入 负向提示词 技巧",
-    "B": "输入负向提示词有什么技巧",
-    "C": "编写 负向提示词 教程"
+    "B": "输入负向提示词技巧",
+    "C": "编写 negative prompt 怎么做"
   },
   "68": {
     "idx": 68,
     "A": "软件 键入 负向提示词 技巧",
-    "B": "软件输入负向提示词的技巧",
-    "C": "软件 编写 反向提示词 怎么做"
+    "B": "软件输入负向提示词的技巧",
+    "C": "软件 怎么写 负向提示词 流程"
   },
   "69": {
     "idx": 69,
     "A": "在线 键入 负向提示词 技巧",
     "B": "在线输入负向提示词的技巧",
-    "C": "网页版 编写 negative prompt 教程"
+    "C": "网页版 编写 negative prompt 怎么做"
   },
   "70": {
     "idx": 70,
     "A": "代码 键入 负向提示词 技巧",
-    "B": "代码输入负向提示词的技巧",
-    "C": "代码 写 反向提示词 教学"
+    "B": "编写负向提示词的代码技巧",
+    "C": "命令行 输入 负向提示词 方法"
   },
   "71": {
     "idx": 71,
     "A": "插件 键入 负向提示词 技巧",
-    "B": "插件输入负向提示词的技巧",
-    "C": "插件 写 负向提示词 程"
+    "B": "使用负向提示词插件的技巧",
+    "C": "插件 写 负向提示词 程"
   },
   "72": {
     "idx": 72,
@@ -423,145 +423,145 @@
     "idx": 74,
     "A": "软件 反推 负向提示词 教程",
     "B": "软件反推负向提示词的教程",
-    "C": "软件 怎么反推 负向提示词 怎么做"
+    "C": "软件 分析 negative prompt 怎么做"
   },
   "75": {
     "idx": 75,
     "A": "在线 反推 负向提示词 教程",
     "B": "在线反推负向提示词的教程",
-    "C": "在线 推断 反向提示词 流程"
+    "C": "在线 怎么反推 反向提示词 方法"
   },
   "76": {
     "idx": 76,
     "A": "代码 反推 负向提示词 教程",
-    "B": "代码反推负向提示词的教程",
-    "C": "代码 怎么反推 negative prompt 教程"
+    "B": "通过代码反推负向提示词的教程",
+    "C": "命令行 推断 negative prompt 教程"
   },
   "77": {
     "idx": 77,
     "A": "插件 反推 负向提示词 教程",
-    "B": "插件反推负向提示词的教程",
-    "C": "插件 反推 负向提示词 流程"
+    "B": "反推负向提示词插件使用教程",
+    "C": "插件 推断 negative prompt 步骤"
   },
   "79": {
     "idx": 79,
     "A": "AI 反推 负向提示词 工具",
     "B": "智能反推负向提示词的工具",
-    "C": "AI 怎么反推 反向提示词 怎么做"
+    "C": "AI 推断 反向提示词 流程"
   },
   "80": {
     "idx": 80,
     "A": "软件 反推 负向提示词 工具",
     "B": "软件反推负向提示词的工具",
-    "C": "软件 怎么反推 负向提示词 流程"
+    "C": "电脑端 反推 negative prompt 教学"
   },
   "81": {
     "idx": 81,
     "A": "在线 反推 负向提示词 工具",
     "B": "在线反推负向提示词的工具",
-    "C": "网页版 反推 反向提示词 步骤"
+    "C": "网页版 分析 negative prompt 教程"
   },
   "82": {
     "idx": 82,
     "A": "代码 反推 负向提示词 工具",
-    "B": "代码反推负向提示词的工具",
-    "C": "命令行 推断 反向提示词 教学"
+    "B": "反推负向提示词的代码工具",
+    "C": "命令行 分析 负向提示词 步骤"
   },
   "83": {
     "idx": 83,
     "A": "插件 反推 负向提示词 工具",
-    "B": "插件反推负向提示词的工具",
-    "C": "插件 分析 负向提示词 步骤"
+    "B": "反推负向提示词插件工具",
+    "C": "插件 反推 negative prompt 步骤"
   },
   "85": {
     "idx": 85,
     "A": "AI 反推 负向提示词 技巧",
     "B": "智能反推负向提示词的技巧",
-    "C": "AI 反推 negative prompt 教学"
+    "C": "AI 反推 负向提示词 步骤"
   },
   "86": {
     "idx": 86,
     "A": "软件 反推 负向提示词 技巧",
-    "B": "软件反推负向提示词的技巧",
-    "C": "软件 推断 负向提示词 教程"
+    "B": "怎么通过软件反负向提示词",
+    "C": "电脑端 分析 负向提示词 流程"
   },
   "87": {
     "idx": 87,
     "A": "在线 反推 负向提示词 技巧",
-    "B": "在线反推负向提示词技巧",
-    "C": "网页版 分析 负向提示词 方法"
+    "B": "在线反推负向提示词有什么技巧",
+    "C": "在线 反推 negative prompt 怎么做"
   },
   "88": {
     "idx": 88,
     "A": "代码 反推 负向提示词 技巧",
-    "B": "代码反推负向提示词的技巧",
-    "C": "代码 分析 负向提示词 方法"
+    "B": "如何用代码实现负向提示词的反推",
+    "C": "代码 分析 负向提示词 教学"
   },
   "89": {
     "idx": 89,
     "A": "插件 反推 负向提示词 技巧",
-    "B": "插件反推负向提示词的技巧",
-    "C": "插件 分析 反向提示词 教程"
+    "B": "有什么插件可以辅助反推负向提示词",
+    "C": "插件 分析 反向提示词 方法"
   },
   "90": {
     "idx": 90,
     "A": "键入 描述 教程",
-    "B": "怎么写描述词的教程",
-    "C": "输入 提示描述 方法"
+    "B": "输入描述词的详细教程",
+    "C": "编写 描述 方法"
   },
   "92": {
     "idx": 92,
     "A": "软件 键入 描述 教程",
-    "B": "软件写描述词的教程",
-    "C": "软件 写 描述词 教学"
+    "B": "软件输入描述词的操作教程",
+    "C": "软件 怎么写 描述词 教学"
   },
   "93": {
     "idx": 93,
     "A": "在线 键入 描述 教程",
-    "B": "在线描述词的教程",
-    "C": "网页版 怎么写 描述 教学"
+    "B": "在线输入描述词的教程",
+    "C": "网页版 编写 提示描述 怎么做"
   },
   "94": {
     "idx": 94,
     "A": "代码 键入 描述 教程",
-    "B": "代码写描述词的教程",
-    "C": "命令行 输入 描述词 怎么做"
+    "B": "如何用代码输入描述词",
+    "C": "代码 输入 描述 教程"
   },
   "95": {
     "idx": 95,
     "A": "插件 键入 描述 教程",
-    "B": "插件写描述词的教程",
-    "C": "插件 怎么写 描述词 步骤"
+    "B": "输入描述词的插件使用教程",
+    "C": "插件 写 提示描述 方法"
   },
   "96": {
     "idx": 96,
     "A": "键入 描述 工具",
-    "B": "写描述词的工具推荐",
-    "C": "写 描述 怎么做"
+    "B": "有哪些好用的输入描述词工具",
+    "C": "输入 提示描述 流程"
   },
   "97": {
     "idx": 97,
     "A": "AI 键入 描述 工具",
-    "B": "智能写描述词的工具",
-    "C": "AI 写 提示描述 流程"
+    "B": "智能输入描述词的工具推荐",
+    "C": "AI 写 提示描述 教学"
   },
   "98": {
     "idx": 98,
     "A": "软件 键入 描述 工具",
-    "B": "软件写描述词的工具",
-    "C": "电脑端 输入 描述词 教程"
+    "B": "输入描述词的软件工具",
+    "C": "软件 输入 描述 教程"
   },
   "99": {
     "idx": 99,
     "A": "在线 键入 描述 工具",
-    "B": "在线描述词的工具",
-    "C": "在线 怎么写 描述词 流程"
+    "B": "在线输入描述词的工具",
+    "C": "网页版 写 提示描述 流程"
   },
   "100": {
     "idx": 100,
-    "A": "元素生成 配音文案 教程",
-    "B": "怎样根据元素生成配音文案的教程",
-    "C": "做 旁白文案 步骤"
+    "A": "代码 键入 描述 工具",
+    "B": "输入描述词的代码工具",
+    "C": "命令行 编写 描述 方法"
   },
   "101": {
     "idx": 101,
@@ -704,391 +704,15235 @@
   "127": {
     "idx": 127,
     "A": "AI 元素生成 描述 教程",
-    "B": "人工智能生成元素描述词的教程",
-    "C": "AI 创作 提示描述 步骤"
+    "B": "如何编写元素生成的描述词教程",
+    "C": "AI 创作 提示描述 怎么做"
   },
   "128": {
     "idx": 128,
     "A": "软件 元素生成 描述 教程",
     "B": "软件生成元素描述词的教程",
-    "C": "软件 做 描述词 教学"
+    "C": "软件 做 描述词 流程"
   },
   "129": {
     "idx": 129,
     "A": "在线 元素生成 描述 教程",
     "B": "在线生成元素描述词的教程",
-    "C": "网页版 制作 描述词 流程"
+    "C": "在线 生成 提示描述 怎么做"
   },
   "130": {
     "idx": 130,
     "A": "代码 元素生成 描述 教程",
-    "B": "代码生成元素描述词的教程",
-    "C": "代码 创作 提示描述 步骤"
+    "B": "代码生成元素描述词的教程",
+    "C": "命令行 做 描述词 怎么做"
   },
   "131": {
     "idx": 131,
     "A": "插件 元素生成 描述 教程",
-    "B": "插件生成元素描述词的教程",
-    "C": "插件 创作 描述词 步骤"
+    "B": "元素生成描述词的插件教程",
+    "C": "插件 生成 描述 怎么做"
   },
   "132": {
     "idx": 132,
     "A": "元素生成 描述 工具",
-    "B": "元素生成描述词工具",
-    "C": "制作 描述 方法"
+    "B": "有什么好用的元素生成描述词工具",
+    "C": "怎么做 描述 流程"
   },
   "133": {
     "idx": 133,
     "A": "AI 元素生成 描述 工具",
-    "B": "人工智能生成元素描述词的工具",
-    "C": "AI 生成 描述 教程"
+    "B": "智能生成元素描述词的工具",
+    "C": "AI 制作 提示描述 怎么做"
   },
   "134": {
     "idx": 134,
     "A": "软件 元素生成 描述 工具",
-    "B": "软件生成元素描述词的工具",
-    "C": "软件 制作 提示描述 怎么做"
+    "B": "生成元素描述词的软件工具",
+    "C": "软件 做 描述 步骤"
   },
   "135": {
     "idx": 135,
     "A": "在线 元素生成 描述 工具",
     "B": "在线生成元素描述词的工具",
-    "C": "在线 做 描述词 方法"
+    "C": "网页版 制作 描述 怎么做"
   },
   "136": {
     "idx": 136,
     "A": "代码 元素生成 描述 工具",
-    "B": "代码生成元素描述词的工具",
-    "C": "命令行 创作 描述词 方法"
+    "B": "生成元素描述词的代码工具",
+    "C": "代码 生成 提示描述 方法"
   },
   "137": {
     "idx": 137,
     "A": "插件 元素生成 描述 工具",
-    "B": "插件生成元素描述词的工具",
-    "C": "插件 生成 提示描述 方法"
+    "B": "生成元素描述词的插件工具",
+    "C": "插件 生成 描述 流程"
   },
   "138": {
     "idx": 138,
     "A": "元素生成 描述 技巧",
-    "B": "元素生成描述词的技巧",
-    "C": "怎么做 提示描述 步骤"
+    "B": "编写元素生成描述词的技巧",
+    "C": "做 描述词 怎么做"
   },
   "139": {
     "idx": 139,
     "A": "AI 元素生成 描述 技巧",
-    "B": "人工智能生成元素描述词的技巧",
-    "C": "AI 怎么做 描述 流程"
+    "B": "智能生成元素描述词的技巧",
+    "C": "AI 做 描述 流程"
   },
   "141": {
     "idx": 141,
     "A": "在线 元素生成 描述 技巧",
     "B": "在线生成元素描述词的技巧",
-    "C": "网页版 生成 提示描述 教学"
+    "C": "网页版 生成 描述词 步骤"
   },
   "142": {
     "idx": 142,
     "A": "代码 元素生成 描述 技巧",
-    "B": "代码生成元素描述词的技巧",
-    "C": "命令行 创作 描述 方法"
+    "B": "代码生成元素描述词的技巧",
+    "C": "命令行 怎么做 描述词 教学"
   },
   "143": {
     "idx": 143,
     "A": "插件 元素生成 描述 技巧",
-    "B": "插件生成元素描述词的技巧",
-    "C": "插件 怎么做 提示描述 方法"
+    "B": "元素生成描述词的插件使用技巧",
+    "C": "插件 制作 描述 步骤"
   },
   "144": {
     "idx": 144,
     "A": "风格化 描述 教程",
-    "B": "风格化描述词编写教程",
-    "C": "转风格 描述 步骤"
+    "B": "风格化描述词编写教程",
+    "C": "转风格 描述 方法"
   },
   "146": {
     "idx": 146,
     "A": "软件 风格化 描述 教程",
-    "B": "软件风格化描述词教程",
-    "C": "软件 风格化 提示描述 步骤"
+    "B": "软件编写风格化描述词教程",
+    "C": "软件 风格迁移 描述 教程"
   },
   "147": {
     "idx": 147,
     "A": "在线 风格化 描述 教程",
-    "B": "在线风格化描述词教程",
-    "C": "网页版 风格化 描述 步骤"
+    "B": "在线编写风格化描述词教程",
+    "C": "网页版 转风格 描述 方法"
   },
   "148": {
     "idx": 148,
     "A": "代码 风格化 描述 教程",
-    "B": "代码风格化描述词教程",
-    "C": "命令行 转风格 描述 流程"
+    "B": "代码编写风格化描述词教程",
+    "C": "代码 转风格 描述 方法"
   },
   "149": {
     "idx": 149,
     "A": "插件 风格化 描述 教程",
-    "B": "插件风格化描述词教程",
-    "C": "插件 风格化 提示描述 怎么做"
+    "B": "风格化描述词的插件教程",
+    "C": "插件 转风格 描述词 教程"
   },
   "151": {
     "idx": 151,
     "A": "AI 风格化 描述 工具",
-    "B": "人工智能风格化描述词工具",
-    "C": "AI 转风格 描述 教学"
+    "B": "智能生成风格化描述词工具",
+    "C": "AI 风格化 提示描述 教程"
   },
   "152": {
     "idx": 152,
     "A": "软件 风格化 描述 工具",
-    "B": "软件风格化描述词工具",
-    "C": "电脑端 转风格 描述词 方法"
+    "B": "风格化描述词的软件工具",
+    "C": "电脑端 风格迁移 描述词 流程"
   },
   "153": {
     "idx": 153,
     "A": "在线 风格化 描述 工具",
-    "B": "在线风格化描述词工具",
-    "C": "网页版 转风格 提示描述 教学"
+    "B": "在线生成风格化描述词工具",
+    "C": "网页版 转风格 描述词 怎么做"
   },
   "154": {
     "idx": 154,
     "A": "代码 风格化 描述 工具",
-    "B": "代码风格化描述词工具",
-    "C": "代码 风格迁移 描述词 教学"
+    "B": "风格化描述词的代码工具",
+    "C": "代码 风格迁移 描述词 步骤"
   },
   "155": {
     "idx": 155,
     "A": "插件 风格化 描述 工具",
-    "B": "插件风格化描述词工具",
-    "C": "插件 怎么转风格 提示描述 怎么做"
+    "B": "风格化描述词的插件工具",
+    "C": "插件 风格化 描述词 方法"
   },
   "157": {
     "idx": 157,
     "A": "AI 风格化 描述 技巧",
-    "B": "人工智能风格化描述词技巧",
-    "C": "AI 转风格 描述 教程"
+    "B": "如何写出更有风格的描述词",
+    "C": "AI 风格化 提示描述 流程"
   },
   "158": {
     "idx": 158,
     "A": "软件 风格化 描述 技巧",
-    "B": "软件风格化描述词技巧",
-    "C": "电脑端 风格化 提示描述 方法"
+    "B": "软件里怎么写出有风格的描述",
+    "C": "电脑端 转风格 描述词 教程"
   },
   "159": {
     "idx": 159,
     "A": "在线 风格化 描述 技巧",
-    "B": "在线风格化描述词技巧",
-    "C": "在线 转风格 描述 教程"
+    "B": "在线平台如何写出风格化描述",
+    "C": "在线 风格迁移 描述词 流程"
   },
   "160": {
     "idx": 160,
     "A": "代码 风格化 描述 技巧",
-    "B": "代码风格化描述词技巧",
-    "C": "代码 转风格 描述 教程"
+    "B": "编程实现风格化描述的技巧有哪些",
+    "C": "命令行 风格迁移 提示描述 教学"
   },
   "161": {
     "idx": 161,
     "A": "插件 风格化 描述 技巧",
-    "B": "插件风格化描述词技巧",
-    "C": "插件 风格化 提示描述 流程"
+    "B": "插件里怎么写出风格化描述",
+    "C": "插件 风格迁移 提示描述 教程"
   },
   "162": {
     "idx": 162,
     "A": "键入 生成参数 教程",
-    "B": "输入生成参数的教程",
-    "C": "怎么写 seed 流程"
+    "B": "输入生成参数的详细教程",
+    "C": "输入 生成参数 教程"
   },
   "164": {
     "idx": 164,
     "A": "软件 键入 生成参数 教程",
-    "B": "软件输入生成参数的教程",
-    "C": "软件 编写 出图参数 怎么做"
+    "B": "软件输入生成参数的操作教程",
+    "C": "软件 输入 生成参数 步骤"
   },
   "165": {
     "idx": 165,
     "A": "在线 键入 生成参数 教程",
-    "B": "在线输入生成参数的教程",
-    "C": "网页版 输入 参数 教程"
+    "B": "在线输入生成参数的方法教程",
+    "C": "在线 怎么写 出图参数 教学"
   },
   "166": {
     "idx": 166,
     "A": "代码 键入 生成参数 教程",
-    "B": "代码输入生成参数的教程",
-    "C": "命令行 怎么写 seed 怎么做"
+    "B": "代码里如何输入生成参数",
+    "C": "命令行 编写 生成参数 教程"
   },
   "167": {
     "idx": 167,
     "A": "插件 键入 生成参数 教程",
-    "B": "插件输入生成参数的教程",
-    "C": "插件 写 参数 教程"
+    "B": "插件输入生成参数的教程",
+    "C": "插件 生成参数 教程"
   },
   "168": {
     "idx": 168,
     "A": "键入 生成参数 工具",
-    "B": "输入生成参数的工具",
-    "C": "编写 生成参数 教程"
+    "B": "有哪些输入生成参数的工具",
+    "C": "写 生成参数 流程"
   },
   "169": {
     "idx": 169,
     "A": "AI 键入 生成参数 工具",
-    "B": "人工智能输入生成参数的工具",
-    "C": "AI 输入 出图参数 方法"
+    "B": "好用的智能生成参数工具推荐",
+    "C": "AI 输入 seed 方法"
   },
   "170": {
     "idx": 170,
     "A": "软件 键入 生成参数 工具",
-    "B": "软件输入生成参数的工具",
-    "C": "电脑端 输入 seed 流程"
+    "B": "软件自带的生成参数工具有哪些",
+    "C": "电脑端 写 参数 教程"
   },
   "171": {
     "idx": 171,
     "A": "在线 键入 生成参数 工具",
-    "B": "在线输入生成参数的工具",
-    "C": "网页版 编写 出图参数 教程"
+    "B": "哪里有在线输入参数的生成工具",
+    "C": "在线 写 生成参数 流程"
   },
   "172": {
     "idx": 172,
     "A": "代码 键入 生成参数 工具",
-    "B": "代码输入生成参数的工具",
-    "C": "命令行 写 参数 教学"
+    "B": "写代码时怎么用工具生成参数",
+    "C": "代码 输入 参数 教学"
   },
   "173": {
     "idx": 173,
     "A": "插件 键入 生成参数 工具",
-    "B": "插件输入生成参数的工具",
-    "C": "插件 写 出图参数 流程"
+    "B": "有没有能生成参数的插件工具",
+    "C": "插件 编写 参数 教程"
   },
   "174": {
     "idx": 174,
     "A": "键入 生成参数 技巧",
-    "B": "输入生成参数技巧",
-    "C": "编写 seed 怎么做"
+    "B": "输入生成参数有什么技巧",
+    "C": "写 出图参数 流程"
   },
   "175": {
     "idx": 175,
     "A": "AI 键入 生成参数 技巧",
-    "B": "人工智能输入生成参数的技巧",
-    "C": "AI 编写 参数 流程"
+    "B": "智能生成参数的输入技巧有哪些",
+    "C": "AI 输入 seed 流程"
   },
   "176": {
     "idx": 176,
     "A": "软件 键入 生成参数 技巧",
-    "B": "软件输入生成参数的技巧",
-    "C": "电脑端 写 seed 步骤"
+    "B": "软件输入生成参数的技巧",
+    "C": "电脑端 怎么写 参数 流程"
   },
   "177": {
     "idx": 177,
     "A": "在线 键入 生成参数 技巧",
     "B": "在线输入生成参数的技巧",
-    "C": "网页版 怎么写 seed 教学"
+    "C": "网页版 怎么写 生成参数 流程"
   },
   "178": {
     "idx": 178,
     "A": "代码 键入 生成参数 技巧",
-    "B": "代码输入生成参数的技巧",
-    "C": "命令行 输入 出图参数 步骤"
+    "B": "编写代码输入参数的技巧",
+    "C": "代码 怎么写 参数 教程"
   },
   "179": {
     "idx": 179,
     "A": "插件 键入 生成参数 技巧",
     "B": "插件输入生成参数的技巧",
-    "C": "插件 写 参数 教学"
+    "C": "插件 写 生成参数 步骤"
   },
   "182": {
     "idx": 182,
     "A": "软件 调整 生成参数 教程",
-    "B": "软件调整生成参数的教程",
-    "C": "电脑端 调整 参数 方法"
+    "B": "软件调整生成参数的教程",
+    "C": "电脑端 调整 seed 方法"
   },
   "183": {
     "idx": 183,
     "A": "在线 调整 生成参数 教程",
-    "B": "在线调整生成参数的教程",
-    "C": "网页版 调 参数 方法"
+    "B": "在线调整生成参数的操作教程",
+    "C": "在线 优化 参数 方法"
   },
   "184": {
     "idx": 184,
     "A": "代码 调整 生成参数 教程",
-    "B": "代码调整生成参数的教程",
-    "C": "代码 调 参数 方法"
+    "B": "代码里怎么调整生成参数",
+    "C": "命令行 怎么调 出图参数 教学"
   },
   "185": {
     "idx": 185,
     "A": "插件 调整 生成参数 教程",
     "B": "插件调整生成参数的教程",
-    "C": "插件 调 seed 教程"
+    "C": "插件 调整 出图参数 步骤"
   },
   "187": {
     "idx": 187,
     "A": "AI 调整 生成参数 工具",
-    "B": "人工智能调整生成参数的工具",
-    "C": "AI 调 参数 怎么做"
+    "B": "有没有调整生成参数的智能工具",
+    "C": "AI 调 参数 怎么做"
   },
   "188": {
     "idx": 188,
     "A": "软件 调整 生成参数 工具",
-    "B": "软件调整生成参数的工具",
-    "C": "电脑端 怎么调 出图参数 教学"
+    "B": "软件调整生成参数的工具",
+    "C": "电脑端 优化 生成参数 流程"
   },
   "189": {
     "idx": 189,
     "A": "在线 调整 生成参数 工具",
     "B": "在线调整生成参数的工具",
-    "C": "网页版 调 生成参数 怎么做"
+    "C": "网页版 怎么调 出图参数 教学"
   },
   "190": {
     "idx": 190,
     "A": "代码 调整 生成参数 工具",
-    "B": "代码调整生成参数的工具",
-    "C": "代码 怎么调 seed 步骤"
+    "B": "调整生成参数的代码工具",
+    "C": "命令行 调整 出图参数 方法"
   },
   "191": {
     "idx": 191,
     "A": "插件 调整 生成参数 工具",
-    "B": "插件调整生成参数的工具",
-    "C": "插件 调整 seed 方法"
+    "B": "调整生成参数的插件工具",
+    "C": "插件 调 seed 怎么做"
   },
   "193": {
     "idx": 193,
     "A": "AI 调整 生成参数 技巧",
-    "B": "人工智能调整生成参数的技巧",
-    "C": "AI 调整 出图参数 方法"
+    "B": "智能调整生成参数的技巧",
+    "C": "AI 调 生成参数 教程"
   },
   "194": {
     "idx": 194,
     "A": "软件 调整 生成参数 技巧",
     "B": "软件调整生成参数的技巧",
-    "C": "电脑端 调 生成参数 教程"
+    "C": "软件 调整 生成参数 怎么做"
   },
   "195": {
     "idx": 195,
     "A": "在线 调整 生成参数 技巧",
     "B": "在线调整生成参数的技巧",
-    "C": "在线 怎么调 生成参数 流程"
+    "C": "网页版 调整 出图参数 方法"
   },
   "196": {
     "idx": 196,
     "A": "代码 调整 生成参数 技巧",
     "B": "代码调整生成参数的技巧",
-    "C": "命令行 怎么调 参数 教学"
+    "C": "命令行 调 seed 怎么做"
   },
   "197": {
     "idx": 197,
     "A": "插件 调整 生成参数 技巧",
     "B": "插件调整生成参数的技巧",
-    "C": "插件 调整 出图参数 步骤"
+    "C": "插件 调 生成参数 流程"
   },
   "198": {
     "idx": 198,
     "A": "键入 规格参数 教程",
     "B": "输入规格参数的教程",
-    "C": "写 尺寸 教学"
+    "C": "输入 画幅 教学"
   },
   "199": {
     "idx": 199,
     "A": "AI 键入 规格参数 教程",
-    "B": "人工智能输入规格参数的教程",
-    "C": "AI 怎么写 画幅 方法"
+    "B": "智能输入规格参数的教程",
+    "C": "AI 编写 画幅 流程"
   },
   "200": {
     "idx": 200,
     "A": "软件 键入 规格参数 教程",
     "B": "软件输入规格参数的教程",
-    "C": "软件 怎么写 分辨率 教学"
+    "C": "软件 编写 尺寸 教程"
+  },
+  "202": {
+    "idx": 202,
+    "A": "代码 键入 规格参数 教程",
+    "B": "代码输入规格参数的教程",
+    "C": "代码 输入 分辨率 教学"
+  },
+  "203": {
+    "idx": 203,
+    "A": "插件 键入 规格参数 教程",
+    "B": "插件输入规格参数的教程",
+    "C": "插件 写 规格 怎么做"
+  },
+  "204": {
+    "idx": 204,
+    "A": "键入 规格参数 工具",
+    "B": "输入规格参数的工具",
+    "C": "编写 画幅 方法"
+  },
+  "205": {
+    "idx": 205,
+    "A": "AI 键入 规格参数 工具",
+    "B": "智能输入规格参数的工具",
+    "C": "AI 写 画幅 教学"
+  },
+  "206": {
+    "idx": 206,
+    "A": "软件 键入 规格参数 工具",
+    "B": "软件输入规格参数的工具",
+    "C": "电脑端 写 画幅 怎么做"
+  },
+  "207": {
+    "idx": 207,
+    "A": "在线 键入 规格参数 工具",
+    "B": "在线输入规格参数的工具",
+    "C": "在线 编写 尺寸 教学"
+  },
+  "208": {
+    "idx": 208,
+    "A": "代码 键入 规格参数 工具",
+    "B": "代码输入规格参数的工具",
+    "C": "命令行 输入 尺寸 教学"
+  },
+  "209": {
+    "idx": 209,
+    "A": "插件 键入 规格参数 工具",
+    "B": "插件输入规格参数的工具",
+    "C": "插件 输入 分辨率 步骤"
+  },
+  "210": {
+    "idx": 210,
+    "A": "键入 规格参数 技巧",
+    "B": "输入规格参数的技巧",
+    "C": "输入 尺寸 方法"
+  },
+  "211": {
+    "idx": 211,
+    "A": "AI 键入 规格参数 技巧",
+    "B": "智能输入规格参数的技巧",
+    "C": "AI 编写 尺寸 教程"
+  },
+  "212": {
+    "idx": 212,
+    "A": "软件 键入 规格参数 技巧",
+    "B": "软件输入规格参数的技巧",
+    "C": "电脑端 怎么写 分辨率 教程"
+  },
+  "214": {
+    "idx": 214,
+    "A": "代码 键入 规格参数 技巧",
+    "B": "代码输入规格参数的技巧",
+    "C": "代码 写 尺寸 教学"
+  },
+  "215": {
+    "idx": 215,
+    "A": "插件 键入 规格参数 技巧",
+    "B": "插件输入规格参数的技巧",
+    "C": "插件 写 分辨率 流程"
+  },
+  "217": {
+    "idx": 217,
+    "A": "AI 转换 规格参数 教程",
+    "B": "智能转换规格参数的教程",
+    "C": "AI 转 画幅 方法"
+  },
+  "218": {
+    "idx": 218,
+    "A": "软件 转换 规格参数 教程",
+    "B": "怎么用软件转换规格参数的教程",
+    "C": "电脑端 转 分辨率 教学"
+  },
+  "219": {
+    "idx": 219,
+    "A": "在线 转换 规格参数 教程",
+    "B": "在线转换规格参数的操作教程",
+    "C": "网页版 转格式 画幅 怎么做"
+  },
+  "220": {
+    "idx": 220,
+    "A": "代码 转换 规格参数 教程",
+    "B": "通过代码转换规格参数的教程",
+    "C": "命令行 转换 分辨率 流程"
+  },
+  "221": {
+    "idx": 221,
+    "A": "插件 转换 规格参数 教程",
+    "B": "有什么插件可以转换规格参数的教程",
+    "C": "插件 怎么转 尺寸 方法"
+  },
+  "223": {
+    "idx": 223,
+    "A": "AI 转换 规格参数 工具",
+    "B": "智能转换规格参数的工具推荐",
+    "C": "AI 转 尺寸 教程"
+  },
+  "224": {
+    "idx": 224,
+    "A": "软件 转换 规格参数 工具",
+    "B": "好用的规格参数转换软件",
+    "C": "软件 转 尺寸 教程"
+  },
+  "225": {
+    "idx": 225,
+    "A": "在线 转换 规格参数 工具",
+    "B": "在线转换规格参数的工具",
+    "C": "网页版 转换 分辨率 步骤"
+  },
+  "226": {
+    "idx": 226,
+    "A": "代码 转换 规格参数 工具",
+    "B": "用于转换规格参数的代码工具",
+    "C": "命令行 转 分辨率 教学"
+  },
+  "227": {
+    "idx": 227,
+    "A": "插件 转换 规格参数 工具",
+    "B": "转换规格参数的插件有哪些",
+    "C": "插件 转 规格 怎么做"
+  },
+  "229": {
+    "idx": 229,
+    "A": "AI 转换 规格参数 技巧",
+    "B": "智能转换规格参数的操作技巧",
+    "C": "AI 转换 尺寸 教学"
+  },
+  "230": {
+    "idx": 230,
+    "A": "软件 转换 规格参数 技巧",
+    "B": "软件转换规格参数的实用技巧",
+    "C": "电脑端 怎么转 规格 怎么做"
+  },
+  "231": {
+    "idx": 231,
+    "A": "在线 转换 规格参数 技巧",
+    "B": "在线转换规格参数的小技巧",
+    "C": "网页版 转换 尺寸 教程"
+  },
+  "232": {
+    "idx": 232,
+    "A": "代码 转换 规格参数 技巧",
+    "B": "用代码转换规格参数的技巧",
+    "C": "命令行 怎么转 尺寸 流程"
+  },
+  "233": {
+    "idx": 233,
+    "A": "插件 转换 规格参数 技巧",
+    "B": "使用插件转换规格参数的技巧",
+    "C": "插件 转 规格 流程"
+  },
+  "234": {
+    "idx": 234,
+    "A": "调整 规格参数 教程",
+    "B": "调整规格参数的详细教程",
+    "C": "优化 分辨率 步骤"
+  },
+  "235": {
+    "idx": 235,
+    "A": "AI 调整 规格参数 教程",
+    "B": "智能调整规格参数的教程",
+    "C": "AI 调 尺寸 怎么做"
+  },
+  "236": {
+    "idx": 236,
+    "A": "软件 调整 规格参数 教程",
+    "B": "用软件调整规格参数的教程",
+    "C": "软件 调整 尺寸 教程"
+  },
+  "237": {
+    "idx": 237,
+    "A": "在线 调整 规格参数 教程",
+    "B": "在线调整规格参数的教程",
+    "C": "在线 调 规格 怎么做"
+  },
+  "238": {
+    "idx": 238,
+    "A": "代码 调整 规格参数 教程",
+    "B": "通过代码调整规格参数的教程",
+    "C": "命令行 调 规格 教程"
+  },
+  "239": {
+    "idx": 239,
+    "A": "插件 调整 规格参数 教程",
+    "B": "用插件调整规格参数的教程",
+    "C": "插件 优化 尺寸 怎么做"
+  },
+  "240": {
+    "idx": 240,
+    "A": "调整 规格参数 工具",
+    "B": "调整规格参数的工具推荐",
+    "C": "怎么调 规格 步骤"
+  },
+  "241": {
+    "idx": 241,
+    "A": "AI 调整 规格参数 工具",
+    "B": "智能调整规格参数的工具",
+    "C": "AI 优化 分辨率 流程"
+  },
+  "242": {
+    "idx": 242,
+    "A": "软件 调整 规格参数 工具",
+    "B": "调整规格参数的软件有哪些",
+    "C": "电脑端 调 尺寸 方法"
+  },
+  "243": {
+    "idx": 243,
+    "A": "在线 调整 规格参数 工具",
+    "B": "在线调整规格参数的工具",
+    "C": "在线 怎么调 尺寸 教程"
+  },
+  "244": {
+    "idx": 244,
+    "A": "代码 调整 规格参数 工具",
+    "B": "调整规格参数的代码工具",
+    "C": "命令行 调 尺寸 方法"
+  },
+  "245": {
+    "idx": 245,
+    "A": "插件 调整 规格参数 工具",
+    "B": "调整规格参数的插件工具",
+    "C": "插件 调 尺寸 方法"
+  },
+  "246": {
+    "idx": 246,
+    "A": "调整 规格参数 技巧",
+    "B": "调整规格参数的实用技巧",
+    "C": "调整 分辨率 怎么做"
+  },
+  "247": {
+    "idx": 247,
+    "A": "AI 调整 规格参数 技巧",
+    "B": "智能调整规格参数的技巧",
+    "C": "AI 调 尺寸 方法"
+  },
+  "248": {
+    "idx": 248,
+    "A": "软件 调整 规格参数 技巧",
+    "B": "用软件调整规格参数的技巧",
+    "C": "软件 优化 画幅 步骤"
+  },
+  "249": {
+    "idx": 249,
+    "A": "在线 调整 规格参数 技巧",
+    "B": "在线调整规格参数的技巧",
+    "C": "在线 怎么调 分辨率 步骤"
+  },
+  "250": {
+    "idx": 250,
+    "A": "代码 调整 规格参数 技巧",
+    "B": "通过代码调整规格参数的技巧",
+    "C": "命令行 调 画幅 怎么做"
+  },
+  "251": {
+    "idx": 251,
+    "A": "插件 调整 规格参数 技巧",
+    "B": "使用插件调整规格参数的技巧",
+    "C": "插件 调整 尺寸 怎么做"
+  },
+  "253": {
+    "idx": 253,
+    "A": "AI 下载 模型权重 教程",
+    "B": "智能下载模型权重的教程",
+    "C": "AI 下载 LoRA 方法"
+  },
+  "254": {
+    "idx": 254,
+    "A": "软件 下载 模型权重 教程",
+    "B": "用软件下载模型权重的教程",
+    "C": "电脑端 怎么下载 底模 教程"
+  },
+  "255": {
+    "idx": 255,
+    "A": "在线 下载 模型权重 教程",
+    "B": "在线下载模型权重的教程",
+    "C": "在线 获取 底模 流程"
+  },
+  "256": {
+    "idx": 256,
+    "A": "代码 下载 模型权重 教程",
+    "B": "通过代码下载模型权重的教程",
+    "C": "命令行 获取 模型 教学"
+  },
+  "257": {
+    "idx": 257,
+    "A": "插件 下载 模型权重 教程",
+    "B": "用插件下载模型权重的教程",
+    "C": "插件 下载 LoRA 步骤"
+  },
+  "259": {
+    "idx": 259,
+    "A": "AI 下载 模型权重 工具",
+    "B": "智能下载模型权重的工具",
+    "C": "AI 下载 LoRA 步骤"
+  },
+  "260": {
+    "idx": 260,
+    "A": "软件 下载 模型权重 工具",
+    "B": "下载模型权重的软件推荐",
+    "C": "电脑端 怎么下载 底模 流程"
+  },
+  "261": {
+    "idx": 261,
+    "A": "在线 下载 模型权重 工具",
+    "B": "在线下载模型权重的工具",
+    "C": "网页版 导入 底模 教程"
+  },
+  "262": {
+    "idx": 262,
+    "A": "代码 下载 模型权重 工具",
+    "B": "如何通过代码下载模型权重",
+    "C": "代码 导入 底模 教程"
+  },
+  "263": {
+    "idx": 263,
+    "A": "插件 下载 模型权重 工具",
+    "B": "有哪些插件可以下载模型权重",
+    "C": "插件 获取 LoRA 教学"
+  },
+  "265": {
+    "idx": 265,
+    "A": "AI 下载 模型权重 技巧",
+    "B": "下载模型权重有什么好用的技巧",
+    "C": "AI 怎么下载 checkpoint 方法"
+  },
+  "266": {
+    "idx": 266,
+    "A": "软件 下载 模型权重 技巧",
+    "B": "怎么用软件下载模型权重",
+    "C": "电脑端 下载 模型 教程"
+  },
+  "267": {
+    "idx": 267,
+    "A": "在线 下载 模型权重 技巧",
+    "B": "在线下载模型权重的方法",
+    "C": "在线 下载 底模 方法"
+  },
+  "268": {
+    "idx": 268,
+    "A": "代码 下载 模型权重 技巧",
+    "B": "通过代码下载模型权重的技巧",
+    "C": "代码 导入 LoRA 教程"
+  },
+  "269": {
+    "idx": 269,
+    "A": "插件 下载 模型权重 技巧",
+    "B": "使用插件下载模型权重的技巧",
+    "C": "插件 获取 模型 步骤"
+  },
+  "270": {
+    "idx": 270,
+    "A": "元素生成 模型权重 教程",
+    "B": "元素生成模型权重的教程",
+    "C": "制作 LoRA 教学"
+  },
+  "271": {
+    "idx": 271,
+    "A": "AI 元素生成 模型权重 教程",
+    "B": "如何利用人工智能生成模型权重",
+    "C": "AI 怎么做 checkpoint 方法"
+  },
+  "272": {
+    "idx": 272,
+    "A": "软件 元素生成 模型权重 教程",
+    "B": "软件生成元素模型权重的教程",
+    "C": "软件 制作 LoRA 流程"
+  },
+  "273": {
+    "idx": 273,
+    "A": "在线 元素生成 模型权重 教程",
+    "B": "在线生成元素模型权重的教程",
+    "C": "网页版 生成 LoRA 教学"
+  },
+  "275": {
+    "idx": 275,
+    "A": "插件 元素生成 模型权重 教程",
+    "B": "插件生成元素模型权重的教程",
+    "C": "插件 做 LoRA 步骤"
+  },
+  "276": {
+    "idx": 276,
+    "A": "元素生成 模型权重 工具",
+    "B": "有哪些工具可以生成元素模型权重",
+    "C": "制作 模型 怎么做"
+  },
+  "277": {
+    "idx": 277,
+    "A": "AI 元素生成 模型权重 工具",
+    "B": "好用的智能生成元素模型权重工具",
+    "C": "AI 做 LoRA 流程"
+  },
+  "278": {
+    "idx": 278,
+    "A": "软件 元素生成 模型权重 工具",
+    "B": "适合生成元素模型权重的软件",
+    "C": "电脑端 怎么做 底模 流程"
+  },
+  "279": {
+    "idx": 279,
+    "A": "在线 元素生成 模型权重 工具",
+    "B": "在线生成元素模型权重的工具",
+    "C": "在线 生成 LoRA 怎么做"
+  },
+  "280": {
+    "idx": 280,
+    "A": "代码 元素生成 模型权重 工具",
+    "B": "通过代码生成元素模型权重的工具",
+    "C": "命令行 怎么做 模型 步骤"
+  },
+  "281": {
+    "idx": 281,
+    "A": "插件 元素生成 模型权重 工具",
+    "B": "生成元素模型权重的插件工具",
+    "C": "插件 创作 checkpoint 教学"
+  },
+  "282": {
+    "idx": 282,
+    "A": "元素生成 模型权重 技巧",
+    "B": "元素生成模型权重的操作技巧",
+    "C": "创作 底模 教程"
+  },
+  "283": {
+    "idx": 283,
+    "A": "AI 元素生成 模型权重 技巧",
+    "B": "人工智能生成模型权重的技巧",
+    "C": "AI 怎么做 LoRA 方法"
+  },
+  "284": {
+    "idx": 284,
+    "A": "软件 元素生成 模型权重 技巧",
+    "B": "软件生成元素模型权重的技巧",
+    "C": "电脑端 生成 模型 方法"
+  },
+  "285": {
+    "idx": 285,
+    "A": "在线 元素生成 模型权重 技巧",
+    "B": "在线生成元素模型权重的技巧",
+    "C": "网页版 怎么做 底模 怎么做"
+  },
+  "287": {
+    "idx": 287,
+    "A": "插件 元素生成 模型权重 技巧",
+    "B": "插件生成元素模型权重的技巧",
+    "C": "插件 做 LoRA 步骤"
+  },
+  "289": {
+    "idx": 289,
+    "A": "AI 风格化 模型权重 教程",
+    "B": "人工智能风格化模型权重的教程",
+    "C": "AI 怎么转风格 模型 方法"
+  },
+  "290": {
+    "idx": 290,
+    "A": "软件 风格化 模型权重 教程",
+    "B": "软件进行风格化模型权重的教程",
+    "C": "软件 风格迁移 checkpoint 教程"
+  },
+  "291": {
+    "idx": 291,
+    "A": "在线 风格化 模型权重 教程",
+    "B": "在线风格化模型权重的教程",
+    "C": "网页版 风格迁移 模型 教学"
+  },
+  "292": {
+    "idx": 292,
+    "A": "代码 风格化 模型权重 教程",
+    "B": "通过代码实现风格化模型权重的教程",
+    "C": "命令行 风格迁移 checkpoint 步骤"
+  },
+  "293": {
+    "idx": 293,
+    "A": "插件 风格化 模型权重 教程",
+    "B": "插件风格化模型权重的教程",
+    "C": "插件 风格迁移 LoRA 流程"
+  },
+  "295": {
+    "idx": 295,
+    "A": "AI 风格化 模型权重 工具",
+    "B": "人工智能风格化模型权重的工具",
+    "C": "AI 怎么转风格 LoRA 方法"
+  },
+  "296": {
+    "idx": 296,
+    "A": "软件 风格化 模型权重 工具",
+    "B": "软件风格化模型权重的工具",
+    "C": "电脑端 怎么转风格 模型 步骤"
+  },
+  "297": {
+    "idx": 297,
+    "A": "在线 风格化 模型权重 工具",
+    "B": "在线风格化模型权重的工具",
+    "C": "网页版 转风格 checkpoint 方法"
+  },
+  "298": {
+    "idx": 298,
+    "A": "代码 风格化 模型权重 工具",
+    "B": "通过代码实现风格化模型权重的工具",
+    "C": "命令行 怎么转风格 checkpoint 怎么做"
+  },
+  "299": {
+    "idx": 299,
+    "A": "插件 风格化 模型权重 工具",
+    "B": "插件风格化模型权重的工具",
+    "C": "插件 怎么转风格 LoRA 教学"
+  },
+  "301": {
+    "idx": 301,
+    "A": "AI 风格化 模型权重 技巧",
+    "B": "人工智能风格化模型权重的技巧",
+    "C": "AI 风格迁移 底模 教程"
+  },
+  "302": {
+    "idx": 302,
+    "A": "软件 风格化 模型权重 技巧",
+    "B": "软件风格化模型权重的技巧",
+    "C": "软件 风格迁移 LoRA 流程"
+  },
+  "303": {
+    "idx": 303,
+    "A": "在线 风格化 模型权重 技巧",
+    "B": "在线风格化模型权重的技巧",
+    "C": "在线 风格化 模型 流程"
+  },
+  "304": {
+    "idx": 304,
+    "A": "代码 风格化 模型权重 技巧",
+    "B": "通过代码实现风格化模型权重的技巧",
+    "C": "命令行 风格化 checkpoint 怎么做"
+  },
+  "305": {
+    "idx": 305,
+    "A": "插件 风格化 模型权重 技巧",
+    "B": "插件风格化模型权重的技巧",
+    "C": "插件 怎么转风格 checkpoint 怎么做"
+  },
+  "306": {
+    "idx": 306,
+    "A": "选取 评分 教程",
+    "B": "如何进行选取评分的教程",
+    "C": "怎么选 评分 教学"
+  },
+  "307": {
+    "idx": 307,
+    "A": "AI 选取 评分 教程",
+    "B": "人工智能选取评分的教程",
+    "C": "AI 挑选 打分 流程"
+  },
+  "308": {
+    "idx": 308,
+    "A": "软件 选取 评分 教程",
+    "B": "怎么用软件进行评分选取教学",
+    "C": "软件 选 评分 方法"
+  },
+  "309": {
+    "idx": 309,
+    "A": "在线 选取 评分 教程",
+    "B": "在线进行评分选取的操作教程",
+    "C": "在线 挑选 打分 流程"
+  },
+  "310": {
+    "idx": 310,
+    "A": "代码 选取 评分 教程",
+    "B": "通过代码实现评分选取的方法教学",
+    "C": "命令行 筛选 打分 方法"
+  },
+  "311": {
+    "idx": 311,
+    "A": "插件 选取 评分 教程",
+    "B": "插件评分选取功能的设置教程",
+    "C": "插件 选 评分 教学"
+  },
+  "312": {
+    "idx": 312,
+    "A": "选取 评分 工具",
+    "B": "好用的评分选取工具推荐",
+    "C": "选 打分 步骤"
+  },
+  "313": {
+    "idx": 313,
+    "A": "AI 选取 评分 工具",
+    "B": "智能评分选取工具有哪些",
+    "C": "AI 筛选 评级 怎么做"
+  },
+  "314": {
+    "idx": 314,
+    "A": "软件 选取 评分 工具",
+    "B": "评分选取软件哪个好用",
+    "C": "软件 筛选 打分 教程"
+  },
+  "315": {
+    "idx": 315,
+    "A": "在线 选取 评分 工具",
+    "B": "在线评分选取工具有推荐吗",
+    "C": "网页版 怎么选 打分 步骤"
+  },
+  "316": {
+    "idx": 316,
+    "A": "代码 选取 评分 工具",
+    "B": "实现评分选取的代码工具有哪些",
+    "C": "命令行 挑选 评分 流程"
+  },
+  "317": {
+    "idx": 317,
+    "A": "插件 选取 评分 工具",
+    "B": "好用的评分选取插件推荐",
+    "C": "插件 选 评级 流程"
+  },
+  "319": {
+    "idx": 319,
+    "A": "AI 选取 评分 技巧",
+    "B": "智能评分选取的实用技巧",
+    "C": "AI 挑选 打分 怎么做"
+  },
+  "320": {
+    "idx": 320,
+    "A": "软件 选取 评分 技巧",
+    "B": "软件评分选取的进阶技巧",
+    "C": "电脑端 选 打分 教程"
+  },
+  "321": {
+    "idx": 321,
+    "A": "在线 选取 评分 技巧",
+    "B": "在线评分选取的快捷技巧",
+    "C": "在线 选 打分 方法"
+  },
+  "322": {
+    "idx": 322,
+    "A": "代码 选取 评分 技巧",
+    "B": "代码实现评分选取的技巧分享",
+    "C": "代码 选 打分 教程"
+  },
+  "323": {
+    "idx": 323,
+    "A": "插件 选取 评分 技巧",
+    "B": "评分选取插件的使用技巧",
+    "C": "插件 筛选 打分 怎么做"
+  },
+  "325": {
+    "idx": 325,
+    "A": "AI 重述 评语 教程",
+    "B": "怎么用智能工具重述评语教学",
+    "C": "AI 重写 点评 步骤"
+  },
+  "326": {
+    "idx": 326,
+    "A": "软件 重述 评语 教程",
+    "B": "软件重述评语的操作教程",
+    "C": "电脑端 重写 评语 怎么做"
+  },
+  "327": {
+    "idx": 327,
+    "A": "在线 重述 评语 教程",
+    "B": "在线重述评语的方法教学",
+    "C": "网页版 重写 点评 怎么做"
+  },
+  "328": {
+    "idx": 328,
+    "A": "代码 重述 评语 教程",
+    "B": "用代码重述评语的实现教程",
+    "C": "代码 改写 修改意见 方法"
+  },
+  "329": {
+    "idx": 329,
+    "A": "插件 重述 评语 教程",
+    "B": "插件重述评语的功能教程",
+    "C": "插件 改写 修改意见 流程"
+  },
+  "331": {
+    "idx": 331,
+    "A": "AI 重述 评语 工具",
+    "B": "好用的评语重述工具推荐",
+    "C": "AI 润色 评语 步骤"
+  },
+  "332": {
+    "idx": 332,
+    "A": "软件 重述 评语 工具",
+    "B": "重述评语的软件工具有哪些",
+    "C": "电脑端 怎么改 点评 怎么做"
+  },
+  "333": {
+    "idx": 333,
+    "A": "在线 重述 评语 工具",
+    "B": "在线重述评语的工具推荐",
+    "C": "网页版 怎么改 修改意见 步骤"
+  },
+  "334": {
+    "idx": 334,
+    "A": "代码 重述 评语 工具",
+    "B": "实现评语重述的代码工具有哪些",
+    "C": "命令行 怎么改 评语 怎么做"
+  },
+  "335": {
+    "idx": 335,
+    "A": "插件 重述 评语 工具",
+    "B": "好用的评语重述插件推荐",
+    "C": "插件 改写 反馈 流程"
+  },
+  "337": {
+    "idx": 337,
+    "A": "AI 重述 评语 技巧",
+    "B": "智能重述评语的实用技巧",
+    "C": "AI 改写 评语 流程"
+  },
+  "338": {
+    "idx": 338,
+    "A": "软件 重述 评语 技巧",
+    "B": "软件重述评语的进阶技巧",
+    "C": "软件 改写 点评 流程"
+  },
+  "339": {
+    "idx": 339,
+    "A": "在线 重述 评语 技巧",
+    "B": "在线重述评语的快捷技巧",
+    "C": "在线 重写 评语 方法"
+  },
+  "340": {
+    "idx": 340,
+    "A": "代码 重述 评语 技巧",
+    "B": "代码实现重述评语的技巧分享",
+    "C": "代码 重写 反馈 步骤"
+  },
+  "341": {
+    "idx": 341,
+    "A": "插件 重述 评语 技巧",
+    "B": "插件重述评语的使用技巧",
+    "C": "插件 改写 点评 步骤"
+  },
+  "342": {
+    "idx": 342,
+    "A": "识别 工作流 教程",
+    "B": "识别工作流的设置教程",
+    "C": "识别 工作流 步骤"
+  },
+  "343": {
+    "idx": 343,
+    "A": "AI 识别 工作流 教程",
+    "B": "智能识别工作流的操作教程",
+    "C": "AI 提取文字 workflow 教程"
+  },
+  "344": {
+    "idx": 344,
+    "A": "软件 识别 工作流 教程",
+    "B": "识别工作流的软件使用教程",
+    "C": "软件 识别 流程图 教学"
+  },
+  "345": {
+    "idx": 345,
+    "A": "在线 识别 工作流 教程",
+    "B": "在线识别工作流的设置教程",
+    "C": "在线 转录 工作流 步骤"
+  },
+  "346": {
+    "idx": 346,
+    "A": "代码 识别 工作流 教程",
+    "B": "通过代码实现识别工作流的教程",
+    "C": "命令行 OCR 工作流 方法"
+  },
+  "348": {
+    "idx": 348,
+    "A": "识别 工作流 工具",
+    "B": "好用的识别工作流工具推荐",
+    "C": "OCR 工作流 怎么做"
+  },
+  "349": {
+    "idx": 349,
+    "A": "AI 识别 工作流 工具",
+    "B": "智能识别工作流的工具有哪些",
+    "C": "AI 识别 节点 步骤"
+  },
+  "350": {
+    "idx": 350,
+    "A": "软件 识别 工作流 工具",
+    "B": "识别工作流的软件工具有推荐吗",
+    "C": "电脑端 检测 节点 流程"
+  },
+  "351": {
+    "idx": 351,
+    "A": "在线 识别 工作流 工具",
+    "B": "在线识别工作流的工具有哪些",
+    "C": "网页版 转录 节点 怎么做"
+  },
+  "352": {
+    "idx": 352,
+    "A": "代码 识别 工作流 工具",
+    "B": "实现识别工作流的代码工具有哪些",
+    "C": "命令行 转录 流程图 步骤"
+  },
+  "353": {
+    "idx": 353,
+    "A": "插件 识别 工作流 工具",
+    "B": "有哪些好用的识别工作流插件",
+    "C": "插件 识别 流程图 怎么做"
+  },
+  "354": {
+    "idx": 354,
+    "A": "识别 工作流 技巧",
+    "B": "识别工作流有什么好用的技巧",
+    "C": "检测 节点 方法"
+  },
+  "355": {
+    "idx": 355,
+    "A": "AI 识别 工作流 技巧",
+    "B": "如何利用智能技术优化识别工作流",
+    "C": "AI OCR 工作流 怎么做"
+  },
+  "356": {
+    "idx": 356,
+    "A": "软件 识别 工作流 技巧",
+    "B": "识别工作流软件使用技巧有哪些",
+    "C": "电脑端 检测 节点 流程"
+  },
+  "357": {
+    "idx": 357,
+    "A": "在线 识别 工作流 技巧",
+    "B": "在线识别工作流的操作技巧",
+    "C": "网页版 OCR 流程图 步骤"
+  },
+  "358": {
+    "idx": 358,
+    "A": "代码 识别 工作流 技巧",
+    "B": "编写代码实现识别工作流的技巧",
+    "C": "命令行 转录 工作流 方法"
+  },
+  "361": {
+    "idx": 361,
+    "A": "AI 反推 工作流 教程",
+    "B": "如何通过智能技术反推工作流教程",
+    "C": "AI 反推 workflow 教学"
+  },
+  "362": {
+    "idx": 362,
+    "A": "软件 反推 工作流 教程",
+    "B": "反推工作流的软件操作教程",
+    "C": "电脑端 怎么反推 workflow 教学"
+  },
+  "363": {
+    "idx": 363,
+    "A": "在线 反推 工作流 教程",
+    "B": "在线反推工作流的详细教程",
+    "C": "网页版 怎么反推 节点 教程"
+  },
+  "364": {
+    "idx": 364,
+    "A": "代码 反推 工作流 教程",
+    "B": "通过代码实现反推工作流的教程",
+    "C": "代码 推断 workflow 怎么做"
+  },
+  "365": {
+    "idx": 365,
+    "A": "插件 反推 工作流 教程",
+    "B": "反推工作流插件的安装使用教程",
+    "C": "插件 推断 流程图 怎么做"
+  },
+  "367": {
+    "idx": 367,
+    "A": "AI 反推 工作流 工具",
+    "B": "有没有好用的智能反推工作流工具",
+    "C": "AI 怎么反推 流程图 步骤"
+  },
+  "368": {
+    "idx": 368,
+    "A": "软件 反推 工作流 工具",
+    "B": "反推工作流的常用软件工具",
+    "C": "电脑端 推断 流程图 步骤"
+  },
+  "369": {
+    "idx": 369,
+    "A": "在线 反推 工作流 工具",
+    "B": "在线反推工作流的实用工具",
+    "C": "在线 反推 workflow 步骤"
+  },
+  "370": {
+    "idx": 370,
+    "A": "代码 反推 工作流 工具",
+    "B": "用于反推工作流的代码工具",
+    "C": "代码 分析 workflow 流程"
+  },
+  "371": {
+    "idx": 371,
+    "A": "插件 反推 工作流 工具",
+    "B": "好用的反推工作流插件推荐",
+    "C": "插件 推断 流程图 教程"
+  },
+  "373": {
+    "idx": 373,
+    "A": "AI 反推 工作流 技巧",
+    "B": "智能反推工作流的实用技巧",
+    "C": "AI 推断 workflow 步骤"
+  },
+  "374": {
+    "idx": 374,
+    "A": "软件 反推 工作流 技巧",
+    "B": "反推工作流软件的操作技巧",
+    "C": "软件 推断 工作流 教学"
+  },
+  "375": {
+    "idx": 375,
+    "A": "在线 反推 工作流 技巧",
+    "B": "在线反推工作流的技巧分享",
+    "C": "在线 推断 工作流 教程"
+  },
+  "376": {
+    "idx": 376,
+    "A": "代码 反推 工作流 技巧",
+    "B": "编写代码反推工作流的技巧",
+    "C": "命令行 分析 节点 教程"
+  },
+  "377": {
+    "idx": 377,
+    "A": "插件 反推 工作流 技巧",
+    "B": "反推工作流插件使用技巧",
+    "C": "插件 推断 节点 怎么做"
+  },
+  "378": {
+    "idx": 378,
+    "A": "元素生成 工作流 教程",
+    "B": "元素生成工作流的制作教程",
+    "C": "做 流程图 流程"
+  },
+  "379": {
+    "idx": 379,
+    "A": "AI 元素生成 工作流 教程",
+    "B": "如何利用智能技术进行元素生成工作流制作",
+    "C": "AI 怎么做 节点 教程"
+  },
+  "380": {
+    "idx": 380,
+    "A": "软件 元素生成 工作流 教程",
+    "B": "元素生成工作流软件的操作教程",
+    "C": "软件 做 节点 教程"
+  },
+  "381": {
+    "idx": 381,
+    "A": "在线 元素生成 工作流 教程",
+    "B": "在线制作元素生成工作流的教程",
+    "C": "在线 制作 workflow 方法"
+  },
+  "382": {
+    "idx": 382,
+    "A": "代码 元素生成 工作流 教程",
+    "B": "通过代码实现元素生成工作流的教程",
+    "C": "命令行 生成 workflow 教程"
+  },
+  "383": {
+    "idx": 383,
+    "A": "插件 元素生成 工作流 教程",
+    "B": "元素生成工作流插件使用教程",
+    "C": "插件 创作 workflow 方法"
+  },
+  "384": {
+    "idx": 384,
+    "A": "元素生成 工作流 工具",
+    "B": "有哪些好用的元素生成工作流工具",
+    "C": "做 节点 怎么做"
+  },
+  "385": {
+    "idx": 385,
+    "A": "AI 元素生成 工作流 工具",
+    "B": "智能元素生成工作流工具推荐",
+    "C": "AI 创作 节点 步骤"
+  },
+  "386": {
+    "idx": 386,
+    "A": "软件 元素生成 工作流 工具",
+    "B": "好用的元素生成工作流软件",
+    "C": "软件 创作 工作流 流程"
+  },
+  "387": {
+    "idx": 387,
+    "A": "在线 元素生成 工作流 工具",
+    "B": "在线元素生成工作流工具分享",
+    "C": "在线 怎么做 工作流 流程"
+  },
+  "388": {
+    "idx": 388,
+    "A": "代码 元素生成 工作流 工具",
+    "B": "用于元素生成的代码工具",
+    "C": "代码 制作 工作流 流程"
+  },
+  "389": {
+    "idx": 389,
+    "A": "插件 元素生成 工作流 工具",
+    "B": "元素生成工作流插件有哪些",
+    "C": "插件 做 节点 教学"
+  },
+  "391": {
+    "idx": 391,
+    "A": "AI 元素生成 工作流 技巧",
+    "B": "智能元素生成工作流的技巧",
+    "C": "AI 怎么做 工作流 流程"
+  },
+  "392": {
+    "idx": 392,
+    "A": "软件 元素生成 工作流 技巧",
+    "B": "元素生成工作流软件使用技巧",
+    "C": "电脑端 怎么做 节点 教程"
+  },
+  "393": {
+    "idx": 393,
+    "A": "在线 元素生成 工作流 技巧",
+    "B": "在线元素生成工作流的技巧",
+    "C": "在线 怎么做 workflow 怎么做"
+  },
+  "394": {
+    "idx": 394,
+    "A": "代码 元素生成 工作流 技巧",
+    "B": "代码实现元素生成工作流的技巧",
+    "C": "代码 创作 workflow 教学"
+  },
+  "395": {
+    "idx": 395,
+    "A": "插件 元素生成 工作流 技巧",
+    "B": "元素生成工作流插件使用技巧",
+    "C": "插件 怎么做 workflow 教程"
+  },
+  "397": {
+    "idx": 397,
+    "A": "AI 风格化 工作流 教程",
+    "B": "如何利用智能技术制作风格化工作流",
+    "C": "AI 转风格 流程图 方法"
+  },
+  "398": {
+    "idx": 398,
+    "A": "软件 风格化 工作流 教程",
+    "B": "风格化工作流软件操作教程",
+    "C": "电脑端 怎么转风格 工作流 怎么做"
+  },
+  "399": {
+    "idx": 399,
+    "A": "在线 风格化 工作流 教程",
+    "B": "怎么在网页上进行风格化处理的教程",
+    "C": "网页版 怎么转风格 流程图 方法"
+  },
+  "400": {
+    "idx": 400,
+    "A": "代码 风格化 工作流 教程",
+    "B": "如何通过代码实现风格化工作流的教程",
+    "C": "命令行 怎么转风格 工作流 方法"
+  },
+  "401": {
+    "idx": 401,
+    "A": "插件 风格化 工作流 教程",
+    "B": "有哪些插件可以辅助风格化工作流的教程",
+    "C": "插件 怎么转风格 流程图 方法"
+  },
+  "403": {
+    "idx": 403,
+    "A": "AI 风格化 工作流 工具",
+    "B": "好用的智能风格化处理工具有哪些",
+    "C": "AI 风格化 工作流 流程"
+  },
+  "404": {
+    "idx": 404,
+    "A": "软件 风格化 工作流 工具",
+    "B": "有哪些软件支持风格化工作流",
+    "C": "软件 风格迁移 工作流 流程"
+  },
+  "405": {
+    "idx": 405,
+    "A": "在线 风格化 工作流 工具",
+    "B": "在线进行风格化处理的工具有什么",
+    "C": "网页版 怎么转风格 流程图 流程"
+  },
+  "406": {
+    "idx": 406,
+    "A": "代码 风格化 工作流 工具",
+    "B": "有没有实现风格化工作流的代码工具",
+    "C": "命令行 怎么转风格 工作流 怎么做"
+  },
+  "407": {
+    "idx": 407,
+    "A": "插件 风格化 工作流 工具",
+    "B": "好用的风格化插件推荐",
+    "C": "插件 怎么转风格 流程图 步骤"
+  },
+  "409": {
+    "idx": 409,
+    "A": "AI 风格化 工作流 技巧",
+    "B": "提升风格化工作流效率的技巧",
+    "C": "AI 转风格 流程图 怎么做"
+  },
+  "410": {
+    "idx": 410,
+    "A": "软件 风格化 工作流 技巧",
+    "B": "软件进行风格化处理的实用技巧",
+    "C": "电脑端 风格迁移 节点 方法"
+  },
+  "411": {
+    "idx": 411,
+    "A": "在线 风格化 工作流 技巧",
+    "B": "在线处理风格化的操作技巧",
+    "C": "在线 怎么转风格 工作流 步骤"
+  },
+  "412": {
+    "idx": 412,
+    "A": "代码 风格化 工作流 技巧",
+    "B": "编写代码实现风格化的技巧",
+    "C": "命令行 风格迁移 工作流 怎么做"
+  },
+  "413": {
+    "idx": 413,
+    "A": "插件 风格化 工作流 技巧",
+    "B": "使用插件进行风格化处理的技巧",
+    "C": "插件 怎么转风格 节点 教程"
+  },
+  "414": {
+    "idx": 414,
+    "A": "抠取 批处理 教程",
+    "B": "如何批量抠图的教程",
+    "C": "抠 batch 步骤"
+  },
+  "416": {
+    "idx": 416,
+    "A": "软件 抠取 批处理 教程",
+    "B": "有什么软件可以批量抠图的教程",
+    "C": "电脑端 怎么抠 批处理 流程"
+  },
+  "417": {
+    "idx": 417,
+    "A": "在线 抠取 批处理 教程",
+    "B": "在线批量抠图怎么操作的教程",
+    "C": "网页版 抠 批量 怎么做"
+  },
+  "418": {
+    "idx": 418,
+    "A": "代码 抠取 批处理 教程",
+    "B": "通过代码实现批量抠图的教程",
+    "C": "命令行 抠图 批处理 教学"
+  },
+  "419": {
+    "idx": 419,
+    "A": "插件 抠取 批处理 教程",
+    "B": "有哪些插件可以批量抠图的教程",
+    "C": "插件 抠 批量 方法"
+  },
+  "421": {
+    "idx": 421,
+    "A": "AI 抠取 批处理 工具",
+    "B": "好用的智能批量抠图工具有哪些",
+    "C": "AI 怎么抠 批处理 流程"
+  },
+  "422": {
+    "idx": 422,
+    "A": "软件 抠取 批处理 工具",
+    "B": "有什么可以批量抠图的软件吗",
+    "C": "软件 抠图 batch 步骤"
+  },
+  "423": {
+    "idx": 423,
+    "A": "在线 抠取 批处理 工具",
+    "B": "怎么在线批量抠图",
+    "C": "在线 抠 批处理 教学"
+  },
+  "424": {
+    "idx": 424,
+    "A": "代码 抠取 批处理 工具",
+    "B": "如何用代码实现批量抠图",
+    "C": "代码 抠图 batch 怎么做"
+  },
+  "425": {
+    "idx": 425,
+    "A": "插件 抠取 批处理 工具",
+    "B": "有没有批量抠图的插件",
+    "C": "插件 抠图 批处理 流程"
+  },
+  "426": {
+    "idx": 426,
+    "A": "抠取 批处理 技巧",
+    "B": "批量抠图有哪些好用的技巧",
+    "C": "抠 batch 方法"
+  },
+  "428": {
+    "idx": 428,
+    "A": "软件 抠取 批处理 技巧",
+    "B": "软件批量抠图有什么操作技巧",
+    "C": "软件 抠 batch 教学"
+  },
+  "429": {
+    "idx": 429,
+    "A": "在线 抠取 批处理 技巧",
+    "B": "在线批量抠图怎么操作更高效",
+    "C": "网页版 抠 批量 方法"
+  },
+  "430": {
+    "idx": 430,
+    "A": "代码 抠取 批处理 技巧",
+    "B": "用代码批量抠图有什么技巧",
+    "C": "命令行 抠图 批处理 教学"
+  },
+  "431": {
+    "idx": 431,
+    "A": "插件 抠取 批处理 技巧",
+    "B": "使用插件批量抠图有什么技巧",
+    "C": "插件 分割 批量 流程"
+  },
+  "432": {
+    "idx": 432,
+    "A": "抽帧 批处理 教程",
+    "B": "视频批量抽帧的教程",
+    "C": "提取帧 批量 教程"
+  },
+  "433": {
+    "idx": 433,
+    "A": "AI 抽帧 批处理 教程",
+    "B": "如何利用智能技术批量抽帧",
+    "C": "AI 导出帧 批处理 步骤"
+  },
+  "434": {
+    "idx": 434,
+    "A": "软件 抽帧 批处理 教程",
+    "B": "软件批量抽帧怎么操作",
+    "C": "电脑端 怎么抽帧 批处理 教学"
+  },
+  "435": {
+    "idx": 435,
+    "A": "在线 抽帧 批处理 教程",
+    "B": "在线批量抽帧的方法",
+    "C": "网页版 抽帧 批量 教程"
+  },
+  "436": {
+    "idx": 436,
+    "A": "代码 抽帧 批处理 教程",
+    "B": "怎么写代码批量抽帧",
+    "C": "命令行 怎么抽帧 batch 流程"
+  },
+  "437": {
+    "idx": 437,
+    "A": "插件 抽帧 批处理 教程",
+    "B": "有哪些好用的批量抽帧插件",
+    "C": "插件 抽帧 batch 流程"
+  },
+  "439": {
+    "idx": 439,
+    "A": "AI 抽帧 批处理 工具",
+    "B": "有没有能批量抽帧的智能工具",
+    "C": "AI 抽帧 批处理 教程"
+  },
+  "440": {
+    "idx": 440,
+    "A": "软件 抽帧 批处理 工具",
+    "B": "批量抽帧用什么软件好",
+    "C": "电脑端 怎么抽帧 批量 教学"
+  },
+  "441": {
+    "idx": 441,
+    "A": "在线 抽帧 批处理 工具",
+    "B": "在线批量抽帧工具推荐",
+    "C": "网页版 提取帧 批量 步骤"
+  },
+  "442": {
+    "idx": 442,
+    "A": "代码 抽帧 批处理 工具",
+    "B": "批量抽帧的代码工具怎么找",
+    "C": "代码 怎么抽帧 batch 教学"
+  },
+  "443": {
+    "idx": 443,
+    "A": "插件 抽帧 批处理 工具",
+    "B": "求推荐批量抽帧的插件",
+    "C": "插件 提取帧 batch 教学"
+  },
+  "445": {
+    "idx": 445,
+    "A": "AI 抽帧 批处理 技巧",
+    "B": "批量抽帧有哪些实用技巧",
+    "C": "AI 提取帧 批量 怎么做"
+  },
+  "446": {
+    "idx": 446,
+    "A": "软件 抽帧 批处理 技巧",
+    "B": "软件批量抽帧的操作技巧",
+    "C": "电脑端 提取帧 batch 步骤"
+  },
+  "447": {
+    "idx": 447,
+    "A": "在线 抽帧 批处理 技巧",
+    "B": "在线批量抽帧有什么技巧",
+    "C": "在线 提取帧 批处理 步骤"
+  },
+  "448": {
+    "idx": 448,
+    "A": "代码 抽帧 批处理 技巧",
+    "B": "代码批量抽帧的进阶技巧",
+    "C": "命令行 怎么抽帧 批处理 流程"
+  },
+  "449": {
+    "idx": 449,
+    "A": "插件 抽帧 批处理 技巧",
+    "B": "插件批量抽帧的技巧分享",
+    "C": "插件 提取帧 batch 怎么做"
+  },
+  "450": {
+    "idx": 450,
+    "A": "识别 批处理 教程",
+    "B": "如何批量识别图片或文件的教程",
+    "C": "提取文字 batch 怎么做"
+  },
+  "451": {
+    "idx": 451,
+    "A": "AI 识别 批处理 教程",
+    "B": "智能批量识别的操作教程",
+    "C": "AI OCR 批处理 流程"
+  },
+  "452": {
+    "idx": 452,
+    "A": "软件 识别 批处理 教程",
+    "B": "软件批量识别怎么做",
+    "C": "电脑端 转录 批量 方法"
+  },
+  "453": {
+    "idx": 453,
+    "A": "在线 识别 批处理 教程",
+    "B": "在线批量识别的方法",
+    "C": "网页版 OCR 批处理 流程"
+  },
+  "454": {
+    "idx": 454,
+    "A": "代码 识别 批处理 教程",
+    "B": "如何用代码实现批量识别",
+    "C": "命令行 识别 批处理 教程"
+  },
+  "455": {
+    "idx": 455,
+    "A": "插件 识别 批处理 教程",
+    "B": "有没有批量识别的插件教程",
+    "C": "插件 检测 batch 怎么做"
+  },
+  "457": {
+    "idx": 457,
+    "A": "AI 识别 批处理 工具",
+    "B": "好用的智能批量识别工具",
+    "C": "AI 提取文字 批量 方法"
+  },
+  "458": {
+    "idx": 458,
+    "A": "软件 识别 批处理 工具",
+    "B": "批量识别用什么软件比较好",
+    "C": "电脑端 转录 批量 方法"
+  },
+  "459": {
+    "idx": 459,
+    "A": "在线 识别 批处理 工具",
+    "B": "在线批量识别工具有哪些",
+    "C": "在线 识别 batch 方法"
+  },
+  "460": {
+    "idx": 460,
+    "A": "代码 识别 批处理 工具",
+    "B": "批量识别的代码工具推荐",
+    "C": "命令行 OCR 批处理 步骤"
+  },
+  "461": {
+    "idx": 461,
+    "A": "插件 识别 批处理 工具",
+    "B": "好用的批量识别插件",
+    "C": "插件 检测 批量 教程"
+  },
+  "463": {
+    "idx": 463,
+    "A": "AI 识别 批处理 技巧",
+    "B": "批量识别有哪些操作技巧",
+    "C": "AI 转录 批处理 方法"
+  },
+  "464": {
+    "idx": 464,
+    "A": "软件 识别 批处理 技巧",
+    "B": "软件批量识别的实用技巧",
+    "C": "软件 OCR batch 方法"
+  },
+  "465": {
+    "idx": 465,
+    "A": "在线 识别 批处理 技巧",
+    "B": "在线批量识别有什么技巧",
+    "C": "在线 检测 批量 流程"
+  },
+  "466": {
+    "idx": 466,
+    "A": "代码 识别 批处理 技巧",
+    "B": "代码批量识别的技巧",
+    "C": "代码 转录 批量 怎么做"
+  },
+  "467": {
+    "idx": 467,
+    "A": "插件 识别 批处理 技巧",
+    "B": "怎么用插件批量识别文件的方法",
+    "C": "插件 识别 批量 步骤"
+  },
+  "469": {
+    "idx": 469,
+    "A": "AI 转换 批处理 教程",
+    "B": "如何用人工智能批量转换格式的教程",
+    "C": "AI 转换 批处理 方法"
+  },
+  "470": {
+    "idx": 470,
+    "A": "软件 转换 批处理 教程",
+    "B": "有什么好用的批量转换软件教程",
+    "C": "软件 转换 batch 怎么做"
+  },
+  "471": {
+    "idx": 471,
+    "A": "在线 转换 批处理 教程",
+    "B": "在线批量转换格式的操作方法",
+    "C": "在线 转 批处理 教学"
+  },
+  "472": {
+    "idx": 472,
+    "A": "代码 转换 批处理 教程",
+    "B": "通过代码实现批量转换的教程",
+    "C": "命令行 转 批量 方法"
+  },
+  "473": {
+    "idx": 473,
+    "A": "插件 转换 批处理 教程",
+    "B": "怎么用插件进行批量转换的教程",
+    "C": "插件 转 batch 教学"
+  },
+  "475": {
+    "idx": 475,
+    "A": "AI 转换 批处理 工具",
+    "B": "有哪些好用的人工智能批量转换工具",
+    "C": "AI 怎么转 批量 教学"
+  },
+  "476": {
+    "idx": 476,
+    "A": "软件 转换 批处理 工具",
+    "B": "适合批量转换文件的软件有哪些",
+    "C": "电脑端 转格式 batch 怎么做"
+  },
+  "477": {
+    "idx": 477,
+    "A": "在线 转换 批处理 工具",
+    "B": "好用的在线批量转换工具推荐",
+    "C": "在线 转 批处理 教程"
+  },
+  "478": {
+    "idx": 478,
+    "A": "代码 转换 批处理 工具",
+    "B": "实现批量转换的代码工具分享",
+    "C": "命令行 转换 batch 方法"
+  },
+  "479": {
+    "idx": 479,
+    "A": "插件 转换 批处理 工具",
+    "B": "有哪些好用的批量转换插件",
+    "C": "插件 转 批处理 教程"
+  },
+  "481": {
+    "idx": 481,
+    "A": "AI 转换 批处理 技巧",
+    "B": "人工智能批量转换的小技巧",
+    "C": "AI 转 批处理 教程"
+  },
+  "482": {
+    "idx": 482,
+    "A": "软件 转换 批处理 技巧",
+    "B": "软件批量转换文件的实用技巧",
+    "C": "电脑端 转换 batch 流程"
+  },
+  "483": {
+    "idx": 483,
+    "A": "在线 转换 批处理 技巧",
+    "B": "在线批量转换格式的技巧分享",
+    "C": "网页版 转格式 批处理 方法"
+  },
+  "484": {
+    "idx": 484,
+    "A": "代码 转换 批处理 技巧",
+    "B": "用代码批量转换文件的方法技巧",
+    "C": "代码 转格式 批处理 怎么做"
+  },
+  "485": {
+    "idx": 485,
+    "A": "插件 转换 批处理 技巧",
+    "B": "插件批量转换文件的操作技巧",
+    "C": "插件 转 批处理 教程"
+  },
+  "486": {
+    "idx": 486,
+    "A": "增强 批处理 教程",
+    "B": "如何对文件进行批量增强处理",
+    "C": "修复 批量 怎么做"
+  },
+  "487": {
+    "idx": 487,
+    "A": "AI 增强 批处理 教程",
+    "B": "怎样用人工智能批量增强画质的教程",
+    "C": "AI 修复 batch 教程"
+  },
+  "489": {
+    "idx": 489,
+    "A": "在线 增强 批处理 教程",
+    "B": "在线批量增强文件效果的教程",
+    "C": "在线 增强 批量 教学"
+  },
+  "490": {
+    "idx": 490,
+    "A": "代码 增强 批处理 教程",
+    "B": "通过代码批量增强文件的方法",
+    "C": "命令行 增强 批处理 流程"
+  },
+  "491": {
+    "idx": 491,
+    "A": "插件 增强 批处理 教程",
+    "B": "怎么用插件批量增强文件效果",
+    "C": "插件 超分 批量 流程"
+  },
+  "493": {
+    "idx": 493,
+    "A": "AI 增强 批处理 工具",
+    "B": "好用的人工智能批量增强工具",
+    "C": "AI 提升画质 批量 怎么做"
+  },
+  "494": {
+    "idx": 494,
+    "A": "软件 增强 批处理 工具",
+    "B": "有哪些好用的批量增强软件",
+    "C": "软件 增强 批量 方法"
+  },
+  "495": {
+    "idx": 495,
+    "A": "在线 增强 批处理 工具",
+    "B": "在线批量增强文件的工具推荐",
+    "C": "在线 增强 batch 方法"
+  },
+  "496": {
+    "idx": 496,
+    "A": "代码 增强 批处理 工具",
+    "B": "实现批量增强的代码工具",
+    "C": "代码 增强 批处理 流程"
+  },
+  "497": {
+    "idx": 497,
+    "A": "插件 增强 批处理 工具",
+    "B": "好用的批量增强插件有哪些",
+    "C": "插件 修复 批量 流程"
+  },
+  "498": {
+    "idx": 498,
+    "A": "增强 批处理 技巧",
+    "B": "批量增强文件的实用小技巧",
+    "C": "修复 批处理 流程"
+  },
+  "499": {
+    "idx": 499,
+    "A": "AI 增强 批处理 技巧",
+    "B": "人工智能批量增强画质的技巧",
+    "C": "AI 增强 批量 步骤"
+  },
+  "501": {
+    "idx": 501,
+    "A": "在线 增强 批处理 技巧",
+    "B": "在线批量增强文件的操作技巧",
+    "C": "网页版 怎么增强 批量 教学"
+  },
+  "502": {
+    "idx": 502,
+    "A": "代码 增强 批处理 技巧",
+    "B": "用代码批量增强文件的技巧",
+    "C": "命令行 提升画质 批处理 步骤"
+  },
+  "503": {
+    "idx": 503,
+    "A": "插件 增强 批处理 技巧",
+    "B": "插件批量增强文件的技巧分享",
+    "C": "插件 增强 batch 教学"
+  },
+  "505": {
+    "idx": 505,
+    "A": "AI 上传 数字人 教程",
+    "B": "如何用人工智能上传数字人的教程",
+    "C": "AI 怎么导入 数字人 教程"
+  },
+  "506": {
+    "idx": 506,
+    "A": "软件 上传 数字人 教程",
+    "B": "怎样用软件上传数字人的教程",
+    "C": "电脑端 导入 数字人 方法"
+  },
+  "507": {
+    "idx": 507,
+    "A": "在线 上传 数字人 教程",
+    "B": "在线上传数字人的操作教程",
+    "C": "在线 导入 数字人 方法"
+  },
+  "508": {
+    "idx": 508,
+    "A": "代码 上传 数字人 教程",
+    "B": "通过代码上传数字人的教程",
+    "C": "代码 导入 AI分身 教程"
+  },
+  "509": {
+    "idx": 509,
+    "A": "插件 上传 数字人 教程",
+    "B": "怎么用插件上传数字人的教程",
+    "C": "插件 上传 数字人 怎么做"
+  },
+  "511": {
+    "idx": 511,
+    "A": "AI 上传 数字人 工具",
+    "B": "好用的人工智能数字人上传工具",
+    "C": "AI 怎么导入 虚拟人 教学"
+  },
+  "512": {
+    "idx": 512,
+    "A": "软件 上传 数字人 工具",
+    "B": "有哪些好用的数字人上传软件",
+    "C": "电脑端 导入 数字分身 怎么做"
+  },
+  "513": {
+    "idx": 513,
+    "A": "在线 上传 数字人 工具",
+    "B": "好用的在线数字人上传工具",
+    "C": "在线 怎么导入 AI分身 步骤"
+  },
+  "514": {
+    "idx": 514,
+    "A": "代码 上传 数字人 工具",
+    "B": "实现数字人上传的代码工具",
+    "C": "代码 上传 AI分身 方法"
+  },
+  "515": {
+    "idx": 515,
+    "A": "插件 上传 数字人 工具",
+    "B": "怎么通过插件上传数字人",
+    "C": "插件 上传 虚拟人 方法"
+  },
+  "517": {
+    "idx": 517,
+    "A": "AI 上传 数字人 技巧",
+    "B": "上传数字人的技巧有哪些",
+    "C": "AI 导入 数字分身 教程"
+  },
+  "518": {
+    "idx": 518,
+    "A": "软件 上传 数字人 技巧",
+    "B": "有什么软件可以上传数字人",
+    "C": "软件 怎么导入 数字分身 流程"
+  },
+  "519": {
+    "idx": 519,
+    "A": "在线 上传 数字人 技巧",
+    "B": "在线上传数字人的方法",
+    "C": "网页版 怎么导入 数字人 教学"
+  },
+  "520": {
+    "idx": 520,
+    "A": "代码 上传 数字人 技巧",
+    "B": "如何通过代码上传数字人",
+    "C": "命令行 上传 虚拟人 步骤"
+  },
+  "521": {
+    "idx": 521,
+    "A": "插件 上传 数字人 技巧",
+    "B": "插件上传数字人的操作技巧",
+    "C": "插件 上传 虚拟人 步骤"
+  },
+  "522": {
+    "idx": 522,
+    "A": "键入 数字人 教程",
+    "B": "数字人键入教程怎么看",
+    "C": "怎么写 虚拟人 教学"
+  },
+  "523": {
+    "idx": 523,
+    "A": "AI 键入 数字人 教程",
+    "B": "如何用人工智能键入数字人",
+    "C": "AI 输入 数字分身 方法"
+  },
+  "524": {
+    "idx": 524,
+    "A": "软件 键入 数字人 教程",
+    "B": "有没有键入数字人的软件教程",
+    "C": "电脑端 怎么写 数字人 教程"
+  },
+  "525": {
+    "idx": 525,
+    "A": "在线 键入 数字人 教程",
+    "B": "在线键入数字人的详细步骤",
+    "C": "网页版 怎么写 数字人 教程"
+  },
+  "526": {
+    "idx": 526,
+    "A": "代码 键入 数字人 教程",
+    "B": "代码键入数字人的方法",
+    "C": "命令行 输入 数字分身 流程"
+  },
+  "527": {
+    "idx": 527,
+    "A": "插件 键入 数字人 教程",
+    "B": "通过插件键入数字人的教程",
+    "C": "插件 编写 数字人 教程"
+  },
+  "529": {
+    "idx": 529,
+    "A": "AI 键入 数字人 工具",
+    "B": "好用的数字人键入工具推荐",
+    "C": "AI 输入 数字人 步骤"
+  },
+  "530": {
+    "idx": 530,
+    "A": "软件 键入 数字人 工具",
+    "B": "有没有键入数字人的软件",
+    "C": "软件 编写 虚拟人 教程"
+  },
+  "531": {
+    "idx": 531,
+    "A": "在线 键入 数字人 工具",
+    "B": "在线键入数字人的工具",
+    "C": "网页版 怎么写 数字人 步骤"
+  },
+  "532": {
+    "idx": 532,
+    "A": "代码 键入 数字人 工具",
+    "B": "适合代码键入数字人的工具",
+    "C": "代码 输入 数字人 步骤"
+  },
+  "533": {
+    "idx": 533,
+    "A": "插件 键入 数字人 工具",
+    "B": "键入数字人的插件有哪些",
+    "C": "插件 输入 虚拟人 流程"
+  },
+  "535": {
+    "idx": 535,
+    "A": "AI 键入 数字人 技巧",
+    "B": "人工智能键入数字人的技巧",
+    "C": "AI 编写 数字人 流程"
+  },
+  "536": {
+    "idx": 536,
+    "A": "软件 键入 数字人 技巧",
+    "B": "软件键入数字人的操作技巧",
+    "C": "电脑端 编写 虚拟人 步骤"
+  },
+  "537": {
+    "idx": 537,
+    "A": "在线 键入 数字人 技巧",
+    "B": "在线键入数字人的小技巧",
+    "C": "在线 写 AI分身 教程"
+  },
+  "538": {
+    "idx": 538,
+    "A": "代码 键入 数字人 技巧",
+    "B": "代码键入数字人的实用技巧",
+    "C": "命令行 输入 虚拟人 怎么做"
+  },
+  "539": {
+    "idx": 539,
+    "A": "插件 键入 数字人 技巧",
+    "B": "插件键入数字人的技巧分享",
+    "C": "插件 怎么写 虚拟人 流程"
+  },
+  "541": {
+    "idx": 541,
+    "A": "AI 元素生成 数字人 教程",
+    "B": "如何用人工智能生成数字人元素",
+    "C": "AI 制作 AI分身 步骤"
+  },
+  "542": {
+    "idx": 542,
+    "A": "软件 元素生成 数字人 教程",
+    "B": "软件生成数字人元素的教程",
+    "C": "电脑端 生成 数字分身 步骤"
+  },
+  "543": {
+    "idx": 543,
+    "A": "在线 元素生成 数字人 教程",
+    "B": "在线生成数字人元素的方法",
+    "C": "网页版 创作 数字分身 教程"
+  },
+  "544": {
+    "idx": 544,
+    "A": "代码 元素生成 数字人 教程",
+    "B": "如何用代码生成数字人元素",
+    "C": "代码 怎么做 虚拟人 方法"
+  },
+  "545": {
+    "idx": 545,
+    "A": "插件 元素生成 数字人 教程",
+    "B": "插件生成数字人元素的教程",
+    "C": "插件 生成 数字人 方法"
+  },
+  "547": {
+    "idx": 547,
+    "A": "AI 元素生成 数字人 工具",
+    "B": "生成数字人元素的工具推荐",
+    "C": "AI 怎么做 数字分身 怎么做"
+  },
+  "548": {
+    "idx": 548,
+    "A": "软件 元素生成 数字人 工具",
+    "B": "好用的数字人元素生成软件",
+    "C": "软件 做 虚拟人 步骤"
+  },
+  "549": {
+    "idx": 549,
+    "A": "在线 元素生成 数字人 工具",
+    "B": "在线生成数字人元素的工具",
+    "C": "在线 做 数字人 方法"
+  },
+  "550": {
+    "idx": 550,
+    "A": "代码 元素生成 数字人 工具",
+    "B": "代码生成数字人元素的工具",
+    "C": "代码 怎么做 AI分身 教程"
+  },
+  "551": {
+    "idx": 551,
+    "A": "插件 元素生成 数字人 工具",
+    "B": "有哪些插件可以生成数字人元素",
+    "C": "插件 创作 数字分身 教学"
+  },
+  "553": {
+    "idx": 553,
+    "A": "AI 元素生成 数字人 技巧",
+    "B": "人工智能生成数字人元素的技巧",
+    "C": "AI 怎么做 数字分身 教学"
+  },
+  "554": {
+    "idx": 554,
+    "A": "软件 元素生成 数字人 技巧",
+    "B": "软件生成数字人元素的技巧",
+    "C": "电脑端 怎么做 AI分身 教学"
+  },
+  "555": {
+    "idx": 555,
+    "A": "在线 元素生成 数字人 技巧",
+    "B": "在线生成数字人元素的技巧",
+    "C": "网页版 创作 虚拟人 流程"
+  },
+  "556": {
+    "idx": 556,
+    "A": "代码 元素生成 数字人 技巧",
+    "B": "代码生成数字人元素的技巧",
+    "C": "命令行 做 虚拟人 方法"
+  },
+  "557": {
+    "idx": 557,
+    "A": "插件 元素生成 数字人 技巧",
+    "B": "插件生成数字人元素的技巧",
+    "C": "插件 做 数字人 步骤"
+  },
+  "558": {
+    "idx": 558,
+    "A": "结构生成 版式 教程",
+    "B": "结构化排版设计教程",
+    "C": "怎么生成 排版 怎么做"
+  },
+  "559": {
+    "idx": 559,
+    "A": "AI 结构生成 版式 教程",
+    "B": "如何用人工智能进行结构化排版",
+    "C": "AI 构建 layout 怎么做"
+  },
+  "560": {
+    "idx": 560,
+    "A": "软件 结构生成 版式 教程",
+    "B": "有哪些软件可以做结构化排版",
+    "C": "软件 构建 排版 教学"
+  },
+  "562": {
+    "idx": 562,
+    "A": "代码 结构生成 版式 教程",
+    "B": "如何通过代码生成页面结构和版式教程",
+    "C": "代码 怎么生成 版面 教程"
+  },
+  "563": {
+    "idx": 563,
+    "A": "插件 结构生成 版式 教程",
+    "B": "有哪些好用的插件可以辅助生成结构版式",
+    "C": "插件 怎么生成 排版 流程"
+  },
+  "565": {
+    "idx": 565,
+    "A": "AI 结构生成 版式 工具",
+    "B": "怎么利用智能技术生成页面结构和版式",
+    "C": "AI 生成 版式 流程"
+  },
+  "566": {
+    "idx": 566,
+    "A": "软件 结构生成 版式 工具",
+    "B": "有没有什么软件能自动生成页面结构版式",
+    "C": "电脑端 生成 layout 怎么做"
+  },
+  "567": {
+    "idx": 567,
+    "A": "在线 结构生成 版式 工具",
+    "B": "在线生成页面结构和版式的工具有哪些",
+    "C": "在线 构建 layout 怎么做"
+  },
+  "568": {
+    "idx": 568,
+    "A": "代码 结构生成 版式 工具",
+    "B": "如何用代码快速生成页面结构和版式",
+    "C": "代码 搭建 版式 教程"
+  },
+  "569": {
+    "idx": 569,
+    "A": "插件 结构生成 版式 工具",
+    "B": "有哪些插件能帮我生成页面结构和版式",
+    "C": "插件 搭建 排版 教学"
+  },
+  "570": {
+    "idx": 570,
+    "A": "结构生成 版式 技巧",
+    "B": "页面结构和版式设计有哪些实用技巧",
+    "C": "构建 版式 方法"
+  },
+  "571": {
+    "idx": 571,
+    "A": "AI 结构生成 版式 技巧",
+    "B": "如何利用智能技术优化页面结构和版式设计",
+    "C": "AI 生成 layout 流程"
+  },
+  "572": {
+    "idx": 572,
+    "A": "软件 结构生成 版式 技巧",
+    "B": "软件排版和结构设计的实用技巧有哪些",
+    "C": "电脑端 怎么生成 layout 方法"
+  },
+  "574": {
+    "idx": 574,
+    "A": "代码 结构生成 版式 技巧",
+    "B": "编写代码时如何优化页面结构和版式",
+    "C": "命令行 构建 排版 教学"
+  },
+  "575": {
+    "idx": 575,
+    "A": "插件 结构生成 版式 技巧",
+    "B": "使用插件调整页面结构和版式的技巧",
+    "C": "插件 构建 版面 流程"
+  },
+  "577": {
+    "idx": 577,
+    "A": "AI 键入 模板 教程",
+    "B": "如何通过智能技术实现自动键入模板教程",
+    "C": "AI 编写 套版 流程"
+  },
+  "578": {
+    "idx": 578,
+    "A": "软件 键入 模板 教程",
+    "B": "软件自动键入模板的操作教程",
+    "C": "电脑端 编写 模板 教学"
+  },
+  "579": {
+    "idx": 579,
+    "A": "在线 键入 模板 教程",
+    "B": "在线自动键入模板的使用教程",
+    "C": "网页版 输入 template 步骤"
+  },
+  "580": {
+    "idx": 580,
+    "A": "代码 键入 模板 教程",
+    "B": "如何通过代码实现自动键入模板",
+    "C": "命令行 写 模板 流程"
+  },
+  "581": {
+    "idx": 581,
+    "A": "插件 键入 模板 教程",
+    "B": "有哪些插件可以辅助实现自动键入模板",
+    "C": "插件 编写 套版 流程"
+  },
+  "583": {
+    "idx": 583,
+    "A": "AI 键入 模板 工具",
+    "B": "好用的自动键入模板工具有哪些",
+    "C": "AI 写 template 怎么做"
+  },
+  "584": {
+    "idx": 584,
+    "A": "软件 键入 模板 工具",
+    "B": "有没有适合自动键入模板的软件",
+    "C": "电脑端 编写 template 教程"
+  },
+  "585": {
+    "idx": 585,
+    "A": "在线 键入 模板 工具",
+    "B": "在线自动键入模板的工具有哪些",
+    "C": "在线 编写 template 方法"
+  },
+  "586": {
+    "idx": 586,
+    "A": "代码 键入 模板 工具",
+    "B": "如何用代码实现自动键入模板功能",
+    "C": "代码 编写 template 教程"
+  },
+  "587": {
+    "idx": 587,
+    "A": "插件 键入 模板 工具",
+    "B": "哪些插件支持自动键入模板",
+    "C": "插件 怎么写 template 怎么做"
+  },
+  "589": {
+    "idx": 589,
+    "A": "AI 键入 模板 技巧",
+    "B": "提高自动键入模板效率的技巧",
+    "C": "AI 编写 模板 步骤"
+  },
+  "590": {
+    "idx": 590,
+    "A": "软件 键入 模板 技巧",
+    "B": "软件键入模板有哪些实用技巧",
+    "C": "电脑端 编写 模板 怎么做"
+  },
+  "591": {
+    "idx": 591,
+    "A": "在线 键入 模板 技巧",
+    "B": "在线键入模板的操作技巧",
+    "C": "网页版 编写 套版 流程"
+  },
+  "592": {
+    "idx": 592,
+    "A": "代码 键入 模板 技巧",
+    "B": "代码实现键入模板的进阶技巧",
+    "C": "命令行 输入 套版 方法"
+  },
+  "593": {
+    "idx": 593,
+    "A": "插件 键入 模板 技巧",
+    "B": "使用插件键入模板的技巧",
+    "C": "插件 编写 套版 方法"
+  },
+  "594": {
+    "idx": 594,
+    "A": "结构生成 模板 教程",
+    "B": "如何制作和生成页面结构模板教程",
+    "C": "生成 模板 教学"
+  },
+  "595": {
+    "idx": 595,
+    "A": "AI 结构生成 模板 教程",
+    "B": "利用智能技术生成结构模板的教程",
+    "C": "AI 搭建 template 流程"
+  },
+  "596": {
+    "idx": 596,
+    "A": "软件 结构生成 模板 教程",
+    "B": "软件生成结构模板的操作教程",
+    "C": "软件 怎么生成 template 步骤"
+  },
+  "597": {
+    "idx": 597,
+    "A": "在线 结构生成 模板 教程",
+    "B": "在线生成结构模板的使用教程",
+    "C": "在线 构建 template 步骤"
+  },
+  "598": {
+    "idx": 598,
+    "A": "代码 结构生成 模板 教程",
+    "B": "如何用代码生成结构模板",
+    "C": "命令行 怎么生成 template 步骤"
+  },
+  "599": {
+    "idx": 599,
+    "A": "插件 结构生成 模板 教程",
+    "B": "有哪些插件可以生成结构模板",
+    "C": "插件 构建 模板 教学"
+  },
+  "601": {
+    "idx": 601,
+    "A": "AI 结构生成 模板 工具",
+    "B": "好用的结构模板生成工具有哪些",
+    "C": "AI 怎么生成 模板 教学"
+  },
+  "602": {
+    "idx": 602,
+    "A": "软件 结构生成 模板 工具",
+    "B": "有没有能自动生成结构模板的软件",
+    "C": "软件 生成 模板 流程"
+  },
+  "603": {
+    "idx": 603,
+    "A": "在线 结构生成 模板 工具",
+    "B": "在线生成结构模板的工具有哪些",
+    "C": "在线 生成 套版 流程"
+  },
+  "604": {
+    "idx": 604,
+    "A": "代码 结构生成 模板 工具",
+    "B": "如何用代码快速生成结构模板",
+    "C": "代码 搭建 template 教学"
+  },
+  "605": {
+    "idx": 605,
+    "A": "插件 结构生成 模板 工具",
+    "B": "哪些插件可以用来生成结构模板",
+    "C": "插件 搭建 template 教学"
+  },
+  "607": {
+    "idx": 607,
+    "A": "AI 结构生成 模板 技巧",
+    "B": "智能生成结构模板的实用技巧",
+    "C": "AI 怎么生成 模板 方法"
+  },
+  "608": {
+    "idx": 608,
+    "A": "软件 结构生成 模板 技巧",
+    "B": "软件生成结构模板的技巧有哪些",
+    "C": "软件 搭建 template 教程"
+  },
+  "609": {
+    "idx": 609,
+    "A": "在线 结构生成 模板 技巧",
+    "B": "如何在线制作结构生成模板",
+    "C": "在线 怎么生成 套版 教学"
+  },
+  "610": {
+    "idx": 610,
+    "A": "代码 结构生成 模板 技巧",
+    "B": "编写代码生成结构模板的技巧",
+    "C": "命令行 构建 套版 流程"
+  },
+  "611": {
+    "idx": 611,
+    "A": "插件 结构生成 模板 技巧",
+    "B": "使用插件制作结构模板的方法",
+    "C": "插件 搭建 模板 教学"
+  },
+  "613": {
+    "idx": 613,
+    "A": "AI 替换 模板 教程",
+    "B": "如何用智能技术替换模板的教程",
+    "C": "AI 替换 套版 教程"
+  },
+  "614": {
+    "idx": 614,
+    "A": "软件 替换 模板 教程",
+    "B": "软件替换模板的操作教程",
+    "C": "电脑端 替换成 套版 步骤"
+  },
+  "615": {
+    "idx": 615,
+    "A": "在线 替换 模板 教程",
+    "B": "在线替换模板的详细教程",
+    "C": "在线 怎么换 模板 怎么做"
+  },
+  "616": {
+    "idx": 616,
+    "A": "代码 替换 模板 教程",
+    "B": "通过代码替换模板的教程",
+    "C": "命令行 替换 template 步骤"
+  },
+  "617": {
+    "idx": 617,
+    "A": "插件 替换 模板 教程",
+    "B": "插件替换模板的使用教程",
+    "C": "插件 换 template 流程"
+  },
+  "619": {
+    "idx": 619,
+    "A": "AI 替换 模板 工具",
+    "B": "好用的智能替换模板工具",
+    "C": "AI 替换成 template 怎么做"
+  },
+  "620": {
+    "idx": 620,
+    "A": "软件 替换 模板 工具",
+    "B": "有哪些软件可以替换模板",
+    "C": "电脑端 怎么换 模板 教程"
+  },
+  "621": {
+    "idx": 621,
+    "A": "在线 替换 模板 工具",
+    "B": "在线替换模板的工具推荐",
+    "C": "网页版 替换成 模板 怎么做"
+  },
+  "622": {
+    "idx": 622,
+    "A": "代码 替换 模板 工具",
+    "B": "编写代码替换模板的工具",
+    "C": "命令行 怎么换 模板 怎么做"
+  },
+  "623": {
+    "idx": 623,
+    "A": "插件 替换 模板 工具",
+    "B": "好用的模板替换插件",
+    "C": "插件 换 template 流程"
+  },
+  "625": {
+    "idx": 625,
+    "A": "AI 替换 模板 技巧",
+    "B": "智能替换模板的实用技巧",
+    "C": "AI 怎么换 template 步骤"
+  },
+  "626": {
+    "idx": 626,
+    "A": "软件 替换 模板 技巧",
+    "B": "软件替换模板的技巧分享",
+    "C": "电脑端 替换 套版 流程"
+  },
+  "627": {
+    "idx": 627,
+    "A": "在线 替换 模板 技巧",
+    "B": "在线替换模板的技巧有哪些",
+    "C": "在线 换 套版 怎么做"
+  },
+  "628": {
+    "idx": 628,
+    "A": "代码 替换 模板 技巧",
+    "B": "代码替换模板的技巧与方法",
+    "C": "命令行 换 套版 怎么做"
+  },
+  "629": {
+    "idx": 629,
+    "A": "插件 替换 模板 技巧",
+    "B": "插件替换模板的操作技巧",
+    "C": "插件 替换成 模板 教程"
+  },
+  "630": {
+    "idx": 630,
+    "A": "上传 参考图 教程",
+    "B": "如何上传参考图的教程",
+    "C": "怎么导入 参考 怎么做"
+  },
+  "631": {
+    "idx": 631,
+    "A": "AI 上传 参考图 教程",
+    "B": "智能上传参考图的教程",
+    "C": "AI 怎么导入 垫图 怎么做"
+  },
+  "632": {
+    "idx": 632,
+    "A": "软件 上传 参考图 教程",
+    "B": "软件上传参考图的操作教程",
+    "C": "电脑端 用自己的 垫图 步骤"
+  },
+  "633": {
+    "idx": 633,
+    "A": "在线 上传 参考图 教程",
+    "B": "在线上传参考图的教程",
+    "C": "网页版 怎么导入 垫图 步骤"
+  },
+  "635": {
+    "idx": 635,
+    "A": "插件 上传 参考图 教程",
+    "B": "插件上传参考图的教程",
+    "C": "插件 上传 参考 步骤"
+  },
+  "637": {
+    "idx": 637,
+    "A": "AI 上传 参考图 工具",
+    "B": "智能上传参考图的工具",
+    "C": "AI 导入 参考 流程"
+  },
+  "638": {
+    "idx": 638,
+    "A": "软件 上传 参考图 工具",
+    "B": "上传参考图的软件工具",
+    "C": "电脑端 怎么导入 垫图 教程"
+  },
+  "639": {
+    "idx": 639,
+    "A": "在线 上传 参考图 工具",
+    "B": "在线上传参考图的工具",
+    "C": "在线 怎么导入 参考 步骤"
+  },
+  "640": {
+    "idx": 640,
+    "A": "代码 上传 参考图 工具",
+    "B": "通过代码上传参考图的工具",
+    "C": "代码 怎么导入 参考图 教学"
+  },
+  "641": {
+    "idx": 641,
+    "A": "插件 上传 参考图 工具",
+    "B": "上传参考图的插件工具",
+    "C": "插件 怎么导入 参考图 教程"
+  },
+  "642": {
+    "idx": 642,
+    "A": "上传 参考图 技巧",
+    "B": "上传参考图的实用技巧",
+    "C": "怎么导入 参考 教学"
+  },
+  "643": {
+    "idx": 643,
+    "A": "AI 上传 参考图 技巧",
+    "B": "智能上传参考图的技巧",
+    "C": "AI 上传 参考图 方法"
+  },
+  "644": {
+    "idx": 644,
+    "A": "软件 上传 参考图 技巧",
+    "B": "软件上传参考图的技巧",
+    "C": "电脑端 用自己的 ref 怎么做"
+  },
+  "645": {
+    "idx": 645,
+    "A": "在线 上传 参考图 技巧",
+    "B": "在线上传参考图的技巧",
+    "C": "网页版 导入 参考图 步骤"
+  },
+  "647": {
+    "idx": 647,
+    "A": "插件 上传 参考图 技巧",
+    "B": "插件上传参考图的技巧",
+    "C": "插件 上传 参考图 怎么做"
+  },
+  "649": {
+    "idx": 649,
+    "A": "AI 识别 参考图 教程",
+    "B": "智能识别参考图的教程",
+    "C": "AI 识别 参考图 流程"
+  },
+  "650": {
+    "idx": 650,
+    "A": "软件 识别 参考图 教程",
+    "B": "软件识别参考图的教程",
+    "C": "软件 转录 垫图 教程"
+  },
+  "651": {
+    "idx": 651,
+    "A": "在线 识别 参考图 教程",
+    "B": "在线识别参考图的教程",
+    "C": "在线 识别 ref 方法"
+  },
+  "652": {
+    "idx": 652,
+    "A": "代码 识别 参考图 教程",
+    "B": "代码识别参考图的教程",
+    "C": "代码 转录 ref 怎么做"
+  },
+  "653": {
+    "idx": 653,
+    "A": "插件 识别 参考图 教程",
+    "B": "插件识别参考图的教程",
+    "C": "插件 OCR ref 步骤"
+  },
+  "655": {
+    "idx": 655,
+    "A": "AI 识别 参考图 工具",
+    "B": "智能识别参考图的工具",
+    "C": "AI 转录 参考图 流程"
+  },
+  "656": {
+    "idx": 656,
+    "A": "软件 识别 参考图 工具",
+    "B": "软件识别参考图的工具",
+    "C": "软件 OCR 参考图 流程"
+  },
+  "657": {
+    "idx": 657,
+    "A": "在线 识别 参考图 工具",
+    "B": "有什么在线识别参考图的工具",
+    "C": "在线 检测 参考图 流程"
+  },
+  "658": {
+    "idx": 658,
+    "A": "代码 识别 参考图 工具",
+    "B": "怎么用代码识别参考图",
+    "C": "代码 提取文字 ref 教学"
+  },
+  "659": {
+    "idx": 659,
+    "A": "插件 识别 参考图 工具",
+    "B": "有哪些识别参考图的插件",
+    "C": "插件 OCR 参考图 流程"
+  },
+  "661": {
+    "idx": 661,
+    "A": "AI 识别 参考图 技巧",
+    "B": "利用人工智能识别参考图有什么技巧",
+    "C": "AI OCR ref 教程"
+  },
+  "662": {
+    "idx": 662,
+    "A": "软件 识别 参考图 技巧",
+    "B": "用软件识别参考图的技巧有哪些",
+    "C": "软件 OCR 参考 怎么做"
+  },
+  "663": {
+    "idx": 663,
+    "A": "在线 识别 参考图 技巧",
+    "B": "在线识别参考图有什么好用的技巧",
+    "C": "在线 转录 参考 教学"
+  },
+  "664": {
+    "idx": 664,
+    "A": "代码 识别 参考图 技巧",
+    "B": "通过代码识别参考图的技巧",
+    "C": "代码 OCR 参考 教程"
+  },
+  "665": {
+    "idx": 665,
+    "A": "插件 识别 参考图 技巧",
+    "B": "使用插件识别参考图的技巧",
+    "C": "插件 检测 垫图 方法"
+  },
+  "666": {
+    "idx": 666,
+    "A": "反推 参考图 教程",
+    "B": "如何反推参考图的教程",
+    "C": "推断 ref 教程"
+  },
+  "667": {
+    "idx": 667,
+    "A": "AI 反推 参考图 教程",
+    "B": "人工智能反推参考图的详细教程",
+    "C": "AI 推断 ref 步骤"
+  },
+  "668": {
+    "idx": 668,
+    "A": "软件 反推 参考图 教程",
+    "B": "用软件反推参考图的教程",
+    "C": "电脑端 怎么反推 参考图 方法"
+  },
+  "669": {
+    "idx": 669,
+    "A": "在线 反推 参考图 教程",
+    "B": "在线反推参考图的方法教程",
+    "C": "在线 怎么反推 垫图 方法"
+  },
+  "670": {
+    "idx": 670,
+    "A": "代码 反推 参考图 教程",
+    "B": "怎么用代码实现反推参考图",
+    "C": "命令行 反推 参考图 流程"
+  },
+  "671": {
+    "idx": 671,
+    "A": "插件 反推 参考图 教程",
+    "B": "有哪些反推参考图的插件教程",
+    "C": "插件 推断 参考图 流程"
+  },
+  "673": {
+    "idx": 673,
+    "A": "AI 反推 参考图 工具",
+    "B": "有什么反推参考图的人工智能工具",
+    "C": "AI 怎么反推 垫图 流程"
+  },
+  "674": {
+    "idx": 674,
+    "A": "软件 反推 参考图 工具",
+    "B": "好用的反推参考图软件有哪些",
+    "C": "电脑端 怎么反推 参考图 怎么做"
+  },
+  "675": {
+    "idx": 675,
+    "A": "在线 反推 参考图 工具",
+    "B": "在线反推参考图的工具推荐",
+    "C": "网页版 怎么反推 垫图 步骤"
+  },
+  "676": {
+    "idx": 676,
+    "A": "代码 反推 参考图 工具",
+    "B": "有哪些能反推参考图的代码工具",
+    "C": "代码 分析 垫图 怎么做"
+  },
+  "677": {
+    "idx": 677,
+    "A": "插件 反推 参考图 工具",
+    "B": "反推参考图的插件工具有哪些",
+    "C": "插件 推断 ref 方法"
+  },
+  "679": {
+    "idx": 679,
+    "A": "AI 反推 参考图 技巧",
+    "B": "人工智能反推参考图的技巧",
+    "C": "AI 怎么反推 参考图 步骤"
+  },
+  "680": {
+    "idx": 680,
+    "A": "软件 反推 参考图 技巧",
+    "B": "软件反推参考图的实用技巧",
+    "C": "电脑端 推断 参考图 怎么做"
+  },
+  "681": {
+    "idx": 681,
+    "A": "在线 反推 参考图 技巧",
+    "B": "在线反推参考图的技巧分享",
+    "C": "在线 怎么反推 ref 教程"
+  },
+  "682": {
+    "idx": 682,
+    "A": "代码 反推 参考图 技巧",
+    "B": "用代码反推参考图的技巧",
+    "C": "代码 推断 ref 教学"
+  },
+  "683": {
+    "idx": 683,
+    "A": "插件 反推 参考图 技巧",
+    "B": "使用插件反推参考图的技巧",
+    "C": "插件 反推 参考 步骤"
+  },
+  "685": {
+    "idx": 685,
+    "A": "AI 风格化 参考图 教程",
+    "B": "人工智能风格化参考图的教程",
+    "C": "AI 风格迁移 ref 教学"
+  },
+  "686": {
+    "idx": 686,
+    "A": "软件 风格化 参考图 教程",
+    "B": "软件风格化参考图的教程",
+    "C": "电脑端 风格化 参考图 教学"
+  },
+  "687": {
+    "idx": 687,
+    "A": "在线 风格化 参考图 教程",
+    "B": "在线风格化参考图的教程",
+    "C": "在线 转风格 垫图 方法"
+  },
+  "688": {
+    "idx": 688,
+    "A": "代码 风格化 参考图 教程",
+    "B": "用代码实现风格化参考图的教程",
+    "C": "代码 怎么转风格 参考图 流程"
+  },
+  "689": {
+    "idx": 689,
+    "A": "插件 风格化 参考图 教程",
+    "B": "风格化参考图的插件使用教程",
+    "C": "插件 怎么转风格 参考图 教学"
+  },
+  "691": {
+    "idx": 691,
+    "A": "AI 风格化 参考图 工具",
+    "B": "人工智能风格化参考图的工具",
+    "C": "AI 怎么转风格 垫图 方法"
+  },
+  "692": {
+    "idx": 692,
+    "A": "软件 风格化 参考图 工具",
+    "B": "有什么风格化参考图的软件",
+    "C": "电脑端 怎么转风格 ref 怎么做"
+  },
+  "693": {
+    "idx": 693,
+    "A": "在线 风格化 参考图 工具",
+    "B": "在线风格化参考图的工具",
+    "C": "在线 怎么转风格 参考 怎么做"
+  },
+  "694": {
+    "idx": 694,
+    "A": "代码 风格化 参考图 工具",
+    "B": "风格化参考图的代码工具",
+    "C": "代码 转风格 参考图 步骤"
+  },
+  "695": {
+    "idx": 695,
+    "A": "插件 风格化 参考图 工具",
+    "B": "有哪些风格化参考图的插件",
+    "C": "插件 风格迁移 垫图 教程"
+  },
+  "697": {
+    "idx": 697,
+    "A": "AI 风格化 参考图 技巧",
+    "B": "人工智能风格化参考图的技巧",
+    "C": "AI 风格迁移 ref 流程"
+  },
+  "698": {
+    "idx": 698,
+    "A": "软件 风格化 参考图 技巧",
+    "B": "软件风格化参考图的技巧",
+    "C": "电脑端 怎么转风格 垫图 步骤"
+  },
+  "699": {
+    "idx": 699,
+    "A": "在线 风格化 参考图 技巧",
+    "B": "在线风格化参考图的技巧",
+    "C": "网页版 怎么转风格 垫图 流程"
+  },
+  "700": {
+    "idx": 700,
+    "A": "代码 风格化 参考图 技巧",
+    "B": "用代码风格化参考图的技巧",
+    "C": "代码 怎么转风格 参考 怎么做"
+  },
+  "701": {
+    "idx": 701,
+    "A": "插件 风格化 参考图 技巧",
+    "B": "使用插件风格化参考图的技巧",
+    "C": "插件 风格迁移 ref 教学"
+  },
+  "702": {
+    "idx": 702,
+    "A": "调整 参考图 教程",
+    "B": "如何调整参考图的教程",
+    "C": "优化 ref 教学"
+  },
+  "703": {
+    "idx": 703,
+    "A": "AI 调整 参考图 教程",
+    "B": "怎么用智能技术调整参考图",
+    "C": "AI 优化 参考图 流程"
+  },
+  "704": {
+    "idx": 704,
+    "A": "软件 调整 参考图 教程",
+    "B": "有哪些调整参考图的软件教程",
+    "C": "电脑端 调整 ref 教程"
+  },
+  "705": {
+    "idx": 705,
+    "A": "在线 调整 参考图 教程",
+    "B": "在线调整参考图的方法有哪些",
+    "C": "网页版 调整 参考 怎么做"
+  },
+  "706": {
+    "idx": 706,
+    "A": "代码 调整 参考图 教程",
+    "B": "如何通过编程代码来调整参考图",
+    "C": "代码 调整 ref 步骤"
+  },
+  "709": {
+    "idx": 709,
+    "A": "AI 调整 参考图 工具",
+    "B": "好用的智能参考图调整工具推荐",
+    "C": "AI 优化 参考图 步骤"
+  },
+  "710": {
+    "idx": 710,
+    "A": "软件 调整 参考图 工具",
+    "B": "调整参考图的软件工具有哪些",
+    "C": "电脑端 怎么调 ref 方法"
+  },
+  "711": {
+    "idx": 711,
+    "A": "在线 调整 参考图 工具",
+    "B": "在线调整参考图的工具怎么找",
+    "C": "在线 调整 参考 教学"
+  },
+  "712": {
+    "idx": 712,
+    "A": "代码 调整 参考图 工具",
+    "B": "有没有调整参考图的代码工具",
+    "C": "命令行 调 参考图 怎么做"
+  },
+  "713": {
+    "idx": 713,
+    "A": "插件 调整 参考图 工具",
+    "B": "调整参考图的插件工具有哪些",
+    "C": "插件 调整 ref 流程"
+  },
+  "714": {
+    "idx": 714,
+    "A": "调整 参考图 技巧",
+    "B": "调整参考图有什么实用技巧",
+    "C": "怎么调 参考图 教程"
+  },
+  "715": {
+    "idx": 715,
+    "A": "AI 调整 参考图 技巧",
+    "B": "智能调整参考图的技巧分享",
+    "C": "AI 调整 垫图 步骤"
+  },
+  "716": {
+    "idx": 716,
+    "A": "软件 调整 参考图 技巧",
+    "B": "软件调整参考图的操作技巧",
+    "C": "电脑端 优化 参考 流程"
+  },
+  "717": {
+    "idx": 717,
+    "A": "在线 调整 参考图 技巧",
+    "B": "在线调整参考图的实用技巧",
+    "C": "网页版 调 参考 流程"
+  },
+  "718": {
+    "idx": 718,
+    "A": "代码 调整 参考图 技巧",
+    "B": "代码调整参考图的技巧有哪些",
+    "C": "代码 优化 参考 怎么做"
+  },
+  "721": {
+    "idx": 721,
+    "A": "AI 上传 参考视频 教程",
+    "B": "如何用智能技术上传参考视频",
+    "C": "AI 导入 参考片 教学"
+  },
+  "722": {
+    "idx": 722,
+    "A": "软件 上传 参考视频 教程",
+    "B": "软件上传参考视频的详细教程",
+    "C": "电脑端 用自己的 参考片 教学"
+  },
+  "723": {
+    "idx": 723,
+    "A": "在线 上传 参考视频 教程",
+    "B": "在线上传参考视频的操作教程",
+    "C": "在线 用自己的 参考片 教学"
+  },
+  "724": {
+    "idx": 724,
+    "A": "代码 上传 参考视频 教程",
+    "B": "怎么用代码实现上传参考视频",
+    "C": "代码 上传 参考片 步骤"
+  },
+  "725": {
+    "idx": 725,
+    "A": "插件 上传 参考视频 教程",
+    "B": "上传参考视频的插件使用教程",
+    "C": "插件 用自己的 参考素材 步骤"
+  },
+  "727": {
+    "idx": 727,
+    "A": "AI 上传 参考视频 工具",
+    "B": "智能上传参考视频的工具推荐",
+    "C": "AI 怎么导入 参考视频 怎么做"
+  },
+  "728": {
+    "idx": 728,
+    "A": "软件 上传 参考视频 工具",
+    "B": "好用的参考视频上传软件",
+    "C": "电脑端 上传 参考视频 怎么做"
+  },
+  "729": {
+    "idx": 729,
+    "A": "在线 上传 参考视频 工具",
+    "B": "在线上传参考视频的工具",
+    "C": "网页版 怎么导入 参考素材 步骤"
+  },
+  "730": {
+    "idx": 730,
+    "A": "代码 上传 参考视频 工具",
+    "B": "有没有上传参考视频的代码工具",
+    "C": "代码 用自己的 参考片 教程"
+  },
+  "731": {
+    "idx": 731,
+    "A": "插件 上传 参考视频 工具",
+    "B": "上传参考视频的插件工具有哪些",
+    "C": "插件 用自己的 参考片 流程"
+  },
+  "732": {
+    "idx": 732,
+    "A": "上传 参考视频 技巧",
+    "B": "上传参考视频有什么技巧",
+    "C": "怎么导入 参考视频 教学"
+  },
+  "733": {
+    "idx": 733,
+    "A": "AI 上传 参考视频 技巧",
+    "B": "智能上传参考视频的技巧",
+    "C": "AI 怎么导入 参考素材 教学"
+  },
+  "734": {
+    "idx": 734,
+    "A": "软件 上传 参考视频 技巧",
+    "B": "软件上传参考视频的操作技巧",
+    "C": "软件 上传 参考素材 教学"
+  },
+  "735": {
+    "idx": 735,
+    "A": "在线 上传 参考视频 技巧",
+    "B": "在线上传参考视频的技巧分享",
+    "C": "在线 怎么导入 参考片 教程"
+  },
+  "736": {
+    "idx": 736,
+    "A": "代码 上传 参考视频 技巧",
+    "B": "代码上传参考视频的技巧",
+    "C": "命令行 导入 参考视频 步骤"
+  },
+  "737": {
+    "idx": 737,
+    "A": "插件 上传 参考视频 技巧",
+    "B": "插件上传参考视频的技巧",
+    "C": "插件 用自己的 参考视频 流程"
+  },
+  "739": {
+    "idx": 739,
+    "A": "AI 抽帧 参考视频 教程",
+    "B": "怎么用智能技术从视频中抽帧",
+    "C": "AI 怎么抽帧 参考素材 方法"
+  },
+  "740": {
+    "idx": 740,
+    "A": "软件 抽帧 参考视频 教程",
+    "B": "软件抽帧参考视频的教程",
+    "C": "电脑端 提取帧 参考片 怎么做"
+  },
+  "741": {
+    "idx": 741,
+    "A": "在线 抽帧 参考视频 教程",
+    "B": "在线抽帧参考视频的方法",
+    "C": "网页版 怎么抽帧 参考视频 怎么做"
+  },
+  "742": {
+    "idx": 742,
+    "A": "代码 抽帧 参考视频 教程",
+    "B": "如何用代码从视频中抽帧",
+    "C": "代码 提取帧 参考视频 教学"
+  },
+  "743": {
+    "idx": 743,
+    "A": "插件 抽帧 参考视频 教程",
+    "B": "视频抽帧插件的使用教程",
+    "C": "插件 怎么抽帧 参考视频 怎么做"
+  },
+  "745": {
+    "idx": 745,
+    "A": "AI 抽帧 参考视频 工具",
+    "B": "智能抽帧参考视频的工具",
+    "C": "AI 怎么抽帧 参考素材 教程"
+  },
+  "746": {
+    "idx": 746,
+    "A": "软件 抽帧 参考视频 工具",
+    "B": "好用的视频抽帧软件推荐",
+    "C": "电脑端 怎么抽帧 参考素材 教学"
+  },
+  "747": {
+    "idx": 747,
+    "A": "在线 抽帧 参考视频 工具",
+    "B": "在线抽帧参考视频的工具",
+    "C": "网页版 导出帧 参考素材 步骤"
+  },
+  "748": {
+    "idx": 748,
+    "A": "代码 抽帧 参考视频 工具",
+    "B": "有没有视频抽帧的代码工具",
+    "C": "代码 提取帧 参考片 教程"
+  },
+  "749": {
+    "idx": 749,
+    "A": "插件 抽帧 参考视频 工具",
+    "B": "视频抽帧的插件工具有哪些",
+    "C": "插件 提取帧 参考素材 教程"
+  },
+  "750": {
+    "idx": 750,
+    "A": "抽帧 参考视频 技巧",
+    "B": "如何给参考视频进行抽帧处理",
+    "C": "导出帧 参考素材 步骤"
+  },
+  "751": {
+    "idx": 751,
+    "A": "AI 抽帧 参考视频 技巧",
+    "B": "怎么用智能工具给参考视频抽帧",
+    "C": "AI 抽帧 参考视频 教程"
+  },
+  "752": {
+    "idx": 752,
+    "A": "软件 抽帧 参考视频 技巧",
+    "B": "有哪些软件可以实现参考视频抽帧",
+    "C": "软件 怎么抽帧 参考片 教程"
+  },
+  "753": {
+    "idx": 753,
+    "A": "在线 抽帧 参考视频 技巧",
+    "B": "有没有在线抽帧参考视频的方法",
+    "C": "在线 提取帧 参考素材 流程"
+  },
+  "754": {
+    "idx": 754,
+    "A": "代码 抽帧 参考视频 技巧",
+    "B": "如何通过代码实现参考视频抽帧",
+    "C": "命令行 导出帧 参考片 教学"
+  },
+  "755": {
+    "idx": 755,
+    "A": "插件 抽帧 参考视频 技巧",
+    "B": "有什么插件能帮参考视频抽帧",
+    "C": "插件 提取帧 参考片 教学"
+  },
+  "757": {
+    "idx": 757,
+    "A": "AI 反推 参考视频 教程",
+    "B": "如何利用智能技术反推参考视频内容",
+    "C": "AI 怎么反推 参考素材 怎么做"
+  },
+  "758": {
+    "idx": 758,
+    "A": "软件 反推 参考视频 教程",
+    "B": "有哪些软件可以用来反推参考视频",
+    "C": "电脑端 反推 参考素材 步骤"
+  },
+  "759": {
+    "idx": 759,
+    "A": "在线 反推 参考视频 教程",
+    "B": "怎么在线反推参考视频的制作方法",
+    "C": "在线 怎么反推 参考片 流程"
+  },
+  "760": {
+    "idx": 760,
+    "A": "代码 反推 参考视频 教程",
+    "B": "如何用代码实现参考视频的反推",
+    "C": "命令行 反推 参考素材 步骤"
+  },
+  "761": {
+    "idx": 761,
+    "A": "插件 反推 参考视频 教程",
+    "B": "有哪些插件支持反推参考视频",
+    "C": "插件 反推 参考片 步骤"
+  },
+  "763": {
+    "idx": 763,
+    "A": "AI 反推 参考视频 工具",
+    "B": "有什么智能工具可以反推参考视频",
+    "C": "AI 反推 参考片 教程"
+  },
+  "764": {
+    "idx": 764,
+    "A": "软件 反推 参考视频 工具",
+    "B": "有哪些软件工具能做参考视频反推",
+    "C": "软件 反推 参考视频 步骤"
+  },
+  "765": {
+    "idx": 765,
+    "A": "在线 反推 参考视频 工具",
+    "B": "有没有在线工具可以反推参考视频",
+    "C": "在线 分析 参考素材 流程"
+  },
+  "766": {
+    "idx": 766,
+    "A": "代码 反推 参考视频 工具",
+    "B": "有哪些代码工具适合反推参考视频",
+    "C": "代码 分析 参考素材 流程"
+  },
+  "767": {
+    "idx": 767,
+    "A": "插件 反推 参考视频 工具",
+    "B": "有什么插件工具可以反推参考视频",
+    "C": "插件 推断 参考视频 方法"
+  },
+  "768": {
+    "idx": 768,
+    "A": "反推 参考视频 技巧",
+    "B": "反推参考视频有什么技巧",
+    "C": "反推 参考片 流程"
+  },
+  "769": {
+    "idx": 769,
+    "A": "AI 反推 参考视频 技巧",
+    "B": "如何用智能技术提升反推参考视频的技巧",
+    "C": "AI 推断 参考视频 教程"
+  },
+  "770": {
+    "idx": 770,
+    "A": "软件 反推 参考视频 技巧",
+    "B": "使用软件反推参考视频有什么技巧",
+    "C": "软件 分析 参考视频 步骤"
+  },
+  "771": {
+    "idx": 771,
+    "A": "在线 反推 参考视频 技巧",
+    "B": "在线反推参考视频有什么好用的技巧",
+    "C": "在线 推断 参考视频 流程"
+  },
+  "772": {
+    "idx": 772,
+    "A": "代码 反推 参考视频 技巧",
+    "B": "通过代码反推参考视频有哪些技巧",
+    "C": "命令行 反推 参考视频 教学"
+  },
+  "773": {
+    "idx": 773,
+    "A": "插件 反推 参考视频 技巧",
+    "B": "使用插件反推参考视频的技巧有哪些",
+    "C": "插件 反推 参考素材 教程"
+  },
+  "774": {
+    "idx": 774,
+    "A": "风格化 参考视频 教程",
+    "B": "如何给参考视频做风格化处理",
+    "C": "怎么转风格 参考片 步骤"
+  },
+  "776": {
+    "idx": 776,
+    "A": "软件 风格化 参考视频 教程",
+    "B": "有哪些软件可以给参考视频做风格化",
+    "C": "软件 怎么转风格 参考素材 流程"
+  },
+  "777": {
+    "idx": 777,
+    "A": "在线 风格化 参考视频 教程",
+    "B": "怎么在线给参考视频做风格化处理",
+    "C": "在线 风格迁移 参考片 教学"
+  },
+  "778": {
+    "idx": 778,
+    "A": "代码 风格化 参考视频 教程",
+    "B": "如何用代码实现参考视频的风格化",
+    "C": "代码 风格化 参考片 怎么做"
+  },
+  "779": {
+    "idx": 779,
+    "A": "插件 风格化 参考视频 教程",
+    "B": "有哪些插件可以给参考视频做风格化",
+    "C": "插件 风格化 参考片 教学"
+  },
+  "781": {
+    "idx": 781,
+    "A": "AI 风格化 参考视频 工具",
+    "B": "有什么智能工具可以给参考视频做风格化",
+    "C": "AI 风格化 参考视频 步骤"
+  },
+  "782": {
+    "idx": 782,
+    "A": "软件 风格化 参考视频 工具",
+    "B": "有哪些软件工具可以实现参考视频风格化",
+    "C": "软件 风格化 参考视频 步骤"
+  },
+  "783": {
+    "idx": 783,
+    "A": "在线 风格化 参考视频 工具",
+    "B": "有没有在线工具能给参考视频做风格化",
+    "C": "网页版 怎么转风格 参考素材 方法"
+  },
+  "784": {
+    "idx": 784,
+    "A": "代码 风格化 参考视频 工具",
+    "B": "有哪些代码工具可以做参考视频风格化",
+    "C": "命令行 怎么转风格 参考素材 方法"
+  },
+  "785": {
+    "idx": 785,
+    "A": "插件 风格化 参考视频 工具",
+    "B": "有什么插件工具能实现参考视频风格化",
+    "C": "插件 风格化 参考素材 教程"
+  },
+  "786": {
+    "idx": 786,
+    "A": "风格化 参考视频 技巧",
+    "B": "参考视频风格化有哪些技巧",
+    "C": "转风格 参考片 怎么做"
+  },
+  "788": {
+    "idx": 788,
+    "A": "软件 风格化 参考视频 技巧",
+    "B": "用软件做参考视频风格化有什么技巧",
+    "C": "软件 怎么转风格 参考片 怎么做"
+  },
+  "789": {
+    "idx": 789,
+    "A": "在线 风格化 参考视频 技巧",
+    "B": "在线做参考视频风格化有什么技巧",
+    "C": "网页版 怎么转风格 参考素材 教程"
+  },
+  "790": {
+    "idx": 790,
+    "A": "代码 风格化 参考视频 技巧",
+    "B": "通过代码做参考视频风格化有什么技巧",
+    "C": "命令行 怎么转风格 参考片 教学"
+  },
+  "791": {
+    "idx": 791,
+    "A": "插件 风格化 参考视频 技巧",
+    "B": "使用插件做参考视频风格化有什么技巧",
+    "C": "插件 风格迁移 参考视频 教学"
+  },
+  "793": {
+    "idx": 793,
+    "A": "AI 反推 参考音频 教程",
+    "B": "如何利用智能技术反推参考音频",
+    "C": "AI 反推 参考音频 教程"
+  },
+  "794": {
+    "idx": 794,
+    "A": "软件 反推 参考音频 教程",
+    "B": "有哪些软件可以用来反推参考音频",
+    "C": "软件 怎么反推 参考音频 教学"
+  },
+  "795": {
+    "idx": 795,
+    "A": "在线 反推 参考音频 教程",
+    "B": "怎么在线反推参考音频内容",
+    "C": "网页版 分析 音色样本 教程"
+  },
+  "796": {
+    "idx": 796,
+    "A": "代码 反推 参考音频 教程",
+    "B": "怎么用代码反推参考音频的教程",
+    "C": "命令行 反推 参考音色 步骤"
+  },
+  "797": {
+    "idx": 797,
+    "A": "插件 反推 参考音频 教程",
+    "B": "有哪些插件可以反推参考音频的教程",
+    "C": "插件 反推 参考音色 方法"
+  },
+  "799": {
+    "idx": 799,
+    "A": "AI 反推 参考音频 工具",
+    "B": "好用的音频反推工具推荐",
+    "C": "AI 推断 参考音频 方法"
+  },
+  "800": {
+    "idx": 800,
+    "A": "软件 反推 参考音频 工具",
+    "B": "有没有什么软件能反推参考音频",
+    "C": "软件 分析 音色样本 怎么做"
+  },
+  "801": {
+    "idx": 801,
+    "A": "在线 反推 参考音频 工具",
+    "B": "在线反推参考音频的工具怎么用",
+    "C": "在线 反推 参考音色 方法"
+  },
+  "802": {
+    "idx": 802,
+    "A": "代码 反推 参考音频 工具",
+    "B": "通过代码反推参考音频的工具",
+    "C": "命令行 反推 参考音色 方法"
+  },
+  "803": {
+    "idx": 803,
+    "A": "插件 反推 参考音频 工具",
+    "B": "能反推参考音频的插件有哪些",
+    "C": "插件 怎么反推 音色样本 方法"
+  },
+  "804": {
+    "idx": 804,
+    "A": "反推 参考音频 技巧",
+    "B": "反推参考音频有什么技巧",
+    "C": "反推 音色样本 教学"
+  },
+  "805": {
+    "idx": 805,
+    "A": "AI 反推 参考音频 技巧",
+    "B": "用人工智能反推参考音频的技巧",
+    "C": "AI 反推 参考音频 步骤"
+  },
+  "806": {
+    "idx": 806,
+    "A": "软件 反推 参考音频 技巧",
+    "B": "利用软件反推参考音频的技巧",
+    "C": "电脑端 推断 参考音色 教程"
+  },
+  "807": {
+    "idx": 807,
+    "A": "在线 反推 参考音频 技巧",
+    "B": "在线反推参考音频的操作技巧",
+    "C": "在线 分析 音色样本 教学"
+  },
+  "808": {
+    "idx": 808,
+    "A": "代码 反推 参考音频 技巧",
+    "B": "通过代码反推参考音频的技巧",
+    "C": "命令行 反推 参考音频 教学"
+  },
+  "809": {
+    "idx": 809,
+    "A": "插件 反推 参考音频 技巧",
+    "B": "使用插件反推参考音频的技巧",
+    "C": "插件 反推 音色样本 方法"
+  },
+  "810": {
+    "idx": 810,
+    "A": "风格化 参考音频 教程",
+    "B": "音频风格化处理的教程",
+    "C": "转风格 参考音色 怎么做"
+  },
+  "811": {
+    "idx": 811,
+    "A": "AI 风格化 参考音频 教程",
+    "B": "怎么用人工智能给音频做风格化处理",
+    "C": "AI 风格迁移 参考音频 步骤"
+  },
+  "812": {
+    "idx": 812,
+    "A": "软件 风格化 参考音频 教程",
+    "B": "有哪些软件可以实现音频风格化",
+    "C": "电脑端 风格迁移 音色样本 方法"
+  },
+  "813": {
+    "idx": 813,
+    "A": "在线 风格化 参考音频 教程",
+    "B": "在线进行音频风格化处理的教程",
+    "C": "在线 风格化 参考音频 流程"
+  },
+  "814": {
+    "idx": 814,
+    "A": "代码 风格化 参考音频 教程",
+    "B": "通过代码实现音频风格化的方法",
+    "C": "代码 风格化 参考音色 怎么做"
+  },
+  "815": {
+    "idx": 815,
+    "A": "插件 风格化 参考音频 教程",
+    "B": "音频风格化插件的使用教程",
+    "C": "插件 怎么转风格 音色样本 怎么做"
+  },
+  "817": {
+    "idx": 817,
+    "A": "AI 风格化 参考音频 工具",
+    "B": "好用的音频风格化工具",
+    "C": "AI 风格迁移 参考音频 方法"
+  },
+  "818": {
+    "idx": 818,
+    "A": "软件 风格化 参考音频 工具",
+    "B": "有没有什么软件能做音频风格化",
+    "C": "软件 风格迁移 参考音色 教程"
+  },
+  "819": {
+    "idx": 819,
+    "A": "在线 风格化 参考音频 工具",
+    "B": "在线音频风格化工具推荐",
+    "C": "网页版 怎么转风格 音色样本 教学"
+  },
+  "820": {
+    "idx": 820,
+    "A": "代码 风格化 参考音频 工具",
+    "B": "通过代码实现音频风格化的工具",
+    "C": "命令行 风格化 参考音频 怎么做"
+  },
+  "821": {
+    "idx": 821,
+    "A": "插件 风格化 参考音频 工具",
+    "B": "音频风格化插件有哪些",
+    "C": "插件 风格化 参考音频 步骤"
+  },
+  "822": {
+    "idx": 822,
+    "A": "风格化 参考音频 技巧",
+    "B": "音频风格化处理的实用技巧",
+    "C": "转风格 参考音频 步骤"
+  },
+  "823": {
+    "idx": 823,
+    "A": "AI 风格化 参考音频 技巧",
+    "B": "用人工智能进行音频风格化的技巧",
+    "C": "AI 风格迁移 参考音频 教程"
+  },
+  "824": {
+    "idx": 824,
+    "A": "软件 风格化 参考音频 技巧",
+    "B": "利用软件进行音频风格化的技巧",
+    "C": "电脑端 怎么转风格 参考音频 流程"
+  },
+  "825": {
+    "idx": 825,
+    "A": "在线 风格化 参考音频 技巧",
+    "B": "在线进行音频风格化处理的技巧",
+    "C": "网页版 转风格 音色样本 方法"
+  },
+  "826": {
+    "idx": 826,
+    "A": "代码 风格化 参考音频 技巧",
+    "B": "通过代码调整音频风格的技巧",
+    "C": "命令行 风格化 参考音色 教学"
+  },
+  "827": {
+    "idx": 827,
+    "A": "插件 风格化 参考音频 技巧",
+    "B": "使用音频风格化插件的技巧",
+    "C": "插件 怎么转风格 参考音频 怎么做"
+  },
+  "829": {
+    "idx": 829,
+    "A": "AI 检索 对标内容 教程",
+    "B": "怎么用人工智能检索对标内容",
+    "C": "AI 哪里找 标杆案例 方法"
+  },
+  "830": {
+    "idx": 830,
+    "A": "软件 检索 对标内容 教程",
+    "B": "利用软件检索对标内容的教程",
+    "C": "电脑端 在哪找 竞品 教程"
+  },
+  "831": {
+    "idx": 831,
+    "A": "在线 检索 对标内容 教程",
+    "B": "在线检索对标内容的教程",
+    "C": "网页版 找 竞品 流程"
+  },
+  "832": {
+    "idx": 832,
+    "A": "代码 检索 对标内容 教程",
+    "B": "通过代码检索对标内容的方法",
+    "C": "命令行 哪里找 对标 怎么做"
+  },
+  "833": {
+    "idx": 833,
+    "A": "插件 检索 对标内容 教程",
+    "B": "使用插件检索对标内容的教程",
+    "C": "插件 搜 标杆案例 方法"
+  },
+  "835": {
+    "idx": 835,
+    "A": "AI 检索 对标内容 工具",
+    "B": "好用的对标内容检索工具",
+    "C": "AI 搜索 对标 怎么做"
+  },
+  "836": {
+    "idx": 836,
+    "A": "软件 检索 对标内容 工具",
+    "B": "有没有什么软件可以检索对标内容",
+    "C": "电脑端 哪里找 爆款参考 步骤"
+  },
+  "837": {
+    "idx": 837,
+    "A": "在线 检索 对标内容 工具",
+    "B": "在线检索对标内容的工具推荐",
+    "C": "在线 找 对标 方法"
+  },
+  "838": {
+    "idx": 838,
+    "A": "代码 检索 对标内容 工具",
+    "B": "通过代码检索对标内容的工具",
+    "C": "代码 哪里找 竞品 教学"
+  },
+  "839": {
+    "idx": 839,
+    "A": "插件 检索 对标内容 工具",
+    "B": "好用的对标内容检索插件",
+    "C": "插件 搜 对标 流程"
+  },
+  "840": {
+    "idx": 840,
+    "A": "检索 对标内容 技巧",
+    "B": "如何高效检索对标内容",
+    "C": "哪里找 爆款参考 流程"
+  },
+  "841": {
+    "idx": 841,
+    "A": "AI 检索 对标内容 技巧",
+    "B": "怎么利用智能技术检索对标内容",
+    "C": "AI 找 爆款参考 教学"
+  },
+  "842": {
+    "idx": 842,
+    "A": "软件 检索 对标内容 技巧",
+    "B": "有什么软件可以检索对标内容",
+    "C": "电脑端 在哪找 标杆案例 教学"
+  },
+  "843": {
+    "idx": 843,
+    "A": "在线 检索 对标内容 技巧",
+    "B": "在线检索对标内容的方法有哪些",
+    "C": "网页版 哪里找 爆款参考 怎么做"
+  },
+  "844": {
+    "idx": 844,
+    "A": "代码 检索 对标内容 技巧",
+    "B": "如何通过代码检索对标内容",
+    "C": "代码 在哪找 标杆案例 教学"
+  },
+  "845": {
+    "idx": 845,
+    "A": "插件 检索 对标内容 技巧",
+    "B": "有没有检索对标内容的插件推荐",
+    "C": "插件 哪里找 对标 步骤"
+  },
+  "846": {
+    "idx": 846,
+    "A": "反推 对标内容 教程",
+    "B": "反推对标内容的详细教程",
+    "C": "反推 竞品 怎么做"
+  },
+  "847": {
+    "idx": 847,
+    "A": "AI 反推 对标内容 教程",
+    "B": "如何用智能技术反推对标内容",
+    "C": "AI 反推 对标 步骤"
+  },
+  "849": {
+    "idx": 849,
+    "A": "在线 反推 对标内容 教程",
+    "B": "在线反推对标内容的步骤是什么",
+    "C": "网页版 反推 对标 方法"
+  },
+  "850": {
+    "idx": 850,
+    "A": "代码 反推 对标内容 教程",
+    "B": "怎么通过代码反推对标内容",
+    "C": "命令行 怎么反推 对标 怎么做"
+  },
+  "851": {
+    "idx": 851,
+    "A": "插件 反推 对标内容 教程",
+    "B": "有没有反推对标内容的插件",
+    "C": "插件 推断 标杆案例 方法"
+  },
+  "853": {
+    "idx": 853,
+    "A": "AI 反推 对标内容 工具",
+    "B": "好用的智能反推对标内容工具",
+    "C": "AI 反推 标杆案例 教程"
+  },
+  "854": {
+    "idx": 854,
+    "A": "软件 反推 对标内容 工具",
+    "B": "有哪些反推对标内容的软件",
+    "C": "电脑端 反推 爆款参考 教程"
+  },
+  "855": {
+    "idx": 855,
+    "A": "在线 反推 对标内容 工具",
+    "B": "在线反推对标内容的工具推荐",
+    "C": "在线 怎么反推 标杆案例 方法"
+  },
+  "856": {
+    "idx": 856,
+    "A": "代码 反推 对标内容 工具",
+    "B": "有没有反推对标内容的代码工具",
+    "C": "代码 推断 竞品 步骤"
+  },
+  "857": {
+    "idx": 857,
+    "A": "插件 反推 对标内容 工具",
+    "B": "好用的反推对标内容插件",
+    "C": "插件 怎么反推 竞品 教学"
+  },
+  "858": {
+    "idx": 858,
+    "A": "反推 对标内容 技巧",
+    "B": "反推对标内容有哪些技巧",
+    "C": "反推 竞品 教程"
+  },
+  "859": {
+    "idx": 859,
+    "A": "AI 反推 对标内容 技巧",
+    "B": "利用智能技术反推对标内容的技巧",
+    "C": "AI 反推 标杆案例 步骤"
+  },
+  "861": {
+    "idx": 861,
+    "A": "在线 反推 对标内容 技巧",
+    "B": "在线反推对标内容有什么技巧",
+    "C": "网页版 分析 竞品 教程"
+  },
+  "862": {
+    "idx": 862,
+    "A": "代码 反推 对标内容 技巧",
+    "B": "通过代码反推对标内容的技巧",
+    "C": "代码 推断 竞品 教学"
+  },
+  "863": {
+    "idx": 863,
+    "A": "插件 反推 对标内容 技巧",
+    "B": "反推对标内容的插件使用技巧",
+    "C": "插件 分析 对标 步骤"
+  },
+  "865": {
+    "idx": 865,
+    "A": "AI 解构 对标内容 教程",
+    "B": "如何用智能技术解构对标内容",
+    "C": "AI 分析结构 竞品 流程"
+  },
+  "866": {
+    "idx": 866,
+    "A": "软件 解构 对标内容 教程",
+    "B": "有没有解构对标内容的软件教程",
+    "C": "软件 分析结构 标杆案例 方法"
+  },
+  "867": {
+    "idx": 867,
+    "A": "在线 解构 对标内容 教程",
+    "B": "在线解构对标内容的教程",
+    "C": "网页版 拆解 竞品 步骤"
+  },
+  "868": {
+    "idx": 868,
+    "A": "代码 解构 对标内容 教程",
+    "B": "如何通过代码解构对标内容",
+    "C": "代码 拆解 竞品 怎么做"
+  },
+  "869": {
+    "idx": 869,
+    "A": "插件 解构 对标内容 教程",
+    "B": "解构对标内容的插件教程",
+    "C": "插件 拆解 爆款参考 流程"
+  },
+  "871": {
+    "idx": 871,
+    "A": "AI 解构 对标内容 工具",
+    "B": "好用的智能解构对标内容工具",
+    "C": "AI 解构 对标 方法"
+  },
+  "872": {
+    "idx": 872,
+    "A": "软件 解构 对标内容 工具",
+    "B": "有哪些解构对标内容的软件",
+    "C": "软件 分析结构 竞品 方法"
+  },
+  "873": {
+    "idx": 873,
+    "A": "在线 解构 对标内容 工具",
+    "B": "在线解构对标内容的工具",
+    "C": "在线 分析结构 标杆案例 流程"
+  },
+  "874": {
+    "idx": 874,
+    "A": "代码 解构 对标内容 工具",
+    "B": "有没有解构对标内容的代码工具",
+    "C": "代码 拆解 爆款参考 教学"
+  },
+  "875": {
+    "idx": 875,
+    "A": "插件 解构 对标内容 工具",
+    "B": "好用的解构对标内容插件",
+    "C": "插件 拆解 标杆案例 步骤"
+  },
+  "876": {
+    "idx": 876,
+    "A": "解构 对标内容 技巧",
+    "B": "解构对标内容有哪些技巧",
+    "C": "分析结构 爆款参考 怎么做"
+  },
+  "877": {
+    "idx": 877,
+    "A": "AI 解构 对标内容 技巧",
+    "B": "利用智能技术解构对标内容的技巧",
+    "C": "AI 分析结构 标杆案例 流程"
+  },
+  "878": {
+    "idx": 878,
+    "A": "软件 解构 对标内容 技巧",
+    "B": "解构对标内容的软件使用技巧",
+    "C": "软件 解构 标杆案例 流程"
+  },
+  "879": {
+    "idx": 879,
+    "A": "在线 解构 对标内容 技巧",
+    "B": "在线解构对标内容的技巧",
+    "C": "网页版 分析结构 标杆案例 怎么做"
+  },
+  "880": {
+    "idx": 880,
+    "A": "代码 解构 对标内容 技巧",
+    "B": "通过代码解构对标内容的技巧",
+    "C": "命令行 解构 标杆案例 流程"
+  },
+  "881": {
+    "idx": 881,
+    "A": "插件 解构 对标内容 技巧",
+    "B": "解构对标内容的插件使用技巧",
+    "C": "插件 分析结构 爆款参考 步骤"
+  },
+  "882": {
+    "idx": 882,
+    "A": "元素生成 分镜图 教程",
+    "B": "元素生成分镜图的教程",
+    "C": "生成 storyboard 步骤"
+  },
+  "883": {
+    "idx": 883,
+    "A": "AI 元素生成 分镜图 教程",
+    "B": "如何用智能技术生成分镜图元素",
+    "C": "AI 创作 分镜图 步骤"
+  },
+  "884": {
+    "idx": 884,
+    "A": "软件 元素生成 分镜图 教程",
+    "B": "有什么软件可以生成分镜图元素",
+    "C": "软件 制作 故事板 怎么做"
+  },
+  "885": {
+    "idx": 885,
+    "A": "在线 元素生成 分镜图 教程",
+    "B": "怎么在网上学习制作分镜图里的元素",
+    "C": "在线 做 分镜图 流程"
+  },
+  "886": {
+    "idx": 886,
+    "A": "代码 元素生成 分镜图 教程",
+    "B": "如何通过编程实现分镜图元素生成",
+    "C": "命令行 怎么做 分镜图 怎么做"
+  },
+  "887": {
+    "idx": 887,
+    "A": "插件 元素生成 分镜图 教程",
+    "B": "有哪些插件可以辅助生成分镜图元素",
+    "C": "插件 做 故事板 流程"
+  },
+  "889": {
+    "idx": 889,
+    "A": "AI 元素生成 分镜图 工具",
+    "B": "好用的分镜图元素生成工具推荐",
+    "C": "AI 生成 故事板 流程"
+  },
+  "890": {
+    "idx": 890,
+    "A": "软件 元素生成 分镜图 工具",
+    "B": "制作分镜图元素有什么好用的软件",
+    "C": "软件 怎么做 分镜图 教学"
+  },
+  "891": {
+    "idx": 891,
+    "A": "在线 元素生成 分镜图 工具",
+    "B": "有没有在线生成分镜图元素的工具",
+    "C": "网页版 制作 分镜 教程"
+  },
+  "892": {
+    "idx": 892,
+    "A": "代码 元素生成 分镜图 工具",
+    "B": "有什么代码工具可以生成分镜图元素",
+    "C": "命令行 做 分镜 教学"
+  },
+  "893": {
+    "idx": 893,
+    "A": "插件 元素生成 分镜图 工具",
+    "B": "好用的分镜图元素生成插件有哪些",
+    "C": "插件 做 分镜图 教程"
+  },
+  "894": {
+    "idx": 894,
+    "A": "元素生成 分镜图 技巧",
+    "B": "分镜图元素生成有哪些实用技巧",
+    "C": "生成 故事板 流程"
+  },
+  "895": {
+    "idx": 895,
+    "A": "AI 元素生成 分镜图 技巧",
+    "B": "利用智能技术生成分镜图元素的技巧",
+    "C": "AI 创作 storyboard 教程"
+  },
+  "896": {
+    "idx": 896,
+    "A": "软件 元素生成 分镜图 技巧",
+    "B": "用软件制作分镜图元素的方法和技巧",
+    "C": "电脑端 制作 故事板 教程"
+  },
+  "897": {
+    "idx": 897,
+    "A": "在线 元素生成 分镜图 技巧",
+    "B": "在线生成分镜图元素的操作技巧",
+    "C": "在线 制作 storyboard 教学"
+  },
+  "898": {
+    "idx": 898,
+    "A": "代码 元素生成 分镜图 技巧",
+    "B": "通过代码生成分镜图元素的技巧",
+    "C": "命令行 生成 分镜图 怎么做"
+  },
+  "899": {
+    "idx": 899,
+    "A": "插件 元素生成 分镜图 技巧",
+    "B": "使用插件生成分镜图元素的技巧",
+    "C": "插件 创作 分镜 教学"
+  },
+  "900": {
+    "idx": 900,
+    "A": "添加 转场 教程",
+    "B": "视频添加转场效果的详细教程",
+    "C": "加 转场效果 怎么做"
+  },
+  "901": {
+    "idx": 901,
+    "A": "AI 添加 转场 教程",
+    "B": "怎么用智能工具给视频添加转场",
+    "C": "AI 怎么加 转场 方法"
+  },
+  "902": {
+    "idx": 902,
+    "A": "软件 添加 转场 教程",
+    "B": "用什么软件给视频添加转场效果",
+    "C": "电脑端 加 transition 教学"
+  },
+  "903": {
+    "idx": 903,
+    "A": "在线 添加 转场 教程",
+    "B": "在线给视频添加转场的方法",
+    "C": "在线 怎么加 转场 方法"
+  },
+  "904": {
+    "idx": 904,
+    "A": "代码 添加 转场 教程",
+    "B": "如何用代码给视频添加转场效果",
+    "C": "代码 加上 转场效果 教程"
+  },
+  "905": {
+    "idx": 905,
+    "A": "插件 添加 转场 教程",
+    "B": "有哪些插件可以给视频添加转场",
+    "C": "插件 怎么加 转场效果 教学"
+  },
+  "906": {
+    "idx": 906,
+    "A": "添加 转场 工具",
+    "B": "好用的视频转场添加工具",
+    "C": "添加 转场效果 教程"
+  },
+  "907": {
+    "idx": 907,
+    "A": "AI 添加 转场 工具",
+    "B": "智能添加视频转场的工具推荐",
+    "C": "AI 加 transition 教学"
+  },
+  "908": {
+    "idx": 908,
+    "A": "软件 添加 转场 工具",
+    "B": "适合给视频添加转场的软件有哪些",
+    "C": "软件 怎么加 转场 教程"
+  },
+  "909": {
+    "idx": 909,
+    "A": "在线 添加 转场 工具",
+    "B": "有没有在线添加视频转场的工具",
+    "C": "网页版 怎么加 transition 流程"
+  },
+  "910": {
+    "idx": 910,
+    "A": "代码 添加 转场 工具",
+    "B": "有什么代码工具可以添加视频转场",
+    "C": "命令行 加上 transition 流程"
+  },
+  "911": {
+    "idx": 911,
+    "A": "插件 添加 转场 工具",
+    "B": "好用的视频转场添加插件",
+    "C": "插件 添加 transition 怎么做"
+  },
+  "912": {
+    "idx": 912,
+    "A": "添加 转场 技巧",
+    "B": "视频转场添加的实用技巧",
+    "C": "添加 转场效果 流程"
+  },
+  "913": {
+    "idx": 913,
+    "A": "AI 添加 转场 技巧",
+    "B": "智能处理视频转场的技巧",
+    "C": "AI 加 转场 步骤"
+  },
+  "914": {
+    "idx": 914,
+    "A": "软件 添加 转场 技巧",
+    "B": "使用软件添加视频转场的技巧",
+    "C": "电脑端 加上 transition 怎么做"
+  },
+  "915": {
+    "idx": 915,
+    "A": "在线 添加 转场 技巧",
+    "B": "在线添加视频转场的操作技巧",
+    "C": "网页版 添加 transition 流程"
+  },
+  "916": {
+    "idx": 916,
+    "A": "代码 添加 转场 技巧",
+    "B": "通过代码调整视频转场的技巧",
+    "C": "命令行 怎么加 转场 教学"
+  },
+  "917": {
+    "idx": 917,
+    "A": "插件 添加 转场 技巧",
+    "B": "使用插件添加视频转场的技巧",
+    "C": "插件 怎么加 转场 步骤"
+  },
+  "918": {
+    "idx": 918,
+    "A": "调整 转场 教程",
+    "B": "视频转场效果调整教程",
+    "C": "优化 转场效果 教学"
+  },
+  "919": {
+    "idx": 919,
+    "A": "AI 调整 转场 教程",
+    "B": "如何用智能技术调整视频转场",
+    "C": "AI 优化 转场效果 流程"
+  },
+  "920": {
+    "idx": 920,
+    "A": "软件 调整 转场 教程",
+    "B": "用什么软件调整视频转场效果",
+    "C": "电脑端 优化 转场效果 方法"
+  },
+  "922": {
+    "idx": 922,
+    "A": "代码 调整 转场 教程",
+    "B": "如何通过代码调整视频转场",
+    "C": "命令行 调整 transition 怎么做"
+  },
+  "923": {
+    "idx": 923,
+    "A": "插件 调整 转场 教程",
+    "B": "有哪些插件可以调整视频转场",
+    "C": "插件 优化 transition 流程"
+  },
+  "924": {
+    "idx": 924,
+    "A": "调整 转场 工具",
+    "B": "调整视频转场效果的工具",
+    "C": "怎么调 转场效果 教程"
+  },
+  "925": {
+    "idx": 925,
+    "A": "AI 调整 转场 工具",
+    "B": "智能调整视频转场的工具",
+    "C": "AI 怎么调 transition 步骤"
+  },
+  "926": {
+    "idx": 926,
+    "A": "软件 调整 转场 工具",
+    "B": "好用的视频转场调整软件",
+    "C": "电脑端 优化 transition 教学"
+  },
+  "927": {
+    "idx": 927,
+    "A": "在线 调整 转场 工具",
+    "B": "有哪些在线调整视频转场的工具",
+    "C": "网页版 调 transition 怎么做"
+  },
+  "928": {
+    "idx": 928,
+    "A": "代码 调整 转场 工具",
+    "B": "怎么用代码调整视频转场",
+    "C": "命令行 优化 转场 教学"
+  },
+  "929": {
+    "idx": 929,
+    "A": "插件 调整 转场 工具",
+    "B": "好用的视频转场调整插件有哪些",
+    "C": "插件 优化 转场效果 教学"
+  },
+  "930": {
+    "idx": 930,
+    "A": "调整 转场 技巧",
+    "B": "调整视频转场有什么技巧",
+    "C": "调整 转场 教学"
+  },
+  "931": {
+    "idx": 931,
+    "A": "AI 调整 转场 技巧",
+    "B": "如何利用人工智能优化视频转场效果",
+    "C": "AI 怎么调 transition 教学"
+  },
+  "932": {
+    "idx": 932,
+    "A": "软件 调整 转场 技巧",
+    "B": "视频剪辑软件里怎么调整转场",
+    "C": "软件 调整 转场 方法"
+  },
+  "934": {
+    "idx": 934,
+    "A": "代码 调整 转场 技巧",
+    "B": "通过编程实现转场效果的技巧",
+    "C": "命令行 调整 转场 教程"
+  },
+  "935": {
+    "idx": 935,
+    "A": "插件 调整 转场 技巧",
+    "B": "使用插件调整转场效果的方法",
+    "C": "插件 怎么调 转场效果 怎么做"
+  },
+  "936": {
+    "idx": 936,
+    "A": "抠取 蒙版 教程",
+    "B": "抠图蒙版制作教程",
+    "C": "抠图 抠像 教学"
+  },
+  "937": {
+    "idx": 937,
+    "A": "AI 抠取 蒙版 教程",
+    "B": "如何用人工智能自动抠图做蒙版",
+    "C": "AI 分割 遮罩 怎么做"
+  },
+  "938": {
+    "idx": 938,
+    "A": "软件 抠取 蒙版 教程",
+    "B": "剪辑软件抠图蒙版操作教程",
+    "C": "软件 抠 遮罩 怎么做"
+  },
+  "939": {
+    "idx": 939,
+    "A": "在线 抠取 蒙版 教程",
+    "B": "在线抠图制作蒙版的教程",
+    "C": "网页版 分割 抠像 教程"
+  },
+  "940": {
+    "idx": 940,
+    "A": "代码 抠取 蒙版 教程",
+    "B": "用代码实现抠图蒙版的方法",
+    "C": "代码 抠 mask 方法"
+  },
+  "941": {
+    "idx": 941,
+    "A": "插件 抠取 蒙版 教程",
+    "B": "有哪些好用的抠图蒙版插件",
+    "C": "插件 抠图 遮罩 步骤"
+  },
+  "942": {
+    "idx": 942,
+    "A": "抠取 蒙版 工具",
+    "B": "什么工具可以快速抠图做蒙版",
+    "C": "怎么抠 抠像 方法"
+  },
+  "943": {
+    "idx": 943,
+    "A": "AI 抠取 蒙版 工具",
+    "B": "好用的智能抠图蒙版工具推荐",
+    "C": "AI 怎么抠 抠像 教程"
+  },
+  "944": {
+    "idx": 944,
+    "A": "软件 抠取 蒙版 工具",
+    "B": "剪辑软件里的抠图蒙版工具怎么用",
+    "C": "软件 抠图 mask 流程"
+  },
+  "945": {
+    "idx": 945,
+    "A": "在线 抠取 蒙版 工具",
+    "B": "在线抠图蒙版工具有哪些",
+    "C": "网页版 抠图 遮罩 教学"
+  },
+  "946": {
+    "idx": 946,
+    "A": "代码 抠取 蒙版 工具",
+    "B": "实现抠图蒙版的代码工具",
+    "C": "命令行 抠图 遮罩 步骤"
+  },
+  "947": {
+    "idx": 947,
+    "A": "插件 抠取 蒙版 工具",
+    "B": "好用的抠图蒙版插件推荐",
+    "C": "插件 抠 遮罩 方法"
+  },
+  "948": {
+    "idx": 948,
+    "A": "抠取 蒙版 技巧",
+    "B": "抠图蒙版的操作技巧",
+    "C": "抠 蒙版 流程"
+  },
+  "949": {
+    "idx": 949,
+    "A": "AI 抠取 蒙版 技巧",
+    "B": "利用人工智能提升抠图蒙版质量的技巧",
+    "C": "AI 抠 mask 教程"
+  },
+  "950": {
+    "idx": 950,
+    "A": "软件 抠取 蒙版 技巧",
+    "B": "软件抠图蒙版的高级技巧",
+    "C": "电脑端 分割 mask 方法"
+  },
+  "951": {
+    "idx": 951,
+    "A": "在线 抠取 蒙版 技巧",
+    "B": "在线抠图制作蒙版的技巧",
+    "C": "在线 抠图 蒙版 步骤"
+  },
+  "952": {
+    "idx": 952,
+    "A": "代码 抠取 蒙版 技巧",
+    "B": "编写代码处理抠图蒙版的技巧",
+    "C": "命令行 怎么抠 mask 怎么做"
+  },
+  "953": {
+    "idx": 953,
+    "A": "插件 抠取 蒙版 技巧",
+    "B": "使用插件进行抠图蒙版的技巧",
+    "C": "插件 抠 遮罩 教学"
+  },
+  "954": {
+    "idx": 954,
+    "A": "元素生成 蒙版 教程",
+    "B": "如何通过元素生成制作蒙版教程",
+    "C": "生成 mask 怎么做"
+  },
+  "955": {
+    "idx": 955,
+    "A": "AI 元素生成 蒙版 教程",
+    "B": "利用人工智能生成元素制作蒙版的教程",
+    "C": "AI 制作 抠像 流程"
+  },
+  "956": {
+    "idx": 956,
+    "A": "软件 元素生成 蒙版 教程",
+    "B": "软件中通过元素生成蒙版的教程",
+    "C": "电脑端 创作 蒙版 教程"
+  },
+  "957": {
+    "idx": 957,
+    "A": "在线 元素生成 蒙版 教程",
+    "B": "在线生成元素制作蒙版的教程",
+    "C": "在线 怎么做 抠像 流程"
+  },
+  "958": {
+    "idx": 958,
+    "A": "代码 元素生成 蒙版 教程",
+    "B": "用代码实现元素生成蒙版的教程",
+    "C": "命令行 制作 遮罩 方法"
+  },
+  "959": {
+    "idx": 959,
+    "A": "插件 元素生成 蒙版 教程",
+    "B": "通过插件生成元素制作蒙版的教程",
+    "C": "插件 生成 遮罩 流程"
+  },
+  "960": {
+    "idx": 960,
+    "A": "元素生成 蒙版 工具",
+    "B": "有什么工具可以根据元素生成蒙版",
+    "C": "创作 遮罩 流程"
+  },
+  "961": {
+    "idx": 961,
+    "A": "AI 元素生成 蒙版 工具",
+    "B": "好用的智能元素生成蒙版工具",
+    "C": "AI 创作 蒙版 方法"
+  },
+  "962": {
+    "idx": 962,
+    "A": "软件 元素生成 蒙版 工具",
+    "B": "软件里生成元素做蒙版的工具",
+    "C": "软件 创作 抠像 流程"
+  },
+  "963": {
+    "idx": 963,
+    "A": "在线 元素生成 蒙版 工具",
+    "B": "在线生成元素制作蒙版的工具",
+    "C": "网页版 创作 蒙版 教程"
+  },
+  "964": {
+    "idx": 964,
+    "A": "代码 元素生成 蒙版 工具",
+    "B": "通过代码生成元素做蒙版的工具",
+    "C": "代码 生成 遮罩 教学"
+  },
+  "965": {
+    "idx": 965,
+    "A": "插件 元素生成 蒙版 工具",
+    "B": "好用的元素生成蒙版插件",
+    "C": "插件 创作 mask 方法"
+  },
+  "966": {
+    "idx": 966,
+    "A": "元素生成 蒙版 技巧",
+    "B": "通过元素生成制作蒙版的技巧",
+    "C": "生成 mask 教学"
+  },
+  "967": {
+    "idx": 967,
+    "A": "AI 元素生成 蒙版 技巧",
+    "B": "利用人工智能生成元素做蒙版的技巧",
+    "C": "AI 怎么做 mask 流程"
+  },
+  "968": {
+    "idx": 968,
+    "A": "软件 元素生成 蒙版 技巧",
+    "B": "怎么用软件给元素生成蒙版",
+    "C": "电脑端 怎么做 mask 教程"
+  },
+  "969": {
+    "idx": 969,
+    "A": "在线 元素生成 蒙版 技巧",
+    "B": "在线生成元素蒙版有什么技巧",
+    "C": "在线 制作 mask 怎么做"
+  },
+  "970": {
+    "idx": 970,
+    "A": "代码 元素生成 蒙版 技巧",
+    "B": "如何通过代码实现元素蒙版生成",
+    "C": "命令行 做 抠像 步骤"
+  },
+  "971": {
+    "idx": 971,
+    "A": "插件 元素生成 蒙版 技巧",
+    "B": "有哪些插件可以辅助生成元素蒙版",
+    "C": "插件 怎么做 遮罩 教学"
+  },
+  "972": {
+    "idx": 972,
+    "A": "上传 控制图 教程",
+    "B": "上传控制图的操作教程",
+    "C": "怎么导入 线稿 流程"
+  },
+  "973": {
+    "idx": 973,
+    "A": "AI 上传 控制图 教程",
+    "B": "上传控制图的智能处理教程",
+    "C": "AI 上传 结构图 流程"
+  },
+  "974": {
+    "idx": 974,
+    "A": "软件 上传 控制图 教程",
+    "B": "用软件上传控制图的详细步骤",
+    "C": "电脑端 上传 结构图 怎么做"
+  },
+  "975": {
+    "idx": 975,
+    "A": "在线 上传 控制图 教程",
+    "B": "在线上传控制图的方法",
+    "C": "在线 导入 控制图 教程"
+  },
+  "976": {
+    "idx": 976,
+    "A": "代码 上传 控制图 教程",
+    "B": "如何用代码上传控制图",
+    "C": "命令行 用自己的 线稿 流程"
+  },
+  "977": {
+    "idx": 977,
+    "A": "插件 上传 控制图 教程",
+    "B": "上传控制图的插件使用教程",
+    "C": "插件 怎么导入 结构图 流程"
+  },
+  "978": {
+    "idx": 978,
+    "A": "上传 控制图 工具",
+    "B": "好用的控制图上传工具",
+    "C": "导入 线稿 方法"
+  },
+  "979": {
+    "idx": 979,
+    "A": "AI 上传 控制图 工具",
+    "B": "智能控制图上传工具推荐",
+    "C": "AI 用自己的 结构图 怎么做"
+  },
+  "980": {
+    "idx": 980,
+    "A": "软件 上传 控制图 工具",
+    "B": "适合上传控制图的软件工具",
+    "C": "软件 上传 线稿 方法"
+  },
+  "981": {
+    "idx": 981,
+    "A": "在线 上传 控制图 工具",
+    "B": "在线上传控制图的工具",
+    "C": "网页版 导入 ControlNet 方法"
+  },
+  "982": {
+    "idx": 982,
+    "A": "代码 上传 控制图 工具",
+    "B": "处理控制图上传的代码工具",
+    "C": "命令行 上传 控制图 步骤"
+  },
+  "983": {
+    "idx": 983,
+    "A": "插件 上传 控制图 工具",
+    "B": "上传控制图的插件工具",
+    "C": "插件 用自己的 结构图 方法"
+  },
+  "984": {
+    "idx": 984,
+    "A": "上传 控制图 技巧",
+    "B": "上传控制图的操作技巧",
+    "C": "上传 控制图 怎么做"
+  },
+  "985": {
+    "idx": 985,
+    "A": "AI 上传 控制图 技巧",
+    "B": "智能上传控制图的技巧",
+    "C": "AI 怎么导入 结构图 怎么做"
+  },
+  "986": {
+    "idx": 986,
+    "A": "软件 上传 控制图 技巧",
+    "B": "软件上传控制图的实用技巧",
+    "C": "电脑端 上传 线稿 教程"
+  },
+  "987": {
+    "idx": 987,
+    "A": "在线 上传 控制图 技巧",
+    "B": "在线上传控制图的技巧",
+    "C": "在线 怎么导入 结构图 教程"
+  },
+  "988": {
+    "idx": 988,
+    "A": "代码 上传 控制图 技巧",
+    "B": "代码实现控制图上传的技巧",
+    "C": "命令行 用自己的 结构图 方法"
+  },
+  "989": {
+    "idx": 989,
+    "A": "插件 上传 控制图 技巧",
+    "B": "使用插件上传控制图的技巧",
+    "C": "插件 导入 控制图 怎么做"
+  },
+  "990": {
+    "idx": 990,
+    "A": "识别 控制图 教程",
+    "B": "识别控制图的操作教程",
+    "C": "OCR 结构图 方法"
+  },
+  "991": {
+    "idx": 991,
+    "A": "AI 识别 控制图 教程",
+    "B": "智能识别控制图的教程",
+    "C": "AI 检测 ControlNet 方法"
+  },
+  "992": {
+    "idx": 992,
+    "A": "软件 识别 控制图 教程",
+    "B": "用软件识别控制图的教程",
+    "C": "电脑端 转录 控制图 教程"
+  },
+  "993": {
+    "idx": 993,
+    "A": "在线 识别 控制图 教程",
+    "B": "在线识别控制图的方法",
+    "C": "在线 检测 结构图 怎么做"
+  },
+  "995": {
+    "idx": 995,
+    "A": "插件 识别 控制图 教程",
+    "B": "识别控制图的插件使用教程",
+    "C": "插件 检测 ControlNet 步骤"
+  },
+  "996": {
+    "idx": 996,
+    "A": "识别 控制图 工具",
+    "B": "识别控制图的工具",
+    "C": "转录 结构图 流程"
+  },
+  "997": {
+    "idx": 997,
+    "A": "AI 识别 控制图 工具",
+    "B": "智能识别控制图的工具",
+    "C": "AI 转录 结构图 方法"
+  },
+  "998": {
+    "idx": 998,
+    "A": "软件 识别 控制图 工具",
+    "B": "识别控制图的软件工具",
+    "C": "电脑端 转录 线稿 教学"
+  },
+  "999": {
+    "idx": 999,
+    "A": "在线 识别 控制图 工具",
+    "B": "在线识别控制图的工具",
+    "C": "网页版 提取文字 控制图 步骤"
+  },
+  "1000": {
+    "idx": 1000,
+    "A": "代码 识别 控制图 工具",
+    "B": "识别控制图的代码工具",
+    "C": "命令行 识别 线稿 方法"
+  },
+  "1001": {
+    "idx": 1001,
+    "A": "插件 识别 控制图 工具",
+    "B": "识别控制图的插件工具",
+    "C": "插件 识别 线稿 步骤"
+  },
+  "1002": {
+    "idx": 1002,
+    "A": "识别 控制图 技巧",
+    "B": "识别控制图的技巧",
+    "C": "转录 ControlNet 教学"
+  },
+  "1003": {
+    "idx": 1003,
+    "A": "AI 识别 控制图 技巧",
+    "B": "智能识别控制图的技巧",
+    "C": "AI 转录 线稿 流程"
+  },
+  "1004": {
+    "idx": 1004,
+    "A": "软件 识别 控制图 技巧",
+    "B": "软件识别控制图的技巧",
+    "C": "电脑端 检测 ControlNet 教程"
+  },
+  "1005": {
+    "idx": 1005,
+    "A": "在线 识别 控制图 技巧",
+    "B": "在线识别控制图的技巧",
+    "C": "在线 检测 控制图 怎么做"
+  },
+  "1007": {
+    "idx": 1007,
+    "A": "插件 识别 控制图 技巧",
+    "B": "插件识别控制图的技巧",
+    "C": "插件 提取文字 ControlNet 怎么做"
+  },
+  "1008": {
+    "idx": 1008,
+    "A": "调整 控制图 教程",
+    "B": "调整控制图的操作教程",
+    "C": "调 线稿 方法"
+  },
+  "1009": {
+    "idx": 1009,
+    "A": "AI 调整 控制图 教程",
+    "B": "智能调整控制图的教程",
+    "C": "AI 调整 ControlNet 方法"
+  },
+  "1010": {
+    "idx": 1010,
+    "A": "软件 调整 控制图 教程",
+    "B": "怎么用软件调整控制图的教程",
+    "C": "软件 怎么调 线稿 方法"
+  },
+  "1011": {
+    "idx": 1011,
+    "A": "在线 调整 控制图 教程",
+    "B": "在线调整控制图的方法教程",
+    "C": "网页版 怎么调 ControlNet 怎么做"
+  },
+  "1012": {
+    "idx": 1012,
+    "A": "代码 调整 控制图 教程",
+    "B": "通过代码调整控制图的教程",
+    "C": "命令行 怎么调 结构图 方法"
+  },
+  "1013": {
+    "idx": 1013,
+    "A": "插件 调整 控制图 教程",
+    "B": "有什么插件可以调整控制图",
+    "C": "插件 调 ControlNet 步骤"
+  },
+  "1014": {
+    "idx": 1014,
+    "A": "调整 控制图 工具",
+    "B": "调整控制图用什么工具比较好",
+    "C": "怎么调 ControlNet 步骤"
+  },
+  "1015": {
+    "idx": 1015,
+    "A": "AI 调整 控制图 工具",
+    "B": "智能调整控制图的工具推荐",
+    "C": "AI 调 线稿 步骤"
+  },
+  "1016": {
+    "idx": 1016,
+    "A": "软件 调整 控制图 工具",
+    "B": "调整控制图的软件工具有哪些",
+    "C": "电脑端 怎么调 结构图 步骤"
+  },
+  "1017": {
+    "idx": 1017,
+    "A": "在线 调整 控制图 工具",
+    "B": "在线调整控制图的工具推荐",
+    "C": "在线 优化 线稿 步骤"
+  },
+  "1018": {
+    "idx": 1018,
+    "A": "代码 调整 控制图 工具",
+    "B": "调整控制图的代码工具分享",
+    "C": "代码 怎么调 控制图 步骤"
+  },
+  "1019": {
+    "idx": 1019,
+    "A": "插件 调整 控制图 工具",
+    "B": "好用的控制图调整插件",
+    "C": "插件 怎么调 线稿 教学"
+  },
+  "1020": {
+    "idx": 1020,
+    "A": "调整 控制图 技巧",
+    "B": "调整控制图有哪些实用技巧",
+    "C": "怎么调 线稿 流程"
+  },
+  "1021": {
+    "idx": 1021,
+    "A": "AI 调整 控制图 技巧",
+    "B": "智能调整控制图的操作技巧",
+    "C": "AI 怎么调 结构图 流程"
+  },
+  "1022": {
+    "idx": 1022,
+    "A": "软件 调整 控制图 技巧",
+    "B": "软件调整控制图的技巧分享",
+    "C": "软件 调 ControlNet 教程"
+  },
+  "1023": {
+    "idx": 1023,
+    "A": "在线 调整 控制图 技巧",
+    "B": "在线调整控制图的技巧有哪些",
+    "C": "在线 调 控制图 教程"
+  },
+  "1024": {
+    "idx": 1024,
+    "A": "代码 调整 控制图 技巧",
+    "B": "用代码调整控制图的技巧",
+    "C": "命令行 怎么调 线稿 教程"
+  },
+  "1025": {
+    "idx": 1025,
+    "A": "插件 调整 控制图 技巧",
+    "B": "调整控制图的插件使用技巧",
+    "C": "插件 调整 ControlNet 怎么做"
+  },
+  "1026": {
+    "idx": 1026,
+    "A": "键入 运动轨迹 教程",
+    "B": "如何通过输入来设置运动轨迹的教程",
+    "C": "编写 motion brush 教学"
+  },
+  "1027": {
+    "idx": 1027,
+    "A": "AI 键入 运动轨迹 教程",
+    "B": "智能输入运动轨迹的教程",
+    "C": "AI 怎么写 运动笔刷 步骤"
+  },
+  "1028": {
+    "idx": 1028,
+    "A": "软件 键入 运动轨迹 教程",
+    "B": "用软件设置运动轨迹的教程",
+    "C": "软件 写 运动轨迹 方法"
+  },
+  "1029": {
+    "idx": 1029,
+    "A": "在线 键入 运动轨迹 教程",
+    "B": "在线输入运动轨迹的教程",
+    "C": "在线 输入 motion brush 流程"
+  },
+  "1030": {
+    "idx": 1030,
+    "A": "代码 键入 运动轨迹 教程",
+    "B": "通过代码输入运动轨迹的教程",
+    "C": "代码 编写 motion brush 流程"
+  },
+  "1031": {
+    "idx": 1031,
+    "A": "插件 键入 运动轨迹 教程",
+    "B": "有什么插件可以输入运动轨迹",
+    "C": "插件 写 运镜 步骤"
+  },
+  "1032": {
+    "idx": 1032,
+    "A": "键入 运动轨迹 工具",
+    "B": "输入运动轨迹用什么工具",
+    "C": "写 运动笔刷 步骤"
+  },
+  "1033": {
+    "idx": 1033,
+    "A": "AI 键入 运动轨迹 工具",
+    "B": "智能输入运动轨迹的工具",
+    "C": "AI 编写 运动轨迹 方法"
+  },
+  "1034": {
+    "idx": 1034,
+    "A": "软件 键入 运动轨迹 工具",
+    "B": "输入运动轨迹的软件工具",
+    "C": "电脑端 怎么写 运动轨迹 教程"
+  },
+  "1035": {
+    "idx": 1035,
+    "A": "在线 键入 运动轨迹 工具",
+    "B": "在线输入运动轨迹的工具",
+    "C": "网页版 输入 motion brush 教学"
+  },
+  "1036": {
+    "idx": 1036,
+    "A": "代码 键入 运动轨迹 工具",
+    "B": "输入运动轨迹的代码工具",
+    "C": "命令行 输入 运镜 教学"
+  },
+  "1037": {
+    "idx": 1037,
+    "A": "插件 键入 运动轨迹 工具",
+    "B": "输入运动轨迹的插件推荐",
+    "C": "插件 怎么写 运动轨迹 流程"
+  },
+  "1038": {
+    "idx": 1038,
+    "A": "键入 运动轨迹 技巧",
+    "B": "输入运动轨迹有什么技巧",
+    "C": "编写 motion brush 方法"
+  },
+  "1039": {
+    "idx": 1039,
+    "A": "AI 键入 运动轨迹 技巧",
+    "B": "智能输入运动轨迹的技巧",
+    "C": "AI 写 motion brush 教学"
+  },
+  "1040": {
+    "idx": 1040,
+    "A": "软件 键入 运动轨迹 技巧",
+    "B": "软件输入运动轨迹的技巧",
+    "C": "软件 输入 运动轨迹 怎么做"
+  },
+  "1041": {
+    "idx": 1041,
+    "A": "在线 键入 运动轨迹 技巧",
+    "B": "在线输入运动轨迹的技巧",
+    "C": "网页版 输入 运镜 步骤"
+  },
+  "1042": {
+    "idx": 1042,
+    "A": "代码 键入 运动轨迹 技巧",
+    "B": "代码输入运动轨迹的技巧",
+    "C": "命令行 输入 motion brush 步骤"
+  },
+  "1043": {
+    "idx": 1043,
+    "A": "插件 键入 运动轨迹 技巧",
+    "B": "输入运动轨迹的插件技巧",
+    "C": "插件 怎么写 运镜 步骤"
+  },
+  "1044": {
+    "idx": 1044,
+    "A": "元素生成 运动轨迹 教程",
+    "B": "元素生成运动轨迹的教程",
+    "C": "怎么做 运动轨迹 教程"
+  },
+  "1045": {
+    "idx": 1045,
+    "A": "AI 元素生成 运动轨迹 教程",
+    "B": "智能生成元素运动轨迹的教程",
+    "C": "AI 做 运动笔刷 流程"
+  },
+  "1046": {
+    "idx": 1046,
+    "A": "软件 元素生成 运动轨迹 教程",
+    "B": "软件生成元素运动轨迹的教程",
+    "C": "电脑端 创作 运动笔刷 教学"
+  },
+  "1047": {
+    "idx": 1047,
+    "A": "在线 元素生成 运动轨迹 教程",
+    "B": "在线生成元素运动轨迹的教程",
+    "C": "在线 怎么做 运动笔刷 方法"
+  },
+  "1048": {
+    "idx": 1048,
+    "A": "代码 元素生成 运动轨迹 教程",
+    "B": "代码生成元素运动轨迹的教程",
+    "C": "代码 制作 运动轨迹 怎么做"
+  },
+  "1049": {
+    "idx": 1049,
+    "A": "插件 元素生成 运动轨迹 教程",
+    "B": "插件生成元素运动轨迹的教程",
+    "C": "插件 做 运动笔刷 怎么做"
+  },
+  "1050": {
+    "idx": 1050,
+    "A": "元素生成 运动轨迹 工具",
+    "B": "怎么生成元素的运动轨迹",
+    "C": "创作 motion brush 方法"
+  },
+  "1051": {
+    "idx": 1051,
+    "A": "AI 元素生成 运动轨迹 工具",
+    "B": "有什么智能生成元素运动轨迹的工具",
+    "C": "AI 制作 运镜 方法"
+  },
+  "1052": {
+    "idx": 1052,
+    "A": "软件 元素生成 运动轨迹 工具",
+    "B": "做元素运动轨迹的软件有哪些",
+    "C": "电脑端 创作 运动笔刷 教程"
+  },
+  "1053": {
+    "idx": 1053,
+    "A": "在线 元素生成 运动轨迹 工具",
+    "B": "有没有在线生成元素运动轨迹的工具",
+    "C": "在线 生成 运动轨迹 方法"
+  },
+  "1054": {
+    "idx": 1054,
+    "A": "代码 元素生成 运动轨迹 工具",
+    "B": "如何通过代码实现元素运动轨迹生成",
+    "C": "代码 制作 运动笔刷 方法"
+  },
+  "1055": {
+    "idx": 1055,
+    "A": "插件 元素生成 运动轨迹 工具",
+    "B": "有没有能生成元素运动轨迹的插件",
+    "C": "插件 生成 运动轨迹 教学"
+  },
+  "1056": {
+    "idx": 1056,
+    "A": "元素生成 运动轨迹 技巧",
+    "B": "元素运动轨迹的制作技巧有哪些",
+    "C": "创作 motion brush 教程"
+  },
+  "1057": {
+    "idx": 1057,
+    "A": "AI 元素生成 运动轨迹 技巧",
+    "B": "智能生成元素运动轨迹有什么技巧",
+    "C": "AI 生成 motion brush 流程"
+  },
+  "1058": {
+    "idx": 1058,
+    "A": "软件 元素生成 运动轨迹 技巧",
+    "B": "软件制作元素运动轨迹的技巧",
+    "C": "电脑端 做 运镜 方法"
+  },
+  "1059": {
+    "idx": 1059,
+    "A": "在线 元素生成 运动轨迹 技巧",
+    "B": "在线生成元素运动轨迹的方法技巧",
+    "C": "网页版 怎么做 运镜 怎么做"
+  },
+  "1060": {
+    "idx": 1060,
+    "A": "代码 元素生成 运动轨迹 技巧",
+    "B": "用代码写元素运动轨迹的技巧",
+    "C": "命令行 生成 运动轨迹 方法"
+  },
+  "1061": {
+    "idx": 1061,
+    "A": "插件 元素生成 运动轨迹 技巧",
+    "B": "使用插件制作元素运动轨迹的技巧",
+    "C": "插件 生成 motion brush 步骤"
+  },
+  "1062": {
+    "idx": 1062,
+    "A": "调整 运动轨迹 教程",
+    "B": "怎么调整元素的运动轨迹",
+    "C": "调整 运镜 教程"
+  },
+  "1063": {
+    "idx": 1063,
+    "A": "AI 调整 运动轨迹 教程",
+    "B": "如何利用智能技术调整运动轨迹",
+    "C": "AI 调整 运动笔刷 怎么做"
+  },
+  "1064": {
+    "idx": 1064,
+    "A": "软件 调整 运动轨迹 教程",
+    "B": "用软件调整运动轨迹的方法",
+    "C": "软件 调 motion brush 步骤"
+  },
+  "1065": {
+    "idx": 1065,
+    "A": "在线 调整 运动轨迹 教程",
+    "B": "在线调整运动轨迹的教程",
+    "C": "网页版 优化 motion brush 怎么做"
+  },
+  "1066": {
+    "idx": 1066,
+    "A": "代码 调整 运动轨迹 教程",
+    "B": "如何用代码调整运动轨迹",
+    "C": "代码 调 运动笔刷 教程"
+  },
+  "1068": {
+    "idx": 1068,
+    "A": "调整 运动轨迹 工具",
+    "B": "调整运动轨迹用什么工具好",
+    "C": "调 motion brush 方法"
+  },
+  "1069": {
+    "idx": 1069,
+    "A": "AI 调整 运动轨迹 工具",
+    "B": "有没有智能调整运动轨迹的工具",
+    "C": "AI 调 运镜 教程"
+  },
+  "1070": {
+    "idx": 1070,
+    "A": "软件 调整 运动轨迹 工具",
+    "B": "调整运动轨迹的软件推荐",
+    "C": "电脑端 优化 motion brush 方法"
+  },
+  "1071": {
+    "idx": 1071,
+    "A": "在线 调整 运动轨迹 工具",
+    "B": "在线调整运动轨迹的工具",
+    "C": "网页版 调 运动轨迹 怎么做"
+  },
+  "1072": {
+    "idx": 1072,
+    "A": "代码 调整 运动轨迹 工具",
+    "B": "调整运动轨迹的代码工具",
+    "C": "命令行 调 运动笔刷 流程"
+  },
+  "1073": {
+    "idx": 1073,
+    "A": "插件 调整 运动轨迹 工具",
+    "B": "调整运动轨迹的插件有哪些",
+    "C": "插件 调整 motion brush 方法"
+  },
+  "1074": {
+    "idx": 1074,
+    "A": "调整 运动轨迹 技巧",
+    "B": "调整运动轨迹有什么技巧",
+    "C": "调整 运动轨迹 流程"
+  },
+  "1075": {
+    "idx": 1075,
+    "A": "AI 调整 运动轨迹 技巧",
+    "B": "智能调整运动轨迹的技巧",
+    "C": "AI 调整 运镜 怎么做"
+  },
+  "1076": {
+    "idx": 1076,
+    "A": "软件 调整 运动轨迹 技巧",
+    "B": "软件调整运动轨迹的技巧",
+    "C": "软件 调 运镜 怎么做"
+  },
+  "1077": {
+    "idx": 1077,
+    "A": "在线 调整 运动轨迹 技巧",
+    "B": "在线调整运动轨迹的技巧",
+    "C": "网页版 调 运动轨迹 教程"
+  },
+  "1078": {
+    "idx": 1078,
+    "A": "代码 调整 运动轨迹 技巧",
+    "B": "用代码调整运动轨迹的技巧",
+    "C": "代码 怎么调 运动轨迹 教学"
+  },
+  "1080": {
+    "idx": 1080,
+    "A": "检索 滤镜 教程",
+    "B": "怎么搜索和使用滤镜",
+    "C": "搜索 调色 方法"
+  },
+  "1081": {
+    "idx": 1081,
+    "A": "AI 检索 滤镜 教程",
+    "B": "如何用智能方式检索滤镜",
+    "C": "AI 搜 调色 流程"
+  },
+  "1082": {
+    "idx": 1082,
+    "A": "软件 检索 滤镜 教程",
+    "B": "软件里怎么检索滤镜",
+    "C": "软件 在哪找 调色 步骤"
+  },
+  "1083": {
+    "idx": 1083,
+    "A": "在线 检索 滤镜 教程",
+    "B": "在线检索滤镜的方法",
+    "C": "在线 搜索 filter 教学"
+  },
+  "1084": {
+    "idx": 1084,
+    "A": "代码 检索 滤镜 教程",
+    "B": "通过代码检索滤镜的教程",
+    "C": "命令行 搜索 LUT 教程"
+  },
+  "1085": {
+    "idx": 1085,
+    "A": "插件 检索 滤镜 教程",
+    "B": "有没有检索滤镜的插件",
+    "C": "插件 在哪找 调色 教学"
+  },
+  "1086": {
+    "idx": 1086,
+    "A": "检索 滤镜 工具",
+    "B": "检索滤镜的工具有哪些",
+    "C": "在哪找 LUT 流程"
+  },
+  "1087": {
+    "idx": 1087,
+    "A": "AI 检索 滤镜 工具",
+    "B": "智能检索滤镜的工具",
+    "C": "AI 在哪找 filter 方法"
+  },
+  "1088": {
+    "idx": 1088,
+    "A": "软件 检索 滤镜 工具",
+    "B": "检索滤镜的软件推荐",
+    "C": "电脑端 搜 filter 步骤"
+  },
+  "1089": {
+    "idx": 1089,
+    "A": "在线 检索 滤镜 工具",
+    "B": "在线检索滤镜的工具",
+    "C": "在线 在哪找 滤镜 方法"
+  },
+  "1090": {
+    "idx": 1090,
+    "A": "代码 检索 滤镜 工具",
+    "B": "检索滤镜的代码工具",
+    "C": "命令行 在哪找 filter 怎么做"
+  },
+  "1091": {
+    "idx": 1091,
+    "A": "插件 检索 滤镜 工具",
+    "B": "检索滤镜的插件推荐",
+    "C": "插件 哪里找 filter 步骤"
+  },
+  "1092": {
+    "idx": 1092,
+    "A": "检索 滤镜 技巧",
+    "B": "怎么搜索好用的滤镜技巧",
+    "C": "找 LUT 步骤"
+  },
+  "1093": {
+    "idx": 1093,
+    "A": "AI 检索 滤镜 技巧",
+    "B": "如何用智能技术搜索滤镜技巧",
+    "C": "AI 搜索 filter 教程"
+  },
+  "1094": {
+    "idx": 1094,
+    "A": "软件 检索 滤镜 技巧",
+    "B": "有哪些搜索滤镜技巧的软件",
+    "C": "电脑端 在哪找 滤镜 教程"
+  },
+  "1095": {
+    "idx": 1095,
+    "A": "在线 检索 滤镜 技巧",
+    "B": "在线搜索滤镜技巧的方法",
+    "C": "在线 搜索 filter 怎么做"
+  },
+  "1096": {
+    "idx": 1096,
+    "A": "代码 检索 滤镜 技巧",
+    "B": "通过代码搜索滤镜的技巧",
+    "C": "代码 哪里找 调色 教程"
+  },
+  "1097": {
+    "idx": 1097,
+    "A": "插件 检索 滤镜 技巧",
+    "B": "好用的滤镜搜索插件推荐",
+    "C": "插件 搜 滤镜 教学"
+  },
+  "1098": {
+    "idx": 1098,
+    "A": "下载 滤镜 教程",
+    "B": "怎么下载滤镜的教程",
+    "C": "导入 filter 教学"
+  },
+  "1099": {
+    "idx": 1099,
+    "A": "AI 下载 滤镜 教程",
+    "B": "智能生成滤镜的下载教程",
+    "C": "AI 导入 filter 方法"
+  },
+  "1100": {
+    "idx": 1100,
+    "A": "软件 下载 滤镜 教程",
+    "B": "下载滤镜的软件操作教程",
+    "C": "电脑端 获取 LUT 怎么做"
+  },
+  "1101": {
+    "idx": 1101,
+    "A": "在线 下载 滤镜 教程",
+    "B": "在线下载滤镜的详细教程",
+    "C": "网页版 获取 调色 步骤"
+  },
+  "1102": {
+    "idx": 1102,
+    "A": "代码 下载 滤镜 教程",
+    "B": "编写代码下载滤镜的教程",
+    "C": "命令行 导入 滤镜 教学"
+  },
+  "1103": {
+    "idx": 1103,
+    "A": "插件 下载 滤镜 教程",
+    "B": "下载滤镜插件的安装教程",
+    "C": "插件 获取 filter 步骤"
+  },
+  "1104": {
+    "idx": 1104,
+    "A": "下载 滤镜 工具",
+    "B": "哪里可以下载滤镜工具",
+    "C": "获取 LUT 教程"
+  },
+  "1105": {
+    "idx": 1105,
+    "A": "AI 下载 滤镜 工具",
+    "B": "好用的智能滤镜工具下载",
+    "C": "AI 怎么下载 滤镜 步骤"
+  },
+  "1106": {
+    "idx": 1106,
+    "A": "软件 下载 滤镜 工具",
+    "B": "下载滤镜处理工具的软件",
+    "C": "电脑端 获取 filter 流程"
+  },
+  "1107": {
+    "idx": 1107,
+    "A": "在线 下载 滤镜 工具",
+    "B": "在线获取滤镜工具的方法",
+    "C": "网页版 怎么下载 LUT 方法"
+  },
+  "1108": {
+    "idx": 1108,
+    "A": "代码 下载 滤镜 工具",
+    "B": "下载滤镜相关代码工具",
+    "C": "代码 导入 调色 步骤"
+  },
+  "1109": {
+    "idx": 1109,
+    "A": "插件 下载 滤镜 工具",
+    "B": "好用的滤镜插件工具下载",
+    "C": "插件 导入 LUT 流程"
+  },
+  "1110": {
+    "idx": 1110,
+    "A": "下载 滤镜 技巧",
+    "B": "下载滤镜有什么技巧",
+    "C": "获取 filter 流程"
+  },
+  "1111": {
+    "idx": 1111,
+    "A": "AI 下载 滤镜 技巧",
+    "B": "智能滤镜的下载与使用技巧",
+    "C": "AI 怎么下载 滤镜 方法"
+  },
+  "1112": {
+    "idx": 1112,
+    "A": "软件 下载 滤镜 技巧",
+    "B": "下载滤镜软件的实用技巧",
+    "C": "软件 下载 滤镜 教程"
+  },
+  "1113": {
+    "idx": 1113,
+    "A": "在线 下载 滤镜 技巧",
+    "B": "在线下载滤镜的技巧分享",
+    "C": "网页版 怎么下载 filter 教程"
+  },
+  "1114": {
+    "idx": 1114,
+    "A": "代码 下载 滤镜 技巧",
+    "B": "通过代码下载滤镜的技巧",
+    "C": "代码 下载 filter 方法"
+  },
+  "1115": {
+    "idx": 1115,
+    "A": "插件 下载 滤镜 技巧",
+    "B": "下载滤镜插件的技巧心得",
+    "C": "插件 获取 滤镜 方法"
+  },
+  "1116": {
+    "idx": 1116,
+    "A": "风格化 滤镜 教程",
+    "B": "怎么制作风格化滤镜的教程",
+    "C": "怎么转风格 LUT 教程"
+  },
+  "1117": {
+    "idx": 1117,
+    "A": "AI 风格化 滤镜 教程",
+    "B": "如何用智能技术制作风格化滤镜",
+    "C": "AI 怎么转风格 滤镜 教程"
+  },
+  "1118": {
+    "idx": 1118,
+    "A": "软件 风格化 滤镜 教程",
+    "B": "风格化滤镜的软件制作教程",
+    "C": "电脑端 风格迁移 滤镜 方法"
+  },
+  "1119": {
+    "idx": 1119,
+    "A": "在线 风格化 滤镜 教程",
+    "B": "在线制作风格化滤镜的教程",
+    "C": "网页版 转风格 滤镜 教程"
+  },
+  "1120": {
+    "idx": 1120,
+    "A": "代码 风格化 滤镜 教程",
+    "B": "用代码实现风格化滤镜的教程",
+    "C": "代码 转风格 filter 方法"
+  },
+  "1121": {
+    "idx": 1121,
+    "A": "插件 风格化 滤镜 教程",
+    "B": "风格化滤镜插件的使用教程",
+    "C": "插件 风格迁移 调色 怎么做"
+  },
+  "1122": {
+    "idx": 1122,
+    "A": "风格化 滤镜 工具",
+    "B": "有哪些好用的风格化滤镜工具",
+    "C": "风格化 调色 怎么做"
+  },
+  "1123": {
+    "idx": 1123,
+    "A": "AI 风格化 滤镜 工具",
+    "B": "智能风格化滤镜工具推荐",
+    "C": "AI 转风格 filter 步骤"
+  },
+  "1124": {
+    "idx": 1124,
+    "A": "软件 风格化 滤镜 工具",
+    "B": "好用的风格化滤镜处理软件",
+    "C": "软件 风格化 滤镜 怎么做"
+  },
+  "1125": {
+    "idx": 1125,
+    "A": "在线 风格化 滤镜 工具",
+    "B": "在线使用的风格化滤镜工具",
+    "C": "网页版 怎么转风格 LUT 教程"
+  },
+  "1126": {
+    "idx": 1126,
+    "A": "代码 风格化 滤镜 工具",
+    "B": "风格化滤镜的代码处理工具",
+    "C": "代码 转风格 滤镜 怎么做"
+  },
+  "1127": {
+    "idx": 1127,
+    "A": "插件 风格化 滤镜 工具",
+    "B": "好用的风格化滤镜插件工具",
+    "C": "插件 风格迁移 滤镜 方法"
+  },
+  "1128": {
+    "idx": 1128,
+    "A": "风格化 滤镜 技巧",
+    "B": "风格化滤镜的调整技巧",
+    "C": "风格化 filter 流程"
+  },
+  "1129": {
+    "idx": 1129,
+    "A": "AI 风格化 滤镜 技巧",
+    "B": "智能风格化滤镜的操作技巧",
+    "C": "AI 风格迁移 滤镜 教程"
+  },
+  "1130": {
+    "idx": 1130,
+    "A": "软件 风格化 滤镜 技巧",
+    "B": "风格化滤镜软件的使用技巧",
+    "C": "电脑端 风格化 filter 步骤"
+  },
+  "1131": {
+    "idx": 1131,
+    "A": "在线 风格化 滤镜 技巧",
+    "B": "在线调整风格化滤镜的技巧",
+    "C": "在线 转风格 filter 教学"
+  },
+  "1132": {
+    "idx": 1132,
+    "A": "代码 风格化 滤镜 技巧",
+    "B": "怎么用代码实现风格化滤镜效果",
+    "C": "命令行 风格化 调色 流程"
+  },
+  "1133": {
+    "idx": 1133,
+    "A": "插件 风格化 滤镜 技巧",
+    "B": "有哪些好用的风格化滤镜插件技巧",
+    "C": "插件 怎么转风格 调色 怎么做"
+  },
+  "1134": {
+    "idx": 1134,
+    "A": "调整 滤镜 教程",
+    "B": "滤镜效果怎么调整才好看",
+    "C": "调 滤镜 方法"
+  },
+  "1136": {
+    "idx": 1136,
+    "A": "软件 调整 滤镜 教程",
+    "B": "有没有调整滤镜的软件使用教程",
+    "C": "电脑端 调整 滤镜 怎么做"
+  },
+  "1137": {
+    "idx": 1137,
+    "A": "在线 调整 滤镜 教程",
+    "B": "在线调整滤镜效果的方法有哪些",
+    "C": "在线 调整 调色 方法"
+  },
+  "1138": {
+    "idx": 1138,
+    "A": "代码 调整 滤镜 教程",
+    "B": "如何通过代码编写来调整滤镜",
+    "C": "命令行 怎么调 滤镜 教学"
+  },
+  "1139": {
+    "idx": 1139,
+    "A": "插件 调整 滤镜 教程",
+    "B": "调整滤镜效果的插件使用技巧",
+    "C": "插件 优化 LUT 流程"
+  },
+  "1140": {
+    "idx": 1140,
+    "A": "调整 滤镜 工具",
+    "B": "好用的滤镜调整工具有哪些",
+    "C": "怎么调 LUT 怎么做"
+  },
+  "1141": {
+    "idx": 1141,
+    "A": "AI 调整 滤镜 工具",
+    "B": "有没有能自动调整滤镜的工具",
+    "C": "AI 优化 滤镜 方法"
+  },
+  "1142": {
+    "idx": 1142,
+    "A": "软件 调整 滤镜 工具",
+    "B": "调整滤镜效果的常用软件推荐",
+    "C": "电脑端 调 滤镜 教程"
+  },
+  "1143": {
+    "idx": 1143,
+    "A": "在线 调整 滤镜 工具",
+    "B": "在线调整滤镜的工具哪个好用",
+    "C": "网页版 调 LUT 教学"
+  },
+  "1144": {
+    "idx": 1144,
+    "A": "代码 调整 滤镜 工具",
+    "B": "适合调整滤镜的代码工具推荐",
+    "C": "代码 优化 调色 步骤"
+  },
+  "1145": {
+    "idx": 1145,
+    "A": "插件 调整 滤镜 工具",
+    "B": "好用的滤镜调整插件推荐",
+    "C": "插件 调整 滤镜 步骤"
+  },
+  "1146": {
+    "idx": 1146,
+    "A": "调整 滤镜 技巧",
+    "B": "调整滤镜效果有什么实用技巧",
+    "C": "优化 调色 步骤"
+  },
+  "1148": {
+    "idx": 1148,
+    "A": "软件 调整 滤镜 技巧",
+    "B": "软件调整滤镜效果的进阶技巧",
+    "C": "软件 调 滤镜 流程"
+  },
+  "1149": {
+    "idx": 1149,
+    "A": "在线 调整 滤镜 技巧",
+    "B": "在线调整滤镜效果的实用技巧",
+    "C": "网页版 优化 LUT 教程"
+  },
+  "1150": {
+    "idx": 1150,
+    "A": "代码 调整 滤镜 技巧",
+    "B": "通过代码调整滤镜的技巧有哪些",
+    "C": "代码 调整 调色 方法"
+  },
+  "1151": {
+    "idx": 1151,
+    "A": "插件 调整 滤镜 技巧",
+    "B": "使用插件调整滤镜的技巧分享",
+    "C": "插件 怎么调 LUT 教程"
+  },
+  "1152": {
+    "idx": 1152,
+    "A": "结构生成 构图布局 教程",
+    "B": "如何学习结构生成与构图布局",
+    "C": "怎么生成 布局 怎么做"
+  },
+  "1153": {
+    "idx": 1153,
+    "A": "AI 结构生成 构图布局 教程",
+    "B": "智能生成构图布局的教程有哪些",
+    "C": "AI 搭建 构图布局 方法"
+  },
+  "1154": {
+    "idx": 1154,
+    "A": "软件 结构生成 构图布局 教程",
+    "B": "软件如何进行结构生成与构图布局",
+    "C": "软件 构建 构图 流程"
+  },
+  "1155": {
+    "idx": 1155,
+    "A": "在线 结构生成 构图布局 教程",
+    "B": "在线生成结构与构图布局的教程",
+    "C": "网页版 怎么生成 布局 怎么做"
+  },
+  "1156": {
+    "idx": 1156,
+    "A": "代码 结构生成 构图布局 教程",
+    "B": "如何用代码实现结构生成与构图布局",
+    "C": "代码 生成 构图 怎么做"
+  },
+  "1157": {
+    "idx": 1157,
+    "A": "插件 结构生成 构图布局 教程",
+    "B": "结构生成与构图布局的插件使用教程",
+    "C": "插件 构建 布局 怎么做"
+  },
+  "1158": {
+    "idx": 1158,
+    "A": "结构生成 构图布局 工具",
+    "B": "有哪些辅助结构生成和构图的工具",
+    "C": "生成 布局 步骤"
+  },
+  "1159": {
+    "idx": 1159,
+    "A": "AI 结构生成 构图布局 工具",
+    "B": "好用的智能结构生成与构图工具",
+    "C": "AI 构建 构图布局 方法"
+  },
+  "1160": {
+    "idx": 1160,
+    "A": "软件 结构生成 构图布局 工具",
+    "B": "结构生成与构图布局的软件推荐",
+    "C": "软件 构建 构图 流程"
+  },
+  "1161": {
+    "idx": 1161,
+    "A": "在线 结构生成 构图布局 工具",
+    "B": "在线进行结构生成与构图的工具",
+    "C": "网页版 生成 布局 步骤"
+  },
+  "1162": {
+    "idx": 1162,
+    "A": "代码 结构生成 构图布局 工具",
+    "B": "适合结构生成与构图的代码工具",
+    "C": "命令行 怎么生成 布局 步骤"
+  },
+  "1163": {
+    "idx": 1163,
+    "A": "插件 结构生成 构图布局 工具",
+    "B": "结构生成与构图布局的插件工具",
+    "C": "插件 搭建 布局 步骤"
+  },
+  "1164": {
+    "idx": 1164,
+    "A": "结构生成 构图布局 技巧",
+    "B": "结构生成与构图布局的实用技巧",
+    "C": "搭建 布局 步骤"
+  },
+  "1165": {
+    "idx": 1165,
+    "A": "AI 结构生成 构图布局 技巧",
+    "B": "智能构图布局的生成技巧有哪些",
+    "C": "AI 构建 布局 步骤"
+  },
+  "1166": {
+    "idx": 1166,
+    "A": "软件 结构生成 构图布局 技巧",
+    "B": "软件进行结构生成与构图的技巧",
+    "C": "电脑端 搭建 布局 怎么做"
+  },
+  "1167": {
+    "idx": 1167,
+    "A": "在线 结构生成 构图布局 技巧",
+    "B": "在线进行结构生成与构图的技巧",
+    "C": "网页版 构建 布局 教程"
+  },
+  "1168": {
+    "idx": 1168,
+    "A": "代码 结构生成 构图布局 技巧",
+    "B": "通过代码优化结构生成与构图的技巧",
+    "C": "代码 搭建 构图布局 方法"
+  },
+  "1169": {
+    "idx": 1169,
+    "A": "插件 结构生成 构图布局 技巧",
+    "B": "使用插件进行结构生成与构图的技巧",
+    "C": "插件 构建 构图布局 流程"
+  },
+  "1170": {
+    "idx": 1170,
+    "A": "调整 构图布局 教程",
+    "B": "如何调整画面的构图布局",
+    "C": "优化 布局 教学"
+  },
+  "1171": {
+    "idx": 1171,
+    "A": "AI 调整 构图布局 教程",
+    "B": "智能调整构图布局的方法教程",
+    "C": "AI 优化 构图布局 怎么做"
+  },
+  "1172": {
+    "idx": 1172,
+    "A": "软件 调整 构图布局 教程",
+    "B": "软件调整构图布局的详细教程",
+    "C": "软件 怎么调 构图 步骤"
+  },
+  "1173": {
+    "idx": 1173,
+    "A": "在线 调整 构图布局 教程",
+    "B": "在线调整构图布局的操作教程",
+    "C": "在线 优化 布局 教程"
+  },
+  "1174": {
+    "idx": 1174,
+    "A": "代码 调整 构图布局 教程",
+    "B": "怎么用代码调整画面构图布局的教程",
+    "C": "命令行 优化 构图布局 怎么做"
+  },
+  "1175": {
+    "idx": 1175,
+    "A": "插件 调整 构图布局 教程",
+    "B": "怎么用插件调整画面构图布局的教程",
+    "C": "插件 调整 布局 教学"
+  },
+  "1176": {
+    "idx": 1176,
+    "A": "调整 构图布局 工具",
+    "B": "有什么调整画面构图布局的工具",
+    "C": "调整 构图 流程"
+  },
+  "1177": {
+    "idx": 1177,
+    "A": "AI 调整 构图布局 工具",
+    "B": "有什么能自动调整构图布局的工具",
+    "C": "AI 调 构图布局 方法"
+  },
+  "1178": {
+    "idx": 1178,
+    "A": "软件 调整 构图布局 工具",
+    "B": "有哪些调整画面构图布局的软件",
+    "C": "软件 优化 布局 怎么做"
+  },
+  "1179": {
+    "idx": 1179,
+    "A": "在线 调整 构图布局 工具",
+    "B": "有没有在线调整构图布局的工具",
+    "C": "在线 调整 构图 步骤"
+  },
+  "1180": {
+    "idx": 1180,
+    "A": "代码 调整 构图布局 工具",
+    "B": "有没有调整构图布局的代码工具",
+    "C": "代码 调 布局 步骤"
+  },
+  "1181": {
+    "idx": 1181,
+    "A": "插件 调整 构图布局 工具",
+    "B": "有没有调整构图布局的插件工具",
+    "C": "插件 优化 构图布局 方法"
+  },
+  "1182": {
+    "idx": 1182,
+    "A": "调整 构图布局 技巧",
+    "B": "调整画面构图布局有哪些技巧",
+    "C": "调 布局 教程"
+  },
+  "1183": {
+    "idx": 1183,
+    "A": "AI 调整 构图布局 技巧",
+    "B": "利用人工智能调整构图布局的技巧",
+    "C": "AI 调整 布局 怎么做"
+  },
+  "1184": {
+    "idx": 1184,
+    "A": "软件 调整 构图布局 技巧",
+    "B": "使用软件调整画面构图布局的技巧",
+    "C": "软件 调整 构图布局 流程"
+  },
+  "1185": {
+    "idx": 1185,
+    "A": "在线 调整 构图布局 技巧",
+    "B": "在线调整画面构图布局的技巧",
+    "C": "网页版 怎么调 布局 怎么做"
+  },
+  "1186": {
+    "idx": 1186,
+    "A": "代码 调整 构图布局 技巧",
+    "B": "通过代码调整构图布局的技巧",
+    "C": "代码 优化 布局 怎么做"
+  },
+  "1187": {
+    "idx": 1187,
+    "A": "插件 调整 构图布局 技巧",
+    "B": "使用插件调整构图布局的技巧",
+    "C": "插件 优化 构图布局 教学"
+  },
+  "1188": {
+    "idx": 1188,
+    "A": "裁切 截图 教程",
+    "B": "如何对截图进行裁切的教程",
+    "C": "切片 屏幕截图 教程"
+  },
+  "1189": {
+    "idx": 1189,
+    "A": "AI 裁切 截图 教程",
+    "B": "怎么用人工智能裁切截图的教程",
+    "C": "AI 裁剪 截屏 教程"
+  },
+  "1190": {
+    "idx": 1190,
+    "A": "软件 裁切 截图 教程",
+    "B": "用什么软件裁切截图的教程",
+    "C": "软件 怎么裁 截屏 教程"
+  },
+  "1191": {
+    "idx": 1191,
+    "A": "在线 裁切 截图 教程",
+    "B": "在线裁切截图的方法教程",
+    "C": "在线 截取 截屏 流程"
+  },
+  "1192": {
+    "idx": 1192,
+    "A": "代码 裁切 截图 教程",
+    "B": "如何通过代码实现截图裁切的教程",
+    "C": "代码 怎么裁 截屏 怎么做"
+  },
+  "1193": {
+    "idx": 1193,
+    "A": "插件 裁切 截图 教程",
+    "B": "怎么用插件裁切截图的教程",
+    "C": "插件 截取 屏幕截图 教学"
+  },
+  "1194": {
+    "idx": 1194,
+    "A": "裁切 截图 工具",
+    "B": "有哪些好用的截图裁切工具",
+    "C": "截取 截图 教学"
+  },
+  "1195": {
+    "idx": 1195,
+    "A": "AI 裁切 截图 工具",
+    "B": "有没有能自动裁切截图的工具",
+    "C": "AI 切片 截图 教学"
+  },
+  "1196": {
+    "idx": 1196,
+    "A": "软件 裁切 截图 工具",
+    "B": "有哪些可以裁切截图的软件",
+    "C": "软件 切片 截屏 怎么做"
+  },
+  "1197": {
+    "idx": 1197,
+    "A": "在线 裁切 截图 工具",
+    "B": "哪里有在线裁切截图的工具",
+    "C": "网页版 裁剪 截屏 流程"
+  },
+  "1198": {
+    "idx": 1198,
+    "A": "代码 裁切 截图 工具",
+    "B": "有没有可以裁切截图的代码工具",
+    "C": "代码 怎么裁 截屏 教程"
+  },
+  "1199": {
+    "idx": 1199,
+    "A": "插件 裁切 截图 工具",
+    "B": "有没有可以裁切截图的插件",
+    "C": "插件 截取 屏幕截图 步骤"
+  },
+  "1200": {
+    "idx": 1200,
+    "A": "裁切 截图 技巧",
+    "B": "截图裁切有哪些实用技巧",
+    "C": "截取 屏幕截图 教程"
+  },
+  "1201": {
+    "idx": 1201,
+    "A": "AI 裁切 截图 技巧",
+    "B": "利用人工智能裁切截图的技巧",
+    "C": "AI 切片 截屏 教学"
+  },
+  "1202": {
+    "idx": 1202,
+    "A": "软件 裁切 截图 技巧",
+    "B": "使用软件裁切截图的技巧",
+    "C": "电脑端 切片 截屏 怎么做"
+  },
+  "1203": {
+    "idx": 1203,
+    "A": "在线 裁切 截图 技巧",
+    "B": "在线裁切截图的技巧",
+    "C": "在线 怎么裁 屏幕截图 怎么做"
+  },
+  "1204": {
+    "idx": 1204,
+    "A": "代码 裁切 截图 技巧",
+    "B": "通过代码裁切截图的技巧",
+    "C": "代码 怎么裁 截屏 方法"
+  },
+  "1205": {
+    "idx": 1205,
+    "A": "插件 裁切 截图 技巧",
+    "B": "使用插件裁切截图的技巧",
+    "C": "插件 截取 屏幕截图 教程"
+  },
+  "1206": {
+    "idx": 1206,
+    "A": "抠取 截图 教程",
+    "B": "如何把截图里的主体抠出来的教程",
+    "C": "抠 屏幕截图 教程"
+  },
+  "1207": {
+    "idx": 1207,
+    "A": "AI 抠取 截图 教程",
+    "B": "怎么用人工智能把截图抠出来的教程",
+    "C": "AI 分割 截屏 流程"
+  },
+  "1209": {
+    "idx": 1209,
+    "A": "在线 抠取 截图 教程",
+    "B": "在线抠取截图主体的教程",
+    "C": "网页版 怎么抠 截屏 流程"
+  },
+  "1210": {
+    "idx": 1210,
+    "A": "代码 抠取 截图 教程",
+    "B": "如何用代码实现截图抠图的教程",
+    "C": "命令行 怎么抠 截图 怎么做"
+  },
+  "1211": {
+    "idx": 1211,
+    "A": "插件 抠取 截图 教程",
+    "B": "怎么用插件抠取截图的教程",
+    "C": "插件 抠 屏幕截图 步骤"
+  },
+  "1212": {
+    "idx": 1212,
+    "A": "抠取 截图 工具",
+    "B": "有哪些抠取截图主体的工具",
+    "C": "抠 截图 步骤"
+  },
+  "1213": {
+    "idx": 1213,
+    "A": "AI 抠取 截图 工具",
+    "B": "有没有能自动抠取截图的工具",
+    "C": "AI 抠图 屏幕截图 教程"
+  },
+  "1214": {
+    "idx": 1214,
+    "A": "软件 抠取 截图 工具",
+    "B": "有哪些可以抠取截图的软件",
+    "C": "电脑端 抠 截图 怎么做"
+  },
+  "1215": {
+    "idx": 1215,
+    "A": "在线 抠取 截图 工具",
+    "B": "有什么在线抠图的工具吗",
+    "C": "网页版 怎么抠 截屏 怎么做"
+  },
+  "1216": {
+    "idx": 1216,
+    "A": "代码 抠取 截图 工具",
+    "B": "怎么用代码实现截图抠图",
+    "C": "命令行 怎么抠 屏幕截图 流程"
+  },
+  "1217": {
+    "idx": 1217,
+    "A": "插件 抠取 截图 工具",
+    "B": "有哪些好用的截图抠图插件",
+    "C": "插件 抠图 截图 步骤"
+  },
+  "1218": {
+    "idx": 1218,
+    "A": "抠取 截图 技巧",
+    "B": "截图抠图有什么好方法",
+    "C": "抠图 屏幕截图 流程"
+  },
+  "1219": {
+    "idx": 1219,
+    "A": "AI 抠取 截图 技巧",
+    "B": "如何利用智能技术进行截图抠图",
+    "C": "AI 抠 屏幕截图 方法"
+  },
+  "1221": {
+    "idx": 1221,
+    "A": "在线 抠取 截图 技巧",
+    "B": "在线截图抠图的操作方法",
+    "C": "网页版 抠图 截屏 教程"
+  },
+  "1222": {
+    "idx": 1222,
+    "A": "代码 抠取 截图 技巧",
+    "B": "用代码进行截图抠图的技巧有哪些",
+    "C": "命令行 分割 截屏 教程"
+  },
+  "1223": {
+    "idx": 1223,
+    "A": "插件 抠取 截图 技巧",
+    "B": "截图抠图插件的使用心得",
+    "C": "插件 抠 屏幕截图 教程"
+  },
+  "1224": {
+    "idx": 1224,
+    "A": "抽帧 截图 教程",
+    "B": "视频抽帧截图的详细教程",
+    "C": "提取帧 屏幕截图 教程"
+  },
+  "1225": {
+    "idx": 1225,
+    "A": "AI 抽帧 截图 教程",
+    "B": "如何用智能工具进行视频抽帧截图",
+    "C": "AI 怎么抽帧 屏幕截图 教程"
+  },
+  "1226": {
+    "idx": 1226,
+    "A": "软件 抽帧 截图 教程",
+    "B": "视频抽帧截图用什么软件好",
+    "C": "电脑端 抽帧 截图 流程"
+  },
+  "1227": {
+    "idx": 1227,
+    "A": "在线 抽帧 截图 教程",
+    "B": "在线视频抽帧截图怎么操作",
+    "C": "网页版 导出帧 截图 方法"
+  },
+  "1228": {
+    "idx": 1228,
+    "A": "代码 抽帧 截图 教程",
+    "B": "如何通过代码实现视频抽帧截图",
+    "C": "代码 提取帧 截图 教程"
+  },
+  "1229": {
+    "idx": 1229,
+    "A": "插件 抽帧 截图 教程",
+    "B": "有没有好用的视频抽帧截图插件",
+    "C": "插件 怎么抽帧 截屏 方法"
+  },
+  "1230": {
+    "idx": 1230,
+    "A": "抽帧 截图 工具",
+    "B": "视频抽帧截图用什么工具比较好",
+    "C": "提取帧 屏幕截图 教学"
+  },
+  "1231": {
+    "idx": 1231,
+    "A": "AI 抽帧 截图 工具",
+    "B": "好用的智能视频抽帧截图工具推荐",
+    "C": "AI 怎么抽帧 截屏 步骤"
+  },
+  "1232": {
+    "idx": 1232,
+    "A": "软件 抽帧 截图 工具",
+    "B": "视频抽帧截图软件有哪些",
+    "C": "软件 提取帧 屏幕截图 教程"
+  },
+  "1233": {
+    "idx": 1233,
+    "A": "在线 抽帧 截图 工具",
+    "B": "在线视频抽帧截图工具怎么找",
+    "C": "网页版 提取帧 截屏 流程"
+  },
+  "1234": {
+    "idx": 1234,
+    "A": "代码 抽帧 截图 工具",
+    "B": "有没有实现视频抽帧截图的代码工具",
+    "C": "代码 提取帧 截屏 步骤"
+  },
+  "1235": {
+    "idx": 1235,
+    "A": "插件 抽帧 截图 工具",
+    "B": "视频抽帧截图插件推荐",
+    "C": "插件 导出帧 屏幕截图 流程"
+  },
+  "1236": {
+    "idx": 1236,
+    "A": "抽帧 截图 技巧",
+    "B": "视频抽帧截图有哪些实用技巧",
+    "C": "怎么抽帧 截屏 怎么做"
+  },
+  "1237": {
+    "idx": 1237,
+    "A": "AI 抽帧 截图 技巧",
+    "B": "智能视频抽帧截图的技巧分享",
+    "C": "AI 导出帧 截图 教学"
+  },
+  "1238": {
+    "idx": 1238,
+    "A": "软件 抽帧 截图 技巧",
+    "B": "视频抽帧截图软件的使用技巧",
+    "C": "软件 导出帧 截屏 教学"
+  },
+  "1239": {
+    "idx": 1239,
+    "A": "在线 抽帧 截图 技巧",
+    "B": "在线视频抽帧截图的技巧有哪些",
+    "C": "网页版 怎么抽帧 屏幕截图 怎么做"
+  },
+  "1240": {
+    "idx": 1240,
+    "A": "代码 抽帧 截图 技巧",
+    "B": "视频抽帧截图的代码实现技巧",
+    "C": "命令行 抽帧 截屏 教程"
+  },
+  "1241": {
+    "idx": 1241,
+    "A": "插件 抽帧 截图 技巧",
+    "B": "视频抽帧截图插件的使用技巧",
+    "C": "插件 怎么抽帧 截图 方法"
+  },
+  "1242": {
+    "idx": 1242,
+    "A": "识别 截图 教程",
+    "B": "截图文字识别的详细教程",
+    "C": "提取文字 截图 怎么做"
+  },
+  "1243": {
+    "idx": 1243,
+    "A": "AI 识别 截图 教程",
+    "B": "如何用智能技术识别截图内容",
+    "C": "AI 提取文字 屏幕截图 步骤"
+  },
+  "1244": {
+    "idx": 1244,
+    "A": "软件 识别 截图 教程",
+    "B": "截图识别文字的软件教程",
+    "C": "电脑端 OCR 截屏 方法"
+  },
+  "1245": {
+    "idx": 1245,
+    "A": "在线 识别 截图 教程",
+    "B": "在线截图识别文字怎么弄",
+    "C": "在线 转录 屏幕截图 步骤"
+  },
+  "1246": {
+    "idx": 1246,
+    "A": "代码 识别 截图 教程",
+    "B": "如何用代码实现截图识别",
+    "C": "代码 识别 截图 教学"
+  },
+  "1247": {
+    "idx": 1247,
+    "A": "插件 识别 截图 教程",
+    "B": "截图识别文字的插件使用教程",
+    "C": "插件 识别 截图 流程"
+  },
+  "1248": {
+    "idx": 1248,
+    "A": "识别 截图 工具",
+    "B": "有什么好用的截图识别工具",
+    "C": "提取文字 屏幕截图 教程"
+  },
+  "1249": {
+    "idx": 1249,
+    "A": "AI 识别 截图 工具",
+    "B": "智能截图识别工具推荐",
+    "C": "AI 检测 截屏 流程"
+  },
+  "1250": {
+    "idx": 1250,
+    "A": "软件 识别 截图 工具",
+    "B": "截图识别文字的软件有哪些",
+    "C": "电脑端 检测 屏幕截图 教程"
+  },
+  "1251": {
+    "idx": 1251,
+    "A": "在线 识别 截图 工具",
+    "B": "在线截图识别工具怎么用",
+    "C": "网页版 OCR 截图 步骤"
+  },
+  "1252": {
+    "idx": 1252,
+    "A": "代码 识别 截图 工具",
+    "B": "实现截图识别的代码工具",
+    "C": "代码 识别 屏幕截图 教学"
+  },
+  "1253": {
+    "idx": 1253,
+    "A": "插件 识别 截图 工具",
+    "B": "好用的截图识别插件推荐",
+    "C": "插件 检测 屏幕截图 教学"
+  },
+  "1254": {
+    "idx": 1254,
+    "A": "识别 截图 技巧",
+    "B": "截图识别文字有哪些技巧",
+    "C": "识别 截屏 教程"
+  },
+  "1255": {
+    "idx": 1255,
+    "A": "AI 识别 截图 技巧",
+    "B": "智能截图识别的实用技巧",
+    "C": "AI 检测 屏幕截图 教程"
+  },
+  "1256": {
+    "idx": 1256,
+    "A": "软件 识别 截图 技巧",
+    "B": "有什么好用的截图识别软件技巧",
+    "C": "软件 转录 截图 方法"
+  },
+  "1257": {
+    "idx": 1257,
+    "A": "在线 识别 截图 技巧",
+    "B": "怎么在线识别截图里的内容",
+    "C": "网页版 识别 截图 教学"
+  },
+  "1258": {
+    "idx": 1258,
+    "A": "代码 识别 截图 技巧",
+    "B": "如何通过代码识别截图信息",
+    "C": "命令行 识别 屏幕截图 教学"
+  },
+  "1259": {
+    "idx": 1259,
+    "A": "插件 识别 截图 技巧",
+    "B": "有哪些识别截图的浏览器插件",
+    "C": "插件 提取文字 截图 流程"
+  },
+  "1260": {
+    "idx": 1260,
+    "A": "抹除 截图 教程",
+    "B": "截图里多余的东西怎么抹掉",
+    "C": "抹除 截图 教学"
+  },
+  "1261": {
+    "idx": 1261,
+    "A": "AI 抹除 截图 教程",
+    "B": "如何用人工智能抹除截图里的杂物",
+    "C": "AI 去除 屏幕截图 步骤"
+  },
+  "1262": {
+    "idx": 1262,
+    "A": "软件 抹除 截图 教程",
+    "B": "有没有能抹除截图内容的软件",
+    "C": "电脑端 去掉 屏幕截图 流程"
+  },
+  "1263": {
+    "idx": 1263,
+    "A": "在线 抹除 截图 教程",
+    "B": "在线抹除截图里多余元素的教程",
+    "C": "在线 去除 截屏 方法"
+  },
+  "1264": {
+    "idx": 1264,
+    "A": "代码 抹除 截图 教程",
+    "B": "怎么用代码实现截图抹除功能",
+    "C": "代码 消除 截屏 流程"
+  },
+  "1265": {
+    "idx": 1265,
+    "A": "插件 抹除 截图 教程",
+    "B": "好用的截图抹除插件有哪些",
+    "C": "插件 怎么去掉 截屏 流程"
+  },
+  "1266": {
+    "idx": 1266,
+    "A": "抹除 截图 工具",
+    "B": "有什么好用的截图抹除工具",
+    "C": "去掉 屏幕截图 方法"
+  },
+  "1267": {
+    "idx": 1267,
+    "A": "AI 抹除 截图 工具",
+    "B": "有没有智能抹除截图的工具",
+    "C": "AI 去掉 截图 教程"
+  },
+  "1268": {
+    "idx": 1268,
+    "A": "软件 抹除 截图 工具",
+    "B": "好用的截图抹除软件推荐",
+    "C": "软件 去除 截屏 教学"
+  },
+  "1269": {
+    "idx": 1269,
+    "A": "在线 抹除 截图 工具",
+    "B": "在线抹除截图内容的工具哪个好用",
+    "C": "网页版 怎么去掉 屏幕截图 步骤"
+  },
+  "1270": {
+    "idx": 1270,
+    "A": "代码 抹除 截图 工具",
+    "B": "有没有能抹除截图的代码工具",
+    "C": "代码 去掉 屏幕截图 教学"
+  },
+  "1271": {
+    "idx": 1271,
+    "A": "插件 抹除 截图 工具",
+    "B": "好用的截图抹除插件推荐",
+    "C": "插件 去掉 截屏 方法"
+  },
+  "1272": {
+    "idx": 1272,
+    "A": "抹除 截图 技巧",
+    "B": "怎么把截图里不需要的部分去掉",
+    "C": "消除 截屏 方法"
+  },
+  "1273": {
+    "idx": 1273,
+    "A": "AI 抹除 截图 技巧",
+    "B": "如何用智能技术快速抹除截图",
+    "C": "AI 去除 截屏 步骤"
+  },
+  "1274": {
+    "idx": 1274,
+    "A": "软件 抹除 截图 技巧",
+    "B": "有什么好用的截图抹除操作技巧",
+    "C": "软件 消除 截屏 方法"
+  },
+  "1275": {
+    "idx": 1275,
+    "A": "在线 抹除 截图 技巧",
+    "B": "在线抹除截图杂物的操作技巧",
+    "C": "在线 抹除 屏幕截图 教学"
+  },
+  "1276": {
+    "idx": 1276,
+    "A": "代码 抹除 截图 技巧",
+    "B": "如何通过代码技巧抹除截图内容",
+    "C": "代码 去掉 屏幕截图 怎么做"
+  },
+  "1277": {
+    "idx": 1277,
+    "A": "插件 抹除 截图 技巧",
+    "B": "使用插件抹除截图的技巧",
+    "C": "插件 去掉 屏幕截图 教学"
+  },
+  "1278": {
+    "idx": 1278,
+    "A": "风格化 截图 教程",
+    "B": "怎么给截图做风格化处理",
+    "C": "风格化 截屏 教程"
+  },
+  "1279": {
+    "idx": 1279,
+    "A": "AI 风格化 截图 教程",
+    "B": "如何用人工智能给截图添加风格",
+    "C": "AI 风格迁移 截图 怎么做"
+  },
+  "1280": {
+    "idx": 1280,
+    "A": "软件 风格化 截图 教程",
+    "B": "有没有给截图做风格化的软件",
+    "C": "电脑端 风格迁移 截屏 教学"
+  },
+  "1282": {
+    "idx": 1282,
+    "A": "代码 风格化 截图 教程",
+    "B": "怎么用代码给截图添加独特风格",
+    "C": "代码 怎么转风格 截图 教程"
+  },
+  "1283": {
+    "idx": 1283,
+    "A": "插件 风格化 截图 教程",
+    "B": "好用的截图风格化插件有哪些",
+    "C": "插件 风格化 屏幕截图 流程"
+  },
+  "1284": {
+    "idx": 1284,
+    "A": "风格化 截图 工具",
+    "B": "有什么好用的截图风格化工具",
+    "C": "风格化 截图 怎么做"
+  },
+  "1285": {
+    "idx": 1285,
+    "A": "AI 风格化 截图 工具",
+    "B": "有没有智能风格化截图的工具",
+    "C": "AI 怎么转风格 屏幕截图 教学"
+  },
+  "1286": {
+    "idx": 1286,
+    "A": "软件 风格化 截图 工具",
+    "B": "好用的截图风格化软件推荐",
+    "C": "电脑端 风格化 截屏 方法"
+  },
+  "1287": {
+    "idx": 1287,
+    "A": "在线 风格化 截图 工具",
+    "B": "在线给截图做风格化的工具",
+    "C": "在线 风格迁移 截图 步骤"
+  },
+  "1288": {
+    "idx": 1288,
+    "A": "代码 风格化 截图 工具",
+    "B": "有没有能实现截图风格化的代码工具",
+    "C": "代码 转风格 截图 方法"
+  },
+  "1289": {
+    "idx": 1289,
+    "A": "插件 风格化 截图 工具",
+    "B": "好用的截图风格化插件推荐",
+    "C": "插件 怎么转风格 截屏 教学"
+  },
+  "1290": {
+    "idx": 1290,
+    "A": "风格化 截图 技巧",
+    "B": "如何提升截图的风格化效果",
+    "C": "风格化 屏幕截图 教学"
+  },
+  "1291": {
+    "idx": 1291,
+    "A": "AI 风格化 截图 技巧",
+    "B": "用智能技术优化截图风格的技巧",
+    "C": "AI 转风格 截图 流程"
+  },
+  "1292": {
+    "idx": 1292,
+    "A": "软件 风格化 截图 技巧",
+    "B": "怎么用软件给截图做风格化处理",
+    "C": "软件 怎么转风格 截图 怎么做"
+  },
+  "1294": {
+    "idx": 1294,
+    "A": "代码 风格化 截图 技巧",
+    "B": "如何通过代码实现截图风格化",
+    "C": "代码 风格迁移 截屏 教学"
+  },
+  "1295": {
+    "idx": 1295,
+    "A": "插件 风格化 截图 技巧",
+    "B": "使用插件进行截图风格化的技巧",
+    "C": "插件 风格化 截图 教学"
+  },
+  "1296": {
+    "idx": 1296,
+    "A": "调整 截图 教程",
+    "B": "如何调整截图的画面效果",
+    "C": "调 截屏 教程"
+  },
+  "1297": {
+    "idx": 1297,
+    "A": "AI 调整 截图 教程",
+    "B": "怎么用人工智能自动调整截图",
+    "C": "AI 优化 屏幕截图 方法"
+  },
+  "1298": {
+    "idx": 1298,
+    "A": "软件 调整 截图 教程",
+    "B": "怎么用软件调整截图的教程",
+    "C": "电脑端 调 屏幕截图 流程"
+  },
+  "1299": {
+    "idx": 1299,
+    "A": "在线 调整 截图 教程",
+    "B": "在线调整截图的操作方法",
+    "C": "网页版 调整 截图 步骤"
+  },
+  "1300": {
+    "idx": 1300,
+    "A": "代码 调整 截图 教程",
+    "B": "如何通过代码调整截图的教程",
+    "C": "命令行 怎么调 截屏 教程"
+  },
+  "1301": {
+    "idx": 1301,
+    "A": "插件 调整 截图 教程",
+    "B": "有什么插件可以调整截图",
+    "C": "插件 调整 屏幕截图 怎么做"
+  },
+  "1302": {
+    "idx": 1302,
+    "A": "调整 截图 工具",
+    "B": "调整截图用什么工具比较好",
+    "C": "怎么调 截图 怎么做"
+  },
+  "1303": {
+    "idx": 1303,
+    "A": "AI 调整 截图 工具",
+    "B": "智能调整截图画面的工具推荐",
+    "C": "AI 怎么调 截图 步骤"
+  },
+  "1304": {
+    "idx": 1304,
+    "A": "软件 调整 截图 工具",
+    "B": "调整截图的电脑软件有哪些",
+    "C": "软件 调整 截图 教学"
+  },
+  "1305": {
+    "idx": 1305,
+    "A": "在线 调整 截图 工具",
+    "B": "好用的在线调整截图工具",
+    "C": "在线 调整 截图 流程"
+  },
+  "1306": {
+    "idx": 1306,
+    "A": "代码 调整 截图 工具",
+    "B": "通过代码调整截图的工具",
+    "C": "代码 优化 屏幕截图 怎么做"
+  },
+  "1307": {
+    "idx": 1307,
+    "A": "插件 调整 截图 工具",
+    "B": "调整截图的浏览器插件推荐",
+    "C": "插件 调 截图 方法"
+  },
+  "1308": {
+    "idx": 1308,
+    "A": "调整 截图 技巧",
+    "B": "调整截图有哪些实用技巧",
+    "C": "优化 截图 步骤"
+  },
+  "1309": {
+    "idx": 1309,
+    "A": "AI 调整 截图 技巧",
+    "B": "利用智能技术调整截图的技巧",
+    "C": "AI 优化 截屏 步骤"
+  },
+  "1310": {
+    "idx": 1310,
+    "A": "软件 调整 截图 技巧",
+    "B": "用软件调整截图的进阶技巧",
+    "C": "电脑端 调整 截屏 步骤"
+  },
+  "1311": {
+    "idx": 1311,
+    "A": "在线 调整 截图 技巧",
+    "B": "在线调整截图的实用小技巧",
+    "C": "在线 调整 截图 流程"
+  },
+  "1312": {
+    "idx": 1312,
+    "A": "代码 调整 截图 技巧",
+    "B": "写代码调整截图的方法技巧",
+    "C": "代码 优化 截图 怎么做"
+  },
+  "1313": {
+    "idx": 1313,
+    "A": "插件 调整 截图 技巧",
+    "B": "使用插件调整截图的技巧分享",
+    "C": "插件 怎么调 屏幕截图 教程"
+  },
+  "1314": {
+    "idx": 1314,
+    "A": "增强 截图 教程",
+    "B": "怎么增强截图清晰度的教程",
+    "C": "超分 屏幕截图 教程"
+  },
+  "1315": {
+    "idx": 1315,
+    "A": "AI 增强 截图 教程",
+    "B": "如何用智能技术增强截图效果",
+    "C": "AI 提升画质 屏幕截图 方法"
+  },
+  "1316": {
+    "idx": 1316,
+    "A": "软件 增强 截图 教程",
+    "B": "用软件增强截图画质的教程",
+    "C": "电脑端 超分 截图 怎么做"
+  },
+  "1317": {
+    "idx": 1317,
+    "A": "在线 增强 截图 教程",
+    "B": "在线增强截图清晰度的方法",
+    "C": "网页版 超分 屏幕截图 流程"
+  },
+  "1318": {
+    "idx": 1318,
+    "A": "代码 增强 截图 教程",
+    "B": "通过代码增强截图效果的教程",
+    "C": "代码 提升画质 截图 怎么做"
+  },
+  "1319": {
+    "idx": 1319,
+    "A": "插件 增强 截图 教程",
+    "B": "有什么插件可以增强截图画质",
+    "C": "插件 提升画质 截屏 步骤"
+  },
+  "1320": {
+    "idx": 1320,
+    "A": "增强 截图 工具",
+    "B": "增强截图清晰度的工具推荐",
+    "C": "增强 屏幕截图 教程"
+  },
+  "1321": {
+    "idx": 1321,
+    "A": "AI 增强 截图 工具",
+    "B": "智能增强截图画质的工具",
+    "C": "AI 怎么增强 截图 流程"
+  },
+  "1322": {
+    "idx": 1322,
+    "A": "软件 增强 截图 工具",
+    "B": "增强截图画质的电脑软件",
+    "C": "软件 修复 屏幕截图 教程"
+  },
+  "1323": {
+    "idx": 1323,
+    "A": "在线 增强 截图 工具",
+    "B": "在线增强截图效果的工具",
+    "C": "在线 怎么增强 截图 教程"
+  },
+  "1324": {
+    "idx": 1324,
+    "A": "代码 增强 截图 工具",
+    "B": "写代码增强截图画质的工具",
+    "C": "代码 超分 屏幕截图 教学"
+  },
+  "1325": {
+    "idx": 1325,
+    "A": "插件 增强 截图 工具",
+    "B": "增强截图效果的插件推荐",
+    "C": "插件 修复 截屏 教程"
+  },
+  "1326": {
+    "idx": 1326,
+    "A": "增强 截图 技巧",
+    "B": "增强截图画质的实用技巧",
+    "C": "超分 截图 方法"
+  },
+  "1327": {
+    "idx": 1327,
+    "A": "AI 增强 截图 技巧",
+    "B": "智能增强截图效果的技巧",
+    "C": "AI 修复 截图 方法"
+  },
+  "1328": {
+    "idx": 1328,
+    "A": "软件 增强 截图 技巧",
+    "B": "用软件增强截图画质的技巧",
+    "C": "软件 修复 截屏 流程"
+  },
+  "1329": {
+    "idx": 1329,
+    "A": "在线 增强 截图 技巧",
+    "B": "在线增强截图效果的技巧",
+    "C": "在线 怎么增强 屏幕截图 步骤"
+  },
+  "1330": {
+    "idx": 1330,
+    "A": "代码 增强 截图 技巧",
+    "B": "通过代码增强截图的技巧",
+    "C": "命令行 怎么增强 屏幕截图 怎么做"
+  },
+  "1331": {
+    "idx": 1331,
+    "A": "插件 增强 截图 技巧",
+    "B": "使用插件增强截图的技巧",
+    "C": "插件 提升画质 截图 流程"
+  },
+  "1332": {
+    "idx": 1332,
+    "A": "裁切 视频片段 教程",
+    "B": "视频片段怎么裁切的教程",
+    "C": "截取 视频片段 流程"
+  },
+  "1333": {
+    "idx": 1333,
+    "A": "AI 裁切 视频片段 教程",
+    "B": "智能裁切视频片段的教程",
+    "C": "AI 截取 clip 怎么做"
+  },
+  "1334": {
+    "idx": 1334,
+    "A": "软件 裁切 视频片段 教程",
+    "B": "用软件裁切视频片段的教程",
+    "C": "电脑端 切片 视频片段 方法"
+  },
+  "1335": {
+    "idx": 1335,
+    "A": "在线 裁切 视频片段 教程",
+    "B": "在线裁切视频片段的操作方法",
+    "C": "网页版 截取 clip 步骤"
+  },
+  "1336": {
+    "idx": 1336,
+    "A": "代码 裁切 视频片段 教程",
+    "B": "如何通过代码裁切视频片段",
+    "C": "命令行 怎么裁 视频片段 教程"
+  },
+  "1337": {
+    "idx": 1337,
+    "A": "插件 裁切 视频片段 教程",
+    "B": "有什么插件可以裁切视频片段",
+    "C": "插件 怎么裁 视频片段 流程"
+  },
+  "1338": {
+    "idx": 1338,
+    "A": "裁切 视频片段 工具",
+    "B": "怎么裁剪视频片段",
+    "C": "怎么裁 片段 教程"
+  },
+  "1339": {
+    "idx": 1339,
+    "A": "AI 裁切 视频片段 工具",
+    "B": "有什么智能裁剪视频片段的工具",
+    "C": "AI 怎么裁 clip 方法"
+  },
+  "1340": {
+    "idx": 1340,
+    "A": "软件 裁切 视频片段 工具",
+    "B": "裁剪视频片段用什么软件好",
+    "C": "软件 怎么裁 素材 流程"
+  },
+  "1341": {
+    "idx": 1341,
+    "A": "在线 裁切 视频片段 工具",
+    "B": "在线裁剪视频片段的方法",
+    "C": "在线 切片 clip 方法"
+  },
+  "1342": {
+    "idx": 1342,
+    "A": "代码 裁切 视频片段 工具",
+    "B": "如何用代码裁剪视频片段",
+    "C": "代码 裁剪 clip 教程"
+  },
+  "1343": {
+    "idx": 1343,
+    "A": "插件 裁切 视频片段 工具",
+    "B": "裁剪视频片段的插件有哪些",
+    "C": "插件 裁剪 视频片段 教程"
+  },
+  "1344": {
+    "idx": 1344,
+    "A": "裁切 视频片段 技巧",
+    "B": "裁剪视频片段有哪些实用技巧",
+    "C": "截取 片段 流程"
+  },
+  "1345": {
+    "idx": 1345,
+    "A": "AI 裁切 视频片段 技巧",
+    "B": "利用人工智能裁剪视频片段的技巧",
+    "C": "AI 怎么裁 视频片段 方法"
+  },
+  "1346": {
+    "idx": 1346,
+    "A": "软件 裁切 视频片段 技巧",
+    "B": "使用软件裁剪视频片段的技巧",
+    "C": "电脑端 裁剪 视频片段 教程"
+  },
+  "1347": {
+    "idx": 1347,
+    "A": "在线 裁切 视频片段 技巧",
+    "B": "在线裁剪视频片段的操作技巧",
+    "C": "在线 切片 片段 教程"
+  },
+  "1348": {
+    "idx": 1348,
+    "A": "代码 裁切 视频片段 技巧",
+    "B": "通过代码裁剪视频片段的技巧",
+    "C": "命令行 裁剪 视频片段 怎么做"
+  },
+  "1349": {
+    "idx": 1349,
+    "A": "插件 裁切 视频片段 技巧",
+    "B": "使用插件裁剪视频片段的技巧",
+    "C": "插件 截取 clip 教学"
+  },
+  "1350": {
+    "idx": 1350,
+    "A": "抠取 视频片段 教程",
+    "B": "视频片段抠图教程",
+    "C": "怎么抠 clip 教程"
+  },
+  "1351": {
+    "idx": 1351,
+    "A": "AI 抠取 视频片段 教程",
+    "B": "怎么用智能工具抠取视频片段",
+    "C": "AI 怎么抠 片段 步骤"
+  },
+  "1352": {
+    "idx": 1352,
+    "A": "软件 抠取 视频片段 教程",
+    "B": "抠取视频片段的软件教程",
+    "C": "软件 抠 素材 步骤"
+  },
+  "1353": {
+    "idx": 1353,
+    "A": "在线 抠取 视频片段 教程",
+    "B": "在线抠取视频片段的教程",
+    "C": "网页版 抠 视频片段 方法"
+  },
+  "1355": {
+    "idx": 1355,
+    "A": "插件 抠取 视频片段 教程",
+    "B": "抠取视频片段的插件使用教程",
+    "C": "插件 分割 clip 怎么做"
+  },
+  "1356": {
+    "idx": 1356,
+    "A": "抠取 视频片段 工具",
+    "B": "抠取视频片段用什么工具",
+    "C": "怎么抠 视频片段 教程"
+  },
+  "1357": {
+    "idx": 1357,
+    "A": "AI 抠取 视频片段 工具",
+    "B": "智能抠取视频片段的工具",
+    "C": "AI 怎么抠 片段 怎么做"
+  },
+  "1358": {
+    "idx": 1358,
+    "A": "软件 抠取 视频片段 工具",
+    "B": "抠取视频片段的软件推荐",
+    "C": "软件 抠 视频片段 怎么做"
+  },
+  "1359": {
+    "idx": 1359,
+    "A": "在线 抠取 视频片段 工具",
+    "B": "在线抠取视频片段的工具",
+    "C": "网页版 怎么抠 clip 步骤"
+  },
+  "1360": {
+    "idx": 1360,
+    "A": "代码 抠取 视频片段 工具",
+    "B": "如何用代码实现视频片段抠取",
+    "C": "命令行 怎么抠 素材 流程"
+  },
+  "1361": {
+    "idx": 1361,
+    "A": "插件 抠取 视频片段 工具",
+    "B": "抠取视频片段的插件工具",
+    "C": "插件 分割 片段 教程"
+  },
+  "1362": {
+    "idx": 1362,
+    "A": "抠取 视频片段 技巧",
+    "B": "抠取视频片段有什么技巧",
+    "C": "分割 视频片段 怎么做"
+  },
+  "1363": {
+    "idx": 1363,
+    "A": "AI 抠取 视频片段 技巧",
+    "B": "智能抠取视频片段的技巧",
+    "C": "AI 抠 片段 教程"
+  },
+  "1364": {
+    "idx": 1364,
+    "A": "软件 抠取 视频片段 技巧",
+    "B": "用软件抠取视频片段的技巧",
+    "C": "软件 抠 素材 方法"
+  },
+  "1365": {
+    "idx": 1365,
+    "A": "在线 抠取 视频片段 技巧",
+    "B": "在线抠取视频片段的技巧",
+    "C": "在线 抠 clip 步骤"
+  },
+  "1367": {
+    "idx": 1367,
+    "A": "插件 抠取 视频片段 技巧",
+    "B": "使用插件抠取视频片段的技巧",
+    "C": "插件 抠 片段 方法"
+  },
+  "1368": {
+    "idx": 1368,
+    "A": "风格化 视频片段 教程",
+    "B": "视频片段风格化处理教程",
+    "C": "风格迁移 素材 方法"
+  },
+  "1369": {
+    "idx": 1369,
+    "A": "AI 风格化 视频片段 教程",
+    "B": "怎么用智能技术给视频片段做风格化",
+    "C": "AI 风格迁移 片段 方法"
+  },
+  "1370": {
+    "idx": 1370,
+    "A": "软件 风格化 视频片段 教程",
+    "B": "视频片段风格化处理软件教程",
+    "C": "软件 怎么转风格 素材 流程"
+  },
+  "1371": {
+    "idx": 1371,
+    "A": "在线 风格化 视频片段 教程",
+    "B": "在线给视频片段做风格化的教程",
+    "C": "网页版 风格化 视频片段 教程"
+  },
+  "1372": {
+    "idx": 1372,
+    "A": "代码 风格化 视频片段 教程",
+    "B": "如何用代码实现视频片段风格化",
+    "C": "代码 转风格 视频片段 方法"
+  },
+  "1373": {
+    "idx": 1373,
+    "A": "插件 风格化 视频片段 教程",
+    "B": "视频片段风格化插件教程",
+    "C": "插件 风格化 素材 方法"
+  },
+  "1374": {
+    "idx": 1374,
+    "A": "风格化 视频片段 工具",
+    "B": "视频片段风格化处理工具",
+    "C": "转风格 片段 步骤"
+  },
+  "1375": {
+    "idx": 1375,
+    "A": "AI 风格化 视频片段 工具",
+    "B": "智能视频片段风格化工具",
+    "C": "AI 风格迁移 视频片段 教程"
+  },
+  "1376": {
+    "idx": 1376,
+    "A": "软件 风格化 视频片段 工具",
+    "B": "视频片段风格化软件",
+    "C": "软件 转风格 视频片段 方法"
+  },
+  "1377": {
+    "idx": 1377,
+    "A": "在线 风格化 视频片段 工具",
+    "B": "在线视频片段风格化工具",
+    "C": "网页版 风格化 素材 教学"
+  },
+  "1378": {
+    "idx": 1378,
+    "A": "代码 风格化 视频片段 工具",
+    "B": "视频片段风格化代码实现",
+    "C": "命令行 风格化 素材 步骤"
+  },
+  "1379": {
+    "idx": 1379,
+    "A": "插件 风格化 视频片段 工具",
+    "B": "视频片段风格化插件",
+    "C": "插件 转风格 片段 教学"
+  },
+  "1380": {
+    "idx": 1380,
+    "A": "风格化 视频片段 技巧",
+    "B": "如何给视频片段添加风格化效果",
+    "C": "怎么转风格 clip 教学"
+  },
+  "1381": {
+    "idx": 1381,
+    "A": "AI 风格化 视频片段 技巧",
+    "B": "怎样利用人工智能给视频片段做风格化处理",
+    "C": "AI 转风格 素材 流程"
+  },
+  "1382": {
+    "idx": 1382,
+    "A": "软件 风格化 视频片段 技巧",
+    "B": "有哪些给视频片段做风格化的软件技巧",
+    "C": "软件 怎么转风格 素材 教学"
+  },
+  "1383": {
+    "idx": 1383,
+    "A": "在线 风格化 视频片段 技巧",
+    "B": "在线给视频片段添加风格化的方法",
+    "C": "网页版 转风格 片段 教学"
+  },
+  "1384": {
+    "idx": 1384,
+    "A": "代码 风格化 视频片段 技巧",
+    "B": "通过代码实现视频片段风格化的技巧",
+    "C": "代码 怎么转风格 视频片段 流程"
+  },
+  "1385": {
+    "idx": 1385,
+    "A": "插件 风格化 视频片段 技巧",
+    "B": "有哪些给视频片段做风格化的插件用法",
+    "C": "插件 转风格 视频片段 怎么做"
+  },
+  "1386": {
+    "idx": 1386,
+    "A": "增强 视频片段 教程",
+    "B": "视频片段画质增强的教程",
+    "C": "提升画质 素材 教学"
+  },
+  "1387": {
+    "idx": 1387,
+    "A": "AI 增强 视频片段 教程",
+    "B": "如何用人工智能增强视频片段画质",
+    "C": "AI 提升画质 素材 步骤"
+  },
+  "1388": {
+    "idx": 1388,
+    "A": "软件 增强 视频片段 教程",
+    "B": "有什么增强视频片段画质的软件教程",
+    "C": "软件 增强 素材 怎么做"
+  },
+  "1389": {
+    "idx": 1389,
+    "A": "在线 增强 视频片段 教程",
+    "B": "在线增强视频片段画质的教程",
+    "C": "在线 怎么增强 片段 流程"
+  },
+  "1390": {
+    "idx": 1390,
+    "A": "代码 增强 视频片段 教程",
+    "B": "如何通过代码增强视频片段画质",
+    "C": "代码 怎么增强 素材 教程"
+  },
+  "1391": {
+    "idx": 1391,
+    "A": "插件 增强 视频片段 教程",
+    "B": "增强视频片段画质的插件使用教程",
+    "C": "插件 增强 clip 怎么做"
+  },
+  "1392": {
+    "idx": 1392,
+    "A": "增强 视频片段 工具",
+    "B": "有哪些增强视频片段画质的工具",
+    "C": "修复 片段 怎么做"
+  },
+  "1393": {
+    "idx": 1393,
+    "A": "AI 增强 视频片段 工具",
+    "B": "好用的视频画质增强人工智能工具",
+    "C": "AI 修复 素材 方法"
+  },
+  "1394": {
+    "idx": 1394,
+    "A": "软件 增强 视频片段 工具",
+    "B": "增强视频片段画质的软件推荐",
+    "C": "电脑端 增强 clip 方法"
+  },
+  "1395": {
+    "idx": 1395,
+    "A": "在线 增强 视频片段 工具",
+    "B": "在线增强视频片段画质的工具",
+    "C": "在线 提升画质 clip 教程"
+  },
+  "1396": {
+    "idx": 1396,
+    "A": "代码 增强 视频片段 工具",
+    "B": "增强视频片段画质的代码工具",
+    "C": "代码 怎么增强 视频片段 步骤"
+  },
+  "1397": {
+    "idx": 1397,
+    "A": "插件 增强 视频片段 工具",
+    "B": "增强视频片段画质的插件工具",
+    "C": "插件 增强 视频片段 步骤"
+  },
+  "1398": {
+    "idx": 1398,
+    "A": "增强 视频片段 技巧",
+    "B": "视频片段画质增强的实用技巧",
+    "C": "提升画质 clip 流程"
+  },
+  "1399": {
+    "idx": 1399,
+    "A": "AI 增强 视频片段 技巧",
+    "B": "利用人工智能增强视频画质的技巧",
+    "C": "AI 超分 视频片段 步骤"
+  },
+  "1400": {
+    "idx": 1400,
+    "A": "软件 增强 视频片段 技巧",
+    "B": "增强视频片段画质的软件操作技巧",
+    "C": "电脑端 增强 clip 教学"
+  },
+  "1401": {
+    "idx": 1401,
+    "A": "在线 增强 视频片段 技巧",
+    "B": "在线增强视频片段画质的技巧",
+    "C": "在线 超分 clip 流程"
+  },
+  "1402": {
+    "idx": 1402,
+    "A": "代码 增强 视频片段 技巧",
+    "B": "通过代码增强视频片段画质的技巧",
+    "C": "代码 增强 素材 流程"
+  },
+  "1403": {
+    "idx": 1403,
+    "A": "插件 增强 视频片段 技巧",
+    "B": "增强视频片段画质的插件技巧",
+    "C": "插件 修复 素材 教学"
+  },
+  "1404": {
+    "idx": 1404,
+    "A": "添加 转场片段 教程",
+    "B": "视频片段添加转场的教程",
+    "C": "怎么加 转场素材 流程"
+  },
+  "1405": {
+    "idx": 1405,
+    "A": "AI 添加 转场片段 教程",
+    "B": "如何用人工智能给视频片段添加转场",
+    "C": "AI 添加 转场素材 方法"
+  },
+  "1406": {
+    "idx": 1406,
+    "A": "软件 添加 转场片段 教程",
+    "B": "给视频片段添加转场的软件教程",
+    "C": "电脑端 加 转场片段 步骤"
+  },
+  "1407": {
+    "idx": 1407,
+    "A": "在线 添加 转场片段 教程",
+    "B": "在线给视频片段添加转场的教程",
+    "C": "在线 加上 转场片段 步骤"
+  },
+  "1408": {
+    "idx": 1408,
+    "A": "代码 添加 转场片段 教程",
+    "B": "如何用代码给视频片段添加转场",
+    "C": "命令行 加 转场片段 教程"
+  },
+  "1409": {
+    "idx": 1409,
+    "A": "插件 添加 转场片段 教程",
+    "B": "给视频片段添加转场的插件教程",
+    "C": "插件 加 转场素材 教程"
+  },
+  "1410": {
+    "idx": 1410,
+    "A": "添加 转场片段 工具",
+    "B": "有哪些给视频片段添加转场的工具",
+    "C": "加上 转场片段 步骤"
+  },
+  "1411": {
+    "idx": 1411,
+    "A": "AI 添加 转场片段 工具",
+    "B": "好用的视频转场人工智能工具",
+    "C": "AI 加上 转场素材 教学"
+  },
+  "1412": {
+    "idx": 1412,
+    "A": "软件 添加 转场片段 工具",
+    "B": "给视频片段添加转场的软件工具",
+    "C": "电脑端 添加 转场素材 流程"
+  },
+  "1413": {
+    "idx": 1413,
+    "A": "在线 添加 转场片段 工具",
+    "B": "在线给视频片段添加转场的工具",
+    "C": "网页版 加上 转场素材 流程"
+  },
+  "1414": {
+    "idx": 1414,
+    "A": "代码 添加 转场片段 工具",
+    "B": "给视频片段添加转场的代码工具",
+    "C": "命令行 添加 转场素材 怎么做"
+  },
+  "1415": {
+    "idx": 1415,
+    "A": "插件 添加 转场片段 工具",
+    "B": "给视频片段添加转场的插件工具",
+    "C": "插件 怎么加 转场片段 步骤"
+  },
+  "1416": {
+    "idx": 1416,
+    "A": "添加 转场片段 技巧",
+    "B": "视频片段添加转场的技巧",
+    "C": "添加 转场片段 教学"
+  },
+  "1417": {
+    "idx": 1417,
+    "A": "AI 添加 转场片段 技巧",
+    "B": "利用人工智能添加视频转场的技巧",
+    "C": "AI 添加 转场素材 方法"
+  },
+  "1418": {
+    "idx": 1418,
+    "A": "软件 添加 转场片段 技巧",
+    "B": "给视频片段添加转场的软件技巧",
+    "C": "电脑端 加 转场片段 怎么做"
+  },
+  "1419": {
+    "idx": 1419,
+    "A": "在线 添加 转场片段 技巧",
+    "B": "在线给视频片段添加转场的技巧",
+    "C": "网页版 加上 转场片段 怎么做"
+  },
+  "1420": {
+    "idx": 1420,
+    "A": "代码 添加 转场片段 技巧",
+    "B": "如何通过代码实现视频转场效果",
+    "C": "命令行 添加 转场素材 教学"
+  },
+  "1421": {
+    "idx": 1421,
+    "A": "插件 添加 转场片段 技巧",
+    "B": "有哪些添加转场片段的插件使用技巧",
+    "C": "插件 加 转场片段 怎么做"
+  },
+  "1422": {
+    "idx": 1422,
+    "A": "抠取 关键帧 教程",
+    "B": "视频抠取关键帧的详细教程",
+    "C": "抠 关键帧 流程"
+  },
+  "1423": {
+    "idx": 1423,
+    "A": "AI 抠取 关键帧 教程",
+    "B": "怎样利用智能技术抠取关键帧",
+    "C": "AI 抠 关键帧 怎么做"
+  },
+  "1424": {
+    "idx": 1424,
+    "A": "软件 抠取 关键帧 教程",
+    "B": "用什么软件可以抠取关键帧",
+    "C": "软件 怎么抠 关键帧 教学"
+  },
+  "1425": {
+    "idx": 1425,
+    "A": "在线 抠取 关键帧 教程",
+    "B": "有没有在线抠取关键帧的方法",
+    "C": "在线 分割 帧 教学"
+  },
+  "1426": {
+    "idx": 1426,
+    "A": "代码 抠取 关键帧 教程",
+    "B": "如何编写代码来抠取关键帧",
+    "C": "代码 抠图 帧 方法"
+  },
+  "1428": {
+    "idx": 1428,
+    "A": "抠取 关键帧 工具",
+    "B": "抠取关键帧有哪些好用的工具",
+    "C": "怎么抠 视频帧 步骤"
+  },
+  "1429": {
+    "idx": 1429,
+    "A": "AI 抠取 关键帧 工具",
+    "B": "有哪些智能抠取关键帧的工具",
+    "C": "AI 怎么抠 关键帧 教学"
+  },
+  "1430": {
+    "idx": 1430,
+    "A": "软件 抠取 关键帧 工具",
+    "B": "求推荐好用的抠取关键帧软件",
+    "C": "电脑端 抠图 帧 流程"
+  },
+  "1431": {
+    "idx": 1431,
+    "A": "在线 抠取 关键帧 工具",
+    "B": "哪里有在线抠取关键帧的工具",
+    "C": "在线 抠图 关键帧 方法"
+  },
+  "1432": {
+    "idx": 1432,
+    "A": "代码 抠取 关键帧 工具",
+    "B": "有没有能抠取关键帧的代码工具",
+    "C": "代码 分割 视频帧 步骤"
+  },
+  "1433": {
+    "idx": 1433,
+    "A": "插件 抠取 关键帧 工具",
+    "B": "抠取关键帧的插件工具有哪些",
+    "C": "插件 分割 帧 教学"
+  },
+  "1434": {
+    "idx": 1434,
+    "A": "抠取 关键帧 技巧",
+    "B": "抠取关键帧的操作技巧有哪些",
+    "C": "怎么抠 视频帧 方法"
+  },
+  "1435": {
+    "idx": 1435,
+    "A": "AI 抠取 关键帧 技巧",
+    "B": "智能抠取关键帧有什么技巧",
+    "C": "AI 抠图 关键帧 步骤"
+  },
+  "1436": {
+    "idx": 1436,
+    "A": "软件 抠取 关键帧 技巧",
+    "B": "软件抠取关键帧的实用技巧",
+    "C": "电脑端 抠 视频帧 方法"
+  },
+  "1437": {
+    "idx": 1437,
+    "A": "在线 抠取 关键帧 技巧",
+    "B": "在线抠取关键帧的技巧分享",
+    "C": "网页版 抠图 帧 步骤"
+  },
+  "1438": {
+    "idx": 1438,
+    "A": "代码 抠取 关键帧 技巧",
+    "B": "通过代码抠取关键帧的技巧",
+    "C": "代码 抠图 视频帧 怎么做"
+  },
+  "1441": {
+    "idx": 1441,
+    "A": "AI 抽帧 关键帧 教程",
+    "B": "如何用智能技术实现抽帧和关键帧提取",
+    "C": "AI 怎么抽帧 关键帧 步骤"
+  },
+  "1442": {
+    "idx": 1442,
+    "A": "软件 抽帧 关键帧 教程",
+    "B": "软件抽帧和关键帧提取教程",
+    "C": "电脑端 怎么抽帧 帧 怎么做"
+  },
+  "1443": {
+    "idx": 1443,
+    "A": "在线 抽帧 关键帧 教程",
+    "B": "在线抽帧和关键帧提取怎么做",
+    "C": "在线 提取帧 关键帧 步骤"
+  },
+  "1444": {
+    "idx": 1444,
+    "A": "代码 抽帧 关键帧 教程",
+    "B": "如何用代码实现抽帧和关键帧提取",
+    "C": "命令行 怎么抽帧 帧 教学"
+  },
+  "1445": {
+    "idx": 1445,
+    "A": "插件 抽帧 关键帧 教程",
+    "B": "抽帧和关键帧提取的插件使用教程",
+    "C": "插件 抽帧 关键帧 怎么做"
+  },
+  "1446": {
+    "idx": 1446,
+    "A": "抽帧 关键帧 工具",
+    "B": "有哪些好用的抽帧和关键帧提取工具",
+    "C": "提取帧 帧 教学"
+  },
+  "1447": {
+    "idx": 1447,
+    "A": "AI 抽帧 关键帧 工具",
+    "B": "智能抽帧和关键帧提取工具有哪些",
+    "C": "AI 怎么抽帧 关键帧 方法"
+  },
+  "1448": {
+    "idx": 1448,
+    "A": "软件 抽帧 关键帧 工具",
+    "B": "求推荐抽帧和关键帧提取软件",
+    "C": "软件 抽帧 帧 教学"
+  },
+  "1449": {
+    "idx": 1449,
+    "A": "在线 抽帧 关键帧 工具",
+    "B": "在线抽帧和关键帧提取工具有哪些",
+    "C": "网页版 提取帧 视频帧 方法"
+  },
+  "1450": {
+    "idx": 1450,
+    "A": "代码 抽帧 关键帧 工具",
+    "B": "有没有抽帧和关键帧提取的代码工具",
+    "C": "代码 提取帧 关键帧 流程"
+  },
+  "1451": {
+    "idx": 1451,
+    "A": "插件 抽帧 关键帧 工具",
+    "B": "抽帧和关键帧提取的插件工具有哪些",
+    "C": "插件 提取帧 关键帧 怎么做"
+  },
+  "1452": {
+    "idx": 1452,
+    "A": "抽帧 关键帧 技巧",
+    "B": "抽帧和关键帧提取的操作技巧",
+    "C": "抽帧 帧 教学"
+  },
+  "1453": {
+    "idx": 1453,
+    "A": "AI 抽帧 关键帧 技巧",
+    "B": "智能抽帧和关键帧提取有什么技巧",
+    "C": "AI 怎么抽帧 帧 怎么做"
+  },
+  "1454": {
+    "idx": 1454,
+    "A": "软件 抽帧 关键帧 技巧",
+    "B": "软件抽帧和关键帧提取的技巧",
+    "C": "电脑端 抽帧 视频帧 教程"
+  },
+  "1455": {
+    "idx": 1455,
+    "A": "在线 抽帧 关键帧 技巧",
+    "B": "在线抽帧和关键帧提取的技巧",
+    "C": "在线 怎么抽帧 帧 方法"
+  },
+  "1456": {
+    "idx": 1456,
+    "A": "代码 抽帧 关键帧 技巧",
+    "B": "通过代码实现抽帧和关键帧提取的技巧",
+    "C": "命令行 提取帧 帧 方法"
+  },
+  "1457": {
+    "idx": 1457,
+    "A": "插件 抽帧 关键帧 技巧",
+    "B": "抽帧和关键帧提取的插件使用技巧",
+    "C": "插件 怎么抽帧 关键帧 步骤"
+  },
+  "1459": {
+    "idx": 1459,
+    "A": "AI 反推 关键帧 教程",
+    "B": "如何用智能技术反推关键帧",
+    "C": "AI 推断 关键帧 怎么做"
+  },
+  "1460": {
+    "idx": 1460,
+    "A": "软件 反推 关键帧 教程",
+    "B": "软件反推关键帧的教程",
+    "C": "软件 分析 视频帧 流程"
+  },
+  "1461": {
+    "idx": 1461,
+    "A": "在线 反推 关键帧 教程",
+    "B": "在线反推关键帧的方法",
+    "C": "在线 分析 视频帧 流程"
+  },
+  "1462": {
+    "idx": 1462,
+    "A": "代码 反推 关键帧 教程",
+    "B": "如何编写代码反推关键帧",
+    "C": "命令行 怎么反推 视频帧 教程"
+  },
+  "1463": {
+    "idx": 1463,
+    "A": "插件 反推 关键帧 教程",
+    "B": "反推关键帧的插件使用教程",
+    "C": "插件 怎么反推 关键帧 教学"
+  },
+  "1464": {
+    "idx": 1464,
+    "A": "反推 关键帧 工具",
+    "B": "怎么通过关键帧反推视频内容",
+    "C": "分析 视频帧 教程"
+  },
+  "1465": {
+    "idx": 1465,
+    "A": "AI 反推 关键帧 工具",
+    "B": "有没有能自动反推关键帧的智能工具",
+    "C": "AI 推断 视频帧 步骤"
+  },
+  "1466": {
+    "idx": 1466,
+    "A": "软件 反推 关键帧 工具",
+    "B": "有什么软件可以用来反推关键帧",
+    "C": "电脑端 怎么反推 帧 步骤"
+  },
+  "1467": {
+    "idx": 1467,
+    "A": "在线 反推 关键帧 工具",
+    "B": "哪里有在线反推关键帧的工具",
+    "C": "网页版 推断 关键帧 怎么做"
+  },
+  "1468": {
+    "idx": 1468,
+    "A": "代码 反推 关键帧 工具",
+    "B": "如何通过代码实现关键帧反推",
+    "C": "命令行 怎么反推 视频帧 教程"
+  },
+  "1469": {
+    "idx": 1469,
+    "A": "插件 反推 关键帧 工具",
+    "B": "有没有反推关键帧的插件推荐",
+    "C": "插件 推断 视频帧 教学"
+  },
+  "1470": {
+    "idx": 1470,
+    "A": "反推 关键帧 技巧",
+    "B": "反推关键帧有什么实用技巧",
+    "C": "推断 帧 教学"
+  },
+  "1471": {
+    "idx": 1471,
+    "A": "AI 反推 关键帧 技巧",
+    "B": "如何利用智能技术辅助反推关键帧",
+    "C": "AI 怎么反推 关键帧 步骤"
+  },
+  "1472": {
+    "idx": 1472,
+    "A": "软件 反推 关键帧 技巧",
+    "B": "软件反推关键帧的操作技巧有哪些",
+    "C": "电脑端 推断 帧 步骤"
+  },
+  "1473": {
+    "idx": 1473,
+    "A": "在线 反推 关键帧 技巧",
+    "B": "在线反推关键帧有什么好方法",
+    "C": "网页版 分析 关键帧 方法"
+  },
+  "1474": {
+    "idx": 1474,
+    "A": "代码 反推 关键帧 技巧",
+    "B": "编写代码反推关键帧的技巧是什么",
+    "C": "代码 反推 视频帧 怎么做"
+  },
+  "1475": {
+    "idx": 1475,
+    "A": "插件 反推 关键帧 技巧",
+    "B": "使用插件反推关键帧的技巧分享",
+    "C": "插件 分析 视频帧 教程"
+  },
+  "1476": {
+    "idx": 1476,
+    "A": "风格化 关键帧 教程",
+    "B": "如何制作风格化关键帧的教程",
+    "C": "怎么转风格 帧 步骤"
+  },
+  "1477": {
+    "idx": 1477,
+    "A": "AI 风格化 关键帧 教程",
+    "B": "怎么用智能技术制作风格化关键帧",
+    "C": "AI 怎么转风格 帧 教学"
+  },
+  "1478": {
+    "idx": 1478,
+    "A": "软件 风格化 关键帧 教程",
+    "B": "有没有关于风格化关键帧的软件教程",
+    "C": "软件 转风格 帧 教学"
+  },
+  "1479": {
+    "idx": 1479,
+    "A": "在线 风格化 关键帧 教程",
+    "B": "在线制作风格化关键帧的教程哪里找",
+    "C": "在线 怎么转风格 视频帧 步骤"
+  },
+  "1480": {
+    "idx": 1480,
+    "A": "代码 风格化 关键帧 教程",
+    "B": "如何通过代码实现关键帧风格化",
+    "C": "命令行 转风格 视频帧 方法"
+  },
+  "1481": {
+    "idx": 1481,
+    "A": "插件 风格化 关键帧 教程",
+    "B": "有没有风格化关键帧的插件使用教程",
+    "C": "插件 风格迁移 关键帧 怎么做"
+  },
+  "1482": {
+    "idx": 1482,
+    "A": "风格化 关键帧 工具",
+    "B": "有哪些制作风格化关键帧的工具",
+    "C": "转风格 视频帧 步骤"
+  },
+  "1483": {
+    "idx": 1483,
+    "A": "AI 风格化 关键帧 工具",
+    "B": "有没有智能风格化关键帧的工具",
+    "C": "AI 风格迁移 视频帧 教程"
+  },
+  "1484": {
+    "idx": 1484,
+    "A": "软件 风格化 关键帧 工具",
+    "B": "什么软件适合制作风格化关键帧",
+    "C": "软件 风格迁移 关键帧 教学"
+  },
+  "1485": {
+    "idx": 1485,
+    "A": "在线 风格化 关键帧 工具",
+    "B": "在线制作风格化关键帧的工具有哪些",
+    "C": "网页版 怎么转风格 帧 步骤"
+  },
+  "1486": {
+    "idx": 1486,
+    "A": "代码 风格化 关键帧 工具",
+    "B": "如何通过代码工具实现关键帧风格化",
+    "C": "命令行 风格迁移 帧 教程"
+  },
+  "1487": {
+    "idx": 1487,
+    "A": "插件 风格化 关键帧 工具",
+    "B": "有没有风格化关键帧的插件工具",
+    "C": "插件 风格化 视频帧 方法"
+  },
+  "1488": {
+    "idx": 1488,
+    "A": "风格化 关键帧 技巧",
+    "B": "风格化关键帧的制作技巧有哪些",
+    "C": "风格化 帧 流程"
+  },
+  "1489": {
+    "idx": 1489,
+    "A": "AI 风格化 关键帧 技巧",
+    "B": "如何利用智能技术提升关键帧风格化效果",
+    "C": "AI 怎么转风格 视频帧 步骤"
+  },
+  "1490": {
+    "idx": 1490,
+    "A": "软件 风格化 关键帧 技巧",
+    "B": "软件处理风格化关键帧的技巧",
+    "C": "电脑端 风格化 关键帧 流程"
+  },
+  "1491": {
+    "idx": 1491,
+    "A": "在线 风格化 关键帧 技巧",
+    "B": "在线处理风格化关键帧的技巧",
+    "C": "在线 风格迁移 帧 方法"
+  },
+  "1492": {
+    "idx": 1492,
+    "A": "代码 风格化 关键帧 技巧",
+    "B": "通过代码优化关键帧风格化的技巧",
+    "C": "命令行 转风格 帧 教学"
+  },
+  "1493": {
+    "idx": 1493,
+    "A": "插件 风格化 关键帧 技巧",
+    "B": "使用插件进行关键帧风格化的技巧",
+    "C": "插件 风格化 帧 步骤"
+  },
+  "1494": {
+    "idx": 1494,
+    "A": "增强 关键帧 教程",
+    "B": "如何学习增强关键帧的教程",
+    "C": "提升画质 帧 教学"
+  },
+  "1496": {
+    "idx": 1496,
+    "A": "软件 增强 关键帧 教程",
+    "B": "软件增强关键帧的详细教程",
+    "C": "软件 增强 帧 步骤"
+  },
+  "1497": {
+    "idx": 1497,
+    "A": "在线 增强 关键帧 教程",
+    "B": "在线增强关键帧的操作教程",
+    "C": "在线 提升画质 视频帧 流程"
+  },
+  "1498": {
+    "idx": 1498,
+    "A": "代码 增强 关键帧 教程",
+    "B": "如何用代码实现关键帧增强",
+    "C": "命令行 增强 关键帧 方法"
+  },
+  "1499": {
+    "idx": 1499,
+    "A": "插件 增强 关键帧 教程",
+    "B": "有没有增强关键帧的插件教程",
+    "C": "插件 修复 帧 怎么做"
+  },
+  "1500": {
+    "idx": 1500,
+    "A": "增强 关键帧 工具",
+    "B": "有哪些增强关键帧的工具",
+    "C": "修复 帧 教程"
+  },
+  "1501": {
+    "idx": 1501,
+    "A": "AI 增强 关键帧 工具",
+    "B": "有没有智能增强关键帧的工具",
+    "C": "AI 超分 关键帧 教学"
+  },
+  "1502": {
+    "idx": 1502,
+    "A": "软件 增强 关键帧 工具",
+    "B": "什么软件可以用来增强关键帧",
+    "C": "电脑端 增强 帧 方法"
+  },
+  "1503": {
+    "idx": 1503,
+    "A": "在线 增强 关键帧 工具",
+    "B": "在线增强关键帧的工具有哪些",
+    "C": "在线 增强 视频帧 教程"
+  },
+  "1504": {
+    "idx": 1504,
+    "A": "代码 增强 关键帧 工具",
+    "B": "如何通过代码工具增强关键帧",
+    "C": "代码 提升画质 视频帧 步骤"
+  },
+  "1505": {
+    "idx": 1505,
+    "A": "插件 增强 关键帧 工具",
+    "B": "有什么好用的关键帧增强插件",
+    "C": "插件 提升画质 关键帧 怎么做"
+  },
+  "1506": {
+    "idx": 1506,
+    "A": "增强 关键帧 技巧",
+    "B": "怎么提升关键帧制作技巧",
+    "C": "超分 视频帧 步骤"
+  },
+  "1508": {
+    "idx": 1508,
+    "A": "软件 增强 关键帧 技巧",
+    "B": "关键帧增强软件使用技巧",
+    "C": "软件 增强 关键帧 步骤"
+  },
+  "1509": {
+    "idx": 1509,
+    "A": "在线 增强 关键帧 技巧",
+    "B": "在线增强关键帧的方法",
+    "C": "网页版 修复 视频帧 方法"
+  },
+  "1510": {
+    "idx": 1510,
+    "A": "代码 增强 关键帧 技巧",
+    "B": "如何通过代码实现关键帧增强",
+    "C": "命令行 修复 视频帧 流程"
+  },
+  "1511": {
+    "idx": 1511,
+    "A": "插件 增强 关键帧 技巧",
+    "B": "关键帧增强插件的使用技巧",
+    "C": "插件 修复 帧 流程"
+  },
+  "1512": {
+    "idx": 1512,
+    "A": "检索 音效 教程",
+    "B": "音效检索教程怎么看",
+    "C": "搜 音效素材 教程"
+  },
+  "1513": {
+    "idx": 1513,
+    "A": "AI 检索 音效 教程",
+    "B": "如何利用智能技术检索音效",
+    "C": "AI 搜 声音 流程"
+  },
+  "1514": {
+    "idx": 1514,
+    "A": "软件 检索 音效 教程",
+    "B": "音效检索软件的操作教程",
+    "C": "软件 搜索 声音 教程"
+  },
+  "1515": {
+    "idx": 1515,
+    "A": "在线 检索 音效 教程",
+    "B": "在线搜索音效的教程",
+    "C": "网页版 找 音效素材 教学"
+  },
+  "1516": {
+    "idx": 1516,
+    "A": "代码 检索 音效 教程",
+    "B": "怎么写代码来检索音效",
+    "C": "命令行 搜索 音效 方法"
+  },
+  "1517": {
+    "idx": 1517,
+    "A": "插件 检索 音效 教程",
+    "B": "音效检索插件的使用教程",
+    "C": "插件 找 音效 教程"
+  },
+  "1518": {
+    "idx": 1518,
+    "A": "检索 音效 工具",
+    "B": "好用的音效检索工具推荐",
+    "C": "找 音效素材 怎么做"
+  },
+  "1519": {
+    "idx": 1519,
+    "A": "AI 检索 音效 工具",
+    "B": "有哪些智能音效检索工具",
+    "C": "AI 找 SFX 怎么做"
+  },
+  "1520": {
+    "idx": 1520,
+    "A": "软件 检索 音效 工具",
+    "B": "音效检索软件哪个好用",
+    "C": "软件 搜 音效 步骤"
+  },
+  "1521": {
+    "idx": 1521,
+    "A": "在线 检索 音效 工具",
+    "B": "在线检索音效的工具推荐",
+    "C": "网页版 找 SFX 方法"
+  },
+  "1522": {
+    "idx": 1522,
+    "A": "代码 检索 音效 工具",
+    "B": "好用的音效检索代码工具",
+    "C": "代码 在哪找 音效 方法"
+  },
+  "1523": {
+    "idx": 1523,
+    "A": "插件 检索 音效 工具",
+    "B": "音效检索插件有哪些",
+    "C": "插件 哪里找 音效 教程"
+  },
+  "1524": {
+    "idx": 1524,
+    "A": "检索 音效 技巧",
+    "B": "音效检索有什么技巧",
+    "C": "在哪找 声音 方法"
+  },
+  "1525": {
+    "idx": 1525,
+    "A": "AI 检索 音效 技巧",
+    "B": "智能检索音效的技巧",
+    "C": "AI 哪里找 声音 步骤"
+  },
+  "1526": {
+    "idx": 1526,
+    "A": "软件 检索 音效 技巧",
+    "B": "音效检索软件的使用技巧",
+    "C": "电脑端 哪里找 声音 教程"
+  },
+  "1527": {
+    "idx": 1527,
+    "A": "在线 检索 音效 技巧",
+    "B": "在线检索音效的技巧",
+    "C": "网页版 搜 音效素材 步骤"
+  },
+  "1528": {
+    "idx": 1528,
+    "A": "代码 检索 音效 技巧",
+    "B": "通过代码检索音效的技巧",
+    "C": "代码 找 音效 教学"
+  },
+  "1529": {
+    "idx": 1529,
+    "A": "插件 检索 音效 技巧",
+    "B": "音效检索插件的使用技巧",
+    "C": "插件 找 音效素材 流程"
+  },
+  "1530": {
+    "idx": 1530,
+    "A": "录音 音效 教程",
+    "B": "录制音效的教程",
+    "C": "录音 音效 教学"
+  },
+  "1531": {
+    "idx": 1531,
+    "A": "AI 录音 音效 教程",
+    "B": "如何利用智能技术录制音效",
+    "C": "AI 怎么录 声音 怎么做"
+  },
+  "1532": {
+    "idx": 1532,
+    "A": "软件 录音 音效 教程",
+    "B": "录音软件制作音效教程",
+    "C": "电脑端 怎么录 音效素材 教程"
+  },
+  "1533": {
+    "idx": 1533,
+    "A": "在线 录音 音效 教程",
+    "B": "在线录制音效的教程",
+    "C": "在线 录 音效 步骤"
+  },
+  "1534": {
+    "idx": 1534,
+    "A": "代码 录音 音效 教程",
+    "B": "如何用代码实现音效录制",
+    "C": "命令行 怎么录 音效素材 教学"
+  },
+  "1535": {
+    "idx": 1535,
+    "A": "插件 录音 音效 教程",
+    "B": "录音插件制作音效教程",
+    "C": "插件 录音 音效 教程"
+  },
+  "1536": {
+    "idx": 1536,
+    "A": "录音 音效 工具",
+    "B": "录制音效的工具推荐",
+    "C": "录 声音 步骤"
+  },
+  "1537": {
+    "idx": 1537,
+    "A": "AI 录音 音效 工具",
+    "B": "好用的智能录音工具",
+    "C": "AI 录制 SFX 教学"
+  },
+  "1538": {
+    "idx": 1538,
+    "A": "软件 录音 音效 工具",
+    "B": "录音软件推荐",
+    "C": "软件 怎么录 SFX 流程"
+  },
+  "1539": {
+    "idx": 1539,
+    "A": "在线 录音 音效 工具",
+    "B": "在线录音工具推荐",
+    "C": "在线 录制 音效素材 怎么做"
+  },
+  "1540": {
+    "idx": 1540,
+    "A": "代码 录音 音效 工具",
+    "B": "好用的录音代码工具",
+    "C": "命令行 录制 音效素材 怎么做"
+  },
+  "1541": {
+    "idx": 1541,
+    "A": "插件 录音 音效 工具",
+    "B": "录音插件推荐",
+    "C": "插件 录音 声音 教学"
+  },
+  "1542": {
+    "idx": 1542,
+    "A": "录音 音效 技巧",
+    "B": "录制音效有哪些技巧",
+    "C": "录音 声音 教程"
+  },
+  "1543": {
+    "idx": 1543,
+    "A": "AI 录音 音效 技巧",
+    "B": "智能录音的技巧",
+    "C": "AI 录制 音效素材 流程"
+  },
+  "1544": {
+    "idx": 1544,
+    "A": "软件 录音 音效 技巧",
+    "B": "录音软件的使用技巧",
+    "C": "电脑端 怎么录 音效 教学"
+  },
+  "1545": {
+    "idx": 1545,
+    "A": "在线 录音 音效 技巧",
+    "B": "在线录音的技巧",
+    "C": "在线 录制 音效素材 教程"
+  },
+  "1546": {
+    "idx": 1546,
+    "A": "代码 录音 音效 技巧",
+    "B": "如何通过代码录制音效的技巧",
+    "C": "命令行 录制 音效 教程"
+  },
+  "1547": {
+    "idx": 1547,
+    "A": "插件 录音 音效 技巧",
+    "B": "录制音效时常用的插件使用技巧",
+    "C": "插件 怎么录 音效 教学"
+  },
+  "1548": {
+    "idx": 1548,
+    "A": "元素生成 音效 教程",
+    "B": "制作音效元素的详细教程",
+    "C": "创作 声音 教学"
+  },
+  "1549": {
+    "idx": 1549,
+    "A": "AI 元素生成 音效 教程",
+    "B": "如何利用智能技术生成音效元素",
+    "C": "AI 创作 音效 怎么做"
+  },
+  "1550": {
+    "idx": 1550,
+    "A": "软件 元素生成 音效 教程",
+    "B": "有哪些制作音效元素的软件教程",
+    "C": "软件 做 SFX 教学"
+  },
+  "1551": {
+    "idx": 1551,
+    "A": "在线 元素生成 音效 教程",
+    "B": "在线生成音效元素的方法教程",
+    "C": "网页版 制作 音效 教程"
+  },
+  "1552": {
+    "idx": 1552,
+    "A": "代码 元素生成 音效 教程",
+    "B": "如何用代码编写音效元素",
+    "C": "代码 创作 音效素材 怎么做"
+  },
+  "1553": {
+    "idx": 1553,
+    "A": "插件 元素生成 音效 教程",
+    "B": "制作音效元素时好用的插件教程",
+    "C": "插件 生成 音效素材 步骤"
+  },
+  "1554": {
+    "idx": 1554,
+    "A": "元素生成 音效 工具",
+    "B": "好用的音效元素生成工具推荐",
+    "C": "制作 SFX 步骤"
+  },
+  "1555": {
+    "idx": 1555,
+    "A": "AI 元素生成 音效 工具",
+    "B": "智能生成音效元素的工具",
+    "C": "AI 创作 声音 方法"
+  },
+  "1556": {
+    "idx": 1556,
+    "A": "软件 元素生成 音效 工具",
+    "B": "制作音效元素的软件工具",
+    "C": "电脑端 做 声音 教程"
+  },
+  "1557": {
+    "idx": 1557,
+    "A": "在线 元素生成 音效 工具",
+    "B": "在线生成音效元素的工具",
+    "C": "网页版 做 音效素材 教程"
+  },
+  "1558": {
+    "idx": 1558,
+    "A": "代码 元素生成 音效 工具",
+    "B": "用于生成音效元素的代码工具",
+    "C": "命令行 做 SFX 教程"
+  },
+  "1559": {
+    "idx": 1559,
+    "A": "插件 元素生成 音效 工具",
+    "B": "制作音效元素的插件工具",
+    "C": "插件 生成 音效 怎么做"
+  },
+  "1560": {
+    "idx": 1560,
+    "A": "元素生成 音效 技巧",
+    "B": "音效元素制作的实用技巧",
+    "C": "做 音效 方法"
+  },
+  "1561": {
+    "idx": 1561,
+    "A": "AI 元素生成 音效 技巧",
+    "B": "利用智能技术制作音效元素的技巧",
+    "C": "AI 生成 SFX 方法"
+  },
+  "1562": {
+    "idx": 1562,
+    "A": "软件 元素生成 音效 技巧",
+    "B": "使用软件制作音效元素的技巧",
+    "C": "软件 做 SFX 步骤"
+  },
+  "1563": {
+    "idx": 1563,
+    "A": "在线 元素生成 音效 技巧",
+    "B": "在线制作音效元素的技巧",
+    "C": "在线 制作 音效素材 步骤"
+  },
+  "1564": {
+    "idx": 1564,
+    "A": "代码 元素生成 音效 技巧",
+    "B": "通过代码制作音效元素的技巧",
+    "C": "命令行 怎么做 音效素材 教程"
+  },
+  "1565": {
+    "idx": 1565,
+    "A": "插件 元素生成 音效 技巧",
+    "B": "使用插件制作音效元素的技巧",
+    "C": "插件 制作 音效 步骤"
+  },
+  "1566": {
+    "idx": 1566,
+    "A": "抠取 特效 教程",
+    "B": "如何抠取特效的详细教程",
+    "C": "分割 VFX 方法"
+  },
+  "1567": {
+    "idx": 1567,
+    "A": "AI 抠取 特效 教程",
+    "B": "利用智能技术抠取特效的教程",
+    "C": "AI 抠图 特效 流程"
+  },
+  "1569": {
+    "idx": 1569,
+    "A": "在线 抠取 特效 教程",
+    "B": "在线抠取特效的操作教程",
+    "C": "网页版 抠 effect 教程"
+  },
+  "1570": {
+    "idx": 1570,
+    "A": "代码 抠取 特效 教程",
+    "B": "如何通过代码实现抠取特效",
+    "C": "命令行 抠 视频特效 教程"
+  },
+  "1571": {
+    "idx": 1571,
+    "A": "插件 抠取 特效 教程",
+    "B": "抠取特效时常用的插件教程",
+    "C": "插件 抠 effect 流程"
+  },
+  "1572": {
+    "idx": 1572,
+    "A": "抠取 特效 工具",
+    "B": "好用的抠取特效工具",
+    "C": "分割 特效 怎么做"
+  },
+  "1573": {
+    "idx": 1573,
+    "A": "AI 抠取 特效 工具",
+    "B": "智能抠取特效的工具",
+    "C": "AI 抠图 effect 怎么做"
+  },
+  "1574": {
+    "idx": 1574,
+    "A": "软件 抠取 特效 工具",
+    "B": "抠取特效的软件工具",
+    "C": "软件 怎么抠 特效 方法"
+  },
+  "1575": {
+    "idx": 1575,
+    "A": "在线 抠取 特效 工具",
+    "B": "在线抠取特效的工具",
+    "C": "在线 怎么抠 effect 方法"
+  },
+  "1576": {
+    "idx": 1576,
+    "A": "代码 抠取 特效 工具",
+    "B": "用于抠取特效的代码工具",
+    "C": "代码 抠 视频特效 教程"
+  },
+  "1577": {
+    "idx": 1577,
+    "A": "插件 抠取 特效 工具",
+    "B": "抠取特效的插件工具",
+    "C": "插件 分割 effect 怎么做"
+  },
+  "1578": {
+    "idx": 1578,
+    "A": "抠取 特效 技巧",
+    "B": "抠取特效的实用技巧",
+    "C": "抠 VFX 怎么做"
+  },
+  "1579": {
+    "idx": 1579,
+    "A": "AI 抠取 特效 技巧",
+    "B": "利用智能技术抠取特效的技巧",
+    "C": "AI 分割 effect 流程"
+  },
+  "1581": {
+    "idx": 1581,
+    "A": "在线 抠取 特效 技巧",
+    "B": "在线抠取特效的技巧",
+    "C": "在线 怎么抠 VFX 教学"
+  },
+  "1582": {
+    "idx": 1582,
+    "A": "代码 抠取 特效 技巧",
+    "B": "通过代码抠取特效的技巧",
+    "C": "命令行 抠 视频特效 流程"
+  },
+  "1583": {
+    "idx": 1583,
+    "A": "插件 抠取 特效 技巧",
+    "B": "使用插件抠取特效的技巧",
+    "C": "插件 分割 视频特效 教学"
+  },
+  "1584": {
+    "idx": 1584,
+    "A": "风格化 特效 教程",
+    "B": "给特效添加风格化的教程",
+    "C": "转风格 VFX 教学"
+  },
+  "1585": {
+    "idx": 1585,
+    "A": "AI 风格化 特效 教程",
+    "B": "如何利用智能技术实现特效风格化",
+    "C": "AI 风格迁移 effect 方法"
+  },
+  "1586": {
+    "idx": 1586,
+    "A": "软件 风格化 特效 教程",
+    "B": "制作风格化特效的软件教程",
+    "C": "电脑端 风格迁移 effect 教程"
+  },
+  "1587": {
+    "idx": 1587,
+    "A": "在线 风格化 特效 教程",
+    "B": "在线制作风格化特效的教程",
+    "C": "在线 风格化 effect 流程"
+  },
+  "1588": {
+    "idx": 1588,
+    "A": "代码 风格化 特效 教程",
+    "B": "如何用代码制作风格化特效",
+    "C": "代码 风格化 视频特效 步骤"
+  },
+  "1589": {
+    "idx": 1589,
+    "A": "插件 风格化 特效 教程",
+    "B": "怎么用插件制作风格化特效",
+    "C": "插件 风格迁移 VFX 流程"
+  },
+  "1590": {
+    "idx": 1590,
+    "A": "风格化 特效 工具",
+    "B": "有哪些好用的风格化特效制作工具",
+    "C": "风格化 VFX 流程"
+  },
+  "1591": {
+    "idx": 1591,
+    "A": "AI 风格化 特效 工具",
+    "B": "有什么好用的智能风格化特效工具",
+    "C": "AI 风格迁移 effect 教程"
+  },
+  "1592": {
+    "idx": 1592,
+    "A": "软件 风格化 特效 工具",
+    "B": "哪些软件可以制作风格化特效",
+    "C": "软件 怎么转风格 视频特效 方法"
+  },
+  "1593": {
+    "idx": 1593,
+    "A": "在线 风格化 特效 工具",
+    "B": "在线制作风格化特效的工具推荐",
+    "C": "网页版 风格化 effect 怎么做"
+  },
+  "1594": {
+    "idx": 1594,
+    "A": "代码 风格化 特效 工具",
+    "B": "制作风格化特效的代码工具有哪些",
+    "C": "命令行 风格迁移 特效 教程"
+  },
+  "1595": {
+    "idx": 1595,
+    "A": "插件 风格化 特效 工具",
+    "B": "好用的风格化特效插件推荐",
+    "C": "插件 转风格 effect 流程"
+  },
+  "1596": {
+    "idx": 1596,
+    "A": "风格化 特效 技巧",
+    "B": "风格化特效的制作技巧有哪些",
+    "C": "风格迁移 视频特效 教学"
+  },
+  "1597": {
+    "idx": 1597,
+    "A": "AI 风格化 特效 技巧",
+    "B": "使用智能工具制作风格化特效的技巧",
+    "C": "AI 风格迁移 effect 流程"
+  },
+  "1598": {
+    "idx": 1598,
+    "A": "软件 风格化 特效 技巧",
+    "B": "软件制作风格化特效的实用技巧",
+    "C": "软件 转风格 视频特效 教学"
+  },
+  "1599": {
+    "idx": 1599,
+    "A": "在线 风格化 特效 技巧",
+    "B": "在线制作风格化特效的技巧分享",
+    "C": "在线 怎么转风格 特效 怎么做"
+  },
+  "1600": {
+    "idx": 1600,
+    "A": "代码 风格化 特效 技巧",
+    "B": "用代码实现风格化特效的技巧",
+    "C": "命令行 风格迁移 视频特效 流程"
+  },
+  "1601": {
+    "idx": 1601,
+    "A": "插件 风格化 特效 技巧",
+    "B": "风格化特效插件的使用技巧",
+    "C": "插件 风格化 VFX 怎么做"
+  },
+  "1602": {
+    "idx": 1602,
+    "A": "增强 特效 教程",
+    "B": "如何学习增强特效的制作方法",
+    "C": "提升画质 特效 流程"
+  },
+  "1603": {
+    "idx": 1603,
+    "A": "AI 增强 特效 教程",
+    "B": "怎么用智能技术制作增强特效",
+    "C": "AI 超分 特效 教学"
+  },
+  "1604": {
+    "idx": 1604,
+    "A": "软件 增强 特效 教程",
+    "B": "有哪些软件可以制作增强特效",
+    "C": "电脑端 修复 VFX 教程"
+  },
+  "1605": {
+    "idx": 1605,
+    "A": "在线 增强 特效 教程",
+    "B": "在线制作增强特效的方法",
+    "C": "网页版 超分 视频特效 流程"
+  },
+  "1606": {
+    "idx": 1606,
+    "A": "代码 增强 特效 教程",
+    "B": "如何通过代码实现增强特效",
+    "C": "代码 超分 视频特效 怎么做"
+  },
+  "1607": {
+    "idx": 1607,
+    "A": "插件 增强 特效 教程",
+    "B": "增强特效插件的制作教程",
+    "C": "插件 增强 VFX 流程"
+  },
+  "1608": {
+    "idx": 1608,
+    "A": "增强 特效 工具",
+    "B": "有哪些好用的增强特效工具",
+    "C": "提升画质 VFX 步骤"
+  },
+  "1609": {
+    "idx": 1609,
+    "A": "AI 增强 特效 工具",
+    "B": "好用的智能增强特效工具有哪些",
+    "C": "AI 怎么增强 视频特效 方法"
+  },
+  "1610": {
+    "idx": 1610,
+    "A": "软件 增强 特效 工具",
+    "B": "制作增强特效的常用软件",
+    "C": "电脑端 超分 特效 教程"
+  },
+  "1611": {
+    "idx": 1611,
+    "A": "在线 增强 特效 工具",
+    "B": "在线增强特效的工具推荐",
+    "C": "网页版 修复 视频特效 教学"
+  },
+  "1612": {
+    "idx": 1612,
+    "A": "代码 增强 特效 工具",
+    "B": "好用的增强特效代码工具",
+    "C": "代码 增强 VFX 怎么做"
+  },
+  "1613": {
+    "idx": 1613,
+    "A": "插件 增强 特效 工具",
+    "B": "有哪些增强特效插件",
+    "C": "插件 修复 VFX 方法"
+  },
+  "1614": {
+    "idx": 1614,
+    "A": "增强 特效 技巧",
+    "B": "增强特效的制作技巧有哪些",
+    "C": "怎么增强 特效 方法"
+  },
+  "1615": {
+    "idx": 1615,
+    "A": "AI 增强 特效 技巧",
+    "B": "智能增强特效的实用技巧",
+    "C": "AI 超分 effect 怎么做"
+  },
+  "1616": {
+    "idx": 1616,
+    "A": "软件 增强 特效 技巧",
+    "B": "软件制作增强特效的技巧",
+    "C": "软件 怎么增强 视频特效 步骤"
+  },
+  "1617": {
+    "idx": 1617,
+    "A": "在线 增强 特效 技巧",
+    "B": "在线增强特效的技巧分享",
+    "C": "在线 增强 视频特效 方法"
+  },
+  "1618": {
+    "idx": 1618,
+    "A": "代码 增强 特效 技巧",
+    "B": "用代码实现增强特效的技巧",
+    "C": "代码 增强 视频特效 教学"
+  },
+  "1619": {
+    "idx": 1619,
+    "A": "插件 增强 特效 技巧",
+    "B": "增强特效插件的使用技巧",
+    "C": "插件 修复 特效 流程"
+  },
+  "1620": {
+    "idx": 1620,
+    "A": "反推 大纲 教程",
+    "B": "如何通过内容反推大纲",
+    "C": "怎么反推 提纲 教程"
+  },
+  "1621": {
+    "idx": 1621,
+    "A": "AI 反推 大纲 教程",
+    "B": "如何利用智能技术反推大纲",
+    "C": "AI 反推 内容大纲 教学"
+  },
+  "1622": {
+    "idx": 1622,
+    "A": "软件 反推 大纲 教程",
+    "B": "有哪些软件可以辅助反推大纲",
+    "C": "电脑端 反推 大纲 教程"
+  },
+  "1623": {
+    "idx": 1623,
+    "A": "在线 反推 大纲 教程",
+    "B": "在线反推大纲的方法",
+    "C": "在线 分析 内容大纲 方法"
+  },
+  "1624": {
+    "idx": 1624,
+    "A": "代码 反推 大纲 教程",
+    "B": "如何用代码实现内容反推大纲",
+    "C": "代码 分析 内容大纲 怎么做"
+  },
+  "1625": {
+    "idx": 1625,
+    "A": "插件 反推 大纲 教程",
+    "B": "有哪些插件可以辅助反推大纲",
+    "C": "插件 怎么反推 提纲 怎么做"
+  },
+  "1626": {
+    "idx": 1626,
+    "A": "反推 大纲 工具",
+    "B": "好用的反推大纲工具推荐",
+    "C": "怎么反推 内容大纲 教程"
+  },
+  "1627": {
+    "idx": 1627,
+    "A": "AI 反推 大纲 工具",
+    "B": "有什么智能反推大纲的工具",
+    "C": "AI 反推 提纲 教程"
+  },
+  "1628": {
+    "idx": 1628,
+    "A": "软件 反推 大纲 工具",
+    "B": "有什么软件可以用来反推大纲?",
+    "C": "软件 反推 提纲 教程"
+  },
+  "1629": {
+    "idx": 1629,
+    "A": "在线 反推 大纲 工具",
+    "B": "有没有在线反推大纲的工具?",
+    "C": "网页版 反推 内容大纲 教学"
+  },
+  "1630": {
+    "idx": 1630,
+    "A": "代码 反推 大纲 工具",
+    "B": "通过代码反推大纲的工具有哪些?",
+    "C": "命令行 反推 内容大纲 怎么做"
+  },
+  "1631": {
+    "idx": 1631,
+    "A": "插件 反推 大纲 工具",
+    "B": "有哪些插件可以辅助反推大纲?",
+    "C": "插件 怎么反推 提纲 教程"
+  },
+  "1632": {
+    "idx": 1632,
+    "A": "反推 大纲 技巧",
+    "B": "反推大纲有什么好用的技巧?",
+    "C": "怎么反推 大纲 方法"
+  },
+  "1633": {
+    "idx": 1633,
+    "A": "AI 反推 大纲 技巧",
+    "B": "怎么利用智能技术反推大纲?",
+    "C": "AI 分析 提纲 怎么做"
+  },
+  "1634": {
+    "idx": 1634,
+    "A": "软件 反推 大纲 技巧",
+    "B": "使用软件反推大纲有什么技巧?",
+    "C": "电脑端 分析 内容大纲 教学"
+  },
+  "1635": {
+    "idx": 1635,
+    "A": "在线 反推 大纲 技巧",
+    "B": "在线反推大纲有哪些操作技巧?",
+    "C": "网页版 反推 提纲 方法"
+  },
+  "1636": {
+    "idx": 1636,
+    "A": "代码 反推 大纲 技巧",
+    "B": "通过代码反推大纲有什么技巧?",
+    "C": "代码 反推 大纲 教程"
+  },
+  "1637": {
+    "idx": 1637,
+    "A": "插件 反推 大纲 技巧",
+    "B": "使用插件反推大纲的技巧有哪些?",
+    "C": "插件 反推 内容大纲 流程"
+  },
+  "1638": {
+    "idx": 1638,
+    "A": "解构 大纲 教程",
+    "B": "如何学习解构大纲的教程?",
+    "C": "分析结构 提纲 教学"
+  },
+  "1639": {
+    "idx": 1639,
+    "A": "AI 解构 大纲 教程",
+    "B": "智能解构大纲的教程哪里有?",
+    "C": "AI 拆解 内容大纲 教学"
+  },
+  "1640": {
+    "idx": 1640,
+    "A": "软件 解构 大纲 教程",
+    "B": "有没有软件解构大纲的教程?",
+    "C": "软件 拆解 大纲 流程"
+  },
+  "1642": {
+    "idx": 1642,
+    "A": "代码 解构 大纲 教程",
+    "B": "通过代码解构大纲的教程怎么找?",
+    "C": "命令行 拆解 大纲 流程"
+  },
+  "1643": {
+    "idx": 1643,
+    "A": "插件 解构 大纲 教程",
+    "B": "有没有插件解构大纲的教程?",
+    "C": "插件 分析结构 内容大纲 教学"
+  },
+  "1644": {
+    "idx": 1644,
+    "A": "解构 大纲 工具",
+    "B": "有哪些工具可以用来解构大纲?",
+    "C": "分析结构 大纲 步骤"
+  },
+  "1645": {
+    "idx": 1645,
+    "A": "AI 解构 大纲 工具",
+    "B": "智能解构大纲的工具有哪些?",
+    "C": "AI 解构 大纲 流程"
+  },
+  "1646": {
+    "idx": 1646,
+    "A": "软件 解构 大纲 工具",
+    "B": "有没有软件可以解构大纲?",
+    "C": "电脑端 解构 内容大纲 流程"
+  },
+  "1647": {
+    "idx": 1647,
+    "A": "在线 解构 大纲 工具",
+    "B": "在线解构大纲的工具有哪些?",
+    "C": "在线 拆解 内容大纲 方法"
+  },
+  "1648": {
+    "idx": 1648,
+    "A": "代码 解构 大纲 工具",
+    "B": "通过代码解构大纲的工具有哪些?",
+    "C": "代码 拆解 内容大纲 怎么做"
+  },
+  "1649": {
+    "idx": 1649,
+    "A": "插件 解构 大纲 工具",
+    "B": "有哪些插件可以用来解构大纲?",
+    "C": "插件 解构 提纲 教学"
+  },
+  "1650": {
+    "idx": 1650,
+    "A": "解构 大纲 技巧",
+    "B": "解构大纲有哪些实用的技巧?",
+    "C": "解构 提纲 方法"
+  },
+  "1651": {
+    "idx": 1651,
+    "A": "AI 解构 大纲 技巧",
+    "B": "智能解构大纲有什么技巧?",
+    "C": "AI 分析结构 提纲 步骤"
+  },
+  "1652": {
+    "idx": 1652,
+    "A": "软件 解构 大纲 技巧",
+    "B": "使用软件解构大纲的技巧是什么?",
+    "C": "电脑端 解构 大纲 教程"
+  },
+  "1654": {
+    "idx": 1654,
+    "A": "代码 解构 大纲 技巧",
+    "B": "通过代码解构大纲有什么技巧?",
+    "C": "命令行 拆解 大纲 教学"
+  },
+  "1655": {
+    "idx": 1655,
+    "A": "插件 解构 大纲 技巧",
+    "B": "使用插件解构大纲的技巧有哪些?",
+    "C": "插件 解构 内容大纲 流程"
+  },
+  "1656": {
+    "idx": 1656,
+    "A": "元素生成 大纲 教程",
+    "B": "元素生成大纲的教程怎么看?",
+    "C": "怎么做 内容大纲 怎么做"
+  },
+  "1657": {
+    "idx": 1657,
+    "A": "AI 元素生成 大纲 教程",
+    "B": "智能元素生成大纲的教程有哪些?",
+    "C": "AI 怎么做 内容大纲 怎么做"
+  },
+  "1658": {
+    "idx": 1658,
+    "A": "软件 元素生成 大纲 教程",
+    "B": "有没有软件生成元素大纲的教程?",
+    "C": "软件 制作 提纲 方法"
+  },
+  "1659": {
+    "idx": 1659,
+    "A": "在线 元素生成 大纲 教程",
+    "B": "在线生成元素大纲的教程哪里找?",
+    "C": "在线 怎么做 大纲 方法"
+  },
+  "1660": {
+    "idx": 1660,
+    "A": "代码 元素生成 大纲 教程",
+    "B": "通过代码生成元素大纲的教程有哪些?",
+    "C": "代码 怎么做 提纲 教学"
+  },
+  "1661": {
+    "idx": 1661,
+    "A": "插件 元素生成 大纲 教程",
+    "B": "有没有插件生成元素大纲的教程?",
+    "C": "插件 生成 大纲 方法"
+  },
+  "1662": {
+    "idx": 1662,
+    "A": "元素生成 大纲 工具",
+    "B": "有哪些工具可以生成元素大纲?",
+    "C": "生成 提纲 方法"
+  },
+  "1663": {
+    "idx": 1663,
+    "A": "AI 元素生成 大纲 工具",
+    "B": "智能生成元素大纲的工具有哪些?",
+    "C": "AI 创作 大纲 教程"
+  },
+  "1664": {
+    "idx": 1664,
+    "A": "软件 元素生成 大纲 工具",
+    "B": "有没有软件可以生成元素大纲?",
+    "C": "电脑端 创作 提纲 怎么做"
+  },
+  "1665": {
+    "idx": 1665,
+    "A": "在线 元素生成 大纲 工具",
+    "B": "在线生成元素大纲的工具有哪些?",
+    "C": "在线 怎么做 内容大纲 流程"
+  },
+  "1666": {
+    "idx": 1666,
+    "A": "代码 元素生成 大纲 工具",
+    "B": "通过代码生成元素大纲的工具有哪些?",
+    "C": "命令行 制作 内容大纲 方法"
+  },
+  "1667": {
+    "idx": 1667,
+    "A": "插件 元素生成 大纲 工具",
+    "B": "有哪些插件可以生成元素大纲?",
+    "C": "插件 做 内容大纲 方法"
+  },
+  "1668": {
+    "idx": 1668,
+    "A": "元素生成 大纲 技巧",
+    "B": "元素生成大纲有哪些技巧?",
+    "C": "生成 提纲 流程"
+  },
+  "1669": {
+    "idx": 1669,
+    "A": "AI 元素生成 大纲 技巧",
+    "B": "智能生成元素大纲有什么技巧?",
+    "C": "AI 创作 大纲 怎么做"
+  },
+  "1670": {
+    "idx": 1670,
+    "A": "软件 元素生成 大纲 技巧",
+    "B": "如何用软件快速生成内容大纲的技巧",
+    "C": "软件 制作 提纲 方法"
+  },
+  "1671": {
+    "idx": 1671,
+    "A": "在线 元素生成 大纲 技巧",
+    "B": "在线生成内容大纲的方法和技巧",
+    "C": "在线 做 内容大纲 教程"
+  },
+  "1672": {
+    "idx": 1672,
+    "A": "代码 元素生成 大纲 技巧",
+    "B": "编写代码来自动生成大纲的技巧",
+    "C": "代码 做 大纲 教程"
+  },
+  "1673": {
+    "idx": 1673,
+    "A": "插件 元素生成 大纲 技巧",
+    "B": "有哪些好用的插件可以辅助生成大纲",
+    "C": "插件 怎么做 大纲 教程"
+  },
+  "1674": {
+    "idx": 1674,
+    "A": "结构生成 大纲 教程",
+    "B": "结构化大纲生成的详细教程",
+    "C": "搭建 提纲 步骤"
+  },
+  "1675": {
+    "idx": 1675,
+    "A": "AI 结构生成 大纲 教程",
+    "B": "如何利用智能技术生成结构化大纲",
+    "C": "AI 构建 内容大纲 教程"
+  },
+  "1676": {
+    "idx": 1676,
+    "A": "软件 结构生成 大纲 教程",
+    "B": "有没有能生成结构化大纲的软件教程",
+    "C": "软件 怎么生成 大纲 教学"
+  },
+  "1677": {
+    "idx": 1677,
+    "A": "在线 结构生成 大纲 教程",
+    "B": "在线生成结构化大纲的步骤教程",
+    "C": "网页版 怎么生成 提纲 方法"
+  },
+  "1678": {
+    "idx": 1678,
+    "A": "代码 结构生成 大纲 教程",
+    "B": "通过代码生成结构化大纲的教程",
+    "C": "代码 构建 提纲 怎么做"
+  },
+  "1679": {
+    "idx": 1679,
+    "A": "插件 结构生成 大纲 教程",
+    "B": "结构化大纲生成插件的使用教程",
+    "C": "插件 生成 提纲 步骤"
+  },
+  "1680": {
+    "idx": 1680,
+    "A": "结构生成 大纲 工具",
+    "B": "好用的结构化大纲生成工具推荐",
+    "C": "构建 大纲 方法"
+  },
+  "1681": {
+    "idx": 1681,
+    "A": "AI 结构生成 大纲 工具",
+    "B": "智能生成结构化大纲的工具",
+    "C": "AI 怎么生成 内容大纲 怎么做"
+  },
+  "1682": {
+    "idx": 1682,
+    "A": "软件 结构生成 大纲 工具",
+    "B": "适合生成结构化大纲的软件有哪些",
+    "C": "电脑端 生成 提纲 流程"
+  },
+  "1683": {
+    "idx": 1683,
+    "A": "在线 结构生成 大纲 工具",
+    "B": "好用的在线结构化大纲生成工具",
+    "C": "网页版 搭建 大纲 教程"
+  },
+  "1684": {
+    "idx": 1684,
+    "A": "代码 结构生成 大纲 工具",
+    "B": "用于生成结构化大纲的代码工具",
+    "C": "命令行 搭建 大纲 流程"
+  },
+  "1685": {
+    "idx": 1685,
+    "A": "插件 结构生成 大纲 工具",
+    "B": "好用的结构化大纲生成插件",
+    "C": "插件 怎么生成 提纲 教学"
+  },
+  "1686": {
+    "idx": 1686,
+    "A": "结构生成 大纲 技巧",
+    "B": "如何高效生成结构化大纲的技巧",
+    "C": "生成 提纲 流程"
+  },
+  "1687": {
+    "idx": 1687,
+    "A": "AI 结构生成 大纲 技巧",
+    "B": "智能生成结构化大纲的操作技巧",
+    "C": "AI 怎么生成 提纲 教程"
+  },
+  "1688": {
+    "idx": 1688,
+    "A": "软件 结构生成 大纲 技巧",
+    "B": "使用软件生成结构化大纲的技巧",
+    "C": "电脑端 构建 内容大纲 流程"
+  },
+  "1689": {
+    "idx": 1689,
+    "A": "在线 结构生成 大纲 技巧",
+    "B": "在线生成结构化大纲的实用技巧",
+    "C": "在线 构建 大纲 流程"
+  },
+  "1690": {
+    "idx": 1690,
+    "A": "代码 结构生成 大纲 技巧",
+    "B": "利用代码生成结构化大纲的技巧",
+    "C": "代码 搭建 提纲 方法"
+  },
+  "1691": {
+    "idx": 1691,
+    "A": "插件 结构生成 大纲 技巧",
+    "B": "使用插件生成结构化大纲的技巧",
+    "C": "插件 搭建 提纲 方法"
+  },
+  "1692": {
+    "idx": 1692,
+    "A": "元素生成 脚本 教程",
+    "B": "如何编写脚本来生成内容元素",
+    "C": "生成 剧本 流程"
+  },
+  "1693": {
+    "idx": 1693,
+    "A": "AI 元素生成 脚本 教程",
+    "B": "利用智能技术编写元素生成脚本的教程",
+    "C": "AI 制作 文案脚本 流程"
+  },
+  "1694": {
+    "idx": 1694,
+    "A": "软件 元素生成 脚本 教程",
+    "B": "使用软件编写元素生成脚本的教程",
+    "C": "电脑端 创作 剧本 教学"
+  },
+  "1695": {
+    "idx": 1695,
+    "A": "在线 元素生成 脚本 教程",
+    "B": "在线编写元素生成脚本的教程",
+    "C": "在线 怎么做 脚本 流程"
+  },
+  "1696": {
+    "idx": 1696,
+    "A": "代码 元素生成 脚本 教程",
+    "B": "通过代码编写元素生成脚本的教程",
+    "C": "命令行 创作 文案脚本 怎么做"
+  },
+  "1697": {
+    "idx": 1697,
+    "A": "插件 元素生成 脚本 教程",
+    "B": "元素生成脚本插件的使用教程",
+    "C": "插件 制作 文案脚本 方法"
+  },
+  "1698": {
+    "idx": 1698,
+    "A": "元素生成 脚本 工具",
+    "B": "好用的元素生成脚本工具",
+    "C": "制作 剧本 流程"
+  },
+  "1699": {
+    "idx": 1699,
+    "A": "AI 元素生成 脚本 工具",
+    "B": "智能元素生成脚本工具推荐",
+    "C": "AI 制作 剧本 教学"
+  },
+  "1700": {
+    "idx": 1700,
+    "A": "软件 元素生成 脚本 工具",
+    "B": "好用的元素生成脚本软件",
+    "C": "电脑端 做 剧本 方法"
+  },
+  "1701": {
+    "idx": 1701,
+    "A": "在线 元素生成 脚本 工具",
+    "B": "在线元素生成脚本工具",
+    "C": "在线 制作 文案脚本 怎么做"
+  },
+  "1702": {
+    "idx": 1702,
+    "A": "代码 元素生成 脚本 工具",
+    "B": "用于编写元素生成的代码工具",
+    "C": "代码 生成 脚本 流程"
+  },
+  "1703": {
+    "idx": 1703,
+    "A": "插件 元素生成 脚本 工具",
+    "B": "好用的元素生成脚本插件",
+    "C": "插件 制作 剧本 教程"
+  },
+  "1704": {
+    "idx": 1704,
+    "A": "元素生成 脚本 技巧",
+    "B": "编写元素生成脚本的实用技巧",
+    "C": "制作 文案脚本 方法"
+  },
+  "1705": {
+    "idx": 1705,
+    "A": "AI 元素生成 脚本 技巧",
+    "B": "智能生成元素脚本的操作技巧",
+    "C": "AI 创作 剧本 教程"
+  },
+  "1706": {
+    "idx": 1706,
+    "A": "软件 元素生成 脚本 技巧",
+    "B": "使用软件编写元素脚本的技巧",
+    "C": "软件 做 剧本 流程"
+  },
+  "1707": {
+    "idx": 1707,
+    "A": "在线 元素生成 脚本 技巧",
+    "B": "在线编写元素脚本的技巧",
+    "C": "在线 做 剧本 怎么做"
+  },
+  "1708": {
+    "idx": 1708,
+    "A": "代码 元素生成 脚本 技巧",
+    "B": "编写元素生成代码的技巧",
+    "C": "命令行 生成 剧本 方法"
+  },
+  "1709": {
+    "idx": 1709,
+    "A": "插件 元素生成 脚本 技巧",
+    "B": "使用插件编写元素脚本的技巧",
+    "C": "插件 制作 文案脚本 怎么做"
+  },
+  "1710": {
+    "idx": 1710,
+    "A": "选取 剪辑脚本 教程",
+    "B": "怎么选取剪辑脚本的教程",
+    "C": "筛选 剪辑脚本 怎么做"
+  },
+  "1711": {
+    "idx": 1711,
+    "A": "AI 选取 剪辑脚本 教程",
+    "B": "如何用智能技术选取剪辑脚本的教程",
+    "C": "AI 筛选 时间轴 流程"
+  },
+  "1712": {
+    "idx": 1712,
+    "A": "软件 选取 剪辑脚本 教程",
+    "B": "有什么选取剪辑脚本的软件教程",
+    "C": "软件 筛选 时间轴 步骤"
+  },
+  "1713": {
+    "idx": 1713,
+    "A": "在线 选取 剪辑脚本 教程",
+    "B": "在线选取剪辑脚本的方法教程",
+    "C": "在线 挑选 剪辑脚本 方法"
+  },
+  "1715": {
+    "idx": 1715,
+    "A": "插件 选取 剪辑脚本 教程",
+    "B": "选取剪辑脚本的插件使用教程",
+    "C": "插件 挑选 时间轴 教学"
+  },
+  "1716": {
+    "idx": 1716,
+    "A": "选取 剪辑脚本 工具",
+    "B": "选取剪辑脚本的工具有哪些",
+    "C": "怎么选 卡点表 怎么做"
+  },
+  "1717": {
+    "idx": 1717,
+    "A": "AI 选取 剪辑脚本 工具",
+    "B": "好用的智能选取剪辑脚本工具",
+    "C": "AI 挑选 剪辑表 怎么做"
+  },
+  "1718": {
+    "idx": 1718,
+    "A": "软件 选取 剪辑脚本 工具",
+    "B": "有没有选取剪辑脚本的软件工具",
+    "C": "电脑端 筛选 时间轴 方法"
+  },
+  "1719": {
+    "idx": 1719,
+    "A": "在线 选取 剪辑脚本 工具",
+    "B": "在线选取剪辑脚本的工具推荐",
+    "C": "网页版 筛选 时间轴 流程"
+  },
+  "1720": {
+    "idx": 1720,
+    "A": "代码 选取 剪辑脚本 工具",
+    "B": "通过代码选取剪辑脚本的工具",
+    "C": "命令行 选 剪辑表 步骤"
+  },
+  "1721": {
+    "idx": 1721,
+    "A": "插件 选取 剪辑脚本 工具",
+    "B": "选取剪辑脚本的插件工具",
+    "C": "插件 筛选 卡点表 方法"
+  },
+  "1722": {
+    "idx": 1722,
+    "A": "选取 剪辑脚本 技巧",
+    "B": "选取剪辑脚本的实用技巧",
+    "C": "筛选 时间轴 教学"
+  },
+  "1723": {
+    "idx": 1723,
+    "A": "AI 选取 剪辑脚本 技巧",
+    "B": "利用智能技术选取剪辑脚本的技巧",
+    "C": "AI 挑选 剪辑表 怎么做"
+  },
+  "1724": {
+    "idx": 1724,
+    "A": "软件 选取 剪辑脚本 技巧",
+    "B": "软件选取剪辑脚本的操作技巧",
+    "C": "软件 挑选 剪辑表 方法"
+  },
+  "1725": {
+    "idx": 1725,
+    "A": "在线 选取 剪辑脚本 技巧",
+    "B": "在线选取剪辑脚本的技巧分享",
+    "C": "网页版 筛选 剪辑脚本 流程"
+  },
+  "1727": {
+    "idx": 1727,
+    "A": "插件 选取 剪辑脚本 技巧",
+    "B": "选取剪辑脚本的插件使用技巧",
+    "C": "插件 挑选 剪辑脚本 流程"
+  },
+  "1728": {
+    "idx": 1728,
+    "A": "裁切 剪辑脚本 教程",
+    "B": "怎么裁切剪辑脚本的教程",
+    "C": "切片 时间轴 教程"
+  },
+  "1729": {
+    "idx": 1729,
+    "A": "AI 裁切 剪辑脚本 教程",
+    "B": "如何用智能技术裁切剪辑脚本的教程",
+    "C": "AI 怎么裁 剪辑表 步骤"
+  },
+  "1730": {
+    "idx": 1730,
+    "A": "软件 裁切 剪辑脚本 教程",
+    "B": "有什么裁切剪辑脚本的软件教程",
+    "C": "软件 裁剪 时间轴 怎么做"
+  },
+  "1731": {
+    "idx": 1731,
+    "A": "在线 裁切 剪辑脚本 教程",
+    "B": "在线裁切剪辑脚本的方法教程",
+    "C": "网页版 裁剪 剪辑表 教学"
+  },
+  "1732": {
+    "idx": 1732,
+    "A": "代码 裁切 剪辑脚本 教程",
+    "B": "通过代码裁切剪辑脚本的教程",
+    "C": "命令行 切片 剪辑脚本 流程"
+  },
+  "1733": {
+    "idx": 1733,
+    "A": "插件 裁切 剪辑脚本 教程",
+    "B": "裁切剪辑脚本的插件使用教程",
+    "C": "插件 截取 剪辑脚本 方法"
+  },
+  "1734": {
+    "idx": 1734,
+    "A": "裁切 剪辑脚本 工具",
+    "B": "裁切剪辑脚本的工具有哪些",
+    "C": "截取 剪辑表 教学"
+  },
+  "1735": {
+    "idx": 1735,
+    "A": "AI 裁切 剪辑脚本 工具",
+    "B": "好用的智能裁切剪辑脚本工具",
+    "C": "AI 怎么裁 剪辑表 教学"
+  },
+  "1736": {
+    "idx": 1736,
+    "A": "软件 裁切 剪辑脚本 工具",
+    "B": "有没有裁切剪辑脚本的软件工具",
+    "C": "软件 截取 剪辑脚本 步骤"
+  },
+  "1737": {
+    "idx": 1737,
+    "A": "在线 裁切 剪辑脚本 工具",
+    "B": "在线裁切剪辑脚本的工具推荐",
+    "C": "网页版 怎么裁 时间轴 怎么做"
+  },
+  "1738": {
+    "idx": 1738,
+    "A": "代码 裁切 剪辑脚本 工具",
+    "B": "通过代码裁切剪辑脚本的工具",
+    "C": "代码 裁剪 剪辑脚本 教程"
+  },
+  "1739": {
+    "idx": 1739,
+    "A": "插件 裁切 剪辑脚本 工具",
+    "B": "裁切剪辑脚本的插件工具",
+    "C": "插件 怎么裁 卡点表 步骤"
+  },
+  "1740": {
+    "idx": 1740,
+    "A": "裁切 剪辑脚本 技巧",
+    "B": "裁切剪辑脚本的实用技巧",
+    "C": "截取 剪辑表 怎么做"
+  },
+  "1741": {
+    "idx": 1741,
+    "A": "AI 裁切 剪辑脚本 技巧",
+    "B": "利用智能技术裁切剪辑脚本的技巧",
+    "C": "AI 裁剪 卡点表 流程"
+  },
+  "1742": {
+    "idx": 1742,
+    "A": "软件 裁切 剪辑脚本 技巧",
+    "B": "软件裁切剪辑脚本的操作技巧",
+    "C": "电脑端 裁剪 剪辑脚本 方法"
+  },
+  "1743": {
+    "idx": 1743,
+    "A": "在线 裁切 剪辑脚本 技巧",
+    "B": "在线裁切剪辑脚本的技巧分享",
+    "C": "网页版 怎么裁 剪辑脚本 方法"
+  },
+  "1744": {
+    "idx": 1744,
+    "A": "代码 裁切 剪辑脚本 技巧",
+    "B": "通过代码裁切剪辑脚本的技巧",
+    "C": "命令行 怎么裁 时间轴 怎么做"
+  },
+  "1745": {
+    "idx": 1745,
+    "A": "插件 裁切 剪辑脚本 技巧",
+    "B": "裁切剪辑脚本的插件使用技巧",
+    "C": "插件 截取 卡点表 怎么做"
+  },
+  "1746": {
+    "idx": 1746,
+    "A": "添加 剪辑脚本 教程",
+    "B": "怎么添加剪辑脚本的教程",
+    "C": "加上 剪辑脚本 怎么做"
+  },
+  "1747": {
+    "idx": 1747,
+    "A": "AI 添加 剪辑脚本 教程",
+    "B": "如何用智能技术添加剪辑脚本的教程",
+    "C": "AI 怎么加 剪辑脚本 怎么做"
+  },
+  "1748": {
+    "idx": 1748,
+    "A": "软件 添加 剪辑脚本 教程",
+    "B": "有什么添加剪辑脚本的软件教程",
+    "C": "软件 加 卡点表 怎么做"
+  },
+  "1749": {
+    "idx": 1749,
+    "A": "在线 添加 剪辑脚本 教程",
+    "B": "在线添加剪辑脚本的方法教程",
+    "C": "网页版 添加 卡点表 流程"
+  },
+  "1750": {
+    "idx": 1750,
+    "A": "代码 添加 剪辑脚本 教程",
+    "B": "通过代码添加剪辑脚本的教程",
+    "C": "命令行 添加 时间轴 教学"
+  },
+  "1751": {
+    "idx": 1751,
+    "A": "插件 添加 剪辑脚本 教程",
+    "B": "添加剪辑脚本的插件使用教程",
+    "C": "插件 添加 剪辑表 怎么做"
+  },
+  "1752": {
+    "idx": 1752,
+    "A": "添加 剪辑脚本 工具",
+    "B": "有什么好用的剪辑脚本添加工具",
+    "C": "怎么加 卡点表 流程"
+  },
+  "1753": {
+    "idx": 1753,
+    "A": "AI 添加 剪辑脚本 工具",
+    "B": "怎么用智能工具添加剪辑脚本",
+    "C": "AI 加 剪辑表 怎么做"
+  },
+  "1754": {
+    "idx": 1754,
+    "A": "软件 添加 剪辑脚本 工具",
+    "B": "有哪些添加剪辑脚本的软件",
+    "C": "软件 加 剪辑表 步骤"
+  },
+  "1755": {
+    "idx": 1755,
+    "A": "在线 添加 剪辑脚本 工具",
+    "B": "在线添加剪辑脚本的方法",
+    "C": "在线 加 剪辑表 流程"
+  },
+  "1756": {
+    "idx": 1756,
+    "A": "代码 添加 剪辑脚本 工具",
+    "B": "如何通过代码添加剪辑脚本",
+    "C": "命令行 加 剪辑脚本 教程"
+  },
+  "1757": {
+    "idx": 1757,
+    "A": "插件 添加 剪辑脚本 工具",
+    "B": "有哪些添加剪辑脚本的插件",
+    "C": "插件 加上 剪辑脚本 方法"
+  },
+  "1758": {
+    "idx": 1758,
+    "A": "添加 剪辑脚本 技巧",
+    "B": "添加剪辑脚本有什么好技巧",
+    "C": "添加 时间轴 步骤"
+  },
+  "1759": {
+    "idx": 1759,
+    "A": "AI 添加 剪辑脚本 技巧",
+    "B": "利用智能技术添加剪辑脚本的技巧",
+    "C": "AI 加上 卡点表 怎么做"
+  },
+  "1760": {
+    "idx": 1760,
+    "A": "软件 添加 剪辑脚本 技巧",
+    "B": "软件添加剪辑脚本的操作技巧",
+    "C": "软件 怎么加 时间轴 流程"
+  },
+  "1761": {
+    "idx": 1761,
+    "A": "在线 添加 剪辑脚本 技巧",
+    "B": "在线添加剪辑脚本的实用技巧",
+    "C": "在线 添加 时间轴 怎么做"
+  },
+  "1762": {
+    "idx": 1762,
+    "A": "代码 添加 剪辑脚本 技巧",
+    "B": "编写代码添加剪辑脚本的技巧",
+    "C": "代码 怎么加 时间轴 教学"
+  },
+  "1763": {
+    "idx": 1763,
+    "A": "插件 添加 剪辑脚本 技巧",
+    "B": "使用插件添加剪辑脚本的技巧",
+    "C": "插件 加上 剪辑脚本 教学"
+  },
+  "1764": {
+    "idx": 1764,
+    "A": "剪除 剪辑脚本 教程",
+    "B": "剪辑脚本怎么剪除的教程",
+    "C": "截短 卡点表 教学"
+  },
+  "1765": {
+    "idx": 1765,
+    "A": "AI 剪除 剪辑脚本 教程",
+    "B": "如何用智能方式剪除剪辑脚本",
+    "C": "AI 剪掉 剪辑表 怎么做"
+  },
+  "1766": {
+    "idx": 1766,
+    "A": "软件 剪除 剪辑脚本 教程",
+    "B": "剪除剪辑脚本的软件使用教程",
+    "C": "软件 怎么剪 卡点表 方法"
+  },
+  "1767": {
+    "idx": 1767,
+    "A": "在线 剪除 剪辑脚本 教程",
+    "B": "在线剪除剪辑脚本的操作教程",
+    "C": "网页版 删掉 卡点表 流程"
+  },
+  "1768": {
+    "idx": 1768,
+    "A": "代码 剪除 剪辑脚本 教程",
+    "B": "通过代码剪除剪辑脚本的教程",
+    "C": "命令行 截短 卡点表 步骤"
+  },
+  "1769": {
+    "idx": 1769,
+    "A": "插件 剪除 剪辑脚本 教程",
+    "B": "使用插件剪除剪辑脚本的教程",
+    "C": "插件 截短 时间轴 流程"
+  },
+  "1770": {
+    "idx": 1770,
+    "A": "剪除 剪辑脚本 工具",
+    "B": "有没有剪除剪辑脚本的工具",
+    "C": "截短 卡点表 步骤"
+  },
+  "1771": {
+    "idx": 1771,
+    "A": "AI 剪除 剪辑脚本 工具",
+    "B": "好用的智能剪除剪辑脚本工具",
+    "C": "AI 怎么剪 时间轴 流程"
+  },
+  "1772": {
+    "idx": 1772,
+    "A": "软件 剪除 剪辑脚本 工具",
+    "B": "剪除剪辑脚本的软件有哪些",
+    "C": "软件 删掉 剪辑脚本 教学"
+  },
+  "1773": {
+    "idx": 1773,
+    "A": "在线 剪除 剪辑脚本 工具",
+    "B": "在线剪除剪辑脚本的工具推荐",
+    "C": "网页版 删掉 时间轴 怎么做"
+  },
+  "1774": {
+    "idx": 1774,
+    "A": "代码 剪除 剪辑脚本 工具",
+    "B": "剪除剪辑脚本的代码工具",
+    "C": "代码 删掉 剪辑表 怎么做"
+  },
+  "1775": {
+    "idx": 1775,
+    "A": "插件 剪除 剪辑脚本 工具",
+    "B": "剪除剪辑脚本的插件工具",
+    "C": "插件 删掉 时间轴 怎么做"
+  },
+  "1776": {
+    "idx": 1776,
+    "A": "剪除 剪辑脚本 技巧",
+    "B": "剪除剪辑脚本有什么技巧",
+    "C": "删掉 卡点表 怎么做"
+  },
+  "1777": {
+    "idx": 1777,
+    "A": "AI 剪除 剪辑脚本 技巧",
+    "B": "智能剪除剪辑脚本的技巧",
+    "C": "AI 怎么剪 剪辑脚本 怎么做"
+  },
+  "1778": {
+    "idx": 1778,
+    "A": "软件 剪除 剪辑脚本 技巧",
+    "B": "软件剪除剪辑脚本的技巧",
+    "C": "软件 删掉 剪辑脚本 流程"
+  },
+  "1779": {
+    "idx": 1779,
+    "A": "在线 剪除 剪辑脚本 技巧",
+    "B": "在线剪除剪辑脚本的技巧",
+    "C": "网页版 截短 剪辑脚本 怎么做"
+  },
+  "1780": {
+    "idx": 1780,
+    "A": "代码 剪除 剪辑脚本 技巧",
+    "B": "用代码剪除剪辑脚本的技巧",
+    "C": "命令行 怎么剪 卡点表 步骤"
+  },
+  "1781": {
+    "idx": 1781,
+    "A": "插件 剪除 剪辑脚本 技巧",
+    "B": "利用插件剪除剪辑脚本的技巧",
+    "C": "插件 怎么剪 剪辑脚本 怎么做"
+  },
+  "1782": {
+    "idx": 1782,
+    "A": "调整 剪辑脚本 教程",
+    "B": "调整剪辑脚本的详细教程",
+    "C": "调整 卡点表 教学"
+  },
+  "1783": {
+    "idx": 1783,
+    "A": "AI 调整 剪辑脚本 教程",
+    "B": "智能调整剪辑脚本的教程",
+    "C": "AI 调 卡点表 步骤"
+  },
+  "1784": {
+    "idx": 1784,
+    "A": "软件 调整 剪辑脚本 教程",
+    "B": "调整剪辑脚本的软件教程",
+    "C": "电脑端 优化 时间轴 教程"
+  },
+  "1785": {
+    "idx": 1785,
+    "A": "在线 调整 剪辑脚本 教程",
+    "B": "在线调整剪辑脚本的教程",
+    "C": "网页版 怎么调 时间轴 教学"
+  },
+  "1786": {
+    "idx": 1786,
+    "A": "代码 调整 剪辑脚本 教程",
+    "B": "通过代码调整剪辑脚本的教程",
+    "C": "代码 调 卡点表 怎么做"
+  },
+  "1788": {
+    "idx": 1788,
+    "A": "调整 剪辑脚本 工具",
+    "B": "调整剪辑脚本的工具推荐",
+    "C": "优化 剪辑脚本 教程"
+  },
+  "1789": {
+    "idx": 1789,
+    "A": "AI 调整 剪辑脚本 工具",
+    "B": "智能调整剪辑脚本的工具",
+    "C": "AI 怎么调 剪辑表 步骤"
+  },
+  "1790": {
+    "idx": 1790,
+    "A": "软件 调整 剪辑脚本 工具",
+    "B": "调整剪辑脚本的软件有哪些",
+    "C": "电脑端 怎么调 卡点表 方法"
+  },
+  "1791": {
+    "idx": 1791,
+    "A": "在线 调整 剪辑脚本 工具",
+    "B": "在线调整剪辑脚本的工具",
+    "C": "网页版 怎么调 时间轴 步骤"
+  },
+  "1792": {
+    "idx": 1792,
+    "A": "代码 调整 剪辑脚本 工具",
+    "B": "调整剪辑脚本的代码工具",
+    "C": "命令行 优化 剪辑表 流程"
+  },
+  "1793": {
+    "idx": 1793,
+    "A": "插件 调整 剪辑脚本 工具",
+    "B": "有哪些好用的视频剪辑脚本调整插件",
+    "C": "插件 调 剪辑表 教学"
+  },
+  "1794": {
+    "idx": 1794,
+    "A": "调整 剪辑脚本 技巧",
+    "B": "如何调整视频剪辑脚本",
+    "C": "怎么调 剪辑脚本 流程"
+  },
+  "1795": {
+    "idx": 1795,
+    "A": "AI 调整 剪辑脚本 技巧",
+    "B": "怎么利用智能技术调整视频剪辑脚本",
+    "C": "AI 优化 剪辑脚本 教程"
+  },
+  "1796": {
+    "idx": 1796,
+    "A": "软件 调整 剪辑脚本 技巧",
+    "B": "有什么软件可以调整视频剪辑脚本",
+    "C": "软件 优化 剪辑脚本 教程"
+  },
+  "1797": {
+    "idx": 1797,
+    "A": "在线 调整 剪辑脚本 技巧",
+    "B": "在线调整视频剪辑脚本的方法",
+    "C": "网页版 调整 剪辑脚本 步骤"
+  },
+  "1798": {
+    "idx": 1798,
+    "A": "代码 调整 剪辑脚本 技巧",
+    "B": "如何通过代码调整视频剪辑脚本",
+    "C": "代码 调整 时间轴 步骤"
+  },
+  "1800": {
+    "idx": 1800,
+    "A": "元素生成 配音文案 教程",
+    "B": "视频配音文案元素生成教程",
+    "C": "制作 配音文案 教学"
+  },
+  "1801": {
+    "idx": 1801,
+    "A": "AI 元素生成 配音文案 教程",
+    "B": "怎么用智能技术生成视频配音文案元素",
+    "C": "AI 做 旁白文案 流程"
+  },
+  "1802": {
+    "idx": 1802,
+    "A": "软件 元素生成 配音文案 教程",
+    "B": "有哪些生成配音文案元素的软件教程",
+    "C": "软件 创作 配音文案 教程"
+  },
+  "1803": {
+    "idx": 1803,
+    "A": "在线 元素生成 配音文案 教程",
+    "B": "在线生成配音文案元素的教程",
+    "C": "在线 怎么做 口播文案 怎么做"
+  },
+  "1804": {
+    "idx": 1804,
+    "A": "代码 元素生成 配音文案 教程",
+    "B": "如何用代码生成配音文案元素",
+    "C": "命令行 创作 口播文案 方法"
+  },
+  "1805": {
+    "idx": 1805,
+    "A": "插件 元素生成 配音文案 教程",
+    "B": "有哪些生成配音文案元素的插件教程",
+    "C": "插件 制作 旁白文案 方法"
+  },
+  "1806": {
+    "idx": 1806,
+    "A": "元素生成 配音文案 工具",
+    "B": "好用的配音文案元素生成工具",
+    "C": "制作 旁白文案 方法"
+  },
+  "1807": {
+    "idx": 1807,
+    "A": "AI 元素生成 配音文案 工具",
+    "B": "智能生成配音文案元素的工具",
+    "C": "AI 创作 口播文案 方法"
+  },
+  "1808": {
+    "idx": 1808,
+    "A": "软件 元素生成 配音文案 工具",
+    "B": "制作配音文案元素的软件工具",
+    "C": "电脑端 怎么做 口播文案 方法"
+  },
+  "1809": {
+    "idx": 1809,
+    "A": "在线 元素生成 配音文案 工具",
+    "B": "在线生成配音文案元素的工具",
+    "C": "在线 生成 口播文案 步骤"
+  },
+  "1810": {
+    "idx": 1810,
+    "A": "代码 元素生成 配音文案 工具",
+    "B": "用于生成配音文案元素的代码工具",
+    "C": "命令行 做 口播文案 流程"
+  },
+  "1811": {
+    "idx": 1811,
+    "A": "插件 元素生成 配音文案 工具",
+    "B": "生成配音文案元素的插件工具",
+    "C": "插件 生成 配音文案 方法"
+  },
+  "1812": {
+    "idx": 1812,
+    "A": "元素生成 配音文案 技巧",
+    "B": "配音文案元素生成技巧",
+    "C": "制作 口播文案 步骤"
+  },
+  "1813": {
+    "idx": 1813,
+    "A": "AI 元素生成 配音文案 技巧",
+    "B": "智能生成配音文案的技巧",
+    "C": "AI 创作 配音文案 教学"
+  },
+  "1814": {
+    "idx": 1814,
+    "A": "软件 元素生成 配音文案 技巧",
+    "B": "使用软件生成配音文案的技巧",
+    "C": "电脑端 做 口播文案 教程"
+  },
+  "1815": {
+    "idx": 1815,
+    "A": "在线 元素生成 配音文案 技巧",
+    "B": "在线生成配音文案的技巧",
+    "C": "网页版 怎么做 旁白文案 流程"
+  },
+  "1816": {
+    "idx": 1816,
+    "A": "代码 元素生成 配音文案 技巧",
+    "B": "通过代码生成配音文案的技巧",
+    "C": "代码 创作 口播文案 流程"
+  },
+  "1817": {
+    "idx": 1817,
+    "A": "插件 元素生成 配音文案 技巧",
+    "B": "使用插件生成配音文案的技巧",
+    "C": "插件 创作 口播文案 怎么做"
+  },
+  "1818": {
+    "idx": 1818,
+    "A": "重述 配音文案 教程",
+    "B": "配音文案重述教程",
+    "C": "润色 配音文案 教学"
+  },
+  "1819": {
+    "idx": 1819,
+    "A": "AI 重述 配音文案 教程",
+    "B": "智能重述配音文案的教程",
+    "C": "AI 重写 配音文案 步骤"
+  },
+  "1820": {
+    "idx": 1820,
+    "A": "软件 重述 配音文案 教程",
+    "B": "用软件重述配音文案的教程",
+    "C": "软件 重写 旁白文案 流程"
+  },
+  "1821": {
+    "idx": 1821,
+    "A": "在线 重述 配音文案 教程",
+    "B": "在线重述配音文案的教程",
+    "C": "网页版 怎么改 旁白文案 教学"
+  },
+  "1822": {
+    "idx": 1822,
+    "A": "代码 重述 配音文案 教程",
+    "B": "用代码重述配音文案的教程",
+    "C": "命令行 重写 配音文案 教程"
+  },
+  "1823": {
+    "idx": 1823,
+    "A": "插件 重述 配音文案 教程",
+    "B": "用插件重述配音文案的教程",
+    "C": "插件 润色 口播文案 教程"
+  },
+  "1824": {
+    "idx": 1824,
+    "A": "重述 配音文案 工具",
+    "B": "好用的配音文案重述工具",
+    "C": "重写 旁白文案 怎么做"
+  },
+  "1825": {
+    "idx": 1825,
+    "A": "AI 重述 配音文案 工具",
+    "B": "智能重述配音文案的工具",
+    "C": "AI 重写 配音文案 步骤"
+  },
+  "1826": {
+    "idx": 1826,
+    "A": "软件 重述 配音文案 工具",
+    "B": "重述配音文案的软件工具",
+    "C": "软件 润色 配音文案 方法"
+  },
+  "1827": {
+    "idx": 1827,
+    "A": "在线 重述 配音文案 工具",
+    "B": "在线重述配音文案的工具",
+    "C": "在线 润色 配音文案 步骤"
+  },
+  "1828": {
+    "idx": 1828,
+    "A": "代码 重述 配音文案 工具",
+    "B": "重述配音文案的代码工具",
+    "C": "命令行 润色 旁白文案 怎么做"
+  },
+  "1829": {
+    "idx": 1829,
+    "A": "插件 重述 配音文案 工具",
+    "B": "重述配音文案的插件工具",
+    "C": "插件 润色 配音文案 流程"
+  },
+  "1830": {
+    "idx": 1830,
+    "A": "重述 配音文案 技巧",
+    "B": "配音文案重述技巧",
+    "C": "改写 口播文案 流程"
+  },
+  "1831": {
+    "idx": 1831,
+    "A": "AI 重述 配音文案 技巧",
+    "B": "智能重述配音文案的技巧",
+    "C": "AI 重写 口播文案 怎么做"
+  },
+  "1832": {
+    "idx": 1832,
+    "A": "软件 重述 配音文案 技巧",
+    "B": "用软件重述配音文案的技巧",
+    "C": "电脑端 重写 旁白文案 教程"
+  },
+  "1833": {
+    "idx": 1833,
+    "A": "在线 重述 配音文案 技巧",
+    "B": "在线重述配音文案的技巧",
+    "C": "网页版 改写 配音文案 教程"
+  },
+  "1834": {
+    "idx": 1834,
+    "A": "代码 重述 配音文案 技巧",
+    "B": "如何用代码改写配音文案",
+    "C": "命令行 重写 配音文案 方法"
+  },
+  "1835": {
+    "idx": 1835,
+    "A": "插件 重述 配音文案 技巧",
+    "B": "有哪些改写配音文案的插件技巧",
+    "C": "插件 润色 配音文案 步骤"
+  },
+  "1836": {
+    "idx": 1836,
+    "A": "抠取 底图 教程",
+    "B": "怎样把底图抠出来教程",
+    "C": "怎么抠 底图 教程"
+  },
+  "1837": {
+    "idx": 1837,
+    "A": "AI 抠取 底图 教程",
+    "B": "如何利用智能技术抠取底图",
+    "C": "AI 怎么抠 背景图 流程"
+  },
+  "1838": {
+    "idx": 1838,
+    "A": "软件 抠取 底图 教程",
+    "B": "有什么抠取底图的软件教程",
+    "C": "软件 抠 背景图 教学"
+  },
+  "1839": {
+    "idx": 1839,
+    "A": "在线 抠取 底图 教程",
+    "B": "在线抠取底图的操作方法",
+    "C": "在线 抠 背景图 怎么做"
+  },
+  "1840": {
+    "idx": 1840,
+    "A": "代码 抠取 底图 教程",
+    "B": "如何用代码实现抠取底图",
+    "C": "命令行 分割 底图 教学"
+  },
+  "1841": {
+    "idx": 1841,
+    "A": "插件 抠取 底图 教程",
+    "B": "抠取底图的插件使用教程",
+    "C": "插件 抠图 背景图 怎么做"
+  },
+  "1842": {
+    "idx": 1842,
+    "A": "抠取 底图 工具",
+    "B": "好用的抠取底图工具推荐",
+    "C": "分割 底图 步骤"
+  },
+  "1843": {
+    "idx": 1843,
+    "A": "AI 抠取 底图 工具",
+    "B": "智能抠取底图的工具分享",
+    "C": "AI 抠 底图 流程"
+  },
+  "1844": {
+    "idx": 1844,
+    "A": "软件 抠取 底图 工具",
+    "B": "抠取底图的软件有哪些",
+    "C": "电脑端 分割 底图 流程"
+  },
+  "1845": {
+    "idx": 1845,
+    "A": "在线 抠取 底图 工具",
+    "B": "在线抠取底图的工具推荐",
+    "C": "网页版 抠图 背景图 流程"
+  },
+  "1846": {
+    "idx": 1846,
+    "A": "代码 抠取 底图 工具",
+    "B": "抠取底图的代码工具",
+    "C": "代码 抠图 打底图 教学"
+  },
+  "1847": {
+    "idx": 1847,
+    "A": "插件 抠取 底图 工具",
+    "B": "抠取底图的插件工具",
+    "C": "插件 抠 背景图 教程"
+  },
+  "1848": {
+    "idx": 1848,
+    "A": "抠取 底图 技巧",
+    "B": "抠取底图有什么技巧",
+    "C": "抠 底图 怎么做"
+  },
+  "1849": {
+    "idx": 1849,
+    "A": "AI 抠取 底图 技巧",
+    "B": "智能抠取底图的实用技巧",
+    "C": "AI 分割 打底图 教程"
+  },
+  "1850": {
+    "idx": 1850,
+    "A": "软件 抠取 底图 技巧",
+    "B": "使用软件抠取底图的技巧",
+    "C": "软件 分割 打底图 流程"
+  },
+  "1851": {
+    "idx": 1851,
+    "A": "在线 抠取 底图 技巧",
+    "B": "在线抠取底图的技巧分享",
+    "C": "在线 抠 背景图 流程"
+  },
+  "1852": {
+    "idx": 1852,
+    "A": "代码 抠取 底图 技巧",
+    "B": "抠取底图的代码编写技巧",
+    "C": "命令行 分割 背景图 教学"
+  },
+  "1853": {
+    "idx": 1853,
+    "A": "插件 抠取 底图 技巧",
+    "B": "抠取底图的插件操作技巧",
+    "C": "插件 抠图 打底图 怎么做"
+  },
+  "1854": {
+    "idx": 1854,
+    "A": "反推 底图 教程",
+    "B": "如何根据成品反推底图教程",
+    "C": "推断 打底图 流程"
+  },
+  "1856": {
+    "idx": 1856,
+    "A": "软件 反推 底图 教程",
+    "B": "用软件反推底图的教程",
+    "C": "电脑端 反推 背景图 教学"
+  },
+  "1857": {
+    "idx": 1857,
+    "A": "在线 反推 底图 教程",
+    "B": "在线反推底图的详细教程",
+    "C": "网页版 推断 打底图 教学"
+  },
+  "1858": {
+    "idx": 1858,
+    "A": "代码 反推 底图 教程",
+    "B": "如何通过代码反推底图",
+    "C": "命令行 分析 打底图 流程"
+  },
+  "1859": {
+    "idx": 1859,
+    "A": "插件 反推 底图 教程",
+    "B": "反推底图的插件使用教程",
+    "C": "插件 推断 打底图 怎么做"
+  },
+  "1860": {
+    "idx": 1860,
+    "A": "反推 底图 工具",
+    "B": "有哪些反推底图的工具",
+    "C": "推断 打底图 方法"
+  },
+  "1861": {
+    "idx": 1861,
+    "A": "AI 反推 底图 工具",
+    "B": "智能反推底图的工具",
+    "C": "AI 反推 打底图 流程"
+  },
+  "1862": {
+    "idx": 1862,
+    "A": "软件 反推 底图 工具",
+    "B": "反推底图的软件工具",
+    "C": "电脑端 推断 背景图 方法"
+  },
+  "1863": {
+    "idx": 1863,
+    "A": "在线 反推 底图 工具",
+    "B": "在线反推底图的工具",
+    "C": "网页版 怎么反推 底图 教学"
+  },
+  "1864": {
+    "idx": 1864,
+    "A": "代码 反推 底图 工具",
+    "B": "反推底图的代码工具",
+    "C": "命令行 分析 底图 方法"
+  },
+  "1865": {
+    "idx": 1865,
+    "A": "插件 反推 底图 工具",
+    "B": "反推底图的插件工具",
+    "C": "插件 分析 背景图 教学"
+  },
+  "1866": {
+    "idx": 1866,
+    "A": "反推 底图 技巧",
+    "B": "反推底图有什么技巧",
+    "C": "反推 打底图 方法"
+  },
+  "1868": {
+    "idx": 1868,
+    "A": "软件 反推 底图 技巧",
+    "B": "软件反推底图的技巧",
+    "C": "电脑端 分析 打底图 教学"
+  },
+  "1869": {
+    "idx": 1869,
+    "A": "在线 反推 底图 技巧",
+    "B": "在线反推底图的技巧",
+    "C": "网页版 分析 打底图 步骤"
+  },
+  "1870": {
+    "idx": 1870,
+    "A": "代码 反推 底图 技巧",
+    "B": "代码反推底图的技巧",
+    "C": "命令行 怎么反推 打底图 步骤"
+  },
+  "1871": {
+    "idx": 1871,
+    "A": "插件 反推 底图 技巧",
+    "B": "插件反推底图的技巧",
+    "C": "插件 反推 打底图 教学"
+  },
+  "1872": {
+    "idx": 1872,
+    "A": "抹除 底图 教程",
+    "B": "如何抹除底图上的内容教程",
+    "C": "去除 底图 流程"
+  },
+  "1873": {
+    "idx": 1873,
+    "A": "AI 抹除 底图 教程",
+    "B": "智能抹除底图的教程",
+    "C": "AI 去除 底图 教程"
+  },
+  "1874": {
+    "idx": 1874,
+    "A": "软件 抹除 底图 教程",
+    "B": "用软件抹除底图的教程",
+    "C": "电脑端 去掉 底图 教程"
+  },
+  "1875": {
+    "idx": 1875,
+    "A": "在线 抹除 底图 教程",
+    "B": "在线抹除底图的操作教程",
+    "C": "网页版 抹除 打底图 方法"
+  },
+  "1876": {
+    "idx": 1876,
+    "A": "代码 抹除 底图 教程",
+    "B": "怎么用代码把底图抹除掉",
+    "C": "命令行 去除 背景图 流程"
+  },
+  "1877": {
+    "idx": 1877,
+    "A": "插件 抹除 底图 教程",
+    "B": "有哪些插件可以用来抹除底图",
+    "C": "插件 去除 底图 教学"
+  },
+  "1878": {
+    "idx": 1878,
+    "A": "抹除 底图 工具",
+    "B": "抹除底图用什么工具比较好",
+    "C": "抹除 底图 怎么做"
+  },
+  "1879": {
+    "idx": 1879,
+    "A": "AI 抹除 底图 工具",
+    "B": "有什么智能工具可以自动抹除底图",
+    "C": "AI 怎么去掉 打底图 教学"
+  },
+  "1880": {
+    "idx": 1880,
+    "A": "软件 抹除 底图 工具",
+    "B": "抹除底图的软件有哪些",
+    "C": "电脑端 怎么去掉 打底图 教程"
+  },
+  "1881": {
+    "idx": 1881,
+    "A": "在线 抹除 底图 工具",
+    "B": "在线抹除底图的工具有哪些",
+    "C": "网页版 消除 底图 教学"
+  },
+  "1882": {
+    "idx": 1882,
+    "A": "代码 抹除 底图 工具",
+    "B": "用代码抹除底图的工具推荐",
+    "C": "代码 怎么去掉 底图 流程"
+  },
+  "1883": {
+    "idx": 1883,
+    "A": "插件 抹除 底图 工具",
+    "B": "有什么插件能帮我抹除底图",
+    "C": "插件 去除 打底图 流程"
+  },
+  "1884": {
+    "idx": 1884,
+    "A": "抹除 底图 技巧",
+    "B": "抹除底图有哪些实用技巧",
+    "C": "消除 背景图 流程"
+  },
+  "1885": {
+    "idx": 1885,
+    "A": "AI 抹除 底图 技巧",
+    "B": "利用智能技术抹除底图的技巧",
+    "C": "AI 消除 打底图 流程"
+  },
+  "1886": {
+    "idx": 1886,
+    "A": "软件 抹除 底图 技巧",
+    "B": "使用软件抹除底图的操作技巧",
+    "C": "软件 消除 打底图 方法"
+  },
+  "1887": {
+    "idx": 1887,
+    "A": "在线 抹除 底图 技巧",
+    "B": "在线抹除底图有什么好方法",
+    "C": "网页版 去除 打底图 方法"
+  },
+  "1888": {
+    "idx": 1888,
+    "A": "代码 抹除 底图 技巧",
+    "B": "通过代码抹除底图的技巧分享",
+    "C": "命令行 抹除 打底图 教学"
+  },
+  "1889": {
+    "idx": 1889,
+    "A": "插件 抹除 底图 技巧",
+    "B": "使用插件抹除底图的技巧",
+    "C": "插件 去除 底图 流程"
+  },
+  "1890": {
+    "idx": 1890,
+    "A": "风格化 底图 教程",
+    "B": "如何给底图做风格化处理",
+    "C": "怎么转风格 打底图 步骤"
+  },
+  "1891": {
+    "idx": 1891,
+    "A": "AI 风格化 底图 教程",
+    "B": "怎么用智能技术给底图进行风格化",
+    "C": "AI 怎么转风格 背景图 步骤"
+  },
+  "1892": {
+    "idx": 1892,
+    "A": "软件 风格化 底图 教程",
+    "B": "有哪些软件可以实现底图风格化",
+    "C": "电脑端 风格迁移 背景图 教学"
+  },
+  "1893": {
+    "idx": 1893,
+    "A": "在线 风格化 底图 教程",
+    "B": "在线进行底图风格化的教程",
+    "C": "网页版 风格迁移 打底图 流程"
+  },
+  "1894": {
+    "idx": 1894,
+    "A": "代码 风格化 底图 教程",
+    "B": "如何用代码实现底图风格化",
+    "C": "代码 怎么转风格 打底图 教学"
+  },
+  "1895": {
+    "idx": 1895,
+    "A": "插件 风格化 底图 教程",
+    "B": "有什么插件可以给底图添加风格",
+    "C": "插件 风格迁移 背景图 怎么做"
+  },
+  "1896": {
+    "idx": 1896,
+    "A": "风格化 底图 工具",
+    "B": "底图风格化处理用什么工具",
+    "C": "怎么转风格 底图 教学"
+  },
+  "1897": {
+    "idx": 1897,
+    "A": "AI 风格化 底图 工具",
+    "B": "有哪些智能工具能给底图做风格化",
+    "C": "AI 风格迁移 打底图 教程"
+  },
+  "1898": {
+    "idx": 1898,
+    "A": "软件 风格化 底图 工具",
+    "B": "好用的底图风格化软件推荐",
+    "C": "软件 风格迁移 底图 步骤"
+  },
+  "1899": {
+    "idx": 1899,
+    "A": "在线 风格化 底图 工具",
+    "B": "在线底图风格化处理工具",
+    "C": "在线 转风格 背景图 教程"
+  },
+  "1900": {
+    "idx": 1900,
+    "A": "代码 风格化 底图 工具",
+    "B": "有没有能做底图风格化的代码工具",
+    "C": "命令行 转风格 底图 教程"
+  },
+  "1901": {
+    "idx": 1901,
+    "A": "插件 风格化 底图 工具",
+    "B": "可以实现底图风格化的插件有哪些",
+    "C": "插件 风格迁移 底图 流程"
+  },
+  "1902": {
+    "idx": 1902,
+    "A": "风格化 底图 技巧",
+    "B": "底图风格化有哪些处理技巧",
+    "C": "风格迁移 背景图 方法"
+  },
+  "1903": {
+    "idx": 1903,
+    "A": "AI 风格化 底图 技巧",
+    "B": "智能处理底图风格化的技巧",
+    "C": "AI 转风格 背景图 步骤"
+  },
+  "1904": {
+    "idx": 1904,
+    "A": "软件 风格化 底图 技巧",
+    "B": "使用软件进行底图风格化的技巧",
+    "C": "软件 怎么转风格 打底图 流程"
+  },
+  "1905": {
+    "idx": 1905,
+    "A": "在线 风格化 底图 技巧",
+    "B": "在线处理底图风格化的技巧",
+    "C": "在线 风格迁移 背景图 流程"
+  },
+  "1906": {
+    "idx": 1906,
+    "A": "代码 风格化 底图 技巧",
+    "B": "用代码进行底图风格化的技巧",
+    "C": "命令行 风格化 打底图 教学"
+  },
+  "1907": {
+    "idx": 1907,
+    "A": "插件 风格化 底图 技巧",
+    "B": "通过插件实现底图风格化的技巧",
+    "C": "插件 风格化 打底图 方法"
+  },
+  "1908": {
+    "idx": 1908,
+    "A": "替换 底图 教程",
+    "B": "如何把底图替换掉",
+    "C": "替换成 底图 教程"
+  },
+  "1909": {
+    "idx": 1909,
+    "A": "AI 替换 底图 教程",
+    "B": "怎么用智能技术替换底图",
+    "C": "AI 怎么换 背景图 怎么做"
+  },
+  "1910": {
+    "idx": 1910,
+    "A": "软件 替换 底图 教程",
+    "B": "替换底图用什么软件好",
+    "C": "软件 换 打底图 教学"
+  },
+  "1911": {
+    "idx": 1911,
+    "A": "在线 替换 底图 教程",
+    "B": "在线替换底图的教程",
+    "C": "在线 替换成 底图 步骤"
+  },
+  "1912": {
+    "idx": 1912,
+    "A": "代码 替换 底图 教程",
+    "B": "如何通过代码替换底图",
+    "C": "代码 怎么换 打底图 方法"
+  },
+  "1913": {
+    "idx": 1913,
+    "A": "插件 替换 底图 教程",
+    "B": "有什么插件可以用来替换底图",
+    "C": "插件 怎么换 打底图 教学"
+  },
+  "1914": {
+    "idx": 1914,
+    "A": "替换 底图 工具",
+    "B": "替换底图需要用到什么工具",
+    "C": "换 底图 教程"
+  },
+  "1915": {
+    "idx": 1915,
+    "A": "AI 替换 底图 工具",
+    "B": "有哪些智能工具可以替换底图",
+    "C": "AI 替换成 打底图 方法"
+  },
+  "1916": {
+    "idx": 1916,
+    "A": "软件 替换 底图 工具",
+    "B": "有什么软件可以替换底图",
+    "C": "软件 换 背景图 步骤"
+  },
+  "1917": {
+    "idx": 1917,
+    "A": "在线 替换 底图 工具",
+    "B": "怎么在线替换底图",
+    "C": "网页版 换 底图 步骤"
+  },
+  "1918": {
+    "idx": 1918,
+    "A": "代码 替换 底图 工具",
+    "B": "如何用代码实现底图替换",
+    "C": "代码 替换成 打底图 教学"
+  },
+  "1919": {
+    "idx": 1919,
+    "A": "插件 替换 底图 工具",
+    "B": "有没有替换底图的插件",
+    "C": "插件 替换成 背景图 教程"
+  },
+  "1920": {
+    "idx": 1920,
+    "A": "替换 底图 技巧",
+    "B": "替换底图有什么好方法",
+    "C": "替换成 打底图 怎么做"
+  },
+  "1921": {
+    "idx": 1921,
+    "A": "AI 替换 底图 技巧",
+    "B": "怎么用智能技术替换底图",
+    "C": "AI 换 背景图 方法"
+  },
+  "1922": {
+    "idx": 1922,
+    "A": "软件 替换 底图 技巧",
+    "B": "软件替换底图的操作方法",
+    "C": "软件 替换成 背景图 教学"
+  },
+  "1923": {
+    "idx": 1923,
+    "A": "在线 替换 底图 技巧",
+    "B": "在线替换底图的技巧有哪些",
+    "C": "在线 换 底图 教程"
+  },
+  "1924": {
+    "idx": 1924,
+    "A": "代码 替换 底图 技巧",
+    "B": "用代码替换底图的思路",
+    "C": "命令行 替换成 背景图 教学"
+  },
+  "1925": {
+    "idx": 1925,
+    "A": "插件 替换 底图 技巧",
+    "B": "插件替换底图的使用技巧",
+    "C": "插件 替换 打底图 怎么做"
+  },
+  "1926": {
+    "idx": 1926,
+    "A": "增强 底图 教程",
+    "B": "底图增强的详细教程",
+    "C": "修复 背景图 步骤"
+  },
+  "1927": {
+    "idx": 1927,
+    "A": "AI 增强 底图 教程",
+    "B": "如何利用智能技术增强底图效果",
+    "C": "AI 怎么增强 背景图 方法"
+  },
+  "1929": {
+    "idx": 1929,
+    "A": "在线 增强 底图 教程",
+    "B": "在线增强底图的教程",
+    "C": "在线 怎么增强 底图 步骤"
+  },
+  "1930": {
+    "idx": 1930,
+    "A": "代码 增强 底图 教程",
+    "B": "通过代码增强底图的方法",
+    "C": "命令行 超分 底图 怎么做"
+  },
+  "1931": {
+    "idx": 1931,
+    "A": "插件 增强 底图 教程",
+    "B": "插件增强底图的教程",
+    "C": "插件 提升画质 底图 教学"
+  },
+  "1932": {
+    "idx": 1932,
+    "A": "增强 底图 工具",
+    "B": "有哪些增强底图的工具",
+    "C": "怎么增强 底图 教学"
+  },
+  "1933": {
+    "idx": 1933,
+    "A": "AI 增强 底图 工具",
+    "B": "智能增强底图的工具推荐",
+    "C": "AI 增强 打底图 教程"
+  },
+  "1934": {
+    "idx": 1934,
+    "A": "软件 增强 底图 工具",
+    "B": "增强底图的软件有哪些",
+    "C": "软件 超分 底图 步骤"
+  },
+  "1935": {
+    "idx": 1935,
+    "A": "在线 增强 底图 工具",
+    "B": "在线增强底图的工具",
+    "C": "在线 怎么增强 打底图 教程"
+  },
+  "1936": {
+    "idx": 1936,
+    "A": "代码 增强 底图 工具",
+    "B": "增强底图的代码工具",
+    "C": "命令行 修复 背景图 教程"
+  },
+  "1937": {
+    "idx": 1937,
+    "A": "插件 增强 底图 工具",
+    "B": "好用的底图增强插件",
+    "C": "插件 提升画质 打底图 方法"
+  },
+  "1938": {
+    "idx": 1938,
+    "A": "增强 底图 技巧",
+    "B": "底图增强有哪些实用技巧",
+    "C": "提升画质 底图 方法"
+  },
+  "1939": {
+    "idx": 1939,
+    "A": "AI 增强 底图 技巧",
+    "B": "智能增强底图的技巧",
+    "C": "AI 超分 背景图 方法"
+  },
+  "1941": {
+    "idx": 1941,
+    "A": "在线 增强 底图 技巧",
+    "B": "在线增强底图的方法",
+    "C": "在线 增强 背景图 方法"
+  },
+  "1942": {
+    "idx": 1942,
+    "A": "代码 增强 底图 技巧",
+    "B": "代码增强底图的技巧",
+    "C": "代码 怎么增强 底图 教程"
+  },
+  "1943": {
+    "idx": 1943,
+    "A": "插件 增强 底图 技巧",
+    "B": "插件增强底图的技巧",
+    "C": "插件 提升画质 打底图 方法"
+  },
+  "1944": {
+    "idx": 1944,
+    "A": "选取 样图 教程",
+    "B": "如何选取合适的样图",
+    "C": "筛选 样图 怎么做"
+  },
+  "1945": {
+    "idx": 1945,
+    "A": "AI 选取 样图 教程",
+    "B": "智能选取样图的教程",
+    "C": "AI 挑选 draft 教学"
+  },
+  "1946": {
+    "idx": 1946,
+    "A": "软件 选取 样图 教程",
+    "B": "软件选取样图的教程",
+    "C": "电脑端 筛选 样图 教程"
+  },
+  "1947": {
+    "idx": 1947,
+    "A": "在线 选取 样图 教程",
+    "B": "在线选取样图的教程",
+    "C": "网页版 选 效果图 怎么做"
+  },
+  "1948": {
+    "idx": 1948,
+    "A": "代码 选取 样图 教程",
+    "B": "代码选取样图的教程",
+    "C": "代码 筛选 draft 方法"
+  },
+  "1949": {
+    "idx": 1949,
+    "A": "插件 选取 样图 教程",
+    "B": "插件选取样图的教程",
+    "C": "插件 怎么选 效果图 方法"
+  },
+  "1950": {
+    "idx": 1950,
+    "A": "选取 样图 工具",
+    "B": "选取样图的工具有哪些",
+    "C": "选 样图 教程"
+  },
+  "1951": {
+    "idx": 1951,
+    "A": "AI 选取 样图 工具",
+    "B": "智能选取样图的工具",
+    "C": "AI 筛选 候选图 怎么做"
+  },
+  "1952": {
+    "idx": 1952,
+    "A": "软件 选取 样图 工具",
+    "B": "选取样图的软件推荐",
+    "C": "电脑端 怎么选 样图 步骤"
+  },
+  "1953": {
+    "idx": 1953,
+    "A": "在线 选取 样图 工具",
+    "B": "在线选取样图的工具",
+    "C": "网页版 筛选 候选图 流程"
+  },
+  "1954": {
+    "idx": 1954,
+    "A": "代码 选取 样图 工具",
+    "B": "选取样图的代码工具",
+    "C": "命令行 挑选 候选图 怎么做"
+  },
+  "1955": {
+    "idx": 1955,
+    "A": "插件 选取 样图 工具",
+    "B": "选取样图的插件推荐",
+    "C": "插件 筛选 效果图 流程"
+  },
+  "1956": {
+    "idx": 1956,
+    "A": "选取 样图 技巧",
+    "B": "选取样图有什么技巧",
+    "C": "筛选 draft 教学"
+  },
+  "1957": {
+    "idx": 1957,
+    "A": "AI 选取 样图 技巧",
+    "B": "智能选取样图的技巧",
+    "C": "AI 挑选 draft 方法"
+  },
+  "1958": {
+    "idx": 1958,
+    "A": "软件 选取 样图 技巧",
+    "B": "怎么用软件挑选合适的参考图",
+    "C": "软件 选 效果图 方法"
+  },
+  "1959": {
+    "idx": 1959,
+    "A": "在线 选取 样图 技巧",
+    "B": "在线挑选参考图有什么技巧",
+    "C": "在线 选 候选图 方法"
+  },
+  "1960": {
+    "idx": 1960,
+    "A": "代码 选取 样图 技巧",
+    "B": "如何通过代码来筛选参考图",
+    "C": "命令行 选 效果图 流程"
+  },
+  "1961": {
+    "idx": 1961,
+    "A": "插件 选取 样图 技巧",
+    "B": "有哪些插件可以辅助挑选参考图",
+    "C": "插件 怎么选 效果图 步骤"
+  },
+  "1962": {
+    "idx": 1962,
+    "A": "反推 样图 教程",
+    "B": "怎么根据图片反推提示词",
+    "C": "分析 draft 流程"
+  },
+  "1963": {
+    "idx": 1963,
+    "A": "AI 反推 样图 教程",
+    "B": "如何利用智能技术从图片反推提示词",
+    "C": "AI 推断 样图 方法"
+  },
+  "1964": {
+    "idx": 1964,
+    "A": "软件 反推 样图 教程",
+    "B": "用什么软件可以从图片反推提示词",
+    "C": "软件 分析 候选图 流程"
+  },
+  "1965": {
+    "idx": 1965,
+    "A": "在线 反推 样图 教程",
+    "B": "在线反推图片提示词的方法",
+    "C": "在线 推断 draft 怎么做"
+  },
+  "1966": {
+    "idx": 1966,
+    "A": "代码 反推 样图 教程",
+    "B": "有没有通过代码反推图片提示词的教程",
+    "C": "命令行 怎么反推 候选图 流程"
+  },
+  "1967": {
+    "idx": 1967,
+    "A": "插件 反推 样图 教程",
+    "B": "有哪些插件能实现图片反推提示词",
+    "C": "插件 反推 效果图 流程"
+  },
+  "1968": {
+    "idx": 1968,
+    "A": "反推 样图 工具",
+    "B": "有什么好用的图片反推工具",
+    "C": "反推 候选图 方法"
+  },
+  "1969": {
+    "idx": 1969,
+    "A": "AI 反推 样图 工具",
+    "B": "好用的智能图片反推工具有哪些",
+    "C": "AI 分析 效果图 教学"
+  },
+  "1970": {
+    "idx": 1970,
+    "A": "软件 反推 样图 工具",
+    "B": "求推荐好用的图片反推软件",
+    "C": "软件 推断 样图 教学"
+  },
+  "1971": {
+    "idx": 1971,
+    "A": "在线 反推 样图 工具",
+    "B": "有没有在线反推图片的工具",
+    "C": "网页版 分析 draft 教学"
+  },
+  "1972": {
+    "idx": 1972,
+    "A": "代码 反推 样图 工具",
+    "B": "求好用的图片反推代码工具",
+    "C": "命令行 分析 draft 怎么做"
+  },
+  "1973": {
+    "idx": 1973,
+    "A": "插件 反推 样图 工具",
+    "B": "有哪些好用的图片反推插件",
+    "C": "插件 分析 效果图 流程"
+  },
+  "1974": {
+    "idx": 1974,
+    "A": "反推 样图 技巧",
+    "B": "图片反推提示词有什么技巧",
+    "C": "分析 样图 怎么做"
+  },
+  "1975": {
+    "idx": 1975,
+    "A": "AI 反推 样图 技巧",
+    "B": "智能反推图片提示词的技巧有哪些",
+    "C": "AI 推断 draft 流程"
+  },
+  "1976": {
+    "idx": 1976,
+    "A": "软件 反推 样图 技巧",
+    "B": "使用软件反推图片提示词的技巧",
+    "C": "软件 分析 样图 流程"
+  },
+  "1977": {
+    "idx": 1977,
+    "A": "在线 反推 样图 技巧",
+    "B": "在线反推图片提示词的技巧分享",
+    "C": "网页版 怎么反推 候选图 怎么做"
+  },
+  "1978": {
+    "idx": 1978,
+    "A": "代码 反推 样图 技巧",
+    "B": "通过代码反推图片提示词的技巧",
+    "C": "代码 怎么反推 draft 教程"
+  },
+  "1979": {
+    "idx": 1979,
+    "A": "插件 反推 样图 技巧",
+    "B": "使用插件反推图片提示词的技巧",
+    "C": "插件 推断 draft 方法"
+  },
+  "1980": {
+    "idx": 1980,
+    "A": "增强 样图 教程",
+    "B": "如何对图片进行画质增强",
+    "C": "超分 样图 方法"
+  },
+  "1981": {
+    "idx": 1981,
+    "A": "AI 增强 样图 教程",
+    "B": "怎么用智能技术增强图片画质",
+    "C": "AI 修复 draft 教程"
+  },
+  "1982": {
+    "idx": 1982,
+    "A": "软件 增强 样图 教程",
+    "B": "用什么软件可以增强图片画质",
+    "C": "软件 超分 draft 教学"
+  },
+  "1983": {
+    "idx": 1983,
+    "A": "在线 增强 样图 教程",
+    "B": "在线增强图片画质的方法",
+    "C": "在线 超分 draft 方法"
+  },
+  "1984": {
+    "idx": 1984,
+    "A": "代码 增强 样图 教程",
+    "B": "如何通过代码实现图片画质增强",
+    "C": "代码 提升画质 候选图 怎么做"
+  },
+  "1985": {
+    "idx": 1985,
+    "A": "插件 增强 样图 教程",
+    "B": "有哪些插件可以增强图片画质",
+    "C": "插件 怎么增强 候选图 怎么做"
+  },
+  "1986": {
+    "idx": 1986,
+    "A": "增强 样图 工具",
+    "B": "有哪些好用的图片增强工具",
+    "C": "提升画质 draft 步骤"
+  },
+  "1987": {
+    "idx": 1987,
+    "A": "AI 增强 样图 工具",
+    "B": "好用的智能图片画质增强工具有哪些",
+    "C": "AI 超分 效果图 怎么做"
+  },
+  "1988": {
+    "idx": 1988,
+    "A": "软件 增强 样图 工具",
+    "B": "求推荐好用的图片增强软件",
+    "C": "电脑端 增强 样图 流程"
+  },
+  "1989": {
+    "idx": 1989,
+    "A": "在线 增强 样图 工具",
+    "B": "有没有在线增强图片画质的工具",
+    "C": "在线 修复 draft 步骤"
+  },
+  "1990": {
+    "idx": 1990,
+    "A": "代码 增强 样图 工具",
+    "B": "求好用的图片画质增强代码工具",
+    "C": "命令行 增强 效果图 怎么做"
+  },
+  "1991": {
+    "idx": 1991,
+    "A": "插件 增强 样图 工具",
+    "B": "有哪些好用的图片增强插件",
+    "C": "插件 修复 样图 步骤"
+  },
+  "1992": {
+    "idx": 1992,
+    "A": "增强 样图 技巧",
+    "B": "图片画质增强有什么技巧",
+    "C": "怎么增强 效果图 教学"
+  },
+  "1993": {
+    "idx": 1993,
+    "A": "AI 增强 样图 技巧",
+    "B": "智能增强图片画质的技巧有哪些",
+    "C": "AI 增强 样图 教学"
+  },
+  "1994": {
+    "idx": 1994,
+    "A": "软件 增强 样图 技巧",
+    "B": "使用软件增强图片画质的技巧",
+    "C": "电脑端 怎么增强 样图 方法"
+  },
+  "1995": {
+    "idx": 1995,
+    "A": "在线 增强 样图 技巧",
+    "B": "在线增强图片画质的技巧分享",
+    "C": "网页版 超分 效果图 怎么做"
+  },
+  "1996": {
+    "idx": 1996,
+    "A": "代码 增强 样图 技巧",
+    "B": "通过代码增强图片画质的技巧",
+    "C": "命令行 增强 效果图 步骤"
+  },
+  "1997": {
+    "idx": 1997,
+    "A": "插件 增强 样图 技巧",
+    "B": "使用插件增强图片画质的技巧",
+    "C": "插件 提升画质 效果图 流程"
+  },
+  "1998": {
+    "idx": 1998,
+    "A": "剪除 分镜视频 教程",
+    "B": "如何剪辑分镜视频的教程",
+    "C": "剪掉 分镜片段 步骤"
+  },
+  "1999": {
+    "idx": 1999,
+    "A": "AI 剪除 分镜视频 教程",
+    "B": "怎么用智能技术剪辑分镜视频",
+    "C": "AI 截短 分镜片段 教学"
+  },
+  "2000": {
+    "idx": 2000,
+    "A": "软件 剪除 分镜视频 教程",
+    "B": "剪辑分镜视频的软件使用教程",
+    "C": "软件 剪掉 分镜视频 流程"
+  },
+  "2002": {
+    "idx": 2002,
+    "A": "代码 剪除 分镜视频 教程",
+    "B": "通过编程代码剪辑分镜视频的方法",
+    "C": "代码 怎么剪 分镜视频 怎么做"
+  },
+  "2003": {
+    "idx": 2003,
+    "A": "插件 剪除 分镜视频 教程",
+    "B": "剪辑分镜视频的插件使用教程",
+    "C": "插件 截短 分镜视频 方法"
+  },
+  "2004": {
+    "idx": 2004,
+    "A": "剪除 分镜视频 工具",
+    "B": "有哪些剪辑分镜视频的工具",
+    "C": "截短 分镜视频 流程"
+  },
+  "2005": {
+    "idx": 2005,
+    "A": "AI 剪除 分镜视频 工具",
+    "B": "好用的智能分镜视频剪辑工具",
+    "C": "AI 截短 分镜片段 怎么做"
+  },
+  "2006": {
+    "idx": 2006,
+    "A": "软件 剪除 分镜视频 工具",
+    "B": "剪辑分镜视频的软件推荐",
+    "C": "软件 剪掉 分镜视频 方法"
+  },
+  "2007": {
+    "idx": 2007,
+    "A": "在线 剪除 分镜视频 工具",
+    "B": "在线剪辑分镜视频的工具",
+    "C": "网页版 删掉 分镜视频 流程"
+  },
+  "2008": {
+    "idx": 2008,
+    "A": "代码 剪除 分镜视频 工具",
+    "B": "剪辑分镜视频的代码工具",
+    "C": "代码 剪掉 分镜片段 教程"
+  },
+  "2009": {
+    "idx": 2009,
+    "A": "插件 剪除 分镜视频 工具",
+    "B": "剪辑分镜视频的插件工具",
+    "C": "插件 剪掉 分镜片段 步骤"
+  },
+  "2010": {
+    "idx": 2010,
+    "A": "剪除 分镜视频 技巧",
+    "B": "剪辑分镜视频的小技巧",
+    "C": "剪掉 分镜视频 教程"
+  },
+  "2011": {
+    "idx": 2011,
+    "A": "AI 剪除 分镜视频 技巧",
+    "B": "利用智能技术剪辑分镜视频的技巧",
+    "C": "AI 删掉 分镜视频 教学"
+  },
+  "2012": {
+    "idx": 2012,
+    "A": "软件 剪除 分镜视频 技巧",
+    "B": "使用软件剪辑分镜视频的技巧",
+    "C": "电脑端 删掉 分镜片段 教学"
+  },
+  "2013": {
+    "idx": 2013,
+    "A": "在线 剪除 分镜视频 技巧",
+    "B": "在线剪辑分镜视频的技巧",
+    "C": "网页版 剪掉 分镜视频 步骤"
+  },
+  "2014": {
+    "idx": 2014,
+    "A": "代码 剪除 分镜视频 技巧",
+    "B": "用代码剪辑分镜视频的技巧",
+    "C": "命令行 怎么剪 分镜片段 教程"
+  },
+  "2015": {
+    "idx": 2015,
+    "A": "插件 剪除 分镜视频 技巧",
+    "B": "剪辑分镜视频的插件使用技巧",
+    "C": "插件 剪掉 分镜片段 怎么做"
+  },
+  "2016": {
+    "idx": 2016,
+    "A": "抠取 拼图 教程",
+    "B": "如何从拼图中抠图的教程",
+    "C": "抠 拼图 教学"
+  },
+  "2017": {
+    "idx": 2017,
+    "A": "AI 抠取 拼图 教程",
+    "B": "怎么用智能技术从拼图中抠图",
+    "C": "AI 分割 对比图 方法"
+  },
+  "2018": {
+    "idx": 2018,
+    "A": "软件 抠取 拼图 教程",
+    "B": "抠取拼图的软件操作教程",
+    "C": "软件 抠 拼图 教程"
+  },
+  "2019": {
+    "idx": 2019,
+    "A": "在线 抠取 拼图 教程",
+    "B": "在线抠取拼图的教程",
+    "C": "在线 怎么抠 长图 怎么做"
+  },
+  "2020": {
+    "idx": 2020,
+    "A": "代码 抠取 拼图 教程",
+    "B": "通过编程代码抠取拼图的方法",
+    "C": "命令行 分割 长图 流程"
+  },
+  "2021": {
+    "idx": 2021,
+    "A": "插件 抠取 拼图 教程",
+    "B": "抠取拼图的插件使用教程",
+    "C": "插件 怎么抠 对比图 流程"
+  },
+  "2022": {
+    "idx": 2022,
+    "A": "抠取 拼图 工具",
+    "B": "有哪些抠取拼图的工具",
+    "C": "抠 长图 流程"
+  },
+  "2023": {
+    "idx": 2023,
+    "A": "AI 抠取 拼图 工具",
+    "B": "好用的智能抠图工具",
+    "C": "AI 抠图 拼图 怎么做"
+  },
+  "2024": {
+    "idx": 2024,
+    "A": "软件 抠取 拼图 工具",
+    "B": "抠取拼图的软件推荐",
+    "C": "软件 抠 对比图 怎么做"
+  },
+  "2025": {
+    "idx": 2025,
+    "A": "在线 抠取 拼图 工具",
+    "B": "在线抠取拼图的工具",
+    "C": "在线 分割 长图 方法"
+  },
+  "2026": {
+    "idx": 2026,
+    "A": "代码 抠取 拼图 工具",
+    "B": "抠取拼图的代码工具",
+    "C": "代码 抠图 九宫格 教学"
+  },
+  "2027": {
+    "idx": 2027,
+    "A": "插件 抠取 拼图 工具",
+    "B": "抠取拼图的插件工具",
+    "C": "插件 分割 拼图 步骤"
+  },
+  "2028": {
+    "idx": 2028,
+    "A": "抠取 拼图 技巧",
+    "B": "抠取拼图的小技巧",
+    "C": "分割 长图 教程"
+  },
+  "2029": {
+    "idx": 2029,
+    "A": "AI 抠取 拼图 技巧",
+    "B": "利用智能技术抠取拼图的技巧",
+    "C": "AI 分割 长图 怎么做"
+  },
+  "2030": {
+    "idx": 2030,
+    "A": "软件 抠取 拼图 技巧",
+    "B": "使用软件抠取拼图的技巧",
+    "C": "软件 抠 九宫格 步骤"
+  },
+  "2031": {
+    "idx": 2031,
+    "A": "在线 抠取 拼图 技巧",
+    "B": "在线抠取拼图的技巧",
+    "C": "网页版 怎么抠 对比图 教程"
+  },
+  "2032": {
+    "idx": 2032,
+    "A": "代码 抠取 拼图 技巧",
+    "B": "用代码抠取拼图的技巧",
+    "C": "代码 怎么抠 九宫格 教学"
+  },
+  "2033": {
+    "idx": 2033,
+    "A": "插件 抠取 拼图 技巧",
+    "B": "抠取拼图的插件使用技巧",
+    "C": "插件 分割 对比图 怎么做"
+  },
+  "2034": {
+    "idx": 2034,
+    "A": "结构生成 拼图 教程",
+    "B": "如何生成拼图结构的教程",
+    "C": "生成 长图 方法"
+  },
+  "2035": {
+    "idx": 2035,
+    "A": "AI 结构生成 拼图 教程",
+    "B": "怎么用智能技术生成拼图结构",
+    "C": "AI 生成 九宫格 方法"
+  },
+  "2036": {
+    "idx": 2036,
+    "A": "软件 结构生成 拼图 教程",
+    "B": "生成拼图结构的软件操作教程",
+    "C": "电脑端 怎么生成 拼图 流程"
+  },
+  "2037": {
+    "idx": 2037,
+    "A": "在线 结构生成 拼图 教程",
+    "B": "在线生成拼图结构的教程",
+    "C": "网页版 生成 长图 怎么做"
+  },
+  "2038": {
+    "idx": 2038,
+    "A": "代码 结构生成 拼图 教程",
+    "B": "通过编程代码生成拼图结构的方法",
+    "C": "代码 构建 九宫格 方法"
+  },
+  "2039": {
+    "idx": 2039,
+    "A": "插件 结构生成 拼图 教程",
+    "B": "怎么用插件制作结构拼图的教程",
+    "C": "插件 怎么生成 长图 教学"
+  },
+  "2040": {
+    "idx": 2040,
+    "A": "结构生成 拼图 工具",
+    "B": "有什么好用的结构拼图生成工具",
+    "C": "生成 长图 怎么做"
+  },
+  "2041": {
+    "idx": 2041,
+    "A": "AI 结构生成 拼图 工具",
+    "B": "有没有能自动生成结构拼图的工具",
+    "C": "AI 构建 九宫格 步骤"
+  },
+  "2042": {
+    "idx": 2042,
+    "A": "软件 结构生成 拼图 工具",
+    "B": "制作结构拼图的软件有哪些",
+    "C": "电脑端 怎么生成 九宫格 方法"
+  },
+  "2043": {
+    "idx": 2043,
+    "A": "在线 结构生成 拼图 工具",
+    "B": "在线生成结构拼图的网站推荐",
+    "C": "网页版 搭建 拼图 步骤"
+  },
+  "2044": {
+    "idx": 2044,
+    "A": "代码 结构生成 拼图 工具",
+    "B": "怎么通过代码实现结构拼图生成",
+    "C": "代码 搭建 拼图 怎么做"
+  },
+  "2045": {
+    "idx": 2045,
+    "A": "插件 结构生成 拼图 工具",
+    "B": "好用的结构拼图生成插件有哪些",
+    "C": "插件 构建 九宫格 流程"
+  },
+  "2046": {
+    "idx": 2046,
+    "A": "结构生成 拼图 技巧",
+    "B": "结构拼图的制作技巧有哪些",
+    "C": "怎么生成 对比图 教学"
+  },
+  "2047": {
+    "idx": 2047,
+    "A": "AI 结构生成 拼图 技巧",
+    "B": "怎么用智能工具提升结构拼图效果",
+    "C": "AI 怎么生成 九宫格 教程"
+  },
+  "2048": {
+    "idx": 2048,
+    "A": "软件 结构生成 拼图 技巧",
+    "B": "结构拼图软件的操作技巧",
+    "C": "软件 搭建 拼图 怎么做"
+  },
+  "2049": {
+    "idx": 2049,
+    "A": "在线 结构生成 拼图 技巧",
+    "B": "在线制作结构拼图有什么技巧",
+    "C": "网页版 生成 拼图 步骤"
+  },
+  "2050": {
+    "idx": 2050,
+    "A": "代码 结构生成 拼图 技巧",
+    "B": "如何用代码优化结构拼图生成",
+    "C": "代码 生成 长图 怎么做"
+  },
+  "2051": {
+    "idx": 2051,
+    "A": "插件 结构生成 拼图 技巧",
+    "B": "使用结构拼图插件的进阶技巧",
+    "C": "插件 生成 长图 教程"
+  },
+  "2052": {
+    "idx": 2052,
+    "A": "元素生成 歌词 教程",
+    "B": "怎么写出歌词元素生成的教程",
+    "C": "创作 词 教学"
+  },
+  "2053": {
+    "idx": 2053,
+    "A": "AI 元素生成 歌词 教程",
+    "B": "如何利用智能技术辅助歌词创作",
+    "C": "AI 怎么做 歌词 流程"
+  },
+  "2054": {
+    "idx": 2054,
+    "A": "软件 元素生成 歌词 教程",
+    "B": "歌词元素生成软件的使用教程",
+    "C": "电脑端 怎么做 lyrics 步骤"
+  },
+  "2055": {
+    "idx": 2055,
+    "A": "在线 元素生成 歌词 教程",
+    "B": "在线生成歌词元素的方法教程",
+    "C": "网页版 生成 词 流程"
+  },
+  "2056": {
+    "idx": 2056,
+    "A": "代码 元素生成 歌词 教程",
+    "B": "怎么用代码编写歌词元素生成程序",
+    "C": "代码 怎么做 歌词 教程"
+  },
+  "2057": {
+    "idx": 2057,
+    "A": "插件 元素生成 歌词 教程",
+    "B": "歌词元素生成插件的安装与使用教程",
+    "C": "插件 制作 lyrics 步骤"
+  },
+  "2058": {
+    "idx": 2058,
+    "A": "元素生成 歌词 工具",
+    "B": "有没有好用的歌词元素生成工具",
+    "C": "创作 词 步骤"
+  },
+  "2059": {
+    "idx": 2059,
+    "A": "AI 元素生成 歌词 工具",
+    "B": "好用的歌词创作辅助工具推荐",
+    "C": "AI 怎么做 lyrics 流程"
+  },
+  "2060": {
+    "idx": 2060,
+    "A": "软件 元素生成 歌词 工具",
+    "B": "歌词元素生成软件哪个好用",
+    "C": "软件 生成 词 方法"
+  },
+  "2061": {
+    "idx": 2061,
+    "A": "在线 元素生成 歌词 工具",
+    "B": "在线生成歌词元素的工具推荐",
+    "C": "网页版 创作 词 教程"
+  },
+  "2062": {
+    "idx": 2062,
+    "A": "代码 元素生成 歌词 工具",
+    "B": "有没有能生成歌词元素的代码工具",
+    "C": "代码 生成 词 教学"
+  },
+  "2063": {
+    "idx": 2063,
+    "A": "插件 元素生成 歌词 工具",
+    "B": "好用的歌词元素生成插件推荐",
+    "C": "插件 生成 词 教程"
+  },
+  "2064": {
+    "idx": 2064,
+    "A": "元素生成 歌词 技巧",
+    "B": "歌词元素创作的技巧有哪些",
+    "C": "生成 词 怎么做"
+  },
+  "2065": {
+    "idx": 2065,
+    "A": "AI 元素生成 歌词 技巧",
+    "B": "如何利用智能工具写出更好的歌词",
+    "C": "AI 创作 lyrics 教学"
+  },
+  "2066": {
+    "idx": 2066,
+    "A": "软件 元素生成 歌词 技巧",
+    "B": "使用歌词生成软件的技巧分享",
+    "C": "电脑端 创作 词 步骤"
+  },
+  "2067": {
+    "idx": 2067,
+    "A": "在线 元素生成 歌词 技巧",
+    "B": "在线创作歌词元素的实用技巧",
+    "C": "网页版 制作 lyrics 教学"
+  },
+  "2068": {
+    "idx": 2068,
+    "A": "代码 元素生成 歌词 技巧",
+    "B": "通过代码优化歌词生成的方法",
+    "C": "代码 做 lyrics 流程"
+  },
+  "2069": {
+    "idx": 2069,
+    "A": "插件 元素生成 歌词 技巧",
+    "B": "歌词元素生成插件的使用心得",
+    "C": "插件 做 歌词 怎么做"
+  },
+  "2070": {
+    "idx": 2070,
+    "A": "重述 歌词 教程",
+    "B": "怎么写歌词重述的教程",
+    "C": "怎么改 lyrics 教学"
+  },
+  "2071": {
+    "idx": 2071,
+    "A": "AI 重述 歌词 教程",
+    "B": "如何利用智能工具进行歌词重述",
+    "C": "AI 重写 歌词 流程"
+  },
+  "2072": {
+    "idx": 2072,
+    "A": "软件 重述 歌词 教程",
+    "B": "歌词重述软件的使用教程",
+    "C": "软件 怎么改 词 怎么做"
+  },
+  "2073": {
+    "idx": 2073,
+    "A": "在线 重述 歌词 教程",
+    "B": "在线进行歌词重述的方法",
+    "C": "在线 怎么改 词 怎么做"
+  },
+  "2075": {
+    "idx": 2075,
+    "A": "插件 重述 歌词 教程",
+    "B": "好用的歌词重述插件推荐",
+    "C": "插件 改写 歌词 怎么做"
+  },
+  "2076": {
+    "idx": 2076,
+    "A": "重述 歌词 工具",
+    "B": "有哪些好用的歌词重述工具",
+    "C": "改写 词 怎么做"
+  },
+  "2077": {
+    "idx": 2077,
+    "A": "AI 重述 歌词 工具",
+    "B": "智能歌词重述工具推荐",
+    "C": "AI 润色 词 步骤"
+  },
+  "2078": {
+    "idx": 2078,
+    "A": "软件 重述 歌词 工具",
+    "B": "好用的歌词重述软件有哪些",
+    "C": "软件 改写 词 教学"
+  },
+  "2079": {
+    "idx": 2079,
+    "A": "在线 重述 歌词 工具",
+    "B": "在线歌词重述工具推荐",
+    "C": "在线 怎么改 lyrics 教学"
+  },
+  "2080": {
+    "idx": 2080,
+    "A": "代码 重述 歌词 工具",
+    "B": "有没有能重述歌词的代码工具",
+    "C": "代码 怎么改 lyrics 怎么做"
+  },
+  "2081": {
+    "idx": 2081,
+    "A": "插件 重述 歌词 工具",
+    "B": "有什么重述歌词的插件工具",
+    "C": "插件 重写 歌词 方法"
+  },
+  "2082": {
+    "idx": 2082,
+    "A": "重述 歌词 技巧",
+    "B": "重述歌词有什么好技巧",
+    "C": "润色 lyrics 流程"
+  },
+  "2083": {
+    "idx": 2083,
+    "A": "AI 重述 歌词 技巧",
+    "B": "怎么用人工智能重述歌词",
+    "C": "AI 重写 歌词 步骤"
+  },
+  "2084": {
+    "idx": 2084,
+    "A": "软件 重述 歌词 技巧",
+    "B": "重述歌词的软件操作技巧",
+    "C": "软件 重写 词 方法"
+  },
+  "2085": {
+    "idx": 2085,
+    "A": "在线 重述 歌词 技巧",
+    "B": "在线重述歌词的技巧有哪些",
+    "C": "网页版 润色 歌词 教学"
+  },
+  "2087": {
+    "idx": 2087,
+    "A": "插件 重述 歌词 技巧",
+    "B": "重述歌词插件的使用技巧",
+    "C": "插件 重写 歌词 方法"
+  },
+  "2088": {
+    "idx": 2088,
+    "A": "录音 配音 教程",
+    "B": "录音和配音的入门教程",
+    "C": "录制 解说 方法"
+  },
+  "2089": {
+    "idx": 2089,
+    "A": "AI 录音 配音 教程",
+    "B": "怎么用人工智能做录音配音",
+    "C": "AI 录制 旁白 步骤"
+  },
+  "2090": {
+    "idx": 2090,
+    "A": "软件 录音 配音 教程",
+    "B": "录音配音软件的使用教程",
+    "C": "电脑端 录音 配音 教学"
+  },
+  "2091": {
+    "idx": 2091,
+    "A": "在线 录音 配音 教程",
+    "B": "在线录音配音的详细教程",
+    "C": "网页版 怎么录 人声 教学"
+  },
+  "2092": {
+    "idx": 2092,
+    "A": "代码 录音 配音 教程",
+    "B": "录音配音的代码实现教程",
+    "C": "代码 录音 旁白 流程"
+  },
+  "2093": {
+    "idx": 2093,
+    "A": "插件 录音 配音 教程",
+    "B": "录音配音插件的安装使用教程",
+    "C": "插件 录 旁白 怎么做"
+  },
+  "2094": {
+    "idx": 2094,
+    "A": "录音 配音 工具",
+    "B": "好用的录音配音工具推荐",
+    "C": "怎么录 人声 方法"
+  },
+  "2095": {
+    "idx": 2095,
+    "A": "AI 录音 配音 工具",
+    "B": "有哪些人工智能录音配音工具",
+    "C": "AI 录 旁白 教学"
+  },
+  "2096": {
+    "idx": 2096,
+    "A": "软件 录音 配音 工具",
+    "B": "录音配音软件有哪些",
+    "C": "电脑端 怎么录 解说 怎么做"
+  },
+  "2097": {
+    "idx": 2097,
+    "A": "在线 录音 配音 工具",
+    "B": "在线录音配音工具有哪些",
+    "C": "网页版 录音 配音 方法"
+  },
+  "2098": {
+    "idx": 2098,
+    "A": "代码 录音 配音 工具",
+    "B": "实现录音配音功能的代码工具",
+    "C": "命令行 录 解说 教程"
+  },
+  "2099": {
+    "idx": 2099,
+    "A": "插件 录音 配音 工具",
+    "B": "录音配音插件有哪些",
+    "C": "插件 录音 配音 教学"
+  },
+  "2100": {
+    "idx": 2100,
+    "A": "录音 配音 技巧",
+    "B": "录音配音的专业技巧",
+    "C": "怎么录 配音 步骤"
+  },
+  "2101": {
+    "idx": 2101,
+    "A": "AI 录音 配音 技巧",
+    "B": "人工智能录音配音的技巧",
+    "C": "AI 录 人声 教学"
+  },
+  "2102": {
+    "idx": 2102,
+    "A": "软件 录音 配音 技巧",
+    "B": "录音配音软件的操作技巧",
+    "C": "电脑端 怎么录 人声 怎么做"
+  },
+  "2103": {
+    "idx": 2103,
+    "A": "在线 录音 配音 技巧",
+    "B": "在线录音配音的技巧分享",
+    "C": "网页版 录制 旁白 教学"
+  },
+  "2104": {
+    "idx": 2104,
+    "A": "代码 录音 配音 技巧",
+    "B": "录音配音代码编写技巧",
+    "C": "代码 录制 旁白 流程"
+  },
+  "2105": {
+    "idx": 2105,
+    "A": "插件 录音 配音 技巧",
+    "B": "录音配音插件的使用技巧",
+    "C": "插件 怎么录 人声 流程"
+  },
+  "2106": {
+    "idx": 2106,
+    "A": "键入 配音 教程",
+    "B": "文字转语音配音的教程",
+    "C": "怎么写 旁白 流程"
+  },
+  "2107": {
+    "idx": 2107,
+    "A": "AI 键入 配音 教程",
+    "B": "怎么用人工智能实现文字转语音配音",
+    "C": "AI 写 配音 流程"
+  },
+  "2108": {
+    "idx": 2108,
+    "A": "软件 键入 配音 教程",
+    "B": "文字转语音配音软件教程",
+    "C": "电脑端 编写 旁白 教程"
+  },
+  "2109": {
+    "idx": 2109,
+    "A": "在线 键入 配音 教程",
+    "B": "在线文字转语音配音教程",
+    "C": "在线 编写 人声 教学"
+  },
+  "2110": {
+    "idx": 2110,
+    "A": "代码 键入 配音 教程",
+    "B": "文字转语音配音的代码实现教程",
+    "C": "命令行 输入 人声 方法"
+  },
+  "2111": {
+    "idx": 2111,
+    "A": "插件 键入 配音 教程",
+    "B": "文字转语音配音插件使用教程",
+    "C": "插件 编写 人声 步骤"
+  },
+  "2112": {
+    "idx": 2112,
+    "A": "键入 配音 工具",
+    "B": "好用的文字转语音配音工具",
+    "C": "输入 旁白 怎么做"
+  },
+  "2113": {
+    "idx": 2113,
+    "A": "AI 键入 配音 工具",
+    "B": "人工智能文字转语音配音工具",
+    "C": "AI 编写 旁白 教学"
+  },
+  "2114": {
+    "idx": 2114,
+    "A": "软件 键入 配音 工具",
+    "B": "文字转语音配音软件有哪些",
+    "C": "电脑端 编写 解说 教程"
+  },
+  "2115": {
+    "idx": 2115,
+    "A": "在线 键入 配音 工具",
+    "B": "在线文字转语音配音工具",
+    "C": "在线 编写 解说 教程"
+  },
+  "2116": {
+    "idx": 2116,
+    "A": "代码 键入 配音 工具",
+    "B": "文字转语音配音代码工具",
+    "C": "命令行 写 旁白 教学"
+  },
+  "2117": {
+    "idx": 2117,
+    "A": "插件 键入 配音 工具",
+    "B": "文字转语音配音插件推荐",
+    "C": "插件 编写 配音 方法"
+  },
+  "2118": {
+    "idx": 2118,
+    "A": "键入 配音 技巧",
+    "B": "文字转语音配音的技巧",
+    "C": "写 旁白 怎么做"
+  },
+  "2119": {
+    "idx": 2119,
+    "A": "AI 键入 配音 技巧",
+    "B": "人工智能文字转语音配音技巧",
+    "C": "AI 怎么写 配音 步骤"
+  },
+  "2120": {
+    "idx": 2120,
+    "A": "软件 键入 配音 技巧",
+    "B": "文字转语音配音软件使用技巧",
+    "C": "软件 编写 人声 方法"
+  },
+  "2121": {
+    "idx": 2121,
+    "A": "在线 键入 配音 技巧",
+    "B": "怎么在网页上输入文字进行配音",
+    "C": "网页版 怎么写 人声 步骤"
+  },
+  "2122": {
+    "idx": 2122,
+    "A": "代码 键入 配音 技巧",
+    "B": "如何通过编写代码实现文字配音",
+    "C": "命令行 怎么写 旁白 教程"
+  },
+  "2123": {
+    "idx": 2123,
+    "A": "插件 键入 配音 技巧",
+    "B": "有哪些插件可以实现输入文字配音",
+    "C": "插件 怎么写 配音 教学"
+  },
+  "2124": {
+    "idx": 2124,
+    "A": "识别 配音 教程",
+    "B": "语音识别配音的详细教程",
+    "C": "提取文字 旁白 方法"
+  },
+  "2125": {
+    "idx": 2125,
+    "A": "AI 识别 配音 教程",
+    "B": "如何利用智能技术进行语音识别配音",
+    "C": "AI OCR 配音 步骤"
+  },
+  "2126": {
+    "idx": 2126,
+    "A": "软件 识别 配音 教程",
+    "B": "用软件进行语音识别配音的教程",
+    "C": "电脑端 识别 旁白 方法"
+  },
+  "2127": {
+    "idx": 2127,
+    "A": "在线 识别 配音 教程",
+    "B": "在线语音识别配音怎么操作",
+    "C": "在线 OCR 解说 流程"
+  },
+  "2128": {
+    "idx": 2128,
+    "A": "代码 识别 配音 教程",
+    "B": "如何通过代码实现语音识别配音",
+    "C": "命令行 OCR 解说 教程"
+  },
+  "2129": {
+    "idx": 2129,
+    "A": "插件 识别 配音 教程",
+    "B": "有没有插件可以做语音识别配音",
+    "C": "插件 转录 旁白 方法"
+  },
+  "2130": {
+    "idx": 2130,
+    "A": "识别 配音 工具",
+    "B": "好用的语音识别配音工具推荐",
+    "C": "检测 人声 步骤"
+  },
+  "2131": {
+    "idx": 2131,
+    "A": "AI 识别 配音 工具",
+    "B": "智能语音识别配音工具有哪些",
+    "C": "AI OCR 旁白 怎么做"
+  },
+  "2132": {
+    "idx": 2132,
+    "A": "软件 识别 配音 工具",
+    "B": "适合语音识别配音的软件有哪些",
+    "C": "软件 转录 配音 步骤"
+  },
+  "2133": {
+    "idx": 2133,
+    "A": "在线 识别 配音 工具",
+    "B": "在线语音识别配音工具有哪些",
+    "C": "在线 检测 旁白 怎么做"
+  },
+  "2134": {
+    "idx": 2134,
+    "A": "代码 识别 配音 工具",
+    "B": "有没有能做语音识别配音的代码工具",
+    "C": "命令行 提取文字 旁白 教学"
+  },
+  "2135": {
+    "idx": 2135,
+    "A": "插件 识别 配音 工具",
+    "B": "好用的语音识别配音插件推荐",
+    "C": "插件 检测 旁白 方法"
+  },
+  "2136": {
+    "idx": 2136,
+    "A": "识别 配音 技巧",
+    "B": "语音识别配音有什么技巧",
+    "C": "OCR 配音 教学"
+  },
+  "2137": {
+    "idx": 2137,
+    "A": "AI 识别 配音 技巧",
+    "B": "智能语音识别配音的操作技巧",
+    "C": "AI 识别 配音 流程"
+  },
+  "2138": {
+    "idx": 2138,
+    "A": "软件 识别 配音 技巧",
+    "B": "使用软件进行语音识别配音的技巧",
+    "C": "电脑端 提取文字 人声 步骤"
+  },
+  "2139": {
+    "idx": 2139,
+    "A": "在线 识别 配音 技巧",
+    "B": "在线语音识别配音的实用技巧",
+    "C": "网页版 转录 旁白 怎么做"
+  },
+  "2140": {
+    "idx": 2140,
+    "A": "代码 识别 配音 技巧",
+    "B": "通过代码进行语音识别配音的技巧",
+    "C": "命令行 提取文字 解说 流程"
+  },
+  "2141": {
+    "idx": 2141,
+    "A": "插件 识别 配音 技巧",
+    "B": "语音识别配音插件的使用技巧",
+    "C": "插件 识别 解说 怎么做"
+  },
+  "2142": {
+    "idx": 2142,
+    "A": "元素生成 配音 教程",
+    "B": "如何通过素材生成配音的教程",
+    "C": "做 解说 方法"
+  },
+  "2143": {
+    "idx": 2143,
+    "A": "AI 元素生成 配音 教程",
+    "B": "智能生成配音素材的教程",
+    "C": "AI 生成 解说 怎么做"
+  },
+  "2144": {
+    "idx": 2144,
+    "A": "软件 元素生成 配音 教程",
+    "B": "用软件生成配音素材的教程",
+    "C": "电脑端 怎么做 解说 步骤"
+  },
+  "2145": {
+    "idx": 2145,
+    "A": "在线 元素生成 配音 教程",
+    "B": "在线生成配音素材的教程",
+    "C": "在线 怎么做 人声 怎么做"
+  },
+  "2146": {
+    "idx": 2146,
+    "A": "代码 元素生成 配音 教程",
+    "B": "如何用代码生成配音素材",
+    "C": "代码 创作 旁白 方法"
+  },
+  "2148": {
+    "idx": 2148,
+    "A": "元素生成 配音 工具",
+    "B": "有哪些生成配音素材的工具",
+    "C": "怎么做 旁白 步骤"
+  },
+  "2149": {
+    "idx": 2149,
+    "A": "AI 元素生成 配音 工具",
+    "B": "智能生成配音素材的工具有哪些",
+    "C": "AI 生成 配音 教程"
+  },
+  "2150": {
+    "idx": 2150,
+    "A": "软件 元素生成 配音 工具",
+    "B": "好用的配音素材生成软件",
+    "C": "电脑端 生成 配音 教学"
+  },
+  "2151": {
+    "idx": 2151,
+    "A": "在线 元素生成 配音 工具",
+    "B": "在线生成配音素材的工具推荐",
+    "C": "网页版 怎么做 旁白 教学"
+  },
+  "2152": {
+    "idx": 2152,
+    "A": "代码 元素生成 配音 工具",
+    "B": "有没有生成配音素材的代码工具",
+    "C": "命令行 怎么做 旁白 教程"
+  },
+  "2153": {
+    "idx": 2153,
+    "A": "插件 元素生成 配音 工具",
+    "B": "好用的配音素材生成插件",
+    "C": "插件 创作 配音 教程"
+  },
+  "2154": {
+    "idx": 2154,
+    "A": "元素生成 配音 技巧",
+    "B": "生成配音素材有什么技巧",
+    "C": "创作 旁白 方法"
+  },
+  "2155": {
+    "idx": 2155,
+    "A": "AI 元素生成 配音 技巧",
+    "B": "智能生成配音素材的技巧",
+    "C": "AI 生成 配音 方法"
+  },
+  "2156": {
+    "idx": 2156,
+    "A": "软件 元素生成 配音 技巧",
+    "B": "使用软件生成配音素材的技巧",
+    "C": "软件 做 旁白 教程"
+  },
+  "2157": {
+    "idx": 2157,
+    "A": "在线 元素生成 配音 技巧",
+    "B": "在线生成配音素材的技巧",
+    "C": "在线 怎么做 解说 怎么做"
+  },
+  "2158": {
+    "idx": 2158,
+    "A": "代码 元素生成 配音 技巧",
+    "B": "通过代码生成配音素材的技巧",
+    "C": "代码 做 解说 怎么做"
+  },
+  "2160": {
+    "idx": 2160,
+    "A": "调整 配音 教程",
+    "B": "如何调整配音效果的教程",
+    "C": "怎么调 解说 流程"
+  },
+  "2161": {
+    "idx": 2161,
+    "A": "AI 调整 配音 教程",
+    "B": "智能调整配音效果的教程",
+    "C": "AI 怎么调 配音 怎么做"
+  },
+  "2162": {
+    "idx": 2162,
+    "A": "软件 调整 配音 教程",
+    "B": "用软件调整配音效果的教程",
+    "C": "电脑端 怎么调 配音 步骤"
+  },
+  "2163": {
+    "idx": 2163,
+    "A": "在线 调整 配音 教程",
+    "B": "怎么在线调整配音的教程",
+    "C": "网页版 调 人声 教程"
+  },
+  "2164": {
+    "idx": 2164,
+    "A": "代码 调整 配音 教程",
+    "B": "如何通过代码调整配音的教程",
+    "C": "命令行 调 人声 流程"
+  },
+  "2165": {
+    "idx": 2165,
+    "A": "插件 调整 配音 教程",
+    "B": "使用插件调整配音的操作教程",
+    "C": "插件 调整 旁白 方法"
+  },
+  "2166": {
+    "idx": 2166,
+    "A": "调整 配音 工具",
+    "B": "有哪些好用的配音调整工具",
+    "C": "优化 旁白 方法"
+  },
+  "2167": {
+    "idx": 2167,
+    "A": "AI 调整 配音 工具",
+    "B": "好用的智能配音调整工具推荐",
+    "C": "AI 优化 解说 教程"
+  },
+  "2168": {
+    "idx": 2168,
+    "A": "软件 调整 配音 工具",
+    "B": "调整配音的软件工具有哪些",
+    "C": "软件 调整 配音 方法"
+  },
+  "2169": {
+    "idx": 2169,
+    "A": "在线 调整 配音 工具",
+    "B": "在线调整配音的工具怎么用",
+    "C": "网页版 优化 配音 怎么做"
+  },
+  "2170": {
+    "idx": 2170,
+    "A": "代码 调整 配音 工具",
+    "B": "通过代码调整配音的工具",
+    "C": "代码 调整 配音 教学"
+  },
+  "2171": {
+    "idx": 2171,
+    "A": "插件 调整 配音 工具",
+    "B": "调整配音的插件工具有哪些",
+    "C": "插件 怎么调 旁白 教学"
+  },
+  "2172": {
+    "idx": 2172,
+    "A": "调整 配音 技巧",
+    "B": "调整配音有哪些实用技巧",
+    "C": "怎么调 人声 方法"
+  },
+  "2173": {
+    "idx": 2173,
+    "A": "AI 调整 配音 技巧",
+    "B": "利用智能技术调整配音的技巧",
+    "C": "AI 优化 人声 怎么做"
+  },
+  "2174": {
+    "idx": 2174,
+    "A": "软件 调整 配音 技巧",
+    "B": "使用软件调整配音的技巧",
+    "C": "电脑端 调整 旁白 教程"
+  },
+  "2175": {
+    "idx": 2175,
+    "A": "在线 调整 配音 技巧",
+    "B": "在线调整配音的实用技巧",
+    "C": "网页版 优化 配音 方法"
+  },
+  "2176": {
+    "idx": 2176,
+    "A": "代码 调整 配音 技巧",
+    "B": "通过代码调整配音的技巧",
+    "C": "命令行 怎么调 解说 怎么做"
+  },
+  "2177": {
+    "idx": 2177,
+    "A": "插件 调整 配音 技巧",
+    "B": "使用插件调整配音的技巧",
+    "C": "插件 调整 解说 方法"
+  },
+  "2179": {
+    "idx": 2179,
+    "A": "AI 增强 配音 教程",
+    "B": "如何用智能技术增强配音的教程",
+    "C": "AI 增强 人声 步骤"
+  },
+  "2180": {
+    "idx": 2180,
+    "A": "软件 增强 配音 教程",
+    "B": "使用软件增强配音的教程",
+    "C": "软件 提升画质 配音 怎么做"
+  },
+  "2181": {
+    "idx": 2181,
+    "A": "在线 增强 配音 教程",
+    "B": "在线增强配音效果的教程",
+    "C": "在线 怎么增强 人声 教程"
+  },
+  "2182": {
+    "idx": 2182,
+    "A": "代码 增强 配音 教程",
+    "B": "通过代码增强配音的教程",
+    "C": "命令行 修复 配音 教学"
+  },
+  "2183": {
+    "idx": 2183,
+    "A": "插件 增强 配音 教程",
+    "B": "使用插件增强配音的教程",
+    "C": "插件 提升画质 旁白 教程"
+  },
+  "2184": {
+    "idx": 2184,
+    "A": "增强 配音 工具",
+    "B": "有哪些增强配音效果的工具",
+    "C": "提升画质 配音 教学"
+  },
+  "2185": {
+    "idx": 2185,
+    "A": "AI 增强 配音 工具",
+    "B": "好用的智能增强配音工具",
+    "C": "AI 修复 人声 教程"
+  },
+  "2186": {
+    "idx": 2186,
+    "A": "软件 增强 配音 工具",
+    "B": "增强配音效果的软件工具",
+    "C": "电脑端 修复 人声 教程"
+  },
+  "2187": {
+    "idx": 2187,
+    "A": "在线 增强 配音 工具",
+    "B": "在线增强配音效果的工具",
+    "C": "在线 怎么增强 配音 步骤"
+  },
+  "2188": {
+    "idx": 2188,
+    "A": "代码 增强 配音 工具",
+    "B": "通过代码增强配音的工具",
+    "C": "代码 修复 配音 流程"
+  },
+  "2189": {
+    "idx": 2189,
+    "A": "插件 增强 配音 工具",
+    "B": "增强配音效果的插件工具",
+    "C": "插件 超分 旁白 教学"
+  },
+  "2190": {
+    "idx": 2190,
+    "A": "增强 配音 技巧",
+    "B": "增强配音效果有哪些技巧",
+    "C": "超分 旁白 教程"
+  },
+  "2191": {
+    "idx": 2191,
+    "A": "AI 增强 配音 技巧",
+    "B": "利用智能技术增强配音的技巧",
+    "C": "AI 提升画质 人声 教学"
+  },
+  "2192": {
+    "idx": 2192,
+    "A": "软件 增强 配音 技巧",
+    "B": "使用软件增强配音的技巧",
+    "C": "软件 修复 配音 流程"
+  },
+  "2193": {
+    "idx": 2193,
+    "A": "在线 增强 配音 技巧",
+    "B": "在线增强配音的实用技巧",
+    "C": "在线 增强 旁白 教学"
+  },
+  "2194": {
+    "idx": 2194,
+    "A": "代码 增强 配音 技巧",
+    "B": "通过代码增强配音的技巧",
+    "C": "代码 怎么增强 配音 怎么做"
+  },
+  "2195": {
+    "idx": 2195,
+    "A": "插件 增强 配音 技巧",
+    "B": "使用插件增强配音的技巧",
+    "C": "插件 超分 配音 教程"
+  },
+  "2196": {
+    "idx": 2196,
+    "A": "检索 BGM 教程",
+    "B": "如何搜索背景音乐的教程",
+    "C": "找 背景音乐 方法"
+  },
+  "2197": {
+    "idx": 2197,
+    "A": "AI 检索 BGM 教程",
+    "B": "利用智能技术搜索背景音乐的教程",
+    "C": "AI 找 BGM 怎么做"
+  },
+  "2198": {
+    "idx": 2198,
+    "A": "软件 检索 BGM 教程",
+    "B": "使用软件搜索背景音乐的教程",
+    "C": "电脑端 在哪找 背景音乐 教程"
+  },
+  "2199": {
+    "idx": 2199,
+    "A": "在线 检索 BGM 教程",
+    "B": "在线搜索背景音乐的教程",
+    "C": "在线 哪里找 BGM 教程"
+  },
+  "2200": {
+    "idx": 2200,
+    "A": "代码 检索 BGM 教程",
+    "B": "通过代码搜索背景音乐的教程",
+    "C": "代码 哪里找 BGM 教程"
+  },
+  "2201": {
+    "idx": 2201,
+    "A": "插件 检索 BGM 教程",
+    "B": "使用插件搜索背景音乐的教程",
+    "C": "插件 搜 背景音乐 流程"
+  },
+  "2202": {
+    "idx": 2202,
+    "A": "检索 BGM 工具",
+    "B": "有哪些搜索背景音乐的工具",
+    "C": "哪里找 配乐 流程"
+  },
+  "2203": {
+    "idx": 2203,
+    "A": "AI 检索 BGM 工具",
+    "B": "好用的智能搜索背景音乐工具",
+    "C": "AI 搜 配乐 教程"
+  },
+  "2204": {
+    "idx": 2204,
+    "A": "软件 检索 BGM 工具",
+    "B": "有什么好用的背景音乐搜索软件",
+    "C": "软件 找 配乐 方法"
+  },
+  "2205": {
+    "idx": 2205,
+    "A": "在线 检索 BGM 工具",
+    "B": "怎么在线搜索背景音乐",
+    "C": "网页版 搜 BGM 怎么做"
+  },
+  "2206": {
+    "idx": 2206,
+    "A": "代码 检索 BGM 工具",
+    "B": "如何通过代码查找背景音乐",
+    "C": "代码 找 BGM 流程"
+  },
+  "2207": {
+    "idx": 2207,
+    "A": "插件 检索 BGM 工具",
+    "B": "有没有能搜背景音乐的插件",
+    "C": "插件 搜索 背景音乐 怎么做"
+  },
+  "2208": {
+    "idx": 2208,
+    "A": "检索 BGM 技巧",
+    "B": "搜索背景音乐有什么好方法",
+    "C": "在哪找 配乐 流程"
+  },
+  "2209": {
+    "idx": 2209,
+    "A": "AI 检索 BGM 技巧",
+    "B": "怎么利用智能技术搜索背景音乐",
+    "C": "AI 搜 配乐 步骤"
+  },
+  "2210": {
+    "idx": 2210,
+    "A": "软件 检索 BGM 技巧",
+    "B": "使用软件搜索背景音乐有什么技巧",
+    "C": "电脑端 在哪找 BGM 流程"
+  },
+  "2211": {
+    "idx": 2211,
+    "A": "在线 检索 BGM 技巧",
+    "B": "在线查找背景音乐有哪些窍门",
+    "C": "在线 搜索 BGM 教学"
+  },
+  "2212": {
+    "idx": 2212,
+    "A": "代码 检索 BGM 技巧",
+    "B": "用代码搜索背景音乐有什么技巧",
+    "C": "命令行 搜索 BGM 教学"
+  },
+  "2213": {
+    "idx": 2213,
+    "A": "插件 检索 BGM 技巧",
+    "B": "使用搜索背景音乐的插件有什么技巧",
+    "C": "插件 哪里找 背景音乐 教程"
+  },
+  "2214": {
+    "idx": 2214,
+    "A": "元素生成 BGM 教程",
+    "B": "怎么根据元素生成背景音乐",
+    "C": "创作 BGM 流程"
+  },
+  "2216": {
+    "idx": 2216,
+    "A": "软件 元素生成 BGM 教程",
+    "B": "用软件根据元素生成背景音乐的教程",
+    "C": "软件 创作 BGM 方法"
+  },
+  "2217": {
+    "idx": 2217,
+    "A": "在线 元素生成 BGM 教程",
+    "B": "在线根据元素生成背景音乐怎么做",
+    "C": "网页版 创作 配乐 流程"
+  },
+  "2218": {
+    "idx": 2218,
+    "A": "代码 元素生成 BGM 教程",
+    "B": "如何通过代码根据元素生成背景音乐",
+    "C": "命令行 制作 背景音乐 教程"
+  },
+  "2219": {
+    "idx": 2219,
+    "A": "插件 元素生成 BGM 教程",
+    "B": "怎么用插件根据元素生成背景音乐",
+    "C": "插件 生成 BGM 教学"
+  },
+  "2220": {
+    "idx": 2220,
+    "A": "元素生成 BGM 工具",
+    "B": "有什么能根据元素生成背景音乐的工具",
+    "C": "做 背景音乐 流程"
+  },
+  "2221": {
+    "idx": 2221,
+    "A": "AI 元素生成 BGM 工具",
+    "B": "有没有根据元素生成背景音乐的智能工具",
+    "C": "AI 生成 BGM 教学"
+  },
+  "2222": {
+    "idx": 2222,
+    "A": "软件 元素生成 BGM 工具",
+    "B": "有什么根据元素生成背景音乐的软件",
+    "C": "电脑端 怎么做 BGM 怎么做"
+  },
+  "2223": {
+    "idx": 2223,
+    "A": "在线 元素生成 BGM 工具",
+    "B": "在线根据元素生成背景音乐的工具推荐",
+    "C": "网页版 怎么做 配乐 怎么做"
+  },
+  "2224": {
+    "idx": 2224,
+    "A": "代码 元素生成 BGM 工具",
+    "B": "通过代码根据元素生成背景音乐的工具",
+    "C": "代码 生成 配乐 教程"
+  },
+  "2225": {
+    "idx": 2225,
+    "A": "插件 元素生成 BGM 工具",
+    "B": "有没有根据元素生成背景音乐的插件",
+    "C": "插件 制作 BGM 怎么做"
+  },
+  "2226": {
+    "idx": 2226,
+    "A": "元素生成 BGM 技巧",
+    "B": "根据元素生成背景音乐有什么技巧",
+    "C": "创作 BGM 教程"
+  },
+  "2228": {
+    "idx": 2228,
+    "A": "软件 元素生成 BGM 技巧",
+    "B": "用软件根据元素生成背景音乐的技巧",
+    "C": "软件 做 配乐 方法"
+  },
+  "2229": {
+    "idx": 2229,
+    "A": "在线 元素生成 BGM 技巧",
+    "B": "在线根据元素生成背景音乐的技巧",
+    "C": "网页版 做 BGM 教学"
+  },
+  "2230": {
+    "idx": 2230,
+    "A": "代码 元素生成 BGM 技巧",
+    "B": "用代码根据元素生成背景音乐的技巧",
+    "C": "命令行 制作 BGM 步骤"
+  },
+  "2231": {
+    "idx": 2231,
+    "A": "插件 元素生成 BGM 技巧",
+    "B": "用插件根据元素生成背景音乐的技巧",
+    "C": "插件 生成 BGM 教学"
+  },
+  "2232": {
+    "idx": 2232,
+    "A": "添加 BGM 教程",
+    "B": "视频怎么添加背景音乐",
+    "C": "加上 BGM 怎么做"
+  },
+  "2233": {
+    "idx": 2233,
+    "A": "AI 添加 BGM 教程",
+    "B": "如何利用智能技术添加背景音乐",
+    "C": "AI 添加 背景音乐 方法"
+  },
+  "2234": {
+    "idx": 2234,
+    "A": "软件 添加 BGM 教程",
+    "B": "用软件给视频添加背景音乐的教程",
+    "C": "电脑端 添加 背景音乐 流程"
+  },
+  "2235": {
+    "idx": 2235,
+    "A": "在线 添加 BGM 教程",
+    "B": "在线给视频添加背景音乐的教程",
+    "C": "在线 加上 BGM 怎么做"
+  },
+  "2236": {
+    "idx": 2236,
+    "A": "代码 添加 BGM 教程",
+    "B": "怎么用代码实现添加背景音乐",
+    "C": "命令行 加 背景音乐 教学"
+  },
+  "2237": {
+    "idx": 2237,
+    "A": "插件 添加 BGM 教程",
+    "B": "如何用插件给视频添加背景音乐",
+    "C": "插件 怎么加 背景音乐 流程"
+  },
+  "2238": {
+    "idx": 2238,
+    "A": "添加 BGM 工具",
+    "B": "有什么好用的添加背景音乐工具",
+    "C": "怎么加 BGM 教程"
+  },
+  "2239": {
+    "idx": 2239,
+    "A": "AI 添加 BGM 工具",
+    "B": "有没有能自动添加背景音乐的智能工具",
+    "C": "AI 怎么加 BGM 教程"
+  },
+  "2240": {
+    "idx": 2240,
+    "A": "软件 添加 BGM 工具",
+    "B": "有什么添加背景音乐的软件",
+    "C": "电脑端 加上 背景音乐 流程"
+  },
+  "2241": {
+    "idx": 2241,
+    "A": "在线 添加 BGM 工具",
+    "B": "在线添加背景音乐的工具推荐",
+    "C": "网页版 加 背景音乐 方法"
+  },
+  "2242": {
+    "idx": 2242,
+    "A": "代码 添加 BGM 工具",
+    "B": "有哪些添加背景音乐的代码工具",
+    "C": "代码 加 配乐 方法"
+  },
+  "2243": {
+    "idx": 2243,
+    "A": "插件 添加 BGM 工具",
+    "B": "有没有添加背景音乐的插件",
+    "C": "插件 添加 背景音乐 方法"
+  },
+  "2244": {
+    "idx": 2244,
+    "A": "添加 BGM 技巧",
+    "B": "给视频添加背景音乐有什么技巧",
+    "C": "加上 BGM 方法"
+  },
+  "2245": {
+    "idx": 2245,
+    "A": "AI 添加 BGM 技巧",
+    "B": "利用智能技术添加背景音乐的技巧",
+    "C": "AI 加上 背景音乐 教程"
+  },
+  "2246": {
+    "idx": 2246,
+    "A": "软件 添加 BGM 技巧",
+    "B": "用什么软件给视频添加背景音乐比较好",
+    "C": "电脑端 加 BGM 步骤"
+  },
+  "2247": {
+    "idx": 2247,
+    "A": "在线 添加 BGM 技巧",
+    "B": "怎么在线给视频配上背景音乐",
+    "C": "网页版 加 配乐 流程"
+  },
+  "2248": {
+    "idx": 2248,
+    "A": "代码 添加 BGM 技巧",
+    "B": "如何通过代码实现给视频添加背景音乐",
+    "C": "代码 加上 BGM 教程"
+  },
+  "2249": {
+    "idx": 2249,
+    "A": "插件 添加 BGM 技巧",
+    "B": "有哪些好用的插件可以给视频添加背景音乐",
+    "C": "插件 添加 背景音乐 方法"
+  },
+  "2250": {
+    "idx": 2250,
+    "A": "调整 BGM 教程",
+    "B": "视频背景音乐怎么调整才好听",
+    "C": "优化 背景音乐 教学"
+  },
+  "2251": {
+    "idx": 2251,
+    "A": "AI 调整 BGM 教程",
+    "B": "如何利用智能技术自动调整视频背景音乐",
+    "C": "AI 优化 背景音乐 流程"
+  },
+  "2252": {
+    "idx": 2252,
+    "A": "软件 调整 BGM 教程",
+    "B": "用什么软件可以调整视频背景音乐的音量和节奏",
+    "C": "软件 调整 配乐 教学"
+  },
+  "2253": {
+    "idx": 2253,
+    "A": "在线 调整 BGM 教程",
+    "B": "在线调整视频背景音乐的方法有哪些",
+    "C": "网页版 调 BGM 步骤"
+  },
+  "2254": {
+    "idx": 2254,
+    "A": "代码 调整 BGM 教程",
+    "B": "怎么用代码来处理和调整视频背景音乐",
+    "C": "命令行 调 配乐 教程"
+  },
+  "2255": {
+    "idx": 2255,
+    "A": "插件 调整 BGM 教程",
+    "B": "有什么插件可以辅助调整视频背景音乐",
+    "C": "插件 优化 配乐 步骤"
+  },
+  "2256": {
+    "idx": 2256,
+    "A": "调整 BGM 工具",
+    "B": "有哪些工具可以用来调整视频背景音乐",
+    "C": "调 配乐 怎么做"
+  },
+  "2257": {
+    "idx": 2257,
+    "A": "AI 调整 BGM 工具",
+    "B": "好用的智能背景音乐调整工具有哪些",
+    "C": "AI 优化 背景音乐 流程"
+  },
+  "2258": {
+    "idx": 2258,
+    "A": "软件 调整 BGM 工具",
+    "B": "推荐几款调整视频背景音乐的软件",
+    "C": "电脑端 调 背景音乐 教学"
+  },
+  "2259": {
+    "idx": 2259,
+    "A": "在线 调整 BGM 工具",
+    "B": "在线调整视频背景音乐的工具有哪些",
+    "C": "网页版 调整 配乐 教程"
+  },
+  "2260": {
+    "idx": 2260,
+    "A": "代码 调整 BGM 工具",
+    "B": "有没有能调整背景音乐的代码工具",
+    "C": "命令行 怎么调 配乐 教程"
+  },
+  "2261": {
+    "idx": 2261,
+    "A": "插件 调整 BGM 工具",
+    "B": "调整视频背景音乐的插件推荐",
+    "C": "插件 优化 背景音乐 教学"
+  },
+  "2262": {
+    "idx": 2262,
+    "A": "调整 BGM 技巧",
+    "B": "调整视频背景音乐有什么实用技巧",
+    "C": "调 配乐 教程"
+  },
+  "2263": {
+    "idx": 2263,
+    "A": "AI 调整 BGM 技巧",
+    "B": "利用智能技术调整背景音乐的技巧有哪些",
+    "C": "AI 调整 配乐 教学"
+  },
+  "2264": {
+    "idx": 2264,
+    "A": "软件 调整 BGM 技巧",
+    "B": "使用软件调整背景音乐的进阶技巧",
+    "C": "电脑端 调整 BGM 怎么做"
+  },
+  "2265": {
+    "idx": 2265,
+    "A": "在线 调整 BGM 技巧",
+    "B": "在线调整背景音乐时有哪些小窍门",
+    "C": "网页版 优化 配乐 教程"
+  },
+  "2266": {
+    "idx": 2266,
+    "A": "代码 调整 BGM 技巧",
+    "B": "通过代码调整背景音乐的技巧分享",
+    "C": "命令行 怎么调 BGM 教学"
+  },
+  "2267": {
+    "idx": 2267,
+    "A": "插件 调整 BGM 技巧",
+    "B": "使用插件调整背景音乐的技巧有哪些",
+    "C": "插件 调 BGM 步骤"
+  },
+  "2268": {
+    "idx": 2268,
+    "A": "键入 字幕 教程",
+    "B": "视频里怎么添加字幕的教程",
+    "C": "输入 字幕条 教程"
+  },
+  "2269": {
+    "idx": 2269,
+    "A": "AI 键入 字幕 教程",
+    "B": "如何利用智能技术自动给视频添加字幕",
+    "C": "AI 输入 字幕条 流程"
+  },
+  "2270": {
+    "idx": 2270,
+    "A": "软件 键入 字幕 教程",
+    "B": "用什么软件给视频添加字幕比较方便",
+    "C": "电脑端 怎么写 视频字幕 方法"
+  },
+  "2271": {
+    "idx": 2271,
+    "A": "在线 键入 字幕 教程",
+    "B": "在线给视频添加字幕的教程有哪些",
+    "C": "网页版 怎么写 字幕 教程"
+  },
+  "2272": {
+    "idx": 2272,
+    "A": "代码 键入 字幕 教程",
+    "B": "怎么用代码给视频自动添加字幕",
+    "C": "命令行 怎么写 视频字幕 怎么做"
+  },
+  "2273": {
+    "idx": 2273,
+    "A": "插件 键入 字幕 教程",
+    "B": "有哪些插件可以帮助给视频添加字幕",
+    "C": "插件 编写 字幕条 方法"
+  },
+  "2274": {
+    "idx": 2274,
+    "A": "键入 字幕 工具",
+    "B": "给视频添加字幕的工具有哪些",
+    "C": "怎么写 视频字幕 方法"
+  },
+  "2275": {
+    "idx": 2275,
+    "A": "AI 键入 字幕 工具",
+    "B": "好用的智能字幕生成工具有哪些",
+    "C": "AI 写 字幕 怎么做"
+  },
+  "2276": {
+    "idx": 2276,
+    "A": "软件 键入 字幕 工具",
+    "B": "推荐几款给视频添加字幕的软件",
+    "C": "软件 写 视频字幕 流程"
+  },
+  "2277": {
+    "idx": 2277,
+    "A": "在线 键入 字幕 工具",
+    "B": "在线给视频添加字幕的工具有哪些",
+    "C": "网页版 写 字幕 流程"
+  },
+  "2278": {
+    "idx": 2278,
+    "A": "代码 键入 字幕 工具",
+    "B": "有没有能自动添加字幕的代码工具",
+    "C": "命令行 写 字幕条 流程"
+  },
+  "2279": {
+    "idx": 2279,
+    "A": "插件 键入 字幕 工具",
+    "B": "给视频添加字幕的插件推荐",
+    "C": "插件 输入 字幕 方法"
+  },
+  "2280": {
+    "idx": 2280,
+    "A": "键入 字幕 技巧",
+    "B": "给视频添加字幕有什么技巧",
+    "C": "写 视频字幕 怎么做"
+  },
+  "2281": {
+    "idx": 2281,
+    "A": "AI 键入 字幕 技巧",
+    "B": "利用智能技术添加字幕的技巧有哪些",
+    "C": "AI 编写 视频字幕 怎么做"
+  },
+  "2282": {
+    "idx": 2282,
+    "A": "软件 键入 字幕 技巧",
+    "B": "使用软件给视频添加字幕的技巧",
+    "C": "电脑端 写 视频字幕 流程"
+  },
+  "2283": {
+    "idx": 2283,
+    "A": "在线 键入 字幕 技巧",
+    "B": "在线给视频添加字幕的实用技巧",
+    "C": "在线 写 字幕 方法"
+  },
+  "2284": {
+    "idx": 2284,
+    "A": "代码 键入 字幕 技巧",
+    "B": "通过代码给视频添加字幕的技巧",
+    "C": "命令行 编写 字幕条 步骤"
+  },
+  "2285": {
+    "idx": 2285,
+    "A": "插件 键入 字幕 技巧",
+    "B": "使用插件给视频添加字幕的技巧",
+    "C": "插件 编写 字幕条 教学"
+  },
+  "2286": {
+    "idx": 2286,
+    "A": "识别 字幕 教程",
+    "B": "怎么识别视频里的字幕",
+    "C": "转录 字幕条 怎么做"
+  },
+  "2287": {
+    "idx": 2287,
+    "A": "AI 识别 字幕 教程",
+    "B": "如何用人工智能自动识别字幕",
+    "C": "AI OCR 字幕条 流程"
+  },
+  "2289": {
+    "idx": 2289,
+    "A": "在线 识别 字幕 教程",
+    "B": "在线识别视频字幕的方法",
+    "C": "网页版 检测 视频字幕 流程"
+  },
+  "2290": {
+    "idx": 2290,
+    "A": "代码 识别 字幕 教程",
+    "B": "通过写代码来识别字幕的教程",
+    "C": "命令行 OCR 视频字幕 教程"
+  },
+  "2291": {
+    "idx": 2291,
+    "A": "插件 识别 字幕 教程",
+    "B": "怎么用插件识别视频字幕",
+    "C": "插件 OCR 视频字幕 怎么做"
+  },
+  "2292": {
+    "idx": 2292,
+    "A": "识别 字幕 工具",
+    "B": "有什么好用的字幕识别工具",
+    "C": "检测 字幕条 流程"
+  },
+  "2293": {
+    "idx": 2293,
+    "A": "AI 识别 字幕 工具",
+    "B": "好用的智能字幕识别工具推荐",
+    "C": "AI 检测 字幕 教学"
+  },
+  "2294": {
+    "idx": 2294,
+    "A": "软件 识别 字幕 工具",
+    "B": "识别字幕的电脑软件有哪些",
+    "C": "软件 检测 字幕 教程"
+  },
+  "2295": {
+    "idx": 2295,
+    "A": "在线 识别 字幕 工具",
+    "B": "在线识别字幕的网站推荐",
+    "C": "在线 OCR 字幕条 流程"
+  },
+  "2296": {
+    "idx": 2296,
+    "A": "代码 识别 字幕 工具",
+    "B": "有没有识别字幕的程序代码",
+    "C": "命令行 OCR 视频字幕 流程"
+  },
+  "2297": {
+    "idx": 2297,
+    "A": "插件 识别 字幕 工具",
+    "B": "好用的字幕识别插件推荐",
+    "C": "插件 转录 字幕条 教程"
+  },
+  "2298": {
+    "idx": 2298,
+    "A": "识别 字幕 技巧",
+    "B": "识别视频字幕有什么好办法",
+    "C": "OCR 视频字幕 流程"
+  },
+  "2299": {
+    "idx": 2299,
+    "A": "AI 识别 字幕 技巧",
+    "B": "利用智能技术识别字幕的技巧",
+    "C": "AI 提取文字 字幕条 流程"
+  },
+  "2300": {
+    "idx": 2300,
+    "A": "软件 识别 字幕 技巧",
+    "B": "使用识别软件提取字幕的经验",
+    "C": "电脑端 识别 字幕 怎么做"
+  },
+  "2301": {
+    "idx": 2301,
+    "A": "在线 识别 字幕 技巧",
+    "B": "在线识别字幕的操作技巧",
+    "C": "网页版 检测 视频字幕 步骤"
+  },
+  "2302": {
+    "idx": 2302,
+    "A": "代码 识别 字幕 技巧",
+    "B": "编写代码识别字幕的进阶技巧",
+    "C": "代码 识别 字幕条 方法"
+  },
+  "2303": {
+    "idx": 2303,
+    "A": "插件 识别 字幕 技巧",
+    "B": "使用字幕识别插件的实用技巧",
+    "C": "插件 OCR 视频字幕 步骤"
+  },
+  "2304": {
+    "idx": 2304,
+    "A": "添加 字幕 教程",
+    "B": "怎么给视频添加字幕",
+    "C": "加 字幕条 教学"
+  },
+  "2305": {
+    "idx": 2305,
+    "A": "AI 添加 字幕 教程",
+    "B": "如何用智能方式给视频加字幕",
+    "C": "AI 怎么加 字幕条 教程"
+  },
+  "2306": {
+    "idx": 2306,
+    "A": "软件 添加 字幕 教程",
+    "B": "用什么软件给视频添加字幕",
+    "C": "电脑端 添加 字幕 教学"
+  },
+  "2307": {
+    "idx": 2307,
+    "A": "在线 添加 字幕 教程",
+    "B": "在线给视频加字幕的方法",
+    "C": "在线 怎么加 字幕 怎么做"
+  },
+  "2308": {
+    "idx": 2308,
+    "A": "代码 添加 字幕 教程",
+    "B": "通过代码给视频添加字幕的教程",
+    "C": "代码 加上 视频字幕 教程"
+  },
+  "2309": {
+    "idx": 2309,
+    "A": "插件 添加 字幕 教程",
+    "B": "怎么用插件给视频添加字幕",
+    "C": "插件 添加 字幕条 教学"
+  },
+  "2310": {
+    "idx": 2310,
+    "A": "添加 字幕 工具",
+    "B": "有什么好用的视频加字幕工具",
+    "C": "加 字幕条 方法"
+  },
+  "2311": {
+    "idx": 2311,
+    "A": "AI 添加 字幕 工具",
+    "B": "智能添加字幕的工具推荐",
+    "C": "AI 怎么加 字幕 教程"
+  },
+  "2312": {
+    "idx": 2312,
+    "A": "软件 添加 字幕 工具",
+    "B": "好用的视频字幕制作软件",
+    "C": "软件 加上 字幕条 教学"
+  },
+  "2313": {
+    "idx": 2313,
+    "A": "在线 添加 字幕 工具",
+    "B": "在线给视频加字幕的工具",
+    "C": "在线 加上 字幕 怎么做"
+  },
+  "2314": {
+    "idx": 2314,
+    "A": "代码 添加 字幕 工具",
+    "B": "有没有给视频加字幕的代码工具",
+    "C": "命令行 添加 字幕条 步骤"
+  },
+  "2315": {
+    "idx": 2315,
+    "A": "插件 添加 字幕 工具",
+    "B": "好用的视频加字幕插件",
+    "C": "插件 加 字幕条 怎么做"
+  },
+  "2316": {
+    "idx": 2316,
+    "A": "添加 字幕 技巧",
+    "B": "给视频添加字幕的实用技巧",
+    "C": "怎么加 视频字幕 步骤"
+  },
+  "2317": {
+    "idx": 2317,
+    "A": "AI 添加 字幕 技巧",
+    "B": "智能添加字幕的快捷方法",
+    "C": "AI 怎么加 视频字幕 步骤"
+  },
+  "2318": {
+    "idx": 2318,
+    "A": "软件 添加 字幕 技巧",
+    "B": "使用软件添加字幕的技巧",
+    "C": "电脑端 加上 字幕条 教程"
+  },
+  "2319": {
+    "idx": 2319,
+    "A": "在线 添加 字幕 技巧",
+    "B": "在线添加字幕的操作小技巧",
+    "C": "在线 加上 字幕条 怎么做"
+  },
+  "2320": {
+    "idx": 2320,
+    "A": "代码 添加 字幕 技巧",
+    "B": "用代码实现添加字幕的技巧",
+    "C": "命令行 怎么加 字幕 教学"
+  },
+  "2321": {
+    "idx": 2321,
+    "A": "插件 添加 字幕 技巧",
+    "B": "使用字幕插件的添加技巧",
+    "C": "插件 加上 字幕 方法"
+  },
+  "2322": {
+    "idx": 2322,
+    "A": "风格化 字幕 教程",
+    "B": "怎么制作风格化的字幕",
+    "C": "风格化 字幕 流程"
+  },
+  "2323": {
+    "idx": 2323,
+    "A": "AI 风格化 字幕 教程",
+    "B": "如何用智能技术制作个性化字幕",
+    "C": "AI 怎么转风格 字幕条 步骤"
+  },
+  "2324": {
+    "idx": 2324,
+    "A": "软件 风格化 字幕 教程",
+    "B": "用什么软件能做出风格化字幕",
+    "C": "软件 怎么转风格 字幕 教程"
+  },
+  "2325": {
+    "idx": 2325,
+    "A": "在线 风格化 字幕 教程",
+    "B": "在线制作风格化字幕的方法",
+    "C": "网页版 风格迁移 视频字幕 流程"
+  },
+  "2326": {
+    "idx": 2326,
+    "A": "代码 风格化 字幕 教程",
+    "B": "通过代码制作风格化字幕的教程",
+    "C": "命令行 转风格 字幕 流程"
+  },
+  "2327": {
+    "idx": 2327,
+    "A": "插件 风格化 字幕 教程",
+    "B": "怎么用插件制作风格化字幕的教程",
+    "C": "插件 风格迁移 字幕条 怎么做"
+  },
+  "2328": {
+    "idx": 2328,
+    "A": "风格化 字幕 工具",
+    "B": "有哪些好用的风格化字幕工具",
+    "C": "风格化 视频字幕 方法"
+  },
+  "2329": {
+    "idx": 2329,
+    "A": "AI 风格化 字幕 工具",
+    "B": "有没有能自动生成风格化字幕的工具",
+    "C": "AI 怎么转风格 字幕条 教学"
+  },
+  "2330": {
+    "idx": 2330,
+    "A": "软件 风格化 字幕 工具",
+    "B": "什么软件可以制作风格化字幕",
+    "C": "电脑端 转风格 字幕 教程"
+  },
+  "2331": {
+    "idx": 2331,
+    "A": "在线 风格化 字幕 工具",
+    "B": "在线制作风格化字幕的工具推荐",
+    "C": "在线 风格迁移 视频字幕 教学"
+  },
+  "2332": {
+    "idx": 2332,
+    "A": "代码 风格化 字幕 工具",
+    "B": "通过代码实现字幕风格化的工具",
+    "C": "命令行 风格化 字幕条 教学"
+  },
+  "2333": {
+    "idx": 2333,
+    "A": "插件 风格化 字幕 工具",
+    "B": "制作风格化字幕的插件有哪些",
+    "C": "插件 怎么转风格 字幕 怎么做"
+  },
+  "2334": {
+    "idx": 2334,
+    "A": "风格化 字幕 技巧",
+    "B": "字幕风格化的处理技巧有哪些",
+    "C": "转风格 字幕 教程"
+  },
+  "2335": {
+    "idx": 2335,
+    "A": "AI 风格化 字幕 技巧",
+    "B": "利用人工智能处理字幕风格化的技巧",
+    "C": "AI 怎么转风格 字幕 方法"
+  },
+  "2336": {
+    "idx": 2336,
+    "A": "软件 风格化 字幕 技巧",
+    "B": "使用软件调整字幕风格的技巧",
+    "C": "电脑端 怎么转风格 字幕条 怎么做"
+  },
+  "2337": {
+    "idx": 2337,
+    "A": "在线 风格化 字幕 技巧",
+    "B": "在线处理字幕风格的实用技巧",
+    "C": "网页版 怎么转风格 字幕条 教程"
+  },
+  "2338": {
+    "idx": 2338,
+    "A": "代码 风格化 字幕 技巧",
+    "B": "编写代码调整字幕风格的方法",
+    "C": "命令行 风格化 视频字幕 流程"
+  },
+  "2339": {
+    "idx": 2339,
+    "A": "插件 风格化 字幕 技巧",
+    "B": "使用插件快速调整字幕风格的技巧",
+    "C": "插件 转风格 视频字幕 怎么做"
+  },
+  "2340": {
+    "idx": 2340,
+    "A": "调整 字幕 教程",
+    "B": "如何调整字幕样式的详细教程",
+    "C": "调 视频字幕 流程"
+  },
+  "2341": {
+    "idx": 2341,
+    "A": "AI 调整 字幕 教程",
+    "B": "怎么用人工智能辅助调整字幕",
+    "C": "AI 怎么调 视频字幕 怎么做"
+  },
+  "2342": {
+    "idx": 2342,
+    "A": "软件 调整 字幕 教程",
+    "B": "有哪些好用的字幕调整软件",
+    "C": "电脑端 调整 视频字幕 步骤"
+  },
+  "2343": {
+    "idx": 2343,
+    "A": "在线 调整 字幕 教程",
+    "B": "在线调整字幕样式的操作方法",
+    "C": "在线 调 字幕条 流程"
+  },
+  "2344": {
+    "idx": 2344,
+    "A": "代码 调整 字幕 教程",
+    "B": "如何通过代码调整字幕样式",
+    "C": "代码 调 字幕条 步骤"
+  },
+  "2345": {
+    "idx": 2345,
+    "A": "插件 调整 字幕 教程",
+    "B": "有没有调整字幕样式的插件",
+    "C": "插件 怎么调 视频字幕 教学"
+  },
+  "2346": {
+    "idx": 2346,
+    "A": "调整 字幕 工具",
+    "B": "好用的字幕调整工具有哪些",
+    "C": "怎么调 字幕 方法"
+  },
+  "2347": {
+    "idx": 2347,
+    "A": "AI 调整 字幕 工具",
+    "B": "智能调整字幕的工具有推荐吗",
+    "C": "AI 调 字幕 流程"
+  },
+  "2348": {
+    "idx": 2348,
+    "A": "软件 调整 字幕 工具",
+    "B": "调整字幕样式的软件哪个好用",
+    "C": "电脑端 怎么调 视频字幕 怎么做"
+  },
+  "2349": {
+    "idx": 2349,
+    "A": "在线 调整 字幕 工具",
+    "B": "在线快速调整字幕的工具",
+    "C": "网页版 调 字幕 流程"
+  },
+  "2350": {
+    "idx": 2350,
+    "A": "代码 调整 字幕 工具",
+    "B": "实现字幕自动调整的代码工具",
+    "C": "代码 调 字幕 方法"
+  },
+  "2351": {
+    "idx": 2351,
+    "A": "插件 调整 字幕 工具",
+    "B": "调整字幕样式的插件推荐",
+    "C": "插件 优化 视频字幕 教程"
+  },
+  "2352": {
+    "idx": 2352,
+    "A": "调整 字幕 技巧",
+    "B": "调整字幕样式的进阶技巧",
+    "C": "调整 字幕 教程"
+  },
+  "2353": {
+    "idx": 2353,
+    "A": "AI 调整 字幕 技巧",
+    "B": "利用人工智能优化字幕的技巧",
+    "C": "AI 怎么调 视频字幕 教学"
+  },
+  "2354": {
+    "idx": 2354,
+    "A": "软件 调整 字幕 技巧",
+    "B": "软件调整字幕样式的操作技巧",
+    "C": "电脑端 调 视频字幕 方法"
+  },
+  "2355": {
+    "idx": 2355,
+    "A": "在线 调整 字幕 技巧",
+    "B": "在线调整字幕样式的技巧分享",
+    "C": "网页版 调 字幕条 步骤"
+  },
+  "2356": {
+    "idx": 2356,
+    "A": "代码 调整 字幕 技巧",
+    "B": "通过代码调整字幕的技巧",
+    "C": "代码 调整 字幕 流程"
+  },
+  "2357": {
+    "idx": 2357,
+    "A": "插件 调整 字幕 技巧",
+    "B": "使用插件调整字幕的实用技巧",
+    "C": "插件 调 视频字幕 流程"
+  },
+  "2358": {
+    "idx": 2358,
+    "A": "元素生成 标题 教程",
+    "B": "如何通过元素生成制作标题的教程",
+    "C": "制作 标题 教程"
+  },
+  "2359": {
+    "idx": 2359,
+    "A": "AI 元素生成 标题 教程",
+    "B": "利用人工智能生成标题元素的教程",
+    "C": "AI 生成 标题 教程"
+  },
+  "2360": {
+    "idx": 2360,
+    "A": "软件 元素生成 标题 教程",
+    "B": "用什么软件生成标题元素比较好",
+    "C": "电脑端 做 标题 流程"
+  },
+  "2361": {
+    "idx": 2361,
+    "A": "在线 元素生成 标题 教程",
+    "B": "在线生成标题元素的教程",
+    "C": "在线 生成 爆款标题 方法"
+  },
+  "2362": {
+    "idx": 2362,
+    "A": "代码 元素生成 标题 教程",
+    "B": "通过代码生成标题元素的方法",
+    "C": "代码 做 标题 步骤"
+  },
+  "2363": {
+    "idx": 2363,
+    "A": "插件 元素生成 标题 教程",
+    "B": "有没有生成标题元素的插件",
+    "C": "插件 生成 文案标题 教学"
+  },
+  "2364": {
+    "idx": 2364,
+    "A": "元素生成 标题 工具",
+    "B": "生成标题元素的工具有哪些",
+    "C": "生成 标题 教程"
+  },
+  "2365": {
+    "idx": 2365,
+    "A": "AI 元素生成 标题 工具",
+    "B": "智能生成标题元素的工具推荐",
+    "C": "AI 创作 标题 流程"
+  },
+  "2366": {
+    "idx": 2366,
+    "A": "软件 元素生成 标题 工具",
+    "B": "制作标题元素的软件有哪些",
+    "C": "电脑端 生成 标题 流程"
+  },
+  "2367": {
+    "idx": 2367,
+    "A": "在线 元素生成 标题 工具",
+    "B": "哪里有在线生成标题元素的工具",
+    "C": "网页版 创作 文案标题 步骤"
+  },
+  "2368": {
+    "idx": 2368,
+    "A": "代码 元素生成 标题 工具",
+    "B": "怎么用代码生成标题元素",
+    "C": "代码 创作 爆款标题 方法"
+  },
+  "2369": {
+    "idx": 2369,
+    "A": "插件 元素生成 标题 工具",
+    "B": "有哪些生成标题元素的插件",
+    "C": "插件 创作 爆款标题 教程"
+  },
+  "2370": {
+    "idx": 2370,
+    "A": "元素生成 标题 技巧",
+    "B": "生成标题元素有什么技巧",
+    "C": "生成 爆款标题 教程"
+  },
+  "2371": {
+    "idx": 2371,
+    "A": "AI 元素生成 标题 技巧",
+    "B": "如何利用智能技术生成标题元素",
+    "C": "AI 制作 文案标题 流程"
+  },
+  "2372": {
+    "idx": 2372,
+    "A": "软件 元素生成 标题 技巧",
+    "B": "有没有生成标题元素的软件推荐",
+    "C": "软件 生成 标题 方法"
+  },
+  "2373": {
+    "idx": 2373,
+    "A": "在线 元素生成 标题 技巧",
+    "B": "在线生成标题元素的方法有哪些",
+    "C": "网页版 怎么做 爆款标题 方法"
+  },
+  "2374": {
+    "idx": 2374,
+    "A": "代码 元素生成 标题 技巧",
+    "B": "编写代码生成标题元素的技巧",
+    "C": "代码 做 爆款标题 教程"
+  },
+  "2375": {
+    "idx": 2375,
+    "A": "插件 元素生成 标题 技巧",
+    "B": "好用的标题元素生成插件有哪些",
+    "C": "插件 怎么做 文案标题 怎么做"
+  },
+  "2376": {
+    "idx": 2376,
+    "A": "重述 标题 教程",
+    "B": "如何学习重述标题的教程",
+    "C": "润色 爆款标题 流程"
+  },
+  "2377": {
+    "idx": 2377,
+    "A": "AI 重述 标题 教程",
+    "B": "智能重述标题的详细教程",
+    "C": "AI 改写 文案标题 教程"
+  },
+  "2378": {
+    "idx": 2378,
+    "A": "软件 重述 标题 教程",
+    "B": "有没有重述标题的软件教程",
+    "C": "电脑端 改写 爆款标题 流程"
+  },
+  "2379": {
+    "idx": 2379,
+    "A": "在线 重述 标题 教程",
+    "B": "在线重述标题的操作教程",
+    "C": "网页版 怎么改 爆款标题 步骤"
+  },
+  "2380": {
+    "idx": 2380,
+    "A": "代码 重述 标题 教程",
+    "B": "如何通过代码实现标题重述",
+    "C": "代码 改写 文案标题 怎么做"
+  },
+  "2381": {
+    "idx": 2381,
+    "A": "插件 重述 标题 教程",
+    "B": "重述标题的插件使用教程",
+    "C": "插件 重写 文案标题 怎么做"
+  },
+  "2382": {
+    "idx": 2382,
+    "A": "重述 标题 工具",
+    "B": "哪里有重述标题的工具",
+    "C": "怎么改 爆款标题 怎么做"
+  },
+  "2383": {
+    "idx": 2383,
+    "A": "AI 重述 标题 工具",
+    "B": "好用的智能标题重述工具",
+    "C": "AI 重写 文案标题 怎么做"
+  },
+  "2384": {
+    "idx": 2384,
+    "A": "软件 重述 标题 工具",
+    "B": "有没有重述标题的软件",
+    "C": "软件 改写 文案标题 教学"
+  },
+  "2385": {
+    "idx": 2385,
+    "A": "在线 重述 标题 工具",
+    "B": "在线重述标题的工具推荐",
+    "C": "网页版 润色 标题 教学"
+  },
+  "2386": {
+    "idx": 2386,
+    "A": "代码 重述 标题 工具",
+    "B": "实现标题重述的代码工具",
+    "C": "命令行 改写 文案标题 怎么做"
+  },
+  "2387": {
+    "idx": 2387,
+    "A": "插件 重述 标题 工具",
+    "B": "好用的标题重述插件",
+    "C": "插件 改写 标题 怎么做"
+  },
+  "2388": {
+    "idx": 2388,
+    "A": "重述 标题 技巧",
+    "B": "重述标题有哪些实用技巧",
+    "C": "重写 爆款标题 方法"
+  },
+  "2389": {
+    "idx": 2389,
+    "A": "AI 重述 标题 技巧",
+    "B": "智能重述标题的技巧分享",
+    "C": "AI 润色 标题 步骤"
+  },
+  "2390": {
+    "idx": 2390,
+    "A": "软件 重述 标题 技巧",
+    "B": "使用软件重述标题的技巧",
+    "C": "软件 怎么改 标题 方法"
+  },
+  "2391": {
+    "idx": 2391,
+    "A": "在线 重述 标题 技巧",
+    "B": "在线重述标题的技巧",
+    "C": "网页版 改写 标题 怎么做"
+  },
+  "2392": {
+    "idx": 2392,
+    "A": "代码 重述 标题 技巧",
+    "B": "通过代码重述标题的方法",
+    "C": "命令行 怎么改 爆款标题 方法"
+  },
+  "2393": {
+    "idx": 2393,
+    "A": "插件 重述 标题 技巧",
+    "B": "使用插件重述标题的技巧",
+    "C": "插件 重写 文案标题 怎么做"
+  },
+  "2394": {
+    "idx": 2394,
+    "A": "检索 成品图 教程",
+    "B": "如何检索成品图的教程",
+    "C": "搜索 海报 怎么做"
+  },
+  "2395": {
+    "idx": 2395,
+    "A": "AI 检索 成品图 教程",
+    "B": "智能检索成品图的教程",
+    "C": "AI 搜 海报 教程"
+  },
+  "2396": {
+    "idx": 2396,
+    "A": "软件 检索 成品图 教程",
+    "B": "有没有检索成品图的软件教程",
+    "C": "软件 哪里找 海报 怎么做"
+  },
+  "2397": {
+    "idx": 2397,
+    "A": "在线 检索 成品图 教程",
+    "B": "在线检索成品图的操作教程",
+    "C": "在线 搜 成品图 教程"
+  },
+  "2398": {
+    "idx": 2398,
+    "A": "代码 检索 成品图 教程",
+    "B": "如何用代码实现成品图检索",
+    "C": "代码 找 海报 教学"
+  },
+  "2399": {
+    "idx": 2399,
+    "A": "插件 检索 成品图 教程",
+    "B": "检索成品图的插件使用教程",
+    "C": "插件 搜 海报 方法"
+  },
+  "2400": {
+    "idx": 2400,
+    "A": "检索 成品图 工具",
+    "B": "哪里有检索成品图的工具",
+    "C": "哪里找 出图 步骤"
+  },
+  "2401": {
+    "idx": 2401,
+    "A": "AI 检索 成品图 工具",
+    "B": "好用的智能成品图检索工具",
+    "C": "AI 找 海报 怎么做"
+  },
+  "2402": {
+    "idx": 2402,
+    "A": "软件 检索 成品图 工具",
+    "B": "有没有检索成品图的软件",
+    "C": "软件 哪里找 海报 怎么做"
+  },
+  "2403": {
+    "idx": 2403,
+    "A": "在线 检索 成品图 工具",
+    "B": "在线检索成品图的工具推荐",
+    "C": "网页版 搜索 图 方法"
+  },
+  "2404": {
+    "idx": 2404,
+    "A": "代码 检索 成品图 工具",
+    "B": "实现成品图检索的代码工具",
+    "C": "代码 找 海报 教程"
+  },
+  "2405": {
+    "idx": 2405,
+    "A": "插件 检索 成品图 工具",
+    "B": "好用的成品图检索插件",
+    "C": "插件 在哪找 图 怎么做"
+  },
+  "2406": {
+    "idx": 2406,
+    "A": "检索 成品图 技巧",
+    "B": "检索成品图有哪些实用技巧",
+    "C": "在哪找 海报 教程"
+  },
+  "2407": {
+    "idx": 2407,
+    "A": "AI 检索 成品图 技巧",
+    "B": "如何利用智能技术搜索成品图",
+    "C": "AI 搜 图 教学"
+  },
+  "2408": {
+    "idx": 2408,
+    "A": "软件 检索 成品图 技巧",
+    "B": "有哪些搜索成品图的软件技巧",
+    "C": "软件 在哪找 海报 流程"
+  },
+  "2409": {
+    "idx": 2409,
+    "A": "在线 检索 成品图 技巧",
+    "B": "在线搜索成品图的方法有哪些",
+    "C": "网页版 在哪找 海报 教程"
+  },
+  "2410": {
+    "idx": 2410,
+    "A": "代码 检索 成品图 技巧",
+    "B": "怎么通过代码搜索成品图",
+    "C": "命令行 搜索 海报 怎么做"
+  },
+  "2411": {
+    "idx": 2411,
+    "A": "插件 检索 成品图 技巧",
+    "B": "有没有搜索成品图的插件技巧",
+    "C": "插件 搜索 成品图 怎么做"
+  },
+  "2412": {
+    "idx": 2412,
+    "A": "裁切 成品图 教程",
+    "B": "成品图怎么进行裁切教学",
+    "C": "怎么裁 海报 方法"
+  },
+  "2413": {
+    "idx": 2413,
+    "A": "AI 裁切 成品图 教程",
+    "B": "如何利用智能技术裁切成品图",
+    "C": "AI 怎么裁 图 步骤"
+  },
+  "2414": {
+    "idx": 2414,
+    "A": "软件 裁切 成品图 教程",
+    "B": "用什么软件裁切成品图比较好",
+    "C": "软件 裁剪 成品图 流程"
+  },
+  "2415": {
+    "idx": 2415,
+    "A": "在线 裁切 成品图 教程",
+    "B": "在线裁切成品图的操作教程",
+    "C": "网页版 怎么裁 成品图 教学"
+  },
+  "2416": {
+    "idx": 2416,
+    "A": "代码 裁切 成品图 教程",
+    "B": "如何用代码实现成品图裁切",
+    "C": "命令行 切片 成品图 怎么做"
+  },
+  "2417": {
+    "idx": 2417,
+    "A": "插件 裁切 成品图 教程",
+    "B": "有没有裁切成品图的插件教程",
+    "C": "插件 怎么裁 海报 步骤"
+  },
+  "2418": {
+    "idx": 2418,
+    "A": "裁切 成品图 工具",
+    "B": "好用的成品图裁切工具推荐",
+    "C": "裁剪 出图 流程"
+  },
+  "2419": {
+    "idx": 2419,
+    "A": "AI 裁切 成品图 工具",
+    "B": "智能裁切成品图的工具哪款好用",
+    "C": "AI 怎么裁 成品图 教学"
+  },
+  "2420": {
+    "idx": 2420,
+    "A": "软件 裁切 成品图 工具",
+    "B": "有哪些好用的成品图裁切软件",
+    "C": "软件 怎么裁 成品图 步骤"
+  },
+  "2421": {
+    "idx": 2421,
+    "A": "在线 裁切 成品图 工具",
+    "B": "在线裁切成品图的工具推荐",
+    "C": "在线 裁剪 图 教程"
+  },
+  "2422": {
+    "idx": 2422,
+    "A": "代码 裁切 成品图 工具",
+    "B": "有没有裁切成品图的代码工具",
+    "C": "命令行 切片 海报 步骤"
+  },
+  "2423": {
+    "idx": 2423,
+    "A": "插件 裁切 成品图 工具",
+    "B": "好用的成品图裁切插件有哪些",
+    "C": "插件 切片 成品图 步骤"
+  },
+  "2424": {
+    "idx": 2424,
+    "A": "裁切 成品图 技巧",
+    "B": "成品图裁切有哪些实用技巧",
+    "C": "切片 海报 步骤"
+  },
+  "2425": {
+    "idx": 2425,
+    "A": "AI 裁切 成品图 技巧",
+    "B": "智能裁切成品图的技巧分享",
+    "C": "AI 切片 成品图 教学"
+  },
+  "2426": {
+    "idx": 2426,
+    "A": "软件 裁切 成品图 技巧",
+    "B": "软件裁切成品图的进阶技巧",
+    "C": "软件 怎么裁 海报 方法"
+  },
+  "2427": {
+    "idx": 2427,
+    "A": "在线 裁切 成品图 技巧",
+    "B": "在线裁切成品图的实用技巧",
+    "C": "网页版 截取 图 步骤"
+  },
+  "2428": {
+    "idx": 2428,
+    "A": "代码 裁切 成品图 技巧",
+    "B": "通过代码裁切成品图的技巧",
+    "C": "命令行 截取 海报 教学"
+  },
+  "2429": {
+    "idx": 2429,
+    "A": "插件 裁切 成品图 技巧",
+    "B": "插件裁切成品图的技巧有哪些",
+    "C": "插件 截取 图 步骤"
+  },
+  "2430": {
+    "idx": 2430,
+    "A": "抠取 成品图 教程",
+    "B": "成品图抠图的详细教程",
+    "C": "抠图 图 方法"
+  },
+  "2431": {
+    "idx": 2431,
+    "A": "AI 抠取 成品图 教程",
+    "B": "如何利用智能技术抠取成品图",
+    "C": "AI 抠 成品图 教学"
+  },
+  "2432": {
+    "idx": 2432,
+    "A": "软件 抠取 成品图 教程",
+    "B": "用什么软件抠取成品图比较好",
+    "C": "软件 分割 图 教程"
+  },
+  "2433": {
+    "idx": 2433,
+    "A": "在线 抠取 成品图 教程",
+    "B": "在线抠取成品图的操作教程",
+    "C": "网页版 怎么抠 出图 步骤"
+  },
+  "2434": {
+    "idx": 2434,
+    "A": "代码 抠取 成品图 教程",
+    "B": "如何用代码实现成品图抠取",
+    "C": "代码 分割 图 怎么做"
+  },
+  "2435": {
+    "idx": 2435,
+    "A": "插件 抠取 成品图 教程",
+    "B": "有没有抠取成品图的插件教程",
+    "C": "插件 抠 海报 怎么做"
+  },
+  "2436": {
+    "idx": 2436,
+    "A": "抠取 成品图 工具",
+    "B": "好用的成品图抠取工具推荐",
+    "C": "分割 海报 教学"
+  },
+  "2437": {
+    "idx": 2437,
+    "A": "AI 抠取 成品图 工具",
+    "B": "智能抠取成品图的工具哪款好用",
+    "C": "AI 抠图 出图 方法"
+  },
+  "2438": {
+    "idx": 2438,
+    "A": "软件 抠取 成品图 工具",
+    "B": "有哪些好用的成品图抠取软件",
+    "C": "电脑端 抠 海报 步骤"
+  },
+  "2439": {
+    "idx": 2439,
+    "A": "在线 抠取 成品图 工具",
+    "B": "在线抠取成品图的工具推荐",
+    "C": "网页版 抠图 出图 步骤"
+  },
+  "2440": {
+    "idx": 2440,
+    "A": "代码 抠取 成品图 工具",
+    "B": "有没有抠取成品图的代码工具",
+    "C": "命令行 抠 出图 流程"
+  },
+  "2441": {
+    "idx": 2441,
+    "A": "插件 抠取 成品图 工具",
+    "B": "好用的成品图抠取插件有哪些",
+    "C": "插件 怎么抠 海报 步骤"
+  },
+  "2442": {
+    "idx": 2442,
+    "A": "抠取 成品图 技巧",
+    "B": "成品图抠取有哪些实用技巧",
+    "C": "抠图 出图 怎么做"
+  },
+  "2443": {
+    "idx": 2443,
+    "A": "AI 抠取 成品图 技巧",
+    "B": "智能抠取成品图的技巧分享",
+    "C": "AI 分割 出图 步骤"
+  },
+  "2444": {
+    "idx": 2444,
+    "A": "软件 抠取 成品图 技巧",
+    "B": "软件抠取成品图的进阶技巧",
+    "C": "软件 怎么抠 出图 教程"
+  },
+  "2445": {
+    "idx": 2445,
+    "A": "在线 抠取 成品图 技巧",
+    "B": "在线抠取成品图的实用技巧",
+    "C": "在线 抠 成品图 流程"
+  },
+  "2446": {
+    "idx": 2446,
+    "A": "代码 抠取 成品图 技巧",
+    "B": "通过代码抠取成品图的技巧",
+    "C": "命令行 怎么抠 海报 方法"
+  },
+  "2447": {
+    "idx": 2447,
+    "A": "插件 抠取 成品图 技巧",
+    "B": "怎么用插件把成品图抠出来",
+    "C": "插件 怎么抠 成品图 流程"
+  },
+  "2448": {
+    "idx": 2448,
+    "A": "识别 成品图 教程",
+    "B": "如何识别成品图的教程",
+    "C": "检测 图 流程"
+  },
+  "2449": {
+    "idx": 2449,
+    "A": "AI 识别 成品图 教程",
+    "B": "怎样用智能技术识别成品图",
+    "C": "AI OCR 图 教学"
+  },
+  "2450": {
+    "idx": 2450,
+    "A": "软件 识别 成品图 教程",
+    "B": "有什么软件可以识别成品图",
+    "C": "软件 识别 海报 教程"
+  },
+  "2451": {
+    "idx": 2451,
+    "A": "在线 识别 成品图 教程",
+    "B": "在线识别成品图的方法有哪些",
+    "C": "在线 识别 图 方法"
+  },
+  "2452": {
+    "idx": 2452,
+    "A": "代码 识别 成品图 教程",
+    "B": "如何通过代码识别成品图",
+    "C": "命令行 识别 海报 步骤"
+  },
+  "2453": {
+    "idx": 2453,
+    "A": "插件 识别 成品图 教程",
+    "B": "怎么用插件识别成品图",
+    "C": "插件 提取文字 出图 流程"
+  },
+  "2454": {
+    "idx": 2454,
+    "A": "识别 成品图 工具",
+    "B": "有哪些好用的成品图识别工具",
+    "C": "识别 成品图 方法"
+  },
+  "2455": {
+    "idx": 2455,
+    "A": "AI 识别 成品图 工具",
+    "B": "好用的智能成品图识别工具推荐",
+    "C": "AI 提取文字 成品图 流程"
+  },
+  "2456": {
+    "idx": 2456,
+    "A": "软件 识别 成品图 工具",
+    "B": "识别成品图的软件有哪些",
+    "C": "软件 OCR 图 方法"
+  },
+  "2457": {
+    "idx": 2457,
+    "A": "在线 识别 成品图 工具",
+    "B": "在线识别成品图的工具推荐",
+    "C": "网页版 检测 海报 流程"
+  },
+  "2458": {
+    "idx": 2458,
+    "A": "代码 识别 成品图 工具",
+    "B": "有没有识别成品图的代码工具",
+    "C": "代码 识别 出图 流程"
+  },
+  "2459": {
+    "idx": 2459,
+    "A": "插件 识别 成品图 工具",
+    "B": "好用的成品图识别插件推荐",
+    "C": "插件 提取文字 海报 步骤"
+  },
+  "2460": {
+    "idx": 2460,
+    "A": "识别 成品图 技巧",
+    "B": "识别成品图有什么小技巧",
+    "C": "转录 成品图 怎么做"
+  },
+  "2461": {
+    "idx": 2461,
+    "A": "AI 识别 成品图 技巧",
+    "B": "智能识别成品图的技巧分享",
+    "C": "AI 识别 图 方法"
+  },
+  "2462": {
+    "idx": 2462,
+    "A": "软件 识别 成品图 技巧",
+    "B": "使用软件识别成品图的技巧",
+    "C": "电脑端 提取文字 出图 步骤"
+  },
+  "2463": {
+    "idx": 2463,
+    "A": "在线 识别 成品图 技巧",
+    "B": "在线识别成品图的操作技巧",
+    "C": "在线 OCR 海报 教学"
+  },
+  "2464": {
+    "idx": 2464,
+    "A": "代码 识别 成品图 技巧",
+    "B": "通过代码识别成品图的技巧",
+    "C": "命令行 OCR 成品图 教学"
+  },
+  "2465": {
+    "idx": 2465,
+    "A": "插件 识别 成品图 技巧",
+    "B": "使用插件识别成品图的技巧",
+    "C": "插件 识别 出图 步骤"
+  },
+  "2466": {
+    "idx": 2466,
+    "A": "反推 成品图 教程",
+    "B": "如何反推成品图的教程",
+    "C": "怎么反推 图 教学"
+  },
+  "2467": {
+    "idx": 2467,
+    "A": "AI 反推 成品图 教程",
+    "B": "智能反推成品图的详细教程",
+    "C": "AI 反推 出图 怎么做"
+  },
+  "2468": {
+    "idx": 2468,
+    "A": "软件 反推 成品图 教程",
+    "B": "用软件反推成品图的教程",
+    "C": "电脑端 反推 海报 步骤"
+  },
+  "2469": {
+    "idx": 2469,
+    "A": "在线 反推 成品图 教程",
+    "B": "在线反推成品图的教程",
+    "C": "网页版 反推 出图 步骤"
+  },
+  "2470": {
+    "idx": 2470,
+    "A": "代码 反推 成品图 教程",
+    "B": "如何用代码反推成品图",
+    "C": "代码 分析 海报 教学"
+  },
+  "2471": {
+    "idx": 2471,
+    "A": "插件 反推 成品图 教程",
+    "B": "怎么用插件反推成品图",
+    "C": "插件 怎么反推 成品图 步骤"
+  },
+  "2472": {
+    "idx": 2472,
+    "A": "反推 成品图 工具",
+    "B": "有没有反推成品图的工具",
+    "C": "反推 海报 怎么做"
+  },
+  "2473": {
+    "idx": 2473,
+    "A": "AI 反推 成品图 工具",
+    "B": "智能反推成品图的工具推荐",
+    "C": "AI 推断 海报 教程"
+  },
+  "2474": {
+    "idx": 2474,
+    "A": "软件 反推 成品图 工具",
+    "B": "反推成品图的软件有哪些",
+    "C": "软件 推断 成品图 步骤"
+  },
+  "2475": {
+    "idx": 2475,
+    "A": "在线 反推 成品图 工具",
+    "B": "在线反推成品图的工具",
+    "C": "网页版 推断 海报 教学"
+  },
+  "2476": {
+    "idx": 2476,
+    "A": "代码 反推 成品图 工具",
+    "B": "反推成品图的代码工具",
+    "C": "代码 反推 出图 教学"
+  },
+  "2477": {
+    "idx": 2477,
+    "A": "插件 反推 成品图 工具",
+    "B": "反推成品图的插件有哪些",
+    "C": "插件 分析 成品图 怎么做"
+  },
+  "2478": {
+    "idx": 2478,
+    "A": "反推 成品图 技巧",
+    "B": "反推成品图有哪些技巧",
+    "C": "分析 图 步骤"
+  },
+  "2479": {
+    "idx": 2479,
+    "A": "AI 反推 成品图 技巧",
+    "B": "智能反推成品图的技巧",
+    "C": "AI 反推 出图 流程"
+  },
+  "2480": {
+    "idx": 2480,
+    "A": "软件 反推 成品图 技巧",
+    "B": "软件反推成品图的技巧",
+    "C": "软件 怎么反推 图 怎么做"
+  },
+  "2481": {
+    "idx": 2481,
+    "A": "在线 反推 成品图 技巧",
+    "B": "在线反推成品图的技巧",
+    "C": "网页版 分析 图 流程"
+  },
+  "2482": {
+    "idx": 2482,
+    "A": "代码 反推 成品图 技巧",
+    "B": "代码反推成品图的技巧",
+    "C": "命令行 推断 出图 教程"
+  },
+  "2483": {
+    "idx": 2483,
+    "A": "插件 反推 成品图 技巧",
+    "B": "插件反推成品图的技巧",
+    "C": "插件 推断 出图 怎么做"
+  },
+  "2484": {
+    "idx": 2484,
+    "A": "抹除 成品图 教程",
+    "B": "怎么把成品图抹除的教程",
+    "C": "抹除 出图 教程"
+  },
+  "2485": {
+    "idx": 2485,
+    "A": "AI 抹除 成品图 教程",
+    "B": "如何用智能技术抹除成品图",
+    "C": "AI 消除 出图 教程"
+  },
+  "2486": {
+    "idx": 2486,
+    "A": "软件 抹除 成品图 教程",
+    "B": "用软件抹除成品图的教程",
+    "C": "电脑端 去掉 图 教学"
+  },
+  "2487": {
+    "idx": 2487,
+    "A": "在线 抹除 成品图 教程",
+    "B": "如何在线把成品图里的东西抹掉",
+    "C": "在线 去除 海报 方法"
+  },
+  "2488": {
+    "idx": 2488,
+    "A": "代码 抹除 成品图 教程",
+    "B": "怎么用代码实现成品图的抹除效果",
+    "C": "命令行 消除 图 流程"
+  },
+  "2489": {
+    "idx": 2489,
+    "A": "插件 抹除 成品图 教程",
+    "B": "有什么插件可以抹除成品图内容",
+    "C": "插件 怎么去掉 出图 方法"
+  },
+  "2490": {
+    "idx": 2490,
+    "A": "抹除 成品图 工具",
+    "B": "成品图抹除工具有哪些",
+    "C": "去除 成品图 教学"
+  },
+  "2491": {
+    "idx": 2491,
+    "A": "AI 抹除 成品图 工具",
+    "B": "好用的智能成品图抹除工具推荐",
+    "C": "AI 抹除 海报 教程"
+  },
+  "2492": {
+    "idx": 2492,
+    "A": "软件 抹除 成品图 工具",
+    "B": "处理成品图抹除的软件有哪些",
+    "C": "软件 去掉 出图 步骤"
+  },
+  "2493": {
+    "idx": 2493,
+    "A": "在线 抹除 成品图 工具",
+    "B": "在线抹除成品图内容的工具推荐",
+    "C": "网页版 抹除 海报 流程"
+  },
+  "2494": {
+    "idx": 2494,
+    "A": "代码 抹除 成品图 工具",
+    "B": "有没有能抹除成品图的代码工具",
+    "C": "命令行 去掉 出图 步骤"
+  },
+  "2495": {
+    "idx": 2495,
+    "A": "插件 抹除 成品图 工具",
+    "B": "好用的成品图抹除插件推荐",
+    "C": "插件 抹除 出图 怎么做"
+  },
+  "2496": {
+    "idx": 2496,
+    "A": "抹除 成品图 技巧",
+    "B": "成品图抹除有什么操作技巧",
+    "C": "去掉 成品图 步骤"
+  },
+  "2497": {
+    "idx": 2497,
+    "A": "AI 抹除 成品图 技巧",
+    "B": "智能处理成品图抹除的技巧",
+    "C": "AI 去掉 海报 流程"
+  },
+  "2498": {
+    "idx": 2498,
+    "A": "软件 抹除 成品图 技巧",
+    "B": "使用软件抹除成品图的技巧",
+    "C": "电脑端 消除 海报 教程"
+  },
+  "2499": {
+    "idx": 2499,
+    "A": "在线 抹除 成品图 技巧",
+    "B": "在线抹除成品图的实用技巧",
+    "C": "在线 抹除 出图 步骤"
+  },
+  "2500": {
+    "idx": 2500,
+    "A": "代码 抹除 成品图 技巧",
+    "B": "通过代码抹除成品图的技巧",
+    "C": "命令行 去掉 海报 教学"
+  },
+  "2501": {
+    "idx": 2501,
+    "A": "插件 抹除 成品图 技巧",
+    "B": "使用插件抹除成品图的技巧",
+    "C": "插件 消除 图 教程"
+  },
+  "2502": {
+    "idx": 2502,
+    "A": "风格化 成品图 教程",
+    "B": "如何给成品图做风格化处理",
+    "C": "风格化 成品图 教程"
+  },
+  "2503": {
+    "idx": 2503,
+    "A": "AI 风格化 成品图 教程",
+    "B": "怎么用智能技术给成品图做风格化",
+    "C": "AI 转风格 海报 步骤"
+  },
+  "2504": {
+    "idx": 2504,
+    "A": "软件 风格化 成品图 教程",
+    "B": "用什么软件能给成品图做风格化",
+    "C": "软件 风格化 图 方法"
+  },
+  "2505": {
+    "idx": 2505,
+    "A": "在线 风格化 成品图 教程",
+    "B": "在线给成品图做风格化处理的方法",
+    "C": "网页版 风格迁移 海报 教学"
+  },
+  "2506": {
+    "idx": 2506,
+    "A": "代码 风格化 成品图 教程",
+    "B": "用代码实现成品图风格化的教程",
+    "C": "命令行 转风格 成品图 方法"
+  },
+  "2507": {
+    "idx": 2507,
+    "A": "插件 风格化 成品图 教程",
+    "B": "有哪些插件可以给成品图做风格化",
+    "C": "插件 风格迁移 出图 方法"
+  },
+  "2508": {
+    "idx": 2508,
+    "A": "风格化 成品图 工具",
+    "B": "成品图风格化处理工具有哪些",
+    "C": "怎么转风格 图 怎么做"
+  },
+  "2509": {
+    "idx": 2509,
+    "A": "AI 风格化 成品图 工具",
+    "B": "智能成品图风格化工具推荐",
+    "C": "AI 风格化 图 教学"
+  },
+  "2510": {
+    "idx": 2510,
+    "A": "软件 风格化 成品图 工具",
+    "B": "好用的成品图风格化软件",
+    "C": "电脑端 转风格 图 教程"
+  },
+  "2511": {
+    "idx": 2511,
+    "A": "在线 风格化 成品图 工具",
+    "B": "在线成品图风格化工具推荐",
+    "C": "网页版 风格化 出图 怎么做"
+  },
+  "2512": {
+    "idx": 2512,
+    "A": "代码 风格化 成品图 工具",
+    "B": "有没有能做风格化的代码工具",
+    "C": "命令行 风格迁移 海报 步骤"
+  },
+  "2513": {
+    "idx": 2513,
+    "A": "插件 风格化 成品图 工具",
+    "B": "好用的成品图风格化插件",
+    "C": "插件 风格迁移 图 怎么做"
+  },
+  "2514": {
+    "idx": 2514,
+    "A": "风格化 成品图 技巧",
+    "B": "成品图风格化处理有什么技巧",
+    "C": "转风格 图 教学"
+  },
+  "2515": {
+    "idx": 2515,
+    "A": "AI 风格化 成品图 技巧",
+    "B": "智能风格化成品图的操作技巧",
+    "C": "AI 转风格 海报 教程"
+  },
+  "2516": {
+    "idx": 2516,
+    "A": "软件 风格化 成品图 技巧",
+    "B": "用软件做成品图风格化的技巧",
+    "C": "软件 转风格 成品图 流程"
+  },
+  "2517": {
+    "idx": 2517,
+    "A": "在线 风格化 成品图 技巧",
+    "B": "在线进行成品图风格化的技巧",
+    "C": "在线 风格化 海报 步骤"
+  },
+  "2518": {
+    "idx": 2518,
+    "A": "代码 风格化 成品图 技巧",
+    "B": "通过代码实现成品图风格化的技巧",
+    "C": "代码 怎么转风格 海报 教程"
+  },
+  "2519": {
+    "idx": 2519,
+    "A": "插件 风格化 成品图 技巧",
+    "B": "使用插件进行成品图风格化的技巧",
+    "C": "插件 风格化 海报 步骤"
+  },
+  "2520": {
+    "idx": 2520,
+    "A": "转换 成品图 教程",
+    "B": "如何把成品图转换成其他格式或效果",
+    "C": "转格式 海报 怎么做"
+  },
+  "2521": {
+    "idx": 2521,
+    "A": "AI 转换 成品图 教程",
+    "B": "怎么用智能技术转换成品图",
+    "C": "AI 转 成品图 步骤"
+  },
+  "2522": {
+    "idx": 2522,
+    "A": "软件 转换 成品图 教程",
+    "B": "用什么软件可以转换成品图",
+    "C": "软件 转 图 流程"
+  },
+  "2523": {
+    "idx": 2523,
+    "A": "在线 转换 成品图 教程",
+    "B": "在线转换成品图的方法",
+    "C": "在线 怎么转 出图 方法"
+  },
+  "2524": {
+    "idx": 2524,
+    "A": "代码 转换 成品图 教程",
+    "B": "用代码转换成品图的教程",
+    "C": "代码 转 海报 教程"
+  },
+  "2525": {
+    "idx": 2525,
+    "A": "插件 转换 成品图 教程",
+    "B": "有什么插件可以转换成品图",
+    "C": "插件 转格式 成品图 步骤"
+  },
+  "2526": {
+    "idx": 2526,
+    "A": "转换 成品图 工具",
+    "B": "成品图转换工具有哪些",
+    "C": "转换 图 教学"
+  },
+  "2527": {
+    "idx": 2527,
+    "A": "AI 转换 成品图 工具",
+    "B": "怎么用人工智能把素材转换成成品图",
+    "C": "AI 转格式 图 方法"
+  },
+  "2528": {
+    "idx": 2528,
+    "A": "软件 转换 成品图 工具",
+    "B": "有什么软件可以把素材转换成成品图",
+    "C": "软件 怎么转 出图 教程"
+  },
+  "2529": {
+    "idx": 2529,
+    "A": "在线 转换 成品图 工具",
+    "B": "在线把素材转换成成品图的方法",
+    "C": "在线 转格式 海报 怎么做"
+  },
+  "2530": {
+    "idx": 2530,
+    "A": "代码 转换 成品图 工具",
+    "B": "如何通过代码实现素材转成品图",
+    "C": "命令行 转换 图 教程"
+  },
+  "2531": {
+    "idx": 2531,
+    "A": "插件 转换 成品图 工具",
+    "B": "有没有能把素材转成品图的插件",
+    "C": "插件 怎么转 出图 流程"
+  },
+  "2532": {
+    "idx": 2532,
+    "A": "转换 成品图 技巧",
+    "B": "转换成品图有什么实用技巧",
+    "C": "转换 图 步骤"
+  },
+  "2533": {
+    "idx": 2533,
+    "A": "AI 转换 成品图 技巧",
+    "B": "利用人工智能转换成品图的技巧",
+    "C": "AI 转换 海报 教程"
+  },
+  "2534": {
+    "idx": 2534,
+    "A": "软件 转换 成品图 技巧",
+    "B": "使用软件转换成品图的技巧",
+    "C": "电脑端 怎么转 出图 流程"
+  },
+  "2535": {
+    "idx": 2535,
+    "A": "在线 转换 成品图 技巧",
+    "B": "在线转换成品图的技巧有哪些",
+    "C": "网页版 转换 成品图 流程"
+  },
+  "2536": {
+    "idx": 2536,
+    "A": "代码 转换 成品图 技巧",
+    "B": "通过代码转换成品图的技巧",
+    "C": "代码 转格式 海报 步骤"
+  },
+  "2537": {
+    "idx": 2537,
+    "A": "插件 转换 成品图 技巧",
+    "B": "使用插件转换成品图的技巧",
+    "C": "插件 转换 图 怎么做"
+  },
+  "2538": {
+    "idx": 2538,
+    "A": "调整 成品图 教程",
+    "B": "怎么调整成品图的详细教程",
+    "C": "优化 图 教学"
+  },
+  "2539": {
+    "idx": 2539,
+    "A": "AI 调整 成品图 教程",
+    "B": "如何用人工智能调整成品图",
+    "C": "AI 怎么调 成品图 步骤"
+  },
+  "2540": {
+    "idx": 2540,
+    "A": "软件 调整 成品图 教程",
+    "B": "有什么软件可以调整成品图",
+    "C": "软件 优化 海报 怎么做"
+  },
+  "2541": {
+    "idx": 2541,
+    "A": "在线 调整 成品图 教程",
+    "B": "在线调整成品图的操作教程",
+    "C": "网页版 怎么调 海报 教程"
+  },
+  "2542": {
+    "idx": 2542,
+    "A": "代码 调整 成品图 教程",
+    "B": "通过代码调整成品图的教程",
+    "C": "命令行 怎么调 出图 怎么做"
+  },
+  "2543": {
+    "idx": 2543,
+    "A": "插件 调整 成品图 教程",
+    "B": "有没有调整成品图的插件教程",
+    "C": "插件 调整 成品图 方法"
+  },
+  "2544": {
+    "idx": 2544,
+    "A": "调整 成品图 工具",
+    "B": "调整成品图用什么工具比较好",
+    "C": "怎么调 海报 教学"
+  },
+  "2545": {
+    "idx": 2545,
+    "A": "AI 调整 成品图 工具",
+    "B": "有什么人工智能工具能调整成品图",
+    "C": "AI 调 海报 方法"
+  },
+  "2546": {
+    "idx": 2546,
+    "A": "软件 调整 成品图 工具",
+    "B": "调整成品图的软件有哪些",
+    "C": "软件 怎么调 海报 怎么做"
+  },
+  "2547": {
+    "idx": 2547,
+    "A": "在线 调整 成品图 工具",
+    "B": "在线调整成品图的工具推荐",
+    "C": "在线 优化 图 流程"
+  },
+  "2548": {
+    "idx": 2548,
+    "A": "代码 调整 成品图 工具",
+    "B": "通过代码调整成品图的工具",
+    "C": "代码 怎么调 出图 方法"
+  },
+  "2549": {
+    "idx": 2549,
+    "A": "插件 调整 成品图 工具",
+    "B": "调整成品图的插件工具有哪些",
+    "C": "插件 怎么调 成品图 方法"
+  },
+  "2550": {
+    "idx": 2550,
+    "A": "调整 成品图 技巧",
+    "B": "调整成品图有哪些实用技巧",
+    "C": "调整 成品图 方法"
+  },
+  "2551": {
+    "idx": 2551,
+    "A": "AI 调整 成品图 技巧",
+    "B": "利用人工智能调整成品图的技巧",
+    "C": "AI 优化 海报 教程"
+  },
+  "2552": {
+    "idx": 2552,
+    "A": "软件 调整 成品图 技巧",
+    "B": "使用软件调整成品图的技巧",
+    "C": "电脑端 怎么调 图 步骤"
+  },
+  "2553": {
+    "idx": 2553,
+    "A": "在线 调整 成品图 技巧",
+    "B": "在线调整成品图的技巧分享",
+    "C": "在线 调整 成品图 教学"
+  },
+  "2554": {
+    "idx": 2554,
+    "A": "代码 调整 成品图 技巧",
+    "B": "通过代码调整成品图的技巧",
+    "C": "命令行 调 出图 怎么做"
+  },
+  "2555": {
+    "idx": 2555,
+    "A": "插件 调整 成品图 技巧",
+    "B": "使用插件调整成品图的技巧",
+    "C": "插件 调整 海报 教学"
+  },
+  "2556": {
+    "idx": 2556,
+    "A": "增强 成品图 教程",
+    "B": "如何增强成品图的画质教程",
+    "C": "怎么增强 图 方法"
+  },
+  "2557": {
+    "idx": 2557,
+    "A": "AI 增强 成品图 教程",
+    "B": "用人工智能增强成品图的教程",
+    "C": "AI 修复 图 步骤"
+  },
+  "2558": {
+    "idx": 2558,
+    "A": "软件 增强 成品图 教程",
+    "B": "使用软件增强成品图的教程",
+    "C": "软件 提升画质 出图 教程"
+  },
+  "2559": {
+    "idx": 2559,
+    "A": "在线 增强 成品图 教程",
+    "B": "在线增强成品图的教程",
+    "C": "网页版 增强 海报 方法"
+  },
+  "2560": {
+    "idx": 2560,
+    "A": "代码 增强 成品图 教程",
+    "B": "通过代码增强成品图的教程",
+    "C": "代码 增强 海报 教程"
+  },
+  "2561": {
+    "idx": 2561,
+    "A": "插件 增强 成品图 教程",
+    "B": "使用插件增强成品图的教程",
+    "C": "插件 提升画质 海报 怎么做"
+  },
+  "2562": {
+    "idx": 2562,
+    "A": "增强 成品图 工具",
+    "B": "增强成品图用什么工具好",
+    "C": "修复 海报 步骤"
+  },
+  "2563": {
+    "idx": 2563,
+    "A": "AI 增强 成品图 工具",
+    "B": "有什么人工智能工具可以增强成品图",
+    "C": "AI 修复 图 教程"
+  },
+  "2564": {
+    "idx": 2564,
+    "A": "软件 增强 成品图 工具",
+    "B": "增强成品图的软件推荐",
+    "C": "软件 提升画质 成品图 流程"
+  },
+  "2565": {
+    "idx": 2565,
+    "A": "在线 增强 成品图 工具",
+    "B": "在线增强成品图的工具",
+    "C": "在线 增强 出图 教程"
+  },
+  "2566": {
+    "idx": 2566,
+    "A": "代码 增强 成品图 工具",
+    "B": "通过代码增强成品图的工具",
+    "C": "代码 修复 出图 教学"
+  },
+  "2567": {
+    "idx": 2567,
+    "A": "插件 增强 成品图 工具",
+    "B": "有哪些好用的图片画质增强工具",
+    "C": "插件 修复 出图 教程"
+  },
+  "2568": {
+    "idx": 2568,
+    "A": "增强 成品图 技巧",
+    "B": "如何提升图片画质的技巧",
+    "C": "怎么增强 海报 流程"
+  },
+  "2569": {
+    "idx": 2569,
+    "A": "AI 增强 成品图 技巧",
+    "B": "怎么用智能技术提升图片画质",
+    "C": "AI 修复 成品图 教程"
+  },
+  "2570": {
+    "idx": 2570,
+    "A": "软件 增强 成品图 技巧",
+    "B": "有没有提升图片画质的软件使用技巧",
+    "C": "软件 提升画质 海报 怎么做"
+  },
+  "2571": {
+    "idx": 2571,
+    "A": "在线 增强 成品图 技巧",
+    "B": "在线提升图片画质的方法",
+    "C": "网页版 增强 海报 方法"
+  },
+  "2572": {
+    "idx": 2572,
+    "A": "代码 增强 成品图 技巧",
+    "B": "通过代码实现图片画质增强的技巧",
+    "C": "代码 提升画质 图 方法"
+  },
+  "2573": {
+    "idx": 2573,
+    "A": "插件 增强 成品图 技巧",
+    "B": "有哪些提升图片画质的插件及技巧",
+    "C": "插件 增强 图 教程"
+  },
+  "2574": {
+    "idx": 2574,
+    "A": "下载 视频成品 教程",
+    "B": "视频成品下载教程",
+    "C": "下载 视频 教学"
+  },
+  "2575": {
+    "idx": 2575,
+    "A": "AI 下载 视频成品 教程",
+    "B": "如何用智能技术下载视频成品",
+    "C": "AI 导入 成片 教学"
+  },
+  "2576": {
+    "idx": 2576,
+    "A": "软件 下载 视频成品 教程",
+    "B": "下载视频成品的软件操作教程",
+    "C": "电脑端 下载 成片 怎么做"
+  },
+  "2577": {
+    "idx": 2577,
+    "A": "在线 下载 视频成品 教程",
+    "B": "在线下载视频成品的方法",
+    "C": "网页版 导入 视频成品 教学"
+  },
+  "2578": {
+    "idx": 2578,
+    "A": "代码 下载 视频成品 教程",
+    "B": "通过代码下载视频成品的教程",
+    "C": "代码 下载 成片 方法"
+  },
+  "2579": {
+    "idx": 2579,
+    "A": "插件 下载 视频成品 教程",
+    "B": "下载视频成品的插件使用教程",
+    "C": "插件 下载 成片 教学"
+  },
+  "2580": {
+    "idx": 2580,
+    "A": "下载 视频成品 工具",
+    "B": "好用的视频成品下载工具",
+    "C": "导入 成片 教程"
+  },
+  "2581": {
+    "idx": 2581,
+    "A": "AI 下载 视频成品 工具",
+    "B": "智能视频成品下载工具推荐",
+    "C": "AI 获取 成片 教学"
+  },
+  "2582": {
+    "idx": 2582,
+    "A": "软件 下载 视频成品 工具",
+    "B": "下载视频成品的软件有哪些",
+    "C": "电脑端 下载 视频成品 步骤"
+  },
+  "2583": {
+    "idx": 2583,
+    "A": "在线 下载 视频成品 工具",
+    "B": "在线下载视频成品的工具",
+    "C": "在线 导入 成片 怎么做"
+  },
+  "2584": {
+    "idx": 2584,
+    "A": "代码 下载 视频成品 工具",
+    "B": "好用的视频成品下载代码工具",
+    "C": "代码 怎么下载 视频 教学"
+  },
+  "2585": {
+    "idx": 2585,
+    "A": "插件 下载 视频成品 工具",
+    "B": "下载视频成品的插件工具",
+    "C": "插件 导入 视频成品 步骤"
+  },
+  "2586": {
+    "idx": 2586,
+    "A": "下载 视频成品 技巧",
+    "B": "下载视频成品的实用技巧",
+    "C": "导入 成片 教学"
+  },
+  "2587": {
+    "idx": 2587,
+    "A": "AI 下载 视频成品 技巧",
+    "B": "智能下载视频成品的技巧",
+    "C": "AI 导入 视频成品 方法"
+  },
+  "2588": {
+    "idx": 2588,
+    "A": "软件 下载 视频成品 技巧",
+    "B": "使用软件下载视频成品的技巧",
+    "C": "软件 获取 视频 教学"
+  },
+  "2589": {
+    "idx": 2589,
+    "A": "在线 下载 视频成品 技巧",
+    "B": "在线下载视频成品的技巧",
+    "C": "在线 导入 视频成品 流程"
+  },
+  "2590": {
+    "idx": 2590,
+    "A": "代码 下载 视频成品 技巧",
+    "B": "通过代码下载视频成品的技巧",
+    "C": "代码 怎么下载 视频 怎么做"
+  },
+  "2591": {
+    "idx": 2591,
+    "A": "插件 下载 视频成品 技巧",
+    "B": "使用插件下载视频成品的技巧",
+    "C": "插件 导入 成片 步骤"
+  },
+  "2592": {
+    "idx": 2592,
+    "A": "裁切 视频成品 教程",
+    "B": "视频成品裁切教程",
+    "C": "截取 视频成品 方法"
+  },
+  "2593": {
+    "idx": 2593,
+    "A": "AI 裁切 视频成品 教程",
+    "B": "智能裁切视频成品的教程",
+    "C": "AI 裁剪 成片 步骤"
+  },
+  "2594": {
+    "idx": 2594,
+    "A": "软件 裁切 视频成品 教程",
+    "B": "用软件裁切视频成品的教程",
+    "C": "电脑端 截取 视频成品 方法"
+  },
+  "2595": {
+    "idx": 2595,
+    "A": "在线 裁切 视频成品 教程",
+    "B": "在线裁切视频成品的教程",
+    "C": "在线 裁剪 成片 怎么做"
+  },
+  "2596": {
+    "idx": 2596,
+    "A": "代码 裁切 视频成品 教程",
+    "B": "通过代码裁切视频成品的教程",
+    "C": "代码 截取 视频成品 方法"
+  },
+  "2597": {
+    "idx": 2597,
+    "A": "插件 裁切 视频成品 教程",
+    "B": "使用插件裁切视频成品的教程",
+    "C": "插件 切片 成片 步骤"
+  },
+  "2598": {
+    "idx": 2598,
+    "A": "裁切 视频成品 工具",
+    "B": "好用的视频成品裁切工具",
+    "C": "怎么裁 视频成品 方法"
+  },
+  "2599": {
+    "idx": 2599,
+    "A": "AI 裁切 视频成品 工具",
+    "B": "智能裁切视频成品的工具",
+    "C": "AI 截取 视频 方法"
+  },
+  "2600": {
+    "idx": 2600,
+    "A": "软件 裁切 视频成品 工具",
+    "B": "裁切视频成品的软件工具",
+    "C": "软件 裁剪 成片 怎么做"
+  },
+  "2601": {
+    "idx": 2601,
+    "A": "在线 裁切 视频成品 工具",
+    "B": "在线裁切视频成品的工具",
+    "C": "在线 裁剪 视频 方法"
+  },
+  "2602": {
+    "idx": 2602,
+    "A": "代码 裁切 视频成品 工具",
+    "B": "通过代码裁切视频成品的工具",
+    "C": "代码 裁剪 视频 教程"
+  },
+  "2603": {
+    "idx": 2603,
+    "A": "插件 裁切 视频成品 工具",
+    "B": "裁切视频成品的插件工具",
+    "C": "插件 裁剪 视频成品 步骤"
+  },
+  "2604": {
+    "idx": 2604,
+    "A": "裁切 视频成品 技巧",
+    "B": "视频成品裁切的实用技巧",
+    "C": "截取 视频 步骤"
+  },
+  "2605": {
+    "idx": 2605,
+    "A": "AI 裁切 视频成品 技巧",
+    "B": "智能裁切视频成品的技巧",
+    "C": "AI 切片 视频 教程"
+  },
+  "2606": {
+    "idx": 2606,
+    "A": "软件 裁切 视频成品 技巧",
+    "B": "使用软件裁切视频成品的技巧",
+    "C": "软件 怎么裁 成片 流程"
+  },
+  "2607": {
+    "idx": 2607,
+    "A": "在线 裁切 视频成品 技巧",
+    "B": "怎么在网页上裁剪视频",
+    "C": "在线 截取 成片 怎么做"
+  },
+  "2608": {
+    "idx": 2608,
+    "A": "代码 裁切 视频成品 技巧",
+    "B": "如何通过代码裁剪视频",
+    "C": "代码 截取 成片 步骤"
+  },
+  "2609": {
+    "idx": 2609,
+    "A": "插件 裁切 视频成品 技巧",
+    "B": "有什么插件可以裁剪视频",
+    "C": "插件 截取 视频成品 步骤"
+  },
+  "2610": {
+    "idx": 2610,
+    "A": "抠取 视频成品 教程",
+    "B": "视频抠图怎么做",
+    "C": "分割 视频 怎么做"
+  },
+  "2611": {
+    "idx": 2611,
+    "A": "AI 抠取 视频成品 教程",
+    "B": "如何利用智能技术抠取视频画面",
+    "C": "AI 抠 视频成品 方法"
+  },
+  "2612": {
+    "idx": 2612,
+    "A": "软件 抠取 视频成品 教程",
+    "B": "有哪些软件可以抠视频",
+    "C": "电脑端 抠 视频成品 怎么做"
+  },
+  "2613": {
+    "idx": 2613,
+    "A": "在线 抠取 视频成品 教程",
+    "B": "怎么在线抠视频",
+    "C": "网页版 怎么抠 成片 方法"
+  },
+  "2614": {
+    "idx": 2614,
+    "A": "代码 抠取 视频成品 教程",
+    "B": "如何用代码实现视频抠图",
+    "C": "命令行 抠图 成片 流程"
+  },
+  "2615": {
+    "idx": 2615,
+    "A": "插件 抠取 视频成品 教程",
+    "B": "有没有好用的视频抠图插件",
+    "C": "插件 抠图 视频成品 步骤"
+  },
+  "2616": {
+    "idx": 2616,
+    "A": "抠取 视频成品 工具",
+    "B": "视频抠图用什么工具好",
+    "C": "分割 成片 流程"
+  },
+  "2617": {
+    "idx": 2617,
+    "A": "AI 抠取 视频成品 工具",
+    "B": "有哪些智能视频抠图工具",
+    "C": "AI 抠图 成片 教程"
+  },
+  "2618": {
+    "idx": 2618,
+    "A": "软件 抠取 视频成品 工具",
+    "B": "好用的视频抠图软件推荐",
+    "C": "软件 抠图 视频 教学"
+  },
+  "2619": {
+    "idx": 2619,
+    "A": "在线 抠取 视频成品 工具",
+    "B": "在线抠视频的工具哪个好用",
+    "C": "网页版 怎么抠 成片 教学"
+  },
+  "2620": {
+    "idx": 2620,
+    "A": "代码 抠取 视频成品 工具",
+    "B": "有没有抠视频的代码工具",
+    "C": "命令行 分割 成片 教程"
+  },
+  "2621": {
+    "idx": 2621,
+    "A": "插件 抠取 视频成品 工具",
+    "B": "好用的视频抠图插件有哪些",
+    "C": "插件 抠 视频 怎么做"
+  },
+  "2622": {
+    "idx": 2622,
+    "A": "抠取 视频成品 技巧",
+    "B": "视频抠图有什么技巧",
+    "C": "怎么抠 视频 流程"
+  },
+  "2623": {
+    "idx": 2623,
+    "A": "AI 抠取 视频成品 技巧",
+    "B": "智能抠视频有什么技巧",
+    "C": "AI 分割 视频 怎么做"
+  },
+  "2624": {
+    "idx": 2624,
+    "A": "软件 抠取 视频成品 技巧",
+    "B": "用软件抠视频的技巧有哪些",
+    "C": "软件 分割 视频成品 教程"
+  },
+  "2625": {
+    "idx": 2625,
+    "A": "在线 抠取 视频成品 技巧",
+    "B": "在线抠视频的实用技巧",
+    "C": "网页版 怎么抠 视频 教学"
+  },
+  "2626": {
+    "idx": 2626,
+    "A": "代码 抠取 视频成品 技巧",
+    "B": "通过代码抠视频的技巧",
+    "C": "代码 分割 视频成品 教程"
+  },
+  "2627": {
+    "idx": 2627,
+    "A": "插件 抠取 视频成品 技巧",
+    "B": "抠视频插件的使用技巧",
+    "C": "插件 分割 视频 流程"
+  },
+  "2628": {
+    "idx": 2628,
+    "A": "识别 视频成品 教程",
+    "B": "怎么识别视频里的内容",
+    "C": "识别 视频成品 方法"
+  },
+  "2629": {
+    "idx": 2629,
+    "A": "AI 识别 视频成品 教程",
+    "B": "如何利用智能技术识别视频内容",
+    "C": "AI 检测 成片 教学"
+  },
+  "2630": {
+    "idx": 2630,
+    "A": "软件 识别 视频成品 教程",
+    "B": "有什么软件可以识别视频内容",
+    "C": "电脑端 转录 视频成品 教学"
+  },
+  "2631": {
+    "idx": 2631,
+    "A": "在线 识别 视频成品 教程",
+    "B": "怎么在线识别视频内容",
+    "C": "在线 OCR 成片 教学"
+  },
+  "2632": {
+    "idx": 2632,
+    "A": "代码 识别 视频成品 教程",
+    "B": "如何用代码识别视频内容",
+    "C": "命令行 识别 视频成品 教学"
+  },
+  "2633": {
+    "idx": 2633,
+    "A": "插件 识别 视频成品 教程",
+    "B": "有没有识别视频内容的插件",
+    "C": "插件 提取文字 成片 方法"
+  },
+  "2634": {
+    "idx": 2634,
+    "A": "识别 视频成品 工具",
+    "B": "视频内容识别工具推荐",
+    "C": "识别 成片 步骤"
+  },
+  "2635": {
+    "idx": 2635,
+    "A": "AI 识别 视频成品 工具",
+    "B": "智能视频内容识别工具有哪些",
+    "C": "AI 转录 视频 教学"
+  },
+  "2636": {
+    "idx": 2636,
+    "A": "软件 识别 视频成品 工具",
+    "B": "好用的视频识别软件",
+    "C": "软件 OCR 成片 步骤"
+  },
+  "2637": {
+    "idx": 2637,
+    "A": "在线 识别 视频成品 工具",
+    "B": "在线识别视频内容的工具",
+    "C": "在线 提取文字 视频 教学"
+  },
+  "2638": {
+    "idx": 2638,
+    "A": "代码 识别 视频成品 工具",
+    "B": "有没有识别视频的代码工具",
+    "C": "代码 识别 成片 方法"
+  },
+  "2639": {
+    "idx": 2639,
+    "A": "插件 识别 视频成品 工具",
+    "B": "好用的视频识别插件推荐",
+    "C": "插件 OCR 成片 教程"
+  },
+  "2640": {
+    "idx": 2640,
+    "A": "识别 视频成品 技巧",
+    "B": "识别视频内容有什么技巧",
+    "C": "检测 视频 怎么做"
+  },
+  "2641": {
+    "idx": 2641,
+    "A": "AI 识别 视频成品 技巧",
+    "B": "智能识别视频内容的技巧",
+    "C": "AI 识别 视频成品 教程"
+  },
+  "2642": {
+    "idx": 2642,
+    "A": "软件 识别 视频成品 技巧",
+    "B": "用软件识别视频内容的技巧",
+    "C": "电脑端 检测 成片 流程"
+  },
+  "2643": {
+    "idx": 2643,
+    "A": "在线 识别 视频成品 技巧",
+    "B": "在线识别视频内容的技巧",
+    "C": "网页版 识别 成片 教学"
+  },
+  "2644": {
+    "idx": 2644,
+    "A": "代码 识别 视频成品 技巧",
+    "B": "通过代码识别视频内容的技巧",
+    "C": "命令行 转录 视频 方法"
+  },
+  "2645": {
+    "idx": 2645,
+    "A": "插件 识别 视频成品 技巧",
+    "B": "视频识别插件的使用技巧",
+    "C": "插件 OCR 视频 怎么做"
+  },
+  "2646": {
+    "idx": 2646,
+    "A": "添加 视频成品 教程",
+    "B": "怎么给视频添加内容",
+    "C": "加上 成片 教学"
+  },
+  "2647": {
+    "idx": 2647,
+    "A": "AI 添加 视频成品 教程",
+    "B": "怎么给视频成品添加内容教程",
+    "C": "AI 加上 视频成品 流程"
+  },
+  "2648": {
+    "idx": 2648,
+    "A": "软件 添加 视频成品 教程",
+    "B": "有什么软件可以给视频成品添加内容",
+    "C": "软件 加上 视频 怎么做"
+  },
+  "2649": {
+    "idx": 2649,
+    "A": "在线 添加 视频成品 教程",
+    "B": "在线给视频成品添加内容的教程",
+    "C": "在线 添加 视频 流程"
+  },
+  "2650": {
+    "idx": 2650,
+    "A": "代码 添加 视频成品 教程",
+    "B": "通过代码给视频成品添加内容的教程",
+    "C": "命令行 加上 视频成品 教学"
+  },
+  "2651": {
+    "idx": 2651,
+    "A": "插件 添加 视频成品 教程",
+    "B": "有哪些插件可以给视频成品添加内容",
+    "C": "插件 怎么加 视频成品 方法"
+  },
+  "2652": {
+    "idx": 2652,
+    "A": "添加 视频成品 工具",
+    "B": "给视频成品添加内容的工具推荐",
+    "C": "加上 视频成品 教程"
+  },
+  "2653": {
+    "idx": 2653,
+    "A": "AI 添加 视频成品 工具",
+    "B": "智能给视频成品添加内容的工具",
+    "C": "AI 怎么加 视频成品 方法"
+  },
+  "2654": {
+    "idx": 2654,
+    "A": "软件 添加 视频成品 工具",
+    "B": "给视频成品添加内容的软件有哪些",
+    "C": "软件 添加 成片 步骤"
+  },
+  "2655": {
+    "idx": 2655,
+    "A": "在线 添加 视频成品 工具",
+    "B": "在线给视频成品添加内容的工具",
+    "C": "网页版 怎么加 成片 怎么做"
+  },
+  "2656": {
+    "idx": 2656,
+    "A": "代码 添加 视频成品 工具",
+    "B": "用代码给视频成品添加内容的工具",
+    "C": "代码 加 视频成品 方法"
+  },
+  "2657": {
+    "idx": 2657,
+    "A": "插件 添加 视频成品 工具",
+    "B": "给视频成品添加内容的插件有哪些",
+    "C": "插件 添加 成片 步骤"
+  },
+  "2658": {
+    "idx": 2658,
+    "A": "添加 视频成品 技巧",
+    "B": "给视频成品添加内容的实用技巧",
+    "C": "加 视频成品 教学"
+  },
+  "2659": {
+    "idx": 2659,
+    "A": "AI 添加 视频成品 技巧",
+    "B": "智能给视频成品添加内容的技巧",
+    "C": "AI 添加 视频成品 方法"
+  },
+  "2660": {
+    "idx": 2660,
+    "A": "软件 添加 视频成品 技巧",
+    "B": "使用软件给视频成品添加内容的技巧",
+    "C": "电脑端 添加 视频成品 怎么做"
+  },
+  "2661": {
+    "idx": 2661,
+    "A": "在线 添加 视频成品 技巧",
+    "B": "在线给视频成品添加内容的技巧",
+    "C": "网页版 怎么加 视频 怎么做"
+  },
+  "2662": {
+    "idx": 2662,
+    "A": "代码 添加 视频成品 技巧",
+    "B": "通过代码给视频成品添加内容的技巧",
+    "C": "命令行 加上 成片 教学"
+  },
+  "2663": {
+    "idx": 2663,
+    "A": "插件 添加 视频成品 技巧",
+    "B": "使用插件给视频成品添加内容的技巧",
+    "C": "插件 加 视频 教学"
+  },
+  "2664": {
+    "idx": 2664,
+    "A": "剪除 视频成品 教程",
+    "B": "怎么剪除视频成品里的内容教程",
+    "C": "截短 成片 教学"
+  },
+  "2665": {
+    "idx": 2665,
+    "A": "AI 剪除 视频成品 教程",
+    "B": "智能剪除视频成品内容的教程",
+    "C": "AI 删掉 视频 步骤"
+  },
+  "2666": {
+    "idx": 2666,
+    "A": "软件 剪除 视频成品 教程",
+    "B": "用什么软件剪除视频成品内容",
+    "C": "软件 截短 成片 流程"
+  },
+  "2667": {
+    "idx": 2667,
+    "A": "在线 剪除 视频成品 教程",
+    "B": "在线剪除视频成品内容的教程",
+    "C": "网页版 怎么剪 视频 教程"
+  },
+  "2668": {
+    "idx": 2668,
+    "A": "代码 剪除 视频成品 教程",
+    "B": "怎么用代码剪除视频成品内容",
+    "C": "命令行 怎么剪 视频 教程"
+  },
+  "2669": {
+    "idx": 2669,
+    "A": "插件 剪除 视频成品 教程",
+    "B": "有哪些插件可以剪除视频成品内容",
+    "C": "插件 剪掉 视频 教学"
+  },
+  "2670": {
+    "idx": 2670,
+    "A": "剪除 视频成品 工具",
+    "B": "剪除视频成品内容的工具推荐",
+    "C": "怎么剪 视频 教学"
+  },
+  "2671": {
+    "idx": 2671,
+    "A": "AI 剪除 视频成品 工具",
+    "B": "智能剪除视频成品内容的工具",
+    "C": "AI 剪掉 视频成品 方法"
+  },
+  "2672": {
+    "idx": 2672,
+    "A": "软件 剪除 视频成品 工具",
+    "B": "剪除视频成品内容的软件有哪些",
+    "C": "软件 删掉 成片 方法"
+  },
+  "2673": {
+    "idx": 2673,
+    "A": "在线 剪除 视频成品 工具",
+    "B": "在线剪除视频成品内容的工具",
+    "C": "在线 剪掉 视频 方法"
+  },
+  "2674": {
+    "idx": 2674,
+    "A": "代码 剪除 视频成品 工具",
+    "B": "用代码剪除视频成品内容的工具",
+    "C": "代码 剪掉 成片 流程"
+  },
+  "2675": {
+    "idx": 2675,
+    "A": "插件 剪除 视频成品 工具",
+    "B": "剪除视频成品内容的插件有哪些",
+    "C": "插件 截短 视频成品 方法"
+  },
+  "2676": {
+    "idx": 2676,
+    "A": "剪除 视频成品 技巧",
+    "B": "剪除视频成品内容的实用技巧",
+    "C": "怎么剪 成片 方法"
+  },
+  "2677": {
+    "idx": 2677,
+    "A": "AI 剪除 视频成品 技巧",
+    "B": "智能剪除视频成品内容的技巧",
+    "C": "AI 截短 视频成品 步骤"
+  },
+  "2678": {
+    "idx": 2678,
+    "A": "软件 剪除 视频成品 技巧",
+    "B": "使用软件剪除视频成品内容的技巧",
+    "C": "电脑端 删掉 成片 教程"
+  },
+  "2679": {
+    "idx": 2679,
+    "A": "在线 剪除 视频成品 技巧",
+    "B": "在线剪除视频成品内容的技巧",
+    "C": "网页版 截短 成片 教程"
+  },
+  "2680": {
+    "idx": 2680,
+    "A": "代码 剪除 视频成品 技巧",
+    "B": "通过代码剪除视频成品内容的技巧",
+    "C": "代码 剪掉 视频 流程"
+  },
+  "2681": {
+    "idx": 2681,
+    "A": "插件 剪除 视频成品 技巧",
+    "B": "使用插件剪除视频成品内容的技巧",
+    "C": "插件 删掉 视频成品 步骤"
+  },
+  "2682": {
+    "idx": 2682,
+    "A": "风格化 视频成品 教程",
+    "B": "怎么给视频成品做风格化处理教程",
+    "C": "风格化 视频成品 步骤"
+  },
+  "2683": {
+    "idx": 2683,
+    "A": "AI 风格化 视频成品 教程",
+    "B": "智能给视频成品做风格化处理的教程",
+    "C": "AI 转风格 视频成品 方法"
+  },
+  "2684": {
+    "idx": 2684,
+    "A": "软件 风格化 视频成品 教程",
+    "B": "有什么软件可以给视频成品做风格化",
+    "C": "电脑端 转风格 视频成品 教学"
+  },
+  "2685": {
+    "idx": 2685,
+    "A": "在线 风格化 视频成品 教程",
+    "B": "在线给视频成品做风格化处理的教程",
+    "C": "在线 风格迁移 成片 教程"
+  },
+  "2686": {
+    "idx": 2686,
+    "A": "代码 风格化 视频成品 教程",
+    "B": "怎么用代码给视频成品做风格化处理",
+    "C": "命令行 转风格 成片 步骤"
+  },
+  "2687": {
+    "idx": 2687,
+    "A": "插件 风格化 视频成品 教程",
+    "B": "如何使用插件制作风格化视频教程",
+    "C": "插件 怎么转风格 视频成品 教程"
+  },
+  "2688": {
+    "idx": 2688,
+    "A": "风格化 视频成品 工具",
+    "B": "有哪些好用的视频风格化处理工具",
+    "C": "转风格 视频成品 方法"
+  },
+  "2689": {
+    "idx": 2689,
+    "A": "AI 风格化 视频成品 工具",
+    "B": "智能视频风格化处理工具推荐",
+    "C": "AI 怎么转风格 视频 方法"
+  },
+  "2690": {
+    "idx": 2690,
+    "A": "软件 风格化 视频成品 工具",
+    "B": "视频风格化处理软件有哪些",
+    "C": "电脑端 风格化 成片 教程"
+  },
+  "2691": {
+    "idx": 2691,
+    "A": "在线 风格化 视频成品 工具",
+    "B": "在线视频风格化处理平台推荐",
+    "C": "网页版 怎么转风格 视频 怎么做"
+  },
+  "2692": {
+    "idx": 2692,
+    "A": "代码 风格化 视频成品 工具",
+    "B": "通过代码实现视频风格化的方法",
+    "C": "代码 怎么转风格 视频成品 怎么做"
+  },
+  "2693": {
+    "idx": 2693,
+    "A": "插件 风格化 视频成品 工具",
+    "B": "视频风格化插件有哪些推荐",
+    "C": "插件 风格化 成片 方法"
+  },
+  "2694": {
+    "idx": 2694,
+    "A": "风格化 视频成品 技巧",
+    "B": "视频风格化处理的制作技巧",
+    "C": "风格化 视频成品 方法"
+  },
+  "2695": {
+    "idx": 2695,
+    "A": "AI 风格化 视频成品 技巧",
+    "B": "智能视频风格化处理技巧分享",
+    "C": "AI 风格迁移 视频 怎么做"
+  },
+  "2696": {
+    "idx": 2696,
+    "A": "软件 风格化 视频成品 技巧",
+    "B": "视频风格化软件的使用技巧",
+    "C": "电脑端 风格化 视频 方法"
+  },
+  "2697": {
+    "idx": 2697,
+    "A": "在线 风格化 视频成品 技巧",
+    "B": "在线视频风格化处理技巧",
+    "C": "在线 转风格 成片 方法"
+  },
+  "2698": {
+    "idx": 2698,
+    "A": "代码 风格化 视频成品 技巧",
+    "B": "编写代码处理视频风格化的技巧",
+    "C": "代码 转风格 视频 怎么做"
+  },
+  "2699": {
+    "idx": 2699,
+    "A": "插件 风格化 视频成品 技巧",
+    "B": "使用视频风格化插件的技巧",
+    "C": "插件 风格化 视频成品 怎么做"
+  },
+  "2700": {
+    "idx": 2700,
+    "A": "转换 视频成品 教程",
+    "B": "视频格式转换教程",
+    "C": "怎么转 视频 流程"
+  },
+  "2701": {
+    "idx": 2701,
+    "A": "AI 转换 视频成品 教程",
+    "B": "智能视频转换处理教程",
+    "C": "AI 转换 成片 步骤"
+  },
+  "2702": {
+    "idx": 2702,
+    "A": "软件 转换 视频成品 教程",
+    "B": "视频转换软件操作教程",
+    "C": "电脑端 转格式 成片 教学"
+  },
+  "2703": {
+    "idx": 2703,
+    "A": "在线 转换 视频成品 教程",
+    "B": "在线视频转换处理方法",
+    "C": "在线 怎么转 视频成品 流程"
+  },
+  "2704": {
+    "idx": 2704,
+    "A": "代码 转换 视频成品 教程",
+    "B": "通过代码进行视频转换的教程",
+    "C": "代码 怎么转 视频成品 怎么做"
+  },
+  "2705": {
+    "idx": 2705,
+    "A": "插件 转换 视频成品 教程",
+    "B": "视频转换插件使用教程",
+    "C": "插件 转 视频 方法"
+  },
+  "2706": {
+    "idx": 2706,
+    "A": "转换 视频成品 工具",
+    "B": "好用的视频转换工具推荐",
+    "C": "怎么转 成片 流程"
+  },
+  "2707": {
+    "idx": 2707,
+    "A": "AI 转换 视频成品 工具",
+    "B": "智能视频转换工具推荐",
+    "C": "AI 怎么转 视频 步骤"
+  },
+  "2708": {
+    "idx": 2708,
+    "A": "软件 转换 视频成品 工具",
+    "B": "视频转换软件有哪些",
+    "C": "电脑端 怎么转 视频成品 教学"
+  },
+  "2709": {
+    "idx": 2709,
+    "A": "在线 转换 视频成品 工具",
+    "B": "在线视频转换工具推荐",
+    "C": "网页版 怎么转 视频成品 怎么做"
+  },
+  "2710": {
+    "idx": 2710,
+    "A": "代码 转换 视频成品 工具",
+    "B": "视频转换代码实现工具",
+    "C": "命令行 转换 视频 流程"
+  },
+  "2711": {
+    "idx": 2711,
+    "A": "插件 转换 视频成品 工具",
+    "B": "视频转换插件推荐",
+    "C": "插件 转格式 视频成品 教程"
+  },
+  "2712": {
+    "idx": 2712,
+    "A": "转换 视频成品 技巧",
+    "B": "视频转换处理技巧",
+    "C": "转 成片 方法"
+  },
+  "2713": {
+    "idx": 2713,
+    "A": "AI 转换 视频成品 技巧",
+    "B": "智能视频转换处理技巧",
+    "C": "AI 转格式 视频 教程"
+  },
+  "2714": {
+    "idx": 2714,
+    "A": "软件 转换 视频成品 技巧",
+    "B": "视频转换软件使用技巧",
+    "C": "软件 转换 视频 怎么做"
+  },
+  "2715": {
+    "idx": 2715,
+    "A": "在线 转换 视频成品 技巧",
+    "B": "在线视频转换操作技巧",
+    "C": "在线 怎么转 成片 方法"
+  },
+  "2716": {
+    "idx": 2716,
+    "A": "代码 转换 视频成品 技巧",
+    "B": "视频转换代码编写技巧",
+    "C": "命令行 转格式 视频成品 教学"
+  },
+  "2717": {
+    "idx": 2717,
+    "A": "插件 转换 视频成品 技巧",
+    "B": "视频转换插件使用技巧",
+    "C": "插件 转换 成片 步骤"
+  },
+  "2718": {
+    "idx": 2718,
+    "A": "增强 视频成品 教程",
+    "B": "视频画质增强教程",
+    "C": "提升画质 成片 教程"
+  },
+  "2719": {
+    "idx": 2719,
+    "A": "AI 增强 视频成品 教程",
+    "B": "智能视频画质增强教程",
+    "C": "AI 增强 成片 教学"
+  },
+  "2720": {
+    "idx": 2720,
+    "A": "软件 增强 视频成品 教程",
+    "B": "视频画质增强软件使用教程",
+    "C": "电脑端 提升画质 视频成品 方法"
+  },
+  "2721": {
+    "idx": 2721,
+    "A": "在线 增强 视频成品 教程",
+    "B": "在线视频画质增强方法",
+    "C": "网页版 提升画质 视频成品 怎么做"
+  },
+  "2722": {
+    "idx": 2722,
+    "A": "代码 增强 视频成品 教程",
+    "B": "通过代码实现视频画质增强的教程",
+    "C": "命令行 增强 成片 怎么做"
+  },
+  "2723": {
+    "idx": 2723,
+    "A": "插件 增强 视频成品 教程",
+    "B": "视频画质增强插件使用教程",
+    "C": "插件 增强 视频成品 教学"
+  },
+  "2724": {
+    "idx": 2724,
+    "A": "增强 视频成品 工具",
+    "B": "好用的视频画质增强工具",
+    "C": "修复 视频成品 步骤"
+  },
+  "2725": {
+    "idx": 2725,
+    "A": "AI 增强 视频成品 工具",
+    "B": "智能视频画质增强工具推荐",
+    "C": "AI 提升画质 视频 流程"
+  },
+  "2726": {
+    "idx": 2726,
+    "A": "软件 增强 视频成品 工具",
+    "B": "视频画质增强软件推荐",
+    "C": "软件 增强 视频 流程"
+  },
+  "2727": {
+    "idx": 2727,
+    "A": "在线 增强 视频成品 工具",
+    "B": "有什么在线工具可以增强视频效果",
+    "C": "在线 提升画质 成片 方法"
+  },
+  "2728": {
+    "idx": 2728,
+    "A": "代码 增强 视频成品 工具",
+    "B": "怎么用代码来增强视频画质",
+    "C": "代码 超分 视频 步骤"
+  },
+  "2729": {
+    "idx": 2729,
+    "A": "插件 增强 视频成品 工具",
+    "B": "有哪些插件可以用来增强视频效果",
+    "C": "插件 增强 视频 教学"
+  },
+  "2730": {
+    "idx": 2730,
+    "A": "增强 视频成品 技巧",
+    "B": "增强视频画质有哪些实用技巧",
+    "C": "超分 视频 步骤"
+  },
+  "2731": {
+    "idx": 2731,
+    "A": "AI 增强 视频成品 技巧",
+    "B": "如何利用智能技术提升视频质量",
+    "C": "AI 增强 成片 教学"
+  },
+  "2732": {
+    "idx": 2732,
+    "A": "软件 增强 视频成品 技巧",
+    "B": "用软件增强视频效果的方法",
+    "C": "软件 怎么增强 成片 怎么做"
+  },
+  "2733": {
+    "idx": 2733,
+    "A": "在线 增强 视频成品 技巧",
+    "B": "在线提升视频画质的技巧有哪些",
+    "C": "网页版 增强 视频 方法"
+  },
+  "2734": {
+    "idx": 2734,
+    "A": "代码 增强 视频成品 技巧",
+    "B": "通过代码优化视频效果的技巧",
+    "C": "命令行 修复 成片 方法"
+  },
+  "2735": {
+    "idx": 2735,
+    "A": "插件 增强 视频成品 技巧",
+    "B": "使用插件增强视频画质的技巧",
+    "C": "插件 提升画质 视频成品 步骤"
+  },
+  "2736": {
+    "idx": 2736,
+    "A": "抠取 合成图 教程",
+    "B": "抠图合成图片的详细教程",
+    "C": "怎么抠 合成 步骤"
+  },
+  "2737": {
+    "idx": 2737,
+    "A": "AI 抠取 合成图 教程",
+    "B": "如何用智能工具进行抠图合成",
+    "C": "AI 怎么抠 拼合图 步骤"
+  },
+  "2738": {
+    "idx": 2738,
+    "A": "软件 抠取 合成图 教程",
+    "B": "抠图合成图片的软件操作教程",
+    "C": "软件 抠图 拼合图 教学"
+  },
+  "2739": {
+    "idx": 2739,
+    "A": "在线 抠取 合成图 教程",
+    "B": "在线抠图合成图片的方法教程",
+    "C": "网页版 抠图 拼合图 流程"
+  },
+  "2740": {
+    "idx": 2740,
+    "A": "代码 抠取 合成图 教程",
+    "B": "如何用代码实现抠图合成效果",
+    "C": "代码 分割 融合图 教程"
+  },
+  "2741": {
+    "idx": 2741,
+    "A": "插件 抠取 合成图 教程",
+    "B": "使用插件进行抠图合成的教程",
+    "C": "插件 抠图 合成 怎么做"
+  },
+  "2742": {
+    "idx": 2742,
+    "A": "抠取 合成图 工具",
+    "B": "有哪些好用的抠图合成工具",
+    "C": "抠图 融合图 步骤"
+  },
+  "2743": {
+    "idx": 2743,
+    "A": "AI 抠取 合成图 工具",
+    "B": "推荐几款智能抠图合成工具",
+    "C": "AI 抠图 合成 流程"
+  },
+  "2744": {
+    "idx": 2744,
+    "A": "软件 抠取 合成图 工具",
+    "B": "抠图合成图片用什么软件好",
+    "C": "电脑端 抠图 融合图 方法"
+  },
+  "2745": {
+    "idx": 2745,
+    "A": "在线 抠取 合成图 工具",
+    "B": "在线抠图合成图片的工具推荐",
+    "C": "在线 抠图 合成 教程"
+  },
+  "2746": {
+    "idx": 2746,
+    "A": "代码 抠取 合成图 工具",
+    "B": "有没有能抠图合成的代码工具",
+    "C": "命令行 抠图 合成图 教程"
+  },
+  "2747": {
+    "idx": 2747,
+    "A": "插件 抠取 合成图 工具",
+    "B": "好用的抠图合成插件有哪些",
+    "C": "插件 怎么抠 融合图 教学"
+  },
+  "2748": {
+    "idx": 2748,
+    "A": "抠取 合成图 技巧",
+    "B": "抠图合成图片的进阶技巧",
+    "C": "抠图 拼合图 教程"
+  },
+  "2749": {
+    "idx": 2749,
+    "A": "AI 抠取 合成图 技巧",
+    "B": "智能抠图合成的技巧分享",
+    "C": "AI 抠图 融合图 方法"
+  },
+  "2750": {
+    "idx": 2750,
+    "A": "软件 抠取 合成图 技巧",
+    "B": "软件抠图合成的实用技巧",
+    "C": "电脑端 抠图 合成图 教学"
+  },
+  "2751": {
+    "idx": 2751,
+    "A": "在线 抠取 合成图 技巧",
+    "B": "在线抠图合成的技巧有哪些",
+    "C": "在线 抠图 融合图 怎么做"
+  },
+  "2752": {
+    "idx": 2752,
+    "A": "代码 抠取 合成图 技巧",
+    "B": "用代码进行抠图合成的技巧",
+    "C": "命令行 抠图 合成 流程"
+  },
+  "2753": {
+    "idx": 2753,
+    "A": "插件 抠取 合成图 技巧",
+    "B": "使用插件抠图合成的技巧",
+    "C": "插件 怎么抠 合成 怎么做"
+  },
+  "2754": {
+    "idx": 2754,
+    "A": "结构生成 合成图 教程",
+    "B": "如何通过结构生成制作合成图",
+    "C": "构建 合成图 步骤"
+  },
+  "2755": {
+    "idx": 2755,
+    "A": "AI 结构生成 合成图 教程",
+    "B": "利用智能技术生成结构合成图的教程",
+    "C": "AI 构建 融合图 方法"
+  },
+  "2756": {
+    "idx": 2756,
+    "A": "软件 结构生成 合成图 教程",
+    "B": "用软件制作结构合成图的教程",
+    "C": "软件 生成 合成图 教程"
+  },
+  "2757": {
+    "idx": 2757,
+    "A": "在线 结构生成 合成图 教程",
+    "B": "在线制作结构合成图的方法",
+    "C": "在线 搭建 拼合图 教学"
+  },
+  "2758": {
+    "idx": 2758,
+    "A": "代码 结构生成 合成图 教程",
+    "B": "如何用代码生成结构合成图",
+    "C": "命令行 怎么生成 合成 怎么做"
+  },
+  "2759": {
+    "idx": 2759,
+    "A": "插件 结构生成 合成图 教程",
+    "B": "使用插件制作结构合成图的教程",
+    "C": "插件 搭建 拼合图 流程"
+  },
+  "2760": {
+    "idx": 2760,
+    "A": "结构生成 合成图 工具",
+    "B": "有哪些结构生成合成图的工具",
+    "C": "生成 合成图 流程"
+  },
+  "2761": {
+    "idx": 2761,
+    "A": "AI 结构生成 合成图 工具",
+    "B": "智能结构生成合成图的工具推荐",
+    "C": "AI 构建 融合图 步骤"
+  },
+  "2762": {
+    "idx": 2762,
+    "A": "软件 结构生成 合成图 工具",
+    "B": "制作结构合成图的软件有哪些",
+    "C": "软件 搭建 合成 步骤"
+  },
+  "2763": {
+    "idx": 2763,
+    "A": "在线 结构生成 合成图 工具",
+    "B": "在线生成结构合成图的工具",
+    "C": "网页版 怎么生成 融合图 教程"
+  },
+  "2764": {
+    "idx": 2764,
+    "A": "代码 结构生成 合成图 工具",
+    "B": "有没有生成结构合成图的代码工具",
+    "C": "代码 生成 拼合图 方法"
+  },
+  "2765": {
+    "idx": 2765,
+    "A": "插件 结构生成 合成图 工具",
+    "B": "好用的结构生成合成图插件",
+    "C": "插件 构建 融合图 流程"
+  },
+  "2766": {
+    "idx": 2766,
+    "A": "结构生成 合成图 技巧",
+    "B": "结构生成合成图的制作技巧",
+    "C": "搭建 拼合图 教程"
+  },
+  "2767": {
+    "idx": 2767,
+    "A": "AI 结构生成 合成图 技巧",
+    "B": "如何通过智能技术生成结构合成图",
+    "C": "AI 搭建 合成 教学"
+  },
+  "2768": {
+    "idx": 2768,
+    "A": "软件 结构生成 合成图 技巧",
+    "B": "有哪些制作结构合成图的软件技巧",
+    "C": "电脑端 怎么生成 融合图 方法"
+  },
+  "2769": {
+    "idx": 2769,
+    "A": "在线 结构生成 合成图 技巧",
+    "B": "在线生成结构合成图的方法有哪些",
+    "C": "网页版 构建 融合图 流程"
+  },
+  "2770": {
+    "idx": 2770,
+    "A": "代码 结构生成 合成图 技巧",
+    "B": "如何用代码实现结构合成图的生成",
+    "C": "代码 构建 合成图 怎么做"
+  },
+  "2771": {
+    "idx": 2771,
+    "A": "插件 结构生成 合成图 技巧",
+    "B": "制作结构合成图有哪些好用的插件技巧",
+    "C": "插件 生成 拼合图 教学"
+  },
+  "2772": {
+    "idx": 2772,
+    "A": "叠加 合成图 教程",
+    "B": "图片叠加合成的详细教程",
+    "C": "合成 合成 方法"
+  },
+  "2773": {
+    "idx": 2773,
+    "A": "AI 叠加 合成图 教程",
+    "B": "如何利用智能技术进行图片叠加合成",
+    "C": "AI 合成 合成 教学"
+  },
+  "2774": {
+    "idx": 2774,
+    "A": "软件 叠加 合成图 教程",
+    "B": "图片叠加合成的软件操作教程",
+    "C": "电脑端 加 拼合图 怎么做"
+  },
+  "2775": {
+    "idx": 2775,
+    "A": "在线 叠加 合成图 教程",
+    "B": "在线进行图片叠加合成的教程",
+    "C": "在线 叠加 融合图 教程"
+  },
+  "2776": {
+    "idx": 2776,
+    "A": "代码 叠加 合成图 教程",
+    "B": "如何通过编程实现图片叠加合成",
+    "C": "代码 叠 合成图 方法"
+  },
+  "2777": {
+    "idx": 2777,
+    "A": "插件 叠加 合成图 教程",
+    "B": "图片叠加合成的插件使用教程",
+    "C": "插件 合成 融合图 怎么做"
+  },
+  "2778": {
+    "idx": 2778,
+    "A": "叠加 合成图 工具",
+    "B": "有什么好用的图片叠加合成工具",
+    "C": "合成 融合图 教程"
+  },
+  "2779": {
+    "idx": 2779,
+    "A": "AI 叠加 合成图 工具",
+    "B": "有哪些智能图片叠加合成工具推荐",
+    "C": "AI 合成 拼合图 步骤"
+  },
+  "2780": {
+    "idx": 2780,
+    "A": "软件 叠加 合成图 工具",
+    "B": "好用的图片叠加合成软件有哪些",
+    "C": "软件 合成 融合图 教学"
+  },
+  "2781": {
+    "idx": 2781,
+    "A": "在线 叠加 合成图 工具",
+    "B": "在线图片叠加合成工具有哪些",
+    "C": "在线 叠 拼合图 流程"
+  },
+  "2782": {
+    "idx": 2782,
+    "A": "代码 叠加 合成图 工具",
+    "B": "适合图片叠加合成的代码工具有哪些",
+    "C": "代码 叠加 拼合图 步骤"
+  },
+  "2783": {
+    "idx": 2783,
+    "A": "插件 叠加 合成图 工具",
+    "B": "有哪些实用的图片叠加合成插件",
+    "C": "插件 叠加 拼合图 怎么做"
+  },
+  "2784": {
+    "idx": 2784,
+    "A": "叠加 合成图 技巧",
+    "B": "图片叠加合成的进阶技巧",
+    "C": "叠加 融合图 流程"
+  },
+  "2785": {
+    "idx": 2785,
+    "A": "AI 叠加 合成图 技巧",
+    "B": "智能图片叠加合成的实用技巧",
+    "C": "AI 加 拼合图 步骤"
+  },
+  "2786": {
+    "idx": 2786,
+    "A": "软件 叠加 合成图 技巧",
+    "B": "图片叠加合成软件的操作技巧",
+    "C": "电脑端 合成 合成 教学"
+  },
+  "2787": {
+    "idx": 2787,
+    "A": "在线 叠加 合成图 技巧",
+    "B": "在线处理图片叠加合成的技巧",
+    "C": "在线 叠加 拼合图 流程"
+  },
+  "2788": {
+    "idx": 2788,
+    "A": "代码 叠加 合成图 技巧",
+    "B": "图片叠加合成的代码编写技巧",
+    "C": "代码 合成 合成 教学"
+  },
+  "2789": {
+    "idx": 2789,
+    "A": "插件 叠加 合成图 技巧",
+    "B": "图片叠加合成插件的使用技巧",
+    "C": "插件 叠 合成 教学"
+  },
+  "2790": {
+    "idx": 2790,
+    "A": "检索 知识库 教程",
+    "B": "如何搭建并检索知识库的教程",
+    "C": "搜 知识库 方法"
+  },
+  "2791": {
+    "idx": 2791,
+    "A": "AI 检索 知识库 教程",
+    "B": "如何利用智能技术检索知识库",
+    "C": "AI 搜索 资料库 流程"
+  },
+  "2792": {
+    "idx": 2792,
+    "A": "软件 检索 知识库 教程",
+    "B": "知识库检索软件的使用教程",
+    "C": "电脑端 搜 知识库 教学"
+  },
+  "2793": {
+    "idx": 2793,
+    "A": "在线 检索 知识库 教程",
+    "B": "在线检索知识库的操作教程",
+    "C": "网页版 搜 knowledge base 方法"
+  },
+  "2794": {
+    "idx": 2794,
+    "A": "代码 检索 知识库 教程",
+    "B": "如何用代码实现知识库检索功能",
+    "C": "命令行 搜 knowledge base 教程"
+  },
+  "2795": {
+    "idx": 2795,
+    "A": "插件 检索 知识库 教程",
+    "B": "知识库检索插件的使用教程",
+    "C": "插件 搜索 知识库 流程"
+  },
+  "2796": {
+    "idx": 2796,
+    "A": "检索 知识库 工具",
+    "B": "有哪些好用的知识库检索工具",
+    "C": "搜索 资料库 教学"
+  },
+  "2797": {
+    "idx": 2797,
+    "A": "AI 检索 知识库 工具",
+    "B": "智能知识库检索工具有哪些",
+    "C": "AI 在哪找 knowledge base 怎么做"
+  },
+  "2798": {
+    "idx": 2798,
+    "A": "软件 检索 知识库 工具",
+    "B": "好用的知识库检索软件推荐",
+    "C": "软件 哪里找 knowledge base 步骤"
+  },
+  "2799": {
+    "idx": 2799,
+    "A": "在线 检索 知识库 工具",
+    "B": "在线知识库检索工具有哪些",
+    "C": "网页版 在哪找 资料库 步骤"
+  },
+  "2800": {
+    "idx": 2800,
+    "A": "代码 检索 知识库 工具",
+    "B": "有哪些适合知识库检索的代码工具",
+    "C": "命令行 搜索 knowledge base 教程"
+  },
+  "2801": {
+    "idx": 2801,
+    "A": "插件 检索 知识库 工具",
+    "B": "好用的知识库检索插件推荐",
+    "C": "插件 搜 知识库 怎么做"
+  },
+  "2802": {
+    "idx": 2802,
+    "A": "检索 知识库 技巧",
+    "B": "提高知识库检索效率的技巧",
+    "C": "搜 资料库 流程"
+  },
+  "2803": {
+    "idx": 2803,
+    "A": "AI 检索 知识库 技巧",
+    "B": "智能知识库检索的实用技巧",
+    "C": "AI 在哪找 资料库 方法"
+  },
+  "2804": {
+    "idx": 2804,
+    "A": "软件 检索 知识库 技巧",
+    "B": "知识库检索软件的操作技巧",
+    "C": "软件 哪里找 资料库 方法"
+  },
+  "2805": {
+    "idx": 2805,
+    "A": "在线 检索 知识库 技巧",
+    "B": "在线检索知识库的技巧",
+    "C": "在线 搜 知识库 步骤"
+  },
+  "2806": {
+    "idx": 2806,
+    "A": "代码 检索 知识库 技巧",
+    "B": "知识库检索的代码实现技巧",
+    "C": "命令行 搜索 资料库 流程"
+  },
+  "2807": {
+    "idx": 2807,
+    "A": "插件 检索 知识库 技巧",
+    "B": "如何通过插件高效检索知识库",
+    "C": "插件 在哪找 knowledge base 方法"
   }
 }

Разница между файлами не показана из-за своего большого размера
+ 495 - 415
examples/process_pipeline/script/search_eval/runs_full/q0010/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 518 - 421
examples/process_pipeline/script/search_eval/runs_full/q0010/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 515 - 410
examples/process_pipeline/script/search_eval/runs_full/q0010/form_C.json


+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0033/form_A.json

@@ -0,0 +1,13 @@
+{
+  "form": "A",
+  "query": "在线 元素生成 提示词 技巧",
+  "original_q": "在线 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0033/form_B.json

@@ -0,0 +1,13 @@
+{
+  "form": "B",
+  "query": "怎么写出更好的元素生成提示词",
+  "original_q": "在线 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0033/form_C.json

@@ -0,0 +1,13 @@
+{
+  "form": "C",
+  "query": "在线 生成 咒语 步骤",
+  "original_q": "在线 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0034/form_A.json

@@ -0,0 +1,13 @@
+{
+  "form": "A",
+  "query": "代码 元素生成 提示词 技巧",
+  "original_q": "代码 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0034/form_B.json

@@ -0,0 +1,13 @@
+{
+  "form": "B",
+  "query": "写代码时如何优化元素生成提示词",
+  "original_q": "代码 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0034/form_C.json

@@ -0,0 +1,13 @@
+{
+  "form": "C",
+  "query": "代码 制作 提示词 教学",
+  "original_q": "代码 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0035/form_A.json

@@ -0,0 +1,13 @@
+{
+  "form": "A",
+  "query": "插件 元素生成 提示词 技巧",
+  "original_q": "插件 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0035/form_B.json

@@ -0,0 +1,13 @@
+{
+  "form": "B",
+  "query": "使用扩展功能时怎么写元素生成提示词",
+  "original_q": "插件 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

+ 13 - 0
examples/process_pipeline/script/search_eval/runs_full/q0035/form_C.json

@@ -0,0 +1,13 @@
+{
+  "form": "C",
+  "query": "插件 创作 提示词 方法",
+  "original_q": "插件 元素生成 提示词 技巧",
+  "platforms": [
+    "xhs",
+    "gzh",
+    "zhihu"
+  ],
+  "total": 0,
+  "failed": 0,
+  "results": []
+}

Разница между файлами не показана из-за своего большого размера
+ 307 - 0
examples/process_pipeline/script/search_eval/runs_full/q0038/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 307 - 0
examples/process_pipeline/script/search_eval/runs_full/q0038/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 229 - 0
examples/process_pipeline/script/search_eval/runs_full/q0038/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 225 - 0
examples/process_pipeline/script/search_eval/runs_full/q0039/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 80 - 0
examples/process_pipeline/script/search_eval/runs_full/q0039/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 21 - 0
examples/process_pipeline/script/search_eval/runs_full/q0039/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 330 - 0
examples/process_pipeline/script/search_eval/runs_full/q0040/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 79 - 0
examples/process_pipeline/script/search_eval/runs_full/q0040/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 338 - 0
examples/process_pipeline/script/search_eval/runs_full/q0040/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 311 - 0
examples/process_pipeline/script/search_eval/runs_full/q0041/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 128 - 0
examples/process_pipeline/script/search_eval/runs_full/q0041/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 105 - 0
examples/process_pipeline/script/search_eval/runs_full/q0041/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 47 - 0
examples/process_pipeline/script/search_eval/runs_full/q0043/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 73 - 0
examples/process_pipeline/script/search_eval/runs_full/q0043/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 312 - 0
examples/process_pipeline/script/search_eval/runs_full/q0043/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 193 - 0
examples/process_pipeline/script/search_eval/runs_full/q0044/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 337 - 0
examples/process_pipeline/script/search_eval/runs_full/q0044/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 313 - 0
examples/process_pipeline/script/search_eval/runs_full/q0044/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 221 - 0
examples/process_pipeline/script/search_eval/runs_full/q0045/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 296 - 0
examples/process_pipeline/script/search_eval/runs_full/q0045/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 21 - 0
examples/process_pipeline/script/search_eval/runs_full/q0045/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 154 - 0
examples/process_pipeline/script/search_eval/runs_full/q0046/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 315 - 0
examples/process_pipeline/script/search_eval/runs_full/q0046/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 48 - 0
examples/process_pipeline/script/search_eval/runs_full/q0046/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 185 - 0
examples/process_pipeline/script/search_eval/runs_full/q0047/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 107 - 0
examples/process_pipeline/script/search_eval/runs_full/q0047/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 317 - 0
examples/process_pipeline/script/search_eval/runs_full/q0047/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 157 - 0
examples/process_pipeline/script/search_eval/runs_full/q0049/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 21 - 0
examples/process_pipeline/script/search_eval/runs_full/q0049/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 319 - 0
examples/process_pipeline/script/search_eval/runs_full/q0049/form_C.json


Разница между файлами не показана из-за своего большого размера
+ 21 - 0
examples/process_pipeline/script/search_eval/runs_full/q0050/form_A.json


Разница между файлами не показана из-за своего большого размера
+ 242 - 0
examples/process_pipeline/script/search_eval/runs_full/q0050/form_B.json


Разница между файлами не показана из-за своего большого размера
+ 118 - 0
examples/process_pipeline/script/search_eval/runs_full/q0050/form_C.json


Некоторые файлы не были показаны из-за большого количества измененных файлов