menesnas commited on
Commit
5a4ba7f
·
verified ·
1 Parent(s): 9c31ffc

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +162 -0
  2. chat_template.jinja +99 -0
  3. main.py +137 -0
README.md ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Pharmacy Prompt Serialization Format (PPSF) — Custom Jinja2 Chat Template
2
+
3
+ Bu proje, bir dil modelinin (LLM) kullanıcı, sistem, asistan ve araç (tool calling) mesajlarını doğru ayırt edebilmesi ve **Pharmacy Prompt Serialization Format (PPSF v1.0 / v1.1)** spesifikasyonuna uygun şekilde serileştirmesi için geliştirilmiş bir **Custom Jinja2 Chat Template** uygulamasıdır.
4
+
5
+ Hugging Face `transformers` kütüphanesinin `apply_chat_template()` fonksiyonu ile **%100 tam uyumlu** olarak çalışacak şekilde tasarlanmıştır.
6
+
7
+ ---
8
+
9
+ ## 🎯 Ödev Amacı ve Özellikler
10
+
11
+ - **Hugging Face Standartlarına Tam Uyumluluk:** Standart `messages` dizisini (`role`, `content`, `tool_calls`) ve `tools` listesini kabul eder.
12
+ - **Alan Spesifik Rol Tanımları (Pharmacy Protocol):**
13
+ - `system` $\rightarrow$ `@SYSTEM`
14
+ - `user` $\rightarrow$ `@PATIENT`
15
+ - `assistant` $\rightarrow$ `@PHARMACIST`
16
+ - `tool` $\rightarrow$ `@TOOL_RESPONSE`
17
+ - **Tool Calling (Araç Çağrısı) Desteği:**
18
+ - Mevcut araç tanımlarını `@TOOLS` bloğu altında ilan eder.
19
+ - Asistanın araç çağırma isteklerini `@TOOL_CALL` formatında formatlar.
20
+ - Araç yanıtlarını `@TOOL_RESPONSE` olarak bağlama ekler.
21
+ - **Geleceğe Uyumlu Metadata Desteği (PPSF v1.1):**
22
+ - Mesaj nesnesinde yer alan `metadata.reference` verilerini `@REFERENCE` bloğuna dönüştürür.
23
+ - Mesaj nesnesinde yer alan `metadata.thought` verilerini (Chain of Thought) `@THOUGHT` bloğuna dönüştürür.
24
+
25
+ ---
26
+
27
+ ## 📁 Proje Dosya Yapısı
28
+
29
+ ```
30
+ Chat_Template/
31
+ ├── chat_template.jinja # PPSF v1.0 / v1.1 Jinja2 şablon dosyası
32
+ ├── main.py # Jinja2 ve Hugging Face AutoTokenizer test scripti
33
+ └── README.md # Proje dokümantasyonu
34
+ ```
35
+
36
+ ---
37
+
38
+ ## 🚀 Kurulum ve Çalıştırma
39
+
40
+ ### 1. Gereksinimler
41
+ Projeyi çalıştırmak için Python 3.8+ ve aşağıdaki kütüphanelerin kurulu olması yeterlidir:
42
+
43
+ ```bash
44
+ pip install jinja2 transformers
45
+ ```
46
+
47
+ ### 2. Test Scriptini Çalıştırma
48
+ Tüm test senaryolarını (Standart sohbet, Tool Calling ve Metadata kullanımı) çalıştırmak için:
49
+
50
+ ```bash
51
+ python main.py
52
+ ```
53
+
54
+ ---
55
+
56
+ ## 💻 Kullanım Örnekleri
57
+
58
+ ### Hugging Face `transformers` ile Kullanım
59
+
60
+ ```python
61
+ from transformers import AutoTokenizer
62
+
63
+ # Herhangi bir tokenizer yüklendikten sonra özel şablon atanabilir:
64
+ tokenizer = AutoTokenizer.from_pretrained("gpt2")
65
+
66
+ with open("chat_template.jinja", "r", encoding="utf-8") as f:
67
+ tokenizer.chat_template = f.read()
68
+
69
+ messages = [
70
+ {"role": "system", "content": "Sen uzman bir eczacı yapay zekâsısın."},
71
+ {"role": "user", "content": "Boğazım ağrıyor."}
72
+ ]
73
+
74
+ prompt = tokenizer.apply_chat_template(
75
+ messages,
76
+ add_generation_prompt=True,
77
+ tokenize=False
78
+ )
79
+
80
+ print(prompt)
81
+ ```
82
+
83
+ **Üretilen Çıktı:**
84
+ ```text
85
+ @FORMAT PPSF/1.0
86
+
87
+ @SYSTEM
88
+ Sen uzman bir eczacı yapay zekâsısın.
89
+
90
+ @PATIENT
91
+ Boğazım ağrıyor.
92
+
93
+ @PHARMACIST
94
+ ```
95
+
96
+ ---
97
+
98
+ ### Tool Calling Senaryosu Örneği
99
+
100
+ **Girdi:**
101
+ ```python
102
+ messages = [
103
+ {"role": "system", "content": "Sen uzman bir eczacı yapay zekâsısın."},
104
+ {"role": "user", "content": "Parol ne işe yarar?"},
105
+ {
106
+ "role": "assistant",
107
+ "content": None,
108
+ "tool_calls": [
109
+ {
110
+ "function": {
111
+ "name": "search_drug",
112
+ "arguments": {"drug": "Parol"}
113
+ }
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ "role": "tool",
119
+ "content": '{"drug": "Parol", "active_ingredient": "Parasetamol", "usage": "Ağrı kesici ve ateş düşürücü"}'
120
+ }
121
+ ]
122
+ ```
123
+
124
+ **Üretilen Çıktı:**
125
+ ```text
126
+ @FORMAT PPSF/1.0
127
+
128
+ @SYSTEM
129
+ Sen uzman bir eczacı yapay zekâsısın.
130
+
131
+ @PATIENT
132
+ Parol ne işe yarar?
133
+
134
+ @TOOL_CALL
135
+ {
136
+ "name": "search_drug",
137
+ "arguments": {"drug": "Parol"}
138
+ }
139
+
140
+ @TOOL_RESPONSE
141
+ {"drug": "Parol", "active_ingredient": "Parasetamol", "usage": "Ağrı kesici ve ateş düşürücü"}
142
+
143
+ @PHARMACIST
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 🏛️ Mimari Tasarım Notları (PPSF v1.1 Desteği)
149
+
150
+ Hugging Face standart `messages` yapısında `thought` veya `reference` rolleri bulunmamaktadır. Bu nedenle PPSF formatında CoT (Düşünce Adımları) ve RAG (Referans Dokümanlar) desteği `metadata` nesnesi üzerinden sağlanmıştır:
151
+
152
+ ```python
153
+ {
154
+ "role": "user",
155
+ "content": "Grip için hangi ilacı kullanmalıyım?",
156
+ "metadata": {
157
+ "reference": "[Kılavuz Doc #42]: Parasetamol 500mg tercih edilir."
158
+ }
159
+ }
160
+ ```
161
+
162
+ Jinja2 şablonu bu `metadata` içeriğini otomatik olarak algılar ve `@REFERENCE` ile `@THOUGHT` bloklarını sırasıyla bağlama yerleştirir. Bu yaklaşım, ekosistem uyumluluğunu bozmadan formatı genişletilebilir kılar.
chat_template.jinja ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#-
2
+ Pharmacy Prompt Serialization Format (PPSF) v1.0 / v1.1
3
+
4
+ Supported roles:
5
+ system -> @SYSTEM
6
+ user -> @PATIENT (with optional @REFERENCE via metadata)
7
+ assistant -> @PHARMACIST (with optional @THOUGHT via metadata)
8
+ tool -> @TOOL_RESPONSE
9
+
10
+ Tool Calling:
11
+ tools -> @TOOLS
12
+ tool_calls -> @TOOL_CALL
13
+
14
+ Copyright:
15
+ PPSF v1.0
16
+ -#}
17
+ {{- "@FORMAT PPSF/1.0\n\n" -}}
18
+
19
+ {#- ===========================
20
+ SYSTEM MESSAGE
21
+ =========================== -#}
22
+ {%- if messages and messages[0]["role"] == "system" -%}
23
+ @SYSTEM
24
+ {{ messages[0]["content"] | trim }}
25
+
26
+ {% endif -%}
27
+
28
+ {#- ===========================
29
+ TOOL DEFINITIONS
30
+ =========================== -#}
31
+ {%- if tools -%}
32
+ @TOOLS
33
+ Available tools:
34
+
35
+ {% for tool in tools -%}
36
+ {{ tool | tojson }}
37
+ {% endfor %}
38
+ To invoke a tool respond ONLY with:
39
+
40
+ @TOOL_CALL
41
+ {
42
+ "name": "...",
43
+ "arguments": { ... }
44
+ }
45
+
46
+ {% endif -%}
47
+
48
+ {#- ===========================
49
+ CHAT HISTORY
50
+ =========================== -#}
51
+ {%- for message in messages -%}
52
+ {%- if loop.first and message["role"] == "system" -%}
53
+ {# Handled in system block #}
54
+ {%- elif message["role"] == "user" -%}
55
+ {%- set ref = message.get("reference") or (message.get("metadata") and message.metadata.get("reference")) -%}
56
+ {%- if ref -%}
57
+ @REFERENCE
58
+ {{ ref | trim }}
59
+
60
+ {% endif -%}
61
+ @PATIENT
62
+ {{ message["content"] | trim }}
63
+
64
+ {% elif message["role"] == "assistant" -%}
65
+ {%- set thought = message.get("thought") or (message.get("metadata") and message.metadata.get("thought")) -%}
66
+ {%- if thought -%}
67
+ @THOUGHT
68
+ {{ thought | trim }}
69
+
70
+ {% endif -%}
71
+ {%- if message.get("content") -%}
72
+ @PHARMACIST
73
+ {{ message["content"] | trim }}
74
+
75
+ {% endif -%}
76
+ {%- if message.get("tool_calls") -%}
77
+ {%- for tc in message["tool_calls"] -%}
78
+ @TOOL_CALL
79
+ {
80
+ "name": {{ tc["function"]["name"] | tojson }},
81
+ "arguments": {{ tc["function"]["arguments"] if tc["function"]["arguments"] is string else (tc["function"]["arguments"] | tojson) }}
82
+ }
83
+
84
+ {% endfor -%}
85
+ {%- endif -%}
86
+ {%- elif message["role"] == "tool" -%}
87
+ @TOOL_RESPONSE
88
+ {{ message["content"] | trim }}
89
+
90
+ {% endif -%}
91
+ {%- endfor -%}
92
+
93
+ {#- ===========================
94
+ GENERATION PROMPT
95
+ =========================== -#}
96
+ {%- if add_generation_prompt -%}
97
+ @PHARMACIST
98
+ {%- endif -%}
99
+
main.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import jinja2
3
+
4
+ def tojson_filter(val, indent=None):
5
+ if indent is not None:
6
+ return json.dumps(val, ensure_ascii=False, indent=indent)
7
+ return json.dumps(val, ensure_ascii=False)
8
+
9
+ def render_with_jinja(template_path, messages, tools=None, add_generation_prompt=False):
10
+ with open(template_path, "r", encoding="utf-8") as f:
11
+ template_content = f.read()
12
+
13
+ env = jinja2.Environment(trim_blocks=True, lstrip_blocks=True)
14
+ env.filters["tojson"] = tojson_filter
15
+
16
+ template = env.from_string(template_content)
17
+ return template.render(
18
+ messages=messages,
19
+ tools=tools,
20
+ add_generation_prompt=add_generation_prompt
21
+ )
22
+
23
+ def render_with_huggingface(template_path, messages, tools=None, add_generation_prompt=False):
24
+ try:
25
+ from transformers import AutoTokenizer
26
+ with open(template_path, "r", encoding="utf-8") as f:
27
+ template_content = f.read()
28
+
29
+ tokenizer = AutoTokenizer.from_pretrained("gpt2")
30
+ tokenizer.chat_template = template_content
31
+ return tokenizer.apply_chat_template(
32
+ messages,
33
+ tools=tools,
34
+ add_generation_prompt=add_generation_prompt,
35
+ tokenize=False
36
+ )
37
+ except Exception as e:
38
+ return f"[HuggingFace Error / Not Available]: {e}"
39
+
40
+ if __name__ == "__main__":
41
+ template_file = "chat_template.jinja"
42
+
43
+ print("=" * 60)
44
+ print(" 1. Standart Sohbet Senaryosu (PPSF v1.0)")
45
+ print("=" * 60)
46
+ messages_1 = [
47
+ {
48
+ "role": "system",
49
+ "content": "Sen uzman bir eczacı yapay zekâsısın."
50
+ },
51
+ {
52
+ "role": "user",
53
+ "content": "Boğazım ağrıyor."
54
+ }
55
+ ]
56
+
57
+ print("\n--- [Jinja2 Output] ---")
58
+ print(render_with_jinja(template_file, messages_1, add_generation_prompt=True))
59
+
60
+ print("--- [HuggingFace apply_chat_template Output] ---")
61
+ print(render_with_huggingface(template_file, messages_1, add_generation_prompt=True))
62
+
63
+ print("=" * 60)
64
+ print(" 2. Tool Calling & Tool Response Senaryosu")
65
+ print("=" * 60)
66
+ messages_2 = [
67
+ {
68
+ "role": "system",
69
+ "content": "Sen uzman bir eczacı yapay zekâsısın."
70
+ },
71
+ {
72
+ "role": "user",
73
+ "content": "Parol ne işe yarar?"
74
+ },
75
+ {
76
+ "role": "assistant",
77
+ "content": None,
78
+ "tool_calls": [
79
+ {
80
+ "function": {
81
+ "name": "search_drug",
82
+ "arguments": {"drug": "Parol"}
83
+ }
84
+ }
85
+ ]
86
+ },
87
+ {
88
+ "role": "tool",
89
+ "content": '{"drug": "Parol", "active_ingredient": "Parasetamol", "usage": "Ağrı kesici ve ateş düşürücü"}'
90
+ }
91
+ ]
92
+
93
+ tools_2 = [
94
+ {
95
+ "name": "search_drug",
96
+ "description": "Verilen ilaç hakkında detaylı bilgi arar.",
97
+ "parameters": {
98
+ "type": "object",
99
+ "properties": {
100
+ "drug": {"type": "string", "description": "İlaç adı"}
101
+ },
102
+ "required": ["drug"]
103
+ }
104
+ }
105
+ ]
106
+
107
+ print("\n--- [Jinja2 Output] ---")
108
+ print(render_with_jinja(template_file, messages_2, tools=tools_2, add_generation_prompt=True))
109
+
110
+ print("=" * 60)
111
+ print(" 3. PPSF v1.1 Gelecek Uyumlu Metadata (@THOUGHT & @REFERENCE)")
112
+ print("=" * 60)
113
+ messages_3 = [
114
+ {
115
+ "role": "system",
116
+ "content": "Sen uzman bir eczacı yapay zekâsısın."
117
+ },
118
+ {
119
+ "role": "user",
120
+ "content": "Grip için hangi ilacı kullanmalıyım?",
121
+ "metadata": {
122
+ "reference": "[Kılavuz Doc #42]: Parasetamol 500mg hafif ağrı ve ateş durumlarında tercih edilir."
123
+ }
124
+ },
125
+ {
126
+ "role": "assistant",
127
+ "content": "Ateş ve hafif ağrınız varsa doktor veya eczacınıza danışarak Parasetamol içerikli ilaçlar tercih edebilirsiniz.",
128
+ "metadata": {
129
+ "thought": "Kullanıcının semptomları grip kaynaklı ateş ve hafif ağrı belirtilerine uymaktadır. Referans doküman #42 incelenerek Parasetamol tavsiye edildi."
130
+ }
131
+ }
132
+ ]
133
+
134
+ print("\n--- [Jinja2 Output] ---")
135
+ print(render_with_jinja(template_file, messages_3, add_generation_prompt=False))
136
+
137
+