你把掃描表格轉成文字,品名、金額排得整整齊齊,卻把「應付 1,240」抄成「1,248」。如果接到文件問答系統,錯字可能變成之後每次回答的依據。MiniCPM-OCR Jev 教學要解決的,就是怎麼在入庫前,多設一道能追查的品質分流。
這篇寫給第一次接觸 OCR 品質評分的讀者:先用白話理解原理,再準備繁中表格、呼叫本機 API、選擇複核門檻。概念段不需要程式背景;操作段需要已備妥 NVIDIA GPU 的 Linux Docker 環境,以及基本 Python 操作。
本文依 2026 年 10 月 29 日查閱的官方文件與固定程式版本整理。本次主機是 Apple silicon,未執行 Jev GPU 推論;下方是部署與評估方法,紙上數字均另行標示,不把它們寫成模型成績。
先說結論:分數是篩檢尺,放行要有驗收收據
可靠入庫=有效評分+自己的門檻驗證+可回看的原圖。把 Jev 想成收件處的篩檢員:它幫你安排哪些稿件先看,合格標準則由你的文件與錯誤成本決定。
- 先看
verdict=scored,再讀prob_yes;技術失敗與低品質候選分開記。 - 同一張原圖配上正確、錯字、錯金額、錯欄四種候選,檢查這把尺會漏掉什麼。
- 用校準集選門檻,再到未參與選門檻的保留集驗收;金額等重要欄位仍保留獨立規則。
一、MiniCPM-OCR Jev 教學:先分清五個零件
OCR(光學字元辨識)負責從圖片讀字;Jev 接在辨識之後,對已有結果評分。官方模型指南把評估單位定為一個文字、公式或表格區域,輸入包含原圖、候選文字,以及候選文字重新畫成的圖片。
- ①「底稿」:文件上的原始區域裁圖。保留頁碼與座標,別讓正確數字來自隔壁欄。
- ②「抄本」:OCR 輸出的候選內容,連同表格結構一起交給評分器。
- ③「重印稿」:Renderer(渲染器)把候選內容畫回像素,讓模型比較版面。
- ④「篩檢尺」:Jev 比較這組輸入,給出 0 到 1 的分數。
- ⑤「收件規則」:你選的門檻、關鍵欄位檢查與複核流程,決定資料往哪走。
為何要重畫?同樣一段繁中文字,換字型可能改變字形、換行與欄寬。對模型而言,這些像素都是輸入。官方 Dockerfile特別處理 CJK 字型與字型替代;缺少對應字型,可能畫成方框。先把尺固定,才有意義比較分數。
別把 prob_yes=0.95直接翻成「這批繁中表格有 95% 正確率」。官方指南明確要求另查分數區間與實際正確比例是否吻合。機率校準文件也用這種對照解釋 calibration:同一分數區間的預測,要和觀察到的比例相符,才有機率意義。

