mirror of
https://github.com/RuoJi6/ARTEX.git
synced 2026-10-27 17:03:49 +08:00
Merge branch 'feat/noa-experimental':noa 实验性上下文压缩
This commit is contained in:
commit
95bcd4ef9c
13 files changed
+181
-6
No files matched your search
@@ -33,6 +33,7 @@ type ChatAgent struct {
|
||||
webSearch WebSearchOpts
|
||||
guard *guard.Guard // optional; nil disables intercept hooks for chat
|
||||
nonStreamingFn func() bool // resolver: use non-streaming (Complete) path? (nil = streaming)
|
||||
noaEnabledFn func() bool // resolver: use experimental noa compaction? (nil = off)
|
||||
maxTokensFn func() int // resolver: per-reply output cap (nil/0 = send no cap)
|
||||
}
|
||||
|
||||
@@ -46,6 +47,11 @@ func (c *ChatAgent) SetNonStreaming(fn func() bool) { c.nonStreamingFn = fn }
|
||||
|
||||
func (c *ChatAgent) nonStreaming() bool { return c.nonStreamingFn != nil && c.nonStreamingFn() }
|
||||
|
||||
// SetNoaEnabled wires a resolver deciding whether chat runs use the experimental
|
||||
// noa context-compression mechanism. nil/unset = off (built-in compaction). Read
|
||||
// per run so the settings toggle takes effect without rebuilding the agent.
|
||||
func (c *ChatAgent) SetNoaEnabled(fn func() bool) { c.noaEnabledFn = fn }
|
||||
|
||||
// SetMaxTokens wires a resolver for the per-reply output cap. nil/unset or 0 =
|
||||
// send no cap and let the endpoint decide. Read per run, like nonStreaming.
|
||||
func (c *ChatAgent) SetMaxTokens(fn func() int) { c.maxTokensFn = fn }
|
||||
@@ -161,6 +167,8 @@ func (c *ChatAgent) Chat(ctx context.Context, agentKey, sessionID, message strin
|
||||
opts.Transcript = c.tx
|
||||
opts.SessionID = sessionID
|
||||
}
|
||||
// 实验功能:开启后由 noa 接管上下文压缩(归档集中在 <workDir>/noa/<SessionID> 下,持久)。
|
||||
enableNoa(&opts, c.noaEnabledFn, c.workDir, "chat-"+sessionID, noaWarn("chat-"+sessionID))
|
||||
ctx = attachSideCapture(ctx, &opts)
|
||||
s := agentcore.NewSession(opts)
|
||||
defer s.Close()
|
||||
|
||||
@@ -31,9 +31,15 @@ type MainAgent struct {
|
||||
workDir string // shared work dir (surfaced in prompt as artifact-output target)
|
||||
steerWork func(intentID int64, msg string) error // engine callback: steer a running work (nil = off)
|
||||
nonStreamingFn func() bool // resolver: use non-streaming (Complete) path? (nil = streaming)
|
||||
noaEnabledFn func() bool // resolver: use experimental noa compaction? (nil = off)
|
||||
maxTokensFn func() int // resolver: per-reply output cap (nil/0 = send no cap)
|
||||
}
|
||||
|
||||
// SetNoaEnabled wires a resolver deciding whether runs use the experimental noa
|
||||
// context-compression mechanism. nil/unset = off (built-in compaction). Read per
|
||||
// run so the settings toggle takes effect without rebuilding the agent.
|
||||
func (m *MainAgent) SetNoaEnabled(fn func() bool) { m.noaEnabledFn = fn }
|
||||
|
||||
// SetNonStreaming wires a resolver deciding whether runs use the non-streaming
|
||||
// model path (true = non-streaming). nil/unset = streaming (default).
|
||||
func (m *MainAgent) SetNonStreaming(fn func() bool) { m.nonStreamingFn = fn }
|
||||
@@ -167,6 +173,13 @@ func (m *MainAgent) Chat(ctx context.Context, taskID int64, mainSeg int, as *db.
|
||||
opts.SessionID = fmt.Sprintf("exp%d-main-s%d", ts.ID(), mainSeg)
|
||||
}
|
||||
}
|
||||
// 实验功能:开启后由 noa 接管上下文压缩(归档集中在 <workDir>/noa/<SessionID> 下,持久)。
|
||||
// session id 与 transcript 同规则(分段感知),使归档与恢复对齐。
|
||||
noaSession := fmt.Sprintf("exp%d-main", ts.ID())
|
||||
if mainSeg > 0 {
|
||||
noaSession = fmt.Sprintf("exp%d-main-s%d", ts.ID(), mainSeg)
|
||||
}
|
||||
enableNoa(&opts, m.noaEnabledFn, m.workDir, noaSession, noaWarn(noaSession))
|
||||
ctx = attachSideCapture(ctx, &opts)
|
||||
s := agentcore.NewSession(opts)
|
||||
defer s.Close()
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Autumn-27/norma/agentcore"
|
||||
"github.com/Autumn-27/norma/noaadapter"
|
||||
)
|
||||
|
||||
// noaWarn returns a diagnostics sink tagging non-fatal noa messages with the
|
||||
// session, routed through the package logger (agents have no per-instance one).
|
||||
func noaWarn(session string) func(string) {
|
||||
return func(msg string) { log.Printf("[noa] %s: %s", session, msg) }
|
||||
}
|
||||
|
||||
// noa 是 norma v0.4.0 引入的「模型驱动上下文压缩」机制,作为平台实验功能由用户在
|
||||
// 系统设置中开关。它与内置 compaction 互斥:noaadapter.Enable 是唯一入口,一次挂上
|
||||
// 上下文接管器(Compactor)、Compress 工具与三段常驻提示词,不调用 Enable 即为关闭
|
||||
// (内置 compaction 照常工作)。开关由每个 agent 注入的 noaEnabledFn 解析,每 run 读
|
||||
// 一次,故切换只影响之后启动的 run,无需重建 agent。
|
||||
|
||||
// enableNoa 在解析器报告开启时把 noa 接入 opts。archiveRoot 是压缩原文的持久化基目录
|
||||
// (取全局 workDir,各 agent 统一落在 <workDir>/noa 下,不随任务/意图目录分散),sessionID
|
||||
// 命名其下的归档子目录(全局唯一,故同一基目录内不冲突)。
|
||||
//
|
||||
// noa 是实验功能:接入失败不得中断真实任务。发生错误时经 onWarn 上报并回退内置压缩。
|
||||
// 启用成功时清掉 opts.Compaction,避免 agentcore 因「两个上下文管理器同时设置」告警。
|
||||
func enableNoa(opts *agentcore.Options, enabled func() bool, archiveRoot, sessionID string, onWarn func(string)) {
|
||||
if enabled == nil || !enabled() {
|
||||
return
|
||||
}
|
||||
if opts.OnWarn == nil {
|
||||
opts.OnWarn = onWarn
|
||||
}
|
||||
if err := noaadapter.Enable(opts, noaadapter.Options{
|
||||
ArchiveBaseDir: filepath.Join(archiveRoot, "noa"),
|
||||
SessionID: sessionID,
|
||||
OnWarn: onWarn,
|
||||
}); err != nil {
|
||||
if onWarn != nil {
|
||||
onWarn("noa 压缩启用失败,回退内置压缩:" + err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
// Compactor 覆盖 Compaction,但两者并存时 agentcore 每次会告警;明确清掉。
|
||||
opts.Compaction = nil
|
||||
}
|
||||
@@ -36,6 +36,7 @@ type Planner struct {
|
||||
workDir string // shared work dir (surfaced in prompt as artifact-output target)
|
||||
injectConstraints func() bool // resolver: inject task operation constraints into system prompt? (nil = yes)
|
||||
nonStreamingFn func() bool // resolver: use non-streaming (Complete) path? (nil = streaming)
|
||||
noaEnabledFn func() bool // resolver: use experimental noa compaction? (nil = off)
|
||||
maxTokensFn func() int // resolver: per-reply output cap (nil/0 = send no cap)
|
||||
compactor *Compactor // cold-node compaction (§7); nil = disabled
|
||||
|
||||
@@ -64,6 +65,11 @@ func (p *Planner) SetNonStreaming(fn func() bool) { p.nonStreamingFn = fn }
|
||||
|
||||
func (p *Planner) nonStreaming() bool { return p.nonStreamingFn != nil && p.nonStreamingFn() }
|
||||
|
||||
// SetNoaEnabled wires a resolver deciding whether runs use the experimental noa
|
||||
// context-compression mechanism. nil/unset = off (built-in compaction). Read per
|
||||
// run so the settings toggle takes effect without rebuilding the agent.
|
||||
func (p *Planner) SetNoaEnabled(fn func() bool) { p.noaEnabledFn = fn }
|
||||
|
||||
// SetMaxTokens wires a resolver for the per-reply output cap. nil/unset or 0 =
|
||||
// send no cap and let the endpoint decide. Read per run, like nonStreaming.
|
||||
func (p *Planner) SetMaxTokens(fn func() int) { p.maxTokensFn = fn }
|
||||
@@ -430,6 +436,9 @@ func (p *Planner) Plan(ctx context.Context, taskID int64, as *db.AssetStore, ts
|
||||
opts.Transcript = p.tx
|
||||
opts.SessionID = fmt.Sprintf("exp%d-planner", ts.ID())
|
||||
}
|
||||
// 实验功能:开启后由 noa 接管上下文压缩(归档集中在 <workDir>/noa/<SessionID> 下,持久)。
|
||||
noaSession := fmt.Sprintf("exp%d-planner", ts.ID())
|
||||
enableNoa(&opts, p.noaEnabledFn, p.workDir, noaSession, noaWarn(noaSession))
|
||||
// 态势(刚完成的意图 + 完整图)现在拼进本轮 user 输入(见下方 input)。user 里还有
|
||||
// 指令 + 跨唤醒待办(todo 是模型自己的规划便签,可再生,放 user 即可)。
|
||||
// 开场白按「本轮有无具体变动」分两种:有变动 → 指向下方【实际变动】块;无变动
|
||||
|
||||
@@ -78,6 +78,10 @@ type Worker struct {
|
||||
// path. Read per run so a profile/task toggle takes effect without rebuilding
|
||||
// the agent. nil = streaming (default).
|
||||
nonStreamingFn func() bool
|
||||
// noaEnabledFn resolves whether this run uses the experimental noa context-
|
||||
// compression mechanism. Read per run, like nonStreaming. nil = off (built-in
|
||||
// compaction).
|
||||
noaEnabledFn func() bool
|
||||
// maxTokensFn resolves the per-reply output cap in tokens, on the same
|
||||
// per-run basis. nil or 0 = send no cap and let the endpoint decide.
|
||||
maxTokensFn func() int
|
||||
@@ -114,6 +118,11 @@ func (w *Worker) SetNonStreaming(fn func() bool) { w.nonStreamingFn = fn }
|
||||
|
||||
func (w *Worker) nonStreaming() bool { return w.nonStreamingFn != nil && w.nonStreamingFn() }
|
||||
|
||||
// SetNoaEnabled wires a resolver deciding whether runs use the experimental noa
|
||||
// context-compression mechanism. nil/unset = off (built-in compaction). Read per
|
||||
// run so the settings toggle takes effect without rebuilding the agent.
|
||||
func (w *Worker) SetNoaEnabled(fn func() bool) { w.noaEnabledFn = fn }
|
||||
|
||||
// SetMaxTokens wires a resolver for the per-reply output cap. nil/unset or 0 =
|
||||
// send no cap and let the endpoint decide. Read per run, like nonStreaming.
|
||||
func (w *Worker) SetMaxTokens(fn func() int) { w.maxTokensFn = fn }
|
||||
@@ -481,6 +490,9 @@ func (w *Worker) execute(ctx context.Context, name string, taskID int64, as *db.
|
||||
input = "开始执行 system 里领到的意图:只做它、只产生事实、assets、finding、做完即停。"
|
||||
}
|
||||
|
||||
// 实验功能:开启后由 noa 接管上下文压缩(归档集中在 <workDir>/noa/<SessionID> 下,持久)。
|
||||
noaSession := WorkerSessionID(ts.ID(), intent.ID)
|
||||
enableNoa(&opts, w.noaEnabledFn, w.workDir, noaSession, noaWarn(noaSession))
|
||||
ctx = attachSideCapture(ctx, &opts)
|
||||
s := agentcore.NewSession(opts)
|
||||
defer s.Close() // release the session's background-task manager (temp dir + processes)
|
||||
|
||||
Reference in new issue
Block a user