llm.generation — Sampling and Backends¶
Token sampling and the generation backend abstraction. The backend is what the serving tier and the trainer's evaluation loop both call into.
Sampling Utilities¶
sampling
¶
Shared token sampling utilities for generation backends.
apply_repetition_penalty
¶
Apply repetition penalty in-place on 1D logits.
Token ids outside [0, vocab_size) are silently dropped, matching
the other penalty helpers (:func:apply_frequency_penalty,
:func:apply_presence_penalty, :func:apply_logit_bias). Without
this the torch.gather below raises an out-of-bounds error for any
id that is not representable in these logits (e.g. a truncation or
API boundary passing ids the model's vocabulary never produced).
源代码位于: src/llm/generation/sampling.py
apply_frequency_penalty
¶
Subtract frequency_penalty * count(token) from each seen token's logit.
Implements the OpenAI-compatible frequency_penalty semantics
(see https://platform.openai.com/docs/api-reference/chat/create):
positive values penalise tokens in proportion to how often they
have already appeared in the generated text. Zero (the default)
is a no-op so callers don't need to special-case the off state.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
logits
|
Tensor
|
1D |
必需 |
token_ids
|
list[int]
|
List of token ids generated so far (may include duplicates; duplicates count toward the penalty). |
必需 |
frequency_penalty
|
float
|
Penalty coefficient. |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Tensor
|
A new 1D tensor with the per-frequency penalty subtracted. |
源代码位于: src/llm/generation/sampling.py
apply_presence_penalty
¶
Subtract a flat presence_penalty from each seen token's logit.
Implements the OpenAI-compatible presence_penalty semantics
(see https://platform.openai.com/docs/api-reference/chat/create):
positive values penalise tokens that have appeared at least
once in the generated text, encouraging the model to talk
about new topics. The penalty is flat — a token that
appeared 5 times is penalised the same as one that appeared
once. That is the key distinction from
:func:apply_frequency_penalty, which scales by count.
Negative values boost seen tokens (less common, but valid per OpenAI's spec — useful when you want the model to stay on topic).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
logits
|
Tensor
|
1D |
必需 |
token_ids
|
list[int]
|
List of token ids generated so far. Order and duplicates are ignored — only the set matters. |
必需 |
presence_penalty
|
float
|
Penalty coefficient. |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Tensor
|
A new 1D tensor with the flat per-presence penalty applied. |
源代码位于: src/llm/generation/sampling.py
apply_logit_bias
¶
Add a per-token additive bias to 1D logits before sampling.
Implements the OpenAI-compatible logit_bias semantics
(see https://platform.openai.com/docs/api-reference/chat/create):
the bias is added to the affected token's logit prior to
sampling. Negative values discourage the token (down to -100
for a hard ban in OpenAI's spec); positive values encourage it
(up to +100 for near-exclusive selection).
The bias is applied after the penalty helpers
(:func:apply_repetition_penalty,
:func:apply_frequency_penalty,
:func:apply_presence_penalty). Rationale: a penalty subtracts
to discourage repetition, and the bias is a user-intent override
— applying it last lets the bias dominate any natural penalty
the model would otherwise impose. This matches OpenAI's
reference ordering (logit-bias is the final logit-stage
modification before sampling).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
logits
|
Tensor
|
1D |
必需 |
logit_bias
|
Mapping[Any, float] | None
|
Mapping |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Tensor
|
A new 1D tensor with the per-token bias added. |
源代码位于: src/llm/generation/sampling.py
mask_undecodable_logits
¶
Mask every logit whose token id the tokenizer cannot decode.
sample_next_token returns any id in [0, model_vocab); when the
model's vocabulary is larger than the tokenizer's (a padded vocab, or a
BPE/HF model served with a char tokenizer), sampling a tail id used to
crash mid-stream — tokenizer.decode([token_id]) raises KeyError
after part of the text was already yielded (RIL ISS-125). The penalty
helpers already guard out-of-range ids; the sampled id itself must be
bounded to the tokenizer's decodeable range too, by zeroing the tail
probability mass (equivalently pinning those logits to -inf).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
logits
|
Tensor
|
1D |
必需 |
tokenizer_vocab_size
|
int | None
|
The tokenizer's decodeable vocabulary size.
|
必需 |
源代码位于: src/llm/generation/sampling.py
sampling_probs
¶
Return the exact softmax distribution sample_next_token draws from.
Applies temperature scaling, top-k and top-p filtering identically to
:func:sample_next_token and returns the full-vocab probability vector
(masked-out tokens carry zero mass). Used by speculative decoding to
score acceptance ratios against the same filtered distributions the
draft/target samplers actually propose from — scoring against the raw
full-vocab softmax would make the accepted-token set diverge from the
eager backend's output (RIL ISS-99).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
logits
|
Tensor
|
1D |
必需 |
temperature
|
float
|
Sampling temperature. Must be non-zero — the
caller handles the |
1.0
|
top_k
|
int | None
|
Top-k filter; only the |
None
|
top_p
|
float | None
|
Nucleus filter; the smallest tokens whose cumulative
probability exceeds |
None
|
源代码位于: src/llm/generation/sampling.py
sample_next_token
¶
Sample one token id from 1D logits.
源代码位于: src/llm/generation/sampling.py
Generation Backend ABC¶
backends
¶
Generation backend abstractions.
GenerationConfig
dataclass
¶
Shared generation hyperparameters across inference backends.
源代码位于: src/llm/generation/backends.py
GenerationBackend
¶
Bases: ABC
Backend protocol for text generation.
源代码位于: src/llm/generation/backends.py
EagerGenerationBackend
¶
Bases: GenerationBackend
Default in-process generation using the library stream_generate path.
源代码位于: src/llm/generation/backends.py
BatchedGenerationBackend
¶
Bases: GenerationBackend
Generation via ContinuousBatchingEngine (iteration-level scheduling).
源代码位于: src/llm/generation/backends.py
SpeculativeDecodingBackend
¶
Bases: GenerationBackend
Speculative decoding: small draft model proposes, large target verifies.
Implements Leviathan et al. 2023 - the draft model speculates
gamma tokens ahead; the target scores them in a single
forward pass and accepts each with probability
min(1, q_target / q_draft). On rejection, sample a
correction token from (q_target - q_draft)+. The output
distribution exactly matches the target distribution under the
same sampling parameters.
The model argument to :meth:stream / :meth:batch_generate
is ignored - the target and draft models are bound at
construction time. tokenizer must be the shared tokenizer
used by both models (same vocab, pad id, eos id).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
target_model
|
DecoderModel
|
The "expensive" model whose distribution is the canonical output distribution. |
必需 |
draft_model
|
DecoderModel
|
The "cheap" model used for speculation. Must
share vocabulary with |
必需 |
gamma
|
int
|
Number of speculative tokens per round (default 5). Typical values: 4-8. |
5
|
源代码位于: src/llm/generation/backends.py
Backend Registry¶
registry
¶
Generation backend registry and bootstrap.
build_speculative_backend
¶
Build a speculative decoding backend (Leviathan et al., 2023).
Both target_model and draft_model must share vocabulary
with the tokenizer passed at generation time. The gamma
parameter controls how many candidate tokens the draft proposes
per round.
源代码位于: src/llm/generation/registry.py
get_generation_backend
¶
Resolve a generation backend by registry name.
Backend-specific kwargs are forwarded to the factory — e.g.
target_model=..., draft_model=..., gamma=... for the
speculative backend, or engine=... for batched.
源代码位于: src/llm/generation/registry.py
Eager (Streaming) Backend¶
eager
¶
stream_generate
¶
stream_generate(model, tokenizer, prompt, max_new_tokens, temperature=1.0, top_k=None, top_p=None, repetition_penalty=1.0, frequency_penalty=0.0, presence_penalty=0.0, logit_bias=None, use_cache=True, stop=None)
Generator function for incremental text generation.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
stop
|
str | list[str] | None
|
OpenAI-compat stop sequence(s). Generation halts the
moment the accumulated output contains any of these as a
suffix; the stop string itself is NOT included in the
yielded output. Accepts a single string or a list of
strings (OpenAI caps at 4). |
None
|
产生:
| 名称 | 类型 | 描述 |
|---|---|---|
str |
Generator[str]
|
Newly generated text chunk (usually one token decoded). |
源代码位于: src/llm/generation/eager.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | |
generate
¶
generate(model, tokenizer, prompt, max_new_tokens, temperature=1.0, top_k=None, top_p=None, repetition_penalty=1.0, frequency_penalty=0.0, presence_penalty=0.0, logit_bias=None, use_cache=True, stop=None)
Generate text from a prompt using a trained model.
源代码位于: src/llm/generation/eager.py
batch_generate
¶
batch_generate(model, tokenizer, prompts, max_new_tokens, temperature=1.0, top_k=None, top_p=None, repetition_penalty=1.0, frequency_penalty=0.0, presence_penalty=0.0, logit_bias=None, stop=None)
Batch generate text from multiple prompts.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
model
|
DecoderModel
|
The decoder model. |
必需 |
tokenizer
|
SimpleCharacterTokenizer
|
The tokenizer. |
必需 |
prompts
|
list[str]
|
List of input prompts. |
必需 |
max_new_tokens
|
int
|
Maximum tokens to generate per prompt. |
必需 |
temperature
|
float
|
Sampling temperature. 0 for greedy. |
1.0
|
top_k
|
int | None
|
Top-k sampling parameter. |
None
|
top_p
|
float | None
|
Nucleus sampling parameter. |
None
|
repetition_penalty
|
float
|
Repetition penalty. |
1.0
|
frequency_penalty
|
float
|
OpenAI-compatible per-frequency penalty
(subtracts |
0.0
|
presence_penalty
|
float
|
OpenAI-compatible per-presence penalty
(subtracts a flat |
0.0
|
logit_bias
|
dict[int, float] | None
|
OpenAI-compatible additive per-token biases
( |
None
|
stop
|
str | list[str] | None
|
OpenAI-compat stop sequence(s). Generation for each
sequence halts the moment the generated text (post-prompt)
contains any stop string; the stop string itself is NOT
included in the returned text. Accepts a single string or
a list of strings. |
None
|
返回:
| 类型 | 描述 |
|---|---|
list[str]
|
List of generated texts (prompt + generated tokens, with any |
list[str]
|
stop sequence truncated). |
源代码位于: src/llm/generation/eager.py
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | |
Speculative Decoding Backend¶
speculative
¶
Speculative decoding (Leviathan et al., 2023).
A small draft model speculates gamma candidate tokens ahead of
the target model. The target then scores all gamma + 1
positions in a single forward pass, and the algorithm either accepts
each candidate (with probability preserving the target distribution)
or samples a correction token. Net effect: every accepted token costs
roughly one draft forward; only rejections require the more expensive
target forward.
The implementation is greedy/sample-aware via
:func:llm.generation.sampling.sample_next_token and emits decoded
chunks through the standard generator protocol so it slots into the
existing :class:llm.generation.backends.GenerationBackend.
References
Leviathan, Kalman, Matan Kalman, and Yossi Matias. "Fast Inference from Transformers via Speculative Decoding." ICML 2023. https://arxiv.org/abs/2211.17192
TokenizerLike
¶
Bases: Protocol
Anything with encode/decode + optional pad/eos token ids.
源代码位于: src/llm/generation/speculative.py
speculative_generate
¶
speculative_generate(target, draft, tokenizer, prompt, max_new_tokens, *, gamma=5, temperature=1.0, top_k=None, top_p=None, repetition_penalty=1.0, frequency_penalty=0.0, presence_penalty=0.0, logit_bias=None, seed=None, stop=None)
Speculative decoding generator.
Yields decoded chunks. Stops after max_new_tokens produced
tokens or on EOS.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
target
|
DecoderModel
|
Target model (the "expensive" one). Its forward distribution is the canonical output distribution. |
必需 |
draft
|
DecoderModel
|
Draft model (the "cheap" one). Must share vocabulary
with the target and have the same |
必需 |
tokenizer
|
TokenizerLike
|
Tokenizer with |
必需 |
prompt
|
str
|
Prompt text. |
必需 |
max_new_tokens
|
int
|
Hard cap on generated tokens. |
必需 |
gamma
|
int
|
Number of speculative tokens per round. Typical values are 4-8. |
5
|
temperature
|
float
|
Sampling temperature for the correction token (the algorithm preserves the target distribution under these settings). |
1.0
|
top_k
|
int | None
|
Top-k sampling parameter for the correction token. |
None
|
top_p
|
float | None
|
Nucleus-sampling (top-p) parameter for the correction token. |
None
|
repetition_penalty
|
float
|
Applied to both draft and target logits before sampling. |
1.0
|
seed
|
int | None
|
Optional RNG seed for reproducible rejection sampling. |
None
|
stop
|
str | list[str] | None
|
OpenAI-compat stop sequence(s). Generation halts the
moment the accumulated output contains any of these as a
suffix; the stop string itself is NOT included in the
yielded output. Accepts a single string or a list of
strings. |
None
|
源代码位于: src/llm/generation/speculative.py
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 | |