Context
PR #400 consolidates accuracy-phase OSL (output sequence length) onto a single reference-tokenizer path and splits the scorer output contract into:
get_raw_outputs() — what the model generated → used for OSL / response accounting
get_scoring_outputs() — text to score; base returns raw, only BFCLv4Scorer overrides it to serialize the merged tool_calls
Problem
For tool-call / structured-output responses (BFCL v4 single-turn — the Edge-Agentic accuracy gate), client-side OSL is inherently approximate:
get_raw_outputs() returns str(TextModelOutput) = reasoning + output + msgspec.json.encode(merged_tool_calls).
- The tool_calls portion is msgspec's canonical re-serialized JSON, which is not the raw token sequence the model emitted — different whitespace / key order / escaping, and the server may have stripped
<tool_call>… markup before parsing the call into structured form.
So the OSL token count for tool-call responses does not exactly equal what the model generated. Plain-text workloads (DeepSeek-R1, gpt-oss, ROUGE) are exact; only structured-output is affected.
The only exact source
The server's usage.completion_tokens is the exact generated-token count. Note it is not universally reliable:
- SGLang native
/generate already exposes it (meta_info.completion_tokens → QueryResult.metadata["n_tokens"]), but the aggregator currently ignores it.
- OpenAI-compat non-streaming carries
usage; streaming requires stream_options.include_usage=true, which we do not currently send.
- It can also diverge from the reference-tokenizer count MLPerf uses elsewhere (special tokens / EOS / speculative decoding).
So it can only be an opportunistic cross-check for structured-output OSL, never a replacement for the reference tokenizer.
To decide
Related: PR #400 (reviewer threads on execute.py _load_osl_tokenizer / _phase_osl_stats).
Context
PR #400 consolidates accuracy-phase OSL (output sequence length) onto a single reference-tokenizer path and splits the scorer output contract into:
get_raw_outputs()— what the model generated → used for OSL / response accountingget_scoring_outputs()— text to score; base returns raw, onlyBFCLv4Scoreroverrides it to serialize the mergedtool_callsProblem
For tool-call / structured-output responses (BFCL v4 single-turn — the Edge-Agentic accuracy gate), client-side OSL is inherently approximate:
get_raw_outputs()returnsstr(TextModelOutput)=reasoning + output + msgspec.json.encode(merged_tool_calls).<tool_call>…markup before parsing the call into structured form.So the OSL token count for tool-call responses does not exactly equal what the model generated. Plain-text workloads (DeepSeek-R1, gpt-oss, ROUGE) are exact; only structured-output is affected.
The only exact source
The server's
usage.completion_tokensis the exact generated-token count. Note it is not universally reliable:/generatealready exposes it (meta_info.completion_tokens→QueryResult.metadata["n_tokens"]), but the aggregator currently ignores it.usage; streaming requiresstream_options.include_usage=true, which we do not currently send.So it can only be an opportunistic cross-check for structured-output OSL, never a replacement for the reference tokenizer.
To decide
usage.completion_tokensas an opportunistic OSL source where reliably available (SGLang today; OpenAI streaming behindinclude_usage), falling back to the reference tokenizer.Related: PR #400 (reviewer threads on
execute.py_load_osl_tokenizer/_phase_osl_stats).