Repository navigation
fix: lower default repetition_penalty to avoid table hallucination (#240) - #244
agourakis82 wants to merge 2 commits into
Conversation
…ai-org#240) The SDK's default page_loader.repetition_penalty=1.1 causes the model to deterministically hallucinate spurious trailing content on table regions: on a real-world invoice table, every identical call under temperature=0.0 appended a fabricated extra row ('missing in table') that does not exist in the source image. A repetition_penalty sweep on the same real image showed a clear threshold: the hallucination is absent at rp<=1.05 and present at rp>=1.08 (tested 1.01, 1.02, 1.05, 1.08, 1.1, 1.15, 1.2), with 8/8 identical, deterministic outputs at every value. The hallucination was reproduced identically on two independent backends/hardware: mlx_vlm (Apple Silicon) and vLLM (CUDA), through both a raw mlx_vlm.generate() call and the full SDK pipeline (glmocr.server + PP-DocLayoutV3 layout detection + vLLM OCR). This lowers the default to 1.05, just below the observed threshold, keeping some repetition suppression (relevant to zai-org#220-style repeat loops) while avoiding the table hallucination in all tested cases. See discussion and repro scripts in: zai-org#240 (comment) zai-org#240 (comment) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
Configuration defaults are aligned; only a minor regression-test nit remains.
Review effort: Lite
Findings: None
What changed in this PR
Lowers the default repetition_penalty from 1.1 to 1.05 to reduce table hallucinations.
Changes:
- Updates Python and YAML defaults.
- Documents the observed behavior from issue #240.
| File | Description |
|---|---|
glmocr/config.yaml |
Updates the packaged runtime default and rationale. |
glmocr/config.py |
Updates the built-in page-loader default. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
I checked this PR locally at Verified the config-only diff: The Python and YAML defaults are aligned on I also reproduced the declared formatting/lint gate with a fresh Result: I did not rerun the OCR/model sweep itself in this environment, so this is validation of the PR surface and declared pre-commit gate, not an independent reproduction of the hallucination threshold. |
What
Lowers the SDK's default
pipeline.page_loader.repetition_penaltyfrom1.1to1.05in bothglmocr/config.pyandglmocr/config.yaml.Why
While investigating #240, I found that the default
repetition_penalty=1.1makes GLM-OCR deterministically hallucinate a spurious extra row on table regions. On the real invoice image attached to #240, every identical call (temperature=0.0) appended a fabricated row that does not exist anywhere in the source:A
repetition_penaltysweep on the same image (8 identical runs per value, fully deterministic at each) shows a clear threshold:repetition_penaltyNone,1.01,1.02,1.051.08,1.1(current default),1.15,1.2I reproduced this identically on two independent backends/hardware:
mlx_vlm.generate()on Apple Silicon (mlx-community/GLM-OCR-bf16)glmocr.server+PP-DocLayoutV3layout detection +vllm serve zai-org/GLM-OCR— on CUDA (vLLM 0.29.0)Both gave byte-identical output across repeated calls, with the hallucination appearing/disappearing at the same threshold in both environments.
This PR moves the default just below that threshold (
1.05) rather than removing repetition suppression entirely, since some penalty is presumably useful against repeat loops (README/older reports mention repetition issues). Happy to adjust the exact value or make it task-specific (e.g. a lower penalty fortablethantext) if maintainers have a preference or additional data — my testing was limited to this one document/table layout.Testing
pre-commit run --files glmocr/config.py glmocr/config.yamlpasses (black, flake8, typos, etc.)References
🤖 Generated with Claude Code