Skip to content

TITO: non_assistant_text session-mismatch ≈ 0.99 in production agentic-RL  #32

Description

@nightlessbaron

Summary

In production agentic-RL rollouts, tito_session_mismatch_rate/non_assistant_text is ≈ 0.99 — i.e. almost every session shows a non-assistant-text token divergence.

# miles/utils/chat_template_utils/token_seq_comparator.py
NON_ASSISTANT_TEXT = "non_assistant_text"
# Non-assistant content (user, system, tool, etc.) differs.  This indicates
# a bug in the TITO algorithm — these regions should match exactly.

Evidence (two independent runs, identical tokenizer/config)

metric run A run B
tito_session_mismatch_rate 1.0 1.0
…/non_assistant_text ~0.99 ~0.99
…/assistant_text ~0.99 ~0.99
…/special_token_count ~0.006–0.012 ~0.006
…/special_token_type ~0.002–0.004 ~0.004

So the special-token structure is essentially fine (~0), and assistant_text divergence is the documented/expected "non-severe" case (assistant tokens are inherited from the pretokenized prefix). The concern is non_assistant_text (which "should match exactly") sitting at ~0.99.

Relevant config:

  • tito_model = k2v3
  • chat_template = autofix
  • 8B Llama-family tokenizer

Analysis — where the divergence comes from

SessionRegistry.compute_session_mismatch (miles/rollout/session/linear_trajectory.py) compares:

  • expected_ids = apply_chat_template(session.messages, tokenizer=<HF>, add_generation_prompt=False, tokenize=True) — a canonical full HF render, vs
  • session.token_ids — the accumulated checkpoint.

session.token_ids is not a pure HF render. In chat_completions / LinearTrajectory.update_pretokenized_state (miles/rollout/session/sessions.py) it is assembled from:

  • turn 0: SGLang-returned choice["prompt_token_ids"], plus
  • subsequent turns: incremental merge_tokens deltas for appended non-assistant (user/tool/system) messages + SGLang completion tokens.

So non_assistant_text divergence has two candidate sources:

  1. SGLang/gateway tokenization of non-assistant text differs from HF apply_chat_template (chat-template / whitespace / boundary differences — plausibly the autofix template path or a gateway-side template that isn't byte-identical to the HF one), and/or
  2. incremental tokenization seams in merge_tokens when appending user/tool/system messages, vs a single full-sequence render.

Questions

  1. Is non_assistant_text ≈ 0.99 expected for the tito_model=k2v3 + chat_template=autofix configuration, or a genuine TITO/chat-template bug as the comparator comment states?
  2. If this is non-severe in practice (training is self-consistent — generation and stored tokens both come from SGLang, so the loss is computed on actually-generated tokens), should non_assistant_text be downgraded from the strict set for these configs (or the seam behavior documented) so the metric isn't silently pinned at 1.0?

Impact

No crash. Training appears self-consistent, so this reads as a correctness-signal / metric-integrity concern rather than training-data corruption. Filing because (a) the comparator explicitly classifies non_assistant_text divergence as a bug, and (b) the rate is ~1.0 across runs, which makes tito_session_mismatch_rate uninformative as a guardrail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions