Skip to content

GLM-5.2 Repetition Penalty: Prevent Runtime Drift

Independent research — not an official Z.ai publication.Identity and provider disclosure

A blue token stream splits through four runtime control lanes, with the lowest lane marked by an amber configuration warning

Original editorial visualization of one token stream crossing four runtime contracts. The empty socket, neutral dial, comb, and amber warning represent different accepted fields and bounds—not measured output quality.

Start GLM-5.2 with every repetition control neutral, then enable exactly one named experiment on one pinned runtime. For the source versions checked here, neutral means repetition_penalty=1.0, frequency_penalty=0.0, and presence_penalty=0.0. Those numbers are not a portable request: Z.AI does not currently document any of the three fields, direct Transformers exposes only the first, and vLLM and SGLang expose all three with different bounds.

This distinction prevents two failure modes. A gateway may drop an unknown field and leave you thinking a penalty is active. A local migration may begin applying a penalty that the hosted baseline never used. Either outcome can be misdiagnosed as a model, quantization, or prompt regression.

Our dated audit hashes ten public artifacts and resolves 23 deterministic configuration fixtures. It makes zero authenticated API calls, zero tokenizer calls, and zero model calls. It proves the checked schema, source defaults, and validator behavior—not the ideal penalty value for a task.

  1. Read the contract table
  2. Compare the four runtime contracts
  3. Separate the three penalty meanings
  4. Understand the neutral baseline
  5. Review the 23-fixture audit
  6. Copy the fail-closed validator
  7. Build a hosted Z.AI request
  8. Configure direct Transformers
  9. Configure vLLM and SGLang
  10. Avoid double penalties
  11. Design a useful evaluation
  12. Protect code and structured output
  13. Migrate and roll back safely
  14. Review access
  15. Audit sources and limits
  16. Resolve common questions

The checked contracts are not interchangeable:

Route or artifact Repetition Frequency Presence Omitted values Practical decision
Z.AI Chat Completion schema not documented not documented not documented no penalty contract published omit all three or verify a separately documented extension
Pinned GLM-5.2 generation config absent absent absent checkpoint adds no override engine or caller decides
Transformers 5.12 supported not exposed by GenerationConfig not exposed by GenerationConfig 1.0 pin 1.0 for a neutral baseline
vLLM 0.27.1 supported, greater than 0 −2 through 2 −2 through 2 1.0 / 0.0 / 0.0 validate all three as vLLM fields
SGLang 0.5.17 supported, greater than 0 through 2 −2 through 2 −2 through 2 1.0 / 0.0 / 0.0 enforce SGLang’s upper bound of 2

The current Z.AI Chat Completion reference is the hosted contract used here. Absence from that schema means undocumented in the checked source; it does not prove every backend or OpenAI-compatible proxy rejects the field. A safe client nevertheless fails closed because accepting, ignoring, and rejecting lead to materially different experiments.

The pinned GLM-5.2 generation config sets temperature 1 and top P 0.95 but contains none of the three penalty keys. Do not infer an intended non-neutral penalty from community presets, a model quantization, or another GLM release.

The model name identifies weights and a family of behaviors; it does not make every request envelope identical. In this audit, the route contract comes from four separately versioned artifacts:

  • Z.AI’s hosted schema lists allowed and documented request fields.
  • Transformers 5.12 defines GenerationConfig defaults and logits processors.
  • vLLM 0.27.1 defines its own SamplingParams fields and validation ranges.
  • SGLang 0.5.17 defines another SamplingParams contract with a tighter repetition-penalty upper bound.

The official GLM-5.2 model card currently names Transformers 5.12.0, vLLM 0.23.0 or newer, and SGLang 0.5.13.post1 or newer as supported routes. That compatibility statement does not say their optional sampling fields share defaults, ranges, or token scope. This audit pins newer compatible server versions—vLLM 0.27.1 and SGLang 0.5.17—rather than treating “latest” as a reproducible version.

