docs(dogfood): V009 morphological tokenizer scenarios + fixture evidence

v0.20.1 dogfood verification 의 fixture + scenario 를 DOGFOOD.md /
SMOKE.md 에 반영. 사용자 KnowledgeBase 같은 영어/code 중심 KB 에서
한국어 0-hit 가 정상 (token 부재) 임을 명시하고, ko-dic 의 morpheme
분해 동작을 검증할 reference fixture (korea-overview.md +
korea-compound.md) 를 inline 으로 제공.

DOGFOOD.md §2.1 갱신:
- description: trigram → unicode61 + 형태소 column.
- scenarios: 한국어 2-char (한국, 서울) + compound noun (서울특별시) +
  영어 whole-token 회귀 + 1-char filter 등 7 case 로 확장.
- §2.1bis 신규: V009 dogfood evidence reference corpus + 검증 명령 +
  예상 snippet (lindera 분해 증거) + known limitation (ko-dic
  compound 단일 token 정책, Option α acceptance).

SMOKE.md 'V009 morphological 검색' 갱신:
- trigram 시절 hint advisory + 3자 키워드 권장 시나리오 제거.
- v0.20.1 의 2-char Korean / compound noun / 1-char filter / 영어
  whole-token 회귀 scenario 로 교체.

Reference fixture (실측 verify pass):
- korea-overview.md: '한국' / '서울' / '지하철' 모두 hit.
- korea-compound.md: '한국어' / '한국문화' / '서울특별시' compound hit.

Spec: docs/superpowers/specs/2026-05-28-v0.20.x-korean-morphological-tokenizer-spec.md §9
Plan: docs/superpowers/plans/2026-05-28-v0.20.x-korean-morphological-tokenizer-plan.md (dogfood evidence)
This commit is contained in:
2026-05-28 13:22:43 +00:00
parent 8c56ef3010
commit f2a76cfe94
2 changed files with 86 additions and 25 deletions

View File

@@ -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)

View File

@@ -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