Transformers documentation

Tạo văn bản

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

Tạo văn bản

Tạo văn bản là ứng dụng phổ biến nhất của các mô hình ngôn ngữ lớn (LLM). Một LLM được huấn luyện để tạo ra từ (token) tiếp theo dựa trên một số văn bản ban đầu (prompt) cùng với các đầu ra do chính nó tạo ra cho đến khi đạt độ dài định trước hoặc khi nó chạm đến token kết thúc chuỗi (EOS).

Trong Transformers, API generate() xử lý việc tạo văn bản và có sẵn cho tất cả các mô hình có khả năng sinh. Hướng dẫn này sẽ cho bạn thấy các cơ bản về tạo văn bản với generate() và một số bẫy phổ biến cần tránh.

Đối với các lệnh sau, hãy đảm bảo rằng transformers serve đang chạy.

transformers chat Qwen/Qwen2.5-0.5B-Instruct

Mặc định generate

Trước khi bắt đầu, việc cài đặt bitsandbytes sẽ giúp ích để lượng tử hóa các mô hình rất lớn nhằm giảm mức sử dụng bộ nhớ của chúng.

!pip install -U transformers bitsandbytes

Bitsandbytes hỗ trợ nhiều backend khác ngoài GPU dựa trên CUDA. Tham khảo hướng dẫn cài đặt đa backend để biết thêm.

Tải một LLM bằng from_pretrained() và thêm hai tham số sau để giảm yêu cầu về bộ nhớ.

  • device_map="auto" kích hoạt tính năng Big Model Inference của Accelerate để tự động khởi tạo khung mô hình và nạp, phân phối trọng số mô hình trên tất cả các thiết bị khả dụng, bắt đầu từ thiết bị nhanh nhất (GPU).
  • quantization_config là một đối tượng cấu hình xác định các cài đặt lượng tử hóa. Ví dụ này sử dụng bitsandbytes làm backend lượng tử hóa (xem phần Lượng tử hóa để biết thêm các backend khả dụng) và tải mô hình ở 4-bit.
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)
model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", device_map="auto", quantization_config=quantization_config)

Thực hiện tokenize đầu vào của bạn và đặt tham số padding_side() thành "left" vì LLM không được huấn luyện để tiếp tục sinh từ các token padding. Tokenizer sẽ trả về các input ids và attention mask.

Xử lý nhiều hơn một prompt cùng lúc bằng cách truyền một danh sách các chuỗi vào tokenizer. Gom các đầu vào thành batch để cải thiện thông lượng với chi phí nhỏ về độ trễ và bộ nhớ.

tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1", padding_side="left")
model_inputs = tokenizer(["A list of colors: red, blue"], return_tensors="pt").to(model.device)

Truyền các đầu vào vào generate() để tạo ra các token, sau đó dùng batch_decode() để chuyển các token đã tạo thành văn bản.

generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
"A list of colors: red, blue, green, yellow, orange, purple, pink,"

Cấu hình tạo

Tất cả các cài đặt sinh đều được chứa trong GenerationConfig. Trong ví dụ trên, các cài đặt sinh được suy ra từ tệp generation_config.json của mistralai/Mistral-7B-v0.1. Một chiến lược giải mã mặc định sẽ được sử dụng khi không có cấu hình nào được lưu cùng với mô hình.

Kiểm tra cấu hình thông qua thuộc tính generation_config. Nó chỉ hiển thị các giá trị khác với cấu hình mặc định, trong trường hợp này là bos_token_id và eos_token_id.

from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-v0.1", device_map="auto")
model.generation_config
GenerationConfig {
  "bos_token_id": 1,
  "eos_token_id": 2
}

Bạn có thể tùy chỉnh generate() bằng cách ghi đè các tham số và giá trị trong GenerationConfig. Xem mục này bên dưới để biết các tham số thường được điều chỉnh.

# enable beam search sampling strategy
model.generate(**inputs, num_beams=4, do_sample=True)

generate() cũng có thể được mở rộng bằng các thư viện bên ngoài hoặc mã tùy chỉnh:

  1. tham số logits_processor chấp nhận các instance LogitsProcessor tùy chỉnh để thao tác trên phân phối xác suất của token tiếp theo;
  2. tham số stopping_criteria hỗ trợ StoppingCriteria tùy chỉnh để dừng tạo văn bản;
  3. các phương pháp sinh tùy chỉnh khác có thể được tải thông qua cờ custom_generate (tài liệu).