An OpenAI-compatible client adds another layer. It may expose the two OpenAI style additive fields, hide a native repetition field, or place extensions in an extra_body. Record both the application payload and the server’s resolved configuration. A client-side object is not proof that the engine applied it.

The three names do not mean the same thing

Section titled “The three names do not mean the same thing”

The pinned vLLM sampling source provides a useful side-by-side definition:

  • presence_penalty changes a candidate token based on whether it has appeared in generated text so far. It is membership-based, not count-based.
  • frequency_penalty changes a candidate based on how often it has appeared in generated text. Repeating a token more times changes the effect.
  • repetition_penalty considers tokens found in the prompt and generated text so far. Values above 1 discourage reuse; values below 1 encourage it.

Transformers implements the last family through RepetitionPenaltyLogitsProcessor. The checked source says the processor applies at most once per token and, for a decoder-only model, includes prompt tokens by default. A value of 1.0 is neutral. This is not an additive “subtract 0.5 every time” control.

The operational difference matters. A prompt may intentionally contain a function name, schema key, code identifier, or citation several times. Repetition penalty can affect that token even before it appears in the answer. Frequency and presence penalties, under the cited vLLM definitions, operate on the generated history. Treating the controls as aliases can change which tokens are suppressed.

A neutral value means a supported control makes no adjustment. It does not mean every endpoint accepts the field:

One neutral state, three different payload decisions
{
"zai_hosted": {},
"transformers_5_12": { "repetition_penalty": 1.0 },
"vllm_or_sglang": {
"repetition_penalty": 1.0,
"frequency_penalty": 0.0,
"presence_penalty": 0.0
}
}

The first object intentionally omits all three fields because the checked Z.AI schema does not document them. The local objects make their supported neutral state visible for auditing. If a wrapper rejects explicit neutral fields, log the engine-resolved defaults instead of forcing them through the wire format.

Omission also needs version context. The pinned checkpoint provides no penalty override, so Transformers falls back to its library default of 1.0. vLLM and SGLang currently fall back to 1.0, 0.0, and 0.0. A future model file, engine, or gateway can change the resolved state without changing your application payload. Persist the resolved values beside the requested values.

The audit checks positive, negative, and boundary cases without generating text. Representative outcomes are below; the public receipt contains all 23.

Fixture Route Input Outcome Evidence value
Hosted omission Z.AI no penalty fields accept stays inside the published schema
Hosted repetition field Z.AI repetition 1.1 reject locally prevents an undocumented-field experiment
Local omission Transformers none accept, resolves 1.0 confirms the neutral library default
Active local repetition Transformers 1.1 accept proves a supported non-neutral experiment path
Zero repetition Transformers 0 reject enforces the positive-number constraint
Presence on Transformers Transformers 0.5 reject prevents dialect translation by name alone
vLLM omission vLLM none accept, resolves 0 / 0 / 1 records all neutral defaults
vLLM additive bounds vLLM −2 and 2 accept checks both documented endpoints
vLLM frequency 2.01 vLLM 2.01 reject catches a value above the range
Mixed families vLLM repetition 1.1 + frequency 0.5 accept with warning makes double control visible
SGLang repetition 2 SGLang 2 accept checks its inclusive upper endpoint
SGLang repetition 2.01 SGLang 2.01 reject captures the vLLM/SGLang bound difference
String value vLLM "1.1" reject prevents coercion before serving

Download the byte-identical machine-readable receipt to inspect every source hash, resolved value, error, warning, and assertion. The fixtures prove configuration logic only. They do not prove that 1.1 improves GLM-5.2, that an undocumented hosted field is rejected, or that two engines produce identical tokens. The receipt names its cross-family warning MIXED_PENALTY_FAMILIES_ACTIVE so CI can distinguish it from an OUT_OF_RANGE rejection.

Use a route allowlist before constructing the final request. This compact validator preserves the key distinction between “unsupported field” and “invalid supported value”:

