全图 design->generate->validate->[repair环]->scaffold->build->play(九门)->player->emit;build/play 复用既有 harness 子进程。 SAA 完整框架集接入 aigc-server(graph-core/agent-framework/builtin-nodes/observation/openai,3 BOM;Boot3.5.14/Redisson4.4.0 保住)。 双评审(Opus+Codex)9 项对比前必修:LLM超时重试/ProcessBuilder超时修复/采样面对齐/playerFeedback清串味/gatespec强解析/problems归一/recursionLimit兜底/cost/端口参数化。 首轮对比 breakout/whack/flappy:SAA 通过率 2/3 >= Python 1/3。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
9.2 KiB
SAA 能力 / API / 接入 档案(多路源码调查汇总)
来源:4 个 Claude/Opus 子代理逐行源码取证(API 面 / 能力盘点 / 接入部署 / 用法范式 四视角),彼此交叉验证一致;Codex 第 5 路 51min 卡死已取消,不影响结论(四路已互验)。 基线:
/root/oss/spring-ai-alibaba@ tag v1.1.2.2(HEAD 7405a7d),底层 spring-ai 1.1.2。 关联:spike 执行稿2026-06-15-SAA-AgentScope-spike-execution.md、目标架构…目标架构-review.md、决策 saa-agentic-infra-decision。
0. 一句话结论(决策级)
- 我们的生成流水 = 确定性多步编排 → 用「裸
StateGraph+ 自定义NodeAction」,不用ReactAgent/flow agent(那是给"LLM+工具自治"的)。repair 环用addConditionalEdges回边 + state 计数器,不用 LoopAgent。 - 模型:SAA 复用上游 Spring AI 的
OpenAiChatModel/OpenAiApi(SAA 无自有 OpenAI 封装)。baseUrl 指 new-api,每节点一个OpenAiChatModelbean(共用一个OpenAiApi,仅defaultOptions.model不同),节点按@Qualifier取。便宜模型(DeepSeek)同构,有原生 starter。 - 状态:
MysqlSaver(收DataSource,直接注入 yudao Druid)作引擎唯一权威 saver +RunnableConfig.threadId(任务id);Redis 作业务层旁路缓存(一张图只能注册一个 saver,注册俩抛异常)。releaseThread(false)才能长期续跑。 - 依赖冲突风险 = 低-中、可控:只引
graph-core+ 3 个 BOM;不引 SAA 的 Boot BOM(让项目 3.5.14 胜出);不用 RedisSaver 即避开 Redisson 3.x↔4.x。fastjson/okhttp 双方完全一致;graph-core 不引 web 框架(只 reactor-core),不与 yudao spring-mvc 抢栈。 - 运行形态:进程内嵌,抽
GenerationDispatcher接口挂在现有AigcTaskService.submitGenerate → completeWithVersion契约后(HttpWorkerDispatcher | SaaGraphDispatcher 灰度切,框架可换);图用自带阻塞invoke()在后台线程池跑(禁 Tomcat/Reactor 线程),图执行不包大事务。独立 worker 留 Phase2。
1. 关键 API(照着写代码那层)
- 图:
new StateGraph(name, KeyStrategyFactory);addNode(id, node_async(NodeAction));addEdge(START,..)/(..,END);addConditionalEdges(from, edge_async(EdgeAction→String), Map<key,目标节点>)(repair 回边靠它,mappings 不可空);compile(CompileConfig)→CompiledGraph。 - 状态读写契约:节点
NodeAction.apply(OverAllState)内 读state.value("k", T.class),写 靠return Map.of("k", v)(框架按 key 的KeyStrategy合并;ReplaceStrategy覆盖 /AppendStrategy追加 messages)——不是 setter。 - 执行:
invoke(inputs, RunnableConfig)→Optional<OverAllState>(内部即stream().last().block(),自带阻塞);stream(...)→Flux<NodeOutput>。 - 模型(上游三件套):
OpenAiApi.builder().baseUrl(NEW_API).apiKey(KEY).build()→OpenAiChatModel.builder().openAiApi(api).defaultOptions(OpenAiChatOptions.builder().model("deepseek-chat").build()).build()。 - 持久化:
MysqlSaver.builder().dataSource(ds).createOption(CREATE_IF_NOT_EXISTS).build()/RedisSaver.builder().redisson(redissonClient).build()→SaverConfig.builder().register(saver).build()→CompileConfig.builder().saverConfig(..).releaseThread(false)→RunnableConfig.builder().threadId("..")。 - 流式:
stream()→Flux<NodeOutput>;instanceof StreamingOutput区分 LLM token chunk,.message().getText()取增量。⚠️ 无streamEvents。
2. 能力盘点:本期(MySQL+Redis only)可用 vs Phase2
✅ 本期即可落(纯 JVM 或仅 MySQL+Redis,覆盖我们核心用例):图编排全集(条件/并行/嵌套子图/循环)、agentic ReAct、工具调用、多 agent(sequential/parallel/routing/conditional/loop)、持久化 checkpoint/resume(MysqlSaver 仅需 MySQL、RedisSaver 仅需 Redis,均已验证零 Nacos/MQ import)、流式、HITL 中断恢复、Hook(10)/拦截器(13)、OpenAI 兼容(new-api)+DeepSeek、A2A 点对点、可观测埋点。
⛔ 需 Phase2 基建:完整 Admin 平台(MySQL+Redis+ES+RocketMQ+Nacos 五件套全硬,缺一启动失败)、A2A-Nacos 服务发现、config-nacos、MCP-Nacos 网关、sandbox(Docker)、RAG 走 ES、Prompt 发布线上热更(写 Nacos)。
两条最易误判:① Admin 整包 ≠ MySQL+Redis 就够——只想用编排引擎就别起 admin,直接用 graph-core+agent-framework 库依赖。② 向量库在本 clone 只有 ES 是具体实现。
3. 接入 game-cloud(依赖冲突解法放最前)
真冲突仅 2 处:
- C1 Spring Boot:项目 3.5.14(huijing-dependencies BOM 实际生效)vs SAA 要 3.5.8 → 不引 SAA 的 Boot BOM,让 3.5.14 胜(同 minor 补丁前向兼容,jackson/reactor/spring 仅补丁差,实测安全)。
- C2 Redisson:项目 4.4.0 vs SAA graph-core 用 3.22.0(但
optional=true)→ 不用 RedisSaver 即零冲突;若用,需实测 redisson 4.x 对RMap/RBucket/RLock三 API 兼容。 - 零冲突:fastjson 1.2.83、okhttp 4.12.0 双方一致;graph-core 不引 web 框架。
Maven(只加到 game-module-aigc-server/pom.xml,不动根 POM/BOM):import 三 BOM = spring-ai-bom:1.1.2 + spring-ai-alibaba-bom:1.1.2.2 + spring-ai-alibaba-extensions-bom:1.1.2.2;依赖只加 spring-ai-alibaba-graph-core(图引擎,唯一必需)+ 模型 starter(走 new-api 用 spring-ai-openai)。
reactive↔blocking 桥接:CompiledGraph.invoke() 自带阻塞(内部 .block())→ 在后台 ExecutorService(非 Web/Reactor 线程)调用,否则 block-in-reactor 死锁;超时用 Future.get(timeout) 外包,取消接现有 cancelTask;图执行不包大 @Transactional,跑完单独短事务落库。
最小验证门 E(6 步,mini-desktop 跑):① 加 3 BOM+graph-core → ② mvn -pl …aigc-server -am dependency:tree 断言(boot 全 3.5.14 / redisson 4.4.0 / 无 3.22.0 泄漏 / jackson 2.21.x)→ ③ 写一个纯 Java 节点(不调 LLM)的 hello StateGraph → ④ mvn package 编译门 → ⑤ 单体启动门(验 SAA 与 yudao 自动配置共存无 BeanCreation 失败)→ ⑥ 调 invoke 跑一节点断言返回 state。先不接模型/不接 MysqlSaver/不接 job 链,隔离验"SAA 库能进 game-cloud 进程"这一最便宜命题。
4. 面向我们生成流水的用法范式(7 条,骨架见各子代理报告)
- 主干:
StateGraph+ 每步一个node_async(NodeAction)(render→generate→validate→scaffold→build→play→emit)。 - repair 环:
addConditionalEdges("validate", edge_async(s→ ok?"done": cnt>=N?"giveup":"repair"), …)回边 + staterepair_count计数器;recursionLimit(默认 100,优雅终止非异常)作硬刹车,不替代业务 max-iters。 - build/play 节点:自定义
NodeAction内new ProcessBuilder(...)shell 调 node/esbuild + CDP 九门 harness,mapper.readTree收 JSON,waitFor(timeout)/destroyForcibly。别用 sandbox 模块(那是 agentscope 远程容器);骨架抄LocalFilesystemBackend.java:457-507。 - 进度推前端:节点
apply返回的 Map 里塞一个Flux→ 框架自动在stream()上展开 → 出口@PostMapping(produces=TEXT_EVENT_STREAM_VALUE) Flux<ServerSentEvent<String>>。 - checkpoint:MySQL 权威单 saver +
releaseThread(false);Redis 业务旁路;同 threadId 二次 invoke 即续跑;time-travel 用getStateHistory+checkPointId。 - 可选 HITL:节点实现
InterruptableAction,interrupt()里按 state 开关review_required返回停/放行(条件式,默认自动放行);恢复updateState(...)+withResume()+stream(null, cfg)。HumanNode 已废,必须配 saver。 - 模型:N 个
OpenAiChatModelbean 全指 new-api、仅defaultOptions.model不同,节点@Qualifier取;AGENT_MODEL_NAME不是选模型机制(只是节点 ID + 流式事件前缀)。
5. ⚠️ 六个最易踩的坑(四路交叉验证确认)
HumanNode整文件被注释、不可用 → 用CompileConfig.interruptBefore/After+resume()。- 无
streamEvents→stream()→Flux<NodeOutput>+instanceof StreamingOutput。 - ReAct 循环默认无限上限(
Integer.MAX_VALUE)→ 用 ReactAgent 时生产必挂ModelCallLimitHook/ToolCallLimitHook;我们用裸 StateGraph 则靠 state 计数器 +recursionLimit。 - supervisor / handoff 没实现(仅枚举占位)→ 用 routing 替代。
- 一张图只能注册一个 saver(注册俩抛
IllegalStateException)→ MySQL 权威 + Redis 业务旁路(或自写双写装饰器)。 - Admin 整包要五件套(MySQL+Redis+ES+RocketMQ+Nacos)→ 只要引擎别起 admin,直接用 graph-core + agent-framework 库。
全量逐行证据(含每个类的 文件:行)见本轮四个子代理报告(API 速查 / 能力矩阵 / 接入部署 / 用法范式手册)。本档案为决策级蒸馏,spike 门 E 与生成图实现直接照此落地。