Skip to content

feat: add Llama 3 training chat template with generation markers#5493

Merged
qgallouedec merged 2 commits into
huggingface:mainfrom
RudrenduPaul:feat/llama3-training-chat-template
Apr 10, 2026
Merged

feat: add Llama 3 training chat template with generation markers#5493
qgallouedec merged 2 commits into
huggingface:mainfrom
RudrenduPaul:feat/llama3-training-chat-template

Conversation

@RudrenduPaul

@RudrenduPaul RudrenduPaul commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds a training-compatible variant of the Llama 3 chat template with {% generation %} / {% endgeneration %} markers, enabling return_assistant_tokens_mask=True for assistant-only loss masking in SFT training.

Contributes to #5471 (Tracking: add {% generation %} chat templates for common model families).

Files changed:

  • trl/chat_templates/llama3.jinja — original Llama 3 chat template (source of truth for the exact-match comparison in get_training_chat_template())
  • trl/chat_templates/llama3_training.jinja — training variant: same text output as original, with {% generation %} / {% endgeneration %} wrapping assistant output (<|eot_id|> included inside the block)
  • trl/chat_template_utils.py — loads both templates; adds Llama 3 branch before Qwen3 in get_training_chat_template(); updates docstring
  • tests/test_chat_template_utils.py — adds trl-internal-testing/tiny-LlamaForCausalLM-3 to TestGetTrainingChatTemplate parametrize

Template design: The Llama 3 template is already prefix-preserving (no conditional logic that changes earlier messages when new messages are appended), so no structural prefix-preservation fix is needed — only the {% generation %} markers are added. The training template restructures the original single-pass loop to handle the assistant role separately so markers can wrap the generated tokens only (content + <|eot_id|>), while the role header and BOS token remain outside.

Before submitting

AI writing disclosure

  • No AI usage: the PR was written entirely by a human.
  • AI-assisted: some parts were suggested or improved by AI, but the PR was written and reviewed by a human.
  • AI-generated: the PR was mostly or fully generated by an AI tool.

Who can review?

@qgallouedec (opened #5471)


Note

Low Risk
Low risk: adds an opt-in training chat template for LLaMA 3 and a new selection branch in get_training_chat_template, with tests asserting rendered output stays identical while enabling assistant-token masking.

Overview
Adds LLaMA 3 support to get_training_chat_template() by introducing a canonical llama3.jinja template and a new llama3_training.jinja variant that wraps assistant content in {% generation %} / {% endgeneration %} for return_assistant_tokens_mask=True.

Updates template loading/dispatch in trl/chat_template_utils.py and extends TestGetTrainingChatTemplate to cover a LLaMA 3 tokenizer, ensuring the patched template remains prefix-preserving and preserves rendered text output.

Reviewed by Cursor Bugbot for commit 5efca64. Bugbot is set up for automated code reviews on this repo. Configure here.

RudrenduPaul and others added 2 commits April 9, 2026 15:39
Adds `llama3_training.jinja` — a training-compatible variant of the Llama 3
chat template that wraps assistant output in `{% generation %}` /
`{% endgeneration %}` markers, enabling `return_assistant_tokens_mask=True`
for assistant-only loss masking in SFT training.

- `trl/chat_templates/llama3.jinja`: original Llama 3 chat template (source of truth)
- `trl/chat_templates/llama3_training.jinja`: training variant with generation markers
- `trl/chat_template_utils.py`: load templates and add Llama 3 branch in `get_training_chat_template()`
- `tests/test_chat_template_utils.py`: add `trl-internal-testing/tiny-LlamaForCausalLM-3` to `TestGetTrainingChatTemplate`

Closes part of huggingface#5471.

Built by Rudrendu Paul, developed with Claude Code

@qgallouedec qgallouedec left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm! thanks

@qgallouedec

Copy link
Copy Markdown
Member

@codex review

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5efca64. Configure here.


'+ message['content'] | trim + '<|eot_id|>' %}{% if loop.index0 == 0 %}{% set content = bos_token + content %}{% endif %}{{ content }}{% endfor %}{% if add_generation_prompt %}{{ '<|start_header_id|>assistant<|end_header_id|>

' }}{% endif %} No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Template newline encoding mismatch breaks tokenizer comparison

High Severity

The llama3.jinja file uses actual newline characters (line breaks) in the Jinja string literals, while the real Llama 3 tokenizer's chat_template stores \n as literal two-character escape sequences (backslash+n), matching how the JSON tokenizer_config.json round-trips them. This mirrors how qwen3.jinja correctly uses literal \n escape characters. Because Path.read_text() reads actual newlines (chr(10)) while the tokenizer attribute has backslash+n (chr(92)+chr(110)), the equality check tokenizer.chat_template == llama3_chat_template will be False, causing get_training_chat_template() to raise a ValueError instead of returning the training template.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5efca64. Configure here.

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.

3 participants