Context
Every retrieved chunk — on-device documents and web results alike — is wrapped by sourceBlock (utils/contextUtils.ts:88) as:
--- Source 1: <name> ---
<passage>
--- End of Source 1 ---
This delimiter grammar is load-bearing, not decorative:
- the system prompt tells the model sources arrive as
"Source N: <name>" and to cite by it (utils/promptUtils.ts:34-37);
SOURCE_HEADER = /--- [^:]+: (.+?) ---/g (constants/retrieval.ts:60) parses these headers to build the present-in-context source set (sourcesPresentInContext), which drives citation attribution;
- the truncation fallback re-closes the last open block using the
--- markers (utils/promptUtils.ts:171-180).
Idea
Slim the per-block boilerplate to save prompt tokens, which matters on the small on-device model's tight context budget.
Why the naive fix does NOT work
- Swapping the
--- character saves ~0 tokens. --- is ~1 BPE token in the executorch/Llama-Qwen tokenizer; a single replacement char is also ~1 token, and a rarer Unicode char (§, ¶, private-use) can tokenize to 2-3 tokens — i.e. worse.
- The real overhead is the repeated boilerplate per block, above all the explicit
--- End of Source N --- closer: ~4-6 tokens/block, so ~20-48 tokens across a typical 5-8 block prompt.
Touch points that must stay consistent
SOURCE_HEADER regex — constants/retrieval.ts:60
- truncation re-close —
utils/promptUtils.ts:171-180
- system-prompt instruction (
"Source N: <name>") — utils/promptUtils.ts:34-37
neutralizeDelimiters — utils/web/webResultsToContext.ts (the prompt-injection surface moves to the new delimiter, it does not disappear)
- affects doc blocks too, not only web results
How to decide (acceptance)
- Measure tokens before/after with the actual on-device tokenizer on a representative multi-source prompt (current format vs. no-explicit-closer vs. shortened tag).
- Verify citation/grounding attribution does not regress on the small on-device model — that reliability is the whole point of the feature.
- Consider a rarer delimiter (e.g.
⟦Source 1⟧) purely for robustness — page text rarely contains it, shrinking the forgery surface — independent of any token savings.
Non-goals
Not part of the current web-search review-fix PR. The delimiter format spans the whole RAG path (docs + web), so it should ship separately and only on measurements.
Context
Every retrieved chunk — on-device documents and web results alike — is wrapped by
sourceBlock(utils/contextUtils.ts:88) as:This delimiter grammar is load-bearing, not decorative:
"Source N: <name>"and to cite by it (utils/promptUtils.ts:34-37);SOURCE_HEADER = /--- [^:]+: (.+?) ---/g(constants/retrieval.ts:60) parses these headers to build the present-in-context source set (sourcesPresentInContext), which drives citation attribution;---markers (utils/promptUtils.ts:171-180).Idea
Slim the per-block boilerplate to save prompt tokens, which matters on the small on-device model's tight context budget.
Why the naive fix does NOT work
---character saves ~0 tokens.---is ~1 BPE token in the executorch/Llama-Qwen tokenizer; a single replacement char is also ~1 token, and a rarer Unicode char (§,¶, private-use) can tokenize to 2-3 tokens — i.e. worse.--- End of Source N ---closer: ~4-6 tokens/block, so ~20-48 tokens across a typical 5-8 block prompt.Touch points that must stay consistent
SOURCE_HEADERregex —constants/retrieval.ts:60utils/promptUtils.ts:171-180"Source N: <name>") —utils/promptUtils.ts:34-37neutralizeDelimiters—utils/web/webResultsToContext.ts(the prompt-injection surface moves to the new delimiter, it does not disappear)How to decide (acceptance)
⟦Source 1⟧) purely for robustness — page text rarely contains it, shrinking the forgery surface — independent of any token savings.Non-goals
Not part of the current web-search review-fix PR. The delimiter format spans the whole RAG path (docs + web), so it should ship separately and only on measurements.