|
|
@@ -32,6 +32,9 @@ GATE_ADMIT = load_prompt("gate_admit") # ①.5 创作判定闸:判"是
|
|
|
GATE_REFUTE = load_prompt("gate_refute") # ①.5:挑刺"是制作/越界"
|
|
|
GATE_TIEBREAK = load_prompt("gate_tiebreak") # ①.5:分歧裁决(边界倾向排除)
|
|
|
NORMALIZE = load_prompt("normalize_scope") # ③前:作用域值名词化(③LLM)
|
|
|
+GATE_HOW_ADMIT = load_prompt("gate_how_admit") # ②.5 有序性闸:判"真流水线"
|
|
|
+GATE_HOW_REFUTE = load_prompt("gate_how_refute") # ②.5:挑"假how(离散构成硬串)"
|
|
|
+GATE_HOW_TIEBREAK = load_prompt("gate_how_tiebreak") # ②.5:分歧裁决(边界倾向假how)
|
|
|
|
|
|
# ① 窄表确定性兜底:只放无歧义裸动作动词(绝不放 营造/引导/表达 等名词语素)
|
|
|
_STRIP_VERBS = ("寻找", "定位", "推导", "核验", "提取", "挖掘", "捕捉",
|
|
|
@@ -142,6 +145,83 @@ def creation_gate(read: str) -> tuple[bool, str]:
|
|
|
return v_tie, f"admit={v_admit}/refute={v_refute} 分歧→裁决={v_tie}"
|
|
|
|
|
|
|
|
|
+# ---------- ②.5 假how根治:有序性审查(层2信号+层3对抗投票)+ 假how重拆为 what/why ----------
|
|
|
+def _chain_signals(steps: list[dict]) -> list[str]:
|
|
|
+ """层2 确定性信号:并列输入(input 不指向前步产出)/ 产出近义。喂给层3当证据。"""
|
|
|
+ sigs, outs = [], [(s.get("output") or "") for s in steps]
|
|
|
+ indep = 0
|
|
|
+ for i, s in enumerate(steps):
|
|
|
+ if i == 0:
|
|
|
+ continue
|
|
|
+ inp = s.get("input") or ""
|
|
|
+ if not (("←" in inp) or any(o and o[:4] in inp for o in outs[:i])):
|
|
|
+ indep += 1
|
|
|
+ if indep >= 2:
|
|
|
+ sigs.append(f"{indep} 个后步的 input 未指向前步产出(各自起头)")
|
|
|
+ for i in range(len(outs)):
|
|
|
+ for j in range(i + 1, len(outs)):
|
|
|
+ a, b = outs[i], outs[j]
|
|
|
+ if a and b and (a in b or b in a):
|
|
|
+ sigs.append(f"步骤{i+1}与{j+1}产出近义({a} / {b})")
|
|
|
+ break
|
|
|
+ return sigs
|
|
|
+
|
|
|
+
|
|
|
+def how_gate(k: dict) -> tuple[bool, str]:
|
|
|
+ """层3a 有序性闸(对抗投票:admit 判真链 / refute 挑假链 / 分歧裁决,边界倾向假how)。"""
|
|
|
+ payload = json.dumps({
|
|
|
+ "purpose": k.get("purpose"),
|
|
|
+ "steps": [{"input": s.get("input"), "方法": (s.get("directive") or "")[:300], "产出": s.get("output")}
|
|
|
+ for s in k.get("steps", [])],
|
|
|
+ "代码信号": _chain_signals(k.get("steps", [])),
|
|
|
+ }, ensure_ascii=False)
|
|
|
+ v_admit = _vote(GATE_HOW_ADMIT, payload, "is_real_how", on_fail=True)
|
|
|
+ v_refute = not _vote(GATE_HOW_REFUTE, payload, "is_fake", on_fail=False) # 不假 → 真
|
|
|
+ if v_admit == v_refute:
|
|
|
+ return v_admit, f"admit={v_admit}/refute={v_refute} 一致"
|
|
|
+ v_tie = _vote(GATE_HOW_TIEBREAK, payload, "is_real_how", on_fail=False)
|
|
|
+ return v_tie, f"admit={v_admit}/refute={v_refute} 分歧→裁决={v_tie}"
|
|
|
+
|
|
|
+
|
|
|
+def reshape_nonhow(k: dict) -> list[dict]:
|
|
|
+ """层3b 假how重拆:只拆成 What/Why 主颗(不要 how/组件)。失败则保留原颗,不丢内容。"""
|
|
|
+ body = f"目标:{k.get('purpose','')}\n" + "\n".join(
|
|
|
+ f"- 输入:{s.get('input','')}|方法:{s.get('directive','')}|产出:{s.get('output','')}"
|
|
|
+ for s in k.get("steps", []))
|
|
|
+ user = ("【下面这块原被误判为 how 工序,实为「离散构成 / 原理」,请只拆成 What/Why 主颗——"
|
|
|
+ "每个'是什么/分几类'的构成块拆一颗 What,背后的原理/标准拆一颗 Why;"
|
|
|
+ "不要 how、不要组件颗,parent 一律 null。作用域字段留空 []。】\n\n"
|
|
|
+ f"原标题:{k.get('title','')}\n{body}\n\n"
|
|
|
+ "只输出 JSON:{\"knowledges\":[ ... 仅 what/why,见模板 ... ]}")
|
|
|
+ try:
|
|
|
+ out = chat_json(PHASE1, user, timeout=120).get("knowledges") or []
|
|
|
+ except Exception:
|
|
|
+ out = []
|
|
|
+ res = []
|
|
|
+ for i, nk in enumerate(out, 1):
|
|
|
+ if nk.get("type") == "how": # 保险:拒绝又冒出来的 how
|
|
|
+ continue
|
|
|
+ nk["id"] = f"{k.get('id','k')}r{i}"
|
|
|
+ nk["role"], nk["parent"] = "主", None
|
|
|
+ res.append(nk)
|
|
|
+ return res or [k] # 兜底:没拆出来就保留原颗
|
|
|
+
|
|
|
+
|
|
|
+def fix_fake_hows(knowledges: list[dict]) -> list[dict]:
|
|
|
+ """逐颗 how 审查;假how → 重拆为 what/why(替换原颗)。"""
|
|
|
+ out = []
|
|
|
+ for k in knowledges:
|
|
|
+ if k.get("type") == "how" and len(k.get("steps", [])) >= 2:
|
|
|
+ real, why = how_gate(k)
|
|
|
+ if not real:
|
|
|
+ new = reshape_nonhow(k)
|
|
|
+ print(f" ②.5 假how「{k.get('title')}」({why})→ 重拆 {len(new)} 颗")
|
|
|
+ out.extend(new)
|
|
|
+ continue
|
|
|
+ out.append(k)
|
|
|
+ return out
|
|
|
+
|
|
|
+
|
|
|
# ---------- ③ 作用域候选 + 定位 ----------
|
|
|
def _slim(knowledges: list[dict]) -> list[dict]:
|
|
|
slim = []
|
|
|
@@ -328,7 +408,7 @@ def main() -> None:
|
|
|
posts_out.append({**meta, "no_knowledge": True, "knowledges": []})
|
|
|
continue
|
|
|
print(f" ① 读懂 {len(read)} 字({media['type']})· ①.5 闸:创作({gate_why})")
|
|
|
- knowledges = shape(post, read)
|
|
|
+ knowledges = fix_fake_hows(shape(post, read)) # ② 拆颗 → ②.5 假how根治(假how重拆为 what/why)
|
|
|
how_ids = {k.get("id") for k in knowledges if k.get("type") == "how"}
|
|
|
how_titles = {k.get("id"): k.get("title") for k in knowledges if k.get("type") == "how"}
|
|
|
for k in knowledges:
|