Transformers documentation

Bir sohbet şablonu yazma

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Bir sohbet şablonu yazma

Bir sohbet şablonu, tokenizer'ın ~PreTrainedTokenizer.chat_template özniteliğinde saklanan bir Jinja şablonudur. Jinja, Python benzeri kod ve sözdizimi yazmanıza olanak tanıyan bir şablonlama dilidir.

{%- for message in messages %}
    {{- '<|' + message['role'] + '|>\n' }}
    {{- message['content'] + eos_token }}
{%- endfor %}
{%- if add_generation_prompt %}
    {{- '<|assistant|>\n' }}
{%- endif %}

Bunu bir süre incelediğinizde, aslında bunun Python'a oldukça benzediğini, yalnızca bazı garip {%- sözdizimine sahip olduğunu fark etmelisiniz. Şablon, bir mesaj listesinin üzerinde iterasyon yapar ve her mesaj için mesajın rolünü ve içeriğini, ardından bir dizin sonu belirteci basar. add_generation_prompt=True ise konuşmanın sonuna bir asistan mesajı için başlangıç başlığı ekler.

Yazılan şablonu bir dize olarak yükleyin ve tokenizer'ın chat_template özniteliğine atayın. Ayarlandıktan sonra, apply_chat_template() çağrıldığında şablon her zaman kullanılır. Ayrıca save_pretrained() veya push_to_hub() çağrıldığında tokenizer ile birlikte kaydedilir. Şablon, tokenizer dizinindeki chat_template.jinja dosyasında saklanır. Şablonu değiştirmek için bu dosyayı doğrudan düzenleyebilirsiniz; bu, genellikle bir şablon dizesiyle uğraşmaktan daha kolaydır. Transformers'ın desteklediği diğer disk üzerindeki biçimler için aşağıdaki Chat şablonlarını depolama ve yükleme bölümüne bakın.

Şablon yazma ipuçları

Jinja şablonları yazmaya başlamanın en kolay yolu, mevcut şablonlara başvurmak. Bir sohbet modelinde print(tokenizer.chat_template) komutunu çalıştırarak modelin kullandığı şablonu görebilirsiniz. Araç çağırmayan veya RAG desteklemeyen basit modellerle başlamanızı öneririz çünkü araç kullanım modellerinin şablonları çok karmaşık olabilir. Son olarak, biçimlendirme ve sözdizimi hakkında daha fazla ayrıntı için Jinja belgelerine göz atın.

Ancak, özellikle sohbet şablonları yazarken karşılaşabileceğiniz bazı özel ipuçları ve tuzaklar vardır ve bu bölüm bunlardan bazılarını daha ayrıntılı olarak ele alacaktır.

Çok modlu sohbet şablonları yazma

Çok modlu şablonlar için chat_template özniteliği, tokenizer yerine processor üzerinde ayarlanır. Bir mesajın content anahtarı, tek bir dizge yerine genellikle içerik sözlüklerinden oluşan bir listedir. Listede her içerik öğesinin türünü kontrol etmeyi ve buna göre işlem yapmayı tercih edebilirsiniz.

Genel olarak, şablon doğrudan görüntü veya video verisine erişmemelidir. Bu işlem normalde, şablon işleme (rendering) tamamlandıktan sonra işlemci (processor) tarafından ele alınır. Bunun yerine, şablonunuz görüntü veya video içeriğiyle karşılaştığında <|image|> veya <|video|> gibi tek bir özel belirteç (token) yaymalıdır. İşlemci, daha sonra bu tek özel belirteci, görüntü veya video belirteçlerinden oluşan bir diziye genişletecektir. Yayılacak kesin belirteçler, üzerinde çalıştığınız modele bağlıdır. Mevcut bir çok modallı işlemciyi (multimodal processor) yükleyerek veriyi nasıl işlediğini görmesini şiddetle öneririz.

Aşağıdaki örnek şablon, karışık görsel ve metin içeriğini işler.

