Skip to content

[#169] Fix for stripping vision-tags that were sent by clients withou… - #170

Merged
SearchSavior merged 2 commits into
SearchSavior:mainfrom
ecky-l:main
Sep 12, 2026
Merged

SearchSavior merged 2 commits into
SearchSavior:mainfrom
ecky-l:main

Conversation

@ecky-l

@ecky-l ecky-l commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

…t any images.

  • New _strip_stray_vision_tokens(prompt, ov_images) — if no image was provided and the prompt text contains the model's vision token, strip it (idempotent, logs a warning). This satisfies the invariant: 0 tags ↔ 0 images.

  • Applied in _resolve_prompt_and_images — the single choke point, so it covers all input paths (messages, raw prompt, and bench input_ids) for both streaming and non-streaming. Real image requests are untouched (prepare_inputs already pairs each image with exactly one tag). _run_generation enqueues an EOF sentinel on failure (except: streamer.text_queue.put_nowait(None); raise) so the drain loop always terminates, even when end() isn't called. (except Exception deliberately does not catch CancelledError, so cancellation is unaffected.)

  • Moved result = await gen_task out of finally into the try after the drain loop, and emit metrics only on the happy path — so a generation error now propagates to the caller → HTTP 500 instead of a silent hang.

…ients without any images.

* New _strip_stray_vision_tokens(prompt, ov_images) — if no image was
provided and the prompt text contains the model's vision token, strip
it (idempotent, logs a warning). This satisfies the invariant: 0 tags ↔ 0
images.

* Applied in _resolve_prompt_and_images — the single choke point, so it
covers all input paths (messages, raw prompt, and bench input_ids) for
both streaming and non-streaming. Real image requests are
untouched (prepare_inputs already pairs each image with exactly one tag).
_run_generation enqueues an EOF sentinel on failure (except:
streamer.text_queue.put_nowait(None); raise) so the drain loop always
terminates, even when end() isn't called. (except Exception deliberately
does not catch CancelledError, so cancellation is unaffected.)

* Moved result = await gen_task out of finally into the try after the drain
loop, and emit metrics only on the happy path — so a generation error now
propagates to the caller → HTTP 500 instead of a silent hang.
@SearchSavior

Copy link
Copy Markdown
Owner

@ecky-l this was a great find lol, great work.

I will test this out over the weekend

Updated warning message to clarify the reason for stripping tokens.
@SearchSavior

Copy link
Copy Markdown
Owner

@ecky-l made a small update to the logged error with a reference to this PR. Excellent work finding this edge case!

@SearchSavior
SearchSavior merged commit becb9a9 into SearchSavior:main Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants