Fix chat_template crash on tool-call messages without a `content` key

#134
by albertvillanova HF Staff - opened

Tracked in https://github.com/huggingface/trl/issues/8280, together with the same fix on the other deepseek-ai repos.

Supersedes #122, which changes only the first of the two checks below: with #122 alone, the template still crashes in the second.

Since huggingface/transformers#45422, from transformers 5.23, apply_chat_template drops None-valued message keys. An OpenAI-style tool-call message ("content": None with "tool_calls") then reaches the template without a content key, and this template crashes:

UndefinedError: 'dict object' has no attribute 'content'

Cause

The template reads message['content'] in two checks, is none and is not none. Neither handles a missing key: is none is false and is not none is true, so the template renders the message as plain text and fails to concatenate the missing content.

Fix

Read the content with message.get('content') in both checks, so a missing key behaves exactly like content=None:

- {%- if message['role'] == 'assistant' and message['content'] is none %}
+ {%- if message['role'] == 'assistant' and message.get('content') is none %}
  ...
- {%- if message['role'] == 'assistant' and message['content'] is not none %}
+ {%- if message['role'] == 'assistant' and message.get('content') is not none %}

Reproduction

from transformers import AutoTokenizer

tok = AutoTokenizer.from_pretrained("deepseek-ai/DeepSeek-V3")
tok.apply_chat_template(
    [
        {"role": "user", "content": "What's the weather in Paris?"},
        {"role": "assistant", "content": None, "tool_calls": [{
            "type": "function",
            "function": {"name": "get_weather", "arguments": '{"city":"Paris"}'},
        }]},
    ],
    tokenize=False,
)

On transformers main, this raises with the current template and with #122, and renders correctly with this PR. It also raises on released transformers if the content key is omitted.

Verification

Rendered with transformers before and after huggingface/transformers#45422: a single tool call, a multi-call tool flow with tool outputs and a final answer, a tool-call message without a content key, a plain chat with reasoning, and an empty assistant message. Wherever the current template renders, the output of this PR is byte-identical to it, so nothing changes for existing users. The cases that crash today render correctly.

Ready to merge
This branch is ready to get merged automatically.

Sign up or log in to comment