File size: 6,281 Bytes
baa0dbb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
{%- if tools is iterable and tools | length > 0 %}
{{- '<|im_start|>system
๋‹น์‹ ์€ ๋„๊ตฌ ํ˜ธ์ถœ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ์œ ์šฉํ•œ ๋„์šฐ๋ฏธ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•„์š”ํ•œ ๋„๊ตฌ๊ฐ€ ์ฃผ์–ด์ง„ ๋ชฉ๋ก์— ์žˆ๋Š” ๊ฒฝ์šฐ ๋„๊ตฌ ํ˜ธ์ถœ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
ํ•„์š”ํ•œ ๋„๊ตฌ๊ฐ€ ๋ชฉ๋ก์— ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ๋„๊ตฌ ํ˜ธ์ถœ ์—†์ด ์‚ฌ์šฉ์ž๊ฐ€ ์š”๊ตฌํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”.
ํ•„์š”ํ•œ ๋„๊ตฌ๊ฐ€ ๋ชฉ๋ก์— ์žˆ์ง€๋งŒ ํ•ด๋‹น ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ argument ์ •๋ณด๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ ํ•ด๋‹น ์ •๋ณด๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ์š”์ฒญํ•˜์„ธ์š”.
์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ๋Ÿฌ๋ฒˆ ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋„๊ตฌ ํ˜ธ์ถœ ์ดํ›„ ๋„๊ตฌ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์œผ๋ฉด ํ•ด๋‹น ๊ฒฐ๊ณผ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ต๋ณ€์„ ์ƒ์„ฑํ•˜์„ธ์š”.

๋‹ค์Œ์€ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ๋“ค์˜ ๋ชฉ๋ก ์ž…๋‹ˆ๋‹ค:
<tools>
' }}
    {%- for t in tools %}
        {{- t | tojson }}
        {{- '\n' }}
    {%- endfor %}
{{- '</tools>

๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด ์•„๋ž˜์˜ JSON์œผ๋กœ ์‘๋‹ตํ•˜์„ธ์š”.
๋„๊ตฌ ํ˜ธ์ถœ ํ˜•์‹: <tool_call>{"name": ๋„๊ตฌ ์ด๋ฆ„, "arguments": dictionary ํ˜•ํƒœ์˜ ๋„๊ตฌ ์ธ์ž๊ฐ’}</tool_call><|im_end|>
' }}
{%- endif %}

{%- macro render_content(content) -%}
    {#- `content` may be a plain string, none, or a list of parts as sent by
        OpenAI-compatible clients: [{"type": "text", "text": "..."}] -#}
    {%- if content is none -%}
    {%- elif content is string -%}
        {{- content -}}
    {%- elif content is mapping -%}
        {{- content.text if content.text is defined else content -}}
    {%- elif content is sequence -%}
        {%- for part in content -%}
            {%- if part is mapping and part.text is defined -%}
                {{- part.text -}}
            {%- elif part is string -%}
                {{- part -}}
            {%- endif -%}
        {%- endfor -%}
    {%- else -%}
        {{- content -}}
    {%- endif -%}
{%- endmacro -%}

{%- macro render_tool_calls(tool_calls) -%}
    {%- for tool_call in tool_calls -%}
        {%- if tool_call.function is defined -%}
            {%- set tool_call = tool_call.function -%}
        {%- endif -%}
        {{- '<tool_call>\n' -}}
        {{- '{"name": "' + tool_call.name + '"' -}}
        {%- if tool_call.arguments is defined -%}
            {{- ', "arguments": ' -}}
            {#- OpenAI-compatible clients send `arguments` as a JSON string; pass it through -#}
            {%- if tool_call.arguments is string -%}
                {{- tool_call.arguments -}}
            {%- else -%}
                {{- tool_call.arguments | tojson -}}
            {%- endif -%}
        {%- endif -%}
        {{- '}\n</tool_call>' -}}
    {%- endfor -%}
{%- endmacro -%}

{%- set ns = namespace(last_user_index=-1) %}
{%- for m in messages %}
    {%- if m.role == 'user' %}
        {%- set ns.last_user_index = loop.index0 %}
    {%- endif %}
{%- endfor %}

{%- for message in messages %}
    {%- if message.role == 'system' or message.role == 'user' %}
        {{- '<|im_start|>' + message.role + '\n' }}
        {%- set reasoning_content = '' %}
        {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
            {%- set reasoning_content = message.reasoning_content %}
        {%- elif message.reasoning is defined and message.reasoning is not none %}
            {%- set reasoning_content = message.reasoning %}
        {%- endif %}
        {%- if reasoning_content %}
            {{- '<think>' + reasoning_content.strip() + '</think>' }}
        {%- endif %}
        {{- render_content(message.content) }}
	{%- if message.tool_calls is defined and message.tool_calls is not none %}
            {{- render_tool_calls(message.tool_calls) }}
        {%- endif %}
        {{- '<|im_end|>\n' }}
    {%- elif message.role == 'assistant' %}
        {{- '<|im_start|>assistant\n' }}

        {#- Extract reasoning and content -#}
        {%- set reasoning_content = '' %}
        {%- set content = '' %}
        {%- if message.content is defined and message.content is not none %}
            {%- set content = render_content(message.content) %}
        {%- endif %}
        {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
            {%- set reasoning_content = message.reasoning_content %}
        {%- elif message.reasoning is defined and message.reasoning is not none %}
            {%- set reasoning_content = message.reasoning %}
        {%- elif '</think>' in content %}
            {%- set reasoning_content = content.split('</think>')[0].split('<think>')[-1] %}
            {%- set content = content.split('</think>')[-1].lstrip('\n') %}
        {%- endif %}

        {#- Determine whether to render thinking -#}
        {%- set render_thinking = false %}
        {%- if reasoning_content %}
            {%- if show_thinking is defined and show_thinking %}
                {%- set render_thinking = true %}
            {%- elif not (show_thinking is defined and not show_thinking) %}
                {#- show_thinking undefined: show if last turn or tool-call turn after last user -#}
                {%- if loop.last or (message.tool_calls is defined and loop.index0 > ns.last_user_index) %}
                    {%- set render_thinking = true %}
                {%- endif %}
            {%- endif %}
        {%- endif %}
        {%- if render_thinking %}
            {{- '<think>' + reasoning_content.strip() + '</think>' }}
        {%- else %}
            {{- '</think>' }}
        {%- endif %}

        {{- content }}
	{%- if message.tool_calls is defined and message.tool_calls is not none %}
            {{- render_tool_calls(message.tool_calls) }}
        {%- endif %}
        {{- '<|im_end|>' + ('\n' if (not loop.last or add_generation_prompt) else '') }}
    {%- elif message.role == 'tool' %}
        {{- '<|im_start|>tool\n' }}
        {{- '<tool_response>\n' }}
        {{- render_content(message.content) }}
        {{- '\n' }}
        {{- '</tool_response><|im_end|>\n' }}
    {%- endif %}
{%- endfor %}

{%- if add_generation_prompt %}
    {{- '<|im_start|>assistant\n' }}
    {%- if enable_thinking is defined and enable_thinking is true %}
        {{- '<think>' }}
    {%- else %}
        {{- '</think>' }}
    {%- endif %}
{%- endif %}