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:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user