@ZixuanLi_: Updated chat templates for GLM-5.3 and GLM-5.3-Flash. Tool-result reordering now exits early instead of scanning every …
Summary
GLM-5.3 and GLM-5.3-Flash received updated HuggingFace chat templates that optimize tool-result reordering with an early exit, and developers are advised to pull the latest template for deployment.
View Cached Full Text
Cached at: 09/06/26, 12:46 PM
Updated chat templates for GLM-5.3 and GLM-5.3-Flash.
Tool-result reordering now exits early instead of scanning every block.
Pull the latest template and update your deployment: https://t.co/7rT1chdsex
chat_template.jinja · zai-org/GLM-5.3 at main
Source: https://huggingface.co/zai-org/GLM-5.3/blob/main/chat_template.jinja
![]()
chat template: early break in tool result reordering check
verified
2 days ago
[gMASK]<sop>{%-seteffective_reasoning_effort = reasoning_effort if reasoning_effort is defined and reasoning_effortin[‘low’, ‘high’] else ‘max’ -%}{%-ifeffective_reasoning_effort is not none -%}<|system|>Reasoning Effort:{{ effective_reasoning_effort | capitalize }}{%-endif-%}{%-setclear_thinking = clear_thinking if clear_thinking is defined else false -%}{%-iftools -%}{%-macrotool_to_json(tool) -%}{%-setns_tool = namespace(first=true) -%}{{ ‘{’ -}}{%-fork, vintool.items() -%}{%-ifk != ‘defer_loading’ and k != ‘strict’ -%}{%-ifnot ns_tool.first -%}{{- ’, ’ -}}{%-endif-%}{%-setns_tool.first = false -%}“{{ k }}”:{{ v | tojson(ensure_ascii=False) }}{%-endif-%}{%-endfor-%}{{- ‘}’ -}}{%-endmacro-%}{%-macrotool_references_to_response(refs) -%}{{- ‘<tool_response><tools>\n’ -}}{%-fortrinrefs -%}{%-fortoolintools -%}{%-if’function’intool -%}{%-settool = tool[‘function’] -%}{%-endif-%}{%-iftool.name == tr.name -%}{{- tool_to_json(tool) + ‘\n’ -}}{%-endif-%}{%-endfor-%}{%-endfor-%}{{- ‘</tools></tool_response>’ -}}{%-endmacro-%}<|system|># ToolsYou may call one or more functions to assist with the user query.You are provided with function signatures within<tools></tools>XML tags:<tools>{%fortoolintools %}{%-if’function’intool -%}{%-settool = tool[‘function’] -%}{%-endif-%}{%iftool.defer_loading is not defined or not tool.defer_loading %}{{ tool_to_json(tool) }}{%endif%}{%endfor%}</tools>For each function call, output the function name and arguments within the following XML format:<tool_call>{function-name}<arg_key>{arg-key-1}</arg_key><arg_value>{arg-value-1}</arg_value><arg_key>{arg-key-2}</arg_key><arg_value>{arg-value-2}</arg_value>...</tool_call>{%-endif-%}{%-macrovisible_text(content) -%}{%-ifcontent is string -%}{{- content }}{%-elifcontent is iterable and content is not mapping -%}{%-foritemincontent -%}{%-ifitem is mapping and item.type == ‘text’ -%}{{- item.text }}{%-elifitem is string -%}{{- item }}{%-elifitem is mapping and item.typein[‘image’, ‘image_url’, ‘video’, ‘video_url’, ‘audio’, ‘audio_url’, ‘input_audio’] -%}{%-setmedia_type = item.type | replace(‘_url’, ‘’) | replace(‘input_’, ‘’) -%}{{- “<reminder>You are unable to process this “ ~ media_type ~ “ because you don’t have multi-modal input ability. Try different methods.</reminder>” }}{%-endif-%}{%-endfor-%}{%-elifcontent is not none -%}{{- content }}{%-endif-%}{%-endmacro-%}{%-macrotool_response(text) -%}{{- ‘<tool_response>’ + text + ‘</tool_response>’ -}}{%-endmacro-%}{%-macrorender_tool_response(m) -%}{%-ifm.content is string -%}{{- tool_response(m.content) -}}{%-elifm.content and m.content is not mapping and m.content.0.type == “tool_reference” -%}{{- tool_references_to_response(m.content) -}}{%-elifis_list_of_outputs(m) -%}{%-fortrinm.content -%}{%-iftr.output is iterable and tr.output is not string and tr.output is not mapping and tr.output and tr.output.0.type == “tool_reference” -%}{{- tool_references_to_response(tr.output) -}}{%-else-%}{{- tool_response(visible_text(tr.output)) -}}{%-endif-%}{%-endfor-%}{%-else-%}{{- tool_response(visible_text(m.content)) -}}{%-endif-%}{%-endmacro-%}{%-macroid_of(obj) -%}{%-ifobj.tool_call_id -%}{{- obj.tool_call_id -}}{%-elifobj.id -%}{{- obj.id -}}{%-endif-%}{%-endmacro-%}{%-macrois_list_of_outputs(m) -%}{%-ifm.content and m.content.0.output is defined -%}1{%-endif-%}{%-endmacro-%}{%-macrohas_dup_tool_result_id(lo, hi, target) -%}{%-setns_cnt = namespace(n=0) -%}{%-forkinrange(lo, hi + 1) -%}{%-setm = messages[k] -%}{%-ifis_list_of_outputs(m) -%}{%-forentryinm.content -%}{%-ifid_of(entry) == target -%}{%-setns_cnt.n = ns_cnt.n + 1 -%}{%-endif-%}{%-endfor-%}{%-elifid_of(m) == target -%}{%-setns_cnt.n = ns_cnt.n + 1 -%}{%-endif-%}{%-ifns_cnt.n > 1 -%}{%-break-%}{%-endif-%}{%-endfor-%}{%-ifns_cnt.n > 1 -%}1{%-endif-%}{%-endmacro-%}{%-macrotc_id_exists(tcs, target) -%}{%-setns_f = namespace(found=false) -%}{%-fortcintcs -%}{%-ifid_of(tc) == target -%}{%-setns_f.found = true -%}{%-break-%}{%-endif-%}{%-endfor-%}{%-ifns_f.found -%}1{%-endif-%}{%-endmacro-%}{%-setns = namespace(last_user_index=-1) -%}{%-forminmessages %}{%-ifm.role == ‘user’ %}{%-setns.last_user_index = loop.index0 -%}{%-endif%}{%-endfor%}{%-forminmessages -%}{%-ifm.role == ‘user’ -%}<|user|>{{ visible_text(m.content) }}{%-elifm.role == ‘assistant’ -%}<|assistant|>{%-setcontent = visible_text(m.content) %}{%-ifm.reasoning_content is string %}{%-setreasoning_content = m.reasoning_content %}{%-elif’</think>‘incontent %}{%-setreasoning_content = content.split(’</think>‘)[0].split(’<think>‘)[-1] %}{%-setcontent = content.split(’</think>’)[-1] %}{%-endif%}{%-if(not clear_thinking or loop.index0 > ns.last_user_index) and reasoning_content is defined -%}{{ ‘<think>’ + reasoning_content + ‘</think>’}}{%-else-%}{{ ‘<think></think>’ }}{%-endif-%}{%-ifcontent.strip() -%}{{ content.strip() }}{%-endif-%}{%ifm.tool_calls %}{%fortcinm.tool_calls %}{%-iftc.function %}{%-settc = tc.function %}{%-endif%}{{- ‘<tool_call>’ + tc.name -}}{%set_args = tc.arguments %}{%fork, vin_args.items() %}<arg_key>{{ k }}</arg_key><arg_value>{{ v | tojson(ensure_ascii=False) if v is not string else v }}</arg_value>{%endfor%}</tool_call>{%endfor%}{%endif%}{%-elifm.role == ‘tool’ -%}{%-ifloop.first or (messages[loop.index0 - 1].role != “tool”) %}{{- ‘<|observation|>’ -}}{%-setblock_start = loop.index0 -%}{%-setns_blk = namespace(end=block_start) -%}{%-forjinrange(block_start, messages|length) -%}{%-ifmessages[j].role == ‘tool’ -%}{%-setns_blk.end = j -%}{%-else-%}{%-break-%}{%-endif-%}{%-endfor-%}{%-setns_a = namespace(tool_calls=none) -%}{%-ifblock_start > 0 and messages[block_start - 1].role == ‘assistant’ and messages[block_start - 1].tool_calls -%}{%-setns_a.tool_calls = messages[block_start - 1].tool_calls -%}{%-endif-%}{%-setns_chk = namespace(can_sort=true) -%}{%-ifnot ns_a.tool_calls -%}{%-setns_chk.can_sort = false -%}{%-else-%}{%-forkinrange(block_start, ns_blk.end + 1) -%}{%-ifnot ns_chk.can_sort -%}{%-break-%}{%-endif-%}{%-setm = messages[k] -%}{%-ifis_list_of_outputs(m) -%}{%-forentryinm.content -%}{%-ifnot ns_chk.can_sort -%}{%-break-%}{%-endif-%}{%-seteid = id_of(entry) -%}{%-ifnot eid -%}{%-setns_chk.can_sort = false -%}{%-elifhas_dup_tool_result_id(block_start, ns_blk.end, eid) -%}{%-setns_chk.can_sort = false -%}{%-elifnot tc_id_exists(ns_a.tool_calls, eid) -%}{%-setns_chk.can_sort = false -%}{%-endif-%}{%-endfor-%}{%-else-%}{%-settk_id = id_of(m) -%}{%-ifnot tk_id -%}{%-setns_chk.can_sort = false -%}{%-elifhas_dup_tool_result_id(block_start, ns_blk.end, tk_id) -%}{%-setns_chk.can_sort = false -%}{%-elifnot tc_id_exists(ns_a.tool_calls, tk_id) -%}{%-setns_chk.can_sort = false -%}{%-endif-%}{%-endif-%}{%-endfor-%}{%-foriinrange(ns_a.tool_calls | length) -%}{%-ifnot ns_chk.can_sort -%}{%-break-%}{%-endif-%}{%-settc_id = id_of(ns_a.tool_calls[i]) -%}{%-ifnot tc_id -%}{%-setns_chk.can_sort = false -%}{%-endif-%}{%-forjinrange(i + 1, ns_a.tool_calls | length) -%}{%-ifid_of(ns_a.tool_calls[j]) == tc_id -%}{%-setns_chk.can_sort = false -%}{%-break-%}{%-endif-%}{%-endfor-%}{%-endfor-%}{%-endif-%}{%-ifns_chk.can_sort -%}{%-fortcinns_a.tool_calls -%}{%-settc_id = id_of(tc) -%}{%-forkinrange(block_start, ns_blk.end + 1) -%}{%-setm = messages[k] -%}{%-ifis_list_of_outputs(m) -%}{%-forentryinm.content -%}{%-seteid = id_of(entry) -%}{%-ifeid == tc_id -%}{%-ifentry.output is iterable and entry.output is not string and entry.output is not mapping and entry.output and entry.output.0.type == “tool_reference” -%}{{- tool_references_to_response(entry.output) -}}{%-else-%}{{- tool_response(visible_text(entry.output)) -}}{%-endif-%}{%-endif-%}{%-endfor-%}{%-else-%}{%-settk_id = id_of(m) -%}{%-iftk_id == tc_id -%}{{- render_tool_response(m) -}}{%-endif-%}{%-endif-%}{%-endfor-%}{%-endfor-%}{%-else-%}{%-forkinrange(block_start, ns_blk.end + 1) -%}{{- render_tool_response(messages[k]) -}}{%-endfor-%}{%-endif-%}{%endif-%}{%-elifm.role == ‘system’ -%}<|system|>{{ visible_text(m.content) }}{%-endif-%}{%-endfor-%}{%-ifadd_generation_prompt -%}<|assistant|>{{- ‘<think>’ -}}{%-endif-%}
Similar Articles
GLM-5.2 is available on HuggingChat
GLM-5.2, an open source AI model from zai-org, is now available on HuggingChat.
GLM 5.3 Released
Z.ai has released GLM 5.3, an update to its GLM language model family. The official announcement provides details on the new version.
zai-org/GLM-5.3-Flash
GLM-5.3-Flash is the first natively multimodal model in the GLM-5 series, with 320B total parameters and 18B active parameters, outperforming previous versions and approaching Claude Opus 4.8 through a redesigned hybrid architecture for improved efficiency.
Google is updating Gemma 4's chat templates, bringing major fixes to tool calling and reducing "laziness", and enabling Flash Attention 4 on Hopper GPUs, plus an interactive guide on how to work with and improve its vision!
Google updated Gemma 4's chat templates with major fixes to tool calling, reduced laziness, enabled Flash Attention 4 on Hopper GPUs, and released an interactive vision guide. The updates are available on Hugging Face.
@MaximeRivest: Tool calling in open source LLMs is wildly different from one model to another. I just wipped up: http://chattemplatepl…
A new web tool, Chat Template Playground, lets users visualize how different open-source LLMs render their chat templates, highlighting differences in prompting and tokenization.