news 2026/4/22 23:29:49

基于DeepSeek-OCR-WEBUI实现OpenAI兼容的本地OCR服务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于DeepSeek-OCR-WEBUI实现OpenAI兼容的本地OCR服务

基于DeepSeek-OCR-WEBUI实现OpenAI兼容的本地OCR服务

1. 背景与目标

在文档数字化、自动化处理日益普及的今天,光学字符识别(OCR)技术已成为企业流程提效的关键环节。然而,许多商业OCR服务存在数据隐私风险、调用成本高、中文识别精度不足等问题。为此,DeepSeek-OCR-WEBUI提供了一种高性能、可本地部署的开源解决方案。

本文将详细介绍如何基于DeepSeek-OCR-WEBUI镜像,构建一个完全兼容 OpenAI API 协议的本地 OCR 服务。该方案具备以下核心价值:

  • ✅ 支持/v1/chat/completions接口,无缝对接现有 LLM 应用
  • ✅ 内置轻量 WebUI,支持图片上传与 Markdown 实时预览
  • ✅ 支持 Base64、本地路径、HTTP URL 多种图像输入方式
  • ✅ 可运行于单张消费级显卡(如 4090D),适合边缘部署

最终实现效果:用户可通过网页上传票据、文档截图等图像,系统自动提取文本并按 Markdown 格式还原排版,适用于知识库构建、合同解析、教育资料数字化等场景。


2. 技术架构与工作流程

2.1 系统整体架构

本方案采用前后端分离设计,整体架构如下:

+------------------+ +---------------------+ | Web Browser | <---> | FastAPI Backend | | (static/ui.html) | | - OpenAI 兼容接口 | +------------------+ | - 图像预处理 | | - DeepSeek-OCR 推理 | +----------+----------+ | +-------v--------+ | DeepSeek-OCR 模型 | | (transformers) | +------------------+
  • 前端:单文件ui.html,通过 FileReader 将图片转为 Data URI 发送至后端
  • 后端:FastAPI 实现/v1/chat/completions接口,兼容 OpenAI 客户端调用
  • 模型层:加载deepseek-ai/DeepSeek-OCR模型,使用trust_remote_code=True启用自定义推理逻辑

2.2 核心工作流程

  1. 用户在 WebUI 中选择图像文件
  2. 前端读取文件并转换为data:image/png;base64,...格式的 Data URI
  3. 构造符合 OpenAI 协议的消息体:
    { "model": "deepseek-ocr", "messages": [ { "role": "user", "content": [ {"type": "text", "text": "请以Markdown格式输出内容"}, {"type": "image_url", "image_url": {"url": "data:image..."}} ] } ] }
  4. 后端接收到请求后:
    • 解析消息中的图像 URL
    • 自动判断是 Data URI、本地路径还是远程 HTTP 链接
    • 下载或解码为临时文件
    • 调用model.infer()执行 OCR
  5. 返回结构化文本结果(支持纯文本、Markdown、JSON 等格式)
  6. 前端渲染原始文本及 Markdown 预览

3. 环境准备与项目结构

3.1 环境依赖

建议使用 Conda 创建独立环境:

conda create -n deepseekocr python=3.12.9 conda activate deepseekocr pip install torch==2.6.0 transformers==4.46.3 tokenizers==0.20.3 \ einops addict easydict python-multipart uvicorn fastapi \ Pillow torchvision requests

⚠️ 注意:若使用 A100 或支持 Flash Attention 的 GPU,可安装flash-attn进一步提升性能。

3.2 项目目录结构

推荐组织方式如下:

project/ ├── app.py # FastAPI 主服务 ├── static/ │ └── ui.html # 前端交互页面 └── README.md

所有代码和静态资源保持极简,便于部署和维护。


4. 后端服务实现详解

4.1 模型加载与设备适配

MODEL_NAME = os.getenv("DEEPSEEK_OCR_PATH", "/home/qwt/models/DeepSeek-OCR") tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True) model = AutoModel.from_pretrained(MODEL_NAME, trust_remote_code=True, use_safetensors=True) # 设备与精度自动适配 if torch.cuda.is_available(): device = torch.device("cuda:0") model = model.eval().to(device) try: model = model.to(torch.bfloat16) except Exception: try: model = model.to(torch.float16) except Exception: model = model.to(torch.float32) else: device = torch.device("cpu") model = model.eval().to(device)

该段代码实现了:

  • 自动检测 CUDA 支持
  • 优先使用 BF16 提升推理速度
  • 若不支持则降级到 FP16 或 FP32
  • CPU 回退机制保障最低可用性

4.2 多源图像输入统一处理

