71 lines
2.9 KiB
Python
71 lines
2.9 KiB
Python
import logging
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import httpx
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# ✅ DeepSeek OCR API
|
|
async def extract_deepseek_ocr(file_path: str):
|
|
"""
|
|
deepseek_ocr_vllm 컨테이너를 호출하여 이미지에서 텍스트 및 좌표를 추출합니다.
|
|
"""
|
|
# deepseek_ocr_vllm 컨테이너의 FastAPI 엔드포인트 URL
|
|
# TODO: 실제 엔드포인트명('/ocr')을 확정한 후 필요시 수정해야 합니다.
|
|
DEEPSEEK_API_URL = os.getenv("DEEPSEEK_API_URL", "http://deepseek_ocr_vllm:8000/ocr")
|
|
|
|
if not file_path or not os.path.exists(file_path):
|
|
raise FileNotFoundError(f"파일이 존재하지 않습니다: {file_path}")
|
|
|
|
filename = Path(file_path).name
|
|
full_text_parts = []
|
|
coord_response = []
|
|
|
|
with open(file_path, "rb") as f:
|
|
# TODO: FastAPI 엔드포인트에서 사용하는 파일 파라미터 이름('document')을 확인해야 합니다.
|
|
files = {"document": (filename, f, "application/octet-stream")}
|
|
try:
|
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
|
response = await client.post(DEEPSEEK_API_URL, files=files)
|
|
response.raise_for_status()
|
|
result = response.json()
|
|
except httpx.HTTPStatusError as e:
|
|
logger.error(f"DeepSeek API 오류: {e.response.text}")
|
|
raise RuntimeError(f"DeepSeek API 오류: {e.response.status_code}")
|
|
except httpx.ConnectError as e:
|
|
logger.error(f"DeepSeek 컨테이너 연결 실패: {e}")
|
|
raise RuntimeError(f"DeepSeek 컨테이너({DEEPSEEK_API_URL})에 연결할 수 없습니다.")
|
|
|
|
# TODO: 실제 API 응답 형식에 맞게 JSON 파싱 로직을 수정해야 합니다.
|
|
try:
|
|
# 아래는 응답이 Upstage와 유사한 형식일 경우를 가정한 예시입니다.
|
|
pages = result.get("pages", [])
|
|
for page_idx, p in enumerate(pages, start=1):
|
|
txt = p.get("text")
|
|
if txt:
|
|
full_text_parts.append(txt)
|
|
|
|
for w in p.get("words", []):
|
|
verts = (w.get("boundingBox", {}) or {}).get("vertices")
|
|
if not verts or len(verts) != 4:
|
|
continue
|
|
xs = [v.get("x", 0) for v in verts]
|
|
ys = [v.get("y", 0) for v in verts]
|
|
coord_response.append(
|
|
{
|
|
"text": w.get("text"),
|
|
"coords": [min(xs), min(ys), max(xs), max(ys)],
|
|
"page": page_idx,
|
|
}
|
|
)
|
|
logger.warning("DeepSeek OCR의 실제 응답 형식에 맞게 파싱 로직을 구현해야 합니다.")
|
|
|
|
except Exception as e:
|
|
logger.error(f"[DEEPSEEK] JSON 파싱 실패: {e} / 원본 result: {result}")
|
|
return "", []
|
|
|
|
logger.info("[DEEPSEEK] 텍스트 추출 완료")
|
|
full_response = "\n".join(full_text_parts)
|
|
return full_response, coord_response |