# PIPELINE — V1 ~ V4 매칭 시스템 통합 정리 이 문서는 MDX ↔ Figma Frame 매칭 시스템의 V1 ~ V4 단계를 한 곳에 정리한다. 새 작업자 (또는 새 Claude 세션) 가 이 문서만 읽어도 시스템 전체를 파악할 수 있도록 작성. --- ## 사전 작업 (V1 이전) ### S.1 입력 수집 | 출처 | 입력 문서 | 수집 문장 | |---|---|---| | Figma 프레임 텍스트 | 32 개 | 586 | | BEPS 마스터 텍스트 | 1 개 | 1,410 | | MDX 검증 구간 | 4 개 | 129 | | **합계** | **37** | **2,125** | - **코드** : `pipeline_01_extract_nodes.py` - **결과** : `actual_text_nodes.yaml` ### S.2 키워드 추출 + 정리 ``` 2,125 문장 → 형태소 분석 (Kiwi) → 13,913 등장 / 1,738 고유 ↓ 표기 통합 + 보존 규칙 전처리 후 14,161 등장 / 1,713 고유 ↓ 등장 범위 분류 핵심 451 + 연관 1,238 + 광범위 24 = 1,713 추가: 키워드 세트 524 (frame-level 시그니처) ``` **적용 규칙** - 중요 표기 보존 13개: `DX`, `BIM`, `S/W`, `H/W`, `2D`, `3D`, `AS-IS`, `TO-BE` 등 - 표기 통합: "디지털 전환" / "디지털전환" → 대표 표기 `DX` - 제외: 1글자 단어, 순수 숫자, 공백/기호만 있는 토큰 - 품사: 일반명사 / 고유명사 / 외국어 / 숫자만 **코드** : `pipeline_02_tokenize.py`, `pipeline_04_normalize.py`, `pipeline_05_anchor_candidates.py`, `pipeline_07_auto_anchor_candidates.py` **결과** : `auto_anchor_candidates.yaml`, `keyword_base.yaml`, `domain_terms.yaml` ### S.3 Frame 구조 라벨링 (templates_v2 ontology) 32 개 Figma 프레임 각각에 다음 정보 라벨링: - `visual_pattern.layout` (compare-rows / table-2col / cards-3col 등) - `visual_pattern.family` (table / card / diagram / list) - `visual_pattern.relation_type` (compare / parallel / sequence) - `visual_pattern.cardinality` (ideal / min / max) - `content_affinity.primary` + `secondary` (12 카테고리) - `structure_intent_v2.primary` + `secondary` (9 카테고리) - `slots` (146 고유 slot id — title, col_a_label, col_b_label, rows 등) - `alternative_patterns` (대안 layout) **도출 과정** : r1 → r2 → r3 → final → final_r2 (수동 오버라이드 3건) **코드** : `pipeline_12_generate_templates_v2.py`, `pipeline_12_r3_generate_templates_v2.py`, `pipeline_12_finalize_v2.py` **결과** : `structure_ontology_v2_final_r2.yaml` --- ## V1 — 키워드 매칭 ### 무엇을 보는가 MDX 본문 단어와 frame 의 3 계층 키워드 (핵심 / 세트 / 연관) 의 일치 비율. ### 산식 ``` matching_score = 0.414 × 핵심 점수 + 0.320 × 세트 점수 + 0.265 × 연관 점수 ``` - 핵심 점수 = (frame 핵심 키워드 중 MDX 본문에 등장한 비율) - 세트 점수 = (frame 세트들의 MDX 매칭 coverage 평균) - 연관 점수 = (frame 연관 키워드 중 MDX 본문에 등장한 비율) ### 가중치 도출 과정 1. 초기 (수동) : 0.30 / 0.50 / 0.20 — 도메인 판단 2. **Logistic Regression 학습** (L2, C=1.0, scikit-learn) - 데이터: TARGET 4 × 32 frame = 128 샘플 (정답 4 / 오답 124) - Feature: (standalone_score, group_score, related_score) - Label: 1 (정답) / 0 (오답) - 학습 결과: **0.414 / 0.320 / 0.265** 3. **검증 — LOOCV** (Leave-One-Out Cross-Validation) - 4 TARGET 각각 hold-out → 나머지 3 개로 학습 → hold-out 정답 판별 - 결과: **4 / 4 모두 정답** - 가중치 변동: 0.40 ± 0.02 / 0.32 ± 0.02 / 0.27 ± 0.01 (안정적) ### 결과 정확도 | 방식 | TARGET 정답 | |---|---| | 현재 (수동 0.30/0.50/0.20) | 4 / 4 | | **Logistic Regression (0.414/0.320/0.265)** | **4 / 4** | | OLS Linear (1.0/0.05/-0.05) | 3 / 4 | | BM25 (개별 토큰) | 3 / 4 | | BM25 (세트 포함) | 3 / 4 | | IDF-weighted | 3 / 4 | ### 발견된 약점 - 02-2.2 (TARGET) : 정답 Frame 14 의 anchor 키워드가 MDX 본문과 거의 안 겹침 → V1 점수 낮음 (V4 까지 가도 reject) ### 코드 + 결과 - 매칭 코드 : `pipeline_06_2_mdx_matching.py` - 가중치 학습 : `pipeline_15_logistic_regression.py` - 결과 비교 : `pipeline_15_bm25_with_sets.py`, `pipeline_15_idf_comparison.py` - 결과 파일 : `mdx_matching_result.yaml` - 검증 보고서 : `ATTACH_07_WEIGHT_VALIDATION.html` --- ## V2 — 의미 매칭 (semantic rerank) ### 무엇을 보는가 "키워드는 다르지만 의미가 같은가?" — MDX summary 와 frame.content 의 의미적 유사도. ### 산식 ``` similarity = cosine(embed(MDX summary), embed(frame.content)) ``` - 모델: `jhgan/ko-sroberta-multitask` (한국어 Sentence-BERT) ### 도출 과정 - 별도 가중치 학습 없음. cosine 유사도 그대로 사용. - V1 Top-K 후보 안에서 의미 유사도로 재정렬. ### 결과 정확도 - V1 후보 재정렬 단계라 단독 정확도는 별도 측정 X - V3, V4 의 출발점 (V2 Top-K 후보 → V3 평가) ### 발견된 약점 - 의미 임베딩 단독으로는 frame 식별력 부족 (도메인 키워드 신호가 더 강함) - V1 Top-K 가 부정확하면 V2 도 그 한계 안에서 작동 ### 코드 + 결과 - 매칭 코드 : `pipeline_08_v2_semantic_rerank.py` - 임베딩 모듈 : `embeddings.py` - 결과 파일 : `v2_semantic_rerank_result.yaml` - 진단 : `pipeline_09_v2_diagnosis.py`, `V2_DIAGNOSIS.md` --- ## V3 — 구조 매칭 (structure rerank) ### 무엇을 보는가 "이 콘텐츠를 담을 수 있는 레이아웃인가?" — MDX 글 구조와 frame 의 구조 속성 비교. ### 산식 ``` 구조 점수 = 0.40 × 레이아웃 일치 + 0.35 × 콘텐츠 성격 일치 + 0.25 × 시각 의도 일치 ``` **구성 요소** - **레이아웃 일치** : MDX layout family (table/card/diagram/list) ↔ frame family - **콘텐츠 성격** : 12 카테고리 키워드 사전 매칭 (concept_definition / comparative_matrix / policy_requirements 등) - **시각 의도** : 9 카테고리 키워드 사전 매칭 (matrix_coverage / cycle_interrelation / state_transition 등) ### MDX 본문 분석 방법 - **레이아웃 자동 감지** : `detect_mdx_layout_v2(text)` — 표 / 불릿 / 헤딩 패턴 → layout enum → family - **콘텐츠 성격** : `AFFINITY_KEYWORDS` 사전 매칭 → 등장 횟수 1위 카테고리 = primary - **시각 의도** : `INTENT_KEYWORDS` 사전 매칭 + STRONG 구절 패턴 검증 (예: state_transition 은 "AS-IS / TO-BE" 1개 이상 필요) ### 도출 과정 (5회 튜닝 r1 → r5) | 라운드 | 변경 내용 | 결과 | |---|---|---| | r1 | 초기 키워드 사전 (12 + 9 카테고리) | TARGET 2/4 | | r2 | layout_compat 가중치 조정 | TARGET 2/4 | | r3 | STRONG 패턴 검증 도입 (before_after_change, state_transition) | TARGET 3/4 | | r4 | concept_definition 에서 "개념" 제거, hierarchy 단일 키워드 금지 | TARGET 3/4 | | **r5** | ontology final_r2 (Frame 13 review_queue 해제) | **TARGET 4/4** | ### 결과 정확도 - TARGET : **4/4** (V2 Top-5 후보 안에서) - 단, V2 후보가 부정확하면 V3 도 부정확 ### 발견된 약점 - **콘텐츠 성격 / 시각 의도 분류 부정확** : 키워드 사전 매칭이라 단순 카운트 - 예: MDX 01-2 (DX 와 BIM 의 구분) → 본문에 "국내, 도입, 사례" 가 많아 `policy_requirements` 1위 (실제 `comparative_matrix`) - 한계: 도메인 키워드 사전 의존, 일반 표현 못 잡음 ### 코드 + 결과 - 매칭 코드 : `pipeline_08_v3_r5_structure_rerank.py` (최종) - 의존 모듈 : `pipeline_08_v3_r4_structure_rerank.py`, `pipeline_08_v3_r2_structure_rerank.py`, `structure_v3.py`, `phase_common.py` - MDX 분석 : `detect_mdx.py` - 결과 파일 : `v3_structure_rerank_r5_result.yaml` --- ## V4 — 종합 판정 (template-fit-v1) ### 무엇을 보는가 "실제로 쓸 수 있나? 어느 정도 수정해야 하나?" — V1/V2/V3 신호를 합쳐 frame 적용 가능성 판정. ### 산식 ``` base = 0.25 × anchor + 0.20 × cardinality + 0.20 × relation + 0.15 × slot + 0.20 × content confidence = max(0, base − penalty) ``` **5 축 의미** - `anchor` (0.25) : MDX detected_terms ↔ frame anchor_sets 매칭 (V1 핵심 키워드 매칭과 유사) - `cardinality` (0.20) : MDX 항목 수가 frame cardinality [min, max] 범위 안인가 - `relation` (0.20) : MDX relation_type (compare/parallel/sequence) ↔ frame relation_type 일치 - `slot` (0.15) : 휴리스틱 — within(0.5) + has_labels(0.3) + has_bodies(0.2) - `content` (0.20) : V2 의미 임베딩 cosine **penalty** - cardinality mismatch 시 `adaptation_cost` 부과 (split / merge / infer_missing) - `not_suits` 패턴 매치 시 `not_suits_penalty` - 합계 capped at CAP_TOTAL ### 임계값 라우팅 | 라벨 | confidence | 의미 | 후속 작업 | |---|---|---|---| | `use_as_is` | ≥ 0.90 | 그대로 사용 | 슬롯에 텍스트만 매핑 (자동) | | `light_edit` | ≥ 0.75 | 가벼운 편집 | AI 1 호출 (텍스트 다듬기) | | `restructure` | ≥ 0.60 | 구조 재배치 | 사람 + AI 여러 호출 | | `reject` | < 0.60 | 사용 불가 | 신규 디자인 | ### 도출 과정 1. **r1 (V3 Top-K 평가만)** : V3 Top-5 안에서 confidence 산출 → 5개 중 선택 2. **r2 (안정화)** : V2 후보 재선정 + adaptation_allowed 검증 추가 3. **full32 (최종)** : 32 frame 전체 평가 → 진정한 reject 식별 가능 ### 결과 정확도 - TARGET : **3/4** (use_as_is 매칭 성공) - 01-2 ✓ (Frame 18, conf 0.946) - 02-2.2 ✗ (정답 Frame 14, V4 순위 7, reject) - 03-1 ✓ (Frame 13, conf 0.927) - 03-2 ✓ (Frame 29, conf 0.920) - Holdout : 사람 검수자 합리적 수준 ### 발견된 약점 #### slot 축 ablation 결과 - W_SLOT=0 으로 두고 4축 재정규화 → V4 재계산 - **Top-1 매칭 7/7 동일** (모든 섹션) - TARGET Top-1 정답률: Baseline 3/4 → Ablated 3/4 (동일) - → **slot 축은 frame 선별에 영향 없음. 라벨 게이트 역할만 (use_as_is ↔ light_edit 임계 통과 여부)** #### cardinality 중복 가중 - cardinality 축 (0.20) 과 slot.within (0.075) 이 **같은 신호**를 두 번 평가 - `item_count = len(slot_candidates)` 로 동일 #### 슬롯 의미 매핑 부재 - frame 의 146 개 의미 slot id (`title`, `col_a_label`, `col_b_label`, `rows` 등) 가 V4 점수 계산에 활용 안 됨 - "BIM → col_a_label" 같은 의미 매핑은 코드에 없음 — 후속 단계 책임 #### 표 첫 행만 추출 - MDX 가 4 행 표여도 첫 행만 본문으로 추출. 나머지 행 (S/W·프로세스·성과품) 무시 ### 코드 + 결과 - 매칭 코드 : `pipeline_17_v4_full32.py` (최종, 32 frame 전체) - 의존 모듈 : `template_fit.py` - Ablation : `pipeline_18_slot_axis_ablation.py` - 결과 파일 : `v4_full32_result.yaml` - Ablation 보고서 : `V4_SLOT_ABLATION.md` --- ## 새 pipeline 통합 시 frame 단위 — 명확화 > **주의** : 이 매칭 시스템 (V1~V4) 은 **frame 32 개를 슬라이드 1장 단위로 검증** 함 (예: Frame 18 = BIM/DX 비교 슬라이드 통째로). > > 새 pipeline 의 위계는 **슬라이드 ⊃ slide-base ⊃ slide-body ⊃ 레이아웃 ⊃ Zone ⊃ 프레임** 이며, 여기서 **프레임 = zone 안 디자인 단위** 임. > > → frame DB 의 사이즈 라벨링 재검토 필요: > - 어떤 frame = 슬라이드 전체 (= 레이아웃 그 자체) > - 어떤 frame = zone 1 개 단위 (= 부분 디자인) > - 작은 박스 단위도 가능 > > 새 pipeline 통합 작업의 사전 준비 항목 ([../IMPROVEMENT-REDESIGN.md](../../IMPROVEMENT-REDESIGN.md) 의 7.1 참조) --- ## 사후 작업 (V4 이후) ### 보고서 (DECK 1 ~ 7) | 파일 | 내용 | |---|---| | `DECK_01_TARGET_01_2.html` | TARGET 01-2 × V1~V4 Top-3 매칭 결과 | | `DECK_02_HOLDOUT_02_2_1.html` | Holdout 02-2.1 × V1~V4 Top-3 | | `DECK_03_METHODS.html` | V1~V4 방법 설명 | | `DECK_04_DB_STRUCTURE.html` | MDX 1 vs Top-3 frame 5 컬럼 비교표 | | `DECK_05_STRUCTURE_KEYWORD.html` | 구조 매칭 4 항목 상세 (콘텐츠 성격 / 시각 의도 / 편집 슬롯 / 항목수·관계) | | `DECK_06_FIGMA_TO_DB.html` | Frame 18 의 DB 저장 형태 샘플 (YAML) | | `DECK_07_KEYWORD_PIPELINE.html` | 키워드집 정리 과정 + Frame 18 샘플 | **생성 코드** : `pipeline_16_deck_4pages.py` ### 보조 보고서 | 파일 | 내용 | |---|---| | `KEYWORD_INVENTORY.html` | 키워드집 생성 보고서 (1,713 고유 + 13 중요 표기) | | `ATTACH_07_WEIGHT_VALIDATION.html` | V1 가중치 Logistic Regression 검증 | | `V4_SLOT_ABLATION.md` | V4 slot 축 ablation 결과 | | `FIGMA_KEYWORDS_REPORT.html` | Frame 별 키워드 인벤토리 | | `FRAME_KEYWORD_REVIEW.html` | Frame 별 키워드 검토 | --- ## 발견된 약점 종합 (8 가지) | # | 약점 | 발견 시점 | 우선순위 | |---|---|---|---| | 1 | 02-2.2 매칭 실패 (정답 Frame 14 reject) | V4 결과 | 🥇 1순위 | | 2 | MDX 콘텐츠 성격 분류 부정확 (키워드 사전 한계) | V3 r5 검토 | 🥈 2순위 | | 3 | MDX 시각 의도 분류 부정확 (동일 한계) | V3 r5 검토 | 🥈 2순위 | | 4 | 편집 슬롯 의미 매핑 부재 | V4 코드 검토 | 🥉 3순위 | | 5 | V4 cardinality 중복 가중 | ablation | 🥉 3순위 | | 6 | V4 slot 축 frame 선별 무영향 | ablation | 🥉 3순위 (4 + 5 와 함께) | | 7 | 표 첫 행만 추출 (다행 무시) | DECK 04 정직성 점검 | 4순위 | | 8 | 그림/이미지 frame 매칭 약함 | V3 r5 검토 | 4순위 | ## 다음 단계 (개선 방향) | 작업 | 내용 | 공수 | |---|---|---| | **02-2.2 교정** | Frame 14 anchor_sets 재라벨링 + 도메인 키워드 보강 → TARGET 4/4 | 1~2 일 | | **MDX 분석 LLM 화** | 콘텐츠 성격 / 시각 의도를 키워드 사전 → Anthropic API 호출 | 3~5 일 | | **슬롯 의미 매핑 모듈** | "BIM → col_a_label" 매핑 + V4 slot 축 진짜 역할 부여 | 5~7 일 | | **표 다행 처리** | rows 슬롯 채우기용 다행 추출 | 2~3 일 | | **그림 매칭 강화** | 본문 이미지 + 텍스트 결합 분석 | 2~3 일 | --- ## 핵심 메시지 (3 줄 요약) 1. **TARGET 75% (3/4)** — V1 가중치는 Logistic Regression 으로 검증 (LOOCV 4/4), BM25 / IDF 보다 우위 2. **약점**: V3 의 콘텐츠 성격 / 시각 의도가 키워드 사전 기반이라 부정확. V4 의 slot 축은 ablation 으로 frame 선별 무영향 확인 3. **다음 단계**: 02-2.2 교정 (1~2일) → MDX 분석 LLM 화 (3~5일) → 슬롯 의미 매핑 모듈 (5~7일)