Тема 5 из 6

Генерация текста

Модели вроде GPT пишут текст. Устроено это проще, чем кажется: модель умеет только одно — предсказывать следующий токен.

Шаг за шагом

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

tok = AutoTokenizer.from_pretrained("openai-community/gpt2")
model = AutoModelForCausalLM.from_pretrained("openai-community/gpt2")

ids = tok("The best thing about Python is")["input_ids"]
for _ in range(10):
    with torch.no_grad():
        logits = model(torch.tensor([ids])).logits[0, -1]    # оценки следующего токена
    ids.append(int(logits.argmax()))                         # самый вероятный
print(tok.decode(ids))
  • logits[0, -1] — логиты последней позиции: оценки каждого токена словаря на роль следующего;
  • выбрали токен — дописали — повторили. Это жадная генерация;
  • модель может выбрать токен конца текста (tok.eos_token_id) — тогда ответ закончен.

model.generate

В настоящих программах цикл не пишут — для этого есть generate:

enc = tok("The best thing about Python is", return_tensors="pt")
out = model.generate(**enc, max_new_tokens=30, do_sample=True, temperature=0.8, top_k=50)
print(tok.decode(out[0], skip_special_tokens=True))

max_new_tokens ограничивает длину, do_sample=True включает случайный выбор вместо жадного.

Температура

Жадная генерация часто скучна и зацикливается. Поэтому следующий токен выбирают случайно по вероятностям, а их «остроту» регулируют температурой:

probs = torch.softmax(logits / temperature, dim=-1)
token = torch.multinomial(probs, 1)

Температура меньше 1 усиливает разницу между логитами (текст предсказуемее), больше 1 — сглаживает (текст разнообразнее и безумнее).

Top-k

Чтобы случайный выбор не взял совсем неподходящий токен, оставляют только k лучших:

values, idx = logits.topk(k)
filtered = torch.full_like(logits, float("-inf"))
filtered[idx] = values
probs = torch.softmax(filtered, dim=-1)      # у остальных токенов вероятность 0

-inf после softmax превращается в ноль. Похожий способ — top-p: оставить самые вероятные токены, пока их суммарная вероятность не достигнет p.

Итог

  • языковая модель предсказывает следующий токен по logits[0, -1];
  • жадная генерация, остановка на eos, max_new_tokens;
  • model.generate(…, do_sample=True, temperature=…, top_k=…);
  • температура делит логиты, top-k обнуляет хвост через -inf.