Skip to content

[Bug] Chat Template File name too long #629

@jrruethe

Description

@jrruethe

If I specify a chat template in the config file:

chat_template: "{% macro render_extra_keys(json_dict, handled_keys) ...

Then on this line, it treats that entire chat template as a file name. For long chat templates, this throws an OSError: [Errno 36] File name too long: '/media/user/backup/llm/mergekit/mergekit/_data/chat_templates/{% macro render_extra_keys(json_dict, handled_keys) ....

I expected it to drop down to this line. Either those two cases need to be reversed, OR allow me to specify my chat template as an external file, like "./my_template.jinja" or assume that "my_template.jinja" is in the same directory as the config file being run.

Here is the full trace:

Traceback (most recent call last):
  File "/media/user/backup/llm/models/Qwen_Qwen3-30B-A3B-Base/other/../../../mergekit/mergekit/scripts/run_yaml.py", line 39, in <module>
    main()
  File "/media/user/backup/llm/mergekit/.venv/lib/python3.12/site-packages/click/core.py", line 1442, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/media/user/backup/llm/mergekit/.venv/lib/python3.12/site-packages/click/core.py", line 1363, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/media/user/backup/llm/mergekit/.venv/lib/python3.12/site-packages/click/core.py", line 1226, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/media/user/backup/llm/mergekit/.venv/lib/python3.12/site-packages/click/core.py", line 794, in invoke
    return callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/media/user/backup/llm/mergekit/mergekit/options.py", line 160, in wrapper
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/media/user/backup/llm/models/Qwen_Qwen3-30B-A3B-Base/other/../../../mergekit/mergekit/scripts/run_yaml.py", line 30, in main
    run_merge(
  File "/media/user/backup/llm/mergekit/mergekit/merge.py", line 119, in run_merge
    _set_chat_template(tokenizer, merge_config)
  File "/media/user/backup/llm/mergekit/mergekit/merge.py", line 193, in _set_chat_template
    ).is_file():
      ^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 894, in is_file
    return S_ISREG(self.stat().st_mode)
                   ^^^^^^^^^^^
  File "/usr/lib/python3.12/pathlib.py", line 842, in stat
    return os.stat(self, follow_symlinks=follow_symlinks)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 36] File name too long: '/media/user/backup/llm/mergekit/mergekit/_data/chat_templates/{% macro render_extra_keys(json_dict, handled_keys) %}\n    {%- if json_dict is mapping %}\n        {%- for json_key in json_dict if json_key not in handled_keys %}\n            {%- if json_dict[json_key] is mapping or (json_dict[json_key] is sequence and json_dict[json_key] is not string) %}\n                {{- \'\\n<\' ~ json_key ~ \'>\' ~ (json_dict[json_key] | tojson | safe) ~ \'</\' ~ json_key ~ \'>\' }}\n            {%- else %}\n                {{-\'\\n<\' ~ json_key ~ \'>\' ~ (json_dict[json_key] | string) ~ \'</\' ~ json_key ~ \'>\' }}\n            {%- endif %}\n        {%- endfor %}\n    {%- endif %}\n{% endmacro %}\n\n{%- if messages[0]["role"] == "system" %}\n    {%- set system_message = messages[0]["content"] %}\n    {%- set loop_messages = messages[1:] %}\n{%- else %}\n    {%- set loop_messages = messages %}\n{%- endif %}\n\n{%- if not tools is defined %}\n    {%- set tools = [] %}\n{%- endif %}\n\n{%- if system_message is defined %}\n    {{- "<|im_start|>system\\n" + system_message }}\n{%- else %}\n    {%- if tools is iterable and tools | length > 0 %}\n        {{- "<|im_start|>system\\nYou are Blackrose, a helpful AI assistant that can interact with a computer to solve tasks." }}\n    {%- endif %}\n{%- endif %}\n{%- if tools is iterable and tools | length > 0 %}\n    {{- "\\n\\n# Tools\\n\\nYou have access to the following functions:\\n\\n" }}\n    {{- "<tools>" }}\n    {%- for tool in tools %}\n        {%- if tool.function is defined %}\n            {%- set tool = tool.function %}\n        {%- endif %}\n        {{- "\\n<function>\\n<name>" ~ tool.name ~ "</name>" }}\n        {%- if tool.description is defined %}\n            {{- \'\\n<description>\' ~ (tool.description | trim) ~ \'</description>\' }}\n        {%- endif %}\n        {{- \'\\n<parameters>\' }}\n        {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping %}\n            {%- for param_name, param_fields in tool.parameters.properties|items %}\n                {{- \'\\n<parameter>\' }}\n                {{- \'\\n<name>\' ~ param_name ~ \'</name>\' }}\n                {%- if param_fields.type is defined %}\n                    {{- \'\\n<type>\' ~ (param_fields.type | string) ~ \'</type>\' }}\n                {%- endif %}\n                {%- if param_fields.description is defined %}\n                    {{- \'\\n<description>\' ~ (param_fields.description | trim) ~ \'</description>\' }}\n                {%- endif %}\n                {%- set handled_keys = [\'name\', \'type\', \'description\'] %}\n                {{- render_extra_keys(param_fields, handled_keys) }}\n                {{- \'\\n</parameter>\' }}\n            {%- endfor %}\n        {%- endif %}\n        {% set handled_keys = [\'type\', \'properties\'] %}\n        {{- render_extra_keys(tool.parameters, handled_keys) }}\n        {{- \'\\n</parameters>\' }}\n        {%- set handled_keys = [\'type\', \'name\', \'description\', \'parameters\'] %}\n        {{- render_extra_keys(tool, handled_keys) }}\n        {{- \'\\n</function>\' }}\n    {%- endfor %}\n    {{- "\\n</tools>" }}\n    {{- \'\\n\\nIf you choose to call a function ONLY reply in the following format with NO suffix:\\n\\n<tool_call>\\n<function=example_function_name>\\n<parameter=example_parameter_1>\\nvalue_1\\n</parameter>\\n<parameter=example_parameter_2>\\nThis is the value for the second parameter\\nthat can span\\nmultiple lines\\n</parameter>\\n</function>\\n</tool_call>\\n\\n<IMPORTANT>\\nReminder:\\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\\n- Required parameters MUST be specified\\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\\n</IMPORTANT>\' }}\n{%- endif %}\n{%- if system_message is defined %}\n    {{- \'<|im_end|>\\n\' }}\n{%- else %}\n    {%- if tools is iterable and tools | length > 0 %}\n        {{- \'<|im_end|>\\n\' }}\n    {%- endif %}\n{%- endif %}\n{%- for message in loop_messages %}\n    {%- if message.role == "assistant" and message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}\n        {{- \'<|im_start|>\' + message.role }}\n        {%- if message.content is defined and message.content is string and message.content | trim | length > 0 %}\n            {{- \'\\n\' + message.content | trim + \'\\n\' }}\n        {%- endif %}\n        {%- for tool_call in message.tool_calls %}\n            {%- if tool_call.function is defined %}\n                {%- set tool_call = tool_call.function %}\n            {%- endif %}\n            {{- \'\\n<tool_call>\\n<function=\' + tool_call.name + \'>\\n\' }}\n            {%- if tool_call.arguments is defined %}\n                {%- for args_name, args_value in tool_call.arguments|items %}\n                    {{- \'<parameter=\' + args_name + \'>\\n\' }}\n                    {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}\n                    {{- args_value }}\n                    {{- \'\\n</parameter>\\n\' }}\n                {%- endfor %}\n            {%- endif %}\n            {{- \'</function>\\n</tool_call>\' }}\n        {%- endfor %}\n        {{- \'<|im_end|>\\n\' }}\n    {%- elif message.role == "user" or message.role == "system" or message.role == "assistant" %}\n        {{- \'<|im_start|>\' + message.role + \'\\n\' + message.content + \'<|im_end|>\' + \'\\n\' }}\n    {%- elif message.role == "tool" %}\n        {%- if loop.previtem and loop.previtem.role != "tool" %}\n            {{- \'<|im_start|>user\\n\' }}\n        {%- endif %}\n        {{- \'<tool_response>\\n\' }}\n        {{- message.content }}\n        {{- \'\\n</tool_response>\\n\' }}\n        {%- if not loop.last and loop.nextitem.role != "tool" %}\n            {{- \'<|im_end|>\\n\' }}\n        {%- elif loop.last %}\n            {{- \'<|im_end|>\\n\' }}\n        {%- endif %}\n    {%- else %}\n        {{- \'<|im_start|>\' + message.role + \'\\n\' + message.content + \'<|im_end|>\\n\' }}\n    {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n    {{- \'<|im_start|>assistant\\n\' }}\n{%- endif %}\n.jinja'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions