feat: parse vLLM token ids + logprobs in the chat client - #1585
Conversation
The openai_chat_completions client now best-effort parses the prompt and completion token ids and sampling logprobs that vLLM returns (return_token_ids + logprobs) into Response.tokens, so MITO training (no renderer) can train on real on-policy tokens instead of re-tokenizing the messages downstream. Sampling args still pass straight through; tokens stay None when the provider returns neither token ids nor logprobs (e.g. eval, or non-vLLM providers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 89368c8. Configure here.
| return TurnTokens( | ||
| prompt_ids=list(getattr(completion, "prompt_token_ids", None) or []), | ||
| completion_ids=list(completion_ids), | ||
| completion_logprobs=[lp.logprob for lp in content] if content else [], |
There was a problem hiding this comment.
Partial tokens without prompt ids
Medium Severity
tokens_from_wire builds TurnTokens whenever choice.token_ids is present, but missing completion.prompt_token_ids becomes an empty prompt_ids list instead of skipping tokens. Downstream MITO training can treat the rollout as on-policy while the prompt side is empty.
Reviewed by Cursor Bugbot for commit 89368c8. Configure here.
ApprovabilityVerdict: Needs human review Unresolved review comment identifies a potential bug where missing You can customize Macroscope's approvability policy. Learn more. |
…tellect-ai#1585) The openai_chat_completions client now best-effort parses the prompt and completion token ids and sampling logprobs that vLLM returns (return_token_ids + logprobs) into Response.tokens, so MITO training (no renderer) can train on real on-policy tokens instead of re-tokenizing the messages downstream. Sampling args still pass straight through; tokens stay None when the provider returns neither token ids nor logprobs (e.g. eval, or non-vLLM providers). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>


Summary
openai_chat_completionsclient now best-effort parses the prompt/completion token ids and sampling logprobs that vLLM returns (return_token_ids+logprobs) intoResponse.tokens.TurnTokensjust like the renderer client does.tokens_from_wire(completion, choice): readschoice.token_ids(completion ids),completion.prompt_token_ids(prompt ids), and onelogprobs.content[i].logprobper generated token.logprobs+return_token_ids).tokensstaysNonewhen the provider returns neither (eval, non-vLLM providers).TurnTokens/Response.tokensto reflect that the chat client can populate them too.Base is the
feat/nano-as-v1vf branch.Verification
Confirmed end-to-end against a running vLLM server:
temperature,top_p=1.0,logprobs=True) +return_token_ids=True:prompt_token_ids(==usage.prompt_tokens),choice.token_ids(==usage.completion_tokens, ends in<|im_end|>), and one logprob per completion token — all aligned and accessible via the OpenAI SDK objects.reverse-text-v1RL run in MITO mode with the orchestrator-side backfill disabled, so tokens could only come from this parser: Trainable 128/128 (100%) every step, 0 "No trainable samples" warnings, reward 0.16 → 0.78, 0% errors. A saved rollout'sresponse.tokensdecoded back to the correct prompt and a real reversed-text answer.Note
Parse vLLM token ids and logprobs into
Response.tokensin the OpenAI chat clientAdds a
tokens_from_wirehelper in openai.py that extractschoice.token_ids,completion.prompt_token_ids, andchoice.logprobsfrom a vLLM completion response and constructs aTurnTokensobject.response_from_wirenow calls this helper to populateResponse.tokenswhen the provider returns token ids; previouslytokenswas alwaysNonein this client. ReturnsNonewhen token ids are absent, so non-vLLM providers are unaffected.Macroscope summarized 89368c8.
Note
Low Risk
Additive, best-effort parsing on the response path only; providers without token ids behave as before with
tokens=None.Overview
The OpenAI chat-completions client now best-effort fills
Response.tokensfrom vLLM when the caller enableslogprobsandreturn_token_ids, so MITO training can use on-policy token ids and sampling logprobs without a renderer client.A new
tokens_from_wirehelper readschoice.token_ids,completion.prompt_token_ids, and per-token logprobs fromchoice.logprobs.content;response_from_wireattaches the result to every response. If completion token ids are missing (eval or non-vLLM providers),tokensstaysNone—request forwarding is unchanged.Docstrings on
TurnTokensandResponse.tokensnow state the chat client can populate them via vLLM, not only the renderer path.Reviewed by Cursor Bugbot for commit 89368c8. Bugbot is set up for automated code reviews on this repo. Configure here.