Transformers documentation

Strategi generasi

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

and get access to the augmented documentation experience

to get started

Strategi generasi

Strategi decoding menentukan bagaimana model harus memilih token yang akan dihasilkan berikutnya. Terdapat banyak jenis strategi decoding, dan pemilihan strategi yang tepat memiliki dampak signifikan terhadap kualitas teks yang dihasilkan.

Panduan ini akan membantu Anda memahami berbagai strategi decoding yang tersedia di Transformers serta cara dan kapan menggunakannya.

Metode dekode dasar

Ini adalah metode decoding yang sudah mapan, dan sebaiknya menjadi titik awal Anda untuk tugas-tugas generasi teks.

Pencarian serakah

Greedy search adalah strategi decoding default. Strategi ini memilih token yang paling mungkin pada setiap langkah. Kecuali ditentukan dalam GenerationConfig, strategi ini menghasilkan maksimal 20 token baru.

Greedy search bekerja dengan baik untuk tugas dengan output yang relatif pendek di mana kreativitas bukan prioritas. Namun, metode ini gagal saat menghasilkan urutan yang lebih panjang karena mulai mengulang dirinya sendiri.

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from accelerate import Accelerator

device = Accelerator().device

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt").to(device)

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf", dtype=torch.float16).to(device)
# explicitly set to default length because Llama2 generation length is 4096
outputs = model.generate(**inputs, max_new_tokens=20)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company that provides a suite of tools and services for building, deploying, and maintaining natural language processing'

Sampling

Sampling, atau sampling multinomial, memilih token secara acak berdasarkan distribusi probabilitas di seluruh kosakata model (berbeda dengan token yang paling mungkin, seperti pada pencarian serakah). Ini berarti setiap token dengan probabilitas non-nol memiliki peluang untuk dipilih. Strategi sampling mengurangi pengulangan dan dapat menghasilkan output yang lebih kreatif dan beragam.

Aktifkan pengambilan sampel multinomial dengan do_sample=True dan num_beams=1.

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from accelerate import Accelerator

device = Accelerator().device

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt").to(device)

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf", dtype=torch.float16).to(device)
# explicitly set to 100 because Llama2 generation length is 4096
outputs = model.generate(**inputs, max_new_tokens=50, do_sample=True, num_beams=1)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
'Hugging Face is an open-source company πŸ€—\nWe are open-source and believe that open-source is the best way to build technology. Our mission is to make AI accessible to everyone, and we believe that open-source is the best way to achieve that.'

Beam search

Beam search melacak beberapa urutan yang dihasilkan (beam) pada setiap langkah waktu. Setelah sejumlah langkah tertentu, strategi ini memilih urutan dengan probabilitas keseluruhan tertinggi. Berbeda dengan pencarian greedy, strategi ini dapat β€œmelihat ke depan” dan memilih urutan dengan probabilitas keseluruhan yang lebih tinggi meskipun token awal memiliki probabilitas yang lebih rendah. Strategi ini paling cocok untuk tugas yang berbasis input, seperti mendeskripsikan gambar atau pengenalan ucapan. Anda juga dapat menggunakan do_sample=True dengan beam search untuk melakukan sampling pada setiap langkah, tetapi beam search tetap akan memangkas urutan berprobabilitas rendah secara greedy di antara langkah-langkah.

Lihat visualizer beam search untuk melihat cara kerja beam search.

Aktifkan beam search dengan parameter num_beams (harus lebih besar dari 1, jika tidak, hasilnya setara dengan greedy search).

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from accelerate import Accelerator

device = Accelerator().device

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
inputs = tokenizer("Hugging Face is an open-source company", return_tensors="pt").to(device)

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-hf", dtype=torch.float16).to(device)
# explicitly set to 100 because Llama2 generation length is 4096
outputs = model.generate(**inputs, max_new_tokens=50, num_beams=2)
tokenizer.batch_decode(outputs, skip_special_tokens=True)
"['Hugging Face is an open-source company that develops and maintains the Hugging Face platform, which is a collection of tools and libraries for building and deploying natural language processing (NLP) models. Hugging Face was founded in 2018 by Thomas Wolf']"

Metode kustom untuk generasi

Metode kustom generasi memungkinkan perilaku khusus seperti:

  • meminta model untuk terus berpikir jika ia tidak yakin;
  • mengembalikan generasi jika model terjebak;
  • menangani token khusus dengan logika kustom;
  • gunakan cache KV khusus;

