Handle tool calling in chat template
Browse files### Changes
* Handle tool calling in chat template instead of custom system prompt
This enables automatic function schema generation in transformers by simply passing functions as tools
**Updated using [Chat Template Editor](https://huggingface.co/spaces/CISCai/chat-template-editor)**
- tokenizer_config.json +1 -1
tokenizer_config.json
CHANGED
@@ -195,7 +195,7 @@
|
|
195 |
"<|video_pad|>"
|
196 |
],
|
197 |
"bos_token": null,
|
198 |
-
"chat_template": "{%-
|
199 |
"clean_up_tokenization_spaces": false,
|
200 |
"eos_token": "<|im_end|>",
|
201 |
"errors": "replace",
|
|
|
195 |
"<|video_pad|>"
|
196 |
],
|
197 |
"bos_token": null,
|
198 |
+
"chat_template": "{%- macro json_to_python_type(param_name, json_spec) %}\n{%- set basic_type_map = {\n 'string': 'str',\n 'number': 'float',\n 'integer': 'int',\n 'boolean': 'bool',\n 'null': 'None'\n} %}\n\n{%- if json_spec.enum %}\n {{- param_name|title }}\n{%- elif basic_type_map[json_spec.type] is defined %}\n {{- basic_type_map[json_spec.type] }}\n{%- elif json_spec.type == 'array' %}\n {{- 'List[' + json_to_python_type(param_name, json_spec['items']) + ']' }}\n{%- elif json_spec.type == 'object' %}\n {{- 'Dict[str, ' + json_to_python_type(param_name, json_spec.additionalProperties if json_spec.additionalProperties else 'Any') + ']' if not json_spec.properties else param_name|title }}\n{%- elif json_spec.type is iterable %}\n {{- 'Union[' }}\n {%- for t in json_spec.type %}\n {{- json_to_python_type(param_name, {'type': t}) }}\n {{- ', ' if not loop.last }}\n {%- endfor %}\n {{- ']' }}\n{%- else %}\n {{- 'Any' }}\n{%- endif %}\n{%- endmacro %}\n\n{%- macro object_to_types(json_spec) %}\n {%- set o_ns = namespace(f = caller()) %}\n {%- for param_name, param_fields in json_spec.properties|items %}\n {%- if param_fields.enum %}\n {{- '\\nclass ' + param_name|title + '(Enum):\\n' }}\n {%- for enum_option in param_fields.enum %}\n {{- ' enum_' + loop.index0|string + ' = ' + enum_option|tojson + '\\n' }}\n {%- endfor %}\n {%- endif %}\n {%- endfor %}\n {{- o_ns.f }}\n{%- endmacro %}\n\n{%- macro tool_parser(tools) %}\n{%- for tool in tools %}\n {%- if tool.type is not defined or tool.type == 'function' %}\n {%- if tool.function is defined %}\n {%- set tool = tool.function %}\n {%- endif %}\n {%- set tool_params = tool.parameters if tool.parameters is defined else none %}\n {%- call object_to_types(tool_params) %}\n {{- '\\ndef ' + tool.name + '(' }}\n {%- if tool_params %}\n {%- for param_name, param_fields in tool_params.properties|items %}\n {%- set param_default = param_fields.default|tojson if param_fields.default is string else param_fields.default|string if param_fields.default is defined else 'None' %}\n {{- ', ' if loop.index0 != 0 }}\n {{- param_name + ': ' + ('Optional[' + json_to_python_type(param_name, param_fields) + ']' if param_name not in tool_params.required else json_to_python_type(param_name, param_fields)) }}\n {{- '=' + param_default if param_name not in tool_params.required }}\n {%- endfor %}\n {%- endif %}\n {{- ')' + (' -> ' + tool.return.type if tool.return and tool.return.type else '') + ':\\n \"\"\"\\n ' }}\n {{- tool.description + '\\n' }}\n {%- if tool_params %}\n {{- '\\n Args:\\n' if tool_params else '\\n' }}\n {%- for param_name, param_fields in tool_params.properties|items %}\n {{- ' - ' + param_name + ': ' + (param_fields.description if param_fields.description else '') + '\\n' }}\n {%- endfor %}\n {%- endif %}\n {{- '\\n Returns:\\n - ' + tool.return.description + '\\n' if tool.return and tool.return.description }}\n {%- endcall %}\n {{- ' \"\"\"\\n pass\\n' }}\n {%- endif %}\n{%- endfor %}\n{%- endmacro %}\n\n{%- if messages[0]['role'] == 'system' %}\n {%- set loop_messages = messages[1:] %}\n {%- set system_message = messages[0]['content'] %}\n{%- else %}\n {%- set loop_messages = messages %}\n {%- set system_message = 'You are an expert AI assistant that specializes in providing Python code to solve the task/problem at hand provided by the user.' %}\n{%- endif %}\n{{- '<|im_start|>system\\n' + system_message if system_message or tools }}\n{%- if tools %}\n {{- '''\n\nYou can use Python code freely, including the following available functions:\n\n<|functions_schema|>''' }}\n {{- tool_parser(tools) }}\n {{- '''<|end_functions_schema|>\n\nThe following dangerous builtins are restricted for security:\n- exec\n- eval\n- execfile\n- compile\n- importlib\n- input\n- exit\n\nThink step by step and provide your reasoning, outside of the function calls.\nYou can write Python code and use the available functions. Provide all your python code in a SINGLE markdown code block like the following:\n\n```python\nresult = example_function(arg1, \"string\")\nresult2 = example_function2(result, arg2)\n```\n\nDO NOT use print() statements AT ALL. Avoid mutating variables whenever possible.''' }}\n{%- endif %}\n{{- '<|im_end|>\\n' if system_message or tools }}\n{%- for message in loop_messages %}\n {%- set content = message.content %}\n {%- if message.role == 'assistant' and message.tool_calls %}\n {{- '<|im_start|>' + message.role + '\\n' }}\n {{- '<tool_call>\\n```python\\n' }}\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 {{- tool_call.name + '(' }}\n {%- if tool_call.arguments is defined and tool_call.arguments|length > 0 %}\n {%- for param_name, param_value in tool_call.arguments|items %}\n {{- param_name + '=' + param_value|tojson }}\n {{- ',' if not loop.last }}\n {%- endfor %}\n {%- endif %}\n {{- ')\\n' }}\n {%- endfor %}\n {{- '```\\n</tool_call>\\n' }}\n {{- content if content and not content.startswith('<tool_call>') }}\n {{- '<|im_end|>\\n' }}\n {%- else %}\n {{- '<|im_start|>' + message.role + '\\n' + content + '<|im_end|>\\n' }}\n {%- endif %}\n{%- endfor %}\n\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n{%- endif %}",
|
199 |
"clean_up_tokenization_spaces": false,
|
200 |
"eos_token": "<|im_end|>",
|
201 |
"errors": "replace",
|