feat(v0.20.1): 한국어 morphological tokenizer (V009) + N-gram supplement + eager backfill #191
@@ -285,16 +285,75 @@ echo "# stdin content" | "$RELEASE_BIN" ingest-stdin --title "from stdin" --conf
|
||||
```
|
||||
|
||||
**verify**:
|
||||
- FTS5 trigram (v0.17.0) — 한국어 2자 이상 query hit.
|
||||
- `chunks_fts` schema (`text`, `heading_path` 별 column).
|
||||
- FTS5 `unicode61` + lindera ko-dic 형태소 분해 column (v0.20.1, V009 migration).
|
||||
- `chunks_fts` schema (`text`, `heading_path` 별 column) — V009 의 chunks_ai/au trigger 가 `tokenized_korean_text` 를 CASE expression 으로 raw text 앞에 prepend.
|
||||
- 한국어 2-char query (`한국`, `서울`) 가 chunk 의 ko-dic 분해된 morpheme 또는 explicit 공백 분리된 token 과 일치 시 hit.
|
||||
- 영어는 V002 의 whole-token 매칭으로 회귀 (`token` query 는 `token` 토큰만 hit, `tokenizer` substring 은 hit X). substring recall 이 필요하면 vector/hybrid mode 권장.
|
||||
|
||||
**scenarios**:
|
||||
- 2.1.a Korean trigram query (`해시 충돌`).
|
||||
- 2.1.b English/Korean mixed (`Rust 충돌`).
|
||||
- 2.1.c 1-char query → 0 hit + hint.
|
||||
- 2.1.d raw mode escape (`heading_path : <token>`).
|
||||
- 2.1.e FTS5 phrase query (`"specific phrase"`).
|
||||
- 2.1.f exclusion (`-token`).
|
||||
- 2.1.a Korean 2-char query (`한국`, `서울` → ≥ 1 hit on Korean wiki fixture).
|
||||
- 2.1.b Korean compound noun (`한국어`, `서울특별시` → ko-dic 의 형태소 분해 + 단일 noun 동시 매칭).
|
||||
- 2.1.c English/Korean mixed (`Rust 최적화` → token-AND 두 토큰 모두 hit).
|
||||
- 2.1.d 1-char query → 0 hit (MIN_QUERY_CHARS = 2 filter, `build_match_string` v0.20.1 갱신).
|
||||
- 2.1.e English whole-token (`tokenizer` hit, `token` 은 `tokenizer` 의 substring 매칭 X — V007 trigram 회귀).
|
||||
- 2.1.f raw mode escape (`heading_path : <token>`).
|
||||
- 2.1.g FTS5 phrase query (`"specific phrase"`).
|
||||
- 2.1.h exclusion (`-token`).
|
||||
|
||||
### §2.1bis V009 morphological tokenizer dogfood evidence (v0.20.1)
|
||||
|
||||
**Reference corpus** (이 fixture 로 ingest 시 모든 scenario 보장 hit):
|
||||
|
||||
```bash
|
||||
mkdir -p $DOGFOOD/corpus
|
||||
cat > $DOGFOOD/corpus/korea-overview.md <<'EOF'
|
||||
# 한국 개요
|
||||
|
||||
한국 은 동아시아 의 반도 국가다. 한국 어 는 한반도 의 주요 언어다.
|
||||
서울 은 한국 의 수도다. 서울 의 지하철 은 1974년 1호선 개통 후
|
||||
지금까지 23개 노선으로 확장되었다.
|
||||
|
||||
## 한국 문화
|
||||
|
||||
한국 의 문화 는 오래 된 역사 와 깊은 전통 을 가진다.
|
||||
EOF
|
||||
|
||||
cat > $DOGFOOD/corpus/korea-compound.md <<'EOF'
|
||||
# 한국어 와 한국문화
|
||||
|
||||
한국어 학습 자료. 한국문화 의 핵심 은 정 (情) 이다.
|
||||
서울특별시 와 부산광역시 는 한국 의 양대 도시다.
|
||||
EOF
|
||||
```
|
||||
|
||||
**검증 명령** (모두 hit ≥ 1):
|
||||
|
||||
```bash
|
||||
KB="$RELEASE_BIN --config $DOGFOOD/config.toml"
|
||||
|
||||
# 한국어 2-char (Bug #8 close, v0.20.1 의 핵심 가치)
|
||||
$KB search '한국' --mode lexical --json | jq '.hits | length' # ≥ 1
|
||||
$KB search '서울' --mode lexical --json | jq '.hits | length' # ≥ 1
|
||||
|
||||
# 한국어 3-char + compound noun
|
||||
$KB search '지하철' --mode lexical --json | jq '.hits | length' # ≥ 1
|
||||
$KB search '한국어' --mode lexical --json | jq '.hits | length' # ≥ 1
|
||||
$KB search '한국문화' --mode lexical --json | jq '.hits | length' # ≥ 1
|
||||
$KB search '서울특별시' --mode lexical --json | jq '.hits | length' # ≥ 1
|
||||
|
||||
# 영어 whole-token (V002 동작 회귀)
|
||||
$KB search 'token' --mode lexical --json | jq '.hits | length' # 0 또는 별 token 으로 존재 시 hit
|
||||
$KB search 'tokenizer' --mode lexical --json | jq '.hits | length' # ≥ 1 if corpus has 'tokenizer' word
|
||||
```
|
||||
|
||||
**예상 snippet (lindera 분해 evidence)**:
|
||||
- `'한국'` query → "한국 은 동아시아 의 반 도 국가 다" — ko-dic 의 명사 boundary + 조사 분리 확인.
|
||||
- `'서울'` query → "서울특별시 와" — ko-dic 의 compound `서울특별시` → `[서울, 특별시]` 분해.
|
||||
|
||||
**Known limitation (spec critic R1 #3 acceptance, Option α)**:
|
||||
- ko-dic 이 compound noun 을 단일 token 으로 저장하는 경우 (예: `한국정부` 가 한 token) → `'한국'` query 는 그 chunk 에 hit X.
|
||||
- KB 가 영어/code 위주 (예: 사용자 KnowledgeBase 가 React docs) 면 한국어 token 자체 부재로 0 hit 정상.
|
||||
- N-gram supplement (Option β) 는 v0.21.x P9 follow-up.
|
||||
|
||||
### §2.2 Vector search (P3)
|
||||
|
||||
|
||||
@@ -176,36 +176,38 @@ KB ask "이 KB 안에서 ..." --mode hybrid --k 5 # 9. RAG 답변 (Ollama
|
||||
KB --json ask "..." --mode hybrid # 10. 기계 친화 출력 검증
|
||||
```
|
||||
|
||||
### 한국어 trigram 검색 (v0.17.0)
|
||||
### 한국어 morphological 검색 (v0.20.1)
|
||||
|
||||
`chunks_fts` 가 FTS5 `trigram` tokenizer 로 동작 — 한국어 query 는 3자 이상 substring 매칭. V007 자동 backfill 이라 기존 KB 의 binary 만 v0.17.0+ 로 교체하면 즉시 적용 (re-ingest 불필요). `kebab.sqlite` 파일 크기가 trigram index 비대화로 ~2-5배 또는 수백 MB 증가.
|
||||
`chunks_fts` 가 FTS5 `unicode61` tokenizer + 한국어 lindera ko-dic 형태소 분해된 별 column (`tokenized_korean_text`) 으로 동작 (V009 migration). 한국어 2-char query (`한국`, `서울`) 도 ko-dic morpheme 매칭 시 hit. V009 자동 backfill (`App::open_with_config` 의 first-boot hook) 이라 기존 KB 의 binary 만 v0.20.1+ 로 교체하면 첫 부팅에서 자동 재-tokenize (re-ingest 불필요). `kebab.sqlite` 파일 크기가 형태소 column + lindera-ko-dic embedded dict 의존성으로 다소 증가.
|
||||
|
||||
`fixtures/search/korean/hash-table.md` (또는 등가) 를 워크스페이스에 두고 ingest 한 후:
|
||||
|
||||
```bash
|
||||
# 3자 연속 substring (raw, 원문에 "해시 충돌은" / "충돌은 발생" 가 있음)
|
||||
KB search --mode lexical "충돌은"
|
||||
# 2-char Korean (v0.20.1 의 핵심 가치 — Bug #8 close)
|
||||
KB search --mode lexical "한국"
|
||||
KB search --mode lexical "서울"
|
||||
|
||||
# multi-token Korean — builder 가 ("해시 충돌") OR ("해시" "충돌") 으로
|
||||
# 변환 (각 토큰 2자라 token-AND 후보는 trigram 비호환, whole-phrase 가 hit)
|
||||
# 3-char Korean
|
||||
KB search --mode lexical "한국어"
|
||||
KB search --mode lexical "지하철"
|
||||
|
||||
# Compound noun (ko-dic 가 형태소 분해 — '서울특별시' → [서울, 특별시])
|
||||
KB search --mode lexical "서울특별시"
|
||||
|
||||
# multi-token Korean
|
||||
KB search --mode lexical "해시 충돌"
|
||||
|
||||
# 한영 혼합 — 둘 다 3자 이상이라 whole-phrase + token-AND 모두 후보
|
||||
KB search --mode lexical "Rust 충돌은"
|
||||
# 한영 혼합
|
||||
KB search --mode lexical "Rust 최적화"
|
||||
|
||||
# 2자 query — 정상 0 hit + stderr `[hint] 3자 이상 키워드 권장`
|
||||
KB search --mode lexical "충돌"
|
||||
# 1자 query — `build_match_string` 의 MIN_QUERY_CHARS=2 filter 로 0 hit
|
||||
KB search --mode lexical "키"
|
||||
|
||||
# 동일 케이스의 --json 출력에는 search_response.v1.hint 필드 포함
|
||||
KB search --mode lexical "충돌" --json | jq '.hits | length, .hint'
|
||||
# → 0
|
||||
# → "3자 이상 키워드 권장 (trigram tokenizer 제약)"
|
||||
|
||||
# raw FTS5 mode (single quote 로 감싼 입력) — 사용자 명시 의도, hint 미출력
|
||||
# raw FTS5 mode
|
||||
KB search --mode lexical "'충돌'"
|
||||
```
|
||||
|
||||
영어 lexical 도 substring 매칭으로 바뀜 — `KB search --mode lexical "token"` 이 `tokenizer` / `tokenize` 도 hit (recall ↑, 단어 경계 정밀도 ↓).
|
||||
영어 lexical 은 V002 의 whole-token 매칭으로 회귀 — `KB search --mode lexical "token"` 은 `token` 토큰만 hit, `tokenizer` 의 substring 으로 매칭 X. substring recall 이 필요하면 vector/hybrid mode 권장 (spec §3 Non-Goals Path A).
|
||||
|
||||
### Stale doc indicator
|
||||
|
||||
|
||||
Reference in New Issue
Block a user