Files
2nd/10_Wiki/Dev/Subsystems/TFIDF_이중언어_스코어링.md
T
Antigravity Agent 1cfd3bbb56 docs(10_Wiki): 위키 구조 정리 — 언어 튜토리얼 카테고리 폴더 제거 + 신규 자산 동기화
Topic_CSS/Topic_HTML/Topic_JavaScript/Topic_Prompt/Topic_Comfyui 등 기존 카테고리 폴더를 정리하고,
Topic_Graphic/Dev 등 신규 산출물과 Topics 내부 세션/메모리 기록을 동기화.
2026-07-05 00:10:59 +09:00

122 lines
7.1 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: tfidf-bilingual-scoring
title: "TF-IDF 이중언어 스코어링"
category: "AI_and_ML"
status: "draft"
verification_status: "applied"
canonical_id: ""
aliases: ["TF-IDF", "토크나이저", "tokenizer", "한국어 영어 토큰화", "동의어 확장", "검색 점수", "stop words", "섹션 청킹"]
duplicate_of: ""
source_trust_level: "A"
confidence_score: 0.92
created_at: 2026-06-13
updated_at: 2026-06-13
review_reason: ""
merge_history: []
tags: ["tfidf", "tokenizer", "search", "nlp", "korean", "astraai"]
raw_sources: ["AstraAI/src/retrieval/scoring.ts", "AstraAI/src/retrieval/chunker.ts"]
applied_in: ["AstraAI"]
github_commit: ""
---
# [[TF-IDF 이중언어 스코어링]]
## 🎯 한 줄 통찰 (One-line insight)
임베딩 엔진 없이도 쓸 수 있는 가벼운 검색의 핵심은 "좋은 토크나이저 + TF-IDF 가중"이며, AstraAI 는 **한국어/영어 혼합 토크나이저·불용어·동의어 확장·제목 가중·충돌 신호** 를 더해 단순 `includes()` 매칭을 넘어선 점수를 낸다 [S1].
## 🧠 핵심 개념 (Core concepts)
1. **TF-IDF:** 용어 빈도(TF, 문서 내 흔함) × 역문서빈도(IDF, 전체에서 희소함). 흔하면서 그 문서에만 자주 나오는 단어가 고득점 [S1].
2. **이중언어 토큰화:** 한글-영문 경계를 분리(`성능optimization``성능` `optimization`), 특수기호 보존(C++, C#, .net) [S1].
3. **불용어(Stop words):** 검색에 무의미한 단어(영/한 각각 집합)를 제거 [S1].
4. **동의어 확장:** 질의 토큰을 관련어로 확장(`성능``performance`, `optimization`, `최적화`) [S1].
5. **제목 가중:** 제목 일치는 본문보다 3배 가중(`TITLE_MULTIPLIER: 3.0`) [S1].
6. **토큰 캐시:** 같은 텍스트의 토큰화를 Map 으로 캐시(한도 초과 시 전체 clear) [S1].
## 🧩 추출된 패턴 (Extracted patterns)
- **중앙 설정 객체:** `SCORING_CONFIG` 에 불용어·동의어·임계값·가중치를 모아 한 곳에서 조정 [S1].
- **경계 분리 정규식:** `replace(/([a-z0-9]+)([가-힣]+)/gi, '$1 $2')` 로 언어 경계 분할, `split(/[^a-z0-9가-힣+#.-]+/g)` 로 특수기호(C++) 보존 [S1].
- **TF 계산 1회화:** `buildTermCounts` 로 문서당 용어 빈도 맵을 한 번 만들고 질의 용어마다 재사용 — O(질의×문서) 재스캔 회피 [S1].
- **IDF smoothing:** 문서 수가 적을 때도 안정적이도록 평활화 적용 [S1].
- **충돌 신호 탐지:** "반대/충돌/conflict/vs" 등 지표 단어 수로 conflictSeverity 산출 — 지식 충돌 가능 문서를 표시 [S1].
- **순수 함수 분리:** chunker/scoring 은 fs·네트워크 의존 없는 순수 함수라 단위 테스트·재현이 쉽다 [S2].
## 📖 세부 내용 (Details)
### 토크나이저 (가장 중요한 부품)
```typescript
const normalized = text.toLowerCase()
.replace(/[-]/g, '') // zero-width 제거
.replace(/[^\w\s가-힣_+#.-]/g, ' '); // 의미 없는 기호 → 공백
const splitText = normalized
.replace(/([a-z0-9]+)([가-힣]+)/gi, '$1 $2') // 영→한 경계 분리
.replace(/([가-힣]+)([a-z0-9]+)/gi, '$1 $2');// 한→영 경계 분리
const tokens = splitText.split(/[^a-z0-9가-힣+#.-]+/g) // C++, C#, .net 보존
.map(t => t.trim().replace(/[.,]$/g, ''))
.filter(t => /[가-힣]/.test(t) ? t.length >= 1 : t.length >= 2) // 한글 1자+, 영문 2자+
.filter(t => !STOP_EN.has(t) && !STOP_KO.has(t));
```
한국어는 한 글자도 의미를 가질 수 있어 1자 이상 허용, 영문은 2자 이상으로 노이즈를 줄인다 [S1].
### 동의어 확장
질의 `[성능]``[성능, performance, optimization, 최적화, speed]`. Set 으로 중복 제거 후 반환. brain 문서가 영어로, 질의가 한국어로 와도(또는 반대) 매칭되게 하는 양국어 다리 [S1].
### 섹션 청킹과의 결합
긴 문서를 통째 색인하면 5000자 다주제 문서가 흐릿한 한 단위가 되어 정밀도가 떨어진다. `chunker.ts` 가 헤딩(`#`~`######`) 경계로 섹션을 나누고, 짧은 섹션은 병합·긴 섹션은 문단 경계로 재분할한다. fenced code block(```) 안의 `#` 는 헤딩으로 보지 않는다. 헤딩 breadcrumb 을 보존해 청크가 문맥을 잃지 않게 한다 [S2].
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
- **TF-IDF 의 한계:** 어휘가 다르면(동의어 사전에 없는 환언) 못 잡는다. 그래서 임베딩 하이브리드로 보완한다 → [[RAG 검색 파이프라인]].
- **동의어 사전의 유지보수:** 수작업 사전이라 도메인이 늘면 누락이 생긴다. 핵심 도메인 용어 위주로 관리하는 절충.
- **형태소 분석 부재:** 한국어 조사/어미를 정밀 분해하지 않는다(경량 우선). 정밀도가 더 필요하면 형태소 분석기 도입 여지.
## 🛠️ 적용 사례 (Applied in summary)
- `AstraAI/src/retrieval/scoring.ts` — tokenize/expandQuery/TF-IDF/충돌 탐지 [S1].
- `AstraAI/src/retrieval/chunker.ts` — splitIntoSections 섹션 청킹 [S2].
## 💻 코드 패턴 (Code patterns)
```typescript
// 1) 중앙 설정 객체 — 가중치/임계값 한 곳에서 (src/retrieval/scoring.ts)
const SCORING_CONFIG = {
STOP_WORDS_EN: new Set(['the','a','and',/* ... */]),
STOP_WORDS_KO: new Set(['그리고','그런데',/* ... */]),
SYNONYM_DATA: [['성능', ['performance','optimization','최적화','speed']], /* ... */],
TITLE_MULTIPLIER: 3.0,
GLOBAL_CACHE_LIMIT: 2000,
};
// 2) TF 계산 1회화 (src/retrieval/scoring.ts)
function buildTermCounts(tokens: string[]): Map<string, number> {
const counts = new Map<string, number>();
for (const t of tokens) counts.set(t, (counts.get(t) || 0) + 1);
return counts; // 질의 용어마다 재스캔 대신 이 맵을 조회
}
// 3) 동의어 확장 (src/retrieval/scoring.ts)
export function expandQuery(tokens: string[]): string[] {
const expanded = new Set(tokens);
for (const t of tokens) (synonymMap.get(t) ?? []).forEach(s => expanded.add(s));
return Array.from(expanded);
}
// 4) 헤딩 경계 섹션 청킹 — fence 안의 # 무시 (src/retrieval/chunker.ts)
const fence = line.trimStart().startsWith('```'); if (fence) inFence = !inFence;
const m = !inFence ? line.match(HEADING_RE) : null; // 코드블록 내 #는 헤딩 아님
```
## ✅ 검증 상태 및 신뢰도
- **상태:** draft
- **검증 단계:** applied
- **출처 신뢰도:** A
- **신뢰 점수:** 0.92
- **중복 검사 결과:** 신규 생성 (New discovery)
## 🔗 지식 그래프 (Knowledge Graph)
- **상위/루트:** [[AstraAI 아키텍처 개요]]
- **관련 개념:** [[RAG 검색 파이프라인]], [[5계층 메모리 시스템]], [[TypeScript 기초와 타입 시스템]]
- **참조 맥락:** 로컬 LLM 이 가벼운 텍스트 검색·토큰화·점수 함수를 작성할 때(특히 한/영 혼용) 참조.
## 📚 출처 (Sources)
- [S1] AstraAI/src/retrieval/scoring.ts — 토크나이저, TF-IDF, 동의어, 불용어, 충돌 탐지, 캐시
- [S2] AstraAI/src/retrieval/chunker.ts — 섹션 청킹(순수 함수)
## 📝 변경 이력 (Change history)
- 2026-06-13: AstraAI 코드 분석 기반 초안 생성.