purpose
planEmbeddingBatches の予算軸を UTF-16 code unit から UTF-8 バイト数へ移す。#241 が根拠にした tokens <= chars は成り立っておらず、実測で破れている。
observation(2026-08-15 00:30 JST cron、#242 deploy 後)
Failed to batch-embed diffs for Liplus-Project/neuron-graph-rag@92eb94dcb88c5e7494bc3b69377249e08601d99f
chunk offset 0: 3030: Max context reached 68736 tokens but model supports only 60000
| 項目 |
値 |
| file 数 |
16(#240 の file 予算により 44 から分割済み) |
| batch |
chunk offset 0 のみ = 1 batch |
| planner が課金した文字数 |
<= 60,000(MAX_EMBEDDING_BATCH_CHARS) |
| 実測 token |
68,736 |
したがって tokens / chars >= 1.146。トークン数が文字数を超えている。
#242 が deploy されていることは確認済み: file 数が 44 -> 16 に変わり、token 実測値も過去(85,920 / 60,678 / 64,413)と異なる新しい値になっている。旧コードが動いている可能性は排除される。
原因
#241 / #242 が置いた前提はこれ。
every token of a BPE or SentencePiece vocabulary spans at least one character of the input
⟹ tokens(input) <= input.length + SPECIAL_TOKENS_PER_INPUT
byte_fallback で破れる。 語彙に無い文字は UTF-8 バイト列へ分解され、1 文字が複数 token になる。日本語 1 文字(3 バイト)は最大 3 token。実測の 1.146 倍という超過は、内容の一部がこの経路に落ちていることと整合する。
方針:バイト数で縛る
1 token は最低 1 バイトを消費する。 byte_fallback が最も細かい分解であり、それ以下には割れない。したがって
1 batch の合計 UTF-8 バイト数 <= 60,000 - (special token 分)
⟹ 合計 token 数 <= 60,000 (無条件に成立)
#241 が求めた「校正しない、構成上正しい」という性質を保ったまま、軸を 1 つ下げるだけで直る。文字数軸が満たせなかったのは、文字と token の対応が 1:1 以上であるという前提が偽だったためであり、バイトと token の対応にはその問題が無い。
コスト: 日本語主体の入力では 1 文字 3 バイトのため、文字数軸に比べ約 3 倍保守的になる。batch 数が増える。これは正しさの代金として受け入れる。#240 の file 予算(DIFF_SUBREQUESTS_PER_FILE = 3 は 1 batch あたり 3 file 以上を前提に amortised cost を見積もっている)との整合を確認すること。
constraints
target files
src/pipeline/embedding.ts — 予算軸をバイト数へ
src/pipeline/embedding.test.ts — 契約テストの更新、非 ASCII を含む回帰ケース
src/pipeline/embed-diff.test.ts — 分割ケースの期待値
src/poller.ts — DIFF_SUBREQUESTS_PER_FILE の前提が変わる場合
docs/0-requirements.md / docs/0-requirements.ja.md
acceptance
経緯
#236(token 予算・推定器)、#238(subrequest / file 予算)、#241(文字数軸)に続く 4 周目。#236 の受け入れ条件「watermark が boundary commit を越える」は一度も満たされていない。3 回とも、境界の根拠が実測より楽観的だったことが原因である。今回はバイト数という測定可能な下界を使うため、同じ形での再発は起きない。
purpose
planEmbeddingBatchesの予算軸を UTF-16 code unit から UTF-8 バイト数へ移す。#241 が根拠にしたtokens <= charsは成り立っておらず、実測で破れている。observation(2026-08-15 00:30 JST cron、#242 deploy 後)
chunk offset 0のみ = 1 batchMAX_EMBEDDING_BATCH_CHARS)したがって
tokens / chars >= 1.146。トークン数が文字数を超えている。#242 が deploy されていることは確認済み: file 数が 44 -> 16 に変わり、token 実測値も過去(85,920 / 60,678 / 64,413)と異なる新しい値になっている。旧コードが動いている可能性は排除される。
原因
#241 / #242 が置いた前提はこれ。
byte_fallback で破れる。 語彙に無い文字は UTF-8 バイト列へ分解され、1 文字が複数 token になる。日本語 1 文字(3 バイト)は最大 3 token。実測の 1.146 倍という超過は、内容の一部がこの経路に落ちていることと整合する。
方針:バイト数で縛る
1 token は最低 1 バイトを消費する。 byte_fallback が最も細かい分解であり、それ以下には割れない。したがって
#241 が求めた「校正しない、構成上正しい」という性質を保ったまま、軸を 1 つ下げるだけで直る。文字数軸が満たせなかったのは、文字と token の対応が 1:1 以上であるという前提が偽だったためであり、バイトと token の対応にはその問題が無い。
コスト: 日本語主体の入力では 1 文字 3 バイトのため、文字数軸に比べ約 3 倍保守的になる。batch 数が増える。これは正しさの代金として受け入れる。#240 の file 予算(
DIFF_SUBREQUESTS_PER_FILE = 3は 1 batch あたり 3 file 以上を前提に amortised cost を見積もっている)との整合を確認すること。constraints
WORKERS_AI_BATCH_CONTEXT_LIMIT = 60000は天井の記録として維持DIFF_SUBREQUESTS_PER_FILEの前提が崩れていないか確認し、崩れるなら同一 PR で調整するdocs/0-requirements.md/docs/0-requirements.ja.md)を同一 PR で更新するtarget files
src/pipeline/embedding.ts— 予算軸をバイト数へsrc/pipeline/embedding.test.ts— 契約テストの更新、非 ASCII を含む回帰ケースsrc/pipeline/embed-diff.test.ts— 分割ケースの期待値src/poller.ts—DIFF_SUBREQUESTS_PER_FILEの前提が変わる場合docs/0-requirements.md/docs/0-requirements.ja.mdacceptance
1fb0f6b397c1ff333d698fe58a862b9583b463fe(18 file)と92eb94dcb88c5e7494bc3b69377249e08601d99f(44 file)が embed に成功するneuron-graph-ragの forward watermark が2026-08-11T15:33:02Zを越えて前進する経緯
#236(token 予算・推定器)、#238(subrequest / file 予算)、#241(文字数軸)に続く 4 周目。#236 の受け入れ条件「watermark が boundary commit を越える」は一度も満たされていない。3 回とも、境界の根拠が実測より楽観的だったことが原因である。今回はバイト数という測定可能な下界を使うため、同じ形での再発は起きない。