doc_parser_skill: - New: verify_flowchart.py (flowchart validation) - Updated: LLM.py (multi-provider: DeepSeek + DashScope) - Updated: image_parser.py (logic tree support, external prompts) - Updated: SKILL.md, prompts/image_prompt.md conflict_detection_skill: - Updated: LLM.py (multi-provider sync) - Updated: detect_conflicts.py (logic tree text conversion) ir_generation_skill: - Replaced old scripts/LLM.py + ir_generator.py with standalone project - New: main.py, config.py, step1-3_*.py, ensemble_merge.py - New: prompts/, tests/ subdirectories tests: - New: acceptance/ test suite with schema validation - Fixed: conftest no longer globally skips non-acceptance tests - Updated: test_sample.py for new ir_generation structure Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,77 @@ PROMPT_DETECT_CONFLICT = """你是一个文档一致性检查专家。以下内
|
||||
"""
|
||||
|
||||
|
||||
def _is_nested_tree(lt: dict) -> bool:
|
||||
"""Return True if logic_tree uses the nested children format."""
|
||||
return isinstance(lt.get("children"), list)
|
||||
|
||||
|
||||
def _logic_tree_to_text(lt: dict) -> str:
|
||||
"""Convert logic_tree JSON to readable text for conflict detection.
|
||||
|
||||
Supports both the new nested-tree format and the legacy flat-nodes format.
|
||||
"""
|
||||
if _is_nested_tree(lt):
|
||||
return _nested_tree_to_text(lt)
|
||||
return _flat_tree_to_text(lt)
|
||||
|
||||
|
||||
def _nested_tree_to_text(tree: dict) -> str:
|
||||
"""Convert a nested flowchart tree to readable text."""
|
||||
lines: list[str] = []
|
||||
|
||||
def _walk(node: dict, indent: int = 0):
|
||||
prefix = " " * indent
|
||||
nid = node.get("id", "")
|
||||
name = node.get("name", "")
|
||||
ntype = node.get("type", "")
|
||||
|
||||
type_label = {
|
||||
"start": "起始", "end": "结束", "process": "处理",
|
||||
"decision": "判断", "action": "动作",
|
||||
}.get(ntype, ntype)
|
||||
|
||||
lines.append(f"{prefix}[{type_label}] {nid}: {name}")
|
||||
|
||||
if ntype == "decision":
|
||||
for child in node.get("children", []):
|
||||
cond = child.get("condition", "")
|
||||
lines.append(f"{prefix} 分支 \"{cond}\":")
|
||||
_walk(child["node"], indent + 2)
|
||||
elif "children" in node:
|
||||
for child in node.get("children", []):
|
||||
_walk(child, indent + 1)
|
||||
|
||||
_walk(tree)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _flat_tree_to_text(lt: dict) -> str:
|
||||
"""Convert legacy flat-nodes logic_tree to readable text."""
|
||||
lines: list[str] = []
|
||||
root = lt.get("root", "")
|
||||
if root:
|
||||
lines.append(f"根节点: {root}")
|
||||
for node in lt.get("nodes", []):
|
||||
nid = node.get("id", "")
|
||||
ntype = node.get("type", "")
|
||||
if ntype == "decision":
|
||||
cond = node.get("condition", "")
|
||||
branches = node.get("branches", [])
|
||||
lines.append(f"判断节点 {nid}: 条件=\"{cond}\"")
|
||||
for b in branches:
|
||||
lines.append(f" - 分支 \"{b.get('value', '')}\" → {b.get('target', '')}")
|
||||
elif ntype == "action":
|
||||
lines.append(f"动作节点 {nid}: {node.get('description', '')}")
|
||||
elif ntype == "state":
|
||||
lines.append(f"状态节点 {nid}: {node.get('description', '')}")
|
||||
elif ntype == "start":
|
||||
lines.append(f"起始节点 {nid}: {node.get('description', '')}")
|
||||
elif ntype == "end":
|
||||
lines.append(f"结束节点 {nid}: {node.get('description', '')}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _build_text_for_section(sections: list[dict], section_name: str) -> str:
|
||||
"""Build a single text block for the given section name."""
|
||||
texts: list[str] = []
|
||||
@@ -184,8 +255,9 @@ def detect_conflicts(
|
||||
img_type = img.get("type", "other")
|
||||
rid = img.get("rid", "")
|
||||
description = img.get("description", "").strip()
|
||||
logic_tree = img.get("logic_tree_nested") or img.get("logic_tree")
|
||||
|
||||
if img_type not in DIAGRAM_TYPES or not description:
|
||||
if img_type not in DIAGRAM_TYPES or (not description and not logic_tree):
|
||||
logger.info("Skip conflict check: rid=%s type=%s", rid, img_type)
|
||||
continue
|
||||
|
||||
@@ -211,8 +283,17 @@ def detect_conflicts(
|
||||
logger.info(" [DRY RUN] would call LLM to detect conflicts")
|
||||
continue
|
||||
|
||||
# Enrich description with logic_tree if available
|
||||
combined_desc = description
|
||||
if logic_tree:
|
||||
lt_text = _logic_tree_to_text(logic_tree)
|
||||
if combined_desc:
|
||||
combined_desc = f"[结构化逻辑树]\n{lt_text}\n\n[文字描述]\n{combined_desc}"
|
||||
else:
|
||||
combined_desc = f"[结构化逻辑树]\n{lt_text}"
|
||||
|
||||
prompt = PROMPT_DETECT_CONFLICT.format(
|
||||
image_description=description,
|
||||
image_description=combined_desc,
|
||||
text_description=text_content,
|
||||
section_name=section_name,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user