Fail-closed GLM-5.2 penalty validator
const contracts = {
zai: { supported: [], defaults: {}, ranges: {} },
transformers: {
supported: ["repetition_penalty"],
defaults: { repetition_penalty: 1 },
ranges: { repetition_penalty: { gt: 0 } },
},
vllm: {
supported: ["repetition_penalty", "frequency_penalty", "presence_penalty"],
defaults: { repetition_penalty: 1, frequency_penalty: 0, presence_penalty: 0 },
ranges: {
repetition_penalty: { gt: 0 },
frequency_penalty: { min: -2, max: 2 },
presence_penalty: { min: -2, max: 2 },
},
},
sglang: {
supported: ["repetition_penalty", "frequency_penalty", "presence_penalty"],
defaults: { repetition_penalty: 1, frequency_penalty: 0, presence_penalty: 0 },
ranges: {
repetition_penalty: { gt: 0, max: 2 },
frequency_penalty: { min: -2, max: 2 },
presence_penalty: { min: -2, max: 2 },
},
},
};
export function validatePenalties(route, requested) {
const c = contracts[route];
if (!c) throw new Error(`Unknown route: ${route}`);
const resolved = { ...c.defaults };
const errors = [];
for (const [key, value] of Object.entries(requested)) {
if (!c.supported.includes(key)) {
errors.push(`UNDOCUMENTED_OR_UNSUPPORTED:${key}`);
continue;
}
if (!Number.isFinite(value)) {
errors.push(`INVALID_NUMBER:${key}`);
continue;
}
const r = c.ranges[key];
if ((r.gt !== undefined && value <= r.gt) ||
(r.min !== undefined && value < r.min) ||
(r.max !== undefined && value > r.max)) {
errors.push(`OUT_OF_RANGE:${key}`);
continue;
}
resolved[key] = value;
}
return { accepted: errors.length === 0, requested, resolved, errors };
}

Do not clamp 2.01 to 2, translate presence_penalty into repetition_penalty, or drop an unknown field and continue. Return a local configuration error so the experiment owner can decide deliberately.

Keep the Z.AI request inside its published schema

Section titled “Keep the Z.AI request inside its published schema”

For the hosted route, a conservative request omits penalty fields:

Schema-bounded hosted request
{
"model": "glm-5.2",
"messages": [{ "role": "user", "content": "Review this patch." }],
"do_sample": true,
"temperature": 1.0,
"top_p": 0.95,
"max_tokens": 4096
}

If repetitive output appears, first preserve the full prompt, conversation, tool results, sampling profile, and finish reason. Confirm that duplicated context, a retry loop, a malformed chat template, or missing stop handling did not create the symptom. The temperature and top-P guide owns stochastic-control parity, while the stop-token guide owns termination boundaries.

Only send a penalty extension after its actual provider or gateway publishes a field name, range, default, and behavior for that route. Version that extension separately from Z.AI’s documented schema. A successful HTTP response is still not enough: record the resolved server configuration or run a discriminating canary so an ignored field cannot masquerade as an active control.

The pinned checkpoint does not set repetition_penalty, so make the neutral baseline explicit in direct generation:

Neutral direct-Transformers baseline
outputs = model.generate(
**inputs,
do_sample=True,
temperature=1.0,
top_p=0.95,
repetition_penalty=1.0,
max_new_tokens=4096,
)

When you test a non-neutral value, change only repetition_penalty, retain the neutral run, and label the result as an experiment rather than a GLM-5.2 recommendation. Transformers requires a strictly positive float. Values above 1 penalize previously seen tokens; values between 0 and 1 reward them.

The default processor includes prompt tokens for decoder-only models. If your task must repeat exact identifiers, use task-level tests before rollout. A custom prompt_ignore_length can change the processor scope, but that is a different algorithm and must receive a separate profile name and baseline.

Treat vLLM and SGLang as distinct contracts

Section titled “Treat vLLM and SGLang as distinct contracts”

