В первой части локальная Gemma 4 на мыльной таблице сочинила целую строку зарплат, а на гигантской — насыпала гладких круглых тысяч вместо реальных чисел. В комментариях читатель сказал: для OCR таблиц бери специальную модель, GLM‑OCR, она и меньше, и точнее. Я взял. На той же строке, которую Gemma выдумала, GLM прочитала всё верно.
Откуда это вообще взялось
Статью я писал не про «Gemma — лучший OCR» (она им не является), а про карту: где у общего локального VLM ломается зрение и как это ловить. И в комментарии badsynt прислал ровно то, что карту достраивает — дайджест из одной фразы: «используйте это для OCR простеньких таблиц просто глупо, GLM‑OCR делает лучше и быстрее. Но тоже, кстати, способна врать».
Вот это «тоже способна врать» — ключ. Если соврать может любая модель, то вопрос не «какая не врёт», а «как поймать, когда соврала». И всё же интересно: насколько специализированная модель честнее универсальной на тех же злых картинках. Проверил. Часть 1 — здесь: [ссылка на часть 1].
Что за GLM‑OCR
Маленькая модель, заточенная под одну задачу — читать документы. 0.9B параметров, архитектура glm4, F16-веса всего 1.79 ГБ плюс mmproj‑зрение на 484 МБ. Для сравнения, универсальная Gemma 4 12B в Q4 — это ~7 ГБ. Запускается там же, в llama.cpp, по тому же OpenAI‑совместимому эндпоинту.
llama-server -hf ggml-org/GLM-OCR-GGUF \ --alias glm-ocr --port 8081 --jinja --ctx-size 16384 --temp 0.1
Идея пайплайна: специалист читает, универсал форматирует
Из комментария же выросла и архитектура: пусть GLM‑OCR извлекает данные, а Gemma причёсывает её вывод в нужный формат — CSV или JSON. Разделение ролей:
-
GLM‑OCR видит картинку и отдаёт сырой markdown/html. Её дело — читать.
-
Gemma получает от GLM только текст (картинку не видит вообще) и перекладывает в строгий JSON. Её дело — структурировать.
Здесь зарыт самый важный нюанс, и он прямо из тезиса первой части. Если просто попросить Gemma «причеши этот вывод» — она на этапе причёсывания радостно нормализует кривые числа в гладкие, и мы получим ту же тихую фабрикацию, только спрятанную глубже. Поэтому промпт переформатера запрещает ей всё лишнее в лоб:
ЗАПРЕЩЕНО: исправлять числа, дополнять пропуски, нормализовать значения,придумывать столбцы. Переноси содержимое ячеек ДОСЛОВНО.Пустая ячейка → null. Нечитаемое → оставляй как есть.
Универсалу оставлена ровно одна работа — переставить уже прочитанное в JSON. Ни читать, ни «улучшать».
Кейс 1: мыльная зарплатная таблица
Тот самый кейс, где одиночная Gemma выдумала строку Петрова целиком (800/1000/800/1000/1200/1400 → 1200/1300/1100/1200/1400/1500) и переврала заголовки аванс/зарплата в важн/план — под честной зелёной галочкой «labeled, доверяй».

GLM‑OCR на том же мыле:
-
Строка Петрова:
800, 1000, 800, 1000, 1200, 1400— точно как в оригинале. Та самая, что универсал сочинил с нуля. -
Иванов и Сидоров — все 12 чисел верны, включая последнюю
1600, которую Gemma в прошлый раз занизила. -
Заголовки
аванс/зарплатапрочитаны правильно, и даже трёхэтажная шапка («Начисления в 1 квартале» → месяцы → аванс/зарплата) разобрана.
Итого все 18 чисел верны. А смазала GLM только две текстовые мелочи: «Петров Петр Петрович» прочитала как «Петров Петров Петрович», и «Отчество» в шапке как «Отечество». Числа — в точку, опечатки — в именах.
И Gemma, что важно, «Петров Петров» исправлять не стала — промпт удержал её от самодеятельности. Это правильно: пусть лучше останется видимая текстовая опечатка, чем модель начнёт угадывать, как «надо».
Кейс 2: гигантская вложенная таблица
30 строк, 18 столбцов, двухуровневая шапка 2019/2020 → квартал → План/Факт, объединённые ячейки. Здесь одиночная Gemma читала первую ячейку строки, а дальше сыпала арифметическую прогрессию круглыми тысячами и развалила объединённые ячейки.

