Branch-aware summary never applied at inlet for reasoning models (idless body ≠ DB branch via process_messages_with_output)
Summary
With branch-aware compression (v1.7.0+), a saved summary is never applied on the inlet for chats whose model is a reasoning model (assistant turns persisted with an output array plus a rendered <details type="reasoning">…</details> block in content). The outlet validates the snapshot against the DB branch and accepts it (so it stops rebuilding), but the inlet validates against the idless request body and always rejects it → the full uncompressed history is sent on every request, while the UI still reports a summary exists.
Environment
- Function: Async Context Compression v1.7.2 (commit
439b9f4)
- Open WebUI: 0.9.6
- DB: PostgreSQL
- Model: a reasoning model over an OpenAI-compatible endpoint with
function_calling: native. Assistant turns are stored with an output array and a <details type="reasoning"> block inside content.
Symptom
- Every chat request sends the full history (verified via the upstream proxy's
prompt_tokens), despite a valid chat_summary row covering the older turns.
- The summary row is correct and current-branch-anchored — replaying the stored covered refs against the live DB history nodes matches 100%.
- With
debug_mode enabled, the inlet logs:
[Summary Snapshot] Rejecting snapshot because current messages do not expose stable refs through covered prefix count=<N>.
[Summary Snapshot] DB active branch fallback skipped: request body is not a compatible idless view (body_count=<N>, db_count=<N>).
Note body_count == db_count, yet the idless view is judged incompatible.
Root cause
The request-body messages carry no Open WebUI ids, so _select_applicable_summary_snapshot → _current_branch_refs returns None and the code falls back to _compatible_db_branch_for_body_ref_fallback. That fallback fails for reasoning models:
- Open WebUI rebuilds each assistant message from its
output array before sending, via process_messages_with_output() → convert_output_to_messages(output, ...), which skips reasoning by default (reasoning_format=None). So the model-visible assistant content is regenerated from output (reasoning excluded) and does not equal the stored content (which contains the <details type="reasoning"> fold).
_body_message_matches_db_branch_message compares stored content (folded, with reasoning) against body content (output-derived, no reasoning). Even via the include_output=False path, the content differs, so the folded match fails.
_unfold_db_branch_for_body_ref_fallback calls convert_output_to_messages(output, raw=True), but that does not reproduce the installed OWUI build's process_messages_with_output result (the raw flag / reasoning_format / message-collapsing differ), so the unfolded comparison also fails.
Net: neither the folded nor unfolded comparison matches → snapshot rejected on every inlet → full context sent. The outlet, which validates against DB-reconstructed messages, accepts the snapshot and skips rebuild, so the stale-but-valid summary persists unused.
Reproduction
- Use a reasoning model with
function_calling: native so assistant turns are stored with an output array and a <details type="reasoning"> block in content.
- Let a long chat exceed the compression threshold so a summary is generated and saved.
- Observe subsequent requests: the summary is never applied on the inlet (full history sent), while the outlet keeps the existing snapshot and skips rebuild.
Suggested fix
Reconcile the idless body↔DB comparison with how Open WebUI actually builds the model payload for reasoning models:
- Mirror
process_messages_with_output() exactly in _unfold_db_branch_for_body_ref_fallback (use the same convert_output_to_messages arguments — raw and reasoning_format — as the installed OWUI version), or
- When the body is idless and 1:1 in count/role with the DB active branch, validate the snapshot against the DB branch (as the outlet does) and inject the summary by position, rather than requiring a content-level match of reasoning-stripped bodies.
Happy to provide more detail or test a patch.
Branch-aware summary never applied at inlet for reasoning models (idless body ≠ DB branch via
process_messages_with_output)Summary
With branch-aware compression (v1.7.0+), a saved summary is never applied on the inlet for chats whose model is a reasoning model (assistant turns persisted with an
outputarray plus a rendered<details type="reasoning">…</details>block incontent). The outlet validates the snapshot against the DB branch and accepts it (so it stops rebuilding), but the inlet validates against the idless request body and always rejects it → the full uncompressed history is sent on every request, while the UI still reports a summary exists.Environment
439b9f4)function_calling: native. Assistant turns are stored with anoutputarray and a<details type="reasoning">block insidecontent.Symptom
prompt_tokens), despite a validchat_summaryrow covering the older turns.debug_modeenabled, the inlet logs:body_count == db_count, yet the idless view is judged incompatible.Root cause
The request-body messages carry no Open WebUI ids, so
_select_applicable_summary_snapshot→_current_branch_refsreturnsNoneand the code falls back to_compatible_db_branch_for_body_ref_fallback. That fallback fails for reasoning models:outputarray before sending, viaprocess_messages_with_output()→convert_output_to_messages(output, ...), which skips reasoning by default (reasoning_format=None). So the model-visible assistantcontentis regenerated fromoutput(reasoning excluded) and does not equal the storedcontent(which contains the<details type="reasoning">fold)._body_message_matches_db_branch_messagecompares stored content (folded, with reasoning) against body content (output-derived, no reasoning). Even via theinclude_output=Falsepath, the content differs, so the folded match fails._unfold_db_branch_for_body_ref_fallbackcallsconvert_output_to_messages(output, raw=True), but that does not reproduce the installed OWUI build'sprocess_messages_with_outputresult (therawflag /reasoning_format/ message-collapsing differ), so the unfolded comparison also fails.Net: neither the folded nor unfolded comparison matches → snapshot rejected on every inlet → full context sent. The outlet, which validates against DB-reconstructed messages, accepts the snapshot and skips rebuild, so the stale-but-valid summary persists unused.
Reproduction
function_calling: nativeso assistant turns are stored with anoutputarray and a<details type="reasoning">block incontent.Suggested fix
Reconcile the idless body↔DB comparison with how Open WebUI actually builds the model payload for reasoning models:
process_messages_with_output()exactly in_unfold_db_branch_for_body_ref_fallback(use the sameconvert_output_to_messagesarguments —rawandreasoning_format— as the installed OWUI version), orHappy to provide more detail or test a patch.