mirror of
https://gitcode.com/ageerle/ruoyi-ai.git
synced 2026-04-17 22:03:39 +00:00
fate:增加自定义模型,调整前端模型选择下拉框
This commit is contained in:
@@ -9,6 +9,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.ruoyi.common.chat.service.chat.IChatModelService;
|
||||
import org.ruoyi.common.chat.domain.bo.chat.ChatModelBo;
|
||||
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
import org.ruoyi.enums.ChatModeType;
|
||||
import org.ruoyi.enums.ModelType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -23,6 +24,8 @@ import org.ruoyi.common.log.enums.BusinessType;
|
||||
import org.ruoyi.common.excel.utils.ExcelUtil;
|
||||
import org.ruoyi.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* 模型管理
|
||||
*
|
||||
@@ -55,6 +58,21 @@ public class ChatModelController extends BaseController {
|
||||
return R.ok(chatModelService.queryList(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型供应商枚举
|
||||
*/
|
||||
@GetMapping("/providerOptions")
|
||||
public R<List<LinkedHashMap<String, String>>> providerOptions() {
|
||||
List<LinkedHashMap<String, String>> options = new java.util.ArrayList<>();
|
||||
for (ChatModeType type : ChatModeType.values()) {
|
||||
LinkedHashMap<String, String> item = new LinkedHashMap<>();
|
||||
item.put("label", type.getDescription());
|
||||
item.put("value", type.getCode());
|
||||
options.add(item);
|
||||
}
|
||||
return R.ok(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出模型管理列表
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,8 @@ public enum ChatModeType {
|
||||
DEEP_SEEK("deepseek", "深度求索"),
|
||||
QIAN_WEN("qianwen", "通义千问"),
|
||||
OPEN_AI("openai", "openai"),
|
||||
PPIO("ppio", "ppio");
|
||||
PPIO("ppio", "ppio"),
|
||||
CUSTOM_API("custom_api", "自定义API");
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package org.ruoyi.service.chat;
|
||||
|
||||
import dev.langchain4j.model.chat.ChatModel;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import dev.langchain4j.model.openai.OpenAiChatModel;
|
||||
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
|
||||
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* 聊天消息Service接口
|
||||
*
|
||||
@@ -21,6 +25,23 @@ public interface AbstractChatService {
|
||||
*/
|
||||
StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest);
|
||||
|
||||
/**
|
||||
* 创建同步聊天模型(供 Agent/SupervisorAgent 使用)
|
||||
* 默认实现使用 OpenAI 兼容协议,适用于 OpenAI、DeepSeek、PPIO 等兼容接口的 provider。
|
||||
* ZhiPu、QianWen、Ollama 等需覆盖此方法使用各自 SDK。
|
||||
*
|
||||
* @param chatModelVo 模型配置
|
||||
* @return 同步聊天模型实例
|
||||
*/
|
||||
default ChatModel buildChatModel(ChatModelVo chatModelVo) {
|
||||
return OpenAiChatModel.builder()
|
||||
.baseUrl(chatModelVo.getApiHost())
|
||||
.apiKey(chatModelVo.getApiKey())
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.timeout(Duration.ofSeconds(120))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务提供商名称
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.ruoyi.service.chat.impl.provider;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import dev.langchain4j.model.chat.ChatModel;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import dev.langchain4j.model.openai.OpenAiChatModel;
|
||||
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ruoyi.common.chat.domain.dto.request.ChatRequest;
|
||||
import org.ruoyi.common.chat.domain.vo.chat.ChatModelVo;
|
||||
import org.ruoyi.enums.ChatModeType;
|
||||
import org.ruoyi.observability.MyChatModelListener;
|
||||
import org.ruoyi.service.chat.AbstractChatService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义 API 服务调用
|
||||
*
|
||||
* 适用于 OpenAI 兼容接口或仅通过通用 HTTP 协议接入的第三方大模型服务。
|
||||
* 通过模型配置中的 apiHost / apiKey / modelName 即可复用,不需要再写死具体供应商。
|
||||
*
|
||||
* @author better
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class CustomApiServiceImpl implements AbstractChatService {
|
||||
|
||||
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(180);
|
||||
|
||||
@Override
|
||||
public StreamingChatModel buildStreamingChatModel(ChatModelVo chatModelVo, ChatRequest chatRequest) {
|
||||
return OpenAiStreamingChatModel.builder()
|
||||
.baseUrl(normalizeBaseUrl(chatModelVo.getApiHost()))
|
||||
.apiKey(defaultIfBlank(chatModelVo.getApiKey(), "EMPTY"))
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.timeout(DEFAULT_TIMEOUT)
|
||||
.listeners(List.of(new MyChatModelListener()))
|
||||
.returnThinking(chatRequest.getEnableThinking())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatModel buildChatModel(ChatModelVo chatModelVo) {
|
||||
return OpenAiChatModel.builder()
|
||||
.baseUrl(normalizeBaseUrl(chatModelVo.getApiHost()))
|
||||
.apiKey(defaultIfBlank(chatModelVo.getApiKey(), "EMPTY"))
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.timeout(DEFAULT_TIMEOUT)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return ChatModeType.CUSTOM_API.getCode();
|
||||
}
|
||||
|
||||
private String normalizeBaseUrl(String baseUrl) {
|
||||
if (StrUtil.isBlank(baseUrl)) {
|
||||
throw new IllegalArgumentException("自定义API的请求地址(apiHost)不能为空");
|
||||
}
|
||||
return baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
||||
}
|
||||
|
||||
private String defaultIfBlank(String value, String defaultValue) {
|
||||
return StrUtil.isBlank(value) ? defaultValue : value;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.ruoyi.service.chat.impl.provider;
|
||||
|
||||
|
||||
import dev.langchain4j.model.chat.ChatModel;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import dev.langchain4j.model.ollama.OllamaChatModel;
|
||||
import dev.langchain4j.model.ollama.OllamaStreamingChatModel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -37,6 +39,14 @@ public class OllamaServiceImpl implements AbstractChatService {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatModel buildChatModel(ChatModelVo chatModelVo) {
|
||||
return OllamaChatModel.builder()
|
||||
.baseUrl(chatModelVo.getApiHost())
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return ChatModeType.OLLAMA.getCode();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.ruoyi.service.chat.impl.provider;
|
||||
|
||||
|
||||
import dev.langchain4j.community.model.dashscope.QwenChatModel;
|
||||
import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
|
||||
import dev.langchain4j.model.chat.ChatModel;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -38,6 +40,14 @@ public class QianWenChatServiceImpl implements AbstractChatService {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatModel buildChatModel(ChatModelVo chatModelVo) {
|
||||
return QwenChatModel.builder()
|
||||
.apiKey(chatModelVo.getApiKey())
|
||||
.modelName(chatModelVo.getModelName())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return ChatModeType.QIAN_WEN.getCode();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.ruoyi.service.chat.impl.provider;
|
||||
|
||||
|
||||
import dev.langchain4j.community.model.zhipu.ZhipuAiChatModel;
|
||||
import dev.langchain4j.community.model.zhipu.ZhipuAiStreamingChatModel;
|
||||
import dev.langchain4j.model.chat.ChatModel;
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -35,6 +37,14 @@ public class ZhiPuChatServiceImpl implements AbstractChatService {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatModel buildChatModel(ChatModelVo chatModelVo) {
|
||||
return ZhipuAiChatModel.builder()
|
||||
.apiKey(chatModelVo.getApiKey())
|
||||
.model(chatModelVo.getModelName())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderName() {
|
||||
return ChatModeType.ZHI_PU.getCode();
|
||||
|
||||
Reference in New Issue
Block a user