{%- for message in messages %}
    {%- if loop.index0 == 0 %}
        {{- bos_token }}
    {%- endif %}
    {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n' }}
    {%- if message['content'] is string %}
        {{- message['content'] }}
    {%- else %}
        {%- for content in message['content'] %}
            {%- if content['type'] == 'image' %}
                {{- '<|image|>' }}
            {%- elif content['type'] == 'text' %}
                {{- content['text'] }}
            {%- endif %}
        {%- endfor %}
    {%- endif %}
    {{- '<|eot_id|>' }}
{%- endfor %}
{%- if add_generation_prompt %}
    {{- '<|start_header_id|>assistant<|end_header_id|>\n\n' }}
{%- endif %}

Bu çok modlu şablon, yukarıdaki daha basit şablona çok benzer; ancak content listelerini kontrol eder ve gerekli yerlerde <|image|> jetonlarını oluşturmak için bunların üzerinde döngü yapar. Bu sayede görseller, kullanıcı metninin “akışına” yerleştirilebilir.

Tüm modeller bu şekilde çalışmaz; bazıları, örneğin, tüm görselleri kullanıcı mesajının sonuna taşıyabilir. Sohbet şablonu, modelin eğitildiği biçimle her zaman eşleşmelidir.

Boşlukları kırpma

Jinja, bir metin bloğunun öncesindeki veya sonrasındaki boşlukları basar. Bu durum, sohbet şablonları için bir sorun olabilir çünkü model eğitimi sırasında mevcut olmayan ek boşlukların eklenmesi performansı olumsuz etkileyebilir. Boşlukları kaldırmak için Jinja satır sözdizimine - ekleyin. Bu sayede, şablonunuzu Pythonik girintiler ve satır sonlarıyla yazabilir, ancak işlenmiş çıktıda bir girinti basılmasını önleyebilirsiniz.

Aşağıdaki örnek şablon - kullanmadığı için çıktıda ek boşluklar basılıyor.

{% for message in messages %}
    {{ message['role'] + message['content'] }}
{% endfor %}

Yalnızca hedeflenen içeriğin yazdırılmasını sağlamak için - kullanmanızı şiddetle öneririz.

{%- for message in messages %}
    {{- message['role'] + message['content'] }}
{%- endfor %}

Özel değişkenler ve çağrılabilirler

Bir şablondaki tek sabitler messages değişkeni ve add_generation_prompt boole değeridir. Ancak apply_chat_template() yöntemine geçirilen diğer tüm anahtar kelime argümanlarına erişiminiz vardır.

Bu, esneklik sağlar ve spesifikasyonu tasarlarken aklımıza gelmemiş olabilecek kullanım senaryolarına destek olanağı tanır. En yaygın ek değişken, JSON şeması biçiminde bir araç listesi içeren tools'tur. İstediğiniz herhangi bir değişken adını kullanabilirsiniz ancak bu amaçla tools adını kullanmanızı ve konvansiyona sadık kalmanızı şiddetle öneririz. Bu, şablonların standart API ile daha uyumlu olmasını sağlar.

Ayrıca tokenizer.special_tokens_map içindeki tüm tokenlere de erişebilirsiniz; bu harita genellikle bos_token ve eos_token gibi özel tokenleri içerir. Bunlara {{- bos_token }} gibi doğrudan adlarıyla erişebilirsiniz.

Kullanabileceğiniz iki çağrılabilir fonksiyon bulunmaktadır. Bunları çağırmak için {{- function_name(argument) }} kullanın.

  • raise_exception(msg), bir TemplateException fırlatır. Bu, hata ayıklama veya kullanıcılara hatalı şablon kullanımı konusunda uyarı göndermek için kullanışlıdır.
  • strftime_now(format_str), sistem mesajlarında sıkça ihtiyaç duyulan belirli bir biçimde geçerli tarihi ve saati alır. Python'da datetime.now().strftime(format_str) ifadesine eşdeğerdir.

Python dışı Jinja ile uyumluluk

Jinja birden fazla dilde uygulanmıştır ve bunların sözdizimi genellikle aynıdır. Şablonu Python'da yazmak, dizgelerde lower veya sözlüklerde items gibi Python yöntemlerini kullanmanızı sağlar. Ancak şablon, örneğin Javascript veya Rust ile dağıtım sırasında olduğu gibi Python dışı bir uygulamada kullanılırsa bu çalışmaz.

Tüm Jinja uygulamaları arasında uyumluluğu sağlamak için aşağıdaki değişiklikleri yapın.

  • Python yöntemlerini Jinja filtreleriyle değiştirin. Örneğin, string.lower() yerine string|lower veya dict.items() yerine dict|dictitems kullanın. string.strip() hariç olmak üzere değişikliklerin çoğu aynı deseni izler; bu yöntem string|trim ile değiştirilir. Filtrelerin tam listesi için yerleşik filtreler listesine bakın.
  • True, False ve None değerlerini (bunlar Python'a özgüdür) sırasıyla true, false ve none ile değiştirin.
  • Bir sözlük veya listeyi doğrudan render etmek, diğer implementasyonlarda farklı sonuçlar dönebilir. Örneğin, string girdileri tek tırnaklıdan çift tırnaklıya dönüşebilir. Bunu önlemek için tutarlılığı korumak adına tojson filtresini ekleyin.

Büyük şablonlar

Daha yeni modeller veya tool-calling ve RAG gibi özelliklere sahip modeller, 100 satırdan uzun olabilecek daha büyük şablonlar gerektirir. Daha büyük şablonları ayrı bir dosyada yazmak daha kolay olabilir. Ayrı dosyadaki satır numaraları, şablon ayrıştırma veya çalışma hatalarındaki satır numaralarıyla tam olarak eşleşir; bu da olası sorunların ayıklanmasını kolaylaştırır.

Şablonu ayrı bir dosyada yazın ve sohbet şablonuna çıkarın.

open("template.jinja", "w").write(tokenizer.chat_template)

Düzenlenmiş bir şablonu da tokenizer'a geri yükleyebilirsiniz.

tokenizer.chat_template = open("template.jinja").read()

Sohbet şablonlarını depolama ve yükleme

Chat şablonları diskte çeşitli farklı formatlarda saklanır. Modern checkpoint'ler şablonları bağımsız .jinja dosyaları olarak kaydederken, eski checkpoint'ler bunları tokenizer veya processor yapılandırmasına gömer.

Depolama biçimleri

Şablonlar aşağıdaki formatlardan herhangi birinde saklanabilir.

  • chat_template.jinja (önerilen). Deponun kökünde, tek bir sohbet şablonu içeren bağımsız bir Jinja dosyası. save_pretrained() varsayılan olarak bunu yazar. Şablonun kendi dosyasında saklanması, denetlemeyi, düzenlemeyi ve farkı almayı kolaylaştırır. Hem tokenizer'lar hem de processor'lar chat_template.jinja dosyasını aynı şekilde yükler.
  • additional_chat_templates/<name>.jinja. Bir modelin birden fazla adlandırılmış şablonla birlikte dağıtılması durumunda (örneğin, bir default şablonu ve ayrı bir tool_use şablonu) kullanılan bağımsız Jinja dosyalarının bulunduğu dizin. default şablonu yine de depo kökünde chat_template.jinja dosyasında kalır, ancak diğer tüm adlandırılmış şablonlar, dosya adı kökünün şablon adı olduğu additional_chat_templates/<name>.jinja dizinine yerleştirilir.

Aşağıdaki eski biçimler yalnızca geriye dönük uyumlu yükleme için korunmaktadır. Sohbet şablonlarını bunlardan herhangi birine yazmayın.

  • tokenizer_config.json içindeki chat_template alanı. Bağımsız .jinja dosyaları kullanılmadan önce kullanılan, yalnızca yükleme amaçlı eski bir biçimdir. Şablon, tokenizer_config.json içinde JSON dizgesi olarak gömülüdür. Bir modelin birden fazla adlandırılmış şablonu varsa, alan tek bir dizge yerine {"name": ..., "template": ...} sözlüklerinden oluşan bir listedir. Bu biçimi kullanan mevcut depolar yüklemeye devam eder, ancak save_pretrained() bunun yerine modern .jinja biçimini yazar.

  • chat_template.json. Eski çok modlu işlemci denetim noktaları tarafından kullanılan yalnızca yükleme amaçlı bir eski format. {"chat_template": "<template string>"} biçiminde bir JSON dosyası. Bu formatı kullanan mevcut depolar yüklemeye devam eder, ancak save_pretrained() bunun yerine modern .jinja formatını yazar. Eski bir chat_template.json ile modern .jinja dosyalarını karıştıran bir işlemci deposu, yükleme sırasında bir hata verir.

Yükleme önceliği

from_pretrained() çağrıldığında Transformers, depolama biçimlerini sabit bir önceliğe göre çözer. Bağımsız .jinja dosyaları, yapılandırmaya gömülü şablonlara göre önceliklidir. Yükleyici:

  1. tokenizer_config.json (veya işlemciler için eski chat_template.json) içindeki mevcut herhangi bir chat_template alanını okur.
  2. Eğer varsa, depo kökündeki chat_template.jinja dosyasını okur ve default şablonu olarak kullanır; bu, 1. adımı geçersiz kılar.
  3. additional_chat_templates/ dizinindeki her .jinja dosyasını dosya adı köküyle eşleştirerek okur ve birleştirir.

Sonuçta tek bir default şablonu varsa, ~PreTrainedTokenizer.chat_template bu dizeye ayarlanır. Birden fazla adlandırılmış şablon varsa, chat_template, {name: template_string} biçiminde bir sözlük olur. Bu durumda, apply_chat_template() araçlar geçirildiğinde tool_use girdisini, aksi halde default girdisini seçer.

Kaydetme

save_pretrained() ve push_to_hub() varsayılan olarak .jinja biçimini yazar. Tek bir şablon dizesi chat_template.jinja olarak yazılır. Adlandırılmış şablonlardan oluşan bir sözlük, default girdisini chat_template.jinja dosyasına, kalan her girdiyi ise additional_chat_templates/ altında ayrı bir dosya olarak yazar. chat_template alanı, yinelenmeyi önlemek için tokenizer_config.json dosyasından kaldırılır.

Desteklenen bir yöntemle şablonu eski formatlardan birinde kaydetmenin bir yolu yoktur. Bunlar yalnızca eski depoları yüklemek için korunmaktadır.

Eski bir depoyu güncelleme

tokenizer_config.json veya chat_template.json içindeki gömülü şablonu, önerilen .jinja biçimine, şablonu yeniden yükleyip kaydederek taşıyın.

Yükleme adımı, depoda chat_template içinde kullanılan herhangi bir eski biçimi normalize eder ve ~PushToHubMixin.push_to_hub bir chat_template.jinja dosyası döndürür.

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("your-org/your-model")
tokenizer.push_to_hub("your-org/your-model")

Araçlar için şablonlar

Araçlar için şablon yazarken belirli bir format yoktur ancak standart API'yi takip etmek en iyisidir. Bu, kullanıcıların modelinizle araçları kullanmak için özel kod yazmasına gerek kalmadan şablonun modeller arasında yaygın olarak erişilebilir olmasını sağlar.

Boşluklar ve özel tokenler gibi biçimlendirme öğeleri modele özgüdür. Her şeyin, modelin eğitildiği biçimle birebir eşleştiğinden emin olun.

Aşağıdaki bölüm, araçlar için şablon yazmak için standart API'nin öğelerini listeler.

Araç tanımları

Araçlar, Python işlevleri veya bir JSON şeması olarak iletilir. İşlevler iletildiğinde, bir JSON şeması otomatik olarak oluşturulur ve şablona iletilir. Bir şablon tools değişkenine eriştiğinde, bu değişken her zaman bir JSON şeması listesidir.

Bir şablon her zaman araçları bir JSON şeması olarak alır; ancak bunları, modelin eğitiminde kullanılan biçime uygun hale getirmek için render ederken bu biçimi köklü bir şekilde değiştirmeniz gerekebilir. Örneğin, Command-R, Python fonksiyon başlıklarıyla tanımlanmış araçlarla eğitilmiştir. Şablon, JSON şeması türlerini dahili olarak dönüştürür ve girdi araçlarını Python başlıkları olarak render eder.

Aşağıdaki örnek, bir aracın JSON şeması biçiminde nasıl tanımlandığını gösterir.

{
  "type": "function",
  "function": {
    "name": "multiply",
    "description": "A function that multiplies two numbers",
    "parameters": {
      "type": "object",
      "properties": {
        "a": {
          "type": "number",
          "description": "The first number to multiply"
        },
        "b": {
          "type": "number",
          "description": "The second number to multiply"
        }
      },
      "required": ["a", "b"]
    }
  }
}

Bir sohbet şablonunda araç tanımlarının işlenmesine ilişkin bir örnek aşağıda gösterilmektedir. Belirli jetonlar ve yerleşimler, modelin eğitildiği jetonlarla ve yerleşimlerle eşleşecek şekilde değiştirilmelidir.

{%- if tools %}
    {%- for tool in tools %}
        {{- '<tool>' + tool['function']['name'] + '\n' }}
        {%- for argument in tool['function']['parameters']['properties'] %}
            {{- argument + ': ' + tool['function']['parameters']['properties'][argument]['description'] + '\n' }}
        {%- endfor %}
        {{- '\n</tool>' }}
    {%- endfor %}
{%- endif %}

Araç çağrıları

Araç tanımlarını işlemenin yanı sıra, şablonda araç çağrılarını ve araç yanıtlarını da işlemelisiniz.

Tool çağrıları genellikle "assistant” mesajının tool_calls anahtarı altında iletilir. Çoğu tool çağrısı modeli yalnızca tekil tool çağrılarını desteklese de bu her zaman bir listedir; bu da listenin genellikle yalnızca tek bir öğe içerdiği anlamına gelir.

{
  "role": "assistant",
  "tool_calls": [
    {
      "type": "function",
      "function": {
        "name": "multiply",
        "arguments": {
          "a": 5,
          "b": 6
        }
      }
    }
  ]
}

Araç çağrılarını işlemek için yaygın bir desen aşağıda gösterilmektedir. Bunu bir başlangıç noktası olarak kullanabilirsiniz, ancak şablonunuzun modelin eğitildiği biçimle gerçekten eşleştiğinden emin olun!

{%- if message['role'] == 'assistant' and 'tool_calls' in message %}
    {%- for tool_call in message['tool_calls'] %}
            {{- '<tool_call>' + tool_call['function']['name'] + '\n' + tool_call['function']['arguments']|tojson + '\n</tool_call>' }}
    {%- endfor %}
{%- endif %}

Araç yanıtları

Araç yanıtları, tool rolüne sahip mesaj sözlükleridir. Araç çağrılarından çok daha basittirler ve genellikle yalnızca role, name ve content anahtarlarını içerirler.

{
  "role": "tool",
  "name": "multiply",
  "content": "30"
}

Bazı şablonların name anahtarına bile ihtiyacı olmayabilir; bu durumda şablonunuzu yalnızca content anahtarını okuyacak şekilde yazabilirsiniz.

{%- if message['role'] == 'tool' %}
    {{- "<tool_result>" + message['content'] + "</tool_result>" }}
{%- endif %}

Katkıda bulun

Bir şablon hazır olduğunda, onu tokenizer'daki chat_template özniteliğine ayarlayın ve apply_chat_template() ile test edin. Beklendiği gibi çalışıyorsa, push_to_hub() ile Hub'a yükleyin.

Model sahibi olmasanız bile, boş veya hatalı bir sohbet şablonuna sahip bir model için şablon eklemek faydalıdır. Şablonu eklemek için model deposunda bir pull request açın!

tokenizer.chat_template = template
tokenizer.push_to_hub("amazing_company/cool_model", commit_message="Add chat template", create_pr=True)
Update on GitHub