diff --git a/docker-compose.yml b/docker-compose.yml index 0023fbd5..25b0878e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -150,6 +150,8 @@ services: dockerfile: Dockerfile image: mineru-api:latest container_name: mineru-api + profiles: + - all deploy: resources: reservations: diff --git a/scripts/mineru-api/app.py b/scripts/mineru-api/app.py index 072a238a..d7dad8e3 100644 --- a/scripts/mineru-api/app.py +++ b/scripts/mineru-api/app.py @@ -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, diff --git a/server/db_manager.py b/server/db_manager.py index 35af3401..8e3fae30 100644 --- a/server/db_manager.py +++ b/server/db_manager.py @@ -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() diff --git a/src/core/graphbase.py b/src/core/graphbase.py index 3b446fd5..073c068a 100644 --- a/src/core/graphbase.py +++ b/src/core/graphbase.py @@ -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: diff --git a/src/core/knowledgebase.py b/src/core/knowledgebase.py index 59fdfa1e..951d75ee 100644 --- a/src/core/knowledgebase.py +++ b/src/core/knowledgebase.py @@ -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 diff --git a/src/plugins/_ocr.py b/src/plugins/_ocr.py index f18b0dd5..fc42840e 100644 --- a/src/plugins/_ocr.py +++ b/src/plugins/_ocr.py @@ -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} diff --git a/web/src/apis/base.js b/web/src/apis/base.js index 8ad65fb4..aad20564 100644 --- a/web/src/apis/base.js +++ b/web/src/apis/base.js @@ -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)