diff --git a/config/models.json b/config/models.json index 8d0e24d..fe35fd8 100644 --- a/config/models.json +++ b/config/models.json @@ -116,7 +116,7 @@ "name": "Doubao-Seed-1.6", "provider": "doubao", "supportsMultimodal": true, - "isReasoning": false, + "isReasoning": true, "version": "latest", "description": "支持auto/thinking/non-thinking三种思考模式、支持多模态、256K长上下文" } diff --git a/models/doubao.py b/models/doubao.py index 6ac80b7..68d7925 100644 --- a/models/doubao.py +++ b/models/doubao.py @@ -27,6 +27,7 @@ class DoubaoModel(BaseModel): self.model_name = model_name or self.get_model_identifier() self.base_url = api_base_url or "https://ark.cn-beijing.volces.com/api/v3" self.max_tokens = 4096 # 默认最大输出token数 + self.reasoning_config = None # 推理配置,类似于AnthropicModel def get_default_system_prompt(self) -> str: return """你是一个专业的问题分析专家。当看到问题图片时: @@ -85,11 +86,24 @@ class DoubaoModel(BaseModel): "role": "user", "content": user_content }) + + # 处理推理配置 + thinking = { + "type": "auto" # 默认值 + } + if hasattr(self, 'reasoning_config') and self.reasoning_config: + # 从reasoning_config中获取thinking_mode + thinking_mode = self.reasoning_config.get('thinking_mode', "auto") + thinking = { + "type": thinking_mode + } + # 构建请求数据 data = { "model": self.get_actual_model_name(), "messages": messages, + "thinking": thinking, "temperature": self.temperature, "max_tokens": self.max_tokens, "stream": True @@ -226,11 +240,24 @@ class DoubaoModel(BaseModel): "content": user_content } ] + + # 处理推理配置 + thinking = { + "type": "auto" # 默认值 + } + + if hasattr(self, 'reasoning_config') and self.reasoning_config: + # 从reasoning_config中获取thinking_mode + thinking_mode = self.reasoning_config.get('thinking_mode', "auto") + thinking = { + "type": thinking_mode + } # 构建请求数据 data = { "model": self.get_actual_model_name(), "messages": messages, + "thinking": thinking, "temperature": self.temperature, "max_tokens": self.max_tokens, "stream": True diff --git a/static/js/settings.js b/static/js/settings.js index 0f87966..b0019c5 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -587,6 +587,13 @@ class SettingsManager { this.updateReasoningOptionUI(settings.reasoningDepth); } + // 加载豆包思考模式设置 + if (settings.doubaoThinkingMode && this.doubaoThinkingModeSelect) { + this.doubaoThinkingModeSelect.value = settings.doubaoThinkingMode; + // 更新豆包思考选项UI + this.updateDoubaoThinkingOptionUI(settings.doubaoThinkingMode); + } + // 加载思考预算百分比 const thinkBudgetPercent = parseInt(settings.thinkBudgetPercent || '50'); if (this.thinkBudgetPercentInput) { @@ -735,6 +742,14 @@ class SettingsManager { this.thinkBudgetGroup.style.display = showThinkBudget ? 'block' : 'none'; } + // 处理豆包深度思考设置显示 + const isDoubaoReasoning = modelInfo.isReasoning && modelInfo.provider === 'doubao'; + + // 只有对豆包推理模型才显示深度思考设置 + if (this.doubaoThinkingGroup) { + this.doubaoThinkingGroup.style.display = isDoubaoReasoning ? 'block' : 'none'; + } + // 控制最大Token设置的显示 // 阿里巴巴模型不支持自定义Token设置 const maxTokensGroup = this.maxTokens ? this.maxTokens.closest('.setting-group') : null; @@ -792,6 +807,7 @@ class SettingsManager { model: this.modelSelect.value, maxTokens: this.maxTokens.value, reasoningDepth: this.reasoningDepthSelect?.value || 'standard', + doubaoThinkingMode: this.doubaoThinkingModeSelect?.value || 'auto', thinkBudgetPercent: this.thinkBudgetPercentInput?.value || '50', temperature: this.temperatureInput.value, language: this.languageInput.value, @@ -850,17 +866,30 @@ class SettingsManager { const reasoningDepth = this.reasoningDepthSelect?.value || 'standard'; const thinkBudgetPercent = parseInt(this.thinkBudgetPercentInput?.value || '50'); + // 获取豆包思考模式设置 + const doubaoThinkingMode = this.doubaoThinkingModeSelect?.value || 'auto'; + // 计算思考预算的实际Token数 const thinkBudget = Math.floor(maxTokens * (thinkBudgetPercent / 100)); // 构建推理配置参数 const reasoningConfig = {}; - if (modelInfo.provider === 'anthropic' && modelInfo.isReasoning) { - if (reasoningDepth === 'extended') { - reasoningConfig.reasoning_depth = 'extended'; - reasoningConfig.think_budget = thinkBudget; - } else { - reasoningConfig.speed_mode = 'instant'; + + // 处理不同模型的推理配置 + if (modelInfo.isReasoning) { + // 对于Anthropic模型 + if (modelInfo.provider === 'anthropic') { + if (reasoningDepth === 'extended') { + reasoningConfig.reasoning_depth = 'extended'; + reasoningConfig.think_budget = thinkBudget; + } else { + reasoningConfig.speed_mode = 'instant'; + } + } + + // 对于豆包模型 + if (modelInfo.provider === 'doubao') { + reasoningConfig.thinking_mode = doubaoThinkingMode; } } @@ -903,6 +932,7 @@ class SettingsManager { proxyPort: this.proxyPortInput.value, mathpixApiKey: mathpixApiKey, ocrSource: this.ocrSource, // 添加OCR源配置 + doubaoThinkingMode: doubaoThinkingMode, // 添加豆包思考模式配置 modelInfo: { supportsMultimodal: modelInfo.supportsMultimodal || false, isReasoning: modelInfo.isReasoning || false, @@ -1231,6 +1261,71 @@ class SettingsManager { // 初始化API密钥编辑功能 this.initApiKeyEditFunctions(); + + // 初始化推理选项事件 + this.initReasoningOptionEvents(); + + // 初始化豆包思考选项事件 + this.initDoubaoThinkingOptionEvents(); + } + + // 初始化推理选项事件 + initReasoningOptionEvents() { + const reasoningOptions = document.querySelectorAll('.reasoning-option'); + reasoningOptions.forEach(option => { + option.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + + const value = option.getAttribute('data-value'); + if (value && this.reasoningDepthSelect) { + // 更新select值 + this.reasoningDepthSelect.value = value; + + // 更新UI + this.updateReasoningOptionUI(value); + + // 保存设置 + this.saveSettings(); + } + }); + }); + } + + // 初始化豆包思考选项事件 + initDoubaoThinkingOptionEvents() { + const doubaoThinkingOptions = document.querySelectorAll('.doubao-thinking-option'); + doubaoThinkingOptions.forEach(option => { + option.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + + const value = option.getAttribute('data-value'); + if (value && this.doubaoThinkingModeSelect) { + // 更新select值 + this.doubaoThinkingModeSelect.value = value; + + // 更新UI + this.updateDoubaoThinkingOptionUI(value); + + // 保存设置 + this.saveSettings(); + } + }); + }); + } + + // 更新豆包思考选项UI + updateDoubaoThinkingOptionUI(value) { + const doubaoThinkingOptions = document.querySelectorAll('.doubao-thinking-option'); + doubaoThinkingOptions.forEach(option => { + const optionValue = option.getAttribute('data-value'); + if (optionValue === value) { + option.classList.add('active'); + } else { + option.classList.remove('active'); + } + }); } // 更新思考预算显示 @@ -2244,6 +2339,10 @@ class SettingsManager { this.thinkBudgetPercentValue = document.getElementById('thinkBudgetPercentValue'); this.thinkBudgetGroup = document.querySelector('.think-budget-group'); + // 豆包深度思考相关元素 + this.doubaoThinkingModeSelect = document.getElementById('doubaoThinkingMode'); + this.doubaoThinkingGroup = document.querySelector('.doubao-thinking-group'); + // Initialize Mathpix inputs this.mathpixAppIdInput = document.getElementById('mathpixAppId'); this.mathpixAppKeyInput = document.getElementById('mathpixAppKey'); diff --git a/static/style.css b/static/style.css index a85ff46..2df0e26 100644 --- a/static/style.css +++ b/static/style.css @@ -2336,6 +2336,122 @@ button:disabled { opacity: 1; } +/* 豆包深度思考控制组件样式 */ +.doubao-thinking-control { + display: flex; + flex-direction: column; + gap: 8px; +} + +.doubao-thinking-label { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 6px; +} + +.doubao-thinking-selector { + display: flex; + gap: 8px; + margin-bottom: 8px; +} + +.doubao-thinking-option { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + padding: 12px 8px; + border-radius: 8px; + background: rgba(0, 0, 0, 0.05); + cursor: pointer; + transition: all 0.2s ease; + border: 2px solid transparent; + position: relative; + overflow: hidden; + min-height: 80px; + justify-content: center; +} + +.doubao-thinking-option::before { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 3px; + background: linear-gradient(to right, var(--primary-color), transparent); + opacity: 0; + transition: opacity 0.3s ease; +} + +.doubao-thinking-option:hover { + transform: translateY(-2px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.doubao-thinking-option.active { + background: rgba(var(--primary-rgb), 0.1); + border-color: var(--primary-color); +} + +.doubao-thinking-option.active::before { + opacity: 1; +} + +.doubao-thinking-option i { + font-size: 1.3rem; + margin-bottom: 6px; + color: var(--primary-color); + opacity: 0.8; + transition: all 0.2s ease; +} + +.doubao-thinking-option .option-name { + font-weight: 600; + font-size: 0.85rem; + margin-bottom: 4px; + text-align: center; +} + +.doubao-thinking-option .option-desc { + font-size: 0.7rem; + opacity: 0.7; + text-align: center; + line-height: 1.2; +} + +.doubao-thinking-option:hover i { + transform: scale(1.1); + opacity: 1; +} + +.doubao-thinking-desc { + display: flex; + flex-direction: column; + gap: 6px; + margin-top: 8px; + padding: 8px; + background: rgba(0, 0, 0, 0.03); + border-radius: 6px; +} + +.doubao-desc-item { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.8rem; + opacity: 0.8; +} + +.doubao-desc-item i { + font-size: 0.9rem; + color: var(--primary-color); + opacity: 0.7; + width: 16px; + text-align: center; +} + /* 思考预算控制组件样式 */ .think-budget-control { display: flex; @@ -2487,6 +2603,18 @@ button:disabled { background: rgba(var(--primary-rgb), 0.2); } +[data-theme="dark"] .doubao-thinking-option { + background: rgba(255, 255, 255, 0.05); +} + +[data-theme="dark"] .doubao-thinking-option.active { + background: rgba(var(--primary-rgb), 0.2); +} + +[data-theme="dark"] .doubao-thinking-desc { + background: rgba(255, 255, 255, 0.03); +} + [data-theme="dark"] .think-value-badge { background: rgba(255, 255, 255, 0.1); } diff --git a/templates/index.html b/templates/index.html index bf1252a..0a2f075 100644 --- a/templates/index.html +++ b/templates/index.html @@ -219,6 +219,49 @@ +
@@ -252,6 +295,7 @@
+