from fastapi import FastAPI, UploadFile, File, HTTPException, Form from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from typing import List import os import tempfile from pathlib import Path from dotenv import load_dotenv # 加载环境变量 load_dotenv() from services.ocr_service import OCRService from services.llm_service import LLMService from services.report_integrator import ReportIntegrator from services.pdf_service import PDFService from services.template_service import TemplateService from services.batch_report_service import BatchReportService from services.deepseek_health_service import DeepSeekHealthService app = FastAPI(title="医疗报告分析系统") # CORS配置 app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:5173", "http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # 初始化服务(仅用于综合报告流程) ocr_service = OCRService() llm_service = LLMService() report_integrator = ReportIntegrator(llm_service) pdf_service = PDFService() template_service = TemplateService() batch_service = BatchReportService(ocr_service, llm_service, pdf_service, template_service) # 检查 DeepSeek 配置状态 deepseek_key = os.getenv("DEEPSEEK_API_KEY", "") if deepseek_key: print("✓ DeepSeek API Key 已配置,健康评估和建议功能已启用") else: print("⚠ DeepSeek API Key 未配置,健康评估和建议功能将被跳过") @app.get("/") async def root(): return {"message": "医疗报告分析系统API", "status": "running"} @app.post("/api/comprehensive-report") async def generate_comprehensive_report( files: List[UploadFile] = File(...), patient_name: str = Form(default="患者") ): """ 批量上传并生成综合健康报告 注意:上传的文件不会永久存储,处理完后自动删除 """ temp_files = [] try: # 验证文件类型 allowed_extensions = {".pdf", ".jpg", ".jpeg", ".png", ".bmp"} # 临时保存上传的文件 for file in files: file_ext = Path(file.filename).suffix.lower() if file_ext not in allowed_extensions: raise HTTPException( status_code=400, detail=f"不支持的文件格式: {file.filename}" ) # 创建临时文件 temp_file = tempfile.NamedTemporaryFile( delete=False, suffix=file_ext, dir=str(batch_service.temp_dir) ) # 写入文件内容 content = await file.read() temp_file.write(content) temp_file.close() temp_files.append(temp_file.name) # 批量处理报告 result = batch_service.process_multiple_reports( file_paths=temp_files, patient_name=patient_name ) return { "success": True, "patient_name": result["patient_name"], "report_count": result["report_count"], "pdf_filename": Path(result["pdf_path"]).name, "pdf_path": result["pdf_path"], "generated_at": result["generated_at"], # 包含健康评估和建议内容 "health_assessment": result.get("analysis", {}).get("health_assessment", {}), "health_advice": result.get("analysis", {}).get("health_advice", {}) } except HTTPException: # 清理临时文件 batch_service._cleanup_temp_files(temp_files) raise except Exception as e: # 清理临时文件 batch_service._cleanup_temp_files(temp_files) import traceback error_detail = f"综合报告生成失败: {str(e)}\n{traceback.format_exc()}" print(error_detail) # 打印完整错误堆栈 raise HTTPException(status_code=500, detail=f"综合报告生成失败: {str(e)}") @app.get("/api/comprehensive-report/download/{pdf_filename}") async def download_comprehensive_report(pdf_filename: str): """下载综合健康报告""" try: pdf_path = pdf_service.output_dir / pdf_filename if not pdf_path.exists(): raise HTTPException(status_code=404, detail="PDF文件不存在") return FileResponse( path=str(pdf_path), media_type="application/pdf", filename=pdf_filename ) except Exception as e: raise HTTPException(status_code=500, detail=f"下载失败: {str(e)}") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8001)