mirror of
https://github.com/Zippland/Snap-Solver.git
synced 2026-01-19 17:51:12 +08:00
更新DeepSeek模型配置,新增DeepSeek-V3和DeepSeek推理模型,优化API调用逻辑,支持多模态模型的图像分析,改进前端按钮显示逻辑,提升用户体验
This commit is contained in:
@@ -38,15 +38,23 @@
|
||||
"provider": "openai",
|
||||
"supportsMultimodal": false,
|
||||
"isReasoning": true,
|
||||
"version": "不可用",
|
||||
"version": "2025-01-31",
|
||||
"description": "OpenAI的o3-mini模型,支持图像理解和思考过程"
|
||||
},
|
||||
"deepseek-r1": {
|
||||
"deepseek-chat": {
|
||||
"name": "DeepSeek-V3",
|
||||
"provider": "deepseek",
|
||||
"supportsMultimodal": false,
|
||||
"isReasoning": false,
|
||||
"version": "2025-01",
|
||||
"description": "DeepSeek最新大模型,671B MoE模型,支持60 tokens/秒的高速生成"
|
||||
},
|
||||
"deepseek-reasoner": {
|
||||
"name": "DeepSeek-R1",
|
||||
"provider": "deepseek",
|
||||
"supportsMultimodal": false,
|
||||
"isReasoning": true,
|
||||
"version": "不可用",
|
||||
"version": "latest",
|
||||
"description": "DeepSeek推理模型,提供详细思考过程(仅支持文本)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import json
|
||||
import requests
|
||||
import os
|
||||
from typing import Generator
|
||||
from openai import OpenAI
|
||||
from .base import BaseModel
|
||||
|
||||
class DeepSeekModel(BaseModel):
|
||||
def __init__(self, api_key: str, temperature: float = 0.7, system_prompt: str = None, language: str = None, model_name: str = "deepseek-reasoner"):
|
||||
super().__init__(api_key, temperature, system_prompt, language)
|
||||
self.model_name = model_name
|
||||
|
||||
def get_default_system_prompt(self) -> str:
|
||||
return """You are an expert at analyzing questions and providing detailed solutions. When presented with an image of a question:
|
||||
1. First read and understand the question carefully
|
||||
@@ -14,6 +19,11 @@ class DeepSeekModel(BaseModel):
|
||||
5. If there are multiple approaches, explain the most efficient one first"""
|
||||
|
||||
def get_model_identifier(self) -> str:
|
||||
"""根据模型名称返回正确的API标识符"""
|
||||
# 通过模型名称来确定实际的API调用标识符
|
||||
if self.model_name == "deepseek-chat":
|
||||
return "deepseek-chat"
|
||||
# deepseek-reasoner是默认的推理模型名称
|
||||
return "deepseek-reasoner"
|
||||
|
||||
def analyze_text(self, text: str, proxies: dict = None) -> Generator[dict, None, None]:
|
||||
@@ -22,142 +32,365 @@ class DeepSeekModel(BaseModel):
|
||||
# Initial status
|
||||
yield {"status": "started", "content": ""}
|
||||
|
||||
# Configure client with proxy if needed
|
||||
client_args = {
|
||||
"api_key": self.api_key,
|
||||
"base_url": "https://api.deepseek.com"
|
||||
# 保存原始环境变量
|
||||
original_env = {
|
||||
'http_proxy': os.environ.get('http_proxy'),
|
||||
'https_proxy': os.environ.get('https_proxy')
|
||||
}
|
||||
|
||||
if proxies:
|
||||
session = requests.Session()
|
||||
session.proxies = proxies
|
||||
client_args["http_client"] = session
|
||||
|
||||
client = OpenAI(**client_args)
|
||||
try:
|
||||
# 如果提供了代理设置,通过环境变量设置
|
||||
if proxies:
|
||||
if 'http' in proxies:
|
||||
os.environ['http_proxy'] = proxies['http']
|
||||
if 'https' in proxies:
|
||||
os.environ['https_proxy'] = proxies['https']
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model=self.get_model_identifier(),
|
||||
messages=[{
|
||||
'role': 'system',
|
||||
'content': self.system_prompt
|
||||
}, {
|
||||
'role': 'user',
|
||||
'content': text
|
||||
}],
|
||||
stream=True
|
||||
)
|
||||
# 初始化DeepSeek客户端,不再使用session对象
|
||||
client = OpenAI(
|
||||
api_key=self.api_key,
|
||||
base_url="https://api.deepseek.com"
|
||||
)
|
||||
|
||||
for chunk in response:
|
||||
try:
|
||||
if hasattr(chunk.choices[0].delta, 'reasoning_content'):
|
||||
content = chunk.choices[0].delta.reasoning_content
|
||||
if content:
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": content
|
||||
}
|
||||
elif hasattr(chunk.choices[0].delta, 'content'):
|
||||
content = chunk.choices[0].delta.content
|
||||
if content:
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": content
|
||||
}
|
||||
# 添加系统语言指令
|
||||
system_prompt = self.system_prompt
|
||||
language = self.language or '中文'
|
||||
if not any(phrase in system_prompt for phrase in ['Please respond in', '请用', '使用', '回答']):
|
||||
system_prompt = f"{system_prompt}\n\n请务必使用{language}回答。"
|
||||
|
||||
except Exception as e:
|
||||
print(f"Chunk processing error: {str(e)}")
|
||||
continue
|
||||
# 构建请求参数
|
||||
params = {
|
||||
"model": self.get_model_identifier(),
|
||||
"messages": [
|
||||
{
|
||||
'role': 'system',
|
||||
'content': system_prompt
|
||||
},
|
||||
{
|
||||
'role': 'user',
|
||||
'content': text
|
||||
}
|
||||
],
|
||||
"stream": True
|
||||
}
|
||||
|
||||
# 只有非推理模型才设置temperature参数
|
||||
if not self.model_name.endswith('reasoner') and self.temperature is not None:
|
||||
params["temperature"] = self.temperature
|
||||
|
||||
print(f"调用DeepSeek API: {self.get_model_identifier()}, 是否设置温度: {not self.model_name.endswith('reasoner')}")
|
||||
|
||||
# Send completion status
|
||||
yield {
|
||||
"status": "completed",
|
||||
"content": ""
|
||||
}
|
||||
response = client.chat.completions.create(**params)
|
||||
|
||||
# 使用两个缓冲区,分别用于常规内容和思考内容
|
||||
response_buffer = ""
|
||||
thinking_buffer = ""
|
||||
|
||||
for chunk in response:
|
||||
# 打印chunk以调试
|
||||
try:
|
||||
print(f"DeepSeek API返回chunk: {chunk}")
|
||||
except:
|
||||
print("无法打印chunk")
|
||||
|
||||
try:
|
||||
# 处理推理模型的思考内容
|
||||
if hasattr(chunk.choices[0].delta, 'reasoning_content'):
|
||||
content = chunk.choices[0].delta.reasoning_content
|
||||
if content:
|
||||
# 累积思考内容
|
||||
thinking_buffer += content
|
||||
|
||||
# 只在积累一定数量的字符或遇到句子结束标记时才发送
|
||||
if len(content) >= 20 or content.endswith(('.', '!', '?', '。', '!', '?', '\n')):
|
||||
yield {
|
||||
"status": "thinking",
|
||||
"content": thinking_buffer
|
||||
}
|
||||
|
||||
# 处理常规内容
|
||||
elif hasattr(chunk.choices[0].delta, 'content'):
|
||||
content = chunk.choices[0].delta.content
|
||||
if content:
|
||||
# 累积响应内容
|
||||
response_buffer += content
|
||||
print(f"累积响应内容: '{content}', 当前buffer: '{response_buffer}'")
|
||||
|
||||
# 只在积累一定数量的字符或遇到句子结束标记时才发送
|
||||
if len(content) >= 10 or content.endswith(('.', '!', '?', '。', '!', '?', '\n')):
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
# 尝试直接从message内容获取
|
||||
elif hasattr(chunk.choices[0], 'message') and hasattr(chunk.choices[0].message, 'content'):
|
||||
content = chunk.choices[0].message.content
|
||||
if content:
|
||||
response_buffer += content
|
||||
print(f"从message获取内容: '{content}'")
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
# 检查是否有finish_reason,表示生成结束
|
||||
elif hasattr(chunk.choices[0], 'finish_reason') and chunk.choices[0].finish_reason:
|
||||
print(f"生成结束,原因: {chunk.choices[0].finish_reason}")
|
||||
|
||||
# 如果没有内容但有思考内容,把思考内容作为正文显示
|
||||
if not response_buffer and thinking_buffer:
|
||||
response_buffer = thinking_buffer
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"解析响应chunk时出错: {str(e)}")
|
||||
continue
|
||||
|
||||
# 确保发送最终的缓冲内容
|
||||
if thinking_buffer:
|
||||
yield {
|
||||
"status": "thinking_complete",
|
||||
"content": thinking_buffer
|
||||
}
|
||||
|
||||
# 如果推理完成后没有正文内容,则使用思考内容作为最终响应
|
||||
if not response_buffer and thinking_buffer:
|
||||
response_buffer = thinking_buffer
|
||||
|
||||
# 发送最终响应内容
|
||||
if response_buffer:
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
|
||||
# 发送完成状态
|
||||
yield {
|
||||
"status": "completed",
|
||||
"content": response_buffer
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
print(f"DeepSeek API调用出错: {error_msg}")
|
||||
|
||||
# 提供具体的错误信息
|
||||
if "invalid_api_key" in error_msg.lower():
|
||||
error_msg = "DeepSeek API密钥无效,请检查您的API密钥"
|
||||
elif "rate_limit" in error_msg.lower():
|
||||
error_msg = "DeepSeek API请求频率超限,请稍后再试"
|
||||
elif "quota_exceeded" in error_msg.lower():
|
||||
error_msg = "DeepSeek API配额已用完,请续费或等待下个计费周期"
|
||||
|
||||
yield {
|
||||
"status": "error",
|
||||
"error": f"DeepSeek API错误: {error_msg}"
|
||||
}
|
||||
finally:
|
||||
# 恢复原始环境变量
|
||||
for key, value in original_env.items():
|
||||
if value is None:
|
||||
if key in os.environ:
|
||||
del os.environ[key]
|
||||
else:
|
||||
os.environ[key] = value
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
print(f"调用DeepSeek模型时发生错误: {error_msg}")
|
||||
|
||||
if "invalid_api_key" in error_msg.lower():
|
||||
error_msg = "Invalid API key provided"
|
||||
error_msg = "API密钥无效,请检查设置"
|
||||
elif "rate_limit" in error_msg.lower():
|
||||
error_msg = "Rate limit exceeded. Please try again later."
|
||||
error_msg = "API请求频率超限,请稍后再试"
|
||||
|
||||
yield {
|
||||
"status": "error",
|
||||
"error": f"DeepSeek API error: {error_msg}"
|
||||
"error": f"DeepSeek API错误: {error_msg}"
|
||||
}
|
||||
|
||||
def analyze_image(self, image_data: str, proxies: dict = None) -> Generator[dict, None, None]:
|
||||
"""Stream DeepSeek's response for image analysis"""
|
||||
try:
|
||||
# 检查我们是否有支持图像的模型
|
||||
if self.model_name == "deepseek-chat" or self.model_name == "deepseek-reasoner":
|
||||
yield {
|
||||
"status": "error",
|
||||
"error": "当前DeepSeek模型不支持图像分析,请使用Anthropic或OpenAI的多模态模型"
|
||||
}
|
||||
return
|
||||
|
||||
# Initial status
|
||||
yield {"status": "started", "content": ""}
|
||||
|
||||
# Configure client with proxy if needed
|
||||
client_args = {
|
||||
"api_key": self.api_key,
|
||||
"base_url": "https://api.deepseek.com"
|
||||
# 保存原始环境变量
|
||||
original_env = {
|
||||
'http_proxy': os.environ.get('http_proxy'),
|
||||
'https_proxy': os.environ.get('https_proxy')
|
||||
}
|
||||
|
||||
if proxies:
|
||||
session = requests.Session()
|
||||
session.proxies = proxies
|
||||
client_args["http_client"] = session
|
||||
|
||||
client = OpenAI(**client_args)
|
||||
try:
|
||||
# 如果提供了代理设置,通过环境变量设置
|
||||
if proxies:
|
||||
if 'http' in proxies:
|
||||
os.environ['http_proxy'] = proxies['http']
|
||||
if 'https' in proxies:
|
||||
os.environ['https_proxy'] = proxies['https']
|
||||
|
||||
# 检查系统提示词是否已包含语言设置指令
|
||||
system_prompt = self.system_prompt
|
||||
language = self.language or '中文'
|
||||
if not any(phrase in system_prompt for phrase in ['Please respond in', '请用', '使用', '回答']):
|
||||
system_prompt = f"{system_prompt}\n\n请务必使用{language}回答,无论问题是什么语言。即使在分析图像时也请使用{language}回答。"
|
||||
# 初始化DeepSeek客户端,不再使用session对象
|
||||
client = OpenAI(
|
||||
api_key=self.api_key,
|
||||
base_url="https://api.deepseek.com"
|
||||
)
|
||||
|
||||
response = client.chat.completions.create(
|
||||
model=self.get_model_identifier(),
|
||||
messages=[{
|
||||
'role': 'system',
|
||||
'content': system_prompt
|
||||
}, {
|
||||
'role': 'user',
|
||||
'content': f"Here's an image of a question to analyze: data:image/png;base64,{image_data}"
|
||||
}],
|
||||
stream=True
|
||||
)
|
||||
# 检查系统提示词是否已包含语言设置指令
|
||||
system_prompt = self.system_prompt
|
||||
language = self.language or '中文'
|
||||
if not any(phrase in system_prompt for phrase in ['Please respond in', '请用', '使用', '回答']):
|
||||
system_prompt = f"{system_prompt}\n\n请务必使用{language}回答,无论问题是什么语言。即使在分析图像时也请使用{language}回答。"
|
||||
|
||||
for chunk in response:
|
||||
try:
|
||||
if hasattr(chunk.choices[0].delta, 'reasoning_content'):
|
||||
content = chunk.choices[0].delta.reasoning_content
|
||||
if content:
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": content
|
||||
}
|
||||
elif hasattr(chunk.choices[0].delta, 'content'):
|
||||
content = chunk.choices[0].delta.content
|
||||
if content:
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": content
|
||||
}
|
||||
# 构建请求参数
|
||||
params = {
|
||||
"model": self.get_model_identifier(),
|
||||
"messages": [
|
||||
{
|
||||
'role': 'system',
|
||||
'content': system_prompt
|
||||
},
|
||||
{
|
||||
'role': 'user',
|
||||
'content': f"Here's an image of a question to analyze: data:image/png;base64,{image_data}"
|
||||
}
|
||||
],
|
||||
"stream": True
|
||||
}
|
||||
|
||||
# 只有非推理模型才设置temperature参数
|
||||
if not self.model_name.endswith('reasoner') and self.temperature is not None:
|
||||
params["temperature"] = self.temperature
|
||||
|
||||
except Exception as e:
|
||||
print(f"Chunk processing error: {str(e)}")
|
||||
continue
|
||||
response = client.chat.completions.create(**params)
|
||||
|
||||
# 使用两个缓冲区,分别用于常规内容和思考内容
|
||||
response_buffer = ""
|
||||
thinking_buffer = ""
|
||||
|
||||
for chunk in response:
|
||||
# 打印chunk以调试
|
||||
try:
|
||||
print(f"DeepSeek图像API返回chunk: {chunk}")
|
||||
except:
|
||||
print("无法打印chunk")
|
||||
|
||||
try:
|
||||
# 处理推理模型的思考内容
|
||||
if hasattr(chunk.choices[0].delta, 'reasoning_content'):
|
||||
content = chunk.choices[0].delta.reasoning_content
|
||||
if content:
|
||||
# 累积思考内容
|
||||
thinking_buffer += content
|
||||
|
||||
# 只在积累一定数量的字符或遇到句子结束标记时才发送
|
||||
if len(content) >= 20 or content.endswith(('.', '!', '?', '。', '!', '?', '\n')):
|
||||
yield {
|
||||
"status": "thinking",
|
||||
"content": thinking_buffer
|
||||
}
|
||||
# 处理常规内容
|
||||
elif hasattr(chunk.choices[0].delta, 'content'):
|
||||
content = chunk.choices[0].delta.content
|
||||
if content:
|
||||
# 累积响应内容
|
||||
response_buffer += content
|
||||
print(f"累积图像响应内容: '{content}', 当前buffer: '{response_buffer}'")
|
||||
|
||||
# 只在积累一定数量的字符或遇到句子结束标记时才发送
|
||||
if len(content) >= 10 or content.endswith(('.', '!', '?', '。', '!', '?', '\n')):
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
# 尝试直接从message内容获取
|
||||
elif hasattr(chunk.choices[0], 'message') and hasattr(chunk.choices[0].message, 'content'):
|
||||
content = chunk.choices[0].message.content
|
||||
if content:
|
||||
response_buffer += content
|
||||
print(f"从message获取图像内容: '{content}'")
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
# 检查是否有finish_reason,表示生成结束
|
||||
elif hasattr(chunk.choices[0], 'finish_reason') and chunk.choices[0].finish_reason:
|
||||
print(f"图像生成结束,原因: {chunk.choices[0].finish_reason}")
|
||||
|
||||
# 如果没有内容但有思考内容,把思考内容作为正文显示
|
||||
if not response_buffer and thinking_buffer:
|
||||
response_buffer = thinking_buffer
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"解析图像响应chunk时出错: {str(e)}")
|
||||
continue
|
||||
|
||||
# Send completion status
|
||||
yield {
|
||||
"status": "completed",
|
||||
"content": ""
|
||||
}
|
||||
# 确保发送最终的缓冲内容
|
||||
if thinking_buffer:
|
||||
yield {
|
||||
"status": "thinking_complete",
|
||||
"content": thinking_buffer
|
||||
}
|
||||
|
||||
# 如果推理完成后没有正文内容,则使用思考内容作为最终响应
|
||||
if not response_buffer and thinking_buffer:
|
||||
response_buffer = thinking_buffer
|
||||
|
||||
# 发送最终响应内容
|
||||
if response_buffer:
|
||||
yield {
|
||||
"status": "streaming",
|
||||
"content": response_buffer
|
||||
}
|
||||
|
||||
# 发送完成状态
|
||||
yield {
|
||||
"status": "completed",
|
||||
"content": response_buffer
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
print(f"DeepSeek API调用出错: {error_msg}")
|
||||
|
||||
# 提供具体的错误信息
|
||||
if "invalid_api_key" in error_msg.lower():
|
||||
error_msg = "DeepSeek API密钥无效,请检查您的API密钥"
|
||||
elif "rate_limit" in error_msg.lower():
|
||||
error_msg = "DeepSeek API请求频率超限,请稍后再试"
|
||||
|
||||
yield {
|
||||
"status": "error",
|
||||
"error": f"DeepSeek API错误: {error_msg}"
|
||||
}
|
||||
finally:
|
||||
# 恢复原始环境变量
|
||||
for key, value in original_env.items():
|
||||
if value is None:
|
||||
if key in os.environ:
|
||||
del os.environ[key]
|
||||
else:
|
||||
os.environ[key] = value
|
||||
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
if "invalid_api_key" in error_msg.lower():
|
||||
error_msg = "Invalid API key provided"
|
||||
error_msg = "API密钥无效,请检查设置"
|
||||
elif "rate_limit" in error_msg.lower():
|
||||
error_msg = "Rate limit exceeded. Please try again later."
|
||||
error_msg = "API请求频率超限,请稍后再试"
|
||||
|
||||
yield {
|
||||
"status": "error",
|
||||
"error": f"DeepSeek API error: {error_msg}"
|
||||
"error": f"DeepSeek API错误: {error_msg}"
|
||||
}
|
||||
|
||||
@@ -126,6 +126,15 @@ class ModelFactory:
|
||||
temperature=temperature,
|
||||
system_prompt=system_prompt
|
||||
)
|
||||
# 对于DeepSeek模型,传递model_name参数
|
||||
elif "deepseek" in model_name.lower():
|
||||
return model_class(
|
||||
api_key=api_key,
|
||||
temperature=temperature,
|
||||
system_prompt=system_prompt,
|
||||
language=language,
|
||||
model_name=model_name
|
||||
)
|
||||
else:
|
||||
# 对于其他模型,传递所有参数
|
||||
return model_class(
|
||||
|
||||
@@ -698,8 +698,10 @@ class SnapSolver {
|
||||
this.screenshotImg.src = this.croppedImage;
|
||||
this.imagePreview.classList.remove('hidden');
|
||||
this.cropBtn.classList.remove('hidden');
|
||||
this.sendToClaudeBtn.classList.remove('hidden');
|
||||
this.extractTextBtn.classList.remove('hidden');
|
||||
|
||||
// 根据当前选择的模型类型决定显示哪些按钮
|
||||
this.updateImageActionButtons();
|
||||
|
||||
window.uiManager.showToast('Cropping successful');
|
||||
} catch (error) {
|
||||
console.error('Cropping error details:', {
|
||||
@@ -725,8 +727,8 @@ class SnapSolver {
|
||||
this.cropper = null;
|
||||
}
|
||||
this.cropContainer.classList.add('hidden');
|
||||
this.sendToClaudeBtn.classList.add('hidden');
|
||||
this.extractTextBtn.classList.add('hidden');
|
||||
// 取消裁剪时隐藏图像预览和相关按钮
|
||||
this.imagePreview.classList.add('hidden');
|
||||
document.querySelector('.crop-area').innerHTML = '';
|
||||
});
|
||||
}
|
||||
@@ -858,6 +860,17 @@ class SnapSolver {
|
||||
if (this.sendToClaudeBtn.disabled) return;
|
||||
this.sendToClaudeBtn.disabled = true;
|
||||
|
||||
// 获取当前模型设置
|
||||
const settings = window.settingsManager.getSettings();
|
||||
const isMultimodalModel = settings.modelInfo?.supportsMultimodal || false;
|
||||
const modelName = settings.model || '未知';
|
||||
|
||||
if (!isMultimodalModel) {
|
||||
window.uiManager.showToast(`当前选择的模型 ${modelName} 不支持图像分析。请先提取文本或切换到支持多模态的模型。`, 'error');
|
||||
this.sendToClaudeBtn.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.croppedImage) {
|
||||
try {
|
||||
// 清空之前的结果
|
||||
@@ -1068,6 +1081,12 @@ class SnapSolver {
|
||||
// 更新图像操作按钮
|
||||
this.updateImageActionButtons();
|
||||
|
||||
// 确保DOM完全加载后再次更新按钮状态(以防设置未完全加载)
|
||||
setTimeout(() => {
|
||||
this.updateImageActionButtons();
|
||||
console.log('延时更新图像操作按钮完成');
|
||||
}, 1000);
|
||||
|
||||
console.log('SnapSolver initialization complete');
|
||||
}
|
||||
|
||||
@@ -1187,25 +1206,40 @@ class SnapSolver {
|
||||
|
||||
// 新增方法:根据所选模型更新图像操作按钮
|
||||
updateImageActionButtons() {
|
||||
if (!window.settingsManager) return;
|
||||
if (!window.settingsManager) {
|
||||
console.error('Settings manager not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const settings = window.settingsManager.getSettings();
|
||||
const isMultimodalModel = settings.modelInfo?.supportsMultimodal || false;
|
||||
const modelName = settings.model || '未知';
|
||||
|
||||
console.log(`更新图像操作按钮 - 当前模型: ${modelName}, 是否支持多模态: ${isMultimodalModel}`);
|
||||
|
||||
// 对于截图后的操作按钮显示逻辑
|
||||
if (this.sendToClaudeBtn && this.extractTextBtn) {
|
||||
if (!isMultimodalModel) {
|
||||
// 非多模态模型:只显示提取文本按钮,隐藏发送到AI按钮
|
||||
console.log('非多模态模型:隐藏"发送图片至AI"按钮');
|
||||
this.sendToClaudeBtn.classList.add('hidden');
|
||||
this.extractTextBtn.classList.remove('hidden');
|
||||
} else {
|
||||
// 多模态模型:显示两个按钮
|
||||
if (!this.imagePreview.classList.contains('hidden')) {
|
||||
// 只有在有图像时才显示按钮
|
||||
console.log('多模态模型:显示全部按钮');
|
||||
this.sendToClaudeBtn.classList.remove('hidden');
|
||||
this.extractTextBtn.classList.remove('hidden');
|
||||
} else {
|
||||
// 无图像时隐藏所有按钮
|
||||
console.log('无图像:隐藏所有按钮');
|
||||
this.sendToClaudeBtn.classList.add('hidden');
|
||||
this.extractTextBtn.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn('按钮元素不可用');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,6 +434,11 @@ class SettingsManager {
|
||||
this.updateUIBasedOnModelType();
|
||||
this.updateModelVersionDisplay(e.target.value);
|
||||
this.saveSettings();
|
||||
|
||||
// 通知应用更新图像操作按钮
|
||||
if (window.app && typeof window.app.updateImageActionButtons === 'function') {
|
||||
window.app.updateImageActionButtons();
|
||||
}
|
||||
});
|
||||
|
||||
this.temperatureInput.addEventListener('input', (e) => {
|
||||
|
||||
Reference in New Issue
Block a user