feat(saa): U5 openai 格式 M3 路 — thinking:disabled(extraBody)+ openai NO_PROXY

Plan A U5「切 OpenAI 格式」(创始人 2026-06-19):
- model(): MiniMax 系经 OpenAiChatOptions.extraBody 注入 thinking:{type:disabled} 关推理(治 chat.completions 内联 <think> 污染;探活实证 reasoning:effort:none 不被网关认、唯 thinking:disabled 有效);仅 model 名含 minimax 注入,deepseek 字节零变
- openAiApiNoProxy(): openai 路同 anthropic 旁路系统代理(macOS clash 把 Tailscale IP 走代理→502);dispatcher openai 分支改用之

实测(openai+M3+thinking off,K=10/diverse-10):0 超时/0 <think>残留/0 502 = 路干净;成功率 1/10(10%)。
三臂对照(同 diverse-10/K=10):deepseek(anthropic) 30% > M3(anthropic+thinking,超时假象) 10% = M3(openai+thinking off,干净) 10% → M3 在 gamedef 生成上真逊 deepseek,非协议/超时假象。失败主因 llm_error(无有效 bundle)+ 到门者 F_wiring/G_input/E_live/H_progress(driver/引擎接线)——两模型同款,杠杆在 pipeline/接线非换模型。
不碰 gd-runtime/build-from-source(Plan B 域)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
lili 2026-06-19 11:47:46 -07:00
parent 1cd199cb3c
commit 0cd1496399
2 changed files with 25 additions and 1 deletions

View File

@ -392,7 +392,8 @@ public class SaaGraphDispatcher implements GenerationDispatcher {
} else {
// OpenAI 兼容路(默认):baseUrl 取 host 根(剥末尾 /v1,坑见 §7-1);apiKey 经配置注入。openAiFactory 逐字调 model(api,...),字节等价改造前。
String baseUrl = SaaStudioGraph.stripV1Suffix(properties.getLlmBase());
OpenAiApi api = OpenAiApi.builder().baseUrl(baseUrl).apiKey(properties.getApiKey()).build();
// Plan A U5:openai 路同 anthropic 旁路系统代理(macOS clash 把 Tailscale IP 走代理→502;无代理环境 no-op)。
OpenAiApi api = SaaStudioGraph.openAiApiNoProxy(baseUrl, properties.getApiKey());
mf = SaaStudioGraph.openAiFactory(api);
upstreamDesc = "openai(" + baseUrl + ")";
}

View File

@ -158,12 +158,35 @@ public final class SaaStudioGraph {
if (temperature != null) {
opts.temperature(temperature); // null = 不下发,用服务端默认(对齐 Python design 角色)
}
// Plan A U5「切 OpenAI 格式」(创始人 2026-06-19):MiniMax 系(M3/M2.x)在 chat.completions 默认内联 <think> 污染结构化输出
// (探活 A 实证) → 经 OpenAiChatOptions.extraBody 注入厂商参 thinking:{type:disabled} 关推理(探活 B:干净 JSON、1.3s、零超时)。
// 仅 MiniMax 注入(model 名含 minimax);deepseek 等不动(无此坑、字节零变)。对齐 Python worker 一贯 thinking:disabled。
// 注:chat.completions 路 reasoning:{effort:none} 不被网关认(探活 C 仍内联),唯 thinking:{type:disabled} 有效。
if (modelName != null && modelName.toLowerCase().contains("minimax")) {
opts.extraBody(java.util.Map.<String, Object>of("thinking", java.util.Map.of("type", "disabled")));
}
return OpenAiChatModel.builder()
.openAiApi(api)
.defaultOptions(opts.build())
.build();
}
/**
* 建一个走 new-api 的 {@link OpenAiApi},旁路系统代理(Plan A U5;macOS clash 等会把 Tailscale 内网 IP 走代理→502,
* 同 anthropic 路 {@link Proxy#NO_PROXY} 处理)。本机/内网量测 openai 兼容路必经此旁路;无代理环境为 no-op(安全)。
*/
public static OpenAiApi openAiApiNoProxy(String baseUrl, String apiKey) {
SimpleClientHttpRequestFactory rf = new SimpleClientHttpRequestFactory();
rf.setProxy(Proxy.NO_PROXY);
rf.setConnectTimeout(10_000);
rf.setReadTimeout(120_000);
return OpenAiApi.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.restClientBuilder(RestClient.builder().requestFactory(rf))
.build();
}
/**
* per-role 模型工厂(Plan A/U1「用对 M3」flag 旁挂的缝):把「角色名+采样面 → {@link ChatModel}」抽象成函数,
* 使 {@link #assemble} 的节点布线与「底层走 OpenAI 兼容还是 Anthropic 协议」解耦。