# llama.cpp 本地 GGUF 模型配置说明 本文档说明如何在 Mac M4 Pro 上使用 llama-server 加载本地 GGUF 模型进行 OCR 识别。 ## 目录 - [模型文件](#模型文件) - [可用模型](#可用模型) - [守护脚本](#守护脚本) - [参数配置](#参数配置) - [使用方法](#使用方法) - [常见问题](#常见问题) --- ## 模型文件 模型文件位于 `~/Library/Caches/llama.cpp/` 目录: ```bash [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、表格识别 | **模型下载地址:** - GLM-OCR: https://huggingface.co/ggml-org/GLM-OCR-GGUF - PaddleOCR-VL: https://huggingface.co/PaddlePaddle/PaddleOCR-VL-1.5-GGUF --- ## 守护脚本 我们提供两个独立的守护脚本来管理 llama-server 服务: ### 1. GLM-OCR 守护脚本 **位置:** `ocr_tools/daemons/glmocr_local_daemon.sh` **配置:** - 端口:8080 - 日志:`~/workspace/logs/glmocr_llamaserver.log` - PID:`~/workspace/logs/glmocr_llamaserver.pid` **配置:** - 端口:8080 - 日志:`~/workspace/logs/glmocr_llamaserver.log` - PID:`~/workspace/logs/glmocr_llamaserver.pid` **llama-server 启动命令:** ```bash 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 ``` ### 2. PaddleOCR-VL 守护脚本 **位置:** `ocr_tools/daemons/paddleocr_local_daemon.sh` **配置:** - 端口:8081 - 日志:`~/workspace/logs/paddleocr_llamaserver.log` - PID:`~/workspace/logs/paddleocr_llamaserver.pid` **llama-server 启动命令:** ```bash 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)和独立的日志文件,因此可以同时启动用于对比测试。 --- ## 参数配置 ### llama-server 参数详解 | 参数 | 值 | 说明 | |------|-----|------| | `-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 与 max_tokens 的关系 **关键概念:** 1. **CONTEXT_SIZE (`-c 16384`)** - llama-server 的上下文窗口 - 模型一次能处理的**总 token 数量** - 包括:输入 prompt tokens + 输出 tokens + 图像 tokens 2. **max_tokens (16384)** - OpenAI API 的生成参数 - 模型**输出**的最大 token 数量 - 在配置文件 `model_params.max_tokens` 中设置 **重要规则:** ``` max_tokens <= CONTEXT_SIZE ``` **实际使用场景:** ``` 总上下文 (16384) = 图像 tokens (~500-2000) + Prompt tokens (~10) + 生成输出 tokens (最多 16384) ``` **为什么设置为 16384:** - ✅ 满足复杂表格识别需求(可能输出数千 tokens) - ✅ M4 Pro 48GB 内存充足(Q8_0 模型 ~1GB + 16K KV cache ~2-4GB) - ✅ Metal GPU 加速,性能良好 - ✅ 与配置文件的 max_tokens 参数对齐 **性能调整建议:** - **8192**:平衡性能与长度(适合一般文档) - **16384**:处理复杂大表格(当前推荐设置) - **32768**:极限场景(需要更多内存,性能下降) --- ## 使用方法 ### 前置要求 1. **安装 llama.cpp:** ```bash brew install llama.cpp ``` 2. **确认 conda 环境:** ```bash conda activate mineru2 ``` 3. **验证模型文件:** ```bash ls -lh ~/Library/Caches/llama.cpp/ ``` ### 启动服务 #### 启动 GLM-OCR 服务 ```bash 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-VL 服务 ```bash # 查看配置 ./paddleocr_local_daemon.sh config # 启动服务 ./paddleocr_local_daemon.sh start # 查看状态 ./paddleocr_local_daemon.sh status # 测试 API ./paddleocr_local_daemon.sh test ``` #### 同时启动两个服务(对比测试) ```bash # 两个服务使用不同端口,可以同时运行 ./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` | 显示集成测试示例 | ### API 访问方式 #### GLM-OCR API (端口 8080) ```bash # 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 ``` #### PaddleOCR-VL API (端口 8081) ```bash # 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 ``` ### 配置文件集成 #### GLM-OCR 配置文件 `config/bank_statement_yusys_local.yaml`: ```yaml vl_recognition: module: "glmocr" api_url: "http://localhost:8080/v1/chat/completions" model: "glm-ocr" model_params: max_tokens: 16384 temperature: 0.1 ``` #### PaddleOCR-VL 配置文件 `config/bank_statement_paddleocr_local.yaml`: ```yaml vl_recognition: module: "paddleocr" api_url: "http://localhost:8081/v1/chat/completions" model: "paddleocr-vl" model_params: max_tokens: 16384 temperature: 0.1 ``` #### 使用配置文件处理文档 ```bash 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 ``` --- ## 常见问题 --- ## 常见问题 ### Q1: llama-server 文件访问错误 **问题描述:** ``` Error: file does not exist: file:///Users/... ``` **原因:** llama-server 的文件访问模型是 **基准目录 + 相对路径**,而非文件系统绝对路径。 **解决方法:** 1. 使用 `--media-path` 设置基准目录 2. 图片路径使用**相对路径**:`file://test.png` 而非 `file:///Users/zhch158/workspace/test.png` **示例:** ```bash # 正确配置 --media-path /Users/zhch158/workspace # API 调用时使用 "image_url": {"url": "file://test.png"} # 相对于 media-path # 错误配置 "image_url": {"url": "file:///Users/zhch158/workspace/test.png"} # ❌ 绝对路径不工作 ``` ### Q2: 服务启动但 API 无响应 **排查步骤:** 1. **检查服务状态:** ```bash ./glmocr_local_daemon.sh status ``` 2. **检查端口监听:** ```bash lsof -i :8080 # GLM-OCR lsof -i :8081 # PaddleOCR-VL ``` 3. **查看日志:** ```bash ./glmocr_local_daemon.sh logs ``` 4. **测试 API:** ```bash curl http://localhost:8080/v1/models ``` **常见原因:** - 服务正在启动中(模型加载需要几秒到几十秒) - 端口被占用 - llama-server 版本过旧(需要支持 `--media-path` 参数) ### Q3: 两个模型如何选择? | 场景 | 推荐模型 | 理由 | |------|---------|------| | 中文为主的文档/表格 | PaddleOCR-VL | 中文识别准确率更高 | | 英文为主的文档 | GLM-OCR | 通用性好,速度快 | | 复杂图表识别 | GLM-OCR | 图表理解能力强 | | 需要对比测试 | 同时启动两个 | 使用不同端口并行测试 | **建议:** - 首次使用:同时启动两个服务,使用相同测试数据对比效果 - 确定效果后:选择一个模型日常使用,节省内存 ### Q4: 内存占用过高怎么办? **当前配置占用(单个服务):** - 模型加载:~1GB (Q8_0 量化) - KV cache:~2-4GB (16K 上下文) - 总计:~3-5GB **优化方案:** 1. **减少 CONTEXT_SIZE:** ```bash CONTEXT_SIZE="8192" # 从 16384 降至 8192 ``` 2. **只运行一个服务:** ```bash # 停止不常用的服务 ./paddleocr_local_daemon.sh stop ``` 3. **调整 batch_size:** ```bash BATCH_SIZE="256" # 从 512 降至 256 UBATCH_SIZE="64" # 从 128 降至 64 ``` ### Q5: 如何查看性能指标? **方法 1:查看日志中的性能数据** ```bash 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 命令** ```bash ./glmocr_local_daemon.sh status ``` 显示内容包括: - PID 和运行状态 - 端口监听状态 - 内存使用量 - 最近日志 ### Q6: 如何更新模型? **下载新模型:** ```bash # 模型会自动下载到 ~/Library/Caches/llama.cpp/ # 如果需要手动下载,可以从 HuggingFace 下载并放置到该目录 ``` **更新脚本中的路径:** ```bash # 编辑守护脚本 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" ``` **重启服务:** ```bash ./glmocr_local_daemon.sh restart ``` ### Q7: 文件路径包含中文字符无法识别 **问题:** 路径包含中文时,llama-server 可能无法正确解析。 **解决方法:** 1. 将测试图片移动到不含中文的路径 2. 确保 `--media-path` 路径不包含中文 3. 使用英文文件名 **示例:** ```bash # 推荐 --media-path /Users/zhch158/workspace file://test_image.png # 避免 --media-path /Users/zhch158/工作空间 file://测试图片.png ``` ### Q8: Metal GPU 加速未生效 **检查方法:** ```bash ./glmocr_local_daemon.sh logs ``` **正常输出应包含:** ``` ggml_metal_init: found device: Apple M4 Pro ggml_metal_init: GPU enabled ``` **如果未启用:** 1. 检查 llama.cpp 是否支持 Metal(`llama-server --version`) 2. 确认 `-ngl 99` 参数存在于启动命令 3. 重新安装 llama.cpp:`brew reinstall llama.cpp` --- ## 性能参考数据 ### Mac M4 Pro 48GB 测试结果 **测试场景:** 银行流水表格识别(24 行记录) | 模型 | Prompt 速度 | 生成速度 | 总耗时 | 输出 Tokens | |------|-----------|---------|--------|-----------| | GLM-OCR Q8_0 | 387 tokens/s | 178 tokens/s | ~30s | 3412 | | PaddleOCR-VL-1.5 | (待测试) | (待测试) | (待测试) | (待测试) | **配置参数:** - CONTEXT_SIZE: 16384 - GPU_LAYERS: 99 (Metal) - THREADS: 8 - Temperature: 0 --- ## 相关文档 - [守护脚本 README](../../../ocr_tools/daemons/README.md) - 详细的守护脚本使用说明 - [universal_doc_parser 配置指南](../../../ocr_tools/universal_doc_parser/README.md) - [debug 参数控制](./debug参数控制.md) - [GLM-OCR 官方文档](https://github.com/GLM-OCR/GLM-OCR) - [PaddleOCR-VL 官方文档](https://github.com/PaddlePaddle/PaddleOCR) - [llama.cpp 文档](https://github.com/ggerganov/llama.cpp) --- ## 总结 ### 关键要点 1. **两个独立脚本** - GLM-OCR (8080) 和 PaddleOCR-VL (8081) 可同时运行 2. **CONTEXT_SIZE 必须 >= max_tokens** - 当前都设置为 16384 3. **文件路径使用相对路径** - 相对于 `--media-path` 设置的基准目录 4. **Metal GPU 加速** - Mac M4 Pro 使用 `-ngl 99` 全层加速 5. **确定性输出** - `--temp 0` 确保 OCR 结果一致性 6. **OpenAI 兼容 API** - 完全兼容 OpenAI vision API 格式 ### 快速开始命令 ```bash # 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 ``` ### 下一步 - [ ] 启动服务并测试 API - [ ] 对比两个模型的识别效果 - [ ] 根据实际需求调整参数(CONTEXT_SIZE、threads 等) - [ ] 将性能更好的模型集成到生产 pipeline --- **文档更新日期:** 2026年3月15日