Transformers documentation
Sohbet şablonları
Sohbet şablonları
Sohbet temelleri kılavuzu, TextGenerationPipeline kullanarak sohbet geçmişlerini nasıl saklayacağınızı ve sohbet modellerinden metin nasıl üreteceğinizi açıklar.
Bu kılavuz daha ileri düzey kullanıcılar için hazırlanmıştır; alt sınıfları ve yöntemleri, ayrıca bir modelle sohbet ederken gerçekte neler olduğunu anlamanız için temel kavramları kapsar.
Chat modellerini anlamak için gereken kritik içgörü şudur: Chat eğitimi yapılmış olsun ya da olmasın, tüm nedensel LM'ler bir token dizisini devam ettirir. Nedensel LM'ler eğitilirken eğitim genellikle devasa bir metin korpusu üzerinde “ön-eğitim” ile başlar ve bu da bir “taban” modeli oluşturur.
Bu taban modelleri daha sonra genellikle chat için “ince ayarlanır”; bu, mesaj dizisi olarak biçimlendirilmiş veriler üzerinde eğitilmeleri anlamına gelir. Yine de chat hâlâ sadece bir token dizisidir! Chat modeline ilettiğiniz role ve content sözlükleri listesi, modelin chat yapısını görmesini sağlayan <|user|> veya <|assistant|> veya <|end_of_message|> gibi kontrol token'ları ile genellikle bir token dizisine dönüştürülür.
Birçok olası chat biçimi vardır ve farklı modeller, aynı taban modelinden ince ayarlanmış olsalar bile farklı biçimler veya kontrol token'ları kullanabilir!
Panik yapmayın - sohbet modellerini kullanmak için olası tüm sohbet biçimlerini ezberlemeniz gerekmez. Sohbet modelleri, sohbetlerin nasıl biçimlendirilmesini beklediklerini gösteren sohbet şablonları ile birlikte gelir.
Bunlara apply_chat_template yöntemiyle erişebilirsiniz. İki örneğe bakalım. Bu iki model de aynı Mistral-7B temel modelinden ince ayarlanmıştır:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-Instruct-v0.1")
chat = [
{"role": "user", "content": "Hello, how are you?"},
{"role": "assistant", "content": "I'm doing great. How can I help you today?"},
{"role": "user", "content": "I'd like to show off how chat templating works!"},
]
tokenizer.apply_chat_template(chat, tokenize=False)<s>[INST] Hello, how are you? [/INST]I'm doing great. How can I help you today?</s> [INST] I'd like to show off how chat templating works! [/INST]from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta")
chat = [
{"role": "user", "content": "Hello, how are you?"},
{"role": "assistant", "content": "I'm doing great. How can I help you today?"},
{"role": "user", "content": "I'd like to show off how chat templating works!"},
]
tokenizer.apply_chat_template(chat, tokenize=False)<|user|>\nHello, how are you?</s>\n<|assistant|>\nI'm doing great. How can I help you today?</s>\n<|user|>\nI'd like to show off how chat templating works!</s>\nMistral-7B-Instruct, kullanıcı mesajlarının başlangıcını ve sonunu belirtmek için [INST] ve [/INST] jetonlarını kullanırken, Zephyr-7B konuşmacı rollerini belirtmek için <|user|> ve <|assistant|> jetonlarını kullanır. Sohbet şablonlarının önemli olmasının nedeni budur; yanlış kontrol jetonlarıyla bu modellerin performansı ciddi şekilde düşerdi.
apply_chat_template kullanılarak
apply_chat_template girdisi, role ve content anahtarlarına sahip sözlüklerden oluşan bir liste olarak yapılandırılmalıdır. role anahtarı konuşmacıyı belirtir, content anahtarı ise mesajı içerir. Yaygın roller şunlardır:
- Kullanıcıdan gelen mesajlar için
user - modelden gelen mesajlar için
assistant system, modelin nasıl davranması gerektiğine dair talimatlar için (genellikle sohbetin başına yerleştirilir)
apply_chat_template bu listeyi alır ve biçimlendirilmiş bir dizi döndürür. Diziyi belirteçlere ayırmak istiyorsanız tokenize=True olarak ayarlayın.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta")
model = AutoModelForCausalLM.from_pretrained("HuggingFaceH4/zephyr-7b-beta", device_map="auto", dtype=torch.bfloat16)
messages = [
{"role": "system", "content": "You are a friendly chatbot who always responds in the style of a pirate",},
{"role": "user", "content": "How many helicopters can a human eat in one sitting?"},
]
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt").to(model.device)
print(tokenizer.decode(tokenized_chat["input_ids"][0]))<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s>
<|user|>
How many helicopters can a human eat in one sitting?</s>
<|assistant|>Tokenize edilmiş sohbeti bir yanıt oluşturmak için generate() işlevine iletin.
outputs = model.generate(**tokenized_chat, max_new_tokens=128)
print(tokenizer.decode(outputs[0]))<|system|>
You are a friendly chatbot who always responds in the style of a pirate</s>
<|user|>
How many helicopters can a human eat in one sitting?</s>
<|assistant|>
Matey, I'm afraid I must inform ye that humans cannot eat helicopters. Helicopters are not food, they are flying machines. Food is meant to be eaten, like a hearty plate o' grog, a savory bowl o' stew, or a delicious loaf o' bread. But helicopters, they be for transportin' and movin' around, not for eatin'. So, I'd say none, me hearties. None at all.Bazı tokenizörler özel
<bos>ve<eos>tokenları ekler. Sohbet şablonları zaten gerekli tüm özel tokenları içermelidir ve ek özel tokenlar eklemek genellikle hatalı veya yinelenmiş olur, bu da model performansını olumsuz etkiler. Metniapply_chat_template(tokenize=False)ile biçimlendirdiğinizde, bu tokenların yinelenmesini önlemek için daha sonra tokenizasyon yapacaksanızadd_special_tokens=Falseayarını yaptığınızdan emin olun.apply_chat_template(tokenize=True)kullanıyorsanız bu bir sorun değildir, bu da genellikle daha güvenli seçenek olduğu anlamına gelir!
add_generation_prompt
Yukarıdaki örneklerde add_generation_prompt argümanını fark etmiş olabilirsiniz.
Bu argüman, sohbetin sonuna, bir assistant yanıtının başlangıcını gösteren token'ları ekler. Unutmayın: Tüm sohbet soyutlamalarının altında, sohbet modelleri hâlâ bir token dizisini devam ettiren dil modelleridir!
Şu anda bir assistant yanıtında olduğunu söyleyen token'ları dahil ederseniz, model doğru bir yanıt yazar; ancak bu token'ları dahil etmezseniz, model kafa karışıklığına uğrayıp kullanıcının mesajına yanıt vermek yerine onu devam ettirmek gibi garip bir şey yapabilir!
add_generation_prompt'ın ne yaptığını anlamak için bir örneğe bakalım. Önce, add_generation_prompt olmadan bir sohbet biçimlendirelim:
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=False)
tokenized_chat<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
<|im_start|>user
Can I ask a question?<|im_end|>Şimdi, aynı sohbeti add_generation_prompt=True ile biçimlendirelim:
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
tokenized_chat<|im_start|>user
Hi there!<|im_end|>
<|im_start|>assistant
Nice to meet you!<|im_end|>
<|im_start|>user
Can I ask a question?<|im_end|>
<|im_start|>assistant
add_generation_prompt=True olduğunda, assistant mesajının başlangıcını belirtmek için sona <|im_start|>assistant eklenir. Bu, modelin sıradaki yanıtın bir assistant yanıtı olduğunu bilmesini sağlar.
Tüm modellerin üretim istemcileri (generation prompt) gerektirmesi gerekmez ve Llama gibi bazı modellerde assistant yanıtından önce özel token'lar bulunmaz. Bu durumlarda add_generation_prompt parametresi herhangi bir etkiye sahip değildir.
continue_final_message
continue_final_message parametresi, sohbetin sonundaki mesajın yeni bir mesaj başlatmak yerine devam ettirilip ettirilmeyeceğini kontrol eder. Modelin son mesajdan devam etmesini sağlamak için dizin sonu (end of sequence) tokenlarını kaldırır.
Bu, bir model yanıtını “ön doldurmak” için kullanışlıdır. Aşağıdaki örnekte model, yeni bir mesaj başlatmak yerine JSON dizgesini sürdüren metin üretir. Yanıtlarını nasıl başlatacağını bildiğinizde, talimat uyumunun doğruluğunu artırmak için son derece faydalı olabilir.
chat = [
{"role": "user", "content": "Can you format the answer in JSON?"},
{"role": "assistant", "content": '{"name": "'},
]
formatted_chat = tokenizer.apply_chat_template(chat, tokenize=True, return_dict=True, continue_final_message=True)
model.generate(**formatted_chat)add_generation_prompt ve continue_final_message birlikte kullanılmamalıdır. İlki yeni bir mesajı başlatan token'ları eklerken, ikincisi dizin sonu token'larını kaldırır. Birlikte kullanıldıklarında bir hata döner.
content alanı yerine o alanı önceden doldurmak için bir alan adını dize olarak iletin. Muhakeme modelleri, muhakemelerini ayrı bir reasoning_content alanından okur. content alanını önceden doldurmak, üretim başlamadan önce muhakeme bloğunu kapatır; bu nedenle model bu bloğun içinde devam edemez. reasoning_content alanını doğrudan önceden doldurmak bloğu açık bırakır.
chat = [
{"role": "user", "content": "Explain 1+1"},
{"role": "assistant", "reasoning_content": "The user wants a simple addition. ", "content": ""},
]
formatted_chat = tokenizer.apply_chat_template(chat, tokenize=False, continue_final_message="reasoning_content")Adlandırılmış alan, son mesajda var olmalı ve sohbet şablonu tarafından referans alınmalıdır. Bu kontrollerden herhangi biri başarısız olursa bir hata oluşturulur.
TextGenerationPipeline, yeni bir mesaj başlatmak için varsayılan olarak add_generation_prompt değerini True olarak ayarlar. Ancak sohbetin son mesajının rolü assistant ise, bu mesajın bir ön doldurma (prefill) olduğunu varsayar ve continue_final_message=True değerine geçer. Bunun nedeni, çoğu modelin art arda gelen birden fazla asistan mesajını desteklememesidir. Bu davranışı geçersiz kılmak için continue_final_message argümanını pipeline'a açıkça iletin.
Model eğitimi
Bir sohbet şablonu ile model eğitmek, şablonun modelin eğitiminde kullanılan jetonlarla eşleştiğinden emin olmanın iyi bir yoludur. Sohbet şablonunu veri setinize bir ön işleme adımı olarak uygulayın. Asistan yanıtını tetiklemek için eklenen jetonların eğitim sırasında faydalı olmaması nedeniyle add_generation_prompt=False olarak ayarlayın.
Bir sohbet şablonu ile veri seti ön işleme örneği aşağıda gösterilmektedir.
from transformers import AutoTokenizer
from datasets import Dataset
tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-beta")
chat1 = [
{"role": "user", "content": "Which is bigger, the moon or the sun?"},
{"role": "assistant", "content": "The sun."}
]
chat2 = [
{"role": "user", "content": "Which is bigger, a virus or a bacterium?"},
{"role": "assistant", "content": "A bacterium."}
]
dataset = Dataset.from_dict({"chat": [chat1, chat2]})
dataset = dataset.map(lambda x: {"formatted_chat": tokenizer.apply_chat_template(x["chat"], tokenize=False, add_generation_prompt=False)})
print(dataset['formatted_chat'][0])<|user|>
Which is bigger, the moon or the sun?</s>
<|assistant|>
The sun.</s>Bu adımın ardından, formatted_chat sütununu kullanarak nedensel dil modelleri için eğitim tarifini takip etmeye devam edebilirsiniz.