wiki: Topic_Blog 신규 문서 일괄 추가 + ASTRA 성장 자산 동기화

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Antigravity Agent
2026-06-16 09:55:38 +09:00
parent d77ff5c625
commit e2c5471046
444 changed files with 88916 additions and 231 deletions
@@ -0,0 +1,121 @@
---
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", "connectai"]
raw_sources: ["ConnectAI/src/retrieval/scoring.ts", "ConnectAI/src/retrieval/chunker.ts"]
applied_in: ["ConnectAI"]
github_commit: ""
---
# [[TF-IDF 이중언어 스코어링]]
## 🎯 한 줄 통찰 (One-line insight)
임베딩 엔진 없이도 쓸 수 있는 가벼운 검색의 핵심은 "좋은 토크나이저 + TF-IDF 가중"이며, ConnectAI 는 **한국어/영어 혼합 토크나이저·불용어·동의어 확장·제목 가중·충돌 신호** 를 더해 단순 `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)
- `ConnectAI/src/retrieval/scoring.ts` — tokenize/expandQuery/TF-IDF/충돌 탐지 [S1].
- `ConnectAI/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)
- **상위/루트:** [[ConnectAI 아키텍처 개요]]
- **관련 개념:** [[RAG 검색 파이프라인]], [[5계층 메모리 시스템]], [[TypeScript 기초와 타입 시스템]]
- **참조 맥락:** 로컬 LLM 이 가벼운 텍스트 검색·토큰화·점수 함수를 작성할 때(특히 한/영 혼용) 참조.
## 📚 출처 (Sources)
- [S1] ConnectAI/src/retrieval/scoring.ts — 토크나이저, TF-IDF, 동의어, 불용어, 충돌 탐지, 캐시
- [S2] ConnectAI/src/retrieval/chunker.ts — 섹션 청킹(순수 함수)
## 📝 변경 이력 (Change history)
- 2026-06-13: ConnectAI 코드 분석 기반 초안 생성.