Commit Graph

2 Commits

Author SHA1 Message Date
ThearchyHelios 761117344b 沙箱会话生命周期与记忆检索
## 每跑一次图就多一台常驻 VM,没有任何自动回收路径

_reap_idle 只在 run() 里调,也就是说没人再跑代码时闲置 VM 永远收不掉,
microvm_idle_seconds 形同虚设;而 thread_id 每个 run 都是新的,runner 的
finally 又从不调 cleanup,于是每跑一次带代码节点的图就多一台几百 MB 的常驻
microVM(seatbelt 那边同样积了几十个历史会话目录)。

两处一起补:run 到终态就 cleanup(run_id)(interrupted 除外,人回来还要接着跑),
外加 lifespan 里起一个后台回收任务定期 _reap_idle——回收本来也不该占着请求
路径的时间。实测连跑三次 live_vms 稳定回到 0。

## 超时会连人带文件销毁整台 VM

会话契约是"同 session_id 共享文件系统,可以先写文件下一步再读回来",而
microVM 超时直接 _destroy,工作区连同用户数据一起没了,返回结果里没有任何
提示。另外三个后端超时只 killpg、工作目录照留——换到 microVM 之后同一张图的
行为就变了。现在超时先在 VM 内 pkill 掉跑飞的进程(入口名带唯一后缀,不会
误伤同会话的并发执行),确认 VM 还活着就保住工作区;收拾不动才销毁。

限额变更那条没法避免重建(VM 内存是启动时定死的),但不能不吭声:同一个 run
里两个代码节点填了不同的 memory_mb 就会触发。ExecResult 新增 session_reset,
代码节点在时间线上明确告警,否则下游只会看到一个无从追查的 FileNotFoundError。

## 新建 scope 写入第一条后永远搜不到

hybrid_rank 的 _norm 在 hi==lo 时把所有分数抹成 0,而候选只有一条时 hi 恒等于
lo,合并分 0.0 会被 min_score 过滤掉。"先写一条、下一轮再 recall"恰恰是 agent
最常见的用法。全都一样分是"都一样好",不是"都一样差",改成返回 1.0。

## 记忆去重误判,写入被静默丢弃且返回不相关的旧记忆

remember 拿 recall 的分数判重,但那是 min-max 排名归一化的结果——排第一的那条
在两路信号上都会被归成 1.0,与它和查询像不像毫无关系。于是 scope 里只要已有
两条记忆,新内容随便撞一个字排到第一就被判成重复丢掉,接口还返回 201 并把那条
不相关的旧记忆当成"刚保存的"交回去。改成直接比未归一化的余弦相似度。

验证:三条互不相关的记忆都能写进去、完全相同的仍被去重、单条 scope 可检索。
2026-09-14 15:41:05 +08:00
ThearchyHelios 964eeaa829 AgentLab:可视化 Agent 编排实验台
在画布上拖拽编排 agent 工作流,并实时看着它执行。

后端 FastAPI + LangGraph:把画布 JSON 编译成 StateGraph,15 种节点
(模型/Agent/多Agent、工具/沙箱、分支/循环/子图、记忆/检索/整形、
人工介入/结构校验)。选 LangGraph 是因为可视化编排真正难的是暂停、
恢复和回放,而 checkpointer + interrupt() 正好把这几件事做在了底层。

前端 React + React Flow:节点元数据驱动属性面板与连接桩,运行时
节点高亮、边流动画、卡片内流式 token 全部由同一份事件流驱动。

关键实现:
- Agent 内工具审批用 @task 缓存模型调用,interrupt 重放时不重复计费
- 沙箱保持只读根文件系统,代码经 exec+base64 写入(put_archive 会被
  只读容器拒绝),断网、非 root、内存/CPU/超时限额
- 检索为向量与 BM25 混合,本地哈希 embedding 零配置可用
- 分支条件走 AST 白名单求值器;HTTP 工具逐 IP 拦截内网与元数据地址
- Mock provider 让无 API Key 也能跑通完整链路

7 个内置模板全部冒烟通过,含真实模型端到端验证。
2026-09-13 17:27:00 +08:00