Skip to content

Rollout Models support recording experience data#591

Open
pan-x-c wants to merge 87 commits into
agentscope-ai:mainfrom
pan-x-c:feature/model_self_record_experience
Open

Rollout Models support recording experience data#591
pan-x-c wants to merge 87 commits into
agentscope-ai:mainfrom
pan-x-c:feature/model_self_record_experience

Conversation

@pan-x-c

@pan-x-c pan-x-c commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR introduces a new Experience generation and collection flow. The main goal is to let the Rollout Model record Experience data during inference, while updating the Workflow / Scheduler / WorkflowRunner interfaces to support this model-side recording mode.

The PR focuses on two major changes:

  1. Rollout Models can record Experience data by themselves.
  2. Workflow interfaces are updated to support the new Experience generation mode.

Key Changes

Rollout Model-side Experience Recording

Rollout Models can now convert finished generation requests into Experience objects and store them inside the model process.

Experiences are recorded by key in the format <batch_id>/<task_id>/<run_id>. They are later drained by the Scheduler / RolloutCoordinator instead of being returned directly from WorkflowRunner.

This PR adds the RecordStore interface and an in-memory MemoryStore implementation to support model-side Experience storage, update, overwrite, deletion, and prefix-based draining. Workflows can also patch reward / info back into recorded Experiences after task execution.

The recording path is integrated for vLLM, SGLang, and Tinker rollout models.

New Workflow Interface for Recording-based Workflows

This PR adds WorkflowBase and WorkflowWithRecording to support workflows that rely on rollout-model recording.

WorkflowWithRecording exposes:

  • base_url
  • api_key
  • model_name
  • update_reward(...)

A workflow can call the rollout model through an OpenAI-compatible API. The model records the generated Experience automatically, while the workflow only needs to run the task, compute reward, and write the reward back with update_reward.

The workflow execution result is normalized into Status, which reports completion state, metrics, and successful record keys.

The legacy Workflow interface is still kept for simple workflows that manually construct and return Experience objects.

Scheduler and WorkflowRunner Data Flow Update

WorkflowRunner no longer returns serialized Experience payloads directly. It now returns only execution status.

The Scheduler consumes successful record keys from Status and actively drains recorded Experiences from the corresponding Rollout Model actor.

This separates responsibilities more clearly:

  • WorkflowRunner: executes workflows and returns Status
  • Rollout Model: records and maintains Experiences
  • Scheduler: drains Experiences from rollout actors
  • RolloutCoordinator: handles batch finalization, cleanup, and pipeline submission

Checklist

Please check the following items before code is ready to be reviewed.

  • Code has passed all tests
  • Docstrings have been added/updated in Google Style
  • Documentation has been updated
  • Code is ready for review

@pan-x-c pan-x-c marked this pull request as draft June 24, 2026 12:26
pan-x-c and others added 28 commits June 25, 2026 11:15
…th legacy)

Refactor experience production so heavy data (tokens/logprobs/routed_experts)
no longer rides runner->scheduler->coordinator as serialized bytes. The vLLM
recorder now captures it in-process into a MemoryStore keyed by task_id, and
the coordinator pulls it at finalize time via /records/consume_task. Runners
ship only a small reward map. Both paths coexist behind
`explorer.use_recorded_experience` (default off = legacy).

Recording module (trinity/common/models/vllm_patch/recording/):
- store: drop SqlStore; MemoryStore.update_reward_by_task_id stamps
  reward/run/task on a whole task-id group, pops and returns it (the
  in-memory replacement for the SQL HistoryRecorder join).
- recorder: track in-flight record tasks; add flush() (await pending +
  queue.join) so a consume sees a quiesced store; honor skip_recording_ctx.
- models: build_experience emits one Experience per completion (n>1) with
  info["sample_index"]; eid.suffix=request_id kept for traceability.
- context: add skip_recording_ctx; task_id already flows via api_key
  (RecordingIdentityMiddleware) and now also via VLLMModel.chat (Ray entry).
- query: POST /records/consume_task (flush -> update_reward_by_task_id ->
  serialize_many); drop the SqlStore 503 branch.
- config/server: remove RecordingConfig entirely; the logprob width is a
  recorder-internal constant (we store only the chosen token, which vLLM
  force-includes at logprobs=1). No static config threaded through launch.

task_id propagation (Ray entry, same contextvar as the HTTP middleware):
- vllm_model: chat/generate accept task_id_key, set task_id_ctx around
  _generate_internal; logprobs sets skip_recording_ctx (auxiliary forward).
