diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/constant/OpenAIConst.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/constant/OpenAIConst.java index bab2821c..6ac62d22 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/constant/OpenAIConst.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/constant/OpenAIConst.java @@ -10,6 +10,8 @@ public class OpenAIConst { public final static String OPENAI_HOST = "https://api.openai.com/"; + public final static String apiUrl = "v1/chat/completions"; + public final static int SUCCEED_CODE = 200; } diff --git a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java index ef03cb24..4b3cb97e 100644 --- a/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java +++ b/ruoyi-common/ruoyi-common-chat/src/main/java/org/ruoyi/common/chat/openai/OpenAiStreamClient.java @@ -71,6 +71,11 @@ public class OpenAiStreamClient { */ private String apiHost; + /** + * 自定义url 兼容多个平台 + */ + private String apiUrl; + /** * 自定义的okHttpClient * 如果不自定义 ,就是用sdk默认的OkHttpClient实例 @@ -112,6 +117,11 @@ public class OpenAiStreamClient { } apiHost = builder.apiHost; + if (StrUtil.isBlank(builder.apiUrl)) { + builder.apiUrl = OpenAIConst.apiUrl; + } + apiUrl = builder.apiUrl; + if (Objects.isNull(builder.keyStrategy)) { builder.keyStrategy = new KeyRandomStrategy(); } @@ -180,7 +190,7 @@ public class OpenAiStreamClient { ObjectMapper mapper = new ObjectMapper(); String requestBody = mapper.writeValueAsString(chatCompletion); Request request = new Request.Builder() - .url(this.apiHost + "v1/chat/completions") + .url(this.apiHost + apiUrl) .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody)) .build(); factory.newEventSource(request, eventSourceListener); @@ -611,6 +621,8 @@ public class OpenAiStreamClient { */ private String apiHost; + private String apiUrl; + /** * 自定义OkhttpClient */ @@ -645,6 +657,16 @@ public class OpenAiStreamClient { return this; } + /** + * @param val 自定义请求后缀 + * @return Builder + * @see OpenAIConst + */ + public Builder apiUrl(String val) { + apiUrl = val; + return this; + } + public Builder keyStrategy(KeyStrategyFunction val) { keyStrategy = val; return this; diff --git a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/ChatModel.java b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/ChatModel.java index f67e7657..5dfce097 100644 --- a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/ChatModel.java +++ b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/ChatModel.java @@ -1,6 +1,7 @@ package org.ruoyi.domain; +import com.alibaba.excel.annotation.ExcelProperty; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import lombok.EqualsAndHashCode; @@ -68,6 +69,12 @@ public class ChatModel extends BaseEntity { */ private String apiHost; + /** + * 请求地址后缀 - 兼容多平台 + */ + @ExcelProperty(value = "请求地址后缀") + private String apiUrl; + /** * 密钥 */ diff --git a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/bo/ChatModelBo.java b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/bo/ChatModelBo.java index 45e0705c..f66908ad 100644 --- a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/bo/ChatModelBo.java +++ b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/bo/ChatModelBo.java @@ -1,5 +1,6 @@ package org.ruoyi.domain.bo; +import com.alibaba.excel.annotation.ExcelProperty; import org.ruoyi.common.core.validate.AddGroup; import org.ruoyi.common.core.validate.EditGroup; import org.ruoyi.domain.ChatModel; @@ -79,6 +80,12 @@ public class ChatModelBo extends BaseEntity { @NotBlank(message = "密钥不能为空", groups = { AddGroup.class, EditGroup.class }) private String apiKey; + /** + * 请求地址后缀 - 兼容多平台 + */ + @ExcelProperty(value = "请求地址后缀") + private String apiUrl; + /** * 备注 */ diff --git a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/vo/ChatModelVo.java b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/vo/ChatModelVo.java index 56efb598..49bd93c3 100644 --- a/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/vo/ChatModelVo.java +++ b/ruoyi-modules-api/ruoyi-chat-api/src/main/java/org/ruoyi/domain/vo/ChatModelVo.java @@ -88,11 +88,16 @@ public class ChatModelVo implements Serializable { @ExcelProperty(value = "密钥") private String apiKey; + /** + * 请求地址后缀 - 兼容多平台 + */ + @ExcelProperty(value = "请求地址后缀") + private String apiUrl; + /** * 备注 */ @ExcelProperty(value = "备注") private String remark; - } diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/config/ChatConfig.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/config/ChatConfig.java index e49dce7d..ec577d3c 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/config/ChatConfig.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/config/ChatConfig.java @@ -32,11 +32,12 @@ public class ChatConfig { public OpenAiStreamClient openAiStreamClient() { String apiHost = configService.getConfigValue("chat", "apiHost"); String apiKey = configService.getConfigValue("chat", "apiKey"); - openAiStreamClient = createOpenAiStreamClient(apiHost,apiKey); + String url = configService.getConfigValue("chat", "apiUrl"); + openAiStreamClient = createOpenAiStreamClient(apiHost,apiKey,url); return openAiStreamClient; } - public static OpenAiStreamClient createOpenAiStreamClient(String apiHost, String apiKey) { + public static OpenAiStreamClient createOpenAiStreamClient(String apiHost, String apiKey,String url) { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger()); httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); OkHttpClient okHttpClient = new OkHttpClient.Builder() @@ -47,6 +48,7 @@ public class ChatConfig { .build(); return OpenAiStreamClient.builder() .apiHost(apiHost) + .apiUrl(url) .apiKey(Collections.singletonList(apiKey)) .keyStrategy(new KeyRandomStrategy()) .okHttpClient(okHttpClient) diff --git a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/OpenAIServiceImpl.java b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/OpenAIServiceImpl.java index c2e5ed31..b202ea09 100644 --- a/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/OpenAIServiceImpl.java +++ b/ruoyi-modules/ruoyi-chat/src/main/java/org/ruoyi/chat/service/chat/impl/OpenAIServiceImpl.java @@ -47,7 +47,7 @@ public class OpenAIServiceImpl implements IChatService { @Override public SseEmitter chat(ChatRequest chatRequest,SseEmitter emitter) { ChatModelVo chatModelVo = chatModelService.selectModelByName(chatRequest.getModel()); - openAiStreamClient = ChatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey()); + openAiStreamClient = ChatConfig.createOpenAiStreamClient(chatModelVo.getApiHost(), chatModelVo.getApiKey(),chatModelVo.getApiUrl()); List messages = chatRequest.getMessages(); if (enabled) { String toolString = mcpChat(chatRequest.getPrompt()); diff --git a/script/sql/update/20250509.sql b/script/sql/update/20250509.sql new file mode 100644 index 00000000..19bfe5e1 --- /dev/null +++ b/script/sql/update/20250509.sql @@ -0,0 +1,4 @@ +ALTER TABLE `chat_model` + ADD COLUMN `api_url` varchar(50) NULL COMMENT '请求后缀' AFTER `api_key`; + +INSERT INTO `chat_config` (`id`, `category`, `config_name`, `config_value`, `config_dict`, `create_dept`, `create_time`, `create_by`, `update_by`, `update_time`, `remark`, `version`, `del_flag`, `update_ip`, `tenant_id`) VALUES (1779450794872414211, 'chat', 'apiUrl', 'v1/chat/completions', 'API 请求后缀', 103, '2024-04-14 18:05:05', '1', '1', '2025-04-23 22:29:04', NULL, NULL, '0', NULL, 0);