Skip to content

fix(session): disable training replay outputs during evaluation - #3323

Merged
guapisolo merged 3 commits into
mainfrom
jiajun/session-eval-policy
Sep 22, 2026
Merged

guapisolo merged 3 commits into
mainfrom
jiajun/session-eval-policy

Conversation

@guapisolo

@guapisolo guapisolo commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Keep evaluation sessions free of training replay data and reject unknown creation fields.

Symptom & Reproduction

  • Symptom: Agentic evaluation on a replay-enabled fleet requests training-only routing/indexer data and rejects caller-supplied R3 offsets.
  • Symptom: A misspelled creation field such as {"evalution": true} was accepted and silently created a training session.
  • Reproduction: With routing/indexer replay enabled, create an evaluation session and send a chat request; replay outputs must be disabled.
  • Reproduction: Submit {"evalution": true} or an unrelated field to POST /sessions; each request must return HTTP 400 before allocating a session.

Root Cause

  1. OpenAIEndpointTracer.create and registries dropped evaluation purpose.
  2. resolve_request_args_by_config applied training replay policy to every session.
  3. CreateSessionRequest inherited permissive BaseModel.
  4. Unknown keys were discarded, defaulting evaluation to false.

Fix

Validate POST /sessions with CreateSessionRequest, now based on StrictBaseModel, and pass only the resolved evaluation: bool into SessionCore.create_session. Unknown, misspelled, or invalid creation fields return HTTP 400 before allocation; empty bodies still default to training. Chat completion parsing remains separate.

Propagate GenerateFnInput.evaluation through the tracer into v1/v2 session state so the purpose survives rollback and branching. After model rules resolve the request, evaluation forces return_sampling_mask, return_routed_experts, and return_indexer_topk to false and removes routed_experts_start_len.

Training behavior, sampling default/override precedence, TITO rendering, and compatibility checks stay unchanged. Evaluation may vary temperature between turns, and sample collection remains supported without replay data.

Verification

  • /opt/sglang/bin/python -m pytest tests/fast/router/test_session_evaluation.py -q: 37 passed at 6bad30d5327c92533eda7457bb61c2f98c875546, covering valid creation, typo/unknown-field rejection before allocation, continuation/retry, concurrent train/eval sessions, sampling resolution, and collection without replay outputs.
  • ruff, autoflake, isort, and black checks on the changed files passed; git diff --check passed.

Review Focus

  • CreateSessionRequest / SessionCore.create_session: reject unknown creation fields at the HTTP boundary while passing only the resolved boolean into core state.
  • SessionStateV2 / LinearTrajectory: keep session purpose across continuation, retries, and concurrent training/evaluation.
  • prepare_chat_request: enforce replay suppression without changing the training path; disabling response fields does not guarantee zero internal engine capture.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

try:
params = CreateSessionRequest.model_validate_json(await request.body() or b"{}")
except ValidationError as exc:
return JSONResponse(status_code=400, content={"error": str(exc)})
@guapisolo

Copy link
Copy Markdown
Collaborator Author

@claude review always

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

@guapisolo guapisolo changed the title fix(session): disable training replay outputs during evaluation [DO NOT MERGE fix(session): disable training replay outputs during evaluation Sep 19, 2026
@guapisolo guapisolo changed the title [DO NOT MERGE fix(session): disable training replay outputs during evaluation [DO NOT MERGE] fix(session): disable training replay outputs during evaluation Sep 19, 2026
@guapisolo
guapisolo marked this pull request as draft September 19, 2026 10:45
@guapisolo guapisolo closed this Sep 20, 2026
@guapisolo guapisolo reopened this Sep 20, 2026
@guapisolo
guapisolo marked this pull request as ready for review September 21, 2026 21:02

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@guapisolo guapisolo changed the title [DO NOT MERGE] fix(session): disable training replay outputs during evaluation fix(session): disable training replay outputs during evaluation Sep 21, 2026
@guapisolo

Copy link
Copy Markdown
Collaborator Author

@claude review always

@guapisolo
guapisolo force-pushed the jiajun/session-eval-policy branch from 10518c5 to e8e1b63 Compare September 22, 2026 04:07

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Comment thread miles/rollout/session/types.py Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

@@ -50,7 +50,7 @@ async def generate(input: GenerateFnInput) -> GenerateFnOutput:
)
use_v2 = getattr(input.args, "use_session_server", None) == "v2"
collect_spec_metrics = use_v2 and input.args.sglang_speculative_algorithm is not None
tracer = await OpenAIEndpointTracer.create(input.args)
tracer = await OpenAIEndpointTracer.create(input.args, evaluation=input.evaluation)

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.

instead of passing evaluation flag, how about explicitly passing "is_replay"? In case, we need to turn it off for non-evaluation requests too. What do you think?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I also thought of this... My idea is the evaluation semantic is easy to be understood by user, and also we might skip more TITO components for evaluation to ensure perf. So I think keep this param name is ok.

Agentic evaluation inherited training replay settings and R3-only request
constraints because session creation did not record its purpose.

Propagate evaluation through the tracer and v1/v2 session state, then force
replay outputs off after model request resolution. Preserve sampling
defaults, TITO behavior, and the training path.

Add HTTP coverage for creation, continuation, retries, concurrent sessions,
and sample collection without replay data, plus user documentation.
Validate the creation body with CreateSessionRequest at the HTTP route and
pass only the evaluation boolean into SessionCore. Keep parse_chat_request
specific to chat completions instead of sharing its input contract with
session creation.

Preserve empty-body defaults, strict booleans, error response shape and
allocation ordering. Validation errors now use schema diagnostics.

Verification: 481 focused CPU tests passed on an unchanged rerun; the first
run had an intermittent upstream empty-404 failure in the parity test.
All pre-commit hooks passed. No GPU backend code changed.
@guapisolo
guapisolo force-pushed the jiajun/session-eval-policy branch from e8e1b63 to eeddbe1 Compare September 22, 2026 05:24

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

@guapisolo
guapisolo added this pull request to stack #3591 September 22, 2026 05:53
Session creation previously ignored misspelled or unsupported fields,
which could silently select the training policy.

Use StrictBaseModel for CreateSessionRequest and cover unknown keys at
the HTTP boundary before session allocation.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The CreateSessionRequest gap I flagged earlier (plain BaseModel silently dropping unknown/misspelled keys like evalution) is now fixed: it subclasses StrictBaseModel and POST /sessions validates the body via model_validate_json, returning HTTP 400 on ValidationError before the session is allocated.

Extended reasoning...

Diff vs base commit 418be99 is the PR's three commits (6b6378c, eeddbe1, 6bad30d), touching session creation/evaluation-flag plumbing across core.py, sessions.py, linear_trajectory.py, request_args.py, session_state.py, types.py, and openai_endpoint_utils.py. Verified the previously-flagged StrictBaseModel/extra-forbid gap in types.py is now closed and the /sessions route rejects invalid bodies with 400 before allocation, matching the PR description. No new issues found in the evaluation-flag threading; a human reviewer already approved.

@guapisolo
guapisolo merged commit 8c3a85c into main Sep 22, 2026
25 checks passed
@guapisolo
guapisolo deleted the jiajun/session-eval-policy branch September 22, 2026 09:29
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.

4 participants