- model: ModelWrapper.chat/chat_async forward task_id_key; SGLang.chat
  accepts-and-ignores it (recording is vLLM-only).

Coordinator + runner + workflow:
- rollout_coordinator: _resolve_rank_urls (ray.get_actor per engine) and a
  recording-mode finalize that fans out /records/consume_task per engine,
  deserializes, and feeds objects to the pipeline (no re-serialization).
- experience_pipeline: process_experiences(exps) public object entry.
- workflow_runner: recording mode returns a pickled reward map keyed by the
  per-sample task_id_key the workflow stamped; legacy path unchanged.
- workflow: SimpleWorkflow/AsyncSimpleWorkflow run a per-sample n=1 loop in
  recording mode (distinct task_id_key per sample == reward unit for GRPO),
  legacy n=repeat_times single-call path unchanged.
- config: ExplorerConfig.use_recorded_experience flag.

SQL path removal (MemoryStore only):
- delete proxy/recorder.py (HistoryRecorder) and proxy_test.py; proxy
  service/app drop /feedback, /commit, record_feedback, submit_experiences,
  ready_experiences (keep allocate_model + weight sync); allocator no longer
  fills record_db_url; drop InferenceModelConfig.record_db_url and the dead
  ExplorerConfig.db_url field; RecordingConfig deleted.

Serve-mode external reward reporting is intentionally left unimplemented this
version (proxy /feedback//commit removed); the affected serve integration
tests (TestServeWithTrainer, ServeTest) are skipped with a pointer to the
recording refactor plan. convert_messages_to_experience redirect (multi-turn)
is deferred with TODOs at its call sites.

Co-Authored-By: Claude Fable 5 <[email protected]>
…-x-c/Trinity-RFT into feature/model_self_record_experience
Comment thread trinity/common/workflows/workflow.py Outdated
Comment thread trinity/common/config.py
Comment thread trinity/common/config.py Outdated
Comment on lines +154 to 155
response_text: str = "" # Text of the response
prompt_text: Optional[str] = None # Text of the prompt

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can response_text and prompt_text be the same default value

@pan-x-c pan-x-c force-pushed the feature/model_self_record_experience branch from c85db9e to 740805a Compare July 1, 2026 13:37
@pan-x-c

pan-x-c commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

/unittest-module-trainer

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

unittest: Run #1803

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
29 25 0 4 0 0 0 1h 17m

🎉 All tests passed!

Github Test Reporter by CTRF 💚

@pan-x-c pan-x-c changed the title vLLM OpenAI API server supports recording experience data Rollout Models support recording experience data Jul 2, 2026
@pan-x-c

pan-x-c commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

/unittest-all

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

unittest: Run #1805

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
420 405 8 7 0 0 0 2h 39m

Some tests failed!

Name Failure Message
❌ tests/explorer/workflow_test.py::TestConcurrentWorkflowRunner::test_concurrent_workflow_runner The test failed in the call phase due to an assertion error
❌ tests/utils/plugin_test.py::TestPluginLoader::test_load_plugins_local_0__workspace_tests_utils_plugins The test failed in the call phase
❌ tests/utils/plugin_test.py::TestPluginLoader::test_load_plugins_local_1_tests_utils_plugins The test failed in the call phase
❌ tests/utils/plugin_test.py::TestPluginLoader::test_load_plugins_remote_0__workspace_tests_utils_plugins The test failed in the call phase due to an exception
❌ tests/utils/plugin_test.py::TestPluginLoader::test_load_plugins_remote_1_tests_utils_plugins The test failed in the call phase due to an exception

See all failed tests here

Github Test Reporter by CTRF 💚

@pan-x-c

pan-x-c commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

/unittest-module-utils

@pan-x-c

pan-x-c commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

/unittest-pattern-TestConcurrentWorkflowRunner

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

unittest: Run #1806

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
46 44 1 1 0 0 0 36.1s

Some tests failed!

Name Failure Message
❌ tests/utils/registry_test.py::TestRegistryWithRay::test_dynamic_import The test failed in the call phase

Github Test Reporter by CTRF 💚

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

unittest: Run #1807

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
1 1 0 0 0 0 0 1m 59s

🎉 All tests passed!

Github Test Reporter by CTRF 💚

@pan-x-c

pan-x-c commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

/unittest-pattern-test_dynamic_import

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

unittest: Run #1808

Tests 📝 Passed ✅ Failed ❌ Skipped ⏭️ Pending ⏳ Other ❓ Flaky 🍂 Duration ⏱️
1 1 0 0 0 0 0 21.0s

🎉 All tests passed!

Github Test Reporter by CTRF 💚

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