diff --git a/backend/.env.example b/backend/.env.example index 31ae530..18a68d9 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -79,6 +79,7 @@ EMBEDDING_DIMENSION=1536 # Embedding 维度 OCR_ACCESS_KEY_ID=修改此项为阿里云 OCR 访问密钥ID OCR_ACCESS_KEY_SECRET=修改此项为阿里云 OCR 访问密钥Secret OCR_ENDPOINT=修改此项为阿里云 OCR 终端节点 +OCR_TIMEOUT_SECONDS=120 OCR_USE_LOCAL=false MODERATION_ENABLED=false diff --git a/backend/core/config.py b/backend/core/config.py index 827362a..c41b8bf 100644 --- a/backend/core/config.py +++ b/backend/core/config.py @@ -105,6 +105,7 @@ class Settings(BaseSettings): ocr_access_key_id: Optional[str] = None ocr_access_key_secret: Optional[str] = None ocr_endpoint: str = "ocr-api.cn-hangzhou.aliyuncs.com" # OCR 服务端点 + ocr_timeout_seconds: float = 120.0 # OCR 请求超时(含上传图片 body) # 微信小程序配置 wechat_app_id: Optional[str] = None diff --git a/backend/services/vector_service.py b/backend/services/vector_service.py index f780993..a852651 100644 --- a/backend/services/vector_service.py +++ b/backend/services/vector_service.py @@ -205,15 +205,21 @@ class VectorService: # 初始化阿里云 OCR(图片、扫描 PDF、DOCX 内嵌图均依赖云端识别) self.ocr_engine = None + self._ocr_timeout_ms = int(settings.ocr_timeout_seconds * 1000) if ALIYUN_OCR_AVAILABLE and settings.ocr_access_key_id and settings.ocr_access_key_secret: try: config = open_api_models.Config( access_key_id=settings.ocr_access_key_id, access_key_secret=settings.ocr_access_key_secret, - endpoint=settings.ocr_endpoint + endpoint=settings.ocr_endpoint, + connect_timeout=self._ocr_timeout_ms, + read_timeout=self._ocr_timeout_ms, ) self.ocr_engine = OcrClient(config) - logger.info("✅ 阿里云 OCR 已启用,将使用云端 OCR 服务识别图片文字") + logger.info( + "✅ 阿里云 OCR 已启用,将使用云端 OCR 服务识别图片文字 " + f"(endpoint={settings.ocr_endpoint}, timeout={settings.ocr_timeout_seconds}s)" + ) except Exception as e: logger.warning(f"⚠️ 阿里云 OCR 初始化失败: {e}") elif not ALIYUN_OCR_AVAILABLE: @@ -261,7 +267,7 @@ class VectorService: image_bytes = f.read() image_size_kb = len(image_bytes) / 1024 - logger.debug(f"📊 [阿里云OCR] 图片大小: {image_size_kb:.2f}KB") + logger.info(f"📊 [阿里云OCR] 图片大小: {image_size_kb:.2f}KB") # 使用 StreamClient 读取字节流(阿里云 SDK 要求的格式) body_stream = StreamClient.read_from_bytes(image_bytes) @@ -270,8 +276,13 @@ class VectorService: # 构建请求 request = ocr_models.RecognizeGeneralRequest(body=body_stream) - # 运行时选项 - runtime = util_models.RuntimeOptions() + # 运行时选项(默认超时过短会导致大图片 write timeout) + runtime = util_models.RuntimeOptions( + connect_timeout=self._ocr_timeout_ms, + read_timeout=self._ocr_timeout_ms, + autoretry=True, + max_attempts=2, + ) logger.debug(f"☁️ [阿里云OCR] 调用 API: recognize_general_with_options") # 调用阿里云 OCR API(使用 with_options 版本)