{%- macro render_extra_keys(json_dict, handled_keys) -%}
    {%- if json_dict is mapping -%}
        {%- for json_key in json_dict if json_key not in handled_keys -%}
            {%- if json_dict[json_key] is string -%}
                {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | string) ~ '</' ~ json_key ~ '>' }}
            {%- else -%}
                {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | tojson | safe) ~ '</' ~ json_key ~ '>' }}
            {%- endif -%}
        {%- endfor -%}
    {%- endif -%}
{%- endmacro %}

{%- macro render_content(content, is_system_content=false) -%}
    {%- if content is string -%}
        {{- content }}
    {%- elif content is iterable and content is not mapping -%}
        {%- for item in content -%}
            {%- if item is mapping -%}
                {%- if item.type is defined and item.type == 'text' -%}
                    {{- item.text if item.text is defined else '' }}
                {%- elif 'text' in item -%}
                    {{- item.text }}
                {%- elif 'image' in item or 'image_url' in item or 'video' in item -%}
                    {{- raise_exception('This template is text-only and does not support image/video content.') }}
                {%- else -%}
                    {{- raise_exception('Unexpected item type in content.') }}
                {%- endif -%}
            {%- elif item is string -%}
                {{- item }}
            {%- else -%}
                {{- raise_exception('Unexpected non-text item in content.') }}
            {%- endif -%}
        {%- endfor -%}
    {%- elif content is none or content is undefined -%}
        {{- '' }}
    {%- else -%}
        {{- raise_exception('Unexpected content type.') }}
    {%- endif -%}
{%- endmacro %}

{%- if not messages or messages|length == 0 -%}
    {{- raise_exception('No messages provided.') }}
{%- endif -%}

{%- if not tools is defined or tools is none -%}
    {%- set tools = [] -%}
{%- endif -%}

{%- if messages[0].role == 'system' -%}
    {%- set system_message = render_content(messages[0].content, true) | trim -%}
    {%- set loop_messages = messages[1:] -%}
{%- else -%}
    {%- set system_message = none -%}
    {%- set loop_messages = messages -%}
{%- endif -%}

{# -------------------- system / tools preamble -------------------- #}
{%- if tools and tools is iterable and tools is not mapping and tools | length > 0 -%}
    {{- '
system\n' }}
    {%- if system_message -%}
        {{- system_message }}
        {{- '\n\n' }}
    {%- else -%}
        {{- 'You are Qwen, a helpful AI assistant that can interact with a computer to solve tasks.' }}
        {{- '\n\n' }}
    {%- endif -%}

    {{- '# Tools\n\nYou have access to the following functions:\n\n' }}
    {{- '<tools>' }}
    {%- for tool in tools -%}
        {%- if tool.function is defined -%}
            {%- set tool = tool.function -%}
        {%- endif -%}

        {{- '\n<function>\n<name>' ~ tool.name ~ '</name>' }}

        {%- if tool.description is defined -%}
            {{- '\n<description>' ~ (tool.description | trim) ~ '</description>' }}
        {%- endif -%}

        {{- '\n<parameters>' }}
        {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping -%}
            {%- for param_name, param_fields in tool.parameters.properties|items -%}
                {{- '\n<parameter>' }}
                {{- '\n<name>' ~ param_name ~ '</name>' }}
                {%- if param_fields.type is defined -%}
                    {{- '\n<type>' ~ (param_fields.type | string) ~ '</type>' }}
                {%- endif -%}
                {%- if param_fields.description is defined -%}
                    {{- '\n<description>' ~ (param_fields.description | trim) ~ '</description>' }}
                {%- endif -%}
                {%- set handled_keys = ['name', 'type', 'description'] -%}
                {{- render_extra_keys(param_fields, handled_keys) }}
                {{- '\n</parameter>' }}
            {%- endfor -%}
        {%- endif -%}

        {%- set handled_keys = ['type', 'properties'] -%}
        {{- render_extra_keys(tool.parameters, handled_keys) }}
        {{- '\n</parameters>' }}

        {%- set handled_keys = ['type', 'name', 'description', 'parameters'] -%}
        {{- render_extra_keys(tool, handled_keys) }}
        {{- '\n</function>' }}
    {%- endfor -%}
    {{- '\n</tools>' }}

    {{- '\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- Do not add any text after a function call\n- If there is no function call available, answer the question normally using your current knowledge and do not mention function calling\n</IMPORTANT>' }}

    {{- '
\n' }}
{%- else -%}
    {%- if system_message is not none -%}
        {{- '
system\n' + system_message + '
\n' }}
    {%- endif -%}
{%- endif -%}

{# -------------------- conversation -------------------- #}
{%- for message in loop_messages -%}
    {%- if message.role == 'user' -%}
        {%- set content = render_content(message.content) | trim -%}
        {{- '
user\n' + content + '
\n' }}

    {%- elif message.role == 'assistant' -%}
        {%- set content = render_content(message.content) | trim -%}
        {{- '
assistant' }}

        {%- if content -%}
            {{- '\n' + content }}
        {%- endif -%}

        {%- if message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls is not mapping and message.tool_calls | length > 0 -%}
            {%- for tool_call in message.tool_calls -%}
                {%- if tool_call.function is defined -%}
                    {%- set tool_call = tool_call.function -%}
                {%- endif -%}

                {%- if content or not loop.first -%}
                    {{- '\n' }}
                {%- endif -%}

                {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
                {%- if tool_call.arguments is defined -%}
                    {%- for args_name, args_value in tool_call.arguments|items -%}
                        {{- '<parameter=' + args_name + '>\n' }}
                        {%- set args_value = args_value if args_value is string else args_value | tojson | safe -%}
                        {{- args_value }}
                        {{- '\n</parameter>\n' }}
                    {%- endfor -%}
                {%- endif -%}
                {{- '</function>\n</tool_call>' }}
            {%- endfor -%}
        {%- endif -%}

        {{- '
\n' }}

    {%- elif message.role == 'tool' -%}
        {%- set content = render_content(message.content) | trim -%}
        {%- if loop.previtem and loop.previtem.role != 'tool' -%}
            {{- '
user' }}
        {%- endif -%}
        {{- '\n<tool_response>\n' }}
        {{- content }}
        {{- '\n</tool_response>' }}
        {%- if not loop.last and loop.nextitem.role != 'tool' -%}
            {{- '
\n' }}
        {%- elif loop.last -%}
            {{- '
\n' }}
        {%- endif -%}

    {%- elif message.role == 'system' -%}
        {{- raise_exception('System message must be at the beginning.') }}

    {%- else -%}
        {{- raise_exception('Unexpected message role.') }}
    {%- endif -%}
{%- endfor -%}

{%- if add_generation_prompt -%}
    {{- '
assistant\n' }}
{%- endif -%}