diff --git a/src/main/java/cn/van/business/util/ds/SocialMediaLlmClient.java b/src/main/java/cn/van/business/util/ds/SocialMediaLlmClient.java index d9ac8fb..c425cc1 100644 --- a/src/main/java/cn/van/business/util/ds/SocialMediaLlmClient.java +++ b/src/main/java/cn/van/business/util/ds/SocialMediaLlmClient.java @@ -191,6 +191,9 @@ public class SocialMediaLlmClient { return chatCompletionsUrl; } String u = chatCompletionsUrl.trim().replaceAll("/+$", ""); + if (u.contains("minimax")) { + return normalizeMiniMaxOpenAiUrl(u); + } if (!u.contains("volces.com") || u.contains("chat/completions")) { return u; } @@ -203,6 +206,27 @@ public class SocialMediaLlmClient { return u; } + /** + * MiniMax 文档里的 Anthropic 基址(.../anthropic)与 OpenAI SDK 基址(.../v1)都不能直接当 Chat Completions 用。 + * 本客户端只发 OpenAI 格式,统一落到 .../v1/chat/completions。 + */ + private static String normalizeMiniMaxOpenAiUrl(String url) { + String u = url; + if (u.contains("/anthropic")) { + u = u.replaceFirst("/anthropic(?:/v1/messages)?$", "").replaceFirst("/anthropic$", ""); + } + if (u.endsWith("/v1/chat/completions")) { + return u; + } + if (u.endsWith("/v1")) { + return u + "/chat/completions"; + } + if (!u.contains("/chat/completions")) { + return u + "/v1/chat/completions"; + } + return u; + } + private String callOpenAiCompatible(String chatCompletionsUrl, String apiKey, String model, String userText) throws IOException { String endpoint = normalizeOpenAiCompatibleUrl(chatCompletionsUrl); @@ -212,7 +236,7 @@ public class SocialMediaLlmClient { } Map requestBody = new HashMap<>(); - requestBody.put("model", model); + requestBody.put("model", normalizeMiniMaxModel(model)); requestBody.put("messages", new Map[]{ Map.of("role", "user", "content", userText) }); @@ -231,7 +255,7 @@ public class SocialMediaLlmClient { request.header("Authorization", "Bearer " + apiKey.trim()); } - log.info("请求 OpenAI 兼容 API: URL={}, model={}", endpoint, model); + log.info("请求 OpenAI 兼容 API: URL={}, model={}", endpoint, normalizeMiniMaxModel(model)); HttpResponse response = request.execute(); if (response.getStatus() != 200) { @@ -256,6 +280,18 @@ public class SocialMediaLlmClient { return choices.get(0).path("message").path("content").asText(); } + /** 控制台展示名「MiniMax M3」与接口要求的 MiniMax-M3 对齐 */ + private static String normalizeMiniMaxModel(String model) { + if (StrUtil.isBlank(model)) { + return model; + } + String m = model.trim(); + if ("MiniMax M3".equalsIgnoreCase(m) || "minimax m3".equalsIgnoreCase(m)) { + return "MiniMax-M3"; + } + return m; + } + private static final class ResolvedLlm { String mode; String baseUrl;