From f2a76cfe9404ceb94b3c37710c8fb7d696c14957 Mon Sep 17 00:00:00 2001 From: altair823 Date: Thu, 28 May 2026 13:22:43 +0000 Subject: [PATCH] docs(dogfood): V009 morphological tokenizer scenarios + fixture evidence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- docs/DOGFOOD.md | 75 +++++++++++++++++++++++++++++++++++++++++++------ docs/SMOKE.md | 36 +++++++++++++----------- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/docs/DOGFOOD.md b/docs/DOGFOOD.md index e38b894..557745e 100644 --- a/docs/DOGFOOD.md +++ b/docs/DOGFOOD.md @@ -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 : `). -- 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 : `). +- 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) diff --git a/docs/SMOKE.md b/docs/SMOKE.md index 24d261f..22198f2 100644 --- a/docs/SMOKE.md +++ b/docs/SMOKE.md @@ -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