diff --git a/backend/ai-core/internal/background/proactive_decision.go b/backend/ai-core/internal/background/proactive_decision.go index bcd548d..4098456 100644 --- a/backend/ai-core/internal/background/proactive_decision.go +++ b/backend/ai-core/internal/background/proactive_decision.go @@ -36,11 +36,11 @@ func DefaultProactiveGuard() *ProactiveGuard { QuietHoursStart: 23, QuietHoursEnd: 7, MinGapByUrgency: map[string]time.Duration{ - "low": 30 * time.Minute, - "medium": 10 * time.Minute, - "high": 2 * time.Minute, + "low": 15 * time.Minute, + "medium": 5 * time.Minute, + "high": 1 * time.Minute, }, - MaxMessagesPerHour: 3, + MaxMessagesPerHour: 5, } } diff --git a/backend/ai-core/internal/background/thinker.go b/backend/ai-core/internal/background/thinker.go index 01fe809..334e64f 100644 --- a/backend/ai-core/internal/background/thinker.go +++ b/backend/ai-core/internal/background/thinker.go @@ -323,6 +323,8 @@ func (t *Thinker) RecordUserMessage(sessionID string) { if sessionID != "" { t.activeSessionID = sessionID } + // 用户主动发消息时重置主动消息推送冷却——活跃对话中应允许昔涟回复 + t.lastProactiveMsgTime = time.Time{} t.mu.Unlock() // 重置静默检测定时器 @@ -594,69 +596,88 @@ func (t *Thinker) performThink(triggerReason string) { // 6. 准备工具定义(通过自主工具策略过滤) openAITools := t.filterToolsByPolicy(t.buildOpenAITools()) - // 7. 调用 LLM(支持工具调用,策略限制轮数) + // 7. 调用 LLM — 优先使用深度思考模型,工具阶段回退到工具模型 maxToolRounds := t.autoToolPolicy.MaxToolCallsPerRound var finalContent string var totalToolCalls int var toolCallRecords []map[string]interface{} - for round := 0; round <= maxToolRounds; round++ { - resp, err := t.toolAdapter.ChatWithTools(ctx, messages, openAITools) - if err != nil { - log.Printf("[后台思考] LLM调用失败 (round=%d): %v", round, err) - return - } + // Round 0: 深度思考模型(优先),失败时回退到工具模型 + resp, err := t.llmAdapter.ChatWithTools(ctx, messages, openAITools) + if err != nil { + log.Printf("[后台思考] 深度思考模型调用失败,回退到工具模型: %v", err) + resp, err = t.toolAdapter.ChatWithTools(ctx, messages, openAITools) + } + if err != nil { + log.Printf("[后台思考] LLM调用失败: %v", err) + return + } - if len(resp.ToolCalls) == 0 { - finalContent = resp.Content - break - } - - log.Printf("[后台思考] LLM 请求 %d 个工具调用 (round=%d)", len(resp.ToolCalls), round) - - assistantMsg := model.LLMMessage{ - Role: model.RoleAssistant, - Content: resp.Content, - ToolCalls: resp.ToolCalls, - ReasoningContent: resp.ReasoningContent, - } - messages = append(messages, assistantMsg) - - for _, tc := range resp.ToolCalls { - var args map[string]interface{} - if err := json.Unmarshal([]byte(tc.Arguments), &args); err != nil { - log.Printf("[后台思考] 工具 %s 参数解析失败: %v", tc.Name, err) - args = make(map[string]interface{}) + if len(resp.ToolCalls) == 0 { + finalContent = resp.Content + } else { + // 深度思考模型请求了工具调用,进入工具执行循环 + for round := 0; round <= maxToolRounds; round++ { + if round > 0 { + // 后续轮次使用工具模型 + resp, err = t.toolAdapter.ChatWithTools(ctx, messages, openAITools) + if err != nil { + log.Printf("[后台思考] 工具模型调用失败 (round=%d): %v", round, err) + return + } } - result, execErr := t.toolRegistry.Execute(ctx, tc.Name, args) - if execErr != nil { - log.Printf("[后台思考] 工具 %s 执行失败: %v", tc.Name, execErr) - } - - resultJSON, _ := json.Marshal(result) - messages = append(messages, model.LLMMessage{ - Role: model.RoleTool, - Content: string(resultJSON), - ToolCallID: tc.ID, - }) - - totalToolCalls++ - toolCallRecords = append(toolCallRecords, map[string]interface{}{ - "name": tc.Name, - "args": args, - }) - } - - if round == maxToolRounds { - finalResp, finalErr := t.llmAdapter.Chat(ctx, messages) - if finalErr != nil { - log.Printf("[后台思考] 最终总结调用失败: %v", finalErr) + if round > 0 && len(resp.ToolCalls) == 0 { finalContent = resp.Content - } else { - finalContent = finalResp.Content + break + } + + log.Printf("[后台思考] LLM 请求 %d 个工具调用 (round=%d)", len(resp.ToolCalls), round) + + assistantMsg := model.LLMMessage{ + Role: model.RoleAssistant, + Content: resp.Content, + ToolCalls: resp.ToolCalls, + ReasoningContent: resp.ReasoningContent, + } + messages = append(messages, assistantMsg) + + for _, tc := range resp.ToolCalls { + var args map[string]interface{} + if err := json.Unmarshal([]byte(tc.Arguments), &args); err != nil { + log.Printf("[后台思考] 工具 %s 参数解析失败: %v", tc.Name, err) + args = make(map[string]interface{}) + } + + result, execErr := t.toolRegistry.Execute(ctx, tc.Name, args) + if execErr != nil { + log.Printf("[后台思考] 工具 %s 执行失败: %v", tc.Name, execErr) + } + + resultJSON, _ := json.Marshal(result) + messages = append(messages, model.LLMMessage{ + Role: model.RoleTool, + Content: string(resultJSON), + ToolCallID: tc.ID, + }) + + totalToolCalls++ + toolCallRecords = append(toolCallRecords, map[string]interface{}{ + "name": tc.Name, + "args": args, + }) + } + + if round == maxToolRounds { + finalResp, finalErr := t.llmAdapter.Chat(ctx, messages) + if finalErr != nil { + log.Printf("[后台思考] 最终总结调用失败: %v", finalErr) + finalContent = resp.Content + } else { + finalContent = finalResp.Content + } + break } - break } }