import logging import json import base64 from typing import Dict, Any, Optional, List import asyncio from app.core.config import settings from app.core.qwen_client import qwen_client class AIClient: """AI 客户端,统一包装千问和 DeepSeek""" def __init__(self): self.timeout = 15 # 请求超时时间(秒) async def extract_pickup_code(self, image_url: str) -> Dict[str, Any]: """ 从图片中提取取件码 Args: image_content: 图片二进制内容 Returns: Dict: 提取结果,包含取件码信息 """ try: primary_result = await self._extract_with_qwen(image_url) # 检查结果是否有效 if self._is_valid_result(primary_result): return primary_result return {"error": "处理失败", "message": "提取取件码失败"} except Exception as e: logging.exception(f"提取取件码异常: {str(e)}") return {"error": "处理失败", "message": str(e)} async def _extract_with_qwen(self, image_url: str) -> Dict[str, Any]: """使用千问提取取件码""" try: # 添加超时控制 return await asyncio.wait_for( qwen_client.extract_pickup_code(image_url), timeout=self.timeout ) except asyncio.TimeoutError: logging.error("千问 API 请求超时") return {"error": "API请求超时", "details": "千问 API 请求超时"} except Exception as e: logging.exception(f"千问提取异常: {str(e)}") return {"error": "处理失败", "message": str(e)} def _is_valid_result(self, result: Dict[str, Any]) -> bool: """检查结果是否有效""" # 检查是否有错误 if "error" in result: return False # 检查是否有站点信息 stations = result.get("stations", []) if not stations: return False # 检查是否有取件码 for station in stations: if station.get("pickup_codes") and len(station.get("pickup_codes", [])) > 0: return True return False # 创建全局实例 ai_client = AIClient()