Files
hunjing/tianmu/README.md
T
2026-08-21 16:00:13 +08:00

248 lines
7.2 KiB
Markdown
Raw 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.
# 天目 · 本地 OCR 引擎
天目(Tiānmù)是魂镜的**本地 OCR 推理引擎**,基于 RapidOCR(PP-OCRv6)和 PaddleOCR-VL-1.6,纯 Python 实现,直接加载 ONNX / PaddlePaddle 模型进行本地文字识别和文档解析。
> 「天目」为观天象、察文字之眼,映照万物纹理;在魂镜中承载本地 OCR 感知能力,为人物的视觉感知提供文字提取与文档理解。
---
## 架构概览
```mermaid
flowchart LR
lingtai[灵台 · Backend]
tianmu[天目 · OCR Local Engine]
models[(models/ocr/ 目录)]
lingtai -->|POST /v1/ocr| tianmu
lingtai -->|POST /v1/ocr/vl| tianmu
lingtai -->|GET /healthz| tianmu
tianmu -->|RapidOCR ONNX Runtime| models
tianmu -->|PaddleOCR-VL 直接加载| models
```
## 提供的 API
| 端点 | 能力 | 引擎 |
| --- | --- | --- |
| `POST /v1/ocr` | 通用文字识别 | RapidOCR(PP-OCRv6) |
| `POST /v1/ocr/vl` | 复杂文档解析(Phase 3) | PaddleOCR-VL-1.6 |
| `GET /healthz` | 健康检查 | — |
### POST /v1/ocr
请求:
```json
{
"image": "<base64 或 HTTP URL>",
"engine": "auto",
"lang": ["ch", "en"]
}
```
响应:
```json
{
"engine": "ppocrv6",
"text": "识别后的文本...",
"blocks": [
{
"text": "字",
"confidence": 0.98,
"bbox": { "points": [[x1,y1],[x2,y1],[x2,y2],[x1,y2]] }
}
],
"duration_ms": 423,
"error": null
}
```
## 模型文件结构
所有模型统一放在项目根目录 `models/ocr/` 下,已预下载完毕:
```text
models/ocr/
├── ppocrv6/ # PP-OCRv6 ONNX 模型(168 MB)
│ ├── det/
│ │ ├── PP-OCRv6_det_tiny.onnx # 轻量检测(1.8 MB)
│ │ ├── PP-OCRv6_det_small.onnx # 默认检测(9.5 MB)
│ │ └── PP-OCRv6_det_medium.onnx # 高精度检测(59 MB)
│ ├── rec/
│ │ ├── PP-OCRv6_rec_tiny.onnx # 轻量识别(4.3 MB)
│ │ ├── PP-OCRv6_rec_small.onnx # 默认识别(20 MB)
│ │ ├── PP-OCRv6_rec_medium.onnx # 高精度识别(73 MB)
│ │ ├── ppocrv6_tiny_dict.txt # tiny 词表(27 KB)
│ │ └── ppocrv6_dict.txt # small/medium 词表(75 KB)
│ └── cls/
│ └── ch_ppocr_mobile_v2.0_cls_mobile.onnx # 方向分类(0.57 MB)
└── paddleocr-vl/ # PaddleOCR-VL-1.6(1.8 GB)
├── model.safetensors
├── config.json
├── tokenizer.json / tokenizer.model
└── modeling_paddleocr_vl.py
```
各模型来源:
| 模型 | 来源 | 下载方式 |
| --- | --- | --------- |
| PP-OCRv6(det/rec/cls) | [RapidAI/RapidOCR - ModelScope](https://www.modelscope.cn/models/RapidAI/RapidOCR) | 预下载或自动下载 |
| PaddleOCR-VL-1.6 | [PaddlePaddle/PaddleOCR-VL-1.6 - HuggingFace](https://huggingface.co/PaddlePaddle/PaddleOCR-VL-1.6) | 已预下载 |
## 快速开始
```bash
# 1. 进入天目目录
cd tianmu
# 2. 创建虚拟环境并安装依赖
uv venv -p 3.12
source .venv/bin/activate
uv sync --extra rapidocr
# 3. 启动天目(推荐)
uv run tianmu
# 4. 验证健康检查
curl http://localhost:8101/healthz
# 5. 测试 OCR(base64 图片)
python3 tests/test_ocr.py
```
## 启动方式对比
| 命令 | 适用场景 | reload | 泄漏警告 |
|------|---------|--------|---------|
| `uv run tianmu` | 开发(推荐) | ❌ | ❌ |
| `uv run uvicorn src.main:app --port 8101 --reload` | 开发热重载 | ✅ | ⚠️ reloader 进程可能打印 resource_tracker 警告 |
| `python3 -m src.main` | 快速测试 | ❌ | ❌ |
> `--reload` 下的 `resource_tracker` 警告是 uvicorn WatchFiles reloader 进程本身的多进程行为,不影响天目功能,纯属视觉问题。生产环境(Docker)无此问题。
## 启动和测试
天目提供两种测试方式:
### 方式一:远程图片测试
```bash
curl -s -X POST http://localhost:8101/v1/ocr \
-H "Content-Type: application/json" \
-d '{"image": "https://example.com/test-image.jpg"}' \
| python3 -m json.tool
```
### 方式二:base64 图片测试
```bash
# 使用内置测试脚本生成测试图片并调用
cd tianmu && source .venv/bin/activate
python3 tests/test_ocr.py
```
### 方式三:本地文件测试
```bash
curl -s -X POST http://localhost:8101/v1/ocr \
-H "Content-Type: application/json" \
-d "{\"image\": \"$(base64 -i /path/to/image.jpg | tr -d '\n')\"}" \
| python3 -m json.tool
```
## 配置
通过 `TIANMU_*` 环境变量配置(详见 `.env.example`):
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `TIANMU_HOST` | `0.0.0.0` | 监听地址 |
| `TIANMU_PORT` | `8101` | 监听端口 |
| `TIANMU_MODELS_DIR` | `../models` | 模型文件根目录 |
| `TIANMU_DEVICE` | `auto` | 推理设备:auto / cuda / mps / cpu |
| `TIANMU_LOG_LEVEL` | `info` | 日志级别 |
## 项目结构
```text
tianmu/ # 源代码
├── pyproject.toml # 依赖(rapidocr / paddlepaddle)
├── README.md # 本文件
├── src/
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置加载(环境变量 → models/ 路径解析)
│ ├── endpoints/
│ │ ├── ocr.py # OCR 端点(/v1/ocr + /v1/ocr/vl)
│ │ └── health.py # 健康检查端点(/healthz)
│ ├── engine/
│ │ ├── rapidocr.py # RapidOCR(PP-OCRv6)推理引擎
│ │ └── paddleocr_vl.py # PaddleOCR-VL-1.6 引擎(预留)
│ ├── schemas/
│ │ └── ocr.py # Pydantic 请求/响应模型
│ └── utils/
│ └── logging.py # loguru 日志配置
└── tests/
├── test_ocr.py # OCR 集成测试(生成图片 + 调用 API)
└── __init__.py
docker/tianmu/ # Docker 构建文件
├── Dockerfile
└── .dockerignore
```
## 引擎选择
天目提供两个引擎,按需切换:
| 引擎 | 场景 | 速度 | 精度 | 依赖 |
| --- | --- | --- | --- | --- |
| PP-OCRv6(via RapidOCR) | 通用文字提取 | ~400ms(CPU) | ⭐⭐⭐⭐ | `rapidocr` |
| PaddleOCR-VL-1.6 | 复杂文档/表格/古籍 | ~3-12s(GPU) | ⭐⭐⭐⭐⭐ | `paddlepaddle` |
调用时通过 `engine` 参数指定:
```json
// 强制使用 PP-OCRv6
{"image": "...", "engine": "ppocrv6"}
// 强制使用 PaddleOCR-VL
{"image": "...", "engine": "paddleocr-vl"}
```
`engine` 不传或传 `auto` 时默认走 PP-OCRv6。
## Docker 部署
详见 `docker/README.md` 及 `docker-compose.app.yml` 中 `hunjing-tianmu` 服务定义。
```bash
# Docker 启动
docker compose -f docker/docker-compose.app.yml --profile tianmu up -d --build hunjing-tianmu
```
## 依赖分组
```bash
# 仅 PP-OCRv6(默认推荐)
uv sync --extra rapidocr
# PP-OCRv6 + PaddleOCR-VL(需要复杂文档解析)
uv sync --extra rapidocr --extra vl
# 所有可选
uv sync --extra all
```
## 测试
```bash
# 基础测试(无需启动服务)
pytest tests/ -v
# 集成测试(需先启动服务)
python3 tests/test_ocr.py
```