GLM-5.2 Repetition Penalty: Prevent Runtime Drift
Independent research — not an official Z.ai publication.Identity and provider disclosure
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.
Navigate the repetition-control contract
Section titled “Navigate the repetition-control contract”- Read the contract table
- Compare the four runtime contracts
- Separate the three penalty meanings
- Understand the neutral baseline
- Review the 23-fixture audit
- Copy the fail-closed validator
- Build a hosted Z.AI request
- Configure direct Transformers
- Configure vLLM and SGLang
- Avoid double penalties
- Design a useful evaluation
- Protect code and structured output
- Migrate and roll back safely
- Review access
- Audit sources and limits
- Resolve common questions
The penalty contract in one table
Section titled “The penalty contract in one table”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.
One model, four penalty contracts
Section titled “One model, four penalty contracts”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
GenerationConfigdefaults and logits processors. - vLLM 0.27.1 defines its own
SamplingParamsfields and validation ranges. - SGLang 0.5.17 defines another
SamplingParamscontract 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_penaltychanges a candidate token based on whether it has appeared in generated text so far. It is membership-based, not count-based.frequency_penaltychanges a candidate based on how often it has appeared in generated text. Repeating a token more times changes the effect.repetition_penaltyconsiders 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.
Neutral does not mean portable
Section titled “Neutral does not mean portable”A neutral value means a supported control makes no adjustment. It does not mean every endpoint accepts the field:
{ "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.
What the 23-fixture audit proves
Section titled “What the 23-fixture audit proves”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.
Reject contract drift before allocation
Section titled “Reject contract drift before allocation”Use a route allowlist before constructing the final request. This compact validator preserves the key distinction between “unsupported field” and “invalid supported value”:
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:
{ "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.
Set an explicit Transformers baseline
Section titled “Set an explicit Transformers baseline”The pinned checkpoint does not set repetition_penalty, so make the neutral
baseline explicit in direct generation:
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:
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.
Do not stack penalty families by accident
Section titled “Do not stack penalty families by accident”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:
- Run the neutral
1 / 0 / 0baseline. - Test one non-neutral field against the same fixture set.
- Retain raw task outcomes, not just an overall preference score.
- Test a combination only when the single-field evidence justifies it.
- 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.
Test repetition with task evidence
Section titled “Test repetition with task evidence”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.
Watch prompt-token side effects
Section titled “Watch prompt-token side effects”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.
Persist requested and applied penalties
Section titled “Persist requested and applied penalties”Store requested and resolved state together:
{ "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.
Select the runtime after validation
Section titled “Select the runtime after validation”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.
Dated penalty evidence and limits
Section titled “Dated penalty evidence and limits”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.
GLM-5.2 repetition penalty FAQ
Section titled “GLM-5.2 repetition penalty FAQ”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.
