Files
2026-06-22 11:06:01 +08:00

337 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenOCR Markdown Service
一个精简版图片/PDF 转 Markdown 服务,核心依赖 `openocr-python==0.1.5`,保留文档解析能力,去掉训练、评测和实验脚本。
**工作流**Windows 本地编写代码 → Git 推送 → Ubuntu 服务器 Docker 运行。
## 功能
- `POST /api/recognize`:上传图片或 PDF,生成 Markdown 和 JSON
- `GET /api/history`:查看已解析文件列表
- `GET /output/...`:访问生成的 Markdown、JSON 和原始文件
- `GET /health`:健康检查
- `GET /docs`Swagger API 文档
- `GET /v1/models`OpenAI 兼容模型列表
- `POST /v1/chat/completions`OpenAI 兼容文档转 Markdown 接口
---
## 服务器首次初始化(Ubuntu)
### 1. 克隆代码与创建目录
```bash
cd ~
git clone <你的仓库地址> OpenOCR
cd OpenOCR
mkdir -p data/output data/uploads
```
### 2. 生成并配置环境变量
```bash
cp .env.example .env
```
纯 Docker 部署时,重点确认以下配置:
```env
OPENOCR_AUTO_DOWNLOAD=true # 首次运行让容器自动下载模型
OPENOCR_USE_GPU=false # 未配置 NVIDIA Docker 插件前保持 false
OPENOCR_CORS_ORIGINS=*
```
完整配置项见 `.env.example`
### 3. 一键编译并启动容器
```bash
docker compose up -d --build
```
### 4. 跟踪模型下载进度
模型体积较大,容器启动后会在后台自动下载。**此时不要急着调用接口**,先查看日志:
```bash
docker compose logs -f
```
首次下载可能需要 **530 分钟**(取决于网络)。当日志出现 `Application startup complete.` 且无报错时,说明模型加载完成,按 `Ctrl + C` 退出日志跟踪。
---
## 健康检查与验证
### 服务器本地
```bash
curl http://127.0.0.1:8000/health
# 期望返回: {"status":"ok"}
```
### Windows 本地浏览器
`服务器IP` 替换为实际地址:
- API 文档:`http://服务器IP:8000/docs`
- 健康检查:`http://服务器IP:8000/health`
若无法访问,请在云服务器安全组中放行 **8000** 端口。
### API 调用示例
```bash
# 上传图片/PDF 进行解析
curl -F "file=@/path/to/page.png" http://127.0.0.1:8000/api/recognize
# 查看历史记录
curl http://127.0.0.1:8000/api/history
# 强制重新识别(同名文件默认复用已有结果)
curl -F "file=@/path/to/page.png" -F "force=true" http://127.0.0.1:8000/api/recognize
```
成功响应示例:
```json
{
"id": "page",
"status": "success",
"message": "Parsed successfully in 12.34s.",
"markdown_url": "/output/page/page.md",
"json_url": "/output/page/page.json"
}
```
Markdown 访问地址:`http://服务器IP:8000/output/<文档名>/<文档名>.md`
### OpenAI 兼容接口
适用于已有 OpenAI SDK / LangChain / 各类 Agent 框架的调用方式。
若配置了 `OPENOCR_ROOT_PATH=/openocr`,则路径前缀为 `/openocr/v1/...`
**列出模型**
```bash
curl https://jsuse.com/openocr/v1/models
```
**文档转 Markdownchat/completions**
```bash
curl https://jsuse.com/openocr/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "opendoc-0.1b",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Convert this document to markdown"},
{
"type": "image_url",
"image_url": {"url": "https://example.com/page.png"}
}
]
}
]
}'
```
也支持 `data:image/png;base64,...` 形式的图片 URL。
响应中的 `choices[0].message.content` 即为 Markdown 文本。
若设置了 `OPENOCR_API_KEY`,需附加请求头:
```bash
-H "Authorization: Bearer your-api-key"
```
Python 示例(OpenAI SDK):
```python
from openai import OpenAI
client = OpenAI(
base_url="https://jsuse.com/openocr/v1",
api_key="your-api-key-or-empty",
)
response = client.chat.completions.create(
model="opendoc-0.1b",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Convert to markdown"},
{
"type": "image_url",
"image_url": {"url": "https://example.com/page.png"},
},
],
}
],
)
print(response.choices[0].message.content)
```
---
## 日常开发与更新
### Windows 本地
改完代码后推送到远程仓库:
```powershell
# 若已配置 git 快捷别名
gpush "feat: 优化 OCR 的 Markdown 布局解析器"
# 或标准命令
git add .
git commit -m "feat: 优化 OCR 的 Markdown 布局解析器"
git push
```
### Ubuntu 服务器
**只改了 Python 代码**(最常见):
```bash
cd ~/OpenOCR
git pull && docker compose up -d --build
```
优化后 Dockerfile 会分层缓存:`pyproject.toml` 不变时不会重装 `openocr-python` 等大依赖,通常 **1030 秒** 即可完成。
**只改了 `.env` 配置**(无需重新 build):
```bash
docker compose up -d
```
**依赖变更**(改了 `pyproject.toml`)才需要完整重建:
```bash
docker compose build --no-cache
docker compose up -d
```
模型缓存在 Docker 卷 `openocr-model-cache` 中,重建容器后**不会重复下载模型**。解析结果在 `./data/` 中,同样不会丢失。
---
## 启动速度优化说明
每次 `docker compose up -d --build` 很慢,通常有两类原因:
| 原因 | 现象 | 已做优化 |
|------|------|----------|
| pip 重复下载依赖 | build 阶段耗时数分钟 | Dockerfile 分层 + BuildKit pip 缓存 |
| 模型重复下载 | 启动后日志里又在下载 | 模型目录挂载到 `openocr-model-cache` 卷 |
**首次部署**仍需下载模型(5~30 分钟,一次性)。之后日常更新应明显变快。
若 BuildKit 缓存未生效,可确认 Docker 版本 ≥ 20.10compose 会自动使用 BuildKit。
---
## 日常排错与手动测试
### 查看日志
```bash
docker compose logs -f openocr-markdown
```
### 命令行手动解析(不经过 API)
```bash
docker compose exec openocr-markdown openocr-md /app/data/uploads/test.pdf --output-dir /app/data/output
```
### 常用运维命令
```bash
docker compose ps # 查看容器状态
docker compose down # 停止服务
docker compose up -d --build # 重新构建并启动
```
---
## 关键配置
通过 `.env` 或环境变量配置:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `OPENOCR_ROOT_PATH` | *(空)* | 反向代理子路径,如 `/openocr` |
| `OPENOCR_OUTPUT_DIR` | `data/output` | 解析结果输出目录 |
| `OPENOCR_UPLOAD_DIR` | `data/uploads` | 上传文件临时目录 |
| `OPENOCR_USE_GPU` | `false` | 是否使用 GPU |
| `OPENOCR_AUTO_DOWNLOAD` | `true` | 首次运行自动下载模型 |
| `OPENOCR_LAYOUT_THRESHOLD` | `0.4` | 版面分析阈值 |
| `OPENOCR_MAX_LENGTH` | `2048` | 识别最大长度 |
| `OPENOCR_CORS_ORIGINS` | `*` | 跨域来源,多个用逗号分隔 |
| `OPENOCR_API_KEY` | *(空)* | OpenAI 兼容接口 Bearer Token,留空则不校验 |
| `OPENOCR_OPENAI_MODEL` | `opendoc-0.1b` | OpenAI 兼容接口使用的模型 ID |
| `OPENOCR_LOG_LEVEL` | `info` | 日志级别 |
---
## 项目结构
```text
.
├── src/openocr_markdown/
│ ├── api.py # FastAPI 服务
│ ├── cli.py # 命令行入口
│ ├── config.py # 环境变量配置
│ ├── engine.py # OpenOCR 模型加载和解析封装
│ └── schemas.py # API 响应模型
├── tests/
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
└── .env.example
```
## 反向代理(Nginx 子路径)
若通过 `https://jsuse.com/openocr/` 这类**子路径**访问(而非直接 `:8000`),必须在 `.env` 中设置:
```env
OPENOCR_ROOT_PATH=/openocr
```
否则 `/health` 可能正常,但 `/docs` 会报 **Failed to load API definition**——因为 Swagger 会去根路径请求 `/openapi.json`,而不是 `/openocr/openapi.json`
Nginx 参考配置:
```nginx
location /openocr/ {
proxy_pass http://127.0.0.1:8000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
修改后重启容器:
```bash
docker compose up -d --build
```
---
## 注意事项
- `.env``data/`、模型缓存目录已在 `.gitignore` 中排除,不会进入 Git
- 首次启动耗时较长属于正常现象,等待模型下载完成后再调用接口
- 生产环境建议在 Docker 前加 Nginx 反向代理并配置 HTTPS