·1
This commit is contained in:
38
lidee-tool/tool-spring-boot-starter-ai/.flattened-pom.xml
Normal file
38
lidee-tool/tool-spring-boot-starter-ai/.flattened-pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>lidee-tool</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</parent>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-spring-boot-starter-ai</artifactId>
|
||||
<version>2.2.4</version>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>LideeYunJi低代码平台 - ai模块</description>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-spring-boot-starter-yunji</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
47
lidee-tool/tool-spring-boot-starter-ai/pom.xml
Normal file
47
lidee-tool/tool-spring-boot-starter-ai/pom.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>lidee-tool</artifactId>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<version>${lidee.version}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>tool-spring-boot-starter-ai</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${lidee.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
<description> LideeYunJi低代码平台 - ai模块 </description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-spring-boot-starter-yunji</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>com.lideeyunji</groupId>
|
||||
<artifactId>tool-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.lideeyunji.tool.framework.ai;
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
import com.lideeyunji.tool.framework.ai.chat.tool.ChatMessage;
|
||||
import com.lideeyunji.tool.framework.ai.chat.tool.Choice;
|
||||
import com.lideeyunji.tool.framework.ai.config.DeepSeekConfig;
|
||||
import com.lideeyunji.tool.framework.ai.config.KimiConfig;
|
||||
import com.lideeyunji.tool.framework.ai.service.Configuration;
|
||||
import com.lideeyunji.tool.framework.ai.service.IChatService;
|
||||
import com.lideeyunji.tool.framework.ai.service.PlatformType;
|
||||
import com.lideeyunji.tool.framework.ai.service.factor.AiService;
|
||||
import com.lideeyunji.tool.framework.ai.template.CreateTableTemplate;
|
||||
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TestUtils {
|
||||
private IChatService chatService;
|
||||
|
||||
@Before
|
||||
public void test_init() throws NoSuchAlgorithmException, KeyManagementException {
|
||||
KimiConfig kimiConfig = new KimiConfig();
|
||||
kimiConfig.setApiKey("sk-EE98wvDeTFvxRcBxDQmWhKQlewkGFIrfyCxvyNxDj8Vaf701");
|
||||
|
||||
|
||||
DeepSeekConfig deepseekConfig = new DeepSeekConfig();
|
||||
deepseekConfig.setApiKey("sk-b31fcf4e27bf45fbb65ace5bbc627d5d");
|
||||
|
||||
Configuration configuration = new Configuration();
|
||||
configuration.setKimiConfig(kimiConfig);
|
||||
configuration.setDeepSeekConfig(deepseekConfig);
|
||||
|
||||
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
.Builder()
|
||||
.connectTimeout(300, TimeUnit.SECONDS)
|
||||
.writeTimeout(300, TimeUnit.SECONDS)
|
||||
.readTimeout(300, TimeUnit.SECONDS)
|
||||
.build();
|
||||
configuration.setOkHttpClient(okHttpClient);
|
||||
|
||||
AiService aiService = new AiService(configuration);
|
||||
|
||||
chatService = aiService.getChatService(PlatformType.KIMI);
|
||||
//chatService = aiService.getChatService(PlatformType.DEEPSEEK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void test_chatCompletions_common() throws Exception {
|
||||
|
||||
long time1 = System.currentTimeMillis();
|
||||
|
||||
ChatBaseRequest chatBaseRequest = ChatBaseRequest.builder()
|
||||
//.model("deepseek-chat")
|
||||
.messages(CreateTableTemplate.getMessageTemplateList())
|
||||
.message(ChatMessage.withUser("物流信息,其中要有,物流单号,收件人,寄件人"))
|
||||
.build();
|
||||
|
||||
|
||||
ChatBaseResponse chatBaseResponse = chatService.chatCompletion(chatBaseRequest);
|
||||
List<Choice> choices = chatBaseResponse.getChoices();
|
||||
if(FuncBase.isEmpty(choices)){
|
||||
return;
|
||||
}
|
||||
Choice choice = choices.get(0);
|
||||
ChatMessage message = choice.getMessage();
|
||||
if(FuncBase.isEmpty(message)){
|
||||
return;
|
||||
}
|
||||
String content = message.getContent();
|
||||
System.out.println("content===="+content);
|
||||
CreateTableTemplate.RspModel rspModel = FuncBase.json2Bean(content, CreateTableTemplate.RspModel.class);
|
||||
System.out.println(rspModel);
|
||||
long time2 = System.currentTimeMillis();
|
||||
|
||||
System.out.println("time2-time1="+(time2-time1));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.lideeyunji.tool.framework.ai.chat.tool.ChatMessage;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
public class ChatBaseRequest {
|
||||
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@Singular
|
||||
private List<ChatMessage> messages;
|
||||
|
||||
/**
|
||||
* 介于 -2.0 和 2.0 之间的数字。如果该值为正,那么新 token 会根据其在已有文本中的出现频率受到相应的惩罚,降低模型重复相同内容的可能性。
|
||||
*/
|
||||
@Builder.Default
|
||||
@JsonProperty("frequency_penalty")
|
||||
private Float frequencyPenalty = 0f;
|
||||
|
||||
/**
|
||||
* 采样温度,介于 0 和 2 之间。更高的值,如 0.8,会使输出更随机,而更低的值,如 0.2,会使其更加集中和确定。
|
||||
* 我们通常建议可以更改这个值或者更改 top_p,但不建议同时对两者进行修改。
|
||||
*/
|
||||
@Builder.Default
|
||||
private Float temperature = 1f;
|
||||
|
||||
/**
|
||||
* 作为调节采样温度的替代方案,模型会考虑前 top_p 概率的 token 的结果。所以 0.1 就意味着只有包括在最高 10% 概率中的 token 会被考虑。
|
||||
* 我们通常建议修改这个值或者更改 temperature,但不建议同时对两者进行修改。
|
||||
*/
|
||||
@Builder.Default
|
||||
@JsonProperty("top_p")
|
||||
private Float topP = 1f;
|
||||
|
||||
/**
|
||||
* 限制一次请求中模型生成 completion 的最大 token 数。输入 token 和输出 token 的总长度受模型的上下文长度的限制。
|
||||
*/
|
||||
@JsonProperty("max_tokens")
|
||||
private Integer maxTokens;
|
||||
|
||||
/**
|
||||
* 辅助属性
|
||||
*/
|
||||
@JsonIgnore
|
||||
private List<String> functions;
|
||||
|
||||
/**
|
||||
* 控制模型调用 tool 的行为。
|
||||
* none 意味着模型不会调用任何 tool,而是生成一条消息。
|
||||
* auto 意味着模型可以选择生成一条消息或调用一个或多个 tool。
|
||||
* 当没有 tool 时,默认值为 none。如果有 tool 存在,默认值为 auto。
|
||||
*/
|
||||
@JsonProperty("tool_choice")
|
||||
private String toolChoice;
|
||||
|
||||
@Builder.Default
|
||||
@JsonProperty("parallel_tool_calls")
|
||||
private Boolean parallelToolCalls = true;
|
||||
|
||||
/**
|
||||
* 一个 object,指定模型必须输出的格式。
|
||||
*
|
||||
* 设置为 { "type": "json_object" } 以启用 JSON 模式,该模式保证模型生成的消息是有效的 JSON。
|
||||
*
|
||||
* 注意: 使用 JSON 模式时,你还必须通过系统或用户消息指示模型生成 JSON。
|
||||
* 否则,模型可能会生成不断的空白字符,直到生成达到令牌限制,从而导致请求长时间运行并显得“卡住”。
|
||||
* 此外,如果 finish_reason="length",这表示生成超过了 max_tokens 或对话超过了最大上下文长度,消息内容可能会被部分截断。
|
||||
*/
|
||||
@JsonProperty("response_format")
|
||||
private Object responseFormat;
|
||||
|
||||
private String user;
|
||||
|
||||
@Builder.Default
|
||||
private Integer n = 1;
|
||||
|
||||
/**
|
||||
* 在遇到这些词时,API 将停止生成更多的 token。
|
||||
*/
|
||||
private List<String> stop;
|
||||
|
||||
/**
|
||||
* 介于 -2.0 和 2.0 之间的数字。如果该值为正,那么新 token 会根据其是否已在已有文本中出现受到相应的惩罚,从而增加模型谈论新主题的可能性。
|
||||
*/
|
||||
@Builder.Default
|
||||
@JsonProperty("presence_penalty")
|
||||
private Float presencePenalty = 0f;
|
||||
|
||||
@JsonProperty("logit_bias")
|
||||
private Map logitBias;
|
||||
|
||||
/**
|
||||
* 是否返回所输出 token 的对数概率。如果为 true,则在 message 的 content 中返回每个输出 token 的对数概率。
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean logprobs = false;
|
||||
|
||||
/**
|
||||
* 一个介于 0 到 20 之间的整数 N,指定每个输出位置返回输出概率 top N 的 token,且返回这些 token 的对数概率。指定此参数时,logprobs 必须为 true。
|
||||
*/
|
||||
@JsonProperty("top_logprobs")
|
||||
private Integer topLogprobs;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.lideeyunji.tool.framework.ai.chat.tool.Choice;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatBaseResponse {
|
||||
/**
|
||||
* 该对话的唯一标识符。
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 对象的类型, 其值为 chat.completion 或 chat.completion.chunk
|
||||
*/
|
||||
private String object;
|
||||
|
||||
/**
|
||||
* 创建聊天完成时的 Unix 时间戳(以秒为单位)。
|
||||
*/
|
||||
private Long created;
|
||||
|
||||
/**
|
||||
* 生成该 completion 的模型名。
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 该指纹代表模型运行时使用的后端配置。
|
||||
*/
|
||||
@JsonProperty("system_fingerprint")
|
||||
private String systemFingerprint;
|
||||
|
||||
/**
|
||||
* 模型生成的 completion 的选择列表。
|
||||
*/
|
||||
private List<Choice> choices;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat;
|
||||
|
||||
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ChatMessageType {
|
||||
SYSTEM("system"),
|
||||
USER("user"),
|
||||
ASSISTANT("assistant"),
|
||||
TOOL("tool"),
|
||||
;
|
||||
|
||||
private final String role;
|
||||
|
||||
public static ChatMessageType getByRole(String role) {
|
||||
// 使用流来查找匹配的
|
||||
Optional<ChatMessageType> matchingEnum = Arrays.stream(ChatMessageType.values())
|
||||
.filter(chatMessageType -> FuncBase.equals(chatMessageType.getRole(), role))
|
||||
.findFirst(); // findFirst()会返回第一个匹配的元素,或者如果找不到则返回一个空的Optional
|
||||
// 检查是否找到了匹配的枚举项
|
||||
if (matchingEnum.isPresent()) {
|
||||
return matchingEnum.get();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.deepseek;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.lideeyunji.tool.framework.ai.config.DeepSeekConfig;
|
||||
import com.lideeyunji.tool.framework.ai.convert.ParameterConvert;
|
||||
import com.lideeyunji.tool.framework.ai.convert.ResultConvert;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
import com.lideeyunji.tool.framework.ai.chat.deepseek.entity.DeepSeekChatRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.deepseek.entity.DeepSeekChatResponse;
|
||||
import com.lideeyunji.tool.framework.ai.service.Configuration;
|
||||
import com.lideeyunji.tool.framework.ai.service.IChatService;
|
||||
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
|
||||
import okhttp3.*;
|
||||
|
||||
|
||||
public class DeepSeekChatService implements IChatService, ParameterConvert<DeepSeekChatRequest>, ResultConvert<DeepSeekChatResponse> {
|
||||
private final DeepSeekConfig deepSeekConfig;
|
||||
private final OkHttpClient okHttpClient;
|
||||
|
||||
|
||||
public DeepSeekChatService(Configuration configuration) {
|
||||
this.deepSeekConfig = configuration.getDeepSeekConfig();
|
||||
this.okHttpClient = configuration.getOkHttpClient();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DeepSeekChatRequest convertParam(ChatBaseRequest chatBaseRequest) {
|
||||
DeepSeekChatRequest deepSeekChatRequest = DeepSeekChatRequest.builder()
|
||||
.messages(chatBaseRequest.getMessages())
|
||||
.frequencyPenalty(chatBaseRequest.getFrequencyPenalty())
|
||||
.maxTokens(chatBaseRequest.getMaxTokens())
|
||||
.presencePenalty(chatBaseRequest.getPresencePenalty())
|
||||
.responseFormat(chatBaseRequest.getResponseFormat())
|
||||
.stop(chatBaseRequest.getStop())
|
||||
.temperature(chatBaseRequest.getTemperature() / 2)
|
||||
.topP(chatBaseRequest.getTopP())
|
||||
.functions(chatBaseRequest.getFunctions())
|
||||
.toolChoice(chatBaseRequest.getToolChoice())
|
||||
.build();
|
||||
return deepSeekChatRequest;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChatBaseResponse convertResponse(DeepSeekChatResponse deepSeekChatResponse) {
|
||||
ChatBaseResponse chatBaseResponse = new ChatBaseResponse();
|
||||
chatBaseResponse.setId(deepSeekChatResponse.getId());
|
||||
chatBaseResponse.setObject(deepSeekChatResponse.getObject());
|
||||
chatBaseResponse.setCreated(deepSeekChatResponse.getCreated());
|
||||
chatBaseResponse.setModel(deepSeekChatResponse.getModel());
|
||||
chatBaseResponse.setSystemFingerprint(deepSeekChatResponse.getSystemFingerprint());
|
||||
chatBaseResponse.setChoices(deepSeekChatResponse.getChoices());
|
||||
return chatBaseResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatBaseResponse chatCompletion(String baseUrl, String apiKey, ChatBaseRequest chatBaseRequest) throws Exception {
|
||||
baseUrl = FuncBase.isEmpty(baseUrl) ? deepSeekConfig.getApiHost() : baseUrl;
|
||||
apiKey = FuncBase.isEmpty(apiKey) ? deepSeekConfig.getApiKey() : apiKey;
|
||||
|
||||
// 转换 请求参数
|
||||
DeepSeekChatRequest deepSeekChatRequest = this.convertParam(chatBaseRequest);
|
||||
deepSeekChatRequest.setModel(deepSeekConfig.getModel());
|
||||
|
||||
// 构造请求
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String requestString = mapper.writeValueAsString(deepSeekChatRequest);
|
||||
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.header("Authorization", "Bearer " + apiKey)
|
||||
.url(baseUrl + deepSeekConfig.getChatCompletionUrl())
|
||||
.post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestString))
|
||||
.build();
|
||||
|
||||
Response execute = okHttpClient.newCall(request).execute();
|
||||
if (FuncBase.isEmpty(execute)) {
|
||||
return null;
|
||||
}
|
||||
if (FuncBase.isEmpty(execute.body())) {
|
||||
return null;
|
||||
}
|
||||
//转为统一格式
|
||||
String rsp = execute.body().string();
|
||||
DeepSeekChatResponse moonshotChatCompletionResponse = FuncBase.json2Bean(rsp, DeepSeekChatResponse.class);
|
||||
return this.convertResponse(moonshotChatCompletionResponse);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatBaseResponse chatCompletion(ChatBaseRequest chatBaseRequest) throws Exception {
|
||||
return this.chatCompletion(null, null, chatBaseRequest);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.deepseek.entity;
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
public class DeepSeekChatRequest extends ChatBaseRequest {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.deepseek.entity;
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 聊天返回结果
|
||||
*/
|
||||
@Data
|
||||
public class DeepSeekChatResponse extends ChatBaseResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.kimi;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.config.KimiConfig;
|
||||
import com.lideeyunji.tool.framework.ai.convert.ParameterConvert;
|
||||
import com.lideeyunji.tool.framework.ai.convert.ResultConvert;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
import com.lideeyunji.tool.framework.ai.chat.kimi.entity.KimiChatRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.kimi.entity.KimiChatResponse;
|
||||
import com.lideeyunji.tool.framework.ai.service.Configuration;
|
||||
import com.lideeyunji.tool.framework.ai.service.IChatService;
|
||||
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
|
||||
import okhttp3.*;
|
||||
|
||||
|
||||
public class KimiChatService implements IChatService, ParameterConvert<KimiChatRequest>, ResultConvert<KimiChatResponse> {
|
||||
private final KimiConfig kimiConfig;
|
||||
private final OkHttpClient okHttpClient;
|
||||
|
||||
|
||||
public KimiChatService(Configuration configuration) {
|
||||
this.kimiConfig = configuration.getKimiConfig();
|
||||
this.okHttpClient = configuration.getOkHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KimiChatRequest convertParam(ChatBaseRequest chatBaseRequest) {
|
||||
KimiChatRequest kimiChatRequest = KimiChatRequest.builder()
|
||||
.messages(chatBaseRequest.getMessages())
|
||||
.frequencyPenalty(chatBaseRequest.getFrequencyPenalty())
|
||||
.maxTokens(chatBaseRequest.getMaxTokens())
|
||||
.presencePenalty(chatBaseRequest.getPresencePenalty())
|
||||
.responseFormat(chatBaseRequest.getResponseFormat())
|
||||
.stop(chatBaseRequest.getStop())
|
||||
.temperature(chatBaseRequest.getTemperature() / 2)
|
||||
.topP(chatBaseRequest.getTopP())
|
||||
.functions(chatBaseRequest.getFunctions())
|
||||
.toolChoice(chatBaseRequest.getToolChoice())
|
||||
.build();
|
||||
return kimiChatRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回复内容参数转换
|
||||
*/
|
||||
@Override
|
||||
public ChatBaseResponse convertResponse(KimiChatResponse kimiChatResponse) {
|
||||
ChatBaseResponse chatBaseResponse = new ChatBaseResponse();
|
||||
chatBaseResponse.setId(kimiChatResponse.getId());
|
||||
chatBaseResponse.setObject(kimiChatResponse.getObject());
|
||||
chatBaseResponse.setCreated(kimiChatResponse.getCreated());
|
||||
chatBaseResponse.setModel(kimiChatResponse.getModel());
|
||||
chatBaseResponse.setChoices(kimiChatResponse.getChoices());
|
||||
return chatBaseResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步请求
|
||||
*/
|
||||
@Override
|
||||
public ChatBaseResponse chatCompletion(String baseUrl, String apiKey, ChatBaseRequest chatBaseRequest) throws Exception {
|
||||
baseUrl = FuncBase.isEmpty(baseUrl) ? kimiConfig.getApiHost() : baseUrl;
|
||||
apiKey = FuncBase.isEmpty(apiKey) ? kimiConfig.getApiKey() : apiKey;
|
||||
// 转换 请求参数
|
||||
KimiChatRequest kimiChatRequest = this.convertParam(chatBaseRequest);
|
||||
kimiChatRequest.setModel(kimiConfig.getModel());
|
||||
|
||||
// 构造请求
|
||||
String requestString = FuncBase.json2Str(kimiChatRequest);
|
||||
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestString);
|
||||
Request request = new Request.Builder()
|
||||
.header("Authorization", "Bearer " + apiKey)
|
||||
.url(baseUrl+ kimiConfig.getChatCompletionUrl())
|
||||
.post(requestBody)
|
||||
.build();
|
||||
|
||||
Response execute = okHttpClient.newCall(request).execute();
|
||||
if (FuncBase.isEmpty(execute)) {
|
||||
return null;
|
||||
}
|
||||
if (FuncBase.isEmpty(execute.body())) {
|
||||
return null;
|
||||
}
|
||||
//转为统一格式
|
||||
String rsp = execute.body().string();
|
||||
KimiChatResponse kimiChatResponse = FuncBase.json2Bean(rsp, KimiChatResponse.class);
|
||||
return this.convertResponse(kimiChatResponse);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChatBaseResponse chatCompletion(ChatBaseRequest chatBaseRequest) throws Exception {
|
||||
return this.chatCompletion(null, null, chatBaseRequest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.kimi.entity;
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
public class KimiChatRequest extends ChatBaseRequest {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.kimi.entity;
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class KimiChatResponse extends ChatBaseResponse {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.tool;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatMessageType;
|
||||
import lombok.*;
|
||||
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@AllArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ChatMessage {
|
||||
private String content;
|
||||
private String role;
|
||||
private String name;
|
||||
private String refusal;
|
||||
|
||||
@JsonProperty("reasoning_content")
|
||||
private String reasoningContent;
|
||||
|
||||
@JsonProperty("tool_call_id")
|
||||
private String toolCallId;
|
||||
|
||||
public ChatMessage(String userMessage) {
|
||||
this.role = ChatMessageType.USER.getRole();
|
||||
this.content =userMessage;
|
||||
}
|
||||
public ChatMessage(ChatMessageType role, String message) {
|
||||
this.role = role.getRole();
|
||||
this.content = message;
|
||||
}
|
||||
public ChatMessage(String role, String message) {
|
||||
this.role = role;
|
||||
this.content = message;
|
||||
}
|
||||
|
||||
public static ChatMessage withSystem(String content) {
|
||||
return new ChatMessage(ChatMessageType.SYSTEM, content);
|
||||
}
|
||||
|
||||
public static ChatMessage withUser(String content) {
|
||||
return new ChatMessage(ChatMessageType.USER, content);
|
||||
}
|
||||
|
||||
public static ChatMessage withAssistant(String content) {
|
||||
return new ChatMessage(ChatMessageType.ASSISTANT, content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.tool;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Choice {
|
||||
private Integer index;
|
||||
|
||||
private ChatMessage delta;
|
||||
private ChatMessage message;
|
||||
|
||||
private Object logprobs;
|
||||
|
||||
/**
|
||||
* 模型停止生成 token 的原因。
|
||||
*
|
||||
* [stop, length, content_filter, tool_calls, insufficient_system_resource]
|
||||
*
|
||||
* stop:模型自然停止生成,或遇到 stop 序列中列出的字符串。
|
||||
* length:输出长度达到了模型上下文长度限制,或达到了 max_tokens 的限制。
|
||||
* content_filter:输出内容因触发过滤策略而被过滤。
|
||||
* tool_calls:函数调用。
|
||||
* insufficient_system_resource:系统推理资源不足,生成被打断。
|
||||
*
|
||||
*/
|
||||
@JsonProperty("finish_reason")
|
||||
private String finishReason;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.lideeyunji.tool.framework.ai.chat.tool;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import lombok.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ToString
|
||||
public class Content {
|
||||
private String text; // 纯文本时使用
|
||||
private List<MultiModal> multiModals; // 多模态时使用
|
||||
|
||||
// 纯文本构造方法
|
||||
public static Content ofText(String text) {
|
||||
Content instance = new Content();
|
||||
instance.text = text;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// 多模态构造方法
|
||||
public static Content ofMultiModals(List<MultiModal> parts) {
|
||||
Content instance = new Content();
|
||||
instance.multiModals = parts;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// 序列化逻辑
|
||||
@JsonValue
|
||||
public Object toJson() {
|
||||
if (text != null) {
|
||||
return text; // 直接返回
|
||||
} else if (multiModals != null) {
|
||||
return multiModals;
|
||||
}
|
||||
throw new IllegalStateException("Invalid content state");
|
||||
}
|
||||
|
||||
public String getText() { return text; }
|
||||
public List<MultiModal> getMultiModals() { return multiModals; }
|
||||
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public static class MultiModal {
|
||||
private String type = Type.TEXT.type;
|
||||
private String text;
|
||||
@JsonProperty("image_url")
|
||||
private ImageUrl imageUrl;
|
||||
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ImageUrl {
|
||||
private String url;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Type {
|
||||
TEXT("text", "文本类型"),
|
||||
IMAGE_URL("image_url", "图片类型,可以为url或者base64"),
|
||||
;
|
||||
private final String type;
|
||||
private final String info;
|
||||
}
|
||||
|
||||
public static List<MultiModal> withMultiModal(String text, String... imageUrl) {
|
||||
List<MultiModal> messages = new ArrayList<>();
|
||||
messages.add(new MultiModal(Type.TEXT.getType(), text, null));
|
||||
for (String url : imageUrl) {
|
||||
messages.add(new MultiModal(Type.IMAGE_URL.getType(), null, new ImageUrl(url)));
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lideeyunji.tool.framework.ai.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DeepSeekConfig {
|
||||
|
||||
private String apiHost = "https://api.deepseek.com/";
|
||||
private String apiKey = "";
|
||||
|
||||
private String model="deepseek-chat";
|
||||
|
||||
private String chatCompletionUrl = "chat/completions";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.lideeyunji.tool.framework.ai.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class KimiConfig {
|
||||
private String apiHost = "https://api.moonshot.cn/";
|
||||
private String apiKey = "";
|
||||
private String model="moonshot-v1-8k";
|
||||
private String chatCompletionUrl = "v1/chat/completions";
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.lideeyunji.tool.framework.ai.convert;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
|
||||
|
||||
public interface ParameterConvert<T> {
|
||||
T convertParam(ChatBaseRequest chatBaseRequest);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lideeyunji.tool.framework.ai.convert;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
|
||||
|
||||
public interface ResultConvert<T> {
|
||||
//统一格式输出
|
||||
ChatBaseResponse convertResponse(T t);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.lideeyunji.tool.framework.ai.properties;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.config.DeepSeekConfig;
|
||||
import com.lideeyunji.tool.framework.ai.config.KimiConfig;
|
||||
import com.lideeyunji.tool.framework.ai.service.factor.AiService;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({
|
||||
DeepSeekConfigProperties.class,
|
||||
KimiConfigProperties.class})
|
||||
|
||||
public class AiConfigAutoConfiguration {
|
||||
|
||||
|
||||
private final DeepSeekConfigProperties deepSeekConfigProperties;
|
||||
private final KimiConfigProperties kimiConfigProperties;
|
||||
|
||||
|
||||
private com.lideeyunji.tool.framework.ai.service.Configuration configuration = new com.lideeyunji.tool.framework.ai.service.Configuration();
|
||||
|
||||
public AiConfigAutoConfiguration(DeepSeekConfigProperties deepSeekConfigProperties, KimiConfigProperties kimiConfigProperties) {
|
||||
this.deepSeekConfigProperties = deepSeekConfigProperties;
|
||||
this.kimiConfigProperties = kimiConfigProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AiService aiService() {
|
||||
return new AiService(configuration);
|
||||
}
|
||||
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
initOkHttp();
|
||||
initDeepSeekConfig();
|
||||
initMoonshotConfig();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void initOkHttp() {
|
||||
// 开启 Http 客户端
|
||||
OkHttpClient.Builder okHttpBuilder = new OkHttpClient
|
||||
.Builder()
|
||||
.connectTimeout(300, TimeUnit.SECONDS)
|
||||
.writeTimeout(300,TimeUnit.SECONDS)
|
||||
.readTimeout(300, TimeUnit.SECONDS);
|
||||
OkHttpClient okHttpClient = okHttpBuilder.build();
|
||||
|
||||
configuration.setOkHttpClient(okHttpClient);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化DeepSeek 配置信息
|
||||
*/
|
||||
private void initDeepSeekConfig(){
|
||||
DeepSeekConfig deepSeekConfig = new DeepSeekConfig();
|
||||
deepSeekConfig.setApiHost(deepSeekConfigProperties.getApiHost());
|
||||
deepSeekConfig.setApiKey(deepSeekConfigProperties.getApiKey());
|
||||
deepSeekConfig.setModel(deepSeekConfigProperties.getModel());
|
||||
deepSeekConfig.setChatCompletionUrl(deepSeekConfigProperties.getChatCompletionUrl());
|
||||
|
||||
configuration.setDeepSeekConfig(deepSeekConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Moonshot 配置信息
|
||||
*/
|
||||
private void initMoonshotConfig() {
|
||||
KimiConfig kimiConfig = new KimiConfig();
|
||||
kimiConfig.setApiHost(kimiConfigProperties.getApiHost());
|
||||
kimiConfig.setApiKey(kimiConfigProperties.getApiKey());
|
||||
kimiConfig.setModel(kimiConfigProperties.getModel());
|
||||
kimiConfig.setChatCompletionUrl(kimiConfigProperties.getChatCompletionUrl());
|
||||
|
||||
configuration.setKimiConfig(kimiConfig);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lideeyunji.tool.framework.ai.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "lideeyunji.ai.deepseek")
|
||||
public class DeepSeekConfigProperties {
|
||||
|
||||
private String apiHost = "https://api.deepseek.com/";
|
||||
private String apiKey = "";
|
||||
private String model="deepseek-chat";
|
||||
private String chatCompletionUrl = "chat/completions";
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lideeyunji.tool.framework.ai.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @Author cly
|
||||
* @Description Moonshot配置文件
|
||||
* @Date 2024/8/30 15:56
|
||||
*/
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "lideeyunji.ai.kimi")
|
||||
public class KimiConfigProperties {
|
||||
private String apiHost = "https://api.moonshot.cn/";
|
||||
private String apiKey = "";
|
||||
private String model = "moonshot-v1-8k";
|
||||
private String chatCompletionUrl = "v1/chat/completions";
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lideeyunji.tool.framework.ai.service;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.config.DeepSeekConfig;
|
||||
import com.lideeyunji.tool.framework.ai.config.KimiConfig;
|
||||
import com.lideeyunji.tool.framework.ai.websearch.searxng.SearXNGConfig;
|
||||
import lombok.Data;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
|
||||
|
||||
@Data
|
||||
public class Configuration {
|
||||
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
private DeepSeekConfig deepSeekConfig;
|
||||
|
||||
private KimiConfig kimiConfig;
|
||||
|
||||
private SearXNGConfig searXNGConfig;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lideeyunji.tool.framework.ai.service;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
|
||||
|
||||
public interface IChatService {
|
||||
|
||||
//同步消息
|
||||
ChatBaseResponse chatCompletion(String baseUrl, String apiKey, ChatBaseRequest chatBaseRequest) throws Exception;
|
||||
ChatBaseResponse chatCompletion(ChatBaseRequest chatBaseRequest) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.lideeyunji.tool.framework.ai.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum PlatformType {
|
||||
DEEPSEEK("deepseek"),
|
||||
KIMI("kimi"),
|
||||
;
|
||||
private final String platform;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lideeyunji.tool.framework.ai.service.factor;
|
||||
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.deepseek.DeepSeekChatService;
|
||||
import com.lideeyunji.tool.framework.ai.chat.kimi.KimiChatService;
|
||||
import com.lideeyunji.tool.framework.ai.service.Configuration;
|
||||
import com.lideeyunji.tool.framework.ai.service.IChatService;
|
||||
import com.lideeyunji.tool.framework.ai.service.PlatformType;
|
||||
import com.lideeyunji.tool.framework.ai.websearch.ChatWithWebSearchEnhance;
|
||||
|
||||
|
||||
public class AiService {
|
||||
|
||||
private final Configuration configuration;
|
||||
|
||||
public AiService(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
public IChatService getChatService(PlatformType platform) {
|
||||
return createChatService(platform);
|
||||
}
|
||||
|
||||
public IChatService webSearchEnhance(IChatService chatService) {
|
||||
return new ChatWithWebSearchEnhance(chatService, configuration);
|
||||
}
|
||||
|
||||
private IChatService createChatService(PlatformType platform) {
|
||||
switch (platform) {
|
||||
case KIMI:
|
||||
return new KimiChatService(configuration);
|
||||
case DEEPSEEK:
|
||||
return new DeepSeekChatService(configuration);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown platform: " + platform);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.lideeyunji.tool.framework.ai.template;
|
||||
|
||||
import com.lideeyunji.tool.framework.ai.chat.tool.ChatMessage;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CreateTableTemplate {
|
||||
//获取模板
|
||||
public static List<ChatMessage> getMessageTemplateList(){
|
||||
List<ChatMessage> sysMessageList=new ArrayList<>();
|
||||
sysMessageList.add(ChatMessage.withSystem("你是一个mysql数据库设计专家,你需要根据用户的需求理解设计出数据表,然后按特定格式返回"));
|
||||
sysMessageList.add(ChatMessage.withSystem("表信息解析:tableName:表名称,其中必须是tbl_ 开头。 tableDescribe:表中文描述"));
|
||||
sysMessageList.add(ChatMessage.withSystem("字段解析:fieldCode:字段编码,fieldName:字段名称,fieldLen:字段长度,fieldDefaultVal:默认值,fieldType:字段类型"));
|
||||
sysMessageList.add(ChatMessage.withSystem("其中fieldType:字段类型的值有:String=字符串类型,Integer=整型,Date=日期(yyyy-MM-dd),DateTime=日期时间(yyyy-MM-dd HH:mm:ss),Time=时间(HH:mm:ss),BigInt=长整型(long),BigDecimal=小数,LongText=长文本,Blob=二进制"));
|
||||
sysMessageList.add(ChatMessage.withSystem("其中必须有的字段未:id,tenant_id,create_user,create_time,create_dept,update_user,update_time,is_deleted"));
|
||||
sysMessageList.add(ChatMessage.withSystem("这个是返回格式,一定要以json格式返回,其他不必要的内容不要返回:{\"tableName\":\"tbl_name\",\"tableDescribe\":\"学生表\",\"fieldModelList\":[{\"fieldCode\":\"name\",\"fieldName\":\"姓名\",\"fieldLen\":10,\"fieldPointLen\":0,\"fieldDefaultVal\":\"\",\"fieldType\":\"String\"},{\"fieldCode\":\"age\",\"fieldName\":\"年龄\",\"fieldLen\":10,\"fieldPointLen\":0,\"fieldDefaultVal\":\"\",\"fieldType\":\"String\"}]}\n"));
|
||||
sysMessageList.add(ChatMessage.withSystem("返回格式[重要]:只需要返回json格式即可 ,其他不必要的内容不要返回"));
|
||||
|
||||
|
||||
return sysMessageList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class RspModel{
|
||||
private String tableName;//表名称
|
||||
private String tableDescribe;//表描述
|
||||
List<FieldModel> fieldModelList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class FieldModel{
|
||||
private String fieldCode;//字段编号 例如:name
|
||||
private String fieldName;//字段名称 例如:姓名
|
||||
|
||||
private Integer fieldLen;//字段长度
|
||||
private Integer fieldPointLen;//字段小数位
|
||||
private String fieldDefaultVal;//默认值
|
||||
private String fieldType;//字段类型
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.lideeyunji.tool.framework.ai.websearch;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseRequest;
|
||||
import com.lideeyunji.tool.framework.ai.chat.ChatBaseResponse;
|
||||
import com.lideeyunji.tool.framework.ai.service.Configuration;
|
||||
import com.lideeyunji.tool.framework.ai.service.IChatService;
|
||||
import com.lideeyunji.tool.framework.ai.websearch.searxng.SearXNGConfig;
|
||||
import com.lideeyunji.tool.framework.ai.websearch.searxng.SearXNGRequest;
|
||||
import com.lideeyunji.tool.framework.ai.websearch.searxng.SearXNGResponse;
|
||||
import com.lideeyunji.tool.framework.exception.lideeYunJiException;
|
||||
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
|
||||
public class ChatWithWebSearchEnhance implements IChatService {
|
||||
private final IChatService chatService;
|
||||
private final SearXNGConfig searXNGConfig;
|
||||
private final OkHttpClient okHttpClient;
|
||||
public ChatWithWebSearchEnhance(IChatService chatService, Configuration configuration) {
|
||||
this.chatService = chatService;
|
||||
this.searXNGConfig = configuration.getSearXNGConfig();
|
||||
this.okHttpClient = configuration.getOkHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatBaseResponse chatCompletion(String baseUrl, String apiKey, ChatBaseRequest chatBaseRequest) throws Exception {
|
||||
return chatService.chatCompletion(baseUrl, apiKey, addWebSearchResults(chatBaseRequest));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatBaseResponse chatCompletion(ChatBaseRequest chatBaseRequest) throws Exception {
|
||||
return chatService.chatCompletion(addWebSearchResults(chatBaseRequest));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ChatBaseRequest addWebSearchResults(ChatBaseRequest chatBaseRequest) {
|
||||
int chatLen = chatBaseRequest.getMessages().size();
|
||||
String prompt = chatBaseRequest.getMessages().get(chatLen - 1).getContent();
|
||||
// 执行联网搜索并将结果附加到提示词中
|
||||
String searchResults = performWebSearch(prompt);
|
||||
chatBaseRequest.getMessages().get(chatLen - 1).setContent("我将提供一段来自互联网的资料信息, 请根据这段资料以及用户提出的问题来给出回答。请确保在回答中使用Markdown格式,并在回答末尾列出参考资料。如果资料中的信息不足以回答用户的问题,可以根据自身知识库进行补充,或者说明无法提供确切的答案。\n" +
|
||||
"网络资料:\n"
|
||||
+ "============\n"
|
||||
+ searchResults
|
||||
+ "============\n"
|
||||
+ "用户问题:\n"
|
||||
+ "============\n"
|
||||
+ prompt
|
||||
+ "============\n");
|
||||
return chatBaseRequest;
|
||||
}
|
||||
|
||||
private String performWebSearch(String query) {
|
||||
|
||||
SearXNGRequest searXNGRequest = SearXNGRequest.builder()
|
||||
.q(query)
|
||||
.engines(searXNGConfig.getEngines())
|
||||
.build();
|
||||
|
||||
|
||||
if(StringUtils.isBlank(searXNGConfig.getUrl())){
|
||||
throw new lideeYunJiException("SearXNG url is not configured");
|
||||
}
|
||||
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.url(searXNGConfig.getUrl()+ "?format=json&q=" + query + "&engines=" + searXNGConfig.getEngines())
|
||||
.get()
|
||||
.build();
|
||||
|
||||
|
||||
try(Response execute = okHttpClient.newCall(request).execute()) {
|
||||
if (execute.isSuccessful() && execute.body() != null){
|
||||
SearXNGResponse searXNGResponse = FuncBase.json2Bean(execute.body().string(), SearXNGResponse.class);
|
||||
|
||||
if(searXNGResponse.getResults().size() > searXNGConfig.getNums()) {
|
||||
return FuncBase.json2Str(searXNGResponse.getResults().subList(0, searXNGConfig.getNums()));
|
||||
}
|
||||
return FuncBase.json2Str(searXNGResponse.getResults());
|
||||
|
||||
|
||||
}else{
|
||||
throw new Exception("SearXNG request failed");
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new lideeYunJiException("SearXNG request failed");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.lideeyunji.tool.framework.ai.websearch.searxng;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
public class SearXNGConfig {
|
||||
private String url;
|
||||
private String engines = "duckduckgo,google,bing,brave,mojeek,presearch,qwant,startpage,yahoo,arxiv,crossref,google_scholar,internetarchivescholar,semantic_scholar";
|
||||
private int nums = 20;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.lideeyunji.tool.framework.ai.websearch.searxng;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class SearXNGRequest {
|
||||
@Builder.Default
|
||||
private final String format = "json";
|
||||
|
||||
private String q;
|
||||
|
||||
@Builder.Default
|
||||
private String engines = "duckduckgo,google,bing,brave,mojeek,presearch,qwant,startpage,yahoo,arxiv,crossref,google_scholar,internetarchivescholar,semantic_scholar";
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.lideeyunji.tool.framework.ai.websearch.searxng;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Data
|
||||
public class SearXNGResponse {
|
||||
private String query;
|
||||
|
||||
@JsonProperty("number_of_results")
|
||||
private String numberOfResults;
|
||||
|
||||
private List<Result> results;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class Result {
|
||||
private String url;
|
||||
private String title;
|
||||
private String content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.lideeyunji.tool.framework.ai.properties.AiConfigAutoConfiguration
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"name": "lideeyunji.ai.deepseek",
|
||||
"type": "com.lideeyunji.tool.framework.ai.properties.DeepSeekConfigProperties",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.DeepSeekConfigProperties"
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.kimi",
|
||||
"type": "com.lideeyunji.tool.framework.ai.properties.KimiConfigProperties",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.KimiConfigProperties"
|
||||
}
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"name": "lideeyunji.ai.deepseek.api-host",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.DeepSeekConfigProperties",
|
||||
"defaultValue": "https:\/\/api.deepseek.com\/"
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.deepseek.api-key",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.DeepSeekConfigProperties",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.deepseek.chat-completion-url",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.DeepSeekConfigProperties",
|
||||
"defaultValue": "chat\/completions"
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.deepseek.model",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.DeepSeekConfigProperties",
|
||||
"defaultValue": "deepseek-chat"
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.kimi.api-host",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.KimiConfigProperties",
|
||||
"defaultValue": "https:\/\/api.moonshot.cn\/"
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.kimi.api-key",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.KimiConfigProperties",
|
||||
"defaultValue": ""
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.kimi.chat-completion-url",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.KimiConfigProperties",
|
||||
"defaultValue": "v1\/chat\/completions"
|
||||
},
|
||||
{
|
||||
"name": "lideeyunji.ai.kimi.model",
|
||||
"type": "java.lang.String",
|
||||
"sourceType": "com.lideeyunji.tool.framework.ai.properties.KimiConfigProperties",
|
||||
"defaultValue": "moonshot-v1-8k"
|
||||
}
|
||||
],
|
||||
"hints": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.lideeyunji.tool.framework.ai.properties.AiConfigAutoConfiguration
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
artifactId=tool-spring-boot-starter-ai
|
||||
groupId=com.lideeyunji
|
||||
version=2.2.4
|
||||
@@ -0,0 +1,50 @@
|
||||
com\lideeyunji\tool\framework\ai\chat\ChatMessageType.class
|
||||
com\lideeyunji\tool\framework\ai\template\CreateTableTemplate$RspModel.class
|
||||
com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatRequest$1.class
|
||||
com\lideeyunji\tool\framework\ai\service\factor\AiService$1.class
|
||||
META-INF\spring-configuration-metadata.json
|
||||
com\lideeyunji\tool\framework\ai\chat\ChatBaseResponse.class
|
||||
com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGRequest.class
|
||||
com\lideeyunji\tool\framework\ai\chat\ChatBaseRequest$ChatBaseRequestBuilderImpl.class
|
||||
com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatRequest$KimiChatRequestBuilder.class
|
||||
com\lideeyunji\tool\framework\ai\config\DeepSeekConfig.class
|
||||
com\lideeyunji\tool\framework\ai\convert\ResultConvert.class
|
||||
com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGResponse$Result.class
|
||||
com\lideeyunji\tool\framework\ai\chat\kimi\KimiChatService.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\Content$MultiModal$MultiModalBuilder.class
|
||||
com\lideeyunji\tool\framework\ai\service\IChatService.class
|
||||
com\lideeyunji\tool\framework\ai\chat\ChatBaseRequest$1.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\ChatMessage$1.class
|
||||
com\lideeyunji\tool\framework\ai\properties\KimiConfigProperties.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\Content$MultiModal$ImageUrl.class
|
||||
com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatResponse.class
|
||||
com\lideeyunji\tool\framework\ai\config\KimiConfig.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\ChatMessage.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\Choice.class
|
||||
com\lideeyunji\tool\framework\ai\chat\ChatBaseRequest.class
|
||||
com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatRequest.class
|
||||
com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatRequest$DeepSeekChatRequestBuilder.class
|
||||
com\lideeyunji\tool\framework\ai\service\factor\AiService.class
|
||||
com\lideeyunji\tool\framework\ai\properties\DeepSeekConfigProperties.class
|
||||
com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatRequest$KimiChatRequestBuilderImpl.class
|
||||
com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatRequest$1.class
|
||||
com\lideeyunji\tool\framework\ai\TestUtils.class
|
||||
com\lideeyunji\tool\framework\ai\service\Configuration.class
|
||||
com\lideeyunji\tool\framework\ai\service\PlatformType.class
|
||||
com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGRequest$SearXNGRequestBuilder.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\Content.class
|
||||
com\lideeyunji\tool\framework\ai\template\CreateTableTemplate$FieldModel.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\Content$MultiModal$Type.class
|
||||
com\lideeyunji\tool\framework\ai\chat\deepseek\DeepSeekChatService.class
|
||||
com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGResponse.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\Content$MultiModal.class
|
||||
com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGConfig.class
|
||||
com\lideeyunji\tool\framework\ai\convert\ParameterConvert.class
|
||||
com\lideeyunji\tool\framework\ai\chat\ChatBaseRequest$ChatBaseRequestBuilder.class
|
||||
com\lideeyunji\tool\framework\ai\template\CreateTableTemplate.class
|
||||
com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatRequest.class
|
||||
com\lideeyunji\tool\framework\ai\properties\AiConfigAutoConfiguration.class
|
||||
com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatRequest$DeepSeekChatRequestBuilderImpl.class
|
||||
com\lideeyunji\tool\framework\ai\chat\tool\ChatMessage$ChatMessageBuilder.class
|
||||
com\lideeyunji\tool\framework\ai\websearch\ChatWithWebSearchEnhance.class
|
||||
com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatResponse.class
|
||||
@@ -0,0 +1,29 @@
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\service\factor\AiService.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatResponse.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\tool\Content.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\ChatMessageType.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatRequest.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\kimi\entity\KimiChatRequest.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\config\KimiConfig.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\template\CreateTableTemplate.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\config\DeepSeekConfig.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\deepseek\DeepSeekChatService.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\websearch\ChatWithWebSearchEnhance.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\kimi\KimiChatService.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\ChatBaseRequest.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGRequest.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\service\Configuration.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\properties\AiConfigAutoConfiguration.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\properties\DeepSeekConfigProperties.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGResponse.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\tool\ChatMessage.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\TestUtils.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\websearch\searxng\SearXNGConfig.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\ChatBaseResponse.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\deepseek\entity\DeepSeekChatResponse.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\convert\ResultConvert.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\service\IChatService.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\chat\tool\Choice.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\properties\KimiConfigProperties.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\service\PlatformType.java
|
||||
C:\Users\Dongpx\Desktop\java工作\hngryy_report\java\lidee-tool\tool-spring-boot-starter-ai\src\main\java\com\lideeyunji\tool\framework\ai\convert\ParameterConvert.java
|
||||
Binary file not shown.
Reference in New Issue
Block a user