File size: 5,213 Bytes
38436fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# Özel Chat Template (Jinja2)

Bir dil modelinin `system`, `user`, `assistant` ve `tool` rollerini ayırt
edebilmesi ve tool calling (function calling) yapabilmesi için hazırlanmış
Jinja2 sohbet şablonu.

## Chat template nedir?

Dil modelleri mesaj listesi göremez; yalnızca düz metin (token dizisi) işler.
Kod tarafında şöyle bir yapı kullanılır:

```python
[
  {"role": "user", "content": "Merhaba"},
  {"role": "assistant", "content": "Selam!"}
]
```

Chat template bu yapıyı modelin anlayacağı düz metne çevirir:

```
<|im_start|>mustafa
Merhaba<|im_end|>
<|im_start|>AI
Selam!<|im_end|>
```

Her model eğitim sırasında belirli bir biçim görür; çıkarımda da aynı biçimi
bekler. Biçim uyuşmazsa model beklenmedik davranır.

## Bu şablonun özellikleri

| Özellik | Açıklama |
|---|---|
| Rol dönüşümü | `user` → `mustafa`, `assistant` → `AI` |
| Araç tanımları | `tools` listesi sistem bloğuna JSON olarak gömülür |
| Araç çağrısı | Assistant mesajındaki `tool_calls` alanı `<tool_call>` etiketleriyle sarmalanır |
| Çoklu çağrı | Model aynı turda birden fazla araç çağırabilir |
| Araç sonucu | `tool` rolü `<tool_response>` etiketleriyle sarmalanır |
| Üretim istemi | `add_generation_prompt` ile son satır açık bırakılır |
| Doğrulama | Bilinmeyen rol gelirse hata fırlatılır |

## Rol eşlemesi

Şablon, standart rol adlarını kendi adlarına çevirir:

| Standart (kodda kullanılan) | Şablonda üretilen |
|---|---|
| `system` | `system` |
| `user` | **`mustafa`** |
| `assistant` | **`AI`** |
| `tool` | `tool` |

Bu sayede kod tarafında OpenAI/Hugging Face standardı korunur; dönüşümü şablon
yapar. Model değiştirildiğinde uygulama kodunu değiştirmek gerekmez.

## Örnek çıktı

**Girdi:**

```python
messages = [
    {"role": "system", "content": "Sen yardımcı bir asistansın."},
    {"role": "user", "content": "Ankara'da hava nasıl?"},
    {"role": "assistant", "content": None, "tool_calls": [
        {"function": {"name": "get_weather", "arguments": {"city": "Ankara"}}}
    ]},
    {"role": "tool", "content": '{"sehir": "Ankara", "sicaklik_c": 27}'},
    {"role": "assistant", "content": "Ankara'da hava 27°C."},
]
```

**Çıktı:**

```
<|im_start|>system
Sen yardımcı bir asistansın.

Kullanabileceğin araçlar:
<tools>
{"name": "get_weather", "description": "Bir şehrin güncel hava durumunu döndürür.", "parameters": {...}}
</tools>

Bir aracı çağırmak için şu biçimi kullan:
<tool_call>
{"name": "araç_adı", "arguments": {...}}
</tool_call><|im_end|>
<|im_start|>mustafa
Ankara'da hava nasıl?<|im_end|>
<|im_start|>AI
<tool_call>
{"name": "get_weather", "arguments": {"city": "Ankara"}}
</tool_call><|im_end|>
<|im_start|>tool
<tool_response>
{"sehir": "Ankara", "sicaklik_c": 27}
</tool_response><|im_end|>
<|im_start|>AI
Ankara'da hava 27°C.<|im_end|>
```

## Kullanım

### Hugging Face tokenizer ile

```python
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("model-adi")
tokenizer.chat_template = open("chat_template.jinja", encoding="utf-8").read()

metin = tokenizer.apply_chat_template(
    messages,
    tools=tools,
    add_generation_prompt=True,   # çıkarımda True, eğitimde False
    tokenize=False,
)
```

Şablonu modelle birlikte yayınlamak için `chat_template.jinja` dosyasını model
deposuna eklemek yeterlidir.

### Doğrudan Jinja2 ile

```python
from jinja2 import Environment

env = Environment()
env.globals["raise_exception"] = lambda m: (_ for _ in ()).throw(ValueError(m))
env.policies["json.dumps_kwargs"] = {"ensure_ascii": False, "sort_keys": False}

sablon = env.from_string(open("chat_template.jinja", encoding="utf-8").read())
print(sablon.render(messages=messages, tools=tools, add_generation_prompt=True))
```

`ensure_ascii=False` ayarı önemlidir: Türkçe karakterlerin `\u015f` gibi kaçış
dizilerine dönüşmesini engeller ve gereksiz token harcanmasını önler.

## `add_generation_prompt` nedir?

Aynı şablon iki farklı amaçla kullanılır:

**Eğitimde (`False`)** — konuşma tamamlanmıştır, model bunu öğrenecektir:

```
<|im_start|>mustafa
Nasılsın?<|im_end|>
<|im_start|>AI
İyiyim!<|im_end|>
```

**Çıkarımda (`True`)** — son satır açık bırakılır, model buradan devam eder:

```
<|im_start|>mustafa
Nasılsın?<|im_end|>
<|im_start|>AI
```

Bu açık satır olmazsa model ne yapacağını bilemez; kendi kullanıcı mesajı
uydurabilir veya konuşmayı sonlandırabilir.

## Test

```bash
pip install jinja2
python test_template.py
```

Test scripti beş senaryoyu kontrol eder:

1. Basit konuşma (araçsız)
2. Üretim istemi davranışı
3. Tam tool calling akışı (çok turlu, çoklu çağrı)
4. Sistem mesajı olmadan araç kullanımı
5. Geçersiz rol reddi

Ayrıca sekiz doğrulama yapar: HTML kaçışı olmaması, Türkçe karakterlerin
korunması, rol dönüşümleri, etiket sarmalama ve üretilen JSON'ların
ayrıştırılabilir olması.

## Dosyalar

| Dosya | İçerik |
|---|---|
| `chat_template.jinja` | Şablonun kendisi |
| `test_template.py` | Test ve doğrulama scripti |
| `README.md` | Bu dosya |

## Lisans

MIT