"""Structure Intent Diagnostic (점수 통합 전 검수용). 4 TARGET MDX 의 structure_intent 추론 결과와, 각 MDX × 32 frame 의 intent_compat 점수를 순수 매트릭스로 출력. 점수 통합 전에 "사람이 보기에 자연스러운가" 확인용. 출력: INTENT_DIAGNOSTIC_REPORT.md """ import sys from pathlib import Path import yaml sys.path.insert(0, str(Path(__file__).parent)) from template_fit import ( load_templates_v1, collect_anchor_vocab, intent_compat, ) from detect_mdx import detect_mdx_analysis from phase_common import TARGET_UNITS, load_target_units, load_frame_index HERE = Path(__file__).parent def main(): templates = load_templates_v1() tpl_by_sid = {t['short_id']: (fid, t) for fid, t in templates.items()} vocab = collect_anchor_vocab(templates) idx_data, frame_to_short = load_frame_index() units_full, units_title = load_target_units() TARGET_MAP = { 'MDX01-2-details': ('MDX01-2', '18', 'BIM vs DX 다면 비교'), 'MDX02-2.2-table': ('MDX02', '14', '주체별 기대효과'), 'MDX03-1': ('MDX03-1', '13', 'DX 필수요건 3요소'), 'MDX03-2': ('MDX03-2', '29', '과정/결과 혁신'), } lines = [] lines.append("# Structure Intent Diagnostic — 점수 통합 전 검수") lines.append("") lines.append("**목적**: `structure_intent` 추론이 사람 직관과 맞는지 확인. " "맞으면 Phase 24/25 점수에 통합 진입.") lines.append("") lines.append("**범위**: 11 문제 frame 에만 intent 태깅. 나머지 21 frames 은 `neutral 0.5` 처리.") lines.append("") lines.append("대상 11 frames: 13, 14, 17, 18, 20, 23, 24, 28, 29, 30, 31") lines.append("") # Intent 계층 — 모든 intent 목록 all_intents = set() for fid, tpl in templates.items(): intents = tpl.get('visual_pattern', {}).get('structure_intent', []) all_intents.update(intents) lines.append(f"**정의된 intent 종류** ({len(all_intents)}): {', '.join(sorted(all_intents))}") lines.append("") # 각 MDX 에 대해 진단 for uid, display, correct_sid, *_ in TARGET_UNITS: mdx_label, correct_sid_expected, short_desc = TARGET_MAP[uid] text = units_full[uid] title = units_title[uid] analysis = detect_mdx_analysis(text, title, anchor_vocab=vocab) mdx_intents = analysis.get('structure_intent', []) lines.append(f"## {mdx_label} — {short_desc}") lines.append("") lines.append(f"- **정답 Frame**: `{correct_sid_expected}`") lines.append(f"- **MDX detected_intents**: `{mdx_intents}`") lines.append(f"- **MDX item_count**: {analysis['item_count']['detected']}") lines.append(f"- **MDX relation_type**: {analysis['relation_type']['value']}") lines.append("") # 각 frame 과의 intent_compat — 정답 + 11개 태깅 frame 기준으로 정렬 scores = [] for fid, tpl in templates.items(): sid = tpl['short_id'] frame_intents = tpl.get('visual_pattern', {}).get('structure_intent', []) compat = intent_compat(mdx_intents, frame_intents) scores.append((sid, tpl['template_id'], frame_intents, compat)) # 정렬: compat DESC scores.sort(key=lambda x: -x[3]) lines.append(f"| 순위 | sid | template_id | frame_intents | compat | 비고 |") lines.append(f"|-----|-----|-------------|---------------|--------|------|") for rank, (sid, tid, intents, compat) in enumerate(scores[:12], 1): mark = ' 🎯 정답' if sid == correct_sid_expected else '' compat_fmt = f"**{compat:.2f}**" if compat >= 0.7 else f"{compat:.2f}" intents_str = ', '.join(intents) if intents else '_(미태깅, neutral)_' lines.append(f"| {rank} | {sid} | {tid[:30]} | {intents_str} | {compat_fmt} | {mark} |") lines.append("") # 하위 몇 개도 표시 lines.append("**하위 5개 (intent 불일치 확인용)**:") lines.append("") lines.append(f"| 순위 | sid | template_id | frame_intents | compat |") lines.append(f"|-----|-----|-------------|---------------|--------|") for rank, (sid, tid, intents, compat) in enumerate(scores[-5:], len(scores)-4): intents_str = ', '.join(intents) if intents else '_(미태깅)_' lines.append(f"| {rank} | {sid} | {tid[:30]} | {intents_str} | {compat:.2f} |") lines.append("") # 핵심 문제 후보에 대한 진단 problem_targets = { 'MDX01-2-details': ['29'], # process_product 'MDX02-2.2-table': ['21'], # solution_engn 'MDX03-1': ['28'], # sw_reality 'MDX03-2': ['18'], # bim_dx } if uid in problem_targets: lines.append("**🔎 문제 후보 진단**:") lines.append("") for tgt_sid in problem_targets[uid]: for sid, tid, intents, compat in scores: if sid == tgt_sid: intents_str = ', '.join(intents) if intents else '_(미태깅)_' verdict = '✓ 낮음 (정상)' if compat <= 0.4 else '⚠️ 높음 (문제)' lines.append(f"- Frame {sid} `{tid}`: intent=[{intents_str}], compat={compat:.2f} {verdict}") break lines.append("") lines.append("---") lines.append("") # 해석 가이드 lines.append("## 검수 가이드") lines.append("") lines.append("1. **정답 Frame 이 상위에 있는가** — compat ≥ 0.8 예상") lines.append("2. **문제 후보 (MDX01-2×29, MDX03-1×28, MDX03-2×18) 가 0.4 이하인가** — " "낮으면 의도대로 intent 가 걸러냄") lines.append("3. **MDX detected_intents 가 자연스러운가** — AI 추론 결과 검토") lines.append("4. **미태깅 frame (neutral 0.5) 이 정답보다 위에 오는가** — " "있으면 부분 적용 한계 = 추가 태깅 필요") lines.append("") lines.append("모두 통과하면 → Phase 24/25 점수 통합 진입.") out = HERE / "INTENT_DIAGNOSTIC_REPORT.md" out.write_text("\n".join(lines), encoding='utf-8') print(f"완료: {out}") if __name__ == "__main__": main()