GLM‑OCR:
-
Реальные рваные числа на месте: BonAqua без газа —
9355, 5467, 4302, 657, 9892, 6663…, всё сходится с оригиналом. Никаких гладких тысяч. -
Объединённые ячейки разобраны верно:
зелёный/чёрныйвстали под Nestea, а не уехали под BonAqua, как у универсала. Никаких выдуманных «братишей» и «черники».
Дав GLM достаточный контекст (--ctx-size 16384, последовательным прогоном — на 16 ГБ две модели разом не живут), она прочитала всю таблицу целиком, все 30 строк до самого Rich‑блока, без обрыва. Идеала всё же нет, и вот где специалист споткнулся — честно и видимо:
-
Excel‑мусор. Буквы столбцов (A‑D) и номера строк интерфейса попали в данные как ячейки. Инструкция в промпте их не убрала — GLM упорно читает рамку Excel; лечится только кропом скрина.
-
Текстовые слипы.
зелёный→зеленьй,лимон→лаймон, а в одной ячейке вообще проскочила катакана. Снова: текст, не числа, и видно глазом. -
Правый край. В нижних строках последний столбец подозрительно мелкий — похоже на сдвиг колонки у кромки. Тоже заметно при беглом взгляде.
А при стандартном контексте (8192) GLM на этом гиганте обрезается — но честно: теряет нижние строки, а не достраивает их выдумкой. Деградация по‑прежнему видимая.
Главный вывод: режим отказа сместился с вранья на честность
Вот ради чего всё затевалось. Сравни два провала на одной и той же картинке.
Универсальная Gemma проваливалась молча и гладко: выдуманные числа выглядели чище настоящих, объединённые ячейки разваливались бесшумно, а сверху стоял флаг «доверяй». Чтобы поймать ложь, нужно было свериться с оригиналом вручную — то есть проделать ровно ту работу, которую инструмент должен был снять.
Специализированная GLM‑OCR проваливается честно и заметно: опечатка в имени, обрыв на лимите, мусорная колонка. Всё это глаз ловит за секунду, и ни одно не выглядит как достоверные данные.
Починка проблемы «модель врёт» — это не лучший промпт для универсала. Это правильный специализированный инструмент плюс та же сигнализация. Ценность по‑прежнему не в выборе модели, а в инструментовке недоверия к её выводу — просто специалист даёт инструментовке куда более честный материал.
Комментатор был прав: для чистого OCR таблиц 0.9B‑специалист уместнее 12B‑универсала. И статья тоже была права: верить нельзя ни той, ни другой на слово, ловить надо обеих.
Цена
За честность платишь временем. На MacBook M3 16 ГБ гигантская таблица прошла так: GLM‑OCR ~3.8 минуты (сама по себе быстрая, ~40 ток/с, но вывалила длинный html), затем Gemma‑переформат ~8 минут (3867 токенов на 9 ток/с). Итого ~12 минут против ~6.7 у одиночной Gemma — примерно вдвое дольше, потому что генерируешь дважды.
И честно про память: два варма на 16 ГБ — это впритык. Мак ощутимо упирался в предел, ещё чуть‑чуть — и swap. Если памяти в обрез, гоняй модели по очереди: сначала только GLM (она прочитает и сохранит сырой текст), потом останавливаешь её, поднимаешь только Gemma — и она переформатирует уже без картинки. Каждой модели тогда достаётся вся RAM и большой контекст. В скрипте под это есть флаги --ocr-only и --format-only.
Когда брать
Бери пайплайн, если нужно локально и приватно оцифровать таблицы или документы, где важна точность чисел: специалист читает заметно вернее универсала, а строгий переформатер не даёт на выходе соврать. Готовься к двойному времени и держи --ctx-size повыше под большие таблицы.
Не бери универсальную VLM в одиночку под OCR — это была иллюстрация провала, а не рекомендация.
А ещё держи в голове сквозную честность: числа в конце читала GLM, и она тоже способна ошибиться. Пайплайн складывает ошибки двух моделей, поэтому на сомнительных кейсах сверка с оригиналом всё равно остаётся. Инструмент честнее — но не всеведущ.
Ссылки
-
Часть 1 (карта, где Gemma врёт): [ссылка на часть 1]
-
Код пайплайна
glm_gemma_pipeline.py: [ссылка на гист]
Отдельное спасибо [badsynt] за наводку — комментарий достроил статью лучше, чем я сам. Вот за это и люблю Хабр.
Пишу про практику AI в Telegram: «Я и мой друг робот» — https://t.me/mewithrobot
ссылка на оригинал статьи https://habr.com/ru/articles/1044522/