Transformers 使用方式与典型场景
四、使用方式与典型场景
示例一:常驻服务化的批量推理(避免每次请求重载)
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
MODEL = "<你的模型>"
tok = AutoTokenizer.from_pretrained(MODEL)
if tok.pad_token is None:
tok.pad_token = tok.eos_token
tok.padding_side = "left" # 生成任务必须左填充
model = AutoModelForCausalLM.from_pretrained(
MODEL, torch_dtype=torch.bfloat16, device_map="auto"
).eval()
@torch.inference_mode()
def batch_generate(prompts: list[str], max_new_tokens: int = 128) -> list[str]:
# 用模型自带的对话模板,而不是手工拼字符串
texts = [
tok.apply_chat_template(
[{"role": "user", "content": p}],
tokenize=False, add_generation_prompt=True,
)
for p in prompts
]
enc = tok(texts, return_tensors="pt", padding=True, truncation=True,
max_length=2048).to(model.device)
out = model.generate(
**enc,
max_new_tokens=max_new_tokens,
do_sample=True, temperature=0.7, top_p=0.9,
repetition_penalty=1.05,
pad_token_id=tok.pad_token_id,
)
# 只截取新生成的部分,避免把 prompt 原样返回
gen = out[:, enc["input_ids"].shape[1]:]
return tok.batch_decode(gen, skip_special_tokens=True)
要点:左填充是生成任务的硬要求,右填充会让短句生成位置错位;截断新生成部分时用 input_ids 的实际长度而不是 prompt 的原始长度(因为 padding 会改变宽度)。
示例二:用 LoRA 做一次轻量微调
from datasets import load_dataset
from transformers import (AutoTokenizer, AutoModelForCausalLM,
TrainingArguments, Trainer, DataCollatorForLanguageModeling)
from peft import LoraConfig, get_peft_model
MODEL = "<你的基座模型>"
tok = AutoTokenizer.from_pretrained(MODEL)
if tok.pad_token is None:
tok.pad_token = tok.eos_token
model = AutoModelForCausalLM.from_pretrained(MODEL, torch_dtype="auto")
lora = LoraConfig(
r=16, lora_alpha=32, lora_dropout=0.05,
target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], # 按模型实际层名调整
task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora)
model.print_trainable_parameters() # 确认可训练参数占比确实很小
raw = load_dataset("json", data_files="train.jsonl", split="train")
def build(ex):
msgs = [{"role": "user", "content": ex["q"]},
{"role": "assistant", "content": ex["a"]}]
text = tok.apply_chat_template(msgs, tokenize=False)
return tok(text, truncation=True, max_length=1024)
ds = raw.map(build, remove_columns=raw.column_names)
args = TrainingArguments(
output_dir="out",
per_device_train_batch_size=4,
gradient_accumulation_steps=8, # 等效 batch = 4 × 8 × 卡数
learning_rate=2e-4, # LoRA 常用比全量微调更大的学习率
num_train_epochs=3,
logging_steps=10,
save_strategy="epoch",
bf16=True,
gradient_checkpointing=True,
report_to="none",
)
Trainer(model=model, args=args, train_dataset=ds,
data_collator=DataCollatorForLanguageModeling(tok, mlm=False)).train()
model.save_pretrained("lora-adapter") # 只存适配器,体积很小
要点:target_modules 必须按目标模型的实际层命名来写(不同架构的注意力层名字不同,写错会静默匹配不到任何层,训练完发现没有任何效果);LoRA 的学习率通常比全量微调大一个量级;保存的只是适配器,推理时要先加载基座再挂适配器。
适合与不适合的场景
适合:快速验证某个开源模型能否解决业务问题;做零样本/少样本的原型;微调与适配器训练;作为研究与教学的标准入口。
不适合:高并发在线推理服务(应换 vLLM、SGLang 这类专用引擎);需要极致延迟的端侧场景(应做量化与专用运行时);需要精细控制训练细节的前沿研究(手写 PyTorch 更直接)。

