feat: 自主思考分层 — 轻量思考(简单)+深度思考(复杂)双模型
- 新增轻量思考循环 lightThinkLoop (默认60s间隔,快速模型)
- 轻量思考用极简 prompt 做快速状态检查
- 检测到「需要深思」时自动唤醒深度思考 performThink("light_wake")
- 环境变量: LIGHT_THINK_ENABLED / LIGHT_THINK_INTERVAL_SEC
- 轻量思考跳过活跃用户 (30s内有消息) 和重复触发 (10s内)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -128,6 +128,10 @@ type Thinker struct {
|
||||
// 默认 300 秒(5 分钟),设为 0 则禁用定时触发
|
||||
thinkInterval time.Duration
|
||||
|
||||
// 轻量思考(简单思考):高频、快速模型、简单 prompt
|
||||
lightThinkEnabled bool
|
||||
lightThinkInterval time.Duration
|
||||
|
||||
// 静默检测超时:用户多久不说话后昔涟可以主动搭话
|
||||
// 默认 120 秒(2 分钟),设为 0 则禁用静默检测
|
||||
silenceTimeout time.Duration
|
||||
@@ -318,6 +322,9 @@ type ThinkerConfig struct {
|
||||
OfflineThinkGap time.Duration // 两次思考最小间隔 (离线,默认 10 分钟)
|
||||
|
||||
// 平台静默观察
|
||||
LightThinkEnabled bool
|
||||
LightThinkInterval time.Duration // 轻量思考间隔 (默认 60s,0 = 禁用)
|
||||
|
||||
PlatformSilentThinkInterval time.Duration // 平台记忆观察间隔 (默认 600s,0 = 禁用)
|
||||
PlatformChannels []PlatformChannel
|
||||
}
|
||||
@@ -339,6 +346,8 @@ func DefaultThinkerConfig() ThinkerConfig {
|
||||
PostChatDelay: getEnvDuration("THINK_POST_CHAT_DELAY_SEC", 5),
|
||||
MinThinkGap: getEnvDuration("THINK_MIN_GAP_SEC", 30),
|
||||
OfflineThinkGap: getEnvDuration("THINK_OFFLINE_GAP_SEC", 600),
|
||||
LightThinkEnabled: getEnvBool("LIGHT_THINK_ENABLED", true),
|
||||
LightThinkInterval: getEnvDuration("LIGHT_THINK_INTERVAL_SEC", 60),
|
||||
PlatformSilentThinkInterval: getEnvDuration("PLATFORM_THINK_INTERVAL_SEC", 600),
|
||||
PlatformChannels: ParsePlatformChannels(os.Getenv("PLATFORM_CHANNELS")),
|
||||
}
|
||||
@@ -379,6 +388,8 @@ func NewThinker(
|
||||
toolAdapter: toolAdapter,
|
||||
iotClient: iotClient,
|
||||
thinkInterval: cfg.ThinkInterval,
|
||||
lightThinkEnabled: cfg.LightThinkEnabled,
|
||||
lightThinkInterval: cfg.LightThinkInterval,
|
||||
silenceTimeout: cfg.SilenceTimeout,
|
||||
proactiveMsgMinGap: getEnvDuration("PROACTIVE_MSG_MIN_GAP_SEC", 1800),
|
||||
postChatDelay: cfg.PostChatDelay,
|
||||
@@ -426,6 +437,10 @@ func (t *Thinker) Start() {
|
||||
t.wg.Add(1)
|
||||
go t.periodicThinkLoop()
|
||||
}
|
||||
if t.lightThinkEnabled && t.lightThinkInterval > 0 {
|
||||
t.wg.Add(1)
|
||||
go t.lightThinkLoop()
|
||||
}
|
||||
|
||||
// 启动平台静默观察循环
|
||||
if len(t.platformChannels) > 0 && t.platformThinkInterval > 0 {
|
||||
@@ -689,6 +704,93 @@ func (t *Thinker) performPlatformObservation() {
|
||||
log.Printf("[后台思考] 平台观察摘要已生成 (长度=%d, 需要关注=%v)", len(result.Summary), result.NeedsAttention)
|
||||
}
|
||||
|
||||
// lightThinkLoop runs frequent lightweight thinking cycles using a fast model.
|
||||
// It checks for urgent matters and can wake the deep thinker when needed.
|
||||
func (t *Thinker) lightThinkLoop() {
|
||||
defer t.wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Printf("[后台思考] 轻量思考循环 panic 恢复: %v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf("[后台思考] 轻量思考已启动 (间隔=%v)", t.lightThinkInterval)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-t.stopCh:
|
||||
log.Println("[后台思考] 轻量思考已停止")
|
||||
return
|
||||
case <-time.After(t.lightThinkInterval):
|
||||
t.mu.Lock()
|
||||
sinceLastUser := time.Since(t.lastUserMessage)
|
||||
sinceLastThink := time.Since(t.lastThinkTime)
|
||||
t.mu.Unlock()
|
||||
|
||||
// Skip if user was active recently (last 30s).
|
||||
if sinceLastUser < 30*time.Second {
|
||||
continue
|
||||
}
|
||||
// Skip if deep think just ran.
|
||||
if sinceLastThink < 10*time.Second {
|
||||
continue
|
||||
}
|
||||
|
||||
t.performLightThink()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// performLightThink runs a single lightweight thinking cycle using the fast model.
|
||||
func (t *Thinker) performLightThink() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Build a minimal system prompt.
|
||||
now := time.Now()
|
||||
systemPrompt := fmt.Sprintf(`你是昔涟。这是一次快速的内心检查(%s)。
|
||||
|
||||
请用一句话在心里判断:
|
||||
1. 开拓者有什么需要立即关注的事情吗?(提醒、设备状态、情绪变化)
|
||||
2. 如果有紧急事项,输出【需要深思】标记;如果一切正常,输出一个字的感受即可。
|
||||
|
||||
注意:只需要极简判断,不要长篇反思。`, now.Format("15:04"))
|
||||
|
||||
userPrompt := "快速检查一下。"
|
||||
messages := []model.LLMMessage{
|
||||
{Role: model.RoleSystem, Content: systemPrompt},
|
||||
{Role: model.RoleUser, Content: userPrompt},
|
||||
}
|
||||
|
||||
// Use fast model (toolAdapter) for light think.
|
||||
resp, err := t.toolAdapter.Chat(ctx, messages)
|
||||
if err != nil {
|
||||
log.Printf("[轻量思考] LLM调用失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
content := resp.Content
|
||||
if content == "" {
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[轻量思考] %s", strings.TrimSpace(content))
|
||||
|
||||
// Check if deep think should be woken.
|
||||
if strings.Contains(content, "【需要深思】") {
|
||||
log.Println("[轻量思考] 检测到【需要深思】,唤醒深度思考...")
|
||||
t.mu.Lock()
|
||||
canDeep := time.Since(t.lastThinkTime) >= t.minThinkGap
|
||||
t.mu.Unlock()
|
||||
if canDeep {
|
||||
t.performThink("light_wake")
|
||||
} else {
|
||||
log.Println("[轻量思考] 距上次深度思考太近,跳过唤醒")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// periodicThinkLoop 周期性自主思考循环
|
||||
// periodicThinkLoop 周期性自主思考循环
|
||||
//
|
||||
// 使用动态间隔:若配置了 ScheduleLoader,每次循环根据当前时段计算间隔;
|
||||
|
||||
Reference in New Issue
Block a user