Repository navigation
Replies: 4 comments
|
Confirmed on The count is genuinely unbounded. /**
* Maximum base64-encoded image payload per request. When a request's
* accumulated images exceed it, the oldest images are replaced by text
* placeholders until the request fits, so a long session keeps completing
* requests instead of being rejected by a request-size cap.
*/
maxRequestImageBytes?: numberand the policy actually handed to the converter, maxRequestImageBytes: profile.maxRequestImageBytes,
requestImagePolicy: {
maxPixels: profile.requestImagePixelBudget,
maxBytes: profile.requestImageMaxBytes,
},Three bounds, all of them size-shaped — per-request bytes, per-image pixels, per-image bytes. Nothing counts images. The part worth leading with: the offload loop you want already exists. That doc comment is describing implemented behaviour, not an aspiration — when the byte bound is crossed the oldest images are already replaced by text placeholders. So a count bound is a second predicate inside a loop that is already trimming oldest-first, at the single site On the alternative: treating the 400 as retryable would contradict the documented intent. One thing to say out loud in the report: the 8-image ceiling belongs to the backend, not to DSH, and DSH has no way to discover it. So a fixed |
|
Same lock-up on What was observedAn Turn 1 failed at step 57 (the step that pushed the history to 31); the next two turns failed at step 1 with the identical message. Failed turns contribute nothing to history, so the same 31 images are re-sent forever — the session is dead, and retrying cannot help. Same end state as the report above, independent of protocol. The byte bound was nowhere near firingAt failure the session held 32 image blocks, ~14.2 MiB of base64 total — under the 20 MiB default This is a second data point for leading with count: on screenshot/PNG-heavy sessions the byte bound is a poor proxy. Here the average was ~450 KB of base64 per image, so the 20 MiB default tolerates ~45 images — 1.5× past a 30-image cap, and ~5.6× past the 8-image cap in the original report. The bound is off in both directions depending on image shapes, which is the same argument as making it provider-configurable. "Trim then retry" is not "retry the 400"I am not proposing to make
Workaround that works today, no patchLower the provider's - id: llm-pi-ai
name: "@deepseek-ai/dsh-llm-pi-ai"
config:
providers:
<provider>:
maxRequestImageBytes: 8388608 # 8 MiB ≈ 17 of my ~450 KB imagesCaveats worth documenting if this becomes advice: (a) it is a proxy — many small images (say 40 KB each) fit 8 MiB at ~200 images and will still wedge the session; (b) it silently drops older visuals for every session on that provider, and the placeholders only keep a path that has to be re-read. The missing escape hatchOnce wedged, nothing in the product recovers the session — there is no trim/compact path for a session that cannot complete a request. Even a targeted recovery ("the last turn failed on an image-count cap; re-run with the N oldest images offloaded") would be enough to unstick people, and it would also cover every unknown backend ceiling. |
|
Another backend hitting the same wedge on and every follow-up re-sends the same history and fails the same way. The core already supports a count bound — +1 for shipping a count bound on |
|
Checked on master
One trap for whoever lands it: that whole block sits inside Both datapoints are worth keeping in the PR: |
Uh oh!
There was an error while loading. Please reload this page.
Summary
llm-pi-aibounds request images by total bytes (maxRequestImageBytes, default 20 MiB) but not by count. Backends that cap images per prompt (DeepSeek engines: 8) reject the request with HTTP 400At most 8 image(s) may be provided in one prompt.That 400 is not retryable, and no fallback model is configured, so the agent loop re-sends the same over-limit context on the next turn. The session can never make progress; every subsequent turn repeats the identical error.Reproduction
openai-completionsprovider backed by a DeepSeek engine (8 images per prompt).Current behavior
The image offload trigger only passes a byte bound:
packages/llm/llm-pi-ai/src/adapter.ts—requestImagePolicycarriesmaxRequestImageBytesonly.packages/llm/llm-pi-ai/src/config.ts—maxRequestImageBytesschema and default; nomaxImages.Expected behavior
Bound the count the same way as bytes. When a request would exceed the limit, drop the oldest images (keep them in the conversation as text placeholders) and continue the turn. We run
maxImages: 8in production as a patch on the same offload path, applied to 0.2.1-rc.2. Alternatively, treat the backend's per-prompt image-limit 400 as retryable after trimming. Happy to send a PR for the count bound.Environment
openai-completionsvia LiteLLM, engine enforcing an 8-images-per-prompt limitAll reactions