Files
C.E.L_Slide_test2/tests/matching/matrix_17.py
T
KyeongminandClaude Opus 4.8 b836e79ee1 wip: phase_z2 evidence 파이프라인 + matching 실험(phase2~26) + 프론트 trace 패널 진행분 스냅샷
- src: phase_z2 composition/mapper/pipeline/placement_planner/retry, ai_fallback(prompts/schema/validate), mdx_text_atoms 신규
- Front: PipelineTracePanel 신규, FramePanel/SlideCanvas/Home/designAgentApi 등 갱신 + 테스트 4종 추가
- templates/phase_z2: catalog(component_expansion_registry, node_slot_mapping 신규), frames, families, slide_base 갱신
- tests/matching: phase2~26 매칭 실험 스크립트·리포트·온톨로지 전체 (미커밋 진행분)
- tests: b4_v4 evidence, task5~28.5 시리즈, regression(imp95 baseline) 등 신규 테스트 대량 추가
- docs/reference: MDX 구조 인벤토리, MDX→Frame 구조 계약 문서
- scripts: mdx 계약/parity/coverage/viewport 체크, gitea comment, run sync 유틸
- .gitignore: tmp*.json, chromedriver, .orchestrator, *.pkl, Front_test* 등 임시/스냅샷 제외

미완성 작업의 보존용 스냅샷 커밋 (2026-07-02)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 17:03:42 +09:00

