""" OCR 请求 / 响应 Pydantic 模型。 定义天目微服务内部的 API 契约,供 endpoints 和 engine 使用。 """ from __future__ import annotations from typing import Any from pydantic import BaseModel, Field class OCRRequest(BaseModel): """通用 OCR 请求。""" image: str = Field(description="图片数据:base64 编码字符串或 HTTP(s) URL") engine: str = Field( default="auto", description="引擎选择:auto(自动选择)/ ppocrv6 / paddleocr-vl", ) lang: list[str] = Field( default_factory=lambda: ["ch", "en"], description="识别语言列表,默认中英文。仅对 ppocrv6 引擎生效", ) resize: int | None = Field( default=None, description="可选:图片最大边长(px),超过则等比缩放。减少传输 / 推理耗时", ) save_md: bool = Field( default=False, description="是否将识别结果保存为 Markdown 文件到 output/md/ 目录", ) class BBox(BaseModel): """文本框坐标。""" points: list[list[float]] = Field(description="四个顶点坐标 [[x1,y1],[x2,y1],[x3,y2],[x4,y2]]") class TextBlock(BaseModel): """单行/单块识别结果。""" text: str = Field(description="识别文字") confidence: float = Field(description="置信度 0~1", ge=0, le=1) bbox: BBox = Field(description="文本框坐标") class OCRResponse(BaseModel): """通用 OCR 响应。""" engine: str = Field(description="实际使用的引擎,如 ppocrv6 / paddleocr-vl") text: str = Field(default="", description="拼接后的全文") blocks: list[TextBlock] = Field(default_factory=list, description="逐块识别结果") duration_ms: float = Field(default=0, description="推理耗时(毫秒)") error: str | None = Field(default=None, description="错误信息,成功时为 null") saved_md_path: str | None = Field( default=None, description="保存的 Markdown 文件路径(仅 save_md=true 时有值)" ) class OCRVLRequest(BaseModel): """PaddleOCR-VL 复杂文档解析请求。""" image: str = Field(description="图片数据:base64 编码字符串或 HTTP(s) URL") output_format: str = Field( default="markdown", description="输出格式:markdown / json / text", ) save_md: bool = Field( default=False, description="是否将识别结果保存为 Markdown 文件到 output/md/ 目录", ) class OCRVLResponse(BaseModel): """PaddleOCR-VL 响应。""" engine: str = Field(default="paddleocr-vl") text: str = Field(default="", description="结构化输出文本(Markdown / JSON / 纯文本)") format: str = Field(default="markdown", description="实际输出格式") duration_ms: float = Field(default=0, description="推理耗时(毫秒)") error: str | None = Field(default=None, description="错误信息,成功时为 null") saved_md_path: str | None = Field( default=None, description="保存的 Markdown 文件路径(仅 save_md=true 时有值)" ) # ── 健康检查 ────────────────────────────────────────────── class EngineStatus(BaseModel): """引擎状态。""" status: str = Field(description="ok / degraded / error / unavailable") class HealthResponse(BaseModel): """健康检查响应。""" status: str = Field(description="整体状态:ok / degraded / error") engines: dict[str, Any] = Field(default_factory=dict, description="各引擎状态") version: str = Field(description="天目版本")