后端: 1. execute 主链路重构为“上下文工具域 + 主动优化候选闭环”——移除 order_guard,粗排后默认进入主动微调,先诊断再从后端候选中选择 move/swap,避免 LLM 自由全局乱搜 2. 工具体系升级为动态注入协议——新增 context_tools_add / remove、工具域与二级包映射、主动优化白名单;schedule / taskclass / web 工具按域按包暴露,msg0 规则包与 execute 上下文同步重写 3. analyze_health 升级为主动优化唯一裁判入口——补齐 rhythm / tightness / profile / feasibility 指标、候选扫描与复诊打分、停滞信号、forced imperfection 判定,并把连续优化状态写回运行态 4. 任务类能力并入新 Agent 执行链——新增 upsert_task_class 写工具与启动注入事务写入;任务类模型补充学科画像与整天屏蔽配置,粗排支持 excluded_days_of_week,steady 策略改为基于目标位置/单日负载/分散度/缓冲的候选打分 5. 运行态与路由补齐优化模式语义——新增 active tool domain/packs、pending context hook、active optimize only、taskclass 写入回盘快照;区分 first_full / global_reopt / local_adjust,并完善首次粗排后默认 refine 的判定 前端: 6. 助手时间线渲染细化——推理内容改为独立 reasoning block,支持与工具/状态/正文按时序交错展示,自动收口折叠,修正 confirm reject 恢复动作 仓库: 7. newAgent 文档整体迁入 docs/backend,补充主动优化执行规划与顺序约束拆解文档,删除旧调试日志文件 PS:这次科研了2天,总算是有些进展了——LLM永远只适合做选择题、判断题,不适合做开放创新题。
107 lines
3.7 KiB
Go
107 lines
3.7 KiB
Go
package newagentprompt
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// summarizeExecuteAnalyzeHealthObservationV2 把 analyze_health 结果压成更短的单行摘要。
|
|
//
|
|
// 职责边界:
|
|
// 1. 只保留 execute 下一步真正需要消费的裁决字段,不重复展开整份 metrics。
|
|
// 2. 若存在候选,会优先展示“候选数量 + 前两个候选工具”,帮助模型迅速进入选择题。
|
|
// 3. 这里只做摘要,不负责改变决策含义;真实判定仍以 analyze_health 原始 JSON 为准。
|
|
func summarizeExecuteAnalyzeHealthObservationV2(payload map[string]any) string {
|
|
decision, _ := payload["decision"].(map[string]any)
|
|
metrics, _ := payload["metrics"].(map[string]any)
|
|
rhythmMetrics, _ := metrics["rhythm"].(map[string]any)
|
|
tightnessMetrics, _ := metrics["tightness"].(map[string]any)
|
|
candidates, _ := decision["candidates"].([]any)
|
|
|
|
parts := make([]string, 0, 7)
|
|
if text := compactHealthAny(decision["should_continue_optimize"]); text != "" {
|
|
parts = append(parts, "continue="+text)
|
|
}
|
|
if text := strings.TrimSpace(asExecuteString(decision["recommended_operation"])); text != "" {
|
|
parts = append(parts, "recommended="+text)
|
|
}
|
|
if text := strings.TrimSpace(asExecuteString(tightnessMetrics["tightness_level"])); text != "" {
|
|
parts = append(parts, "tightness="+text)
|
|
}
|
|
if text := buildBlockBalanceSummary(rhythmMetrics); text != "" {
|
|
parts = append(parts, text)
|
|
}
|
|
if text := compactHealthAny(decision["is_forced_imperfection"]); text != "" {
|
|
parts = append(parts, "forced="+text)
|
|
}
|
|
if len(candidates) > 0 {
|
|
parts = append(parts, fmt.Sprintf("candidates=%d", len(candidates)))
|
|
if preview := compactHealthCandidatePreview(candidates); preview != "" {
|
|
parts = append(parts, "options="+preview)
|
|
}
|
|
}
|
|
if text := strings.TrimSpace(asExecuteString(decision["primary_problem"])); text != "" {
|
|
parts = append(parts, "problem="+compactExecuteText(text, 36))
|
|
}
|
|
if len(parts) == 0 {
|
|
return "返回了健康裁决结果。"
|
|
}
|
|
return strings.Join(parts, " | ")
|
|
}
|
|
|
|
// buildBlockBalanceSummary 把 block_balance 连同正负来源一起压成单段摘要。
|
|
//
|
|
// 职责边界:
|
|
// 1. 这里只做 execute 摘要层的可读性补充,避免 LLM 只看到 balance=0 却看不到来源。
|
|
// 2. 不改变 analyze_health 原始 JSON 结构;原始结构仍由 metrics.rhythm 提供完整字段。
|
|
// 3. 若三个字段都缺失,则直接留空,避免构造误导性的默认值。
|
|
func buildBlockBalanceSummary(rhythmMetrics map[string]any) string {
|
|
if len(rhythmMetrics) == 0 {
|
|
return ""
|
|
}
|
|
|
|
blockBalance := compactHealthAny(rhythmMetrics["block_balance"])
|
|
fragmentedCount := compactHealthAny(rhythmMetrics["fragmented_count"])
|
|
compressedCount := compactHealthAny(rhythmMetrics["compressed_run_count"])
|
|
if blockBalance == "" && fragmentedCount == "" && compressedCount == "" {
|
|
return ""
|
|
}
|
|
|
|
return fmt.Sprintf(
|
|
"block_balance=%s(fragmented=%s,compressed=%s)",
|
|
fallbackExecuteText(blockBalance, "?"),
|
|
fallbackExecuteText(fragmentedCount, "?"),
|
|
fallbackExecuteText(compressedCount, "?"),
|
|
)
|
|
}
|
|
|
|
func compactHealthCandidatePreview(candidates []any) string {
|
|
if len(candidates) == 0 {
|
|
return ""
|
|
}
|
|
preview := make([]string, 0, 2)
|
|
for _, raw := range candidates {
|
|
item, _ := raw.(map[string]any)
|
|
if len(item) == 0 {
|
|
continue
|
|
}
|
|
id := strings.TrimSpace(asExecuteString(item["candidate_id"]))
|
|
tool := strings.TrimSpace(asExecuteString(item["tool"]))
|
|
if id == "" && tool == "" {
|
|
continue
|
|
}
|
|
switch {
|
|
case id != "" && tool != "":
|
|
preview = append(preview, id+":"+tool)
|
|
case id != "":
|
|
preview = append(preview, id)
|
|
default:
|
|
preview = append(preview, tool)
|
|
}
|
|
if len(preview) >= 2 {
|
|
break
|
|
}
|
|
}
|
|
return strings.Join(preview, ",")
|
|
}
|