Преглед на файлове

feat(query):创作Demo 实质/形式 改取 depth3-4 类目层(非叶子),对齐制作侧

之前误取叶子(元素层)→ 拼出"成语/句式辞格"等过细怪串。对照制作侧实质/形式树取的是
中间"类目"层(物品/动物/叙事技法/视觉风格),改 _nonleaf 取 depth 3-4 非叶子节点:
实质=社会观念/历史/军事谋略/政治…(80个)、形式=叙事技法/对比反差/认知引导…(48个)。
重生成后 query 更通顺、筛后保留率升至 14-19/20。目的池/阶段/知识类型不变。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SamLee преди 2 седмици
родител
ревизия
ec0bd0998b
променени са 1 файла, в които са добавени 25 реда и са изтрити 5 реда
  1. 25 5
      scripts/build_creation_demo.py

+ 25 - 5
scripts/build_creation_demo.py

@@ -32,7 +32,7 @@ def _segs(p):
 
 
 def _leaves(idx, source_type, under=None):
-    """某树某支下的叶子节点名(没有更深子节点的)。under 限定分支(如 实质 限 理念、形式 限 架构)。"""
+    """某树某支下的叶子节点名(没有更深子节点的=元素层)。under 限定分支。"""
     paths = [(_segs(n["path"]), n.get("name")) for n in idx if n.get("source_type") == source_type]
     if under:
         paths = [(s, nm) for s, nm in paths if under in s]
@@ -50,6 +50,26 @@ def _leaves(idx, source_type, under=None):
     return out
 
 
+def _nonleaf(idx, source_type, depths=(3, 4), under=None):
+    """某树某支下、指定层级的【非叶子"类目"节点】(底下还有元素,不取元素本身)。
+    对齐制作侧取法:实质/形式 取 depth 3-4 的类目层,而非最深的元素层。"""
+    paths = [(_segs(n["path"]), n.get("name")) for n in idx if n.get("source_type") == source_type]
+    if under:
+        paths = [(s, nm) for s, nm in paths if under in s]
+    allp = {"/".join(s) for s, _ in paths}
+    out, seen = [], set()
+    for s, nm in paths:
+        if len(s) not in depths:
+            continue
+        full = "/".join(s)
+        is_nonleaf = any(o != full and o.startswith(full + "/") for o in allp)
+        name = nm or (s[-1] if s else "")
+        if is_nonleaf and name and name not in seen:
+            seen.add(name)
+            out.append(name)
+    return out
+
+
 def _filter(queries, settings):
     """把一批原串喂 query_filter.txt(LLM 只做 keep/排除)。返回 [{keep,reason}] 对齐顺序。"""
     user = json.dumps([{"idx": i, "query": q} for i, q in enumerate(queries)], ensure_ascii=False)
@@ -76,8 +96,8 @@ def main():
     settings = Settings.from_env()
     rng = random.Random(7)
     idx = json.loads(TREES.read_text("utf-8"))
-    SHI = _leaves(idx, "实质", under="理念")
-    XING = _leaves(idx, "形式", under="架构")
+    SHI = _nonleaf(idx, "实质", depths=(3, 4), under="理念")   # 类目层,非元素
+    XING = _nonleaf(idx, "形式", depths=(3, 4), under="架构")  # 类目层,非元素
     POOL = _leaves(idx, "作用") + _leaves(idx, "感受") + _leaves(idx, "意图")
     print(f"实质 {len(SHI)} / 形式 {len(XING)} / 目的池 {len(POOL)} / 阶段 {len(STAGES)}")
 
@@ -88,11 +108,11 @@ def main():
     families = [
         {"key": "f1", "name": "实质 × 形式", "axes": ["实质", "形式", "知识类型"],
          "gen": lambda: {"parts": {"实质": pick(SHI), "形式": pick(XING), "知识类型": pick(KTYPE)}}},
-        {"key": "f2", "name": "实质 × 目的池", "axes": ["实质", "作用/感受/意图", "知识类型"],
+        {"key": "f2", "name": "实质 × (作用/感受/意图)", "axes": ["实质", "作用/感受/意图", "知识类型"],
          "gen": lambda: {"parts": {"实质": pick(SHI), "目的": pick(POOL), "知识类型": pick(KTYPE)}}},
         {"key": "f3", "name": "纯形式", "axes": ["形式", "知识类型"],
          "gen": lambda: {"parts": {"形式": pick(XING), "知识类型": pick(KTYPE)}}},
-        {"key": "f4", "name": "形式 × 目的池", "axes": ["形式", "作用/感受/意图", "知识类型"],
+        {"key": "f4", "name": "形式 × (作用/感受/意图)", "axes": ["形式", "作用/感受/意图", "知识类型"],
          "gen": lambda: {"parts": {"形式": pick(XING), "目的": pick(POOL), "知识类型": pick(KTYPE)}}},
         {"key": "f5", "name": "创作阶段 × 实质", "axes": ["实质", "创作阶段", "知识类型"],
          "gen": lambda: {"parts": {"实质": pick(SHI), "创作阶段": pick(STAGES), "知识类型": pick(KTYPE)}}},