MinerU开源大模型部署方案国产化信创环境麒麟OS海光CPU适配1. 项目背景与挑战最近在信创项目里我们遇到了一个挺头疼的问题客户需要在国产化的麒麟操作系统和海光CPU服务器上部署一个能看懂文档图片的AI服务。听起来简单但做起来全是坑。客户的需求很明确他们手头有大量的PDF报告、财务报表和扫描件需要AI能自动提取里面的文字、表格甚至回答关于文档内容的问题。市面上虽然有不少文档理解模型但要么对硬件要求太高动不动就要GPU要么在国产化环境里水土不服各种依赖库装不上、跑不起来。我们试了好几个方案要么是模型太大在海光CPU上推理慢得像蜗牛要么是架构太新麒麟系统的老版本glibc库根本不支持。就在我们快要放弃的时候发现了MinerU这个宝藏项目——一个专门为文档场景优化的1.2B小模型号称在CPU上都能跑得飞快。但问题来了官方的部署方案是针对x86架构的我们要怎么把它搬到海光CPU和麒麟OS上呢这就是今天要跟大家分享的实战经验。2. MinerU模型核心优势解析2.1 为什么选择1.2B的小模型你可能要问现在动辄几十B、几百B的大模型满天飞为什么偏偏选个1.2B的“小个子”这里有几个很实际的考虑第一是部署成本。大模型确实能力强但需要GPU才能跑得动而很多信创环境的服务器只有CPU。MinerU-1.2B经过特殊优化在纯CPU环境下处理一张A4文档截图只需要1-2秒这个速度在实际业务中是完全可用的。第二是精准度。MinerU不是通用模型它是专门为“看懂文档”这个任务训练的。就像让一个专门看财务报表的会计去分析报表肯定比让一个什么都会一点但不精通的通才更靠谱。它在处理表格、公式、复杂版面时的准确率比很多通用模型要高。第三是资源占用。1.2B的模型文件只有几百MB内存占用也小很适合在资源受限的国产化服务器上长期运行。2.2 模型到底能做什么简单来说MinerU是个“文档翻译官”它能把图片里的文档内容“读”出来还能“理解”内容。具体能做的包括文字提取把图片里的所有文字按照原来的段落格式提取出来保持原文的结构。表格识别自动识别表格的边框把每个单元格的内容提取出来还能还原行列关系。内容总结你问它“这份报告主要讲了什么”它能用几句话给你概括出来。问答对话你可以指着文档里的某个部分问问题比如“第三季度的营收是多少”它能找到对应数据回答你。版面分析能识别出文档里哪些是标题、哪些是正文、哪些是图表说明。最让我惊喜的是它对中文文档的支持特别好包括那些竖排、繁体、带印章的扫描件都能处理得不错。3. 国产化环境适配实战3.1 环境准备与依赖排查适配国产化环境第一步不是急着装软件而是先搞清楚环境里有什么、缺什么。我们在麒麟OS上遇到了几个典型问题glibc版本冲突很多AI框架需要较新的glibc但麒麟OS为了稳定性用的版本比较老。我们的做法不是升级系统库那会影响其他业务而是找那些对glibc要求不高的替代方案。CPU指令集差异海光CPU兼容x86指令集但有些优化指令可能不支持。我们编译时要去掉那些特定的CPU优化标志。依赖库缺失麒麟OS的软件源可能没有最新的Python包需要手动编译或者找替代品。我们的检查清单是这样的# 1. 检查系统基本信息 uname -a cat /etc/os-release lscpu | grep -i model name # 2. 检查关键库版本 ldd --version python3 --version pip3 --version # 3. 测试网络连通性很多包需要从外网下载 curl -I https://pypi.org3.2 分步部署指南3.2.1 基础环境搭建首先我们需要一个干净的Python环境。这里不建议用系统自带的Python而是用Miniconda创建一个独立环境# 下载Miniconda选择适合麒麟OS的版本 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh # 安装注意安装路径不要有中文和空格 bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3 # 初始化conda /opt/miniconda3/bin/conda init # 创建专门的环境 conda create -n mineru python3.9 -y conda activate mineru3.2.2 依赖包安装与问题解决接下来安装必要的包这里有几个坑要避开# 先升级pip用国内源加速 pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple # 安装基础依赖按顺序安装避免依赖冲突 pip install torch1.13.1 torchvision0.14.1 -i https://pypi.tuna.tsinghua.edu.cn/simple # 如果上面安装失败试试CPU版本 pip install torch1.13.1cpu torchvision0.14.1cpu -f https://download.pytorch.org/whl/torch_stable.html # 安装transformers和MinerU相关包 pip install transformers4.35.0 pip install Pillow opencv-python-headless如果遇到“找不到满足版本的包”错误可以尝试降低版本要求比如torch可以试试1.12.0从源码编译虽然麻烦但最可靠找替代包比如用Pillow-SIMD代替Pillow3.2.3 模型下载与配置MinerU的模型可以从OpenDataLab下载但国内访问可能较慢。我们准备了两种方案方案一直接下载网络好时用from transformers import AutoModel, AutoProcessor model_name OpenDataLab/MinerU2.5-2509-1.2B model AutoModel.from_pretrained(model_name, trust_remote_codeTrue) processor AutoProcessor.from_pretrained(model_name, trust_remote_codeTrue)方案二离线部署网络受限时用如果服务器不能连外网可以找一台能上网的机器先下载好# 在能上网的机器上 python -c from transformers import AutoModel, AutoProcessor import os model_name OpenDataLab/MinerU2.5-2509-1.2B save_path ./mineru_model # 下载模型和处理器 model AutoModel.from_pretrained(model_name, trust_remote_codeTrue) processor AutoProcessor.from_pretrained(model_name, trust_remote_codeTrue) # 保存到本地 model.save_pretrained(save_path) processor.save_pretrained(save_path) print(f模型已保存到 {save_path}) # 打包整个目录 tar -czf mineru_model.tar.gz mineru_model/然后把打包好的文件传到国产化服务器上加载时指定本地路径model AutoModel.from_pretrained(/path/to/mineru_model, trust_remote_codeTrue) processor AutoProcessor.from_pretrained(/path/to/mineru_model, trust_remote_codeTrue)3.3 Web服务集成模型跑起来只是第一步我们还需要一个友好的界面让业务人员能用起来。这里用Flask搭个简单的Web服务from flask import Flask, request, jsonify, render_template from PIL import Image import io import os app Flask(__name__) # 全局加载模型实际生产环境要考虑并发 model None processor None def load_model(): global model, processor if model is None: from transformers import AutoModel, AutoProcessor model_path /path/to/mineru_model # 改成你的实际路径 model AutoModel.from_pretrained(model_path, trust_remote_codeTrue) processor AutoProcessor.from_pretrained(model_path, trust_remote_codeTrue) model.eval() # 设置为评估模式 app.route(/) def index(): 提供上传页面 return !DOCTYPE html html headtitleMinerU文档解析/title/head body h2上传文档图片/h2 form action/analyze methodpost enctypemultipart/form-data input typefile nameimage acceptimage/* requiredbrbr textarea namequestion rows3 cols50 placeholder输入你的问题比如提取文字、总结内容等/textareabrbr input typesubmit value开始解析 /form /body /html app.route(/analyze, methods[POST]) def analyze(): 处理图片解析请求 if image not in request.files: return jsonify({error: 没有上传图片}), 400 load_model() # 确保模型已加载 # 读取图片 image_file request.files[image] image Image.open(io.BytesIO(image_file.read())).convert(RGB) # 获取问题 question request.form.get(question, 请提取图片中的文字) try: # 预处理 inputs processor(imagesimage, textquestion, return_tensorspt) # 推理注意这里简化了实际要处理生成过程 with torch.no_grad(): outputs model.generate(**inputs, max_new_tokens500) # 解码结果 result processor.decode(outputs[0], skip_special_tokensTrue) return jsonify({ success: True, question: question, answer: result }) except Exception as e: return jsonify({error: str(e)}), 500 if __name__ __main__: # 生产环境不要用debug模式 app.run(host0.0.0.0, port5000, debugFalse)这个服务启动后用户打开浏览器就能上传文档图片、输入问题然后看到解析结果。4. 性能优化与生产部署4.1 CPU推理优化技巧在海光CPU上跑模型不优化的话速度可能不太理想。我们试了几个方法效果比较明显1. 使用Intel OneDNN加速海光兼容import os os.environ[OMP_NUM_THREADS] 4 # 根据CPU核心数调整 os.environ[MKL_NUM_THREADS] 4 # 在加载模型前设置 import torch torch.set_num_threads(4) # 限制PyTorch使用的线程数2. 批处理请求如果同时有多个文档要处理不要一个一个来攒一批一起处理def batch_process(images, questions): 批量处理图片 # 预处理所有图片 inputs processor( imagesimages, textquestions, paddingTrue, return_tensorspt ) # 批量推理 with torch.no_grad(): outputs model.generate(**inputs, max_new_tokens500) # 解码所有结果 results [] for i in range(len(outputs)): result processor.decode(outputs[i], skip_special_tokensTrue) results.append(result) return results3. 模型量化把模型从FP32转换成INT8速度能提升不少精度损失很小from transformers import AutoModel, AutoProcessor import torch # 加载模型 model AutoModel.from_pretrained(OpenDataLab/MinerU2.5-2509-1.2B, trust_remote_codeTrue) # 动态量化 quantized_model torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtypetorch.qint8 ) # 保存量化后的模型 torch.save(quantized_model.state_dict(), mineru_quantized.pth)4.2 生产环境部署建议在实际项目里我们是这样部署的1. 使用Docker容器化虽然麒麟OS有自己的容器方案但我们还是用Docker因为生态更成熟。Dockerfile大概长这样FROM kylin:latest # 使用麒麟基础镜像 # 设置国内源 RUN sed -i s/# deb/deb/g /etc/apt/sources.list \ sed -i s|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g /etc/apt/sources.list # 安装基础依赖 RUN apt-get update apt-get install -y \ python3.9 \ python3-pip \ libgl1-mesa-glx \ libglib2.0-0 \ rm -rf /var/lib/apt/lists/* # 复制模型文件提前下载好 COPY mineru_model /app/mineru_model COPY requirements.txt /app/ COPY app.py /app/ # 安装Python包 WORKDIR /app RUN pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 启动服务 EXPOSE 5000 CMD [python3, app.py]2. 添加健康检查在Kubernetes或容器平台里要配置健康检查livenessProbe: httpGet: path: /health port: 5000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /health port: 5000 initialDelaySeconds: 5 periodSeconds: 53. 日志和监控加了详细的日志方便排查问题import logging from datetime import datetime logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(fmineru_{datetime.now().strftime(%Y%m%d)}.log), logging.StreamHandler() ] ) logger logging.getLogger(__name__) # 在关键地方记录日志 app.route(/analyze, methods[POST]) def analyze(): logger.info(f收到解析请求问题: {question[:50]}...) # ... 处理逻辑 logger.info(f解析完成耗时: {time.time() - start_time:.2f}秒)5. 实际应用案例5.1 财务报表解析我们第一个上线的场景是财务报表解析。客户每天要处理几百份PDF格式的财报原来需要人工一页页看现在用MinerU自动提取关键数据。处理流程PDF转成图片一页一张批量上传到MinerU服务问特定问题比如“营业收入是多少”“净利润同比增长多少”把提取的数据自动填到Excel模板里效果对比人工处理每份报表15-20分钟MinerU处理每份报表1-2分钟包括人工核对时间准确率数字提取99%以上文字总结85%左右5.2 合同文档审查另一个用得不错的场景是合同审查。法务部门要检查合同里的关键条款比如付款条件、违约责任这些。我们训练MinerU识别特定的条款类型当用户问“付款条件是什么”时模型会找到合同里关于付款的段落问“违约责任有哪些”时会提取违约相关的条款虽然不是100%准确但能大大减少法务的初筛工作量。5.3 技术文档问答内部技术文档很多新员工来了找不到需要的信息。我们搭了个文档问答系统把所有技术文档的扫描件喂给MinerU员工在系统里提问比如“服务器重启的流程是什么”模型找到相关文档段落并给出答案这样新员工不用在几百个文档里翻来翻去了。6. 遇到的问题与解决方案6.1 内存泄漏问题运行一段时间后服务内存占用越来越高。排查发现是PIL库处理图片时的问题。解决方案# 原来的写法有问题 def process_image(image_bytes): image Image.open(io.BytesIO(image_bytes)) # ... 处理图片 # 这里没有显式关闭可能导致内存泄漏 # 改进后的写法 def process_image(image_bytes): with Image.open(io.BytesIO(image_bytes)) as image: image image.convert(RGB) # ... 处理图片 # with语句结束后自动清理6.2 并发处理瓶颈刚开始部署时多个用户同时上传文档服务就卡住了。因为模型推理是CPU密集型的同时处理多个请求会把CPU占满。解决方案用消息队列比如Redis缓冲请求部署多个服务实例用Nginx做负载均衡限制单个请求的处理时间超时就返回错误from concurrent.futures import ThreadPoolExecutor import threading # 全局线程池限制并发数 executor ThreadPoolExecutor(max_workers2) # 根据CPU核心数调整 model_lock threading.Lock() # 模型推理锁 app.route(/analyze, methods[POST]) def analyze(): # 提交到线程池处理 future executor.submit(process_image_task, image_bytes, question) try: # 设置超时30秒 result future.result(timeout30) return jsonify(result) except TimeoutError: future.cancel() return jsonify({error: 处理超时}), 5046.3 模型准确率优化有些文档质量差比如拍照歪斜、光线暗模型识别准确率下降。解决方案上传前用OpenCV做预处理旋转校正、亮度调整对于表格多的文档先用专门的表格识别模型预处理设置置信度阈值低于阈值的让人工复核import cv2 import numpy as np def preprocess_image(image): 图片预处理 # 转成灰度图 gray cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY) # 二值化让文字更清晰 _, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 矫正倾斜用霍夫变换检测直线 coords np.column_stack(np.where(binary 0)) angle cv2.minAreaRect(coords)[-1] if angle -45: angle 90 angle # 旋转图片 (h, w) binary.shape[:2] center (w // 2, h // 2) M cv2.getRotationMatrix2D(center, angle, 1.0) rotated cv2.warpAffine(binary, M, (w, h)) return Image.fromarray(rotated)7. 总结与建议7.1 项目总结经过几个月的折腾MinerU在麒麟OS海光CPU的环境里总算稳定跑起来了。总结几点经验技术层面小模型在国产化环境里确实有优势部署简单资源要求低纯CPU推理要重视优化量化、批处理这些技巧很管用国产化环境的兼容性问题大部分都能通过“降版本、换方案”解决业务层面不是所有文档都适合用AI处理表格、报告这类结构化文档效果最好要设置合理预期AI是辅助工具不是完全替代人工上线前一定要做充分测试特别是边界情况比如模糊图片、复杂表格7.2 给后来者的建议如果你也要在信创环境部署AI模型我的建议是第一先做可行性验证。别一上来就搞全套先找个最简单的例子在目标环境里跑通确认基础依赖没问题。第二准备降级方案。最新的库很可能装不上要提前找好老版本的替代品。比如PyTorch如果1.13装不上就试试1.12、1.11。第三重视预处理。模型再厉害输入的质量也决定了输出的质量。图片预处理、文本清洗这些工作能大大提升最终效果。第四做好监控。服务上线后要监控CPU、内存、响应时间设好告警阈值。我们遇到过内存泄漏跑了三天把服务器跑挂了就是监控没到位。第五保持更新。开源社区在快速迭代MinerU也在不断更新。定期关注新版本但升级前一定要在测试环境充分验证。国产化这条路不好走坑很多但走通了价值也很大。希望我们的经验能帮你少踩几个坑。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。