Kami memungkinkan metode generasi kustom melalui repositori model, dengan asumsi tag model dan struktur file tertentu (lihat subbagian di bawah). Fitur ini merupakan ekstensi dari kode pemodelan kustom dan, seperti itu, memerlukan pengaturan trust_remote_code=True.

Jika repositori model menyimpan metode generasi kustom, cara termudah untuk mencobanya adalah dengan memuat model dan menghasilkan output dengannya:

from transformers import AutoModelForCausalLM, AutoTokenizer

# `transformers-community/custom_generate_example` holds a copy of `Qwen/Qwen2.5-0.5B-Instruct`, but
# with custom generation code -> calling `generate` uses the custom generation method!
tokenizer = AutoTokenizer.from_pretrained("transformers-community/custom_generate_example")
model = AutoModelForCausalLM.from_pretrained(
    "transformers-community/custom_generate_example", device_map="auto", trust_remote_code=True
)

inputs = tokenizer(["The quick brown"], return_tensors="pt").to(model.device)
# The custom generation method is a minimal greedy decoding implementation. It also prints a custom message at run time.
gen_out = model.generate(**inputs)
# you should now see its custom message, "✨ using a custom generation method ✨"
print(tokenizer.batch_decode(gen_out, skip_special_tokens=True))
'The quick brown fox jumps over a lazy dog, and the dog is a type of animal. Is'

Repositori model dengan metode generasi kustom memiliki properti khusus: metode generasinya dapat dimuat dari model apa pun melalui argumen custom_generate dari generate(). Ini berarti siapa pun dapat membuat dan membagikan metode generasi kustom mereka untuk berpotensi bekerja dengan model Transformers apa pun, tanpa mengharuskan pengguna untuk menginstal paket Python tambahan.

from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct")
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct", device_map="auto")

inputs = tokenizer(["The quick brown"], return_tensors="pt").to(model.device)
# `custom_generate` replaces the original `generate` by the custom generation method defined in
# `transformers-community/custom_generate_example`
gen_out = model.generate(**inputs, custom_generate="transformers-community/custom_generate_example", trust_remote_code=True)
print(tokenizer.batch_decode(gen_out, skip_special_tokens=True)[0])
'The quick brown fox jumps over a lazy dog, and the dog is a type of animal. Is'

Anda sebaiknya membaca file README.md dari repositori yang berisi strategi generasi kustom untuk melihat perbedaan argumen baru dan tipe output, jika ada. Jika tidak, Anda dapat mengasumsikan bahwa cara kerjanya sama seperti metode generate() dasar.

Anda dapat menemukan semua metode generasi kustom dengan mencari tag kustom mereka., custom_generate.

Pertimbangkan repositori Hub transformers-community/custom_generate_example sebagai contoh. README.md menyatakan bahwa repositori ini memiliki argumen input tambahan, left_padding, yang menambahkan sejumlah token padding sebelum prompt.

gen_out = model.generate(
    **inputs, custom_generate="transformers-community/custom_generate_example", trust_remote_code=True, left_padding=5
)
print(tokenizer.batch_decode(gen_out)[0])
'<|endoftext|><|endoftext|><|endoftext|><|endoftext|><|endoftext|>The quick brown fox jumps over the lazy dog.\n\nThe sentence "The quick'

Jika metode kustom memiliki persyaratan Python yang dipatok yang tidak dipenuhi oleh lingkungan Anda, Anda akan mendapatkan pengecualian tentang persyaratan yang hilang. Misalnya, transformers-community/custom_generate_bad_requirements memiliki set persyaratan yang mustahil yang didefinisikan dalam file custom_generate/requirements.txt miliknya, dan Anda akan melihat pesan kesalahan di bawah ini jika Anda mencoba menjalankannya.

ImportError: Missing requirements in your local environment for `transformers-community/custom_generate_bad_requirements`:
foo (installed: None)
bar==0.0.0 (installed: None)
torch>=99.0 (installed: 2.6.0)

Memperbarui persyaratan Python Anda secara sesuai akan menghilangkan pesan kesalahan ini.

Membuat metode generasi kustom

Untuk membuat metode generasi baru, Anda perlu membuat repositori Model baru dan mendorong beberapa file ke dalamnya.

  1. Model yang Anda gunakan untuk merancang metode generasi Anda.
  2. custom_generate/generate.py, yang berisi semua logika untuk metode generasi kustom Anda.
  3. custom_generate/requirements.txt, digunakan untuk menambahkan persyaratan Python baru secara opsional dan/atau mengunci versi tertentu agar metode Anda dapat digunakan dengan benar.
  4. README.md, di mana Anda harus menambahkan tag custom_generate dan mendokumentasikan argumen baru atau perbedaan tipe output dari metode kustom Anda di sini.