系统支持三种图像输入方式,并通过_download_to_temp统一处理为本地临时文件:

输入类型示例处理方式
Data URIdata:image/png;base64,...Base64 解码保存
本地路径/path/to/img.pngfile:///...复制为临时文件
HTTP(S)https://example.com/img.jpg下载至临时目录

关键函数逻辑如下:

def _download_to_temp(url: str) -> str: if _is_data_uri(url): header, b64 = url.split(",", 1) ext = ".png" if "image/png" in header else ".jpg" raw = base64.b64decode(b64) return _save_bytes_to_temp(raw, suffix=ext) elif _is_local_like(url): p = _to_local_path(url) with open(p, "rb") as f: data = f.read() ext = os.path.splitext(p)[1] or ".img" return _save_bytes_to_temp(data, suffix=ext) else: resp = requests.get(url, timeout=30) resp.raise_for_status() ctype = resp.headers.get("Content-Type", "") ext = mimetypes.guess_extension(ctype) or ".img" return _save_bytes_to_temp(resp.content, suffix=ext)

此设计确保了接口的灵活性和兼容性,开发者无需关心图像来源。

4.3 OpenAI 兼容接口实现

健康检查与模型列表
@app.get("/health") async def health_check(): return {"status": "healthy"} @app.get("/v1/models") async def list_models(): return { "object": "list", "data": [{"id": "deepseek-ocr", "object": "model", "created": int(time.time()), "owned_by": "owner"}], }
核心推理接口/v1/chat/completions
@app.post("/v1/chat/completions") async def chat_completions(request: Request): payload = await request.json() messages = payload.get("messages") if not isinstance(messages, list) or not messages: raise HTTPException(status_code=400, detail="`messages` must be a non-empty list") prompt_text, image_path = _extract_text_and_first_image_from_messages(messages) if not image_path: raise HTTPException(status_code=400, detail="No image found in messages.") try: answer = _run_ocr_infer(prompt_text, image_path) finally: if image_path and os.path.exists(image_path): try: os.unlink(image_path) # 自动清理临时文件 except Exception: pass prompt_tokens = _token_count_approx(prompt_text) completion_tokens = _token_count_approx(answer) return JSONResponse({ "id": f"chatcmpl_{uuid.uuid4().hex[:24]}", "object": "chat.completion", "created": int(time.time()), "model": "deepseek-ocr", "choices": [{ "index": 0, "message": {"role": "assistant", "content": answer}, "finish_reason": "stop" }], "usage": { "prompt_tokens": prompt_tokens, "completion_tokens": completion_tokens, "total_tokens": prompt_tokens + completion_tokens }, })

响应格式完全遵循 OpenAI 规范,便于集成到 LangChain、LlamaIndex 等框架中。


5. 前端交互与用户体验优化

5.1 WebUI 功能特性

static/ui.html是一个零依赖的单页应用,主要功能包括:

  • 🖼️ 图片预览:上传后即时显示缩略图
  • 🧩 预设模板:提供 Markdown / 纯文本 / JSON 三种输出模式
  • 💬 自定义提示:允许追加指令(如“公式用 $...$ 包裹”)
  • ⏱️ 请求耗时统计:显示识别所用时间
  • 📝 Markdown 实时预览:内置marked.js渲染富文本

5.2 关键前端逻辑

