本文档说明如何在 Mac M4 Pro 上使用 llama-server 加载本地 GGUF 模型进行 OCR 识别。
模型文件位于 ~/Library/Caches/llama.cpp/ 目录:
[192.168.1.27:~/Library/Caches/llama.cpp]$ ll
total 6374440
# GLM-OCR 模型
-rw-r--r--@ 1 zhch158 staff 1399 Mar 14 22:51 manifest=ggml-org=GLM-OCR-GGUF=latest.json
-rw-r--r--@ 1 zhch158 staff 950433408 Mar 14 22:53 ggml-org_GLM-OCR-GGUF_GLM-OCR-Q8_0.gguf # 主模型 950MB
-rw-r--r--@ 1 zhch158 staff 66 Mar 14 22:53 ggml-org_GLM-OCR-GGUF_GLM-OCR-Q8_0.gguf.etag
-rw-r--r--@ 1 zhch158 staff 484403648 Mar 14 22:54 ggml-org_GLM-OCR-GGUF_mmproj-GLM-OCR-Q8_0.gguf # 投影器 484MB
-rw-r--r--@ 1 zhch158 staff 66 Mar 14 22:54 ggml-org_GLM-OCR-GGUF_mmproj-GLM-OCR-Q8_0.gguf.etag
# PaddleOCR-VL 模型
-rw-r--r--@ 1 zhch158 staff 1407 Mar 15 16:04 manifest=PaddlePaddle=PaddleOCR-VL-1.5-GGUF=latest.json
-rw-r--r--@ 1 zhch158 staff 935768992 Mar 15 16:05 PaddlePaddle_PaddleOCR-VL-1.5-GGUF_PaddleOCR-VL-1.5.gguf # 主模型 936MB
-rw-r--r--@ 1 zhch158 staff 66 Mar 15 16:05 PaddlePaddle_PaddleOCR-VL-1.5-GGUF_PaddleOCR-VL-1.5.gguf.etag
-rw-r--r--@ 1 zhch158 staff 881770496 Mar 15 16:06 PaddlePaddle_PaddleOCR-VL-1.5-GGUF_PaddleOCR-VL-1.5-mmproj.gguf # 投影器 882MB
-rw-r--r--@ 1 zhch158 staff 66 Mar 15 16:06 PaddlePaddle_PaddleOCR-VL-1.5-GGUF_PaddleOCR-VL-1.5-mmproj.gguf.etag
我们提供两个 OCR 视觉语言模型的本地部署方案:
| 模型 | 主模型大小 | 投影器大小 | 守护脚本 | 端口 | 适用场景 |
|---|---|---|---|---|---|
| GLM-OCR Q8_0 | 950MB | 484MB | glmocr_local_daemon.sh |
8080 | 通用 OCR、英文、图表识别 |
| PaddleOCR-VL-1.5 | 936MB | 882MB | paddleocr_local_daemon.sh |
8081 | 中文 OCR、表格识别 |
模型下载地址:
我们提供两个独立的守护脚本来管理 llama-server 服务:
位置: ocr_tools/daemons/glmocr_local_daemon.sh
配置:
~/workspace/logs/glmocr_llamaserver.log~/workspace/logs/glmocr_llamaserver.pid配置:
~/workspace/logs/glmocr_llamaserver.log~/workspace/logs/glmocr_llamaserver.pidllama-server 启动命令:
llama-server \
-m ~/Library/Caches/llama.cpp/ggml-org_GLM-OCR-GGUF_GLM-OCR-Q8_0.gguf \
--mmproj ~/Library/Caches/llama.cpp/ggml-org_GLM-OCR-GGUF_mmproj-GLM-OCR-Q8_0.gguf \
--host 0.0.0.0 \
--port 8080 \
--media-path /Users/zhch158/workspace \
-c 16384 \
-ngl 99 \
-t 8 \
-b 512 \
-ub 128 \
--temp 0
位置: ocr_tools/daemons/paddleocr_local_daemon.sh
配置:
~/workspace/logs/paddleocr_llamaserver.log~/workspace/logs/paddleocr_llamaserver.pidllama-server 启动命令:
llama-server \
-m ~/Library/Caches/llama.cpp/PaddlePaddle_PaddleOCR-VL-1.5-GGUF_PaddleOCR-VL-1.5.gguf \
--mmproj ~/Library/Caches/llama.cpp/PaddlePaddle_PaddleOCR-VL-1.5-GGUF_PaddleOCR-VL-1.5-mmproj.gguf \
--host 0.0.0.0 \
--port 8081 \
--media-path /Users/zhch158/workspace \
-c 16384 \
-ngl 99 \
-t 8 \
-b 512 \
-ub 128 \
--temp 0
两个脚本使用不同的端口(8080 vs 8081)和独立的日志文件,因此可以同时启动用于对比测试。
| 参数 | 值 | 说明 |
|---|---|---|
-m |
模型路径 | 主 GGUF 模型文件(Q8_0 量化) |
--mmproj |
投影器路径 | 多模态投影器(用于处理图像) |
--host |
0.0.0.0 |
服务监听地址(允许外部访问) |
--port |
8080/8081 |
服务端口 |
--media-path |
/Users/zhch158/workspace |
图片基准目录(使用相对路径访问) |
-c |
16384 |
CONTEXT_SIZE - 上下文窗口大小 |
-ngl |
99 |
Metal GPU 层数(99 = 全部加速) |
-t |
8 |
CPU 线程数(M4 Pro 推荐值) |
-b |
512 |
批处理大小 |
-ub |
128 |
微批处理大小 |
--temp |
0 |
温度参数(0 = 确定性输出) |
关键概念:
CONTEXT_SIZE (-c 16384) - llama-server 的上下文窗口
max_tokens (16384) - OpenAI API 的生成参数
model_params.max_tokens 中设置重要规则:
max_tokens <= CONTEXT_SIZE
实际使用场景:
总上下文 (16384) = 图像 tokens (~500-2000)
+ Prompt tokens (~10)
+ 生成输出 tokens (最多 16384)
为什么设置为 16384:
性能调整建议:
安装 llama.cpp:
brew install llama.cpp
确认 conda 环境:
conda activate mineru2
验证模型文件:
ls -lh ~/Library/Caches/llama.cpp/
cd /Users/zhch158/workspace/repository.git/ocr_platform/ocr_tools/daemons
# 查看配置
./glmocr_local_daemon.sh config
# 启动服务
./glmocr_local_daemon.sh start
# 查看状态
./glmocr_local_daemon.sh status
# 测试 API
./glmocr_local_daemon.sh test
# 查看配置
./paddleocr_local_daemon.sh config
# 启动服务
./paddleocr_local_daemon.sh start
# 查看状态
./paddleocr_local_daemon.sh status
# 测试 API
./paddleocr_local_daemon.sh test
# 两个服务使用不同端口,可以同时运行
./glmocr_local_daemon.sh start # 端口 8080
./paddleocr_local_daemon.sh start # 端口 8081
# 检查状态
./glmocr_local_daemon.sh status
./paddleocr_local_daemon.sh status
所有脚本支持以下命令:
| 命令 | 说明 |
|---|---|
start |
启动服务 |
stop |
停止服务 |
restart |
重启服务 |
status |
显示服务状态(PID、端口、内存、最近日志) |
logs |
实时查看日志(tail -f) |
config |
显示当前配置和系统信息 |
test |
测试 /v1/models API 端点 |
test-client |
显示集成测试示例 |
# OpenAI 兼容端点
curl -X POST http://localhost:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "glm-ocr",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Table Recognition:"},
{"type": "image_url", "image_url": {"url": "file://test.png"}}
]
}],
"max_tokens": 16384
}'
# Models 端点
curl http://localhost:8080/v1/models
# OpenAI 兼容端点
curl -X POST http://localhost:8081/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{
"model": "paddleocr-vl",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Table Recognition:"},
{"type": "image_url", "image_url": {"url": "file://test.png"}}
]
}],
"max_tokens": 16384
}'
# Models 端点
curl http://localhost:8081/v1/models
config/bank_statement_yusys_local.yaml:
vl_recognition:
module: "glmocr"
api_url: "http://localhost:8080/v1/chat/completions"
model: "glm-ocr"
model_params:
max_tokens: 16384
temperature: 0.1
config/bank_statement_paddleocr_local.yaml:
vl_recognition:
module: "paddleocr"
api_url: "http://localhost:8081/v1/chat/completions"
model: "paddleocr-vl"
model_params:
max_tokens: 16384
temperature: 0.1
cd /Users/zhch158/workspace/repository.git/ocr_platform/ocr_tools/universal_doc_parser
# 使用 GLM-OCR
python parse.py --input document.pdf \
--config config/bank_statement_yusys_local.yaml --debug
# 使用 PaddleOCR-VL
python parse.py --input document.pdf \
--config config/bank_statement_paddleocr_local.yaml --debug
问题描述:
Error: file does not exist: file:///Users/...
原因: llama-server 的文件访问模型是 基准目录 + 相对路径,而非文件系统绝对路径。
解决方法:
--media-path 设置基准目录file://test.png 而非 file:///Users/zhch158/workspace/test.png示例:
# 正确配置
--media-path /Users/zhch158/workspace
# API 调用时使用
"image_url": {"url": "file://test.png"} # 相对于 media-path
# 错误配置
"image_url": {"url": "file:///Users/zhch158/workspace/test.png"} # ❌ 绝对路径不工作
排查步骤:
检查服务状态:
./glmocr_local_daemon.sh status
检查端口监听:
lsof -i :8080 # GLM-OCR
lsof -i :8081 # PaddleOCR-VL
查看日志:
./glmocr_local_daemon.sh logs
测试 API:
curl http://localhost:8080/v1/models
常见原因:
--media-path 参数)| 场景 | 推荐模型 | 理由 |
|---|---|---|
| 中文为主的文档/表格 | PaddleOCR-VL | 中文识别准确率更高 |
| 英文为主的文档 | GLM-OCR | 通用性好,速度快 |
| 复杂图表识别 | GLM-OCR | 图表理解能力强 |
| 需要对比测试 | 同时启动两个 | 使用不同端口并行测试 |
建议:
当前配置占用(单个服务):
优化方案:
减少 CONTEXT_SIZE:
CONTEXT_SIZE="8192" # 从 16384 降至 8192
只运行一个服务:
# 停止不常用的服务
./paddleocr_local_daemon.sh stop
调整 batch_size:
BATCH_SIZE="256" # 从 512 降至 256
UBATCH_SIZE="64" # 从 128 降至 64
方法 1:查看日志中的性能数据
tail -20 ~/workspace/logs/glmocr_llamaserver.log
日志输出示例:
prompt eval time = 10448.11 ms / 2701 tokens ( 3.87 ms per token, 387 tokens/s)
generate eval time = 19105.23 ms / 3412 tokens ( 5.60 ms per token, 178 tokens/s)
total time = 29614.40 ms
方法 2:使用 status 命令
./glmocr_local_daemon.sh status
显示内容包括:
下载新模型:
# 模型会自动下载到 ~/Library/Caches/llama.cpp/
# 如果需要手动下载,可以从 HuggingFace 下载并放置到该目录
更新脚本中的路径:
# 编辑守护脚本
vim /Users/zhch158/workspace/repository.git/ocr_platform/ocr_tools/daemons/glmocr_local_daemon.sh
# 修改模型路径
MODEL_PATH="$HOME/Library/Caches/llama.cpp/新模型文件名.gguf"
MMPROJ_PATH="$HOME/Library/Caches/llama.cpp/新投影器文件名.gguf"
重启服务:
./glmocr_local_daemon.sh restart
问题: 路径包含中文时,llama-server 可能无法正确解析。
解决方法:
--media-path 路径不包含中文示例:
# 推荐
--media-path /Users/zhch158/workspace
file://test_image.png
# 避免
--media-path /Users/zhch158/工作空间
file://测试图片.png
检查方法:
./glmocr_local_daemon.sh logs
正常输出应包含:
ggml_metal_init: found device: Apple M4 Pro
ggml_metal_init: GPU enabled
如果未启用:
llama-server --version)-ngl 99 参数存在于启动命令brew reinstall llama.cpp测试场景: 银行流水表格识别(24 行记录)
| 模型 | Prompt 速度 | 生成速度 | 总耗时 | 输出 Tokens |
|---|---|---|---|---|
| GLM-OCR Q8_0 | 387 tokens/s | 178 tokens/s | ~30s | 3412 |
| PaddleOCR-VL-1.5 | (待测试) | (待测试) | (待测试) | (待测试) |
配置参数:
--media-path 设置的基准目录-ngl 99 全层加速--temp 0 确保 OCR 结果一致性# 1. 进入守护脚本目录
cd /Users/zhch158/workspace/repository.git/ocr_platform/ocr_tools/daemons
# 2. 启动服务(选择一个或同时启动)
./glmocr_local_daemon.sh start
./paddleocr_local_daemon.sh start
# 3. 查看状态
./glmocr_local_daemon.sh status
# 4. 使用 OCR pipeline 处理文档
cd ../universal_doc_parser
python parse.py --input document.pdf --config config/bank_statement_yusys_local.yaml --debug
文档更新日期: 2026年3月15日