import os import logging from chongming_worker import rpc_method from ..models.pydantic import AnalyzePostRequest, AnalyzePostResponse from ..global_var import get_client, get_is_aicc logger = logging.getLogger("plugins.doubao.analyze") @rpc_method( subject="doubao.analyze", method="POST", summary="Analyze image via Doubao vision model", response_model=AnalyzePostResponse, ) async def analyze(request: AnalyzePostRequest) -> AnalyzePostResponse: logger.info("收到分析请求: prompt=%s, image_len=%d", request.prompt, len(request.image_base64)) client = get_client() if client is None: logger.error("豆包客户端未初始化(is_aicc=%s)", get_is_aicc()) return AnalyzePostResponse(result="", error="客户端未初始化,请检查插件启动日志确认 API_KEY 和 AICC 配置是否正确") # 获取图片数据 image_base64 = request.image_base64 if not image_base64: return AnalyzePostResponse(result="", error="未提供图片数据(image_base64或image_path)") if image_base64.startswith('data:image/'): image_base64 = image_base64.split(',', 1)[1] mime_type = "image/png" prompt = request.prompt or "" try: # AICC 模式的 AsyncOpenAI 不支持 thinking 参数,需通过 extra_body 传递 if get_is_aicc(): create_kwargs = {"extra_body": {"thinking": {"type": "disabled"}}} else: create_kwargs = {"thinking": {"type": "disabled"}} response = await client.chat.completions.create( model=os.getenv("DOUBAO_MODEL", "doubao-seed-evolving"), messages=[ { "role": "user", "content": [ {"type": "image_url", "image_url": f"data:{mime_type};base64,{image_base64}"}, {"type": "text", "text": prompt} ] } # type: ignore ], **create_kwargs # type: ignore ) result = response.choices[0].message.content # type: ignore logger.info("分析完成: 结果长度=%d", len(result) if result else 0) return AnalyzePostResponse(result=result) # type: ignore except Exception as e: error_msg = str(e) # 针对 AICC 安全通道密钥缺失,给出明确提示 # KeyMissingError 可能被包装在 APIConnectionError 的 __cause__ 链中 is_key_missing = ( "KeyMissingError" in type(e).__name__ or "Can not get key" in error_msg or any("KeyMissingError" in type(c).__name__ for c in [getattr(e, '__cause__', None), getattr(e, '__context__', None)] if c is not None) ) if is_key_missing: logger.error( "AICC 安全通道密钥获取失败,请检查: " "1) api_key 是否有效 " "2) ra_url(安全令牌地址)是否正确 " "3) APIGateway /v1/security/token 端点是否可达" ) return AnalyzePostResponse( result="", error="AICC 安全通道初始化失败:无法获取加密密钥。" "请检查 api_key 有效性及安全令牌服务 (/v1/security/token) 连通性。" ) logger.error("调用豆包API失败: %s", e, exc_info=True) return AnalyzePostResponse(result="", error=f"调用豆包API失败: {error_msg}")