Files
C.E.L_Slide_test2/scripts/eval_block_matcher.py
kyeongmin 85c680f02a docs + V4 catalog + samples + Phase Q legacy 보존
전체 26 files (20 추가 + 6 수정), 10507 insertions.

Phase Z 문서 :
- docs/architecture/PHASE-Z-CHANGE-LOG.md (신설) — axis-by-axis 의사결정 history
  (newest-on-top). Step 7-A 부터 6 entry 박힘 + 2026-05-08 / 2026-05-08 #2
  (compat 매트릭스 폐기 / 6-B 폐기 / F14 표현 정정 / label gate policy 분리).
- docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md (수정) — Step 5/6/9 Gap note
  append (구조 무변, append-only). 6-B 폐기 사실 + Refinement F.
- docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md (수정) — snapshot date
  2026-05-08 갱신. §3 핵심 missing item 5 (Step 5/6/9 boundary axis breakdown
  + 폐기 기록). §6 한 줄 갱신 — 다음 axis 후보 A~F.

Project root docs :
- PLAN.md / PROGRESS.md / README.md (수정) — 토큰 체계 / 폴더 구조 / 설계 문서 /
  역할 분리 반영.
- IMPROVEMENT-REDESIGN.md (신설) — Phase Z 설계 핵심 문서.
- PROCESS_OVERVIEW.html (신설) — 파이프라인 개요 시각.
- docs/tasks/* (신설) — Phase Z task 문서.

V4 catalog (Phase Z runtime 필수 의존성) :
- tests/matching/v4_full32_result.yaml (신설, 4888 줄) — V4 매칭 결과 32 frame
  × 10 MDX section. lookup_v4_match() / lookup_v4_candidates() 가 본 파일 read.
  Phase Z runtime 이 *없으면 즉시 abort* — clone 후 즉시 동작 가능 보장.

Samples :
- samples/mdx_batch/04.mdx (신설) — MDX04 기본 sample.
- samples/mdx/04. DX 지연 요인.mdx (신설) — MDX04 원본.

Phase Q legacy 보존 (별 axis "Phase Q audit & salvage" 영역) :
- src/block_matcher_tfidf.py / catalog_blocks.py / frame_extractor.py /
  pipeline_v2.py — Phase Q (옛 파이프라인) src 신규 untracked 파일들.
  Phase Z runtime 와 의존성 0. Phase Q audit axis 에서 검토 예정.
- scripts/eval_block_matcher.py / fetch_all_frame_screenshots.py /
  match_17_units_my_matcher.py / match_mdx_strict.py / match_mdx_to_frames_tfidf.py /
  ocr_augment_texts.py / run_pipeline_v2.py / previews/ — Phase Q 작업 시
  사용한 옛 script. 같이 보존.
- run_mdx03_pipeline.py (수정) — Phase Q 진입점 (no flag) + Phase Z 진입점
  (--phase-z2 flag) 동시 wrapper. Phase Z 만 사용 시 `python -m
  src.phase_z2_pipeline samples/mdx_batch/03.mdx <run_id>` 직접 호출.

비-scope :
- tests/matching/ (v4_full32_result.yaml 외 ~63MB) — V4 진화 history /
  reports / DECK / ATTACH. Phase Q audit axis 에서 검토.
- tests/pipeline/ (~15MB) — pipeline data. Phase Q audit 영역.
- templates/catalog/blocks.yaml — 옛 block catalog. Phase Q audit.
- templates/phase_z2/frames/ — 옛 frame partial 위치. Phase Q audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:47:58 +09:00

83 lines
2.2 KiB
Python

"""블록 매칭 비교 스크립트.
기존 tag/item_count 매칭과 새 TF-IDF 매칭을 나란히 비교.
"진짜 좋아졌나?"를 판단하기 위한 도구.
사용법:
python scripts/eval_block_matcher.py
출력:
각 MDX의 중목차별로:
- legacy 매칭 결과 (기존)
- tfidf 매칭 결과 (새)
- 일치 여부
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from src.mdx_normalizer import normalize_mdx_content as normalize_mdx
from src.pipeline_v2 import match_blocks_for_sections
def evaluate_mdx(mdx_path: Path):
"""단일 MDX에 대해 TF-IDF 매칭 결과를 출력."""
content = mdx_path.read_text(encoding="utf-8")
result = normalize_mdx(content)
sections = result.get("sections", [])
print(f"\n{'='*60}")
print(f"MDX: {mdx_path.name}")
print(f"{'='*60}")
v2_results = match_blocks_for_sections(sections)
for zone_name, info in v2_results.items():
path = info["path"]
match = info.get("match")
sub_titles = info.get("sub_titles", [])
candidates = info.get("candidates", [])
print(f"\n zone: {zone_name}")
print(f" sub_titles: {sub_titles}")
print(f" path: {path}")
if match:
print(f" ✅ direct-fit: {match['block_id']} (score={match['score']})")
else:
print(f" → recipe 경로")
if candidates:
for i, c in enumerate(candidates):
print(f" 후보 {i+1}: {c['block_id']} (score={c['score']})")
else:
print(f" 후보 없음")
def main():
mdx_dir = Path("samples/mdx")
if not mdx_dir.exists():
print(f"MDX 폴더 없음: {mdx_dir}")
return
mdx_files = sorted(mdx_dir.glob("*.mdx"))
if not mdx_files:
print("MDX 파일 없음")
return
print(f"블록 매칭 평가 ({len(mdx_files)}개 MDX)")
print(f"catalog: templates/catalog/blocks.yaml")
for mdx_path in mdx_files:
try:
evaluate_mdx(mdx_path)
except Exception as e:
print(f"\n{mdx_path.name}: {e}")
print(f"\n{'='*60}")
print("평가 완료")
if __name__ == "__main__":
main()