Repository navigation
Fix History replay dropping output-format reminders - #10554
Merged
Merged
Conversation
Render historical input turns with the same format reminder as the original request, without adding user messages for output-only events. Add a three-turn prefix regression across Chat, JSON, and XML adapters and update exact-message expectations. Amp-Thread-ID: https://ampcode.com/threads/T-01a0f840-fb6d-771c-889d-a19606285691 Co-authored-by: Isaac Miller <isaac@cmpnd.ai>
Contributor
|
mannuch
added a commit
to mannuch/dspy
that referenced
this pull request
Oct 5, 2026
Pulls in 49 upstream commits, three of which touch the RLM/adapter code this branch changes: - stanfordnlp#10554 (reminders in History replay): adopted for the REPL-event branch too, so a replayed step's user message is now byte-identical to the one sent at that step. Pinned by test_replayed_step_message_matches_the_live_one. - stanfordnlp#10493 (interpreter factories at call time): the positional `interpreter` argument is gone. `history_processor` follows upstream's convention for runtime configuration and is now keyword-only on forward/aforward; the "second positional argument" TypeError is removed. RLM tests move from the pooled-interpreter fixture to `interpreter_factory=PythonInterpreter`. - stanfordnlp#10478 (sub-dspy interpreters): `_LLMCallBudget`, `_setup_facade` and `sub_agent_rules` thread through the action loop alongside the history plumbing. Conflict resolutions of note: - Reserved-name validation keeps upstream's `interpreter_factory` guard and `is_reserved()` (now covering sandbox-facade names) plus this branch's `_RESERVED_INPUT_NAMES` check, each with its own error message. - Upstream's new facade tests read `result.trajectory`; renamed to `repl_trajectory` to match this branch. - Adapter exact-message tests take upstream's expectations (ours were formatting-only); the RLM request snapshot is regenerated so it carries both upstream's sub-agent instructions and this branch's signature fields. Full suite: 2616 passed, 365 skipped, 2 xfailed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
marcodelpin
added a commit
to marcodelpin/dspy
that referenced
this pull request
Oct 7, 2026
Upstream sync of 7 commits (stanfordnlp#10569 stanfordnlp#10408 stanfordnlp#10417 stanfordnlp#10576 stanfordnlp#10553 stanfordnlp#10554 stanfordnlp#10539). Three conflicts, each resolved keeping the fork side and porting the upstream change: - dspy/streaming/streaming_listener.py: keep the fork's self.reset() (stanfordnlp#8425) at the allow_reuse site; reset() now also clears value_started and held_whitespace, the per-stream state upstream stanfordnlp#10553 added. - tests/adapters/test_chat_adapter.py: keep the fork's objective line (stanfordnlp#9901, history not listed) and take stanfordnlp#10554's format reminder on the first history turn. - tests/adapters/test_xml_adapter.py: keep the fork's rebuilt golden and add stanfordnlp#10554's reminder to the history turn. New test test_reset_clears_boundary_whitespace_state pins the reset() addition (red on a mutant without it, green with it).
3 tasks done
isaacbmiller
pushed a commit
that referenced
this pull request
Oct 12, 2026
…age_content Adapter.format_conversation_history passes main_request since #10554, so TwoStepAdapter.format_conversation_history raised TypeError. Amp-Thread-ID: https://ampcode.com/threads/T-01a12205-b058-723a-ad3e-3dd53a6cd097 Co-authored-by: Isaac Miller <isaac@cmpnd.ai>
isaacbmiller
added a commit
that referenced
this pull request
Oct 12, 2026
…age_content (#10628) Adapter.format_conversation_history passes main_request since #10554, so TwoStepAdapter.format_conversation_history raised TypeError. Amp-Thread-ID: https://ampcode.com/threads/T-01a12205-b058-723a-ad3e-3dd53a6cd097 Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Isaac Miller <isaac@cmpnd.ai>
dbreunig
added a commit
to dbreunig/dspy
that referenced
this pull request
Oct 16, 2026
Each call sent the turn budget in its trailing user message, but history did not store it, so the next call replayed that turn without it. Call N was no longer a prefix of call N+1, which defeats provider prompt-cache checkpoints on the trailing message. Store each turn's turn_budget in that turn's history event. Since stanfordnlp#10554 replays the output-format reminder for events with inputs, replay now rebuilds the exact request, and with native function calling every request is a prefix of the next. That also covers turns 2+, which already dropped the trailing reminder before this change. Also default `show_turn_budget` to False at class level so agents pickled before the flag existed (unpickling skips __init__) keep working.
isaacbmiller
added a commit
that referenced
this pull request
Oct 16, 2026
#10662) * feat(dspy): ReActV2 show the agent its remaining turn budget each turn ReActV2 never told the model about `max_iters`; it ran into a forced `submit` without warning. Each LM call now carries a `turn_budget` input ("Turn 3 of 10 (7 more after this one).") and the instructions say the run must end with `submit`. The forced final call says no turns remain. The budget is rendered only in the newest user message and is not stored in history, so earlier counts are not replayed and the cached history prefix is unchanged. It follows per-call `max_iters` overrides and can be turned off with `show_turn_budget=False`, which also frees the reserved `turn_budget` field name. Motivated by "Budget-Aware Tool-Use Enables Effective Agent Scaling" (arXiv 2511.17006). Tracks CMP-1454. * test(dspy): expect ReActV2 turn_budget in GEPA reflective dataset inputs * fix(dspy): keep ReActV2 requests cache-prefixable with turn_budget Each call sent the turn budget in its trailing user message, but history did not store it, so the next call replayed that turn without it. Call N was no longer a prefix of call N+1, which defeats provider prompt-cache checkpoints on the trailing message. Store each turn's turn_budget in that turn's history event. Since #10554 replays the output-format reminder for events with inputs, replay now rebuilds the exact request, and with native function calling every request is a prefix of the next. That also covers turns 2+, which already dropped the trailing reminder before this change. Also default `show_turn_budget` to False at class level so agents pickled before the flag existed (unpickling skips __init__) keep working. * refactor(dspy): always show ReActV2 the turn budget Drop the `show_turn_budget` setting per review; the budget is always on. `turn_budget` joins the reserved input names. Agents pickled before this change restore an inner signature without the field, so the budget is skipped when the field is absent. * refactor(dspy): drop ReActV2 turn budget instruction line The turn_budget field description already says the model sees its current turn and how many remain before it must submit. Keeping the explanation only there leaves the agent instructions identical to main, and field descriptions are not rewritten by instruction optimizers. * docs(dspy): reword ReActV2 turn budget description * Simplify explanation of turn_budget in ReActV2 Removed redundant explanation about turn_budget storage and replay rebuilds. * Update dspy.ReActV2 function documentation Clarify description of dspy.ReActV2 function. --------- Co-authored-by: Isaac Miller <17116851+isaacbmiller@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Current user turns include the adapter’s output-format reminder, but
Historyreplay drops it. This rewrites a previously sent message rather than extending the request, preventing reuse of the cached trajectory prefix on affected providers.Render historical input turns with
main_request=True, preserving the reminder across Chat, JSON, and XML adapters. Keep output-only events free of synthetic user messages. No new state, public API, or provider-specific cache logic.This is separate from #10387. Its specialized REPL-event renderer will need to adopt the same behavior; this PR changes only general History replay.
Verification
pytest -q tests/adapters tests/predict/test_react.py tests/predict/test_predict.py: 464 passed, 1 skipped.git diff --checkpass.This preserves input-turn reminders for the same adapter/signature; it does not claim lossless replay across signature changes or resolve native-reasoning replay.