fix: 后台思考使用深度思考模型 + 主动消息推送冷却优化

- thinker.go: Round 0 优先调用 llmAdapter(deepseek-v4-pro),失败回退 toolAdapter
- thinker.go: RecordUserMessage 重置 lastProactiveMsgTime,活跃对话中允许推送
- proactive_decision.go: MinGap low 30→15min, medium 10→5min, high 2→1min; 小时上限 3→5

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 17:10:28 +08:00
parent 79af5c15c3
commit 5325eaca3f
2 changed files with 78 additions and 57 deletions
@@ -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,
}
}
+74 -53
View File
@@ -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
}
}