Conversation
…emplates without it) Clients such as pi send the system prompt with role "developer" by default (OpenAI's current spelling of "system"). Most chat templates do not know the role and raise "Unexpected message role", which the server returns as a 400. Map developer to system before rendering unless the template spells the role itself (gpt-oss does). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0173pf9k9fSVtwbm3f898HDt
There was a problem hiding this comment.
🟡 Changes recommended
Template capability detection may mishandle dictionary templates and incidental developer text.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds OpenAI developer role support by mapping unsupported roles to system before chat-template rendering.
Changes:
- Adds developer-role normalization.
- Preserves input immutability.
- Adds tokenizer regression coverage.
File summaries
| File | Summary |
|---|---|
tests/tokenizer/test_tokenize.py |
Tests role mapping and input preservation. |
python/freetoken/tokenizer/tokenize.py |
Implements developer-role normalization before rendering. |
Review details
Suppressed comments (1)
python/freetoken/tokenizer/tokenize.py:60
- The bare substring check does not prove that the template handles this role: a Jinja comment or error/help string such as
developer is unsupportedalso makes this branch preserve the role, after whichapply_chat_templatestill raisesUnexpected message role. Detect an actual role handler or use a more reliable capability check instead of any occurrence in the template source.
if "developer" in (chat_template or "") or not any(
m.get("role") == "developer" for m in messages
):
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+53
to
+60
| messages: list[dict[str, Any]], chat_template: str | None | ||
| ) -> list[dict[str, Any]]: | ||
| """OpenAI's ``developer`` role is the current spelling of ``system`` (clients such as pi | ||
| send the system prompt that way by default). Most chat templates do not know it and raise | ||
| ("Unexpected message role"), so map it to ``system`` unless the template handles it.""" | ||
| if "developer" in (chat_template or "") or not any( | ||
| m.get("role") == "developer" for m in messages | ||
| ): |
gdevenyi
force-pushed
the
5080/02-tool-schema-435
branch
from
September 18, 2026 03:06
45373a6 to
dfce416
Compare
gdevenyi
force-pushed
the
5080/03-developer-role-391
branch
from
September 18, 2026 03:06
f4b6ebe to
925a217
Compare
gdevenyi
force-pushed
the
5080/02-tool-schema-435
branch
from
September 19, 2026 21:30
dfce416 to
d6109f3
Compare
gdevenyi
force-pushed
the
5080/03-developer-role-391
branch
from
September 19, 2026 21:31
925a217 to
d4a2701
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merges upstream FlashML-org#391 (
fix(tokenizer): accept the OpenAI developer role, head965e1780; closed by its author on 2026-09-14). Stacked on #10.Changes
TokenizeManager._rendermaps adevelopermessage tosystembeforeapply_chat_template, unless the chat template itself mentionsdeveloper.Testing
This merge and the next one in the stack (FlashML-org#475, both small
tokenizer/tokenize.pychanges) were tested together at 805e347, not separately.Unit tests:
pytest tests/tokenizer tests/server -m "not slow"at 805e347: 852 passed, 4 skipped.Live (
reasoning_effort: low, "Answer tersely." + "2+2?"):maine0886cc): thedeveloperrole returns HTTP 400could not encode request: Unexpected message role.developerandsystemboth giveprompt_tokens49 and the answer "4". Checked again on the final stack (2d56708): thedeveloperrole answers normally.Server: same command as the previous PR in the stack. Startup to ready 60.2 s.
Environment:
nvidia/Qwen3.8-Flash-Next-NVFP4Stack: the
5080deploybranch ismaine0886cc plus upstream PRs merged one at a time for a single-user, full-context (262,144-token) deployment on this card. Each PR in the stack is based on the previous one, so its diff is exactly one merge step. Merge them in order, or merge the top of the stack alone.How tests were run: with the server stopped, since a running server holds almost all VRAM and GPU tests fail spuriously. Benchmarks are streamed chat completions with 256 tokens generated with
ignore_eos, one request at a time. Prompts are salted so the radix cache cannot hit.Rebased 2026-09-17 onto upstream main
cac247a(v0.1.3). The whole stack was rebuilt merge by merge on the new base (previous basee0886cc); the merge resolutions were replayed unchanged viagit rerere, and the rebuilt tip differs from the old one by exactly thee0886cc..cac247afile set. This PR's head is now925a217.Rebased 2026-09-19 onto upstream main
cc1f5c2(4 commits pastcac247a: FlashML-org#471 greedy sampling in mixed batches, FlashML-org#518 WeightLoadError, FlashML-org#521 tvm-ffi jit arch, FlashML-org#524 install index). Same replay as before viagit rerere; the replayed stack differs from the previous tip8adde91by exactly thecac247a..cc1f5c2file set. This PR's head is nowd4a2701.🤖 Generated with Claude Code
https://claude.ai/code/session_01Bu6LgoxLR4wETqb7RPR2vt