Replies: 4 comments
|
已在 repo 当前 master( 根因确认(
关键点:这不是"把
或者更窄的修法:汇总调用不传 tools(第 158 行整个省略)——但这也丢掉了"保留 warm-prefix cache"的初衷(注释 111-114 说明 replay 工具 schema 是为了复用 prefix cache)。所以这个 bug 牵涉跨包( 顺手补充一个你能对照的独立证据:与 token-cap(#3201/#3465,Yunado 的分析)确实正交 —— 那个是 output budget 被 reasoning 吃掉、summaryText 仍能找到部分 text;这个则是"模型根本没产出 text",直接命中第 171 行的抛错分支。你的 74/432 出现 25 次、其中 15 次是"3–17s 的工具调用时长"这个取证非常到位,刚好打在这条分支上(而非 400/截断那两条)。 可能的另一层追问(如果你要报 upstream):第 171 行 throw 前, 一句话:缺陷确认、根因在 |
|
Status: CONFIRMED upstream. argszero: "this is a real, reproducible data
We have been running option 2 in production since 2026-09-02, so the cache What we didA The numbers, on one boxLane:
So option 2 costs about 77 s per compaction on this hardware, roughly a It is cheaper than it looks, because the tool RESULTS are the bulkMeasured on a real compaction here, 87% of the summarization request was tool Two things follow for the fix choice:
The failure is silent, which is the part that hurt
Related: #3201, #3465 (token-cap class — different, as you say), #5524 Still present in 0.1.2-rc.1 (checked 2026-09-03)This box upgraded alpha.5 → rc.1 and the defect is unchanged. Checked in the
And rc.1's own source states the cause, which is the neatest confirmation of
So the field genuinely is absent by design today, the summarization call has no |
|
你这个确认非常有价值——production 数据(39% 静默丢摘要、单会话 12 次、87% 请求是 tool results)把 #5521 从"我觉得是缺陷"钉成了"可量化、且被实际运维承受的缺陷"。几点补充: 1. 你的 2. Option 1(toolChoice)根子上对,但确实是跨包改动。 你在 rc.1 里查到的证据( 3. 你"failure path 应记录 raw blocks"的建议我完全同意,且和我最初回复里"抛错前把 rawOutput 记进 compaction/raw 可观测事件"是同一诉求。 现在抛错时 rawOutput 被直接丢弃,用户看到的就是一句笼统的 4. 一个可讨论的延伸:tool-choice 缺字段不只影响 compaction——任何"带 tools 但不应调工具"的合成调用(如 #5521、以及可能的 prompt-diagnostics/评估类调用)都有同类风险。如果 upstream 决定加 一句话:Option 2 是当下正确的权衡, Option 1 是长期正确的修复, 且你的 waterfall 插件方案本身证明了这是插件化可挂载面。如果你愿意, 这个 |
|
Thank you — the Our shim is compaction-only, by construction. Its gate is literally if (!options || options.purpose !== COMPACTION_PURPOSE) return { action: 'pass' }so it does nothing for any other synthetic call that carries tools and must Confirming your master reading against the shipped rc.1, so the evidence
— and On logging On packaging the shim as a plugin — done, and thank you for the nudge.
Zero dependencies, nothing imported from The README says three things I want to be explicit about here too, because a
If any of the framing there misrepresents the harness's behaviour, tell me and One correction to my own earlier numbers, in the interest of not leaving a bad |
Uh oh!
There was an error while loading. Please reload this page.
Summary
compaction-basicsends the conversation's tool schemas on the summarizationcall and sets no tool choice. A tool-capable model, deep in a session where
every turn has been a tool call, answers the "compaction engine" instruction with
another tool call.
summaryText()keeps onlytextblocks, finds none, andthrows
summarization produced no text summary content— and the raw output isnever logged, so nothing downstream can say why.
This is a different failure from the token-cap one in #3201 / #3465 (that one is
reasoning eating the 8,192-token output budget, and Yunado's analysis there
matches what I measured too). Both can happen on the same model.
Evidence
74 compactions across 432 sessions,
qwen3.8-27b(Q5_K_XL) via llama.cpp b10751on an OpenAI-compatible endpoint, dsh 0.1.2-alpha.5. 25 produced no summary:
compaction/enderrorsummarization produced no text summary content400 status code (no body)summarization truncated at the token capsummary is not smaller than the shadowed contentpi-ai stream idle timeout after 300000msI put a capture proxy in front of the endpoint to see the request itself. The
summarization call:
The short durations are the tell: 3–17 s is a tool call being emitted, not 2,900
tokens of summary being written (a successful one on the same lane takes 131 s).
Where it comes from
buildSummarizationInput()reconstructs "the last routed request's cacheableprefix: its system prompt and tool schemas", and
summarizeWithLlm()streamswith
tools: [...input.tools]. That is deliberate and reasonable — it keeps thecall a genuine prefix so the provider's KV cache is reused. The gap is only that
nothing tells the model not to use them.
Why it is easy to misread
It retries at every step, so the context keeps growing until the provider rejects
the request outright. From the outside it looks like a context-length problem.
Suggested fix
Either would do:
toolChoice: "none"on the summarization call. Best outcome: the promptstays a cache prefix (no re-prefill) and a text answer is certain. It needs
plumbing —
GenerateOptionshas notoolChoiceanddsh-llm-pi-aibuildsthe pi-ai options field by field — though pi-ai itself already maps
options.toolChoiceontotool_choice.naming what came back instead of text turns weeks of silent loss into an
obvious diagnosis.
Workaround, if it helps anyone before then
A dependency-free plugin on the
llm/streamwaterfall that deletestoolsfromcalls whose
purposeis"compaction":Loaded by
file://URL from acordis.patch.ymlrow. It works — 100% ofcompactions have produced summaries since — but it costs a full re-prefill of
the condensed region, because the schemas sit inside the system region of Qwen's
template: about two minutes per compaction here.
toolChoice: "none"upstreamwould avoid that cost entirely.
All reactions