Both checked servers expose all three controls and share neutral defaults, but their accepted repetition bounds differ:

Pinned vLLM neutral SamplingParams
from vllm import SamplingParams
sampling = SamplingParams(
repetition_penalty=1.0,
frequency_penalty=0.0,
presence_penalty=0.0,
temperature=1.0,
top_p=0.95,
max_tokens=4096,
)

vLLM 0.27.1 requires only that repetition penalty be finite and greater than zero. SGLang 0.5.17 limits it to (0, 2]. Both constrain presence and frequency to [-2, 2]. Validate against the selected engine, not against the wider of the two ranges.

If you use an OpenAI-compatible HTTP layer, inspect its protocol model as well as the native sampling object. A client may serialize standard presence and frequency fields but require an extension mechanism for repetition. Preserve the server version, protocol adapter version, and resolved native values in the same receipt.

The engines can accept multiple non-neutral controls, but acceptance does not make the experiment interpretable. A repetition penalty and an additive frequency penalty can both alter the same candidate token through different math. If output changes, you cannot attribute the effect to one control.

Use this rollout order:

  1. Run the neutral 1 / 0 / 0 baseline.
  2. Test one non-neutral field against the same fixture set.
  3. Retain raw task outcomes, not just an overall preference score.
  4. Test a combination only when the single-field evidence justifies it.
  5. Give the combination a new profile name and rollback threshold.

The audit warns on mixed repetition and additive families and on simultaneous frequency and presence controls. It does not reject them because the pinned vLLM and SGLang sources allow them. Your deployment policy can be stricter than the engine.

A useful evaluation contains prompts that need both legitimate repetition and protection from loops:

Task fixture Legitimate repeated material Failure to measure
Code patch variable, function, and file names renamed identifiers, incomplete patch, repeated commentary
JSON extraction required keys and enum values missing keys, duplicate objects, schema failure
Tool call tool name and argument keys invalid arguments, repeated call cycle
Citation answer source names and exact terms dropped citations, repeated paragraph
Long agent trace task constraints and checkpoints looped plan, forgotten constraint, premature stop

Score task success, loop incidence, schema validity, and required-token recall. Do not optimize only for lexical novelty: a response that avoids repetition by dropping required identifiers is worse.

Per-token scores can help detect a distribution shift, but their availability and stage differ by runtime. The GLM-5.2 logprobs guide keeps that observability contract separate and explains why likelihood is not task correctness. Explicit token targeting is another separate control: the GLM-5.2 logit-bias map covers listed token IDs, sequence-aware bias, and hard masks rather than history-based penalties.

Run more than one sample when sampling is enabled. Hold the model revision, engine, chat template, reasoning effort, temperature, top P, output cap, prompt, tools, and hardware class constant. The reasoning-effort guide explains why reasoning depth is a separate control; changing it in the same experiment destroys attribution.

Because the checked Transformers repetition processor includes prompt tokens by default, a non-neutral value can discourage terms the prompt explicitly requires. This is a source-based risk inference, not a measured GLM-5.2 failure. It deserves targeted fixtures for:

  • property names that must recur across a JSON array;
  • API and function identifiers repeated in code;
  • exact legal, medical, or scientific terminology;
  • citation labels used in more than one paragraph;
  • tool names and argument keys carried across turns.

For machine-consumed output, validate the result with the structured-output pattern rather than judging fluency. For tools, run the complete function-calling loop and count repeated calls separately from repeated words. A generation penalty cannot repair an application loop that keeps resubmitting the same tool result.

Store requested and resolved state together:

Minimum repetition-control receipt
{
"route": "vllm",
"engine_version": "0.27.1",
"model_revision": "b4734de4facf877f85769a911abafc5283eab3d9",
"requested": {
"repetition_penalty": 1.0,
"frequency_penalty": 0.0,
"presence_penalty": 0.0
},
"resolved": {
"repetition_penalty": 1.0,
"frequency_penalty": 0.0,
"presence_penalty": 0.0
},
"fixture_set": "repetition-contract-v1"
}