Tham khảo hướng dẫn Các chiến lược sinh để tìm hiểu thêm về các chiến lược tìm kiếm, lấy mẫu và giải mã.

Lưu

Tạo một instance của GenerationConfig và chỉ định các tham số giải mã mà bạn muốn.

from transformers import AutoModelForCausalLM, GenerationConfig

model = AutoModelForCausalLM.from_pretrained("my_account/my_model")
generation_config = GenerationConfig(
    max_new_tokens=50, do_sample=True, top_k=50, eos_token_id=model.config.eos_token_id
)

Sử dụng save_pretrained() để lưu một cấu hình sinh cụ thể và đặt tham số push_to_hub thành True để tải nó lên Hub.

generation_config.save_pretrained("my_account/my_model", push_to_hub=True)

Để trống tham số config_file_name. Tham số này nên được sử dụng khi lưu trữ nhiều cấu hình sinh trong một thư mục duy nhất. Nó cho phép bạn chỉ định cấu hình sinh nào cần tải. Bạn có thể tạo các cấu hình khác nhau cho các tác vụ sinh khác nhau (sinh văn bản sáng tạo với sampling, tóm tắt với beam search) để sử dụng với một mô hình duy nhất.

from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, GenerationConfig

tokenizer = AutoTokenizer.from_pretrained("google-t5/t5-small")
model = AutoModelForSeq2SeqLM.from_pretrained("google-t5/t5-small")

translation_generation_config = GenerationConfig(
    num_beams=4,
    early_stopping=True,
    decoder_start_token_id=0,
    eos_token_id=model.config.eos_token_id,
    pad_token=model.config.pad_token_id,
)

translation_generation_config.save_pretrained("/tmp", config_file_name="translation_generation_config.json", push_to_hub=True)

generation_config = GenerationConfig.from_pretrained("/tmp", config_file_name="translation_generation_config.json")
inputs = tokenizer("translate English to French: Configuration files are easy to use!", return_tensors="pt")
outputs = model.generate(**inputs, generation_config=generation_config)
print(tokenizer.batch_decode(outputs, skip_special_tokens=True))

Các tùy chọn phổ biến

generate() là một công cụ mạnh mẽ, có thể tùy chỉnh sâu. Điều này có thể gây khó khăn cho người dùng mới. Phần này chứa danh sách các tùy chọn sinh phổ biến mà bạn có thể định nghĩa trong hầu hết các công cụ sinh văn bản trong Transformers: generate(), GenerationConfig, pipelines, CLI chat, …

Tên tùy chọnLoạiMô tả đơn giản
max_new_tokensintKiểm soát độ dài tối đa của quá trình sinh. Hãy đảm bảo định nghĩa tham số này, vì mặc định nó thường có giá trị nhỏ.
do_sampleboolXác định xem quá trình sinh sẽ lấy mẫu token tiếp theo (True) hay thay vào đó là tham lam (False). Hầu hết các trường hợp sử dụng nên đặt cờ này thành True. Xem hướng dẫn này để biết thêm thông tin.
temperaturefloatMức độ khó dự đoán của token tiếp theo được chọn. Giá trị cao (>0.8) phù hợp cho các tác vụ sáng tạo, giá trị thấp (ví dụ <0.4) cho các tác vụ đòi hỏi “suy nghĩ”. Yêu cầu do_sample=True.
num_beamsintKhi được đặt thành >1, thuật toán beam search sẽ được kích hoạt. Beam search hoạt động tốt với các tác vụ dựa trên đầu vào. Xem hướng dẫn này để biết thêm thông tin.
repetition_penaltyfloatĐặt giá trị này lớn hơn >1.0 nếu bạn thấy mô hình lặp lại nội dung thường xuyên. Giá trị lớn hơn sẽ áp dụng mức phạt lớn hơn.
eos_token_idlist[int]Token (các token) sẽ khiến quá trình sinh kết thúc. Giá trị mặc định thường là tốt, nhưng bạn có thể chỉ định một token khác.

Những bẫy

Phần bên dưới đề cập đến một số vấn đề phổ biến mà bạn có thể gặp phải trong quá trình tạo văn bản và cách giải quyết chúng.

Độ dài đầu ra

generate() mặc định trả về tối đa 20 token trừ khi được chỉ định khác trong GenerationConfig của model. Rất khuyến nghị đặt thủ công số lượng token được tạo bằng tham số max_new_tokens để kiểm soát độ dài đầu ra. Các model Decoder-only trả về prompt ban đầu cùng với các token được tạo.

