Skip to content

Commit a7d162b

Browse files
committed
improve gguf-function-calling parser
1 parent 066638c commit a7d162b

File tree

1 file changed

+31
-18
lines changed

1 file changed

+31
-18
lines changed

llama_cpp/llama_chat_format.py

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4144,31 +4144,35 @@ def gguf_function_calling(
41444144
]:
41454145

41464146
function_calling_template = None
4147-
if hasattr(llama, 'model_path'):
4148-
metadata = llama.metadata
4149-
if metadata and "tokenizer.chat_template" in metadata:
4150-
function_calling_template = metadata["tokenizer.chat_template"]
4151-
4152-
4147+
4148+
41534149
function_calling_template = (
41544150
"{% for message in messages %}"
41554151
"<|im_start|>{{ message.role }}\n"
41564152
# System message
41574153
"{% if message.role == 'system' %}"
4154+
"<|system|>\n"
41584155
"{{ message.content }}"
4159-
"{% if tool_calls %}"
4160-
"\n\nYou have access to the following functions:\n"
4156+
"{% if tools %}"
4157+
"\n# Tools\n"
4158+
"\nYou may call one or more functions to assist with the user query."
4159+
"\nPrefer proposing the function first; only emit `<function_calls>` when user intent to run is clear from context."
4160+
"\n\nSoft consent policy:"
4161+
"\n- Proceed immediately if the user explicitly asks to run/fetch/call/use a tool, or previously agreed, or supplied all required parameters."
4162+
"\n- Otherwise: reply with a one-line proposal naming the function and why, and end with “Proceed?”."
4163+
"\n- Do not over-ask if consent is obvious."
4164+
"\n\nYou are provided with function signatures within <tools></tools> XML tags:"
4165+
"\n<tools>"
41614166
"{% for tool in tools %}"
4162-
'\n{% if tool.function.get("description") %}/* {{ tool.function.description | trim }} */{% endif %}'
4163-
"\nfunctions.{{ tool.function.name }}:\n"
4164-
"{{ tool.function.parameters | tojson }}"
4165-
"\n{% endfor %}"
4166-
"\nYou must respond to user messages with either a single message or with one or more function calls."
4167-
"\n\nTo respond with a message use the following format:"
4168-
"\n\nmessage:"
4169-
"\n<message>"
4170-
"\n\nTo respond with one or more function calls use the following format:"
4171-
"\n\n<function_calls>"
4167+
"{{ tool | tojson }}"
4168+
"{% endfor %}"
4169+
"</tools>"
4170+
"\n\nYou can respond in two ways:"
4171+
"\n\n1. Message only (proposal/confirmation step):"
4172+
"\nmessage:"
4173+
"\nI can use `ExampleFunction` to retrieve that. Proceed?"
4174+
"\n\n2. Message + function calls (when intent is clearly allowed by context):"
4175+
"\nmessage:"
41724176
"\nfunctions.<function_name>:"
41734177
'\n{ "arg1": "value1", "arg2": "value2" }'
41744178
"\nfunctions.<function_name>:"
@@ -4204,6 +4208,15 @@ def gguf_function_calling(
42044208
"{% endfor %}"
42054209
"{% if add_generation_prompt %}<|im_start|>assistant\n{% endif %}"
42064210
)
4211+
4212+
if hasattr(llama, 'model_path'):
4213+
metadata = llama.metadata
4214+
if metadata and "tokenizer.chat_template" in metadata:
4215+
function_calling_template = metadata["tokenizer.chat_template"]
4216+
4217+
if kwargs.get('chat_template'):
4218+
function_calling_template = kwargs.get('chat_template')
4219+
42074220
template_renderer = ImmutableSandboxedEnvironment(
42084221
autoescape=jinja2.select_autoescape(["html", "xml"]),
42094222
undefined=jinja2.StrictUndefined,

0 commit comments

Comments
 (0)