Files
chongming-plugins/doubao/router/analyze.py
T

80 lines
3.5 KiB
Python
Raw Normal View History

2026-07-21 15:43:39 +08:00
import os
2026-07-31 16:53:38 +08:00
import logging
2026-07-21 15:43:39 +08:00
from chongming_worker import rpc_method
from ..models.pydantic import AnalyzePostRequest, AnalyzePostResponse
2026-07-27 14:28:07 +08:00
from ..global_var import get_client, get_is_aicc
2026-07-21 15:43:39 +08:00
2026-07-31 16:53:38 +08:00
logger = logging.getLogger("plugins.doubao.analyze")
2026-07-21 15:43:39 +08:00
@rpc_method(
subject="doubao.analyze",
method="POST",
summary="Analyze image via Doubao vision model",
response_model=AnalyzePostResponse,
)
async def analyze(request: AnalyzePostRequest) -> AnalyzePostResponse:
2026-07-31 16:53:38 +08:00
logger.info("收到分析请求: prompt=%s, image_len=%d", request.prompt, len(request.image_base64))
2026-07-27 14:28:07 +08:00
client = get_client()
2026-07-21 15:43:39 +08:00
if client is None:
2026-07-31 16:53:38 +08:00
logger.error("豆包客户端未初始化(is_aicc=%s)", get_is_aicc())
return AnalyzePostResponse(result="", error="客户端未初始化,请检查插件启动日志确认 API_KEY 和 AICC 配置是否正确")
2026-07-21 15:43:39 +08:00
# 获取图片数据
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:
2026-07-27 14:28:07 +08:00
# AICC 模式的 AsyncOpenAI 不支持 thinking 参数,需通过 extra_body 传递
if get_is_aicc():
create_kwargs = {"extra_body": {"thinking": {"type": "disabled"}}}
else:
create_kwargs = {"thinking": {"type": "disabled"}}
2026-07-21 15:43:39 +08:00
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
],
2026-07-27 14:28:07 +08:00
**create_kwargs # type: ignore
2026-07-21 15:43:39 +08:00
)
result = response.choices[0].message.content # type: ignore
2026-07-31 16:53:38 +08:00
logger.info("分析完成: 结果长度=%d", len(result) if result else 0)
2026-07-21 15:43:39 +08:00
return AnalyzePostResponse(result=result) # type: ignore
except Exception as e:
2026-08-03 16:56:56 +08:00
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) 连通性。"
)
2026-07-31 16:53:38 +08:00
logger.error("调用豆包API失败: %s", e, exc_info=True)
2026-08-03 16:56:56 +08:00
return AnalyzePostResponse(result="", error=f"调用豆包API失败: {error_msg}")