Compare commits
3 Commits
master
...
fa93d4ffe0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa93d4ffe0 | ||
|
|
d00e3ce11e | ||
|
|
06d5b6ca63 |
91
pom.xml
91
pom.xml
@@ -29,13 +29,14 @@
|
|||||||
<encoding>UTF-8</encoding>
|
<encoding>UTF-8</encoding>
|
||||||
<guava.version>16.0.1</guava.version>
|
<guava.version>16.0.1</guava.version>
|
||||||
<mybatis-spring-boot.version>2.3.1</mybatis-spring-boot.version>
|
<mybatis-spring-boot.version>2.3.1</mybatis-spring-boot.version>
|
||||||
<mybatis-plus-spring-boot.version>3.5.14</mybatis-plus-spring-boot.version>
|
<mybatis-plus-spring-boot.version>3.5.5</mybatis-plus-spring-boot.version>
|
||||||
<mysql.version>8.0.33</mysql.version>
|
<mysql.version>8.0.33</mysql.version>
|
||||||
<lombok.version>1.18.30</lombok.version>
|
<lombok.version>1.18.30</lombok.version>
|
||||||
<spring-data-redis.version>3.23.6</spring-data-redis.version>
|
<spring-data-redis.version>3.23.6</spring-data-redis.version>
|
||||||
<rocketmq.version>2.2.3</rocketmq.version>
|
<rocketmq.version>2.2.3</rocketmq.version>
|
||||||
<spring.authorization.server.version>0.4.0</spring.authorization.server.version>
|
<spring.authorization.server.version>0.4.0</spring.authorization.server.version>
|
||||||
<springai.alibaba.version>1.0.0.2</springai.alibaba.version>
|
<springai.alibaba.version>1.0.0.2</springai.alibaba.version>
|
||||||
|
<langchain.version>1.12.2</langchain.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
@@ -91,70 +92,66 @@
|
|||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring AI -->
|
|
||||||
<!-- <dependency>-->
|
|
||||||
<!-- <groupId>org.springframework.ai</groupId>-->
|
|
||||||
<!-- <artifactId>spring-ai-bom</artifactId>-->
|
|
||||||
<!-- <version>${spring.ai.version}</version>-->
|
|
||||||
<!-- <type>pom</type>-->
|
|
||||||
<!-- <scope>import</scope>-->
|
|
||||||
<!-- </dependency>-->
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.cloud.ai</groupId>
|
|
||||||
<artifactId>spring-ai-alibaba-bom</artifactId>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
<version>${springai.alibaba.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-open-ai -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.cloud.ai</groupId>
|
<groupId>dev.langchain4j</groupId>
|
||||||
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
|
<artifactId>langchain4j-open-ai</artifactId>
|
||||||
<version>${springai.alibaba.version}</version>
|
<version>${langchain.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.cloud.ai</groupId>
|
<groupId>dev.langchain4j</groupId>
|
||||||
<artifactId>spring-ai-alibaba-graph-core</artifactId>
|
<artifactId>langchain4j</artifactId>
|
||||||
<version>${springai.alibaba.version}</version>
|
<version>${langchain.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-ollama -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.cloud.ai</groupId>
|
<groupId>dev.langchain4j</groupId>
|
||||||
<artifactId>spring-ai-alibaba-starter-memory-jdbc</artifactId>
|
<artifactId>langchain4j-ollama</artifactId>
|
||||||
<version>${springai.alibaba.version}</version>
|
<version>${langchain.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
|
<version>${mybatis-plus-spring-boot.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>${mysql.version}</version>
|
<version>${mysql.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- <dependency>-->
|
<!-- collections -->
|
||||||
<!-- <groupId>org.springframework.ai</groupId>-->
|
<dependency>
|
||||||
<!-- <artifactId>spring-ai-pdf-document-reader</artifactId>-->
|
<groupId>com.google.guava</groupId>
|
||||||
<!-- <version>${spring.ai.version}</version>-->
|
<artifactId>guava</artifactId>
|
||||||
<!-- </dependency>-->
|
<version>32.1.3-jre</version>
|
||||||
<!-- <dependency>-->
|
</dependency>
|
||||||
<!-- <groupId>org.springframework.ai</groupId>-->
|
<dependency>
|
||||||
<!-- <artifactId>spring-ai-pgvector-store</artifactId>-->
|
<groupId>org.apache.commons</groupId>
|
||||||
<!-- <version>${spring.ai.version}</version>-->
|
<artifactId>commons-collections4</artifactId>
|
||||||
<!-- </dependency>-->
|
<version>4.2</version>
|
||||||
<!-- <dependency>-->
|
</dependency>
|
||||||
<!-- <groupId>org.springframework.ai</groupId>-->
|
<dependency>
|
||||||
<!-- <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>-->
|
<groupId>org.apache.commons</groupId>
|
||||||
<!-- <version>${spring.ai.version}</version>-->
|
<artifactId>commons-lang3</artifactId>
|
||||||
<!-- </dependency>-->
|
<version>3.15.0</version>
|
||||||
<!-- <dependency>-->
|
</dependency>
|
||||||
<!-- <groupId>org.springframework.ai</groupId>-->
|
|
||||||
<!-- <artifactId>spring-ai-tika-document-reader</artifactId>-->
|
|
||||||
<!-- <version>${spring.ai.version}</version>-->
|
|
||||||
<!-- </dependency>-->
|
|
||||||
|
|
||||||
|
<!-- JSON -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
<version>2.0.51</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ package com.xiang;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +1,22 @@
|
|||||||
package com.xiang.xsa.xservice.ai.server;
|
package com.xiang.xsa.xservice.ai.server;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.agent.BaseAgent;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelTypeEnum;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.ai.chat.client.ChatClient;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
|
|
||||||
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
|
|
||||||
import org.springframework.ai.chat.memory.ChatMemory;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ChatController {
|
public class ChatController {
|
||||||
|
|
||||||
private final ChatClient chatClient;
|
private final BaseAgent baseAgent;
|
||||||
private final ChatMemory chatMemory;
|
|
||||||
|
|
||||||
@PostMapping("/chat")
|
@GetMapping("/chat")
|
||||||
public String chatDemo(@RequestParam("question") String question) {
|
public String chatDemo(@RequestParam("question") String question, @RequestParam("id") Long id) {
|
||||||
return chatClient.prompt(question).call().content();
|
baseAgent.chat(ModelTypeEnum.OPEN_AI, id, question);
|
||||||
|
return "321";
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/chatWithFlux")
|
|
||||||
public Flux<String> chatWithFlux(@RequestParam("question") String question) {
|
|
||||||
return chatClient.prompt(question).stream().content();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/chatWithConversionId")
|
|
||||||
public String chatWithConversionId(@RequestParam("sessionId") String sessionId, @RequestParam("question") String question) {
|
|
||||||
|
|
||||||
return chatClient.prompt()
|
|
||||||
.user(question)
|
|
||||||
.advisors(
|
|
||||||
MessageChatMemoryAdvisor.builder(chatMemory).conversationId(sessionId).build(), new SimpleLoggerAdvisor()
|
|
||||||
)
|
|
||||||
.call().content();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
spring:
|
spring:
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:mysql://rm-bp15t34gqx62jm069ro.mysql.rds.aliyuncs.com:3306/xservice-ai-center?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
|
url: jdbc:mysql://120.27.153.87:3306/xe-service-ai?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
|
||||||
username: root
|
username: root
|
||||||
password: xb#UWqnhH24&XpX
|
password: sdkljfikdfn@123
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
ai:
|
|
||||||
dashscope:
|
ai:
|
||||||
api-key: sk-07353fd191074c9c930b134230ba88ea
|
openai:
|
||||||
chat:
|
configs:
|
||||||
options:
|
bai-lian:
|
||||||
model: qwen-plus
|
apiKey: sk-70cb426d7d1e4b54b4ffe71022e7d815
|
||||||
http:
|
modelName: qwen3.5-plus
|
||||||
connect-timeout: 30s
|
baseUrl: https://dashscope.aliyuncs.com/compatible-mode/v1
|
||||||
read-timeout: 60s
|
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ spring:
|
|||||||
|
|
||||||
profiles:
|
profiles:
|
||||||
active: local
|
active: local
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
config:
|
||||||
|
import-check:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: 38020
|
port: 38020
|
||||||
@@ -14,4 +19,9 @@ server:
|
|||||||
charset: UTF-8
|
charset: UTF-8
|
||||||
enabled: true
|
enabled: true
|
||||||
force: true
|
force: true
|
||||||
|
mybatis:
|
||||||
|
mapper-locations:
|
||||||
|
- classpath*:mapper/*/*.xml
|
||||||
|
configuration:
|
||||||
|
map-underscore-to-camel-case: true
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.xiang.xservice.ai.agent;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelTypeEnum;
|
||||||
|
|
||||||
|
public interface BaseAgent {
|
||||||
|
void chat(ModelTypeEnum modelType, Long memoryId, String message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.xiang.xservice.ai.agent;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.xiang.xservice.ai.config.OpenAIBaseConfig;
|
||||||
|
import com.xiang.xservice.ai.config.OpenAIConfig;
|
||||||
|
import com.xiang.xservice.ai.core.assistant.Assistant;
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelTypeEnum;
|
||||||
|
import com.xiang.xservice.ai.core.handler.MyStreamingHandler;
|
||||||
|
import com.xiang.xservice.ai.core.route.TaskRouter;
|
||||||
|
import com.xiang.xservice.ai.core.storage.DbPersistentStore;
|
||||||
|
import com.xiang.xservice.ai.core.storage.MemoryPersistentStore;
|
||||||
|
import com.xiang.xservice.ai.repository.manage.IAiSimpleChatMessageManage;
|
||||||
|
import dev.langchain4j.data.message.SystemMessage;
|
||||||
|
import dev.langchain4j.data.message.UserMessage;
|
||||||
|
import dev.langchain4j.memory.chat.ChatMemoryProvider;
|
||||||
|
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import dev.langchain4j.service.AiServices;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SimpleChatAgent implements BaseAgent {
|
||||||
|
|
||||||
|
private final TaskRouter router;
|
||||||
|
private final OpenAIBaseConfig openAIBaseConfig;
|
||||||
|
private final IAiSimpleChatMessageManage aiSimpleChatMessageManage;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void chat(ModelTypeEnum modelType, Long id, String message) {
|
||||||
|
|
||||||
|
DbPersistentStore store = new DbPersistentStore(aiSimpleChatMessageManage);
|
||||||
|
|
||||||
|
ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()
|
||||||
|
.id(memoryId)
|
||||||
|
.maxMessages(10)
|
||||||
|
.chatMemoryStore(store)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
OpenAIConfig openAIConfig = openAIBaseConfig.getConfigs().get("bai-lian");
|
||||||
|
ModelConfig modelConfig = ModelConfig.builder()
|
||||||
|
.baseUrl(openAIConfig.getBaseUrl())
|
||||||
|
.apiKey(openAIConfig.getApiKey())
|
||||||
|
.maxRetries(openAIConfig.getMaxRetries())
|
||||||
|
.modelName(openAIConfig.getModelName())
|
||||||
|
.temperature(openAIConfig.getTemperature())
|
||||||
|
.build();
|
||||||
|
StreamingChatModel chat = router.route(ModelStrategyEnum.CHAT, modelType.getModelType(), modelConfig);
|
||||||
|
if (chat == null) {
|
||||||
|
throw new RuntimeException("chat model route failed");
|
||||||
|
}
|
||||||
|
Assistant assistant = AiServices.builder(Assistant.class)
|
||||||
|
.streamingChatModel(chat)
|
||||||
|
.chatMemoryProvider(chatMemoryProvider)
|
||||||
|
.build();
|
||||||
|
UserMessage userMessage = new UserMessage(message);
|
||||||
|
SystemMessage systemMessage = new SystemMessage("你是一个能够与人聊天的AI智能助手,名字叫龙虾");
|
||||||
|
assistant.chat(id, Lists.newArrayList(systemMessage, userMessage))
|
||||||
|
.onPartialResponse(System.out::print)
|
||||||
|
.onCompleteResponse(res -> System.out.println("\n完成"))
|
||||||
|
.onToolExecuted(error -> System.out.println("\n错误"))
|
||||||
|
.ignoreErrors()
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.xiang.xservice.ai.config;
|
|
||||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
|
|
||||||
import com.alibaba.cloud.ai.memory.jdbc.MysqlChatMemoryRepository;
|
|
||||||
import org.springframework.ai.chat.client.ChatClient;
|
|
||||||
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
|
|
||||||
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
|
|
||||||
import org.springframework.ai.chat.memory.ChatMemory;
|
|
||||||
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化llm客户端
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
public class LlmClientConfig {
|
|
||||||
|
|
||||||
private static final String DEFAULT_PROMPT = "你是一个友好的AI助手,可以根据用户提出的问题进行解答";
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ChatClient initChatCLient(ChatClient.Builder charClientBuilder, ChatMemory chatMemory) {
|
|
||||||
return charClientBuilder
|
|
||||||
.defaultSystem(DEFAULT_PROMPT)
|
|
||||||
.defaultAdvisors(
|
|
||||||
new SimpleLoggerAdvisor(),
|
|
||||||
MessageChatMemoryAdvisor.builder(chatMemory).build()
|
|
||||||
)
|
|
||||||
.defaultOptions(
|
|
||||||
DashScopeChatOptions.builder().withTemperature(1.2).build()
|
|
||||||
).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public ChatMemory initChatMemory(JdbcTemplate jdbcTemplate) {
|
|
||||||
return MessageWindowChatMemory.builder()
|
|
||||||
.chatMemoryRepository(MysqlChatMemoryRepository.mysqlBuilder()
|
|
||||||
.jdbcTemplate(jdbcTemplate)
|
|
||||||
.build())
|
|
||||||
.maxMessages(100)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.xiang.xservice.ai.config;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "ai.openai")
|
||||||
|
public class OpenAIBaseConfig {
|
||||||
|
private Map<String, OpenAIConfig> configs;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.xiang.xservice.ai.config;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class OpenAIConfig {
|
||||||
|
/**
|
||||||
|
* url
|
||||||
|
*/
|
||||||
|
private String baseUrl;
|
||||||
|
/**
|
||||||
|
* api-key
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
/**
|
||||||
|
* 模型名称
|
||||||
|
*/
|
||||||
|
private String modelName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大重试次数
|
||||||
|
*/
|
||||||
|
private Integer maxRetries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制token数量
|
||||||
|
*/
|
||||||
|
private Integer maxToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 温度
|
||||||
|
*/
|
||||||
|
private Double temperature;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.xiang.xservice.ai.core.assistant;
|
||||||
|
|
||||||
|
import dev.langchain4j.data.message.ChatMessage;
|
||||||
|
import dev.langchain4j.service.MemoryId;
|
||||||
|
import dev.langchain4j.service.TokenStream;
|
||||||
|
import dev.langchain4j.service.UserMessage;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Assistant {
|
||||||
|
TokenStream chat(@MemoryId Object memoryId, @UserMessage List<ChatMessage> messages);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.xiang.xservice.ai.core.entity;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class ModelConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* url
|
||||||
|
*/
|
||||||
|
private String baseUrl;
|
||||||
|
/**
|
||||||
|
* api-key
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
/**
|
||||||
|
* 模型名称
|
||||||
|
*/
|
||||||
|
private String modelName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大重试次数
|
||||||
|
*/
|
||||||
|
private Integer maxRetries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限制token数量
|
||||||
|
*/
|
||||||
|
private Integer maxTokens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 温度
|
||||||
|
*/
|
||||||
|
private Double temperature;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.xiang.xservice.ai.core.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ModelStrategyEnum {
|
||||||
|
|
||||||
|
CHAT("CHAT_MODEL", "聊天模型"),
|
||||||
|
REASON("REASON_MODEL", "逻辑推理模型"),
|
||||||
|
CODE("CODE_MODEL", "代码模型"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String desc;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.xiang.xservice.ai.core.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ModelTypeEnum {
|
||||||
|
|
||||||
|
OPEN_AI("open_ai", "云端部署的支持Open-AI的模型"),
|
||||||
|
OLLAMA("ollama", "本地部署的Ollama模型"),
|
||||||
|
;
|
||||||
|
private final String modelType;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.xiang.xservice.ai.core.handler;
|
||||||
|
|
||||||
|
import dev.langchain4j.model.StreamingResponseHandler;
|
||||||
|
import dev.langchain4j.model.chat.response.ChatResponse;
|
||||||
|
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MyStreamingHandler implements StreamingChatResponseHandler{
|
||||||
|
private StringBuilder builder = new StringBuilder();
|
||||||
|
@Override
|
||||||
|
public void onPartialResponse(String partialResponse) {
|
||||||
|
// 每生成一个 token 或 chunk 的回调
|
||||||
|
builder.append(partialResponse);
|
||||||
|
System.out.print(partialResponse); // 实时打印
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCompleteResponse(ChatResponse completeResponse) {
|
||||||
|
// 完整响应生成完成
|
||||||
|
System.out.println("\n生成完成!");
|
||||||
|
System.out.println("最终输出: " + completeResponse.aiMessage().text());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable error) {
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.xiang.xservice.ai.core.provider;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelTypeEnum;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
|
||||||
|
public interface BaseProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* providerName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String providerName();
|
||||||
|
/**
|
||||||
|
* 创建model
|
||||||
|
* @param config model配置文件
|
||||||
|
* @return ChatModel
|
||||||
|
*/
|
||||||
|
StreamingChatModel build(ModelConfig config);
|
||||||
|
/**
|
||||||
|
* 用于标记这个 Provider 是否适合某个 TaskType
|
||||||
|
* @param taskType ModelStrategyEnum
|
||||||
|
* @return true 支持 false:不支持
|
||||||
|
*/
|
||||||
|
boolean support(ModelStrategyEnum taskType);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.xiang.xservice.ai.core.provider;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelTypeEnum;
|
||||||
|
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 org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OllamaLlmProvider implements BaseProvider{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String providerName() {
|
||||||
|
return ModelTypeEnum.OLLAMA.getModelType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamingChatModel build(ModelConfig config) {
|
||||||
|
return OllamaStreamingChatModel.builder()
|
||||||
|
.baseUrl(config.getBaseUrl())
|
||||||
|
.modelName(config.getModelName())
|
||||||
|
.temperature(config.getTemperature())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean support(ModelStrategyEnum taskType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.xiang.xservice.ai.core.provider;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelTypeEnum;
|
||||||
|
import com.xiang.xservice.ai.core.storage.MemoryPersistentStore;
|
||||||
|
import dev.langchain4j.memory.chat.ChatMemoryProvider;
|
||||||
|
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OpenAILlmProvider implements BaseProvider {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String providerName() {
|
||||||
|
return ModelTypeEnum.OPEN_AI.getModelType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamingChatModel build(ModelConfig config) {
|
||||||
|
|
||||||
|
return OpenAiStreamingChatModel.builder()
|
||||||
|
.baseUrl(config.getBaseUrl())
|
||||||
|
.apiKey(config.getApiKey())
|
||||||
|
.modelName(config.getModelName())
|
||||||
|
.temperature(config.getTemperature())
|
||||||
|
.maxTokens(config.getMaxTokens())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean support(ModelStrategyEnum taskType) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.xiang.xservice.ai.core.route;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.provider.BaseProvider;
|
||||||
|
import com.xiang.xservice.ai.core.strategy.BaseStrategy;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ModelRouter {
|
||||||
|
|
||||||
|
private final Map<String, BaseProvider> providerMap;
|
||||||
|
|
||||||
|
public ModelRouter(List<BaseProvider> providers) {
|
||||||
|
this.providerMap = providers.stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
BaseProvider::providerName,
|
||||||
|
p -> p
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 providerName 选择 Provider,并用 config 构建模型
|
||||||
|
*/
|
||||||
|
public StreamingChatModel route(String providerName, ModelConfig config) {
|
||||||
|
BaseProvider provider = providerMap.get(providerName);
|
||||||
|
if (provider == null) {
|
||||||
|
throw new RuntimeException("Provider " + providerName + " not found");
|
||||||
|
}
|
||||||
|
return provider.build(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取某个 TaskType 支持的所有 Provider 名称
|
||||||
|
*/
|
||||||
|
public List<String> getProvidersForTask(ModelStrategyEnum taskType) {
|
||||||
|
return providerMap.values().stream()
|
||||||
|
.filter(p -> p.support(taskType))
|
||||||
|
.map(BaseProvider::providerName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.xiang.xservice.ai.core.route;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.provider.BaseProvider;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TaskRouter {
|
||||||
|
private final Map<ModelStrategyEnum, List<String>> taskDefaultProviderMap;
|
||||||
|
private final ModelRouter providerRouter;
|
||||||
|
|
||||||
|
public TaskRouter(ModelRouter providerRouter, List<BaseProvider> providers) {
|
||||||
|
this.providerRouter = providerRouter;
|
||||||
|
|
||||||
|
taskDefaultProviderMap = new HashMap<>();
|
||||||
|
for (ModelStrategyEnum taskType : ModelStrategyEnum.values()) {
|
||||||
|
// 默认使用第一个可用的 Provider
|
||||||
|
List<String> supported = providerRouter.getProvidersForTask(taskType);
|
||||||
|
taskDefaultProviderMap.put(taskType, supported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第一层路由 + 第二层 ProviderRouter
|
||||||
|
*/
|
||||||
|
public StreamingChatModel route(ModelStrategyEnum taskType, String providerName, ModelConfig config) {
|
||||||
|
// 如果没有传 providerName,使用默认 Provider
|
||||||
|
if (providerName == null || providerName.isEmpty()) {
|
||||||
|
providerName = taskDefaultProviderMap.get(taskType).get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第二层路由
|
||||||
|
return providerRouter.route(providerName, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.xiang.xservice.ai.core.storage;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.xiang.xservice.ai.pojo.entity.AiSimpleChatMessageDO;
|
||||||
|
import com.xiang.xservice.ai.repository.manage.IAiSimpleChatMessageManage;
|
||||||
|
import dev.langchain4j.data.message.*;
|
||||||
|
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库持久化
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DbPersistentStore implements ChatMemoryStore {
|
||||||
|
|
||||||
|
private final IAiSimpleChatMessageManage aiSimpleChatMessageManage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ChatMessage> getMessages(Object memoryId) {
|
||||||
|
List<AiSimpleChatMessageDO> msg = aiSimpleChatMessageManage.getMsgByMemoryId((Long) memoryId);
|
||||||
|
if (CollectionUtils.isEmpty(msg)) {
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
List<ChatMessage> result = Lists.newArrayList();
|
||||||
|
for (AiSimpleChatMessageDO chatMessageDO : msg) {
|
||||||
|
String role = chatMessageDO.getRole();
|
||||||
|
switch (role) {
|
||||||
|
|
||||||
|
case "SYSTEM":
|
||||||
|
result.add(SystemMessage.from(chatMessageDO.getMessage()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "USER":
|
||||||
|
result.add(UserMessage.from(chatMessageDO.getMessage()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "AI":
|
||||||
|
result.add(AiMessage.from(chatMessageDO.getMessage()));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateMessages(Object memoryId, List<ChatMessage> list) {
|
||||||
|
List<AiSimpleChatMessageDO> result = Lists.newArrayList();
|
||||||
|
for (ChatMessage chatMessage : list) {
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
String type = "";
|
||||||
|
if (chatMessage instanceof SystemMessage systemMessage) {
|
||||||
|
str = new StringBuilder(systemMessage.text());
|
||||||
|
type = "SYSTEM";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chatMessage instanceof UserMessage userMessage) {
|
||||||
|
for (Content content : userMessage.contents()) {
|
||||||
|
if (content instanceof TextContent textContent) {
|
||||||
|
str.append(textContent.text());
|
||||||
|
type = "USER";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chatMessage instanceof AiMessage aiMessage) {
|
||||||
|
str = new StringBuilder(aiMessage.text());
|
||||||
|
type = "AI";
|
||||||
|
}
|
||||||
|
|
||||||
|
AiSimpleChatMessageDO message = AiSimpleChatMessageDO.builder()
|
||||||
|
.userId(1L)
|
||||||
|
.memoryId((Long) memoryId)
|
||||||
|
.message(str.toString())
|
||||||
|
.createTime(LocalDateTime.now())
|
||||||
|
.delFlag(0)
|
||||||
|
.role(type)
|
||||||
|
.build();
|
||||||
|
result.add(message);
|
||||||
|
|
||||||
|
}
|
||||||
|
aiSimpleChatMessageManage.saveBatch(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteMessages(Object memoryId) {
|
||||||
|
aiSimpleChatMessageManage.deleteByMemoryId((Long) memoryId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.xiang.xservice.ai.core.storage;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import dev.langchain4j.data.message.ChatMessage;
|
||||||
|
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内存持久化
|
||||||
|
*/
|
||||||
|
public class MemoryPersistentStore implements ChatMemoryStore {
|
||||||
|
|
||||||
|
private final static Map<Long, List<ChatMessage>> MAP = Maps.newHashMap();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ChatMessage> getMessages(Object memoryId) {
|
||||||
|
Long id = (Long) memoryId;
|
||||||
|
if (MAP.containsKey(id)) {
|
||||||
|
return MAP.get(id);
|
||||||
|
}
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateMessages(Object memoryId, List<ChatMessage> list) {
|
||||||
|
Long id = (Long) memoryId;
|
||||||
|
if (MAP.containsKey(id)) {
|
||||||
|
MAP.get(id).addAll(list);
|
||||||
|
} else {
|
||||||
|
MAP.put(id, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteMessages(Object memoryId) {
|
||||||
|
MAP.remove((Long) memoryId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.xiang.xservice.ai.core.strategy;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
|
||||||
|
public interface BaseStrategy {
|
||||||
|
|
||||||
|
String modelType();
|
||||||
|
|
||||||
|
StreamingChatModel createProvider(String provider, ModelConfig config);
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.xiang.xservice.ai.core.strategy;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import com.xiang.xservice.ai.core.provider.BaseProvider;
|
||||||
|
import com.xiang.xservice.ai.core.route.TaskRouter;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ChatStrategy implements BaseStrategy {
|
||||||
|
|
||||||
|
private final TaskRouter taskRouter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String modelType() {
|
||||||
|
return ModelStrategyEnum.CHAT.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamingChatModel createProvider(String provider, ModelConfig config) {
|
||||||
|
return taskRouter.route(ModelStrategyEnum.CHAT, provider, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.xiang.xservice.ai.core.strategy;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class CodeStrategy implements BaseStrategy {
|
||||||
|
@Override
|
||||||
|
public String modelType() {
|
||||||
|
return ModelStrategyEnum.CODE.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamingChatModel createProvider(String provider, ModelConfig config) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.xiang.xservice.ai.core.strategy;
|
||||||
|
|
||||||
|
import com.xiang.xservice.ai.core.entity.ModelConfig;
|
||||||
|
import com.xiang.xservice.ai.core.enums.ModelStrategyEnum;
|
||||||
|
import dev.langchain4j.model.chat.ChatModel;
|
||||||
|
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ReasonStrategy implements BaseStrategy {
|
||||||
|
@Override
|
||||||
|
public String modelType() {
|
||||||
|
return ModelStrategyEnum.REASON.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamingChatModel createProvider(String provider, ModelConfig config) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.xiang.xservice.ai.pojo.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("ai_simple_chat_message")
|
||||||
|
@Builder
|
||||||
|
public class AiSimpleChatMessageDO {
|
||||||
|
private Long id;
|
||||||
|
private Long userId;
|
||||||
|
private Long memoryId;
|
||||||
|
private String role;
|
||||||
|
private String message;
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
private Integer delFlag;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.xiang.xservice.ai.repository.manage;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.xiang.xservice.ai.pojo.entity.AiSimpleChatMessageDO;
|
||||||
|
import com.xiang.xservice.ai.repository.mapper.IAiSimpleChatMessageMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AiSimpleChatMessageManageImpl extends ServiceImpl<IAiSimpleChatMessageMapper, AiSimpleChatMessageDO> implements IAiSimpleChatMessageManage {
|
||||||
|
@Override
|
||||||
|
public List<AiSimpleChatMessageDO> getMsgByMemoryId(Long memoryId) {
|
||||||
|
LambdaQueryWrapper<AiSimpleChatMessageDO> lambdaQueryWrapper = Wrappers.lambdaQuery();
|
||||||
|
lambdaQueryWrapper.eq(AiSimpleChatMessageDO::getMemoryId, memoryId);
|
||||||
|
lambdaQueryWrapper.eq(AiSimpleChatMessageDO::getDelFlag, 0);
|
||||||
|
return baseMapper.selectList(lambdaQueryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteByMemoryId(Long memoryId) {
|
||||||
|
return baseMapper.deleteByMemoryId(memoryId) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.xiang.xservice.ai.repository.manage;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.xiang.xservice.ai.pojo.entity.AiSimpleChatMessageDO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IAiSimpleChatMessageManage extends IService<AiSimpleChatMessageDO> {
|
||||||
|
List<AiSimpleChatMessageDO> getMsgByMemoryId(Long memoryId);
|
||||||
|
boolean deleteByMemoryId(Long memoryId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.xiang.xservice.ai.repository.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.xiang.xservice.ai.pojo.entity.AiSimpleChatMessageDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
@Repository
|
||||||
|
public interface IAiSimpleChatMessageMapper extends BaseMapper<AiSimpleChatMessageDO> {
|
||||||
|
int deleteByMemoryId(@Param("id") Long memoryId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.xiang.dao.AiSimpleChatMessageMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="com.xiang.xservice.ai.pojo.entity.AiSimpleChatMessageDO">
|
||||||
|
<result column="id" property="id"/>
|
||||||
|
<result column="memory_id" property="memoryId"/>
|
||||||
|
<result column="role" property="role"/>
|
||||||
|
<result column="message" property="message"/>
|
||||||
|
<result column="create_time" property="createTime"/>
|
||||||
|
<result column="user_id" property="userId"/>
|
||||||
|
<result column="del_flag" property="delFlag"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,
|
||||||
|
memory_id,
|
||||||
|
role,
|
||||||
|
message,
|
||||||
|
create_time,
|
||||||
|
user_id,
|
||||||
|
del_flag
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<update id="deleteByMemoryId">
|
||||||
|
update ai_simple_chat_message set del_flag = 1 where memory_id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user