"""domain_terms.yaml (Phase 23b 갱신판) → DOMAIN_TERMS_REPORT.md""" import sys from pathlib import Path import yaml sys.path.insert(0, str(Path(__file__).parent)) HERE = Path(__file__).parent def main(): with open(HERE / "domain_terms.yaml", encoding="utf-8") as f: data = yaml.safe_load(f) lines = [] lines.append("# Phase 23b — Domain Terms 검수 리포트 (정제판)") lines.append("") lines.append("> **개선 범위**: 노이즈 필터 강화 · safe_normalization 자동 분류 · 약어 regex 확장 · corpus 설명 정확화.") lines.append("> **synonyms.yaml은 6개 canonical로 동결** — 본 리포트 결과로 즉시 변경 안 함.") lines.append("") meta = data.get("meta", {}) lines.append("## 0. 메타") lines.append("") lines.append(f"- **Phase**: {meta.get('phase')}") lines.append(f"- **Purpose**: {meta.get('purpose')}") cb = meta.get("corpus_breakdown", {}) lines.append("- **Corpus 구성**:") for k, v in cb.items(): lines.append(f" - {k}: {v}") lines.append(f"- **노이즈 필터 후 2회+ 등장 용어**: {meta.get('total_terms_2plus_after_noise_filter')}개") lines.append(f"- **Note**: {meta.get('note')}") lines.append("") # 1. 고빈도 용어 Top 50 lines.append("## 1. 반복 등장 상위 용어 (노이즈 제거 후)") lines.append("") lines.append("| 순위 | 용어 | 등장 횟수 | 소스 다양성 |") lines.append("|-----|------|----------|------------|") for i, item in enumerate(data.get("top_terms_by_frequency", [])[:50], 1): lines.append(f"| {i} | `{item['term']}` | {item['count']} | {item['sources']}개 |") lines.append("") # 2. Safe normalization (자동 분류됨) sn = data.get("safe_normalization", {}) lines.append("## 2. Safe Normalization — 승격/보류/폐기 자동 분류") lines.append("") lines.append(f"### 2-1. Promote 후보 ({len(sn.get('promote', []))}개) — synonyms.yaml 승격 검토 가능") lines.append("") if sn.get("promote"): lines.append("| Canonical | Variants | 사유 | 검수 |") lines.append("|-----------|----------|------|------|") for item in sn["promote"]: vars_str = ", ".join(f"`{v}`" for v in item["variants"]) lines.append(f"| `{item['canonical']}` | {vars_str} | {item['reason']} | ⬜ 승격 / ⬜ 보류 |") else: lines.append("_(없음)_") lines.append("") lines.append(f"### 2-2. Hold ({len(sn.get('hold', []))}개) — 고유 제품명/브랜드, 치환 위험") lines.append("") if sn.get("hold"): lines.append("| Variants | 사유 |") lines.append("|----------|------|") for item in sn["hold"]: vars_str = ", ".join(f"`{v}`" for v in item["variants"]) lines.append(f"| {vars_str} | {item['reason']} |") lines.append("") lines.append(f"### 2-3. Discard ({len(sn.get('discard', []))}개) — 노이즈/메타 조각") lines.append("") if sn.get("discard"): lines.append("| Variants | 사유 |") lines.append("|----------|------|") for item in sn["discard"]: vars_str = ", ".join(f"`{v}`" for v in item["variants"]) lines.append(f"| {vars_str} | {item['reason']} |") lines.append("") # 3. 약어 풀네임 (확장 regex) lines.append("## 3. 약어-풀네임 후보 (확장 regex)") lines.append("") lines.append("**주의**: 상위 몇 개는 신뢰 가능. 하위는 regex가 주변 문맥 잘못 잡은 경우 포함 → 수동 검수 필수.") lines.append("") abbr = data.get("abbrev_fullname_candidates", []) if abbr: lines.append("| 약어 | 풀네임 | 등장 횟수 | 관계 분류 (검수) |") lines.append("|------|--------|----------|----------------|") for item in abbr: lines.append(f"| `{item['abbr']}` | `{item['full']}` | {item['count']} | ⬜ 동의어 / ⬜ 번역 / ⬜ 노이즈 |") lines.append("") # 4. 한영 병기 (evidence only) lines.append("## 4. 한영 병기 패턴 (evidence only — 신뢰도 낮음)") lines.append("") lines.append("**주의**: regex가 주변 문맥까지 삼키는 경우 많음. 그대로 synonym 하면 안 됨.") lines.append("") ke = data.get("ko_en_paren_pairs_evidence_only", []) if ke: lines.append("| 한글 | 영문 | 등장 횟수 | 분류 (검수) |") lines.append("|------|------|----------|------------|") for item in ke[:30]: lines.append(f"| `{item['ko']}` | `{item['en']}` | {item['count']} | ⬜ 동의어 / ⬜ 번역 / ⬜ 설명 / ⬜ 노이즈 |") lines.append("") # 5. 명시적 수동 검수 lines.append("## 5. 명시적 수동 검수 필요 (관계 모호)") lines.append("") nhr = data.get("needs_human_review", []) for item in nhr: lines.append(f"- ⬜ {item}") lines.append("") # 6. 검수 후 분기 lines.append("---") lines.append("") lines.append("## 6. 검수 후 분기") lines.append("") lines.append("| 분류 | 반영 위치 |") lines.append("|------|----------|") lines.append("| Promote 승격 | `synonyms.yaml` (production) |") lines.append("| Hold / Discard | 폐기 또는 보류, synonyms.yaml에 넣지 않음 |") lines.append("| 약어-풀네임 확정 | `synonyms.yaml` 추가 (매칭 영향 확인 후) |") lines.append("| 한영 병기 확정 | 동일 |") lines.append("| 근접어 / 기관vs역할 | `hierarchy.yaml` (Phase 25 연동 예정) |") lines.append("| 상하위 관계 (Engineering S/W 계열) | `hierarchy.yaml` (taxonomy 구축) |") lines.append("") lines.append("**Production 승격 체크리스트:**") lines.append("") lines.append("1. ✅ 실데이터 증거 (corpus 등장)") lines.append("2. ✅ 치환해도 의미 불변 (문맥 독립)") lines.append("3. ✅ Phase 19 재실행 시 점수 불변 or 개선 (악화 없음)") lines.append("4. ✅ 사람 검수 통과") lines.append("") out = HERE / "DOMAIN_TERMS_REPORT.md" out.write_text("\n".join(lines), encoding="utf-8") print(f"완료: {out}") if __name__ == "__main__": main()