Canary a changed profile before production traffic. Roll back on a bounded increase in schema failures, missing required tokens, tool-loop rate, task failure, latency, or token use. Do not attribute a change to penalties until the adapter receipt proves the intended control reached the intended engine.

Re-run the contract audit when the Z.AI schema, checkpoint revision, Transformers, vLLM, SGLang, or client adapter changes. A dependency upgrade is a configuration migration even when the application payload is untouched.

Once the route validator and acceptance fixtures are ready, choose the access path. Hosted access avoids model-serving operations; self-hosting exposes more native controls but makes version pinning, GPU capacity, and observability your responsibility.

Checked on August 16, 2026 (Hong Kong time). The audit fetched the current Z.AI Chat Completion schema, Hugging Face model API, pinned GLM-5.2 generation config and README, Transformers 5.12 generation configuration and repetition processor, vLLM 0.27.1 sampling source, SGLang 0.5.17 sampling source, the required Z.AI GLM-5.2 release entry, and the Zhipu research index. URLs, status, body byte counts, and SHA-256 hashes are retained; response bodies are not archived.

The foreground round began with an AI HOT item about Cursor joining SpaceX. It contained no GLM-5.2 artifact, parameter, or implementation task, so it was classified weak-glm-link and not used as article evidence. The topic came from proactive first-party documentation and pinned-source research.

One exact Google result set for glm 5.2 repetition penalty was recorded as request serpapi-fa1f2433813d426698c0f1561b964805. It returned fragmented community settings, a third-party quantization, broad GLM pages, and an Unsloth GLM-5 guide, but no first-party cross-runtime contract audit. That gap selected this intent. Community numeric suggestions were deliberately excluded from the recommendation.

The validator performs deterministic configuration checks. It does not prove text quality, backend implementation, account entitlement, route acceptance, or byte-identical output. An undocumented field may be accepted by a separate extension; a supported field may still be transformed by a wrapper. No GLM, MiniMax, grader, authenticated API, credential, private prompt, tokenizer, or model weight was used.

What repetition_penalty should I use for GLM-5.2?

Section titled “What repetition_penalty should I use for GLM-5.2?”

Start at the neutral value 1.0 on a runtime that documents the field. The checked first-party GLM-5.2 sources do not establish a universal non-neutral recommendation. Test one change against task fixtures and keep the neutral baseline.

Does the Z.AI GLM-5.2 API support repetition_penalty?

Section titled “Does the Z.AI GLM-5.2 API support repetition_penalty?”

The Chat Completion schema checked on August 16, 2026 does not document repetition_penalty, frequency_penalty, or presence_penalty. That is not proof of rejection, but a production client should omit them unless its exact route publishes an extension contract.

What is the neutral value for each penalty?

Section titled “What is the neutral value for each penalty?”

For the checked local runtimes, repetition penalty is neutral at 1.0. Frequency and presence penalties are neutral at 0.0. Neutral values do not make an unsupported field portable to the hosted API.

Are frequency_penalty and repetition_penalty equivalent?

Section titled “Are frequency_penalty and repetition_penalty equivalent?”

No. vLLM documents frequency penalty as count-based over generated text and repetition penalty as membership-based over prompt plus generated text. They can affect the same token differently.

Why does SGLang reject a value vLLM accepts?

Section titled “Why does SGLang reject a value vLLM accepts?”

The pinned SGLang 0.5.17 source caps repetition penalty at 2, while pinned vLLM 0.27.1 requires a finite value greater than zero without that upper bound. Validate against the engine actually serving the request.

Can repetition penalty fix an agent tool loop?

Section titled “Can repetition penalty fix an agent tool loop?”

Not reliably. A tool loop often comes from application state, repeated tool results, termination handling, or an invalid call cycle. Measure repeated calls separately from repeated tokens and repair the loop at the layer that owns it.