Top-k sampling — как работает выбор следующего токена в LLM и как его настраивать

Top-k sampling — стратегия декодирования для языковых моделей, при которой на каждом шаге генерации модель оставляет только k самых вероятных токенов, нормализует их вероятности и случайно выбирает следующий токен из этого ограниченного множества. Интуитивно: мы «отрезаем хвост» редких продолжений и балансируем между детерминизмом (малый *k*) и разнообразием (большой *k*).

Top-k sampling — как работает выбор следующего токена в LLM и как его настраивать

Связанные страницы: Контекстное окно, RAG-хаб, Evals (оценка качества).

Top-k sampling (выбор из k лучших токенов): формальное определение

Пусть модель даёт распределение вероятностей p(v) по словарю V для следующего токена. Упорядочим токены по убыванию вероятности и возьмём множество: S_k = { v₁, v₂, …, v_k }, где p(v₁) ≥ p(v₂) ≥ ….

Тогда top-k определяет новое распределение:

  • q(v) = p(v) / Σ_{u∈S_k} p(u) для v ∈ S_k
  • q(v) = 0 для v ∉ S_k

Из q сэмплируем один токен. Крайние случаи:

  • k = 1greedy decoding (всегда берем самый вероятный токен);
  • k ≥ |V| → выбор из полного распределения (эквивалентно «без обрезки»).

Зачем ограничивать распределение

  • Защита от «пухлого хвоста». В больших словарях множество очень редких токенов создаёт шум; отрезав хвост, уменьшаем шанс нелепых продолжений.
  • Контроль разнообразия. Меняя *k*, мы управляем «смелостью» модели: малый *k* тянет к шаблонным, но устойчивым ответам; большой *k* — к неожиданным идеям и ошибкам.
  • Простая ментальная модель. В отличие от top-p (nucleus), где порог задают суммарной вероятностью, у top-k фиксировано количество кандидатов.

Связь с температурой и top-p

  • Температура (T). Масштабирует «остроту» распределения до обрезки. При T→0 распределение становится пиковым; при T>1 — более равномерным. Температуру часто сочетают с top-k: сначала softmax/temperature, затем выбор S_k.
  • Top-p (nucleus). Вместо фиксированного *k* берёт минимальное множество токенов, чья суммарная вероятность ≥ *p* (например, 0,9). Это адаптивно: в «уверенных» шагах множество меньше, в «неуверенных» — больше.
  • Эвристика: если нужен стабильный потолок разнообразия на каждом шаге — top-k; если хотите адаптацию к уверенности модели — top-p. Часто используют оба: сначала top-p, затем ограничивают остаток min(k, |S_p|).

Псевдокод (в духе)

  1. logits = model(x)
  2. logits = logits / T *(T — температура)*
  3. probs = softmax(logits)
  4. idx = argsort_desc(probs)
  5. S_k = idx[:k]
  6. q = normalize(probs[S_k])
  7. next = sample(q) из S_k

Практические пресеты

Сценарий Температура k (старт) Замечания
Фактическое QA / RAG 0–0,3 1–5 Максимум точности; при RAG модель должна опираться на контекст; жёстко лимитируйте длину.
Код / формальные ответы 0,2–0,5 1–20 Снижайте *T* и *k*; проверяйте pass@k на тестах (см. evals).
Подытоживание/рефакторинг 0–0,4 1–10 Краткость и стабильность формата важнее разнообразия.
Маркетинг/рассказы/креатив 0,7–1,0 40–80 Для «искры» повышайте *T* и *k*; следите за логикой и длиной.
Диалог-ассистент общий 0,5–0,8 20–50 Баланс; добавляйте политики/guardrails для рисковых зон.

*Числа ориентировочные; оптимум зависит от модели, языка и длины контекста.*

Как *k* влияет на текст (интуиция)

  • Малый *k*: больше «дежавю» и повторов, меньше рисков. Может застревать в циклах («Да, да, да…»), особенно при длинных ответах.
  • Большой *k*: выше шанс свежих формулировок и «дальних ассоциаций», но растут галлюцинации и сюжетные провисы.
  • Комбинация с T: поднимайте сначала T, затем k. Часто достаточно T≈0,7 и k≈40 вместо «100/1,2».

Сравнение стратегий декодирования

Метод Идея Плюсы Минусы/когда не стоит
Greedy (k=1) Всегда берём максимум Быстро, детерминировано Шаблонность, локальные оптимумы, «залипание»
Top-k Сэмпл из k лучших Прозрачный контроль разнообразия Не учитывает «уверенность» шага; *k* постоянен
Top-p (nucleus) Мини-ядро по суммарной вероятности Адаптивность к неопределённости Размер множества «плавает», сложнее предсказать стиль
Beam search Держим N гипотез Хорош в задачах со строгим скорингом Для open-ended текста даёт скучные/повторные ответы

Тонкие эффекты и частые ошибки

  • Зависимость от длины. На длинной генерации малый *k* повышает риск повторов и «затягивания». Добавляйте ограничения: макс-длина, штраф повторов.
  • Не путайте причину и следствие. Галлюцинации — не только от большого *k*: влияют контекст, отсутствие источников, температура и сам промпт (см. evals для проверки faithfulness).
  • «Фиксированное *k* везде». Для разных жанров/языков оптимум различается. Русский язык с морфологией может выигрывать от чуть большего *k*, чем английский, при той же температуре.
  • Нестабильные форматы. Для JSON/таблиц большой *k* ломает скобки/схему. Включайте пост-валидацию и понижайте *k*.
  • Игнорируем системные ограничения. Слишком «смелые» настройки легко выбивают из рамок политики/стиля; следите за guardrails и лимитами.

Настройка в проде: пошагово

  1. Определите цель: фактичность, стиль, креатив, длина.
  2. Зафиксируйте метрики: win-rate (LLM-judge), EM/F1 для QA, pass@k для кода, жалобы пользователей.
  3. Сделайте сетку: прогоните T ∈ {0.3, 0.7, 1.0} × k ∈ {5, 20, 40, 80} на вашем golden-наборе.
  4. Добавьте контекст: при RAG держите *T* и *k* ниже, при креативе — выше.
  5. Включите защиту: штраф повторов, макс-токены, стоп-фразы.
  6. Мониторинг и A/B: храните версии и связку «настройки → метрики» (см. evals).

Мини-FAQ

Чем top-k принципиально отличается от top-p?

Top-k фиксирует размер множества кандидатов, top-p — суммарную вероятность ядра. Top-p адаптивен к «уверенности» модели, top-k — более предсказуем по разнообразию.

Можно ли использовать и top-k, и top-p вместе?

Да: часто применяют top-p, затем ограничивают максимумом *k*, чтобы ядро не распухало на «неуверенных» шагах.

Что выбрать для кода?

Низкая температура и малый *k* (иногда k=1..5). Дальше — проверка на тестах (pass@k) и авто-попытки.

Повышение *k* улучшит правдивость?

Нет. *k* регулирует разнообразие, а не «знание мира». За факты отвечают контекст, источники и политика генерации; для чувствительных доменов используйте RAG.

Почему на одних языках оптимальные *k* разные?

Распределение токенов и сегментация (токенизатор) различаются. Для языков с богатыми окончаниями полезно немного большее *k*.

Мини-глоссарий

  • Температура — коэффициент, делающий распределение более острым (низкая T) или ровным (высокая T).
  • Top-p (nucleus) — выбор минимального множества токенов с суммарной вероятностью ≥ *p*.
  • Greedy — детерминированный выбор самого вероятного токена.
  • Beam search — поддержка нескольких гипотез с последующим выбором лучшей.

См. также

Task Runner