返回 Pixelle-Video
vlm_dashscope.py
根目录 / pixelle_video / services / api_services / vlm_dashscope.py
1 # -*- coding: utf-8 -*-
2 """
3 Qwen3.5-VL 多模态大模型 API 客户端(DashScope 多模态接口专用)
4 只支持 Qwen3.5-VL 及兼容 DashScope 多模态对话接口
5 参考官方文档:https://help.aliyun.com/zh/model-studio/qwen-api-reference
6 """
7
8 import os
9
10 try:
11 import dashscope
12 from dashscope import MultiModalConversation
13 except ImportError:
14 dashscope = None
15 MultiModalConversation = None
16 import logging
17
18 logger = logging.getLogger(__name__)
19 from typing import Any, Dict, List, Optional
20
21 class QwenVLClient:
22 def __init__(self,
23 api_key: Optional[str] = None,
24 base_url: Optional[str] = None):
25 """
26 Qwen3.5-VL 多模态客户端
27 :param api_key: DashScope/Qwen3.5 API Key
28 :param model: 模型名(如 qwen3.5-plus/qwen3.5-max 等)
29 """
30 self.api_key = api_key or os.getenv("DASHSCOPE_API_KEY")
31
32 def chat(
33 self,
34 text: str,
35 images: List[str],
36 model: str,
37 stream: bool = False,
38 parameters: Optional[Dict] = None,
39 videos: Optional[List[str]] = None,
40 **kwargs
41 ) -> Any:
42 """
43 使用阿里云 dashscope SDK 进行多模态对话(文本+图片/视频),风格与 image_dashscope.py 一致。
44 :param text: 文本内容
45 :param images: 图片路径列表(支持本地路径或URL,内部会转换为file://绝对路径)
46 :param videos: 视频路径列表(支持本地路径或URL,内部会转换为file://绝对路径)
47 :param model: 模型名(支持qwen3.5-plus, qwen3-vl-plus)
48 :param stream: 是否流式输出(暂不支持流式)
49 :param parameters: 其他API参数
50 :return: API响应内容 dict
51 """
52 if dashscope is None or MultiModalConversation is None:
53 raise RuntimeError("dashscope package not installed. Run: pip install dashscope")
54
55 dashscope.api_key = self.api_key
56 # 只支持非流式
57 try:
58 content = [
59 {"text": text},
60 *({"image": p} for p in images),
61 *({"video": p} for p in videos or []),
62 ]
63 messages = [{"role": "user", "content": content}]
64 response = MultiModalConversation.call(
65 model=model,
66 messages=messages,
67 api_key=self.api_key,
68 enable_thinking=False,
69 **(parameters or {})
70 )
71 if hasattr(response, 'status_code') and response.status_code == 200:
72 # qwen3.5-plus 的返回格式为 { choices: [ { message: { content: [...] } } ] }
73 resp = response.output.choices[0].message.content[0]
74 if resp.get('text'):
75 return resp['text']
76 return resp
77 else:
78 raise RuntimeError(f"DashScope QwenVLClient failed: {getattr(response, 'message', response)}")
79 except Exception as e:
80 raise RuntimeError(f"DashScope QwenVLClient error: {e}")
81
82
83 if __name__ == "__main__":
84 import sys
85 import time
86 import json
87 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
88 from config import Config
89
90 # 支持的 VLM 模型列表
91 MODELS = ["qwen3.6-plus", "qwen3.6-flash", "kimi-k2.6"]
92
93 print("=== Qwen VL (DashScope) 多模态可用性测试 ===")
94 api_key = getattr(Config, "DASHSCOPE_API_KEY", None) or os.getenv("DASHSCOPE_API_KEY", "")
95 if not api_key:
96 print("✗ DASHSCOPE_API_KEY 未设置,跳过")
97 sys.exit(1)
98 print(f" API Key: {api_key[:6]}***{api_key[-4:]}")
99 client = QwenVLClient(api_key=api_key)
100
101 # 测试图片
102 img_path = ''
103 abs_img_path = os.path.abspath(img_path)
104 if not os.path.exists(img_path):
105 img_path = "code/result/image/test_avail/test_input.png"
106 abs_img_path = os.path.abspath(img_path)
107 if not os.path.exists(img_path):
108 print("✗ 测试图片不存在,跳过")
109 sys.exit(0)
110
111 text = "请描述这张图片的内容"
112 print(f"\n[多模态] Prompt: {text}")
113 print(f" 图片: {img_path}")
114
115 for model in MODELS:
116 print(f"\n--- 测试模型: {model} ---")
117 t0 = time.time()
118 try:
119 result = client.chat(text=text, images=[img_path], model=model, stream=False)
120 elapsed = time.time() - t0
121 if result:
122 print(f"✓ 返回结果 ({elapsed:.1f}s): {str(result)[:200]}")
123 else:
124 print(f"✗ 返回空结果 ({elapsed:.1f}s)")
125 except Exception as e:
126 print(f"✗ 失败: {e}")
127
127 lines PYTHON