Suya OCR API — vLLM-backed, OpenAI-compatible OCR service
FastAPI service wrapping the Surya-OCR-2 model (datalab-to) served through vLLM: legacy /v1/api/ai/* endpoints, an OpenAI-compatible /v1/chat/completions endpoint, a coalescing request batcher, a local OCR CLI, Docker packaging, multilingual example outputs, and quantization/concurrency benchmarks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import base64
|
||||
import binascii
|
||||
from typing import Any, Literal, Optional
|
||||
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
Field,
|
||||
PrivateAttr,
|
||||
StrictBool,
|
||||
field_validator,
|
||||
model_validator,
|
||||
)
|
||||
|
||||
|
||||
class Info(BaseModel):
|
||||
_decoded_file: bytes = PrivateAttr(default=b"")
|
||||
|
||||
file: str # base64 string
|
||||
type: Literal["png", "jpg", "jpeg", "gif"] # image type like 'png', 'jpg'
|
||||
skip_text_detection: Optional[StrictBool] = Field(False)
|
||||
skip_table_detection: Optional[StrictBool] = Field(False)
|
||||
recognize_math: Optional[StrictBool] = Field(False)
|
||||
ocr_with_boxes: Optional[StrictBool] = Field(True)
|
||||
|
||||
@field_validator("type", mode="before")
|
||||
@classmethod
|
||||
def normalize_type(cls, value: str) -> str:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError("type must be a string")
|
||||
return value.lower()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def decode_base64_file(self):
|
||||
if not self.file:
|
||||
raise ValueError("file must be a non-empty base64 string")
|
||||
try:
|
||||
self._decoded_file = base64.b64decode(self.file, validate=True)
|
||||
except binascii.Error as exc:
|
||||
raise ValueError("file must be valid base64") from exc
|
||||
return self
|
||||
|
||||
|
||||
class ApiResponse(BaseModel):
|
||||
data: Any
|
||||
message: str
|
||||
code: int
|
||||
Reference in New Issue
Block a user