二、先固定 Docker 與字型,再評第一張圖
擔心裝好後每台分數不同?先選官方 Docker 路徑。本機部署指南列出的這條 NVIDIA 起點是至少 12 GB VRAM、驅動版本至少 535。這是本篇採用的部署配置,不是所有推論後端的共同最低需求。
先準備 Docker、可用的 NVIDIA 容器 GPU,以及官方模型權重目錄。從官方權重入口取得並記錄 revision 與檔案雜湊;本篇不在一般筆電下載或啟動整套 GPU 服務。已具備條件的人,從新的練習目錄執行:
git clone https://github.com/OpenBMB/MiniCPM-OCR.git
cd MiniCPM-OCR
git checkout b33b474136088dc43a2341e94590c804ec0c16a5
cd scripts/minicpm-ocr-jev
docker build -f serve/Dockerfile -t jev-eval:pinned .
docker run -d --name jev-eval --gpus '"device=0"' \
-p 127.0.0.1:8030:8030 \
-v /absolute/path/to/checkpoint:/weights:ro \
jev-eval:pinned 8030 /weights
curl -f http://127.0.0.1:8030/healthz
把 /absolute/path/to/checkpoint換成你已下載的真實絕對路徑。驗收時打開 health 回應,確認 status為 ok;HTTP 有回應仍可能是在載入。這條指令只把服務埠綁到本機,練習文件先用自行製作的無個資表格。
固定 commit 還不等於日後重建必定得到同一份映像:Dockerfile 仍會從套件來源安裝部分系統依賴。建置成功後,記下 docker image inspect jev-eval:pinned --format '{{.Id}}',保留那一份映像,另存 health JSON、模型 revision、字型清單及 Chromium 版本。換了映像、字型或裁圖設定,就視為新配置重新驗收。
三、繁中表格怎麼配對?四份抄本共用同一張底稿
怕測到的只是「排版漂亮」?先做受控錯誤對照。自製一張橫排表格,含「項目、金額、應付」等繁中字,並在人工稿標清每個儲存格與欄位歸屬。原圖可以是自己用文書軟體匯出的 PNG;同一區域保留列標題,避免裁到只剩數字。
- 正確稿:文字、數字、欄位與儲存格關係皆吻合。
- 錯字稿:只改一個繁中字,其餘結構不動。
- 錯金額稿:把
1,240改成1,248,只動一位數。 - 錯欄稿:保留數字,交換兩個欄位的值,測試歸屬錯誤。
每份候選各存一個 UTF-8 檔,表格候選可沿用抽取器產生的 HTML 結構,送 category=table。先目視渲染結果有沒有保留表格;不要為了讓分數變好,把候選修成與正式輸出不同的樣子。官方渲染程式說明它會處理 Markdown、HTML 與 LaTeX。
這四份是找破綻的壓力題,不代表實際錯誤比例。還要收集有權使用的真實 OCR 錯誤,涵蓋字型、掃描、低對比、合併儲存格與不同供稿來源。官方資料準備建議要求保留真實與合成錯誤,並以頁面切分,避免相關區域跨到不同資料集。
實作上先把來源文件分成「開發、校準、保留」三組;同頁四份候選永遠留在同組,同文件多頁也一起分。開發組排錯,校準組挑門檻,保留組最後才打開。按群組切分的工具可協助落實;還要檢查重複掃描與相同版型有沒有洩漏。
四、MiniCPM-OCR Jev 教學:呼叫 API,先讀狀態再讀分數
已把裁圖命名 crop.png、候選存成 candidate.html?下面存成 score_one.py,執行 python3 score_one.py。它使用 Python 標準函式庫,把圖片編成沒有 data: 前綴的 base64,寫出原始回應;格式依Docker API 文件。
import base64, json, math
from pathlib import Path
from urllib.request import Request, urlopen
payload = {
"input_form": "ternary",
"items": [{
"case_id": "doc01-p1-table1-correct",
"category": "table",
"image": base64.b64encode(Path("crop.png").read_bytes()).decode(),
"ocr_text": Path("candidate.html").read_text(encoding="utf-8")
}]
}
Path("request.json").write_text(json.dumps(payload, ensure_ascii=False))
req = Request("http://127.0.0.1:8030/v1/rm/score",
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"})
with urlopen(req, timeout=120) as response:
result = json.load(response)
Path("response.json").write_text(json.dumps(result, ensure_ascii=False, indent=2))
rows = result.get("results", [])
if len(rows) != 1 or rows[0].get("case_id") != payload["items"][0]["case_id"]:
raise RuntimeError("回應無法和輸入對帳")
row = rows[0]
if row.get("verdict") != "scored":
raise RuntimeError("本次未得到有效評分,保留回應並送錯誤佇列")
s = row.get("prob_yes")
if type(s) not in (int, float) or not math.isfinite(s) or not 0 <= s <= 1:
raise RuntimeError("分數格式異常")
print("有效評分:", s)
這段只示範單區域收發;網路逾時、HTTP 錯誤會使程式停止,停止不等於已送入實際複核系統。擴成批次時要加上持久化工作狀態、重試上限與去重,依官方 API 的 case_id逐筆對帳,失敗項另列並保留原始資料。
特別分清三件事:summary.pass_rate是成功完成評分的比例;prob_yes是單筆模型分數;你人工標註後算出的正確率,才是候選在這批任務是否正確。官方回傳的 0.0或 -1.0也可能伴隨失敗狀態,所以判斷順序必須先看 verdict。
若做 best-of-N(同區域多份候選選一份),先逐筆排除失敗,再評估被選結果是否過門檻。文件提醒 score_best在候選全部失敗時會回退到 index 0;只讀 best_text會把這個預設位置誤當有效勝出。選最大分數的整條策略,也要重新在保留集評估。
五、門檻怎麼選?把三種分母寫在紙上
門檻不是先猜 0.9,而是先問「漏放一筆錯金額的代價有多高,能複核多少?」在校準集試不同門檻,每筆用人工稿判定:所有必要儲存格正確才算正確;模糊到人也無法裁定的項目另列待查。
- 錯誤漏放率:放行的錯誤筆數 ÷ 全部已知錯誤筆數。看壞稿漏進去多少。
- 放行後錯誤率:放行的錯誤筆數 ÷ 全部自動放行筆數。看進資料庫的稿有多乾淨。
- 複核比例:需要複核筆數 ÷ 全部輸入筆數。技術失敗與模糊稿也計入工作量,另報各類數量。
紙上算例:假設有 100 個區域,人工判定 20 個有錯。某個門檻放行 70 個,其中 2 個有錯,其餘 30 個送複核。錯誤漏放是 2/20=10%;放行後錯誤是 2/70≈2.86%;複核比例是 30/100=30%。這些是教算式的假設筆數,未替 Jev 填入推論結果。

要把分數讀成機率,再把 scored 項目依分數區間分組,逐組記平均分數、人工正確比例與筆數。高分區若只有幾筆,先擴樣本,別用一條好看的平均線代替資料。合成四件組刻意增加了錯誤,對應真實流量的放行後錯誤率,要另用接近正式分布的樣本估計。
選定門檻後凍結,再開保留集;報告以上比例、原始筆數、金額錯誤與錯欄分組,以及複核分鐘數。若看過保留集又調門檻,下一輪另備新保留集。零漏放只代表這批未觀察到錯誤,仍要看樣本量與比例的信賴區間;相關區域也別當作完全獨立樣本。
六、接入 RAG:先進暫存區,再進可搜尋的索引
RAG(檢索增強生成)是先找資料,再請模型依資料回答。你可以把索引想成圖書館目錄:抄錯的書卡若先上架,問答再流暢也可能引用錯誤。尚不熟悉執行層的人,可先看Agent Harness 白話解說。
先在 staging(暫存區)保存 document_id、page_id、region_id、bbox、crop_hash、candidate_text、category、parser_revision、renderer_id、model_revision、verdict、prob_yes、threshold_version、review_status。bbox 是裁圖座標,記清像素或相對座標;人工改稿另存新版本、複核人與裁定時間。原圖與文字的存取權限一起控管。
# 接線示意,不是可直接執行的資料庫程式
record = save_to_staging(original_crop, candidate, versions)
if verdict != "scored" or not valid_score:
queue_error(record)
elif not policy_applies or hard_checks != "pass":
queue_review(record)
elif score < frozen_threshold:
queue_review(record)
else:
mark_accepted(record)
index_only_accepted_records()
上面省略資料庫交易、佇列實作與權限檢查;正式串接要讓「記錄接受」與「索引工作」可對帳,重試同一版本不重複入庫,修正或撤回時刪掉舊索引。評分服務的欄位依前述官方 API 接入;應用程式的接受狀態由你保存。Harness 實作教學可幫你把狀態與停止條件接齊。
hard checks 是可明確計算的規則,例如欄位齊全、金額格式、同幣別下適用的加總。規則失敗或不確定就送複核,高分不抵銷它。這部分可接著看帳單 OCR 的來源與算術驗收;本篇新增的是外部區域評分與渲染校準這一段。
常見坑:尺換了、分母換了,卻沿用舊結論
- 只換 CJK 字型:保留同一批原圖、候選與模型,對新舊渲染配置重新評分;分開看排序翻轉、門檻跨越與真實錯誤。本文不預測繁中字型會讓分數上升多少。
- 只看總平均:把錯金額、錯欄、漏列與技術失敗分開報;整體漂亮可能掩蓋重要欄位。
- 只挑成功請求:把逾時與 render_error 留在總輸入帳上,另外估算重試和人工成本。
- 把模型選優當修稿:所有候選都錯時,最高分仍可能錯;保留最低接受條件與原圖路徑。
常見問題:八個直接答案
1. Jev 就是另一個 OCR 嗎?
不是同一角色。這篇用它評估已有候選;讀圖產生候選由上游抽取器負責。
2. 0.95 可以當繁中正確率嗎?
先別這樣用。先用自己的標註資料對照分數區間與觀察比例,再決定能否解讀為機率。
3. 官方 AUROC 很高,門檻就選 0.5?
不成立。AUROC 衡量區分正誤的排序能力;接受門檻由你的錯誤成本與資料驗證決定。
4. 繁中一定比簡中分數差嗎?
目前不預設方向。本文查閱的公開資料以中英與區域類型說明,未據此推估繁中金額表格的專屬正確率。請保留字形與錯誤類型分組。
5. 表格當 text 送也行嗎?
要用 table 對應表格。官方指出 category 用錯可能扭曲分數,且未必報錯。
6. Mac 讀者該先做什麼?
先做人工稿、四件候選與分組清單。本篇 Docker 指令選的是 NVIDIA 路徑;其他後端應沿各自官方指南另驗,不把這條指令當通用安裝。
7. 複核後改好的文字可以保留原分數嗎?
要另存版本。原分數屬於原本那組候選與圖;人工修稿與重新評分分開留下紀錄。
8. 第一批全對就能大量自動放行嗎?
先通過獨立保留集與業務門檻,再小批觀察。把新字型、新版型和抽取器升版當成重新驗收的觸發條件。
給新手的三個重點
- 先固定原圖、候選與渲染環境,再比較分數。
- 先分清技術成功、錯誤漏放與放行後品質,再選門檻。
- 先留可追查的暫存紀錄,再把已接受版本送進索引。
接著閱讀
左右滑動查看更多推薦
下一步:先為一張表格留下四份抄本
今天先自製一張繁中表格,存好原圖、正確稿與三種錯稿,把預期裁定寫下來,分數先留白。接通服務後再逐筆填入,親眼看看哪些錯誤穿過你的門檻。回到口訣:可靠入庫=有效評分+自己的門檻驗證+可回看的原圖。想繼續把小練習接成完整系統,可瀏覽AI 專區,或從AlphaLab 課程練習下一個工作流程。






