优化模型实例创建逻辑,简化API密钥选择,更新阿里巴巴模型的最大Token设置,支持新的Qwen-VL模型,调整思考过程的处理逻辑,增强用户界面设置的动态效果。

This commit is contained in:
Zylan
2025-04-02 13:28:02 +08:00
parent d95b16c73c
commit 794cac0ca4
6 changed files with 218 additions and 77 deletions

View File

@@ -4,15 +4,54 @@ from openai import OpenAI
from .base import BaseModel
class AlibabaModel(BaseModel):
def __init__(self, api_key: str, temperature: float = 0.7, system_prompt: str = None, language: str = None, model_name: str = None):
self.model_name = model_name or "QVQ-Max-2025-03-25" # 默认使用QVQ-Max模型
# 在super().__init__之前设置model_name这样get_default_system_prompt能使用它
super().__init__(api_key, temperature, system_prompt, language)
def get_default_system_prompt(self) -> str:
return """你是一位专业的问题分析与解答助手。当看到一个问题图片时,请:
1. 仔细阅读并理解问题
2. 分析问题的关键组成部分
3. 提供清晰的、逐步的解决方案
4. 如果相关,解释涉及的概念或理论
5. 如果有多种解决方法,先解释最高效的方法"""
"""根据模型名称返回不同的默认系统提示词"""
# 检查是否是通义千问VL模型
if self.model_name and "qwen-vl" in self.model_name:
return """你是通义千问VL视觉语言助手擅长图像理解、文字识别、内容分析和创作。请根据用户提供的图像
1. 仔细阅读并理解问题
2. 分析问题的关键组成部分
3. 提供清晰的、逐步的解决方案
4. 如果相关,解释涉及的概念或理论
5. 如果有多种解决方法,先解释最高效的方法"""
else:
# QVQ模型使用原先的提示词
return """你是一位专业的问题分析与解答助手。当看到一个问题图片时,请:
1. 仔细阅读并理解问题
2. 分析问题的关键组成部分
3. 提供清晰的、逐步的解决方案
4. 如果相关,解释涉及的概念或理论
5. 如果有多种解决方法,先解释最高效的方法"""
def get_model_identifier(self) -> str:
"""根据模型名称返回对应的模型标识符"""
# 直接映射模型ID到DashScope API使用的标识符
model_mapping = {
"QVQ-Max-2025-03-25": "qvq-max",
"qwen-vl-max-latest": "qwen-vl-max", # 修正为正确的API标识符
}
# 从模型映射表中获取模型标识符,如果不存在则使用默认值
model_id = model_mapping.get(self.model_name)
if model_id:
return model_id
# 如果没有精确匹配,检查是否包含特定前缀
if self.model_name and "qwen-vl" in self.model_name:
if "max" in self.model_name:
return "qwen-vl-max"
elif "plus" in self.model_name:
return "qwen-vl-plus"
elif "lite" in self.model_name:
return "qwen-vl-lite"
return "qwen-vl-max" # 默认使用最强版本
# 最后的默认值
return "qvq-max"
def analyze_text(self, text: str, proxies: dict = None) -> Generator[dict, None, None]:
@@ -59,7 +98,7 @@ class AlibabaModel(BaseModel):
messages=messages,
temperature=self.temperature,
stream=True,
max_tokens=self.max_tokens if hasattr(self, 'max_tokens') and self.max_tokens else 4000
max_tokens=self._get_max_tokens()
)
# 记录思考过程和回答
@@ -67,14 +106,17 @@ class AlibabaModel(BaseModel):
answer_content = ""
is_answering = False
# 检查是否为通义千问VL模型不支持reasoning_content
is_qwen_vl = "qwen-vl" in self.get_model_identifier()
for chunk in response:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
# 处理思考过程
if hasattr(delta, 'reasoning_content') and delta.reasoning_content is not None:
# 处理思考过程仅适用于QVQ模型
if not is_qwen_vl and hasattr(delta, 'reasoning_content') and delta.reasoning_content is not None:
reasoning_content += delta.reasoning_content
# 思考过程作为一个独立的内容发送
yield {
@@ -84,7 +126,7 @@ class AlibabaModel(BaseModel):
}
elif delta.content != "":
# 判断是否开始回答(从思考过程切换到回答)
if not is_answering:
if not is_answering and not is_qwen_vl:
is_answering = True
# 发送完整的思考过程
if reasoning_content:
@@ -126,7 +168,7 @@ class AlibabaModel(BaseModel):
}
def analyze_image(self, image_data: str, proxies: dict = None) -> Generator[dict, None, None]:
"""Stream QVQ-Max's response for image analysis"""
"""Stream model's response for image analysis"""
try:
# Initial status
yield {"status": "started", "content": ""}
@@ -186,7 +228,7 @@ class AlibabaModel(BaseModel):
messages=messages,
temperature=self.temperature,
stream=True,
max_tokens=self.max_tokens if hasattr(self, 'max_tokens') and self.max_tokens else 4000
max_tokens=self._get_max_tokens()
)
# 记录思考过程和回答
@@ -194,14 +236,17 @@ class AlibabaModel(BaseModel):
answer_content = ""
is_answering = False
# 检查是否为通义千问VL模型不支持reasoning_content
is_qwen_vl = "qwen-vl" in self.get_model_identifier()
for chunk in response:
if not chunk.choices:
continue
delta = chunk.choices[0].delta
# 处理思考过程
if hasattr(delta, 'reasoning_content') and delta.reasoning_content is not None:
# 处理思考过程仅适用于QVQ模型
if not is_qwen_vl and hasattr(delta, 'reasoning_content') and delta.reasoning_content is not None:
reasoning_content += delta.reasoning_content
# 思考过程作为一个独立的内容发送
yield {
@@ -211,7 +256,7 @@ class AlibabaModel(BaseModel):
}
elif delta.content != "":
# 判断是否开始回答(从思考过程切换到回答)
if not is_answering:
if not is_answering and not is_qwen_vl:
is_answering = True
# 发送完整的思考过程
if reasoning_content:
@@ -250,4 +295,12 @@ class AlibabaModel(BaseModel):
yield {
"status": "error",
"error": str(e)
}
}
def _get_max_tokens(self) -> int:
"""根据模型类型返回合适的max_tokens值"""
# 检查是否为通义千问VL模型
if "qwen-vl" in self.get_model_identifier():
return 2000 # 通义千问VL模型最大支持2048留一些余量
# QVQ模型或其他模型
return self.max_tokens if hasattr(self, 'max_tokens') and self.max_tokens else 4000

View File

@@ -126,8 +126,8 @@ class ModelFactory:
temperature=temperature,
system_prompt=system_prompt
)
# 对于DeepSeek模型传递model_name参数
elif "deepseek" in model_name.lower():
else:
# 对于所有其他模型传递model_name参数
return model_class(
api_key=api_key,
temperature=temperature,
@@ -135,14 +135,6 @@ class ModelFactory:
language=language,
model_name=model_name
)
else:
# 对于其他模型,传递所有参数
return model_class(
api_key=api_key,
temperature=temperature,
system_prompt=system_prompt,
language=language
)
@classmethod
def get_available_models(cls) -> list[Dict[str, Any]]: