This commit is contained in:
van
2026-04-06 11:15:05 +08:00
parent 0d408d66c3
commit c98491a324

View File

@@ -180,8 +180,37 @@ public class SocialMediaLlmClient {
return t.isEmpty() ? null : t;
}
/**
* 火山方舟「Coding / OpenClaw」文档里的基址常为 {@code .../api/coding/v3},与 OpenAI 兼容对话接口
* {@code .../api/v3/chat/completions} 不同,误填会导致 404。此处自动纠正常见误填。
*
* @see <a href="https://www.volcengine.com/docs/82379/1174746">方舟对话 API</a>
*/
private static String normalizeOpenAiCompatibleUrl(String chatCompletionsUrl) {
if (StrUtil.isBlank(chatCompletionsUrl)) {
return chatCompletionsUrl;
}
String u = chatCompletionsUrl.trim().replaceAll("/+$", "");
if (!u.contains("volces.com") || u.contains("chat/completions")) {
return u;
}
if (u.contains("/api/coding/")) {
String fixed = u.replace("/api/coding/v3", "/api/v3/chat/completions");
if (!fixed.equals(u)) {
return fixed;
}
}
return u;
}
private String callOpenAiCompatible(String chatCompletionsUrl, String apiKey, String model, String userText)
throws IOException {
String endpoint = normalizeOpenAiCompatibleUrl(chatCompletionsUrl);
String originalTrim = chatCompletionsUrl == null ? "" : chatCompletionsUrl.trim().replaceAll("/+$", "");
if (!endpoint.equals(originalTrim)) {
log.info("OpenAI 兼容 URL 已规范化: {} -> {}", originalTrim, endpoint);
}
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", model);
requestBody.put("messages", new Map[]{
@@ -191,7 +220,7 @@ public class SocialMediaLlmClient {
String jsonBody = objectMapper.writeValueAsString(requestBody);
HttpRequest request = HttpRequest.of(chatCompletionsUrl.trim())
HttpRequest request = HttpRequest.of(endpoint)
.method(Method.POST)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
@@ -202,12 +231,21 @@ public class SocialMediaLlmClient {
request.header("Authorization", "Bearer " + apiKey.trim());
}
log.info("请求 OpenAI 兼容 API: URL={}, model={}", chatCompletionsUrl, model);
log.info("请求 OpenAI 兼容 API: URL={}, model={}", endpoint, model);
HttpResponse response = request.execute();
if (response.getStatus() != 200) {
log.error("OpenAI 兼容 API 失败: status={}, body={}", response.getStatus(), response.body());
throw new IOException("API 调用失败HTTP 状态码: " + response.getStatus());
String body = response.body();
log.error("OpenAI 兼容 API 失败: status={}, body={}", response.getStatus(), body);
String hint = "";
if (response.getStatus() == 404) {
hint = "(若为火山方舟:请使用 .../api/v3/chat/completions ,不要用 Coding 文档中的 .../api/coding/v3 ";
}
String snippet = "";
if (StrUtil.isNotBlank(body)) {
snippet = "" + (body.length() > 400 ? body.substring(0, 400) + "..." : body);
}
throw new IOException("API 调用失败HTTP 状态码: " + response.getStatus() + hint + snippet);
}
JsonNode root = objectMapper.readTree(response.body());