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,
|
QuietHoursStart: 23,
|
||||||
QuietHoursEnd: 7,
|
QuietHoursEnd: 7,
|
||||||
MinGapByUrgency: map[string]time.Duration{
|
MinGapByUrgency: map[string]time.Duration{
|
||||||
"low": 30 * time.Minute,
|
"low": 15 * time.Minute,
|
||||||
"medium": 10 * time.Minute,
|
"medium": 5 * time.Minute,
|
||||||
"high": 2 * time.Minute,
|
"high": 1 * time.Minute,
|
||||||
},
|
},
|
||||||
MaxMessagesPerHour: 3,
|
MaxMessagesPerHour: 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -323,6 +323,8 @@ func (t *Thinker) RecordUserMessage(sessionID string) {
|
|||||||
if sessionID != "" {
|
if sessionID != "" {
|
||||||
t.activeSessionID = sessionID
|
t.activeSessionID = sessionID
|
||||||
}
|
}
|
||||||
|
// 用户主动发消息时重置主动消息推送冷却——活跃对话中应允许昔涟回复
|
||||||
|
t.lastProactiveMsgTime = time.Time{}
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
||||||
// 重置静默检测定时器
|
// 重置静默检测定时器
|
||||||
@@ -594,69 +596,88 @@ func (t *Thinker) performThink(triggerReason string) {
|
|||||||
// 6. 准备工具定义(通过自主工具策略过滤)
|
// 6. 准备工具定义(通过自主工具策略过滤)
|
||||||
openAITools := t.filterToolsByPolicy(t.buildOpenAITools())
|
openAITools := t.filterToolsByPolicy(t.buildOpenAITools())
|
||||||
|
|
||||||
// 7. 调用 LLM(支持工具调用,策略限制轮数)
|
// 7. 调用 LLM — 优先使用深度思考模型,工具阶段回退到工具模型
|
||||||
maxToolRounds := t.autoToolPolicy.MaxToolCallsPerRound
|
maxToolRounds := t.autoToolPolicy.MaxToolCallsPerRound
|
||||||
var finalContent string
|
var finalContent string
|
||||||
var totalToolCalls int
|
var totalToolCalls int
|
||||||
var toolCallRecords []map[string]interface{}
|
var toolCallRecords []map[string]interface{}
|
||||||
|
|
||||||
for round := 0; round <= maxToolRounds; round++ {
|
// Round 0: 深度思考模型(优先),失败时回退到工具模型
|
||||||
resp, err := t.toolAdapter.ChatWithTools(ctx, messages, openAITools)
|
resp, err := t.llmAdapter.ChatWithTools(ctx, messages, openAITools)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[后台思考] LLM调用失败 (round=%d): %v", round, err)
|
log.Printf("[后台思考] 深度思考模型调用失败,回退到工具模型: %v", err)
|
||||||
return
|
resp, err = t.toolAdapter.ChatWithTools(ctx, messages, openAITools)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[后台思考] LLM调用失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if len(resp.ToolCalls) == 0 {
|
if len(resp.ToolCalls) == 0 {
|
||||||
finalContent = resp.Content
|
finalContent = resp.Content
|
||||||
break
|
} else {
|
||||||
}
|
// 深度思考模型请求了工具调用,进入工具执行循环
|
||||||
|
for round := 0; round <= maxToolRounds; round++ {
|
||||||
log.Printf("[后台思考] LLM 请求 %d 个工具调用 (round=%d)", len(resp.ToolCalls), round)
|
if round > 0 {
|
||||||
|
// 后续轮次使用工具模型
|
||||||
assistantMsg := model.LLMMessage{
|
resp, err = t.toolAdapter.ChatWithTools(ctx, messages, openAITools)
|
||||||
Role: model.RoleAssistant,
|
if err != nil {
|
||||||
Content: resp.Content,
|
log.Printf("[后台思考] 工具模型调用失败 (round=%d): %v", round, err)
|
||||||
ToolCalls: resp.ToolCalls,
|
return
|
||||||
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 round > 0 && len(resp.ToolCalls) == 0 {
|
||||||
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
|
finalContent = resp.Content
|
||||||
} else {
|
break
|
||||||
finalContent = finalResp.Content
|
}
|
||||||
|
|
||||||
|
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