feat(settings): 增加实验功能开关,可开启 noa 上下文压缩
系统设置新增「实验功能」区块,内含 noa 模型驱动上下文压缩开关(默认关)。 开启后平台接入的四类 agent(planner / worker / 主 agent / 对话)由 noa 接管 上下文压缩,取代内置 compaction;关闭即恢复内置压缩。 - agent: 新增 enableNoa 共享接入器(noaadapter.Enable 唯一入口,all-or-nothing), 四类 agent 各加 noaEnabledFn 解析器 + SetNoaEnabled,每 run 读一次,切换只影响 之后启动的 run,无需重建 agent。归档落在各 agent 本 run 工作目录下(任务级持久), session id 与 transcript 同规则。启用失败经 onWarn 上报并回退内置压缩,不中断任务。 - server: settings key noa_compaction + Manager 读写;8 处 agent 装配点注入平台级 解析器(server 5 + task_llm 3);GET/PUT /api/settings 增加字段。 - web: 系统设置页新增实验功能卡片与开关(乐观更新、失败回滚),类型与 mock 补字段。 官方默认行为不变:开关默认关闭时 noaadapter.Enable 不被调用,内置 compaction 原样工作。
This commit is contained in:
1 parent
4ae319feca
commit
865d52267d
11 files changed
+177
-1
No files matched your search
@@ -271,6 +271,10 @@ const (
|
||||
// 任务并发上限:开关 + 上限数。默认关闭;开启后默认上限 5(见 defaultConcurrencyLimit)。
|
||||
settingConcurrencyOn = "task_concurrency_enabled"
|
||||
settingConcurrencyLimit = "task_concurrency_limit"
|
||||
// 实验功能:noa 模型驱动上下文压缩(norma v0.4.0)。默认关闭——开启后平台接入的四类
|
||||
// agent(planner/worker/主 agent/对话)由 noa 接管上下文压缩,取代内置 compaction。
|
||||
// 每 run 读一次,切换只影响之后启动的 run。
|
||||
settingNoaCompaction = "noa_compaction"
|
||||
// defaultWebSearchBackend is used when web search is on but no backend was picked.
|
||||
defaultWebSearchBackend = "ddgs"
|
||||
// deepSeekWebSearchBackend borrows the active LLM profile instead of its own
|
||||
@@ -488,6 +492,19 @@ func (m *Manager) SetLLMRecordEnabled(on bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NoaCompactionEnabled reports whether the experimental noa context-compression
|
||||
// mechanism is on (默认关;settings.noa_compaction). Read per agent run via the
|
||||
// injected resolver, so a toggle takes effect on the next run without rebuild.
|
||||
func (m *Manager) NoaCompactionEnabled() bool {
|
||||
return m.pg.GetBool(settingNoaCompaction, false)
|
||||
}
|
||||
|
||||
// SetNoaCompaction persists the noa toggle. Effective on the next agent run —
|
||||
// the resolver reads it per run, so no rebuild is needed.
|
||||
func (m *Manager) SetNoaCompaction(on bool) error {
|
||||
return m.pg.SetBool(settingNoaCompaction, on)
|
||||
}
|
||||
|
||||
// LLMPoolEnabled reports whether LLM failover ("轮询") is on (默认关;
|
||||
// settings.llm_pool_enabled). Read when the provider chain is built (applyLLM),
|
||||
// so a change requires a rebuild — putSettings does that.
|
||||
|
||||
@@ -427,6 +427,7 @@ func (s *Server) buildPlannerWorker(pinID *int64, gProv llm.Provider, gCfg agent
|
||||
wk.SetConstraintInject(s.constraintInjectWorker) // 操作约束注入 worker(可配置,默认开;每轮读)
|
||||
wk.SetNonStreaming(nonStreamingResolver(wCfg)) // 该 profile 选非流式时走 Provider.Complete
|
||||
wk.SetMaxTokens(maxTokensResolver(wCfg)) // 单次回复输出上限(0 = 不发)
|
||||
wk.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(每 run 读)
|
||||
pProv, pCfg := s.providerForAgent("planner", pinID, gProv, gCfg)
|
||||
pl := agent.NewPlanner(pProv, pCfg.Model, s.m.dir, tx, pCfg.CompactionWindow(), s.agentMaxTurns("planner"))
|
||||
pl.SetFindingRecorder(s.evidenceStore())
|
||||
@@ -437,6 +438,7 @@ func (s *Server) buildPlannerWorker(pinID *int64, gProv llm.Provider, gCfg agent
|
||||
pl.SetConstraintInject(s.constraintInjectPlanner) // 操作约束注入 planner(可配置,默认开;每轮读)
|
||||
pl.SetNonStreaming(nonStreamingResolver(pCfg)) // 该 profile 选非流式时走 Provider.Complete
|
||||
pl.SetMaxTokens(maxTokensResolver(pCfg)) // 单次回复输出上限(0 = 不发)
|
||||
pl.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(每 run 读)
|
||||
// cold-digest §7: background cold-node compaction, on the planner's provider/
|
||||
// model (§4 uses the running agent's model). Uses Complete (non-streaming) for
|
||||
// the one-shot body summarization.
|
||||
@@ -508,6 +510,7 @@ func (s *Server) applyLLM(cfg agent.Config) error {
|
||||
s.mainAgent.SetSteerWork(s.engine.SteerWork) // steer_work:人对运行中 work 实时纠偏
|
||||
s.mainAgent.SetNonStreaming(nonStreamingResolver(mCfg))
|
||||
s.mainAgent.SetMaxTokens(maxTokensResolver(mCfg))
|
||||
s.mainAgent.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(每 run 读)
|
||||
// chat agent serves MANY custom agents by key → it holds the GLOBAL opts
|
||||
// (backend/key) and gates Enabled per-conversation-agent at Chat time. 对话始终用激活配置。
|
||||
s.chatAgent = agent.NewChatAgent(prov, cfg.Model, s.m.dir, tx, win) // chat page runner
|
||||
@@ -516,6 +519,7 @@ func (s *Server) applyLLM(cfg agent.Config) error {
|
||||
s.chatAgent.SetGuard(s.chatGuard())
|
||||
s.chatAgent.SetNonStreaming(nonStreamingResolver(cfg))
|
||||
s.chatAgent.SetMaxTokens(maxTokensResolver(cfg))
|
||||
s.chatAgent.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(每 run 读)
|
||||
s.llmProv = prov
|
||||
s.llmCfg = cfg
|
||||
s.llmOn = true
|
||||
@@ -699,6 +703,7 @@ func (s *Server) chatAgentForProfile(id int64) *agent.ChatAgent {
|
||||
ca.SetGuard(s.chatGuard())
|
||||
ca.SetNonStreaming(nonStreamingResolver(cfg))
|
||||
ca.SetMaxTokens(maxTokensResolver(cfg))
|
||||
ca.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(每 run 读)
|
||||
s.profMu.Lock()
|
||||
if ex := s.profChatAgents[id]; ex != nil { // lost the race → keep the winner
|
||||
ca = ex
|
||||
@@ -3210,6 +3215,9 @@ func (s *Server) settingsPayload() map[string]any {
|
||||
// 操作约束注入范围(默认都开):把本任务的 allow/deny 约束拼进对应 agent 的系统提示。
|
||||
"constraints_inject_planner": s.constraintInjectPlanner(),
|
||||
"constraints_inject_worker": s.constraintInjectWorker(),
|
||||
// 实验功能:noa 模型驱动上下文压缩(默认关)。开启后平台接入的四类 agent 由 noa
|
||||
// 接管上下文压缩,取代内置 compaction;每 run 读一次,对之后启动的 run 生效。
|
||||
"noa_compaction": s.m.NoaCompactionEnabled(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3255,6 +3263,8 @@ func (s *Server) putSettings(w http.ResponseWriter, r *http.Request) {
|
||||
// 操作约束注入范围开关(默认都开);即时生效(planner/worker 每轮读),无需重建 agent。
|
||||
ConstraintsInjectPlanner *bool `json:"constraints_inject_planner"`
|
||||
ConstraintsInjectWorker *bool `json:"constraints_inject_worker"`
|
||||
// 实验功能:noa 上下文压缩开关(默认关);每 run 读,对之后启动的 run 生效,无需重建 agent。
|
||||
NoaCompaction *bool `json:"noa_compaction"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
writeErr(w, 400, err.Error())
|
||||
@@ -3272,6 +3282,13 @@ func (s *Server) putSettings(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if req.NoaCompaction != nil {
|
||||
// 每 run 读的解析器,切换即时对之后启动的 run 生效,无需 applyLLM 重建。
|
||||
if err := s.m.SetNoaCompaction(*req.NoaCompaction); err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
if req.Workers != nil {
|
||||
if err := s.m.SetWorkers(*req.Workers); err != nil {
|
||||
writeErr(w, 400, err.Error())
|
||||
|
||||
@@ -566,6 +566,7 @@ func (s *Server) agentsForTask(t *Task) *taskAgentBundle {
|
||||
wk.SetCompactionWindowResolver(workerRuntime.CompactionWindow)
|
||||
wk.SetNonStreaming(workerRuntime.nonStreaming) // 按任务当前激活 profile 的流式开关(每轮读)
|
||||
wk.SetMaxTokens(workerRuntime.maxTokens) // 同上,输出上限也跟随当前激活 profile
|
||||
wk.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(平台级开关,每 run 读)
|
||||
wk.SetRunTimeout(time.Duration(s.agentRunSeconds("worker")) * time.Second)
|
||||
wk.SetProxy(s.m.ProxyAddr(), s.m.ProxyCACert())
|
||||
wk.SetWebSearch(s.webSearchFor("worker"))
|
||||
@@ -575,6 +576,7 @@ func (s *Server) agentsForTask(t *Task) *taskAgentBundle {
|
||||
pl.SetCompactionWindowResolver(plannerRuntime.CompactionWindow)
|
||||
pl.SetNonStreaming(plannerRuntime.nonStreaming)
|
||||
pl.SetMaxTokens(plannerRuntime.maxTokens)
|
||||
pl.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(平台级开关,每 run 读)
|
||||
pl.SetKillWork(s.engine.KillWork)
|
||||
pl.SetSteerWork(s.engine.SteerWork)
|
||||
pl.SetProxy(s.m.ProxyAddr(), s.m.ProxyCACert())
|
||||
@@ -585,6 +587,7 @@ func (s *Server) agentsForTask(t *Task) *taskAgentBundle {
|
||||
main.SetCompactionWindowResolver(mainRuntime.CompactionWindow)
|
||||
main.SetNonStreaming(mainRuntime.nonStreaming)
|
||||
main.SetMaxTokens(mainRuntime.maxTokens)
|
||||
main.SetNoaEnabled(s.m.NoaCompactionEnabled) // 实验功能:noa 上下文压缩(平台级开关,每 run 读)
|
||||
main.SetProxy(s.m.ProxyAddr(), s.m.ProxyCACert())
|
||||
main.SetWebSearch(s.webSearchFor("mainagent"))
|
||||
main.SetSteerWork(s.engine.SteerWork) // steer_work:人对运行中 work 实时纠偏
|
||||
|
||||
Reference in new issue
Block a user