Gemma4: chat_template missing from tokenizer_config.json, requires manual loading from separate file
Author: w4nderlust
Pull request: no

## Description

The Gemma4 models (e.g. `google/gemma-4-E2B-it`) don't include `chat_template` in `tokenizer_config.json`. The chat template is shipped as a separate `chat_template.jinja` file instead.

This means the standard `tokenizer.apply_chat_template()` workflow fails out of the box:

```python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("google/gemma-4-E2B-it")
tokenizer.apply_chat_template([{"role": "user", "content": "Hello"}], tokenize=False, add_generation_prompt=True)
```

```
ValueError: Cannot use chat template functions because tokenizer.chat_template is not set
and no template argument was passed!
```

## Workaround

You have to manually load the Jinja file and set it on the tokenizer:

```python
import os
from huggingface_hub import hf_hub_download

chat_template_path = hf_hub_download("google/gemma-4-E2B-it", "chat_template.jinja")
with open(chat_template_path) as f:
    tokenizer.chat_template = f.read()
```

## Expected behavior

`tokenizer.chat_template` should be set automatically when loading the tokenizer, either by embedding the template in `tokenizer_config.json` (like other models do) or by having `AutoTokenizer` detect and load the `.jinja` file automatically.

This affects all Gemma4 variants I tested: E2B-it, E4B-it.

## Environment

- transformers 5.5.0
- Python 3.14
- macOS

Comments:
Quick correction: the `chat_template.jinja` IS auto-loaded correctly by transformers when the file is present in the model directory. The issue is that the chat template is only in a separate `.jinja` file and not embedded in `tokenizer_config.json`.

This means any deployment that downloads only the standard tokenizer files (tokenizer.json + tokenizer_config.json) without also downloading `chat_template.jinja` will silently end up with `tokenizer.chat_template = None`.

This is really a model packaging issue rather than a transformers bug. I'll open a PR on the model repo to embed the template in `tokenizer_config.json`. Other Gemma models (e.g. Gemma 3) do embed it, so this seems like an oversight.

Not sure what you mean by embedding jinja template in a config, since loading an `AutoTokenizer.from_pretrained` loads the template as well (checked with your code snippet). We have moved from storing templates inside tokenizer/processor config to storing them in a separate jinja file. It gives us visually better template inspection and allows to load the same config, no matter if we're loading a tokenizer or a processor

So if you meant to copy the contents of template inside a `tokenizer_config.json`, that should not be the case  

@zucchini-nlp I see! So from_pretrained already auto-loads .jinja files from chat_template.jinja and additional_chat_templates/ — that's good. But this caused confusion for me when working on Nemotron (PR #45300) because older model versions on the hub didn't have this structure yet.

Would be helpful to document this auto-discovery behavior more prominently, especially for users upgrading from older model versions.

Here's a proposed documentation addition (replaced the backticks with $$$ for avoiding messing up rendering in GitHub):

```markdown
## Automatic `.jinja` File Loading

When you use `AutoTokenizer.from_pretrained()`, the transformers library automatically discovers and loads chat templates from separate `.jinja` files. This allows for better template inspection and reusability across tokenizers and processors.

### File Locations

Templates are auto-loaded from two locations:

1. **Default template**: `chat_template.jinja` in the model's root directory
2. **Additional templates**: Any `.jinja` files in the `additional_chat_templates/` directory

### How It Works

When loading a model, transformers will:
- First check for a `chat_template` field in `tokenizer_config.json`
- If not present, look for `.jinja` files and auto-load them
- Render templates using the Jinja2 templating engine

### Example Repository Structure

$$$
model-repo/
├── config.json
├── tokenizer_config.json          # May or may not have chat_template field
├── chat_template.jinja            # Automatically loaded
├── additional_chat_templates/
│   ├── system_prompt.jinja
│   └── function_calling.jinja
└── ...other model files...
$$$

### Inline vs. File-Based Templates

**File-based (recommended for new models):**
- Separate `.jinja` files are automatically discovered and loaded
- Better for visual inspection and maintenance
- Default approach for recent models (Gemma2, Mistral, etc.)

**Inline templates (legacy):**
- Templates stored directly in `tokenizer_config.json`
- Still fully supported but may be less maintainable for complex templates

### Backward Compatibility

Older models may have chat templates embedded only in `tokenizer_config.json`. When upgrading to newer versions of transformers, ensure your model repository includes the `.jinja` files or the `chat_template` field in the config to maintain compatibility.

$$$python
from transformers import AutoTokenizer

# Works with both inline and file-based templates
tokenizer = AutoTokenizer.from_pretrained("model-id")
tokenizer.apply_chat_template(messages, tokenize=False)
$$$

Both approaches work seamlessly with `apply_chat_template()`.
```

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) are likely to be ignored.

I think the suggested documentation, at a minimum, is warranted

@stevhliu re docs

Not sure if we have it anywhere about how the legacy is resolved with chat templates. We had like 2-3 different ways to save it in the past, so i understand the confusion

yeah we should definitely add some docs for this! i'll take a look and add something for it :) 

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the [contributing guidelines](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md) are likely to be ignored.