danielhanchen commited on
Commit
05cd131
·
verified ·
1 Parent(s): 40ec95c

chat_template: fix tool-call parsing under llama.cpp jinja

Browse files

- a.0.b -> a[0].b (4 places): llama.cpp jinja rejects numeric member access with "Static member property must be an identifier"
- guard tc.arguments.items() with "is mapping": llama.cpp probes this branch with arguments as a JSON string, .items() threw, parser generation aborted and it fell back to a content-only grammar, so tool calls were emitted as raw XML in the content field

Rendered prompts are unchanged: 135/135 differential renders byte-identical.

Files changed (1) hide show
  1. chat_template.jinja +5 -5
chat_template.jinja CHANGED
@@ -72,11 +72,11 @@ For each function call, output the function name and arguments within the follow
72
  {%- macro render_tool_response(m) -%}
73
  {%- if m.content is string -%}
74
  {{- tool_response(m.content) -}}
75
- {%- elif m.content and m.content is not mapping and m.content.0.type == "tool_reference" -%}
76
  {{- tool_references_to_response(m.content) -}}
77
  {%- elif is_list_of_outputs(m) -%}
78
  {%- for tr in m.content -%}
79
- {%- if tr.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" -%}
80
  {{- tool_references_to_response(tr.output) -}}
81
  {%- else -%}
82
  {{- tool_response(visible_text(tr.output)) -}}
@@ -94,7 +94,7 @@ For each function call, output the function name and arguments within the follow
94
  {%- endif -%}
95
  {%- endmacro -%}
96
  {%- macro is_list_of_outputs(m) -%}
97
- {%- if m.content and m.content.0.output is defined -%}1{%- endif -%}
98
  {%- endmacro -%}
99
  {%- macro has_dup_tool_result_id(lo, hi, target) -%}
100
  {%- set ns_cnt = namespace(n=0) -%}
@@ -154,7 +154,7 @@ For each function call, output the function name and arguments within the follow
154
  {%- set tc = tc.function %}
155
  {%- endif %}
156
  {{- '<tool_call>' + tc.name -}}
157
- {% set _args = tc.arguments %}{% for k, v in _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 %}
158
  {% endif %}
159
  {%- elif m.role == 'tool' -%}
160
  {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
@@ -221,7 +221,7 @@ For each function call, output the function name and arguments within the follow
221
  {%- for entry in m.content -%}
222
  {%- set eid = id_of(entry) -%}
223
  {%- if eid == tc_id -%}
224
- {%- if entry.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" -%}
225
  {{- tool_references_to_response(entry.output) -}}
226
  {%- else -%}
227
  {{- tool_response(visible_text(entry.output)) -}}
 
72
  {%- macro render_tool_response(m) -%}
73
  {%- if m.content is string -%}
74
  {{- tool_response(m.content) -}}
75
+ {%- elif m.content and m.content is not mapping and m.content[0].type == "tool_reference" -%}
76
  {{- tool_references_to_response(m.content) -}}
77
  {%- elif is_list_of_outputs(m) -%}
78
  {%- for tr in m.content -%}
79
+ {%- if tr.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" -%}
80
  {{- tool_references_to_response(tr.output) -}}
81
  {%- else -%}
82
  {{- tool_response(visible_text(tr.output)) -}}
 
94
  {%- endif -%}
95
  {%- endmacro -%}
96
  {%- macro is_list_of_outputs(m) -%}
97
+ {%- if m.content and m.content[0].output is defined -%}1{%- endif -%}
98
  {%- endmacro -%}
99
  {%- macro has_dup_tool_result_id(lo, hi, target) -%}
100
  {%- set ns_cnt = namespace(n=0) -%}
 
154
  {%- set tc = tc.function %}
155
  {%- endif %}
156
  {{- '<tool_call>' + tc.name -}}
157
+ {% set _args = tc.arguments %}{% if _args is mapping %}{% for k, v in _args.items() %}<arg_key>{{ k }}</arg_key><arg_value>{{ v | tojson(ensure_ascii=False) if v is not string else v }}</arg_value>{% endfor %}{% endif %}</tool_call>{% endfor %}
158
  {% endif %}
159
  {%- elif m.role == 'tool' -%}
160
  {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
 
221
  {%- for entry in m.content -%}
222
  {%- set eid = id_of(entry) -%}
223
  {%- if eid == tc_id -%}
224
+ {%- if entry.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" -%}
225
  {{- tool_references_to_response(entry.output) -}}
226
  {%- else -%}
227
  {{- tool_response(visible_text(entry.output)) -}}