Files
C.E.L_Slide_test2/tests/matching/matrix_simple.py
T

151 lines
5.4 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.
"""단순 매칭 매트릭스: MDX 섹션 × 8 방법 = 매칭된 프레임 번호 + 점수"""
import sys
import json
import yaml
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from common import load_ground_truth, load_figma_texts, load_mdx_sections
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"
def normalize_score(score, method_name):
"""방법별 점수 스케일이 달라서 0~100% 범위로 정규화.
- TF-IDF, Char-ngram, AI-Meta, Weighted: 이미 0~1 → ×100
- Structural: 0~1 → ×100
- BM25, Kiwi+BM25, HardFilter: raw 점수 (0~200+) → top1을 100%로 상대화
"""
return score # 원래 점수 그대로 반환 (아래에서 별도 처리)
def fmt_score(score, method_name, max_score=None):
"""점수를 읽기 좋게 포매팅."""
if method_name in ("TF-IDF", "Char-ngram", "AI-Meta", "Weighted", "Structural"):
# 0~1 스케일 → %
return f"{score * 100:.0f}%"
else:
# BM25 계열: raw 점수. max 대비 상대값
if max_score and max_score > 0:
rel = score / max_score * 100
return f"{rel:.0f}% ({score:.1f})"
return f"{score:.1f}"
def main():
gt_list = load_ground_truth()
figma = load_figma_texts()
mdx = load_mdx_sections()
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)
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),
]
# 각 섹션/방법별 Top-3 (score 포함)
top3_data = {}
for sec_id, sec_text in mdx.items():
top3_data[sec_id] = {}
for name, fn in methods_def:
if name == "AI-Meta":
ranked = method_ai_metadata_matcher(
sec_id, metadata_db["figma_frames"], metadata_db["mdx_sections"]
)
else:
ranked = fn(sec_text, figma)
top3_data[sec_id][name] = ranked[:3]
# ──────────────────────
# 리포트 생성
# ──────────────────────
lines = []
lines.append("# MDX ↔ Figma 매칭 매트릭스 (점수 포함)")
lines.append("")
lines.append("각 셀 형식: `프레임번호(점수)`")
lines.append("")
lines.append("- TF-IDF / Char-ngram / AI-Meta / Weighted / Structural: 0~100% (코사인 or Jaccard)")
lines.append("- BM25 / Kiwi+BM25 / HardFilter: raw 점수 (상대 비교용, 절대값은 문서길이/어휘량에 따라 달라짐)")
lines.append("")
# ══ Top-1 매트릭스 (점수 포함) ══
lines.append("## Top-1 (1순위)")
lines.append("")
method_names = [m[0] for m in methods_def]
header = "| MDX 섹션 | " + " | ".join(method_names) + " |"
lines.append(header)
lines.append("|" + "---|" * (len(method_names) + 1))
for gt in gt_list:
sid = gt["id"]
cells = [sid]
for mname in method_names:
top = top3_data[sid][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 (1/2/3순위)")
lines.append("")
for gt in gt_list:
sid = gt["id"]
lines.append(f"### {sid}")
lines.append("")
lines.append("| 방법 | 1순위 | 2순위 | 3순위 |")
lines.append("|------|-------|-------|-------|")
for mname in method_names:
cells = [mname]
for fid, score in top3_data[sid][mname][:3]:
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.md"
out_path.write_text("\n".join(lines), encoding="utf-8")
print(f"완료: {out_path}")
if __name__ == "__main__":
main()