On-device document recognition on Core AI. A port of
zai-org/GLM-OCR (MIT, 0.9B) — a small, SOTA-quality
document recognizer (OmniDocBench v1.5 94.62, #1 with its layout pipeline). Prompt it with
Text Recognition: / Table Recognition: / Formula Recognition: and get plain text (reading
order), HTML tables (<table>…), or LaTeX. zh / en / fr / es / ru / de / ja / ko. The zoo’s
second doc-OCR, after Unlimited-OCR — a higher-quality, simpler architecture.
GLM-OCR is a small OCR variant of GLM-4.V (Glm4v): a CogViT vision tower + a 16-layer GLM text
decoder with sectioned 3D M-RoPE. This port is the shipped Qwen3-VL vision idiom
(the image_embeds + rope-shift static-input hook) with a GLM text decode — no R-SWA, no MoE, no
MLA. The vision tower runs once; its image_embeds are injected at the image placeholder positions
(V + slot, row-major over the merged grid) and the text decodes on top.
⬇️ Converted .aimodel bundles:
mlboydaisuke/GLM-OCR-CoreAI —
vision/ (CogViT, fp16, 829 MB) + decoder/ (GLM decoder, S=1 pipelined, int8hu, 764 MB) +
tokenizer/. MIT.
downsample conv (2×2) + a GLM patch merger. No deepstack, no learned pos-embed — just baked
2D-rope constants. Exported as one fp16 .aimodel; N (visual tokens) is fixed by the export grid.gate_up_proj, sectioned M-RoPE [16,24,24] with GLM
interleaved rotate. Driven on the pipelined-engine S=1 contract: input_ids [1,1],
position_ids, static image_embeds [N,1536] + rope_shift_start + rope_shift_amount. Zero
embeds + shift_start = 1<<30 → a plain GLM text decoder.COREAI_CHUNK_THRESHOLD=1.image_embeds cos 0.9998; decoder argmax exact over the sampled positions.page image → resize to the export grid (here 22×31 merged = 682 visual tokens)
→ vision .aimodel → image_embeds [682,1536]
→ prompt: [ …, <image>×682, "Text Recognition:" ] (image ids → V+slot, row-major)
→ decoder S=1 pipelined decode (image_embeds injected, shift_start=img_start+N,
shift_amount=N−max(gh,gw)) → tokens
→ detokenize → text / <table>HTML / LaTeX
conversion/export_glm_ocr_pipelined.py
(fp16 / int8lin / int8hu; vision stays fp16). Bundles + HF upload:
conversion/_glmocr_hf_upload.py.image_embeds + rope_shift_start + rope_shift_amount) and COREAI_CHUNK_THRESHOLD=1; feed the
prompt with the image placeholders rewritten to V+slot. The host contract + the exact static-input
values are in the knowledge doc below.knowledge/glm-ocr-port.md.