feat(backthink): 自主思考强化 P1——主会话上下文+owner env+去压制(design/20)
backthink 从"心跳空转(独立sess-backthink+写死nothing to report宏)"改成"看得见主人、 能读写记忆、能调工具":think 读主会话最近20条(history.Recent,倒序映射)作为上下文 + 重写引导prompt(温暖/有针对性/主动表达,删掉 Do not produce chat-style message) + 注入 loop.OwnerEnv(MemWritable=true/ActorOwner/全工具)。 - context.go: mainContext/recentProvider/thinkInput/guidancePrompt - thinker.go: LoopThinker 加 recent;Think 读主会话上下文+OwnerEnv+MutedBroadcast - wire.go: NewLoopThinker(a.loop, a.history) - 刻意偏离(安全): loop.Run session id 仍用 sess-backthink(不写"web"),避免与用户实时回合 checkpoint/中断窗口复用污染;上下文来源+运行环境=主会话/owner env,目标达成。红线靠actor元数据。 - 测试: prompt无压制/有鼓励;主会话消息映射;nil退化;端到端Think(owner env 生效) 验收: build/vet/test 全绿+windows/darwin交叉编译绿. P2(主动推送+渠道选择)后置.
This commit is contained in:
1 parent
44e7a5c2c5
commit
93aff2fea5
5 files changed
+360
-24
No files matched your search
@@ -5,43 +5,43 @@ import (
|
||||
"fmt"
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/loop"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
|
||||
)
|
||||
|
||||
// LoopThinker adapts a *loop.Loop into a Thinker. It is the production wiring
|
||||
// that lets a background pass drive the full tool loop (memory injection, model
|
||||
// steps, tool calls such as IoT/calendar/reminders) without the service knowing
|
||||
// the loop's concrete shape.
|
||||
// that lets an autonomous background pass drive the full tool loop (memory
|
||||
// injection, model steps, tool calls such as IoT/calendar/reminders) while seeing
|
||||
// the main session's recent conversation and running under the owner environment.
|
||||
type LoopThinker struct {
|
||||
loop *loop.Loop
|
||||
loop *loop.Loop
|
||||
recent recentProvider
|
||||
}
|
||||
|
||||
// NewLoopThinker wraps l as a Thinker.
|
||||
func NewLoopThinker(l *loop.Loop) *LoopThinker { return &LoopThinker{loop: l} }
|
||||
// NewLoopThinker wraps l as a Thinker over the given recent-messages provider
|
||||
// (*history.Store in production; nil degrades the think to the guidance prompt
|
||||
// alone, see mainContext).
|
||||
func NewLoopThinker(l *loop.Loop, recent recentProvider) *LoopThinker {
|
||||
return &LoopThinker{loop: l, recent: recent}
|
||||
}
|
||||
|
||||
// Think runs one unattended think through the wrapped loop and returns the
|
||||
// conclusion text. It returns ErrNoLoop when no loop was injected.
|
||||
// conclusion text. It inherits the main session's recent conversation as input
|
||||
// context and injects the owner session environment (MemWritable=true, ActorOwner,
|
||||
// full tool set) so the think can read/write memory and call tools. The loop's
|
||||
// Run session id is the service's own (not the main session id) so the think never
|
||||
// collides with the live main session's durable checkpoint store (design/20).
|
||||
// It returns ErrNoLoop when no loop was injected.
|
||||
func (t *LoopThinker) Think(ctx context.Context, sessionID, trigger string) (string, error) {
|
||||
if t.loop == nil {
|
||||
return "", ErrNoLoop
|
||||
}
|
||||
messages := []model.Message{model.TextMessage(model.RoleUser, backgroundPrompt(trigger))}
|
||||
recent := mainContext(ctx, t.recent)
|
||||
messages := thinkInput(recent, trigger)
|
||||
envCtx := loop.WithSessionEnv(ctx, loop.OwnerEnv())
|
||||
// Mute UI broadcast: background reflection must not leak its intermediate
|
||||
// reasoning into the user-facing chat stream (it only needs the conclusion).
|
||||
res, err := t.loop.Run(loop.WithMutedBroadcast(ctx), sessionID, messages)
|
||||
res, err := t.loop.Run(loop.WithMutedBroadcast(envCtx), sessionID, messages)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("backthink: think: %w", err)
|
||||
}
|
||||
return res.Text, nil
|
||||
}
|
||||
|
||||
// backgroundPrompt is the instruction handed to the runtime for one unattended
|
||||
// thought. It explicitly avoids asking for a chat-style message to the user.
|
||||
func backgroundPrompt(trigger string) string {
|
||||
return "[background autonomous reflection]\n" +
|
||||
"Trigger: " + trigger + "\n" +
|
||||
"Review recent context, device states, calendar and reminders. Decide " +
|
||||
"whether anything is worth proactively telling the owner. If nothing " +
|
||||
"matters, conclude \"nothing to report\". Keep the conclusion to one or " +
|
||||
"two sentences. Do not produce a chat-style message to the user."
|
||||
}
|
||||
Reference in new issue
Block a user