model_inputs = tokenizer(["A sequence of numbers: 1, 2"], return_tensors="pt").to(model.device)
độ dài mặc định
max_new_tokens
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
'A sequence of numbers: 1, 2, 3, 4, 5'

Chiến lược giải mã

Chiến lược giải mã mặc định trong generate() là greedy search, chọn token có xác suất cao nhất tiếp theo, trừ khi được chỉ định khác trong GenerationConfig của mô hình. Mặc dù chiến lược giải mã này hoạt động tốt cho các tác vụ dựa trên đầu vào (chuyển văn bản thành giọng nói, dịch thuật), nhưng nó không tối ưu cho các trường hợp sử dụng sáng tạo hơn (viết truyện, ứng dụng trò chuyện).

Ví dụ, hãy bật chiến lược multinomial sampling để tạo ra các đầu ra đa dạng hơn. Tham khảo hướng dẫn Generation strategy để biết thêm về các chiến lược giải mã.

model_inputs = tokenizer(["I am a cat."], return_tensors="pt").to(model.device)
tìm kiếm tham lam
lấy mẫu đa thức
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

Bên đệm

Các đầu vào cần được đệm (padding) nếu chúng không có cùng độ dài. Tuy nhiên, các LLM không được huấn luyện để tiếp tục sinh nội dung từ các token đệm, điều này có nghĩa là tham số padding_side() cần được đặt ở phía bên trái của đầu vào. Việc đệm bên phải gây bất lợi hơn cho các mô hình không gian trạng thái và mô hình lai, vì trạng thái đệ quy của chúng liên tục cập nhật trên các token đệm ở cuối, khiến bộ nhớ đệm (cache) không còn khớp với phần cuối của prompt.

lấp đầy bên phải
lấp đầy bên trái
model_inputs = tokenizer(
    ["1, 2, 3", "A, B, C, D, E"], padding=True, return_tensors="pt"
).to(model.device)
generated_ids = model.generate(**model_inputs)
tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
'1, 2, 33333333333'

Định dạng prompt

Một số mô hình và tác vụ yêu cầu một định dạng prompt đầu vào nhất định, và nếu định dạng không chính xác, mô hình sẽ trả về kết quả đầu ra không tối ưu. Bạn có thể tìm hiểu thêm về việc tạo prompt trong hướng dẫn kỹ thuật prompt.

Ví dụ, một mô hình chat kỳ vọng đầu vào dưới dạng mẫu chat. Prompt của bạn nên bao gồm role và content để chỉ rõ ai đang tham gia cuộc trò chuyện. Nếu bạn cố gắng truyền prompt dưới dạng một chuỗi duy nhất, mô hình không phải lúc nào cũng trả về đầu ra như mong đợi.

from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig

tokenizer = AutoTokenizer.from_pretrained("HuggingFaceH4/zephyr-7b-alpha")
model = AutoModelForCausalLM.from_pretrained(
    "HuggingFaceH4/zephyr-7b-alpha", device_map="auto", quantization_config=BitsAndBytesConfig(load_in_4bit=True)
)
không có định dạng
mẫu chat
prompt = """How many cats does it take to change a light bulb? Reply as a pirate."""
model_inputs = tokenizer([prompt], return_tensors="pt").to(model.device)
input_length = model_inputs.input_ids.shape[1]
generated_ids = model.generate(**model_inputs, max_new_tokens=50)
print(tokenizer.batch_decode(generated_ids[:, input_length:], skip_special_tokens=True)[0])
"Aye, matey! 'Tis a simple task for a cat with a keen eye and nimble paws. First, the cat will climb up the ladder, carefully avoiding the rickety rungs. Then, with"

Tài nguyên

Xem bên dưới để tìm hiểu thêm về một số thư viện tạo văn bản cụ thể và chuyên biệt hơn.

  • Optimum: một phần mở rộng của Transformers tập trung vào việc tối ưu hóa huấn luyện và suy luận trên các thiết bị phần cứng cụ thể
  • Outlines: một thư viện cho việc tạo văn bản có ràng buộc (ví dụ: tạo các tệp JSON).
  • SynCode: một thư viện cho việc tạo sinh có hướng dẫn bằng ngữ pháp không ngữ cảnh (JSON, SQL, Python).
  • Text Generation Inference: một máy chủ sẵn sàng cho môi trường sản xuất dành cho LLM.
  • Giao diện web tạo văn bản: một giao diện web Gradio để tạo văn bản.
  • logits-processor-zoo: các logits processor bổ sung để kiểm soát việc tạo văn bản.
Update on GitHub