184 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""17개 단위 × 8개 방법 매트릭스 (점수 포함)"""
import sys
import json
import yaml
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from common import load_figma_texts
from extract_units import extract_units
from methods import (
method_tfidf, method_bm25, method_char_ngram,
method_kiwi_bm25, method_structural,
method_ai_metadata_matcher, method_weighted, method_hard_filter,
)
ROOT = Path(r"d:\ad-hoc\kei\design_agent")
PREVIEW_DIR = ROOT / "data" / "figma_previews"
# 17 단위의 순서/메타 (사용자가 제시한 표 그대로)
UNIT_ORDER = [
("MDX01-intro", "중목차 앞 본문", "용어 혼용 문제 제기"),
("MDX01-intro-details", "팝업", "혼용 대표 사례 (정책 2건)"),
("MDX01-1", "중목차", "용어 정의 (건설산업/BIM/DX)"),
("MDX01-2", "중목차", "용어간 상호관계"),
("MDX01-2-image", "이미지", "DX1.png"),
("MDX01-2-details", "팝업+표", "DX와 BIM의 구분 12행 표"),
("MDX02-1", "중목차", "DX의 궁극적 목표"),
("MDX02-1-image", "이미지", "궁극적목표.png"),
("MDX02-2", "중목차(컨테이너)", "소목차 포함 전체"),
("MDX02-2.1", "소목차", "업무 수행 과정의 변화"),
("MDX02-2.2", "소목차", "주체별 기대효과"),
("MDX02-2.2-table", "표", "발주자/시공자/설계자 4×3"),
("MDX03-1", "중목차", "필수 요건 (기술/사람/자연)"),
("MDX03-2", "중목차(컨테이너)", "소목차 포함 전체"),
("MDX03-2.1", "소목차", "과정(Process)의 혁신"),
("MDX03-2.1-table", "표", "As-is/To-be 3행"),
("MDX03-2.2", "소목차", "결과(Product)의 변화"),
]
def fmt_score(score, method_name):
if method_name in ("TF-IDF", "Char-ngram", "AI-Meta", "Weighted", "Structural"):
return f"{score * 100:.0f}%"
else:
return f"{score:.1f}"
def main():
units = extract_units()
figma = load_figma_texts()
with open(PREVIEW_DIR / "index.json", encoding="utf-8") as f:
idx_data = json.load(f)
frame_to_short = {info["frame_id"]: sid for sid, info in idx_data.items()}
with open(Path(__file__).parent / "metadata_db.yaml", encoding="utf-8") as f:
metadata_db = yaml.safe_load(f)
# AI-Metadata는 DB에 등록된 키만 매칭 가능. 17개 단위는 새로 추가 필요.
# 임시로 각 새 단위의 concepts를 derive (안 된 건 빈 리스트)
# 기존 DB에 없는 단위는 부모 섹션의 concepts 사용
mdx_meta = metadata_db.get("mdx_sections", {})
# 17개에 대한 간이 concepts (부모 섹션 상속 or 직접 작성)
extra_meta = {
"MDX01-intro": mdx_meta.get("MDX01-intro", {"concepts": [], "layout_hint": "intro"}),
"MDX01-intro-details": {"concepts": ["정책", "디지털화", "BIM", "스마트건설", "사례"], "layout_hint": "popup-list"},
"MDX01-1": mdx_meta.get("MDX01-1", {"concepts": [], "layout_hint": "definition-list"}),
"MDX01-2": mdx_meta.get("MDX01-2", {"concepts": [], "layout_hint": "compare-rows"}),
"MDX01-2-image": {"concepts": ["DX", "핵심기술", "상호관계", "GIS", "BIM", "디지털트윈"], "layout_hint": "diagram"},
"MDX01-2-details": {"concepts": ["BIM", "DX", "비교", "범위", "S/W", "프로세스", "성과품", "활용", "확장성", "수행개념", "CIVIL", "IT", "주체", "발주처", "설계사", "시공사"], "layout_hint": "compare-rows"},
"MDX02-1": mdx_meta.get("MDX02-1", {"concepts": [], "layout_hint": "cycle-goal"}),
"MDX02-1-image": {"concepts": ["DX", "목표", "안전", "품질", "생산성", "소통", "신뢰"], "layout_hint": "cycle-3way"},
"MDX02-2": mdx_meta.get("MDX02-2", {"concepts": [], "layout_hint": "persona-3col"}),
"MDX02-2.1": {"concepts": ["Process", "변화", "수작업", "S/W", "체계화", "2D", "3D", "협업", "검증", "사전"], "layout_hint": "transition-list"},
"MDX02-2.2": {"concepts": ["발주자", "시공자", "설계자", "역량", "기대효과", "3D모델", "협업", "Claim", "리스크", "품질"], "layout_hint": "persona-3col"},
"MDX02-2.2-table": {"concepts": ["발주자", "시공자", "설계자", "필요역량", "업무", "변화", "3D", "검증", "협업", "표"], "layout_hint": "table-3col"},
"MDX03-1": mdx_meta.get("MDX03-1", {"concepts": [], "layout_hint": "3col-parallel"}),
"MDX03-2": mdx_meta.get("MDX03-2", {"concepts": [], "layout_hint": "compare-2col"}),
"MDX03-2.1": {"concepts": ["Process", "Analogue", "Digital", "혁신", "GIS", "BIM", "Solution", "2D", "3D", "협업"], "layout_hint": "compare-2col"},
"MDX03-2.1-table": {"concepts": ["Analogue", "Digital", "As-is", "To-be", "2D", "3D", "문서", "행정", "시각화", "소통", "표"], "layout_hint": "compare-2col"},
"MDX03-2.2": {"concepts": ["Product", "결과", "성과물", "품질", "Digital", "정보물", "Solution", "협업", "통합관리"], "layout_hint": "compare-2col"},
}
# extra_meta 병합
combined_meta = {**mdx_meta, **extra_meta}
methods_def = [
("TF-IDF", method_tfidf),
("BM25", method_bm25),
("Char-ngram", method_char_ngram),
("Kiwi+BM25", method_kiwi_bm25),
("Structural", method_structural),
("AI-Meta", None),
("Weighted", method_weighted),
("HardFilter", method_hard_filter),
]
# 실행
results = {} # {unit_id: {method: [(fid, score), ...top3]}}
for uid, unit_text in units.items():
results[uid] = {}
for mname, fn in methods_def:
if not unit_text.strip():
results[uid][mname] = []
continue
if mname == "AI-Meta":
ranked = method_ai_metadata_matcher(
uid, metadata_db["figma_frames"], combined_meta
)
else:
ranked = fn(unit_text, figma)
results[uid][mname] = ranked[:3]
# 리포트
lines = []
lines.append("# MDX 17개 단위 × 8개 방법 매칭 매트릭스")
lines.append("")
lines.append("- 각 셀: `프레임번호 (점수)`")
lines.append("- 프레임 번호는 `data/figma_previews/index.json` 기준 01~32")
lines.append("- 점수 스케일: %(코사인/Jaccard), 숫자(BM25 raw)")
lines.append("")
# Top-1 매트릭스
lines.append("## Top-1 매트릭스")
lines.append("")
method_names = [m[0] for m in methods_def]
header = "| # | 단위 | 종류 | " + " | ".join(method_names) + " |"
lines.append(header)
lines.append("|" + "---|" * (len(method_names) + 3))
for i, (uid, kind, desc) in enumerate(UNIT_ORDER, 1):
cells = [str(i), uid, kind]
for mname in method_names:
top = results[uid][mname][:1]
if not top:
cells.append("-")
continue
fid, score = top[0]
short = frame_to_short.get(str(fid), "?")
cells.append(f"**{short}** ({fmt_score(score, mname)})")
lines.append("| " + " | ".join(cells) + " |")
lines.append("")
# Top-3 상세
lines.append("## Top-3 상세")
lines.append("")
for i, (uid, kind, desc) in enumerate(UNIT_ORDER, 1):
lines.append(f"### {i}. {uid} ({kind}) — {desc}")
lines.append("")
lines.append("| 방법 | 1순위 | 2순위 | 3순위 |")
lines.append("|------|-------|-------|-------|")
for mname in method_names:
cells = [mname]
top3 = results[uid][mname][:3]
for fid, score in top3:
short = frame_to_short.get(str(fid), "?")
cells.append(f"**{short}** ({fmt_score(score, mname)})")
while len(cells) < 4:
cells.append("-")
lines.append("| " + " | ".join(cells) + " |")
lines.append("")
# 프레임 번호 참고
lines.append("## 프레임 번호 참고")
lines.append("")
lines.append("| # | 제목 | 미리보기 |")
lines.append("|---|------|---------|")
for sid in sorted(idx_data.keys()):
info = idx_data[sid]
title = info.get("title_text", "").strip().replace("\n", " ") or "_(제목없음)_"
if len(title) > 50:
title = title[:50] + "…"
png_rel = f"../../data/figma_previews/{info['png']}"
lines.append(f"| **{sid}** | {title} | ![{sid}]({png_rel}) |")
lines.append("")
out_path = Path(__file__).parent / "MATRIX_17.md"
out_path.write_text("\n".join(lines), encoding="utf-8")
print(f"완료: {out_path}")
if __name__ == "__main__":
main()