purpose
estimateEmbeddingTokens の推定が実測の半分以下になっており、#237 で入れた token 予算が機能していない。推定をやめ、文字数 で上限を引く形に置き換える。
observation(2026-08-14 16:31 JST cron、#240 merge 後)
MAX_EMBEDDING_BATCH_TOKENS = 30000(#237 )が効いているはずの状況で、次の 2 commit が chunk offset 0 の単一 batch のまま天井を超えている。
commit
file 数
batch
推定
実測
1fb0f6b397c1ff333d698fe58a862b9583b463fe
18
offset 0 のみ(分割されず)
<= 30,000
60,678
bdf8b62bfc8cc88944d342ab0cefc1f544edfa5c
17
offset 0 のみ(分割されず)
<= 30,000
64,413
3030: Max context reached 60678 tokens but model supports only 60000
3030: Max context reached 64413 tokens but model supports only 60000
過小評価の倍率は約 2.02x と約 2.15x。#237 が採った 2x margin では足りていない 。
この 2 値は #237 merge 前(14:31 の cron)の実測値と同一である。同じ commit が同じ実測 token 数を出し続けており、推定が 30,000 以下と判断して 1 batch に載せている。つまり #237 の token 予算はこの 2 commit に対して一度も効いていない。
44 file の 92eb94d は #240 の file 予算(18/phase)により deferred となり、この cron では試行されていない。
原因
src/pipeline/embedding.ts の ASCII_CHARS_PER_TOKEN = 3。
bge-m3 は XLM-RoBERTa SentencePiece 語彙を使い、英語散文では約 4 文字/token、句読点の多いソースでは約 3 文字/token という前提で 3 を採った。しかし diff patch の実測は約 1.4 文字/token である。+ / - 接頭、インデント、記号、短い識別子が並ぶため、SentencePiece が極端に短い token を大量に生成する。
prepareDiffEmbeddingInput が commit message を全 file 入力の先頭に複製する構造も分母を押し上げる(#236 で指摘済み、未修正)。
推定器の校正で追いかける限り、次に想定外の payload が来たときに同じ形で破れる。破れ方は「chunk 全体 failed → #178 不変条件により watermark 恒久停止」であり、コストが高い。
方針:推定をやめ、文字数で縛る
token は入力の 1 文字以上を消費する。 BPE / SentencePiece のいずれでも、1 token が 0 文字に対応することはない。したがって
1 batch の合計文字数 <= 60,000 - (special token 分の小さな定数)
==> 合計 token 数 <= 60,000 (無条件に成立)
校正が不要になる。payload の性質・言語・記号密度に依存しない。tokenizer が Worker 内で利用できないという制約とも整合する(そもそも推定しない)。
副作用の確認:
constraints
推定関数(estimateEmbeddingTokens)を残さない。残せば校正の議論が別の場所に残る
WORKERS_AI_BATCH_CONTEXT_LIMIT = 60000 は天井の記録として維持する。文字数上限の根拠として参照する
単独で上限を超える入力(8000 文字は 60,000 未満なので現状では発生しないが)は fix(pipeline): batch-embed diffs by token budget, not file count [pipeline, docs, tests] #237 と同じく 1 件の batch として送る。欠落させない、無限ループさせない
入力の順序保持と、input 配列 / file 配列を同じ境界で切る契約は変更しない
MAX_EMBEDDING_INPUT_CHARS と新しい batch 上限の関係(batch 上限 / 入力上限 = 最小 file 数)を test で押さえる
要件記述(docs/0-requirements.md / docs/0-requirements.ja.md)を同一 PR で更新する
target files
src/pipeline/embedding.ts — estimateEmbeddingTokens / ASCII_CHARS_PER_TOKEN を退役、planEmbeddingBatches を文字数基準へ
src/pipeline/embedding.test.ts — 推定器のテストを退役、文字数上限の契約テストへ
src/pipeline/embed-diff.test.ts — 分割ケースの期待値更新
docs/0-requirements.md / docs/0-requirements.ja.md — Embedding Pipeline 節
acceptance
経緯
#236 で token 軸を、#238 で subrequest 軸を扱った。本 issue は #236 の修正が推定器の精度不足により機能していなかった ことを扱う。#236 の受け入れ条件「watermark が boundary commit を越える」は本 issue の解決まで開いたままである。
purpose
estimateEmbeddingTokensの推定が実測の半分以下になっており、#237 で入れた token 予算が機能していない。推定をやめ、文字数で上限を引く形に置き換える。observation(2026-08-14 16:31 JST cron、#240 merge 後)
MAX_EMBEDDING_BATCH_TOKENS = 30000(#237)が効いているはずの状況で、次の 2 commit がchunk offset 0の単一 batch のまま天井を超えている。1fb0f6b397c1ff333d698fe58a862b9583b463febdf8b62bfc8cc88944d342ab0cefc1f544edfa5c過小評価の倍率は約 2.02x と約 2.15x。#237 が採った 2x margin では足りていない。
この 2 値は #237 merge 前(14:31 の cron)の実測値と同一である。同じ commit が同じ実測 token 数を出し続けており、推定が 30,000 以下と判断して 1 batch に載せている。つまり #237 の token 予算はこの 2 commit に対して一度も効いていない。
44 file の
92eb94dは #240 の file 予算(18/phase)によりdeferredとなり、この cron では試行されていない。原因
src/pipeline/embedding.tsのASCII_CHARS_PER_TOKEN = 3。bge-m3 は XLM-RoBERTa SentencePiece 語彙を使い、英語散文では約 4 文字/token、句読点の多いソースでは約 3 文字/token という前提で 3 を採った。しかし diff patch の実測は約 1.4 文字/token である。
+/-接頭、インデント、記号、短い識別子が並ぶため、SentencePiece が極端に短い token を大量に生成する。prepareDiffEmbeddingInputが commit message を全 file 入力の先頭に複製する構造も分母を押し上げる(#236 で指摘済み、未修正)。推定器の校正で追いかける限り、次に想定外の payload が来たときに同じ形で破れる。破れ方は「chunk 全体 failed → #178 不変条件により watermark 恒久停止」であり、コストが高い。
方針:推定をやめ、文字数で縛る
token は入力の 1 文字以上を消費する。 BPE / SentencePiece のいずれでも、1 token が 0 文字に対応することはない。したがって
校正が不要になる。payload の性質・言語・記号密度に依存しない。tokenizer が Worker 内で利用できないという制約とも整合する(そもそも推定しない)。
副作用の確認:
MAX_EMBEDDING_INPUT_CHARS = 8000文字で truncate されるため、1 batch は 7 入力以上を保持するDIFF_SUBREQUESTS_PER_FILE = 3は「1 batch が 3 file 以上を保持する」前提で amortised batch cost を 1/file と見積もっている。7 file/batch ならその見積りより良い側に振れるため、fix(poller): cap diff-path files per run against the subrequest budget [poller, pipeline, docs, tests] #240 の予算は維持されるconstraints
estimateEmbeddingTokens)を残さない。残せば校正の議論が別の場所に残るWORKERS_AI_BATCH_CONTEXT_LIMIT = 60000は天井の記録として維持する。文字数上限の根拠として参照するMAX_EMBEDDING_INPUT_CHARSと新しい batch 上限の関係(batch 上限 / 入力上限 = 最小 file 数)を test で押さえるdocs/0-requirements.md/docs/0-requirements.ja.md)を同一 PR で更新するtarget files
src/pipeline/embedding.ts—estimateEmbeddingTokens/ASCII_CHARS_PER_TOKENを退役、planEmbeddingBatchesを文字数基準へsrc/pipeline/embedding.test.ts— 推定器のテストを退役、文字数上限の契約テストへsrc/pipeline/embed-diff.test.ts— 分割ケースの期待値更新docs/0-requirements.md/docs/0-requirements.ja.md— Embedding Pipeline 節acceptance
1fb0f6b/bdf8b62)が embed に成功するneuron-graph-ragの forward watermark が1fb0f6bを越えて前進する経緯
#236 で token 軸を、#238 で subrequest 軸を扱った。本 issue は #236 の修正が推定器の精度不足により機能していなかったことを扱う。#236 の受け入れ条件「watermark が boundary commit を越える」は本 issue の解決まで開いたままである。