feat: 添加mineru健康检查端点并优化类型注解

- 在 app.py 中新增健康检查端点以确认 API 正在运行。
- 优化了类型注解,使用更简洁的语法。
- 在 db_manager.py 中修正了日志信息的语言。
- 在 OCR 插件中添加了对 MinerU OCR 服务健康检查的逻辑。
This commit is contained in:
Wenjie Zhang 2025-05-23 22:16:34 +08:00
parent b0db3c6b0d
commit 911f88d7eb
7 changed files with 32 additions and 16 deletions

View File

@ -150,6 +150,8 @@ services:
dockerfile: Dockerfile
image: mineru-api:latest
container_name: mineru-api
profiles:
- all
deploy:
resources:
reservations:

View File

@ -4,7 +4,6 @@ import tempfile
from base64 import b64encode
from glob import glob
from io import StringIO
from typing import Tuple, Union
import magic_pdf.model as model_config
import uvicorn
@ -54,9 +53,9 @@ def init_writers(
file: UploadFile = None,
output_path: str = None,
output_image_path: str = None,
) -> Tuple[
Union[S3DataWriter, FileBasedDataWriter],
Union[S3DataWriter, FileBasedDataWriter],
) -> tuple[
S3DataWriter | FileBasedDataWriter,
S3DataWriter | FileBasedDataWriter,
bytes,
]:
"""
@ -113,8 +112,8 @@ def process_file(
file_bytes: bytes,
file_extension: str,
parse_method: str,
image_writer: Union[S3DataWriter, FileBasedDataWriter],
) -> Tuple[InferenceResult, PipeResult]:
image_writer: S3DataWriter | FileBasedDataWriter,
) -> tuple[InferenceResult, PipeResult]:
"""
Process PDF file content
@ -128,7 +127,7 @@ def process_file(
Tuple[InferenceResult, PipeResult]: Returns inference result and pipeline result
"""
ds: Union[PymuDocDataset, ImageDataset] = None
ds: PymuDocDataset | ImageDataset = None
if file_extension in pdf_extensions:
ds = PymuDocDataset(file_bytes)
elif file_extension in office_extensions:
@ -169,6 +168,13 @@ def encode_image(image_path: str) -> str:
return b64encode(f.read()).decode()
@app.get("/health", tags=["health"], summary="Health check endpoint")
async def health_check():
"""
Simple health check endpoint to confirm the API is running.
"""
return JSONResponse(content={"status": "healthy"}, status_code=200)
@app.post(
"/file_parse",
tags=["projects"],
@ -206,9 +212,7 @@ async def file_parse(
return_content_list: Whether to return parsed PDF content list. Default to False
"""
try:
if (file is None and file_path is None) or (
file is not None and file_path is not None
):
if (bool(file) == bool(file_path)):
return JSONResponse(
content={"error": "Must provide either file or file_path"},
status_code=400,

View File

@ -35,7 +35,7 @@ class DBManager:
"""创建数据库表"""
# 确保所有表都会被创建
Base.metadata.create_all(self.engine)
logger.info("数据库表创建/检查完成")
logger.info("Database tables created/checked")
def get_session(self):
"""获取数据库会话"""
@ -50,7 +50,7 @@ class DBManager:
session.commit()
except Exception as e:
session.rollback()
logger.error(f"数据库操作失败: {e}")
logger.error(f"Database operation failed: {e}")
raise
finally:
session.close()

View File

@ -26,21 +26,22 @@ class GraphDatabase:
# 尝试加载已保存的图数据库信息
if not self.load_graph_info():
logger.debug(f"未找到已保存的图数据库信息,将创建新的配置")
logger.debug("创建新的图数据库配置")
self.start()
def start(self):
if not config.enable_knowledge_graph or not config.enable_knowledge_base:
return
uri = os.environ.get("NEO4J_URI", "bolt://localhost:7687")
username = os.environ.get("NEO4J_USERNAME", "neo4j")
password = os.environ.get("NEO4J_PASSWORD", "0123456789")
logger.info(f"Connecting to Neo4j at {uri}/{self.kgdb_name}")
logger.info(f"Connecting to Neo4j: {uri}/{self.kgdb_name}")
try:
self.driver = GD.driver(f"{uri}/{self.kgdb_name}", auth=(username, password))
self.status = "open"
logger.info(f"Connected to Neo4j at {uri}/{self.kgdb_name}, {self.get_graph_info(self.kgdb_name)}")
logger.info(f"Connected to Neo4j: {self.get_graph_info(self.kgdb_name)}")
# 连接成功后保存图数据库信息
self.save_graph_info(self.kgdb_name)
except Exception as e:

View File

@ -416,8 +416,10 @@ class KnowledgeBase:
logger.error(f"处理文件 {file_path} 时出错: {e}")
file_info_dict["status"] = "failed"
file_info_dict["error"] = str(e)
raise e
file_infos[file_id] = file_info_dict
finally:
file_infos[file_id] = file_info_dict
return file_infos

View File

@ -163,6 +163,11 @@ class OCRPlugin:
import requests
import json
health_check_response = requests.get(f"{mineru_ocr_uri}/health", timeout=5)
if health_check_response.status_code != 200 or health_check_response.json().get("status") != "healthy":
logger.error("Mineru OCR service health check failed.")
raise RuntimeError("Mineru OCR service health check failed. Please check the log use `docker logs mineru-api`")
# 读取PDF文件
with open(pdf_path, 'rb') as f:
files = {'file': f}

View File

@ -73,6 +73,8 @@ export async function apiRequest(url, options = {}, requiresAuth = false) {
throw new Error('未授权,请先登录')
} else if (response.status === 403) {
throw new Error('没有权限执行此操作')
} else if (response.status === 500) {
throw new Error('Server 500 Error, please check the log use `docker logs api-dev`')
}
throw new Error(errorMessage)