目的
「思想のわりに検索結果がいまいち」という体感に対し、本番で実測できた具体的な原因を 2 件記録する。どちらも graph 層とも拡張の積み重ねとも独立した、単独で効いている要因。
確認済みの事実 1 — 日本語クエリで sparse 側が機能していない
本番 MCP に対し fusion を切り替えて同一クエリを実行した。
| クエリ |
fusion |
sparse_candidates |
dense_candidates |
判断の記録は状態形式で書く |
sparse_only |
0 |
0 |
判断の記録は状態形式で書く |
dense_only |
0 |
5 |
decision structure write skill(英語) |
sparse_only |
3 |
0 |
判断(単語 1 つ) |
sparse_only |
3 |
0 |
英語クエリと日本語 1 語は sparse で引ける。日本語の句になった途端 0 になる。
原因は migrations/0001_fts5_init.sql の自然文側トークナイザ。
tokenize = 'porter unicode61 remove_diacritics 2',
unicode61 は日本語の語境界を分割せず、空白・句読点で区切られるまでの仮名漢字の連なりを 1 トークンとして扱う。porter は英語ステマーなので日本語には作用しない。結果として、日本語文書は「区切り記号で挟まれた塊」単位でしか索引されず、句としてのクエリは完全一致しない限り当たらない。
影響: wiki / docs / issue 本文 / PR 本文は大半が日本語。それらに対する日本語クエリでは hybrid が実質 dense 単独で動いており、RRF に融合する相手がいない。設計上は BM25 + dense の二本立てだが、日本語では一本しか立っていない。
なお diff 側の search_docs_code_fts は trigram なので日本語でも部分一致が効く。壊れているのは自然文側だけ。
確認済みの事実 2 — top-k が同一ファイルの重複で埋まる
上記 dense_only の 5 件の内訳:
| rank |
type |
実体 |
| 1 |
diff |
skills/evolution-decision-structure-write/SKILL.md (2df5052) |
| 2 |
diff |
docs/5.-Notifications.md (4e4f22a) |
| 3 |
doc |
skills/evolution-decision-structure-write/SKILL.md |
| 4 |
diff |
docs/F.-Behavior-First.md (4e4f22a) |
| 5 |
diff |
skills/evolution-decision-structure-write/SKILL.md (601aa38) |
5 枠のうち 3 枠が同一ファイル(doc 1 + 別コミットの diff 2)。同じ内容が doc surface と複数の diff リビジョンとして別行で索引され、同一プールで順位を争っている。
dense_score も 0.585 / 0.577 / 0.573 / 0.572 / 0.571 と平坦で、順位の分離がほとんど起きていない。
影響: top_k の数字ほど情報の幅がない。呼び出し側から見た実効的な多様性は名目の半分以下になりうる。
制約
- 記録が目的。ここでは修正方針を確定しない
- 事実 1 と 事実 2 は原因も対処も別軸なので、着手時は分割する
想定変更箇所
- 事実 1:
migrations/0001_fts5_init.sql の自然文側トークナイザ、および再索引経路
- 事実 2:
src/mcp.ts の融合・整列段(同一実体の集約規則)
備考
この 2 件はどちらも retrieval のランキング以前の層にある。グラフ伝播や結合重みの学習を上に載せても解消しない。検索エンジンの比較検証を行う場合、この 2 点を揃えないと比較条件が成立しない点に注意。
目的
「思想のわりに検索結果がいまいち」という体感に対し、本番で実測できた具体的な原因を 2 件記録する。どちらも graph 層とも拡張の積み重ねとも独立した、単独で効いている要因。
確認済みの事実 1 — 日本語クエリで sparse 側が機能していない
本番 MCP に対し
fusionを切り替えて同一クエリを実行した。判断の記録は状態形式で書くsparse_only判断の記録は状態形式で書くdense_onlydecision structure write skill(英語)sparse_only判断(単語 1 つ)sparse_only英語クエリと日本語 1 語は sparse で引ける。日本語の句になった途端 0 になる。
原因は
migrations/0001_fts5_init.sqlの自然文側トークナイザ。unicode61は日本語の語境界を分割せず、空白・句読点で区切られるまでの仮名漢字の連なりを 1 トークンとして扱う。porterは英語ステマーなので日本語には作用しない。結果として、日本語文書は「区切り記号で挟まれた塊」単位でしか索引されず、句としてのクエリは完全一致しない限り当たらない。影響: wiki / docs / issue 本文 / PR 本文は大半が日本語。それらに対する日本語クエリでは hybrid が実質 dense 単独で動いており、RRF に融合する相手がいない。設計上は BM25 + dense の二本立てだが、日本語では一本しか立っていない。
なお diff 側の
search_docs_code_ftsはtrigramなので日本語でも部分一致が効く。壊れているのは自然文側だけ。確認済みの事実 2 — top-k が同一ファイルの重複で埋まる
上記
dense_onlyの 5 件の内訳:skills/evolution-decision-structure-write/SKILL.md(2df5052)docs/5.-Notifications.md(4e4f22a)skills/evolution-decision-structure-write/SKILL.mddocs/F.-Behavior-First.md(4e4f22a)skills/evolution-decision-structure-write/SKILL.md(601aa38)5 枠のうち 3 枠が同一ファイル(doc 1 + 別コミットの diff 2)。同じ内容が doc surface と複数の diff リビジョンとして別行で索引され、同一プールで順位を争っている。
dense_score も 0.585 / 0.577 / 0.573 / 0.572 / 0.571 と平坦で、順位の分離がほとんど起きていない。
影響:
top_kの数字ほど情報の幅がない。呼び出し側から見た実効的な多様性は名目の半分以下になりうる。制約
想定変更箇所
migrations/0001_fts5_init.sqlの自然文側トークナイザ、および再索引経路src/mcp.tsの融合・整列段(同一実体の集約規則)備考
この 2 件はどちらも retrieval のランキング以前の層にある。グラフ伝播や結合重みの学習を上に載せても解消しない。検索エンジンの比較検証を行う場合、この 2 点を揃えないと比較条件が成立しない点に注意。