Setelah Anda menambahkan semua file yang diperlukan, repositori Anda harus terlihat seperti ini

your_repo/
β”œβ”€β”€ README.md          # include the 'custom_generate' tag
β”œβ”€β”€ config.json
β”œβ”€β”€ ...
└── custom_generate/
    β”œβ”€β”€ generate.py
    └── requirements.txt

Menambahkan model dasar

Titik awal untuk metode generasi kustom Anda adalah repositori model seperti repositori lainnya. Model yang akan ditambahkan ke repositori ini haruslah model yang Anda gunakan untuk merancang metode Anda, dan dimaksudkan sebagai bagian dari pasangan model-generate yang berfungsi dan mandiri. Ketika model di repositori ini dimuat, metode generasi kustom Anda akan menimpa generate. Jangan khawatir β€” metode generasi Anda tetap dapat dimuat dengan model Transformers lainnya, seperti yang dijelaskan di bagian di atas.

Jika Anda hanya ingin menyalin model yang sudah ada, Anda dapat

from transformers import AutoModelForCausalLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("source/model_repo")
model = AutoModelForCausalLM.from_pretrained("source/model_repo")
tokenizer.save_pretrained("your/generation_method", push_to_hub=True)
model.save_pretrained("your/generation_method", push_to_hub=True)

generate.py

Ini adalah inti dari metode generasi Anda. Ini harus berisi metode bernama generate, dan metode ini harus memiliki argumen model sebagai argumen pertamanya. model adalah instance model, yang berarti Anda memiliki akses ke semua atribut dan metode di dalam model, termasuk yang didefinisikan di GenerationMixin (seperti metode dasar generate).

generate.py harus ditempatkan di dalam folder bernama custom_generate, dan bukan di level root repositori. Path file untuk fitur ini di-hardcode.

Di balik layar, ketika metode dasar generate() dipanggil dengan argumen custom_generate, metode tersebut pertama kali memeriksa persyaratan Python-nya (jika ada), kemudian menemukan metode generate kustom di generate.py, dan akhirnya memanggil generate kustom. Semua argumen yang diterima dan model diteruskan ke metode generate kustom Anda, kecuali argumen yang digunakan untuk memicu generasi kustom (trust_remote_code dan custom_generate).

Ini berarti generate Anda dapat memiliki campuran argumen asli dan kustom (serta tipe output yang berbeda) seperti yang ditunjukkan di bawah ini.

import torch

def generate(model, input_ids, generation_config=None, left_padding=None, **kwargs):
    generation_config = generation_config or model.generation_config  # default to the model generation config
    cur_length = input_ids.shape[1]
    max_length = generation_config.max_length or cur_length + generation_config.max_new_tokens

    # Example of custom argument: add `left_padding` (integer) pad tokens before the prompt
    if left_padding is not None:
        if not isinstance(left_padding, int) or left_padding < 0:
            raise ValueError(f"left_padding must be an integer larger than 0, but is {left_padding}")

        pad_token = kwargs.pop("pad_token", None) or generation_config.pad_token_id or model.config.pad_token_id
        if pad_token is None:
            raise ValueError("pad_token is not defined")
        batch_size = input_ids.shape[0]
        pad_tensor = torch.full(size=(batch_size, left_padding), fill_value=pad_token).to(input_ids.device)
        input_ids = torch.cat((pad_tensor, input_ids), dim=1)
        cur_length = input_ids.shape[1]

    # Simple greedy decoding loop
    while cur_length < max_length:
        logits = model(input_ids).logits
        next_token_logits = logits[:, -1, :]
        next_tokens = torch.argmax(next_token_logits, dim=-1)
        input_ids = torch.cat((input_ids, next_tokens[:, None]), dim=-1)
        cur_length += 1

    return input_ids

Ikuti praktik yang direkomendasikan di bawah ini untuk memastikan metode generasi kustom Anda berfungsi sesuai harapan.

  • Silakan gunakan kembali logika untuk validasi dan persiapan input di generate() asli.
  • Sematkan versi transformers di requirements jika Anda menggunakan metode/atribut privat apa pun di model.
  • Pertimbangkan untuk menambahkan validasi model, validasi input, atau bahkan file uji terpisah untuk membantu pengguna memeriksa kewarasan kode Anda di lingkungan mereka.