function fileToDataURI(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onerror = () => reject(new Error('读取文件失败')); reader.onload = () => resolve(reader.result); reader.readAsDataURL(file); }); } runBtn.addEventListener('click', async () => { const f = fileEl.files[0]; const dataUri = await fileToDataURI(f); const preset = presetText(presetEl.value); const custom = promptEl.value.trim(); const textMsg = custom ? (preset + "\n\n" + custom) : preset; const body = { model: "deepseek-ocr", messages: [ { role: "user", content: [ { type: "text", text: textMsg }, { type: "image_url", image_url: { url: dataUri } } ] } ] }; const resp = await fetch('/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); const json = await resp.json(); rawEl.textContent = json.choices[0].message.content; if (window.marked) { mdEl.innerHTML = marked.parse(json.choices[0].message.content); } });

该实现保证了良好的用户体验,即使在网络延迟较高时也能清晰反馈状态。


6. 实际调用示例与集成方法

6.1 使用 OpenAI SDK 调用

得益于协议兼容性,可直接使用官方客户端:

from openai import OpenAI client = OpenAI(base_url="http://127.0.0.1:8001/v1", api_key="sk-x") resp = client.chat.completions.create( model="deepseek-ocr", messages=[ { "role": "user", "content": [ {"type": "text", "text": "请以Markdown格式返回内容"}, {"type": "image_url", "image_url": {"url": "/path/to/document.png"}} ] } ] ) print(resp.choices[0].message.content)

🔐 注意:api_key可任意填写(如"sk-x"),因本地服务未启用鉴权。

6.2 cURL 调用示例

curl http://127.0.0.1:8001/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-ocr", "messages": [ { "role": "user", "content": [ {"type": "text", "text": "提取文字内容"}, {"type": "image_url", "image_url": {"url": "https://example.com/invoice.png"}} ] } ] }'

7. 总结

本文详细介绍了如何基于DeepSeek-OCR-WEBUI镜像搭建一个功能完整、协议兼容的本地 OCR 服务。该方案具有以下优势:

  1. 协议兼容性强:完全支持 OpenAI/v1/chat/completions接口,易于集成现有 AI 工作流。
  2. 部署简单高效:仅需 Python 环境与一张 GPU 显卡即可运行,适合企业私有化部署。
  3. 输入方式灵活:支持 Data URI、本地路径、HTTP 链接等多种图像输入方式。
  4. 输出格式丰富:可通过提示词控制输出为 Markdown、纯文本或结构化 JSON。
  5. 前端体验良好:内置 WebUI 支持拖拽上传、实时预览,降低使用门槛。

该服务已在金融票据识别、教育资料数字化等多个实际场景中验证其稳定性和准确性,尤其在中文复杂版式文档识别方面表现优异。

未来可进一步扩展方向包括:

  • 添加多图像批量处理能力
  • 支持 PDF 文件直接上传解析
  • 引入缓存机制提升重复图像识别效率
  • 增加 API 访问鉴权与限流功能

通过本方案,开发者可以快速构建安全、可控、高性能的本地 OCR 能力,助力各类文档自动化项目的落地实施。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 19:10:48

如何用PaddleOCR-VL-WEB实现SOTA级表格与公式识别?

如何用PaddleOCR-VL-WEB实现SOTA级表格与公式识别&#xff1f; 1. 引言&#xff1a;文档解析进入端到端新时代 在数字化转型加速的背景下&#xff0c;企业对文档智能处理的需求日益增长。传统OCR技术通常依赖多阶段流水线——先检测文本区域&#xff0c;再分别识别文字、表格…

作者头像 李华
网站建设 2026/4/17 20:23:47

PingFangSC字体包仿写文章创作Prompt

PingFangSC字体包仿写文章创作Prompt 【免费下载链接】PingFangSC PingFangSC字体包文件、苹果平方字体文件&#xff0c;包含ttf和woff2格式 项目地址: https://gitcode.com/gh_mirrors/pi/PingFangSC 创作目标 创作一篇关于PingFangSC字体包的专业技术文章&#xff0c…

作者头像 李华
网站建设 2026/4/15 15:44:43

Tunnelto:一键将本地服务转换为全球可访问的公共链接

Tunnelto&#xff1a;一键将本地服务转换为全球可访问的公共链接 【免费下载链接】tunnelto Expose your local web server to the internet with a public URL. 项目地址: https://gitcode.com/GitHub_Trending/tu/tunnelto 在远程协作和分布式开发成为常态的今天&…

作者头像 李华
网站建设 2026/4/18 2:21:02

HY-MT1.5-1.8B学术论文翻译优化方案

HY-MT1.5-1.8B学术论文翻译优化方案 1. 引言&#xff1a;面向学术场景的轻量级翻译模型需求 在当前人工智能驱动的科研环境中&#xff0c;跨语言学术交流日益频繁。研究人员需要高效、准确地将中文论文摘要、技术文档或会议投稿内容翻译为英文&#xff0c;同时保持术语一致性…

作者头像 李华
网站建设 2026/4/4 18:48:38

Open-LLM-VTuber虚拟主播完整指南:零基础搭建你的AI伴侣

Open-LLM-VTuber虚拟主播完整指南&#xff1a;零基础搭建你的AI伴侣 【免费下载链接】Open-LLM-VTuber Talk to LLM by voice with Live2D that runs offline on multiple platforms. An attempt to build AI VTuber neuro-sama. 项目地址: https://gitcode.com/gh_mirrors/o…

作者头像 李华
网站建设 2026/4/22 20:03:53

Qwen All-in-One功能测评:轻量级AI服务的真实表现

Qwen All-in-One功能测评&#xff1a;轻量级AI服务的真实表现 基于 Qwen1.5-0.5B 的轻量级、全能型 AI 服务 Single Model, Multi-Task Inference powered by LLM Prompt Engineering 1. 项目背景与技术定位 在边缘计算和资源受限场景中&#xff0c;部署多个AI模型往往面临显存…

作者头像 李华