Metode generate kustom Anda dapat mengimpor kode secara relatif dari folder custom_generate. Misalnya, jika Anda memiliki file utils.py, Anda dapat mengimpornya seperti ini:

from .utils import some_function

Hanya impor relatif dari folder custom_generate pada level yang sama yang didukung. Impor dari folder induk/saudara tidak valid. Argumen custom_generate juga berfungsi secara lokal dengan direktori apa pun yang berisi struktur custom_generate, yang merupakan alur kerja yang direkomendasikan untuk mengembangkan metode generasi kustom Anda.

gen_out = model.generate(**inputs, custom_generate="path/to/local/dir", trust_remote_code=True)

Memuat direktori lokal tetap mengeksekusi custom_generate/generate.py, sehingga membutuhkan trust_remote_code=True sama seperti repositori Hub. Hanya berikan trust_remote_code=True untuk kode yang Anda tulis atau tinjau.

requirements.txt

Anda dapat secara opsional menentukan persyaratan Python tambahan dalam file requirements.txt di dalam folder custom_generate. Persyaratan ini diperiksa saat runtime dan sebuah pengecualian akan dilempar jika persyaratan tersebut tidak ada, sehingga mendorong pengguna untuk memperbarui lingkungan mereka sesuai kebutuhan.

README.md

README.md pada level root di repositori model biasanya menjelaskan model di dalamnya. Namun, karena fokus repositori adalah metode generasi kustom, kami sangat merekomendasikan untuk menggeser fokusnya ke arah penjelasan metode generasi kustom tersebut. Selain penjelasan metode, kami merekomendasikan untuk mendokumentasikan perbedaan input dan/atau output terhadap generate() asli. Dengan cara ini, pengguna dapat berfokus pada hal-hal baru, dan mengandalkan dokumentasi Transformers untuk detail implementasi generik.

Untuk kemudahan penemuan, kami sangat merekomendasikan Anda untuk menambahkan tag custom_generate ke repositori Anda. Untuk melakukannya, bagian atas file README.md Anda harus terlihat seperti contoh di bawah ini. Setelah Anda mendorong file tersebut, Anda seharusnya dapat melihat tag di repositori Anda!

---
library_name: transformers
tags:
  - custom_generate
---

(your markdown content here)

Praktik yang direkomendasikan:

  • Dokumentasikan perbedaan input dan output di generate().
  • Tambahkan contoh mandiri untuk memungkinkan eksperimen cepat.
  • Jelaskan persyaratan lunak, seperti apakah metode tersebut hanya berfungsi dengan baik pada keluarga model tertentu.

Memanfaatkan kembali persiapan input dari generate

Jika Anda menambahkan loop decoding baru, Anda mungkin ingin mempertahankan persiapan input yang ada di generate (ekspansi batch, attention masks, logits processors, kriteria penghentian, dll.). Anda juga dapat meneruskan callable ke custom_generate untuk menggunakan kembali pipeline persiapan lengkap dari generate() sambil hanya menimpa loop decoding.

def custom_loop(model, input_ids, attention_mask, logits_processor, stopping_criteria, generation_config, **model_kwargs):
    next_tokens = input_ids
    while input_ids.shape[1] < stopping_criteria[0].max_length:
        logits = model(next_tokens, attention_mask=attention_mask, **model_kwargs).logits
        next_token_logits = logits_processor(input_ids, logits[:, -1, :])
        next_tokens = torch.argmax(next_token_logits, dim=-1)[:, None]
        input_ids = torch.cat((input_ids, next_tokens), dim=-1)
        attention_mask = torch.cat((attention_mask, torch.ones_like(next_tokens)), dim=-1)
    return input_ids

output = model.generate(
    **inputs,
    custom_generate=custom_loop,
    max_new_tokens=10,
)

Jika Anda menerbitkan repositori custom_generate, implementasi generate Anda dapat mendefinisikan callable dan meneruskannya ke model.generate(). Hal ini memungkinkan Anda menyesuaikan loop decoding sambil tetap memanfaatkan logika persiapan input bawaan Transformers.

Mencari metode kustomisasi

Anda dapat menemukan semua metode generasi kustom dengan mencari tag kustom mereka., custom_generate. Selain tag, kami mengkurasi dua koleksi metode custom_generate:

Sumber daya

Baca artikel blog Cara menghasilkan teks: menggunakan metode decoding yang berbeda untuk generasi bahasa dengan Transformers untuk penjelasan tentang bagaimana strategi decoding umum bekerja.

Update on GitHub