==
This commit is contained in:
14
pom.xml
14
pom.xml
@@ -34,7 +34,11 @@
|
||||
<groupId>org.springframework.ai</groupId>
|
||||
<artifactId>spring-ai-starter-model-deepseek</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里百炼大模型自动配置-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud.ai</groupId>
|
||||
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
@@ -89,6 +93,14 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<!-- 阿里百炼版本管理-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud.ai</groupId>
|
||||
<artifactId>spring-ai-alibaba-bom</artifactId>
|
||||
<version>1.0.0.2</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.ai.app.config;
|
||||
|
||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
|
||||
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
|
||||
@@ -54,9 +55,9 @@ public class AIConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置AI对话客户端
|
||||
* dashScopeChatClient对话客户端
|
||||
*
|
||||
* @param deepSeekChatModel deepseek大模型
|
||||
* @param dashScopeChatModel 千问max大模型
|
||||
* @param simpleLoggerAdvisor 日志Advisor
|
||||
* @param messageChatMemoryAdvisor 会话记忆Advisor
|
||||
* @return: org.springframework.ai.chat.client.ChatClient
|
||||
@@ -64,7 +65,31 @@ public class AIConfig {
|
||||
* @date: 2025/8/29 9:06
|
||||
*/
|
||||
@Bean
|
||||
public ChatClient chatClient(DeepSeekChatModel deepSeekChatModel,
|
||||
public ChatClient dashScopeChatClient(DashScopeChatModel dashScopeChatModel,
|
||||
SimpleLoggerAdvisor simpleLoggerAdvisor,
|
||||
MessageChatMemoryAdvisor messageChatMemoryAdvisor) {
|
||||
return ChatClient
|
||||
//模型
|
||||
.builder(dashScopeChatModel)
|
||||
//系统角色
|
||||
.defaultSystem("你是一个小团团")
|
||||
//环绕增强
|
||||
.defaultAdvisors(simpleLoggerAdvisor, messageChatMemoryAdvisor)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* deepseek 对话客户端
|
||||
*
|
||||
* @param deepSeekChatModel deepseek大模型
|
||||
* @param simpleLoggerAdvisor 日志增强
|
||||
* @param messageChatMemoryAdvisor 会话记忆增强
|
||||
* @return: org.springframework.ai.chat.client.ChatClient
|
||||
* @author kai.liu
|
||||
* @date: 2025/9/3 16:45
|
||||
*/
|
||||
@Bean
|
||||
public ChatClient deepSeekChatClient(DeepSeekChatModel deepSeekChatModel,
|
||||
SimpleLoggerAdvisor simpleLoggerAdvisor,
|
||||
MessageChatMemoryAdvisor messageChatMemoryAdvisor) {
|
||||
return ChatClient
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.ai.app.controller;
|
||||
|
||||
import com.ai.app.dto.MessageDTO;
|
||||
import com.ai.app.service.AIChatMessageService;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.memory.ChatMemory;
|
||||
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @describe AI对话控制器
|
||||
* @Author kai.liu
|
||||
* @Date 2025/8/28 10:06
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/ai")
|
||||
public class ChatController {
|
||||
|
||||
@Autowired
|
||||
private ChatClient chatClient;
|
||||
|
||||
@Autowired
|
||||
private InMemoryChatMemoryRepository inMemoryChatMemoryRepository;
|
||||
|
||||
@RequestMapping(value = "/chat", produces = "text/stream;charset=UTF-8")
|
||||
public Flux<String> chat(String prompt, String chatId) {
|
||||
return chatClient
|
||||
.prompt()
|
||||
.user(prompt)
|
||||
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
|
||||
.stream().content();
|
||||
}
|
||||
|
||||
@RequestMapping("/history/chat")
|
||||
public List<String> history() {
|
||||
return inMemoryChatMemoryRepository.findConversationIds();
|
||||
}
|
||||
|
||||
@RequestMapping("/history/chat/{chatId}")
|
||||
public List<MessageDTO> history(@PathVariable("chatId") String chatId) {
|
||||
List<Message> messages = inMemoryChatMemoryRepository.findByConversationId(chatId);
|
||||
return messages.stream().map(e -> {
|
||||
return new MessageDTO(e.getMessageType().getValue(), e.getText());
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
85
src/main/java/com/ai/app/controller/DashScopeController.java
Normal file
85
src/main/java/com/ai/app/controller/DashScopeController.java
Normal file
@@ -0,0 +1,85 @@
|
||||
package com.ai.app.controller;
|
||||
|
||||
import com.ai.app.dto.MessageDTO;
|
||||
import com.ai.app.service.ChatHistoryService;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.memory.ChatMemory;
|
||||
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
|
||||
import org.springframework.ai.chat.messages.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @describe AI对话控制器
|
||||
* @Author kai.liu
|
||||
* @Date 2025/8/28 10:06
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/dashscope")
|
||||
public class DashScopeController {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("dashScopeChatClient")
|
||||
private ChatClient dashScopeChatClient;
|
||||
|
||||
@Autowired
|
||||
private ChatHistoryService chatHistoryService;
|
||||
|
||||
@Autowired
|
||||
private InMemoryChatMemoryRepository inMemoryChatMemoryRepository;
|
||||
|
||||
/**
|
||||
* 对话聊天
|
||||
*
|
||||
* @param prompt 用户提示词
|
||||
* @param chatId 对话ID
|
||||
* @return: reactor.core.publisher.Flux<java.lang.String>
|
||||
* @author kai.liu
|
||||
* @date: 2025/9/3 17:30
|
||||
*/
|
||||
@RequestMapping(value = "/chat", produces = "text/stream;charset=UTF-8")
|
||||
public Flux<String> chat(String prompt, String chatId) {
|
||||
return dashScopeChatClient
|
||||
.prompt()
|
||||
.user(prompt)
|
||||
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
|
||||
.stream().content();
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话ID列表
|
||||
*
|
||||
* @param type 类型
|
||||
* @return: java.util.List<java.lang.String>
|
||||
* @author kai.liu
|
||||
* @date: 2025/9/3 17:30
|
||||
*/
|
||||
@GetMapping("/getHistoryChatIdList/{type}")
|
||||
public List<String> getHistoryChatIdList(@PathVariable("type") String type) {
|
||||
return chatHistoryService.getHistoryChatIds(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 会话历史
|
||||
*
|
||||
* @param chatId 会话ID
|
||||
* @return: java.util.List<com.ai.app.dto.MessageDTO>
|
||||
* @author kai.liu
|
||||
* @date: 2025/9/3 17:31
|
||||
*/
|
||||
@RequestMapping("/getChatHistory/{type}/{chatId}")
|
||||
public List<MessageDTO> getChatHistory(@PathVariable("type") String type, @PathVariable("chatId") String chatId) {
|
||||
chatHistoryService.saveHistoryChatId(type, chatId);
|
||||
List<Message> messages = inMemoryChatMemoryRepository.findByConversationId(chatId);
|
||||
return messages.stream().map(e -> new MessageDTO(e.getMessageType().getValue(), e.getText())).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
15
src/main/java/com/ai/app/service/ChatHistoryService.java
Normal file
15
src/main/java/com/ai/app/service/ChatHistoryService.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.ai.app.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @describe 对话历史接口定义
|
||||
* @Author kai.liu
|
||||
* @Date 2025/9/3 17:05
|
||||
*/
|
||||
public interface ChatHistoryService {
|
||||
|
||||
void saveHistoryChatId(String type, String chatId);
|
||||
|
||||
List<String> getHistoryChatIds(String type);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.ai.app.service.impl;
|
||||
|
||||
import com.ai.app.service.ChatHistoryService;
|
||||
import com.ai.app.service.RedisTemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @describe
|
||||
* @Author kai.liu
|
||||
* @Date 2025/9/3 17:05
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ChatHistoryServiceImpl implements ChatHistoryService {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplateService redisTemplateService;
|
||||
|
||||
public static final String CHAT_TYPE_KEY = "ai:history:type:";
|
||||
|
||||
/**
|
||||
* 保存会话ID
|
||||
*
|
||||
* @param type 类型
|
||||
* @param chatId 会话ID
|
||||
* @return: void
|
||||
* @author kai.liu
|
||||
* @date: 2025/9/3 17:14
|
||||
*/
|
||||
@Override
|
||||
public void saveHistoryChatId(String type, String chatId) {
|
||||
String key = CHAT_TYPE_KEY + type;
|
||||
List<String> chatIds;
|
||||
if (redisTemplateService.hasKey(key)) {
|
||||
chatIds = (List<String>) redisTemplateService.get(key);
|
||||
} else {
|
||||
chatIds = new ArrayList<>();
|
||||
}
|
||||
if (chatIds.contains(chatId)) {
|
||||
return;
|
||||
}
|
||||
chatIds.add(chatId);
|
||||
redisTemplateService.set(key, chatIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取历史会话id列表
|
||||
*
|
||||
* @param type 类型
|
||||
* @return: java.util.List<java.lang.String>
|
||||
* @author kai.liu
|
||||
* @date: 2025/9/3 17:08
|
||||
*/
|
||||
@Override
|
||||
public List<String> getHistoryChatIds(String type) {
|
||||
String key = CHAT_TYPE_KEY + type;
|
||||
if (redisTemplateService.hasKey(key)) {
|
||||
return (List<String>) redisTemplateService.get(key);
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
server:
|
||||
port: 8080
|
||||
# servlet:
|
||||
# context-path: /ai
|
||||
servlet:
|
||||
context-path: /ai
|
||||
tomcat:
|
||||
# 等待队列长度 (所有线程忙碌时,排队等待的连接数, 默认: 100)
|
||||
accept-count: 1000
|
||||
@@ -40,10 +40,15 @@ spring:
|
||||
max-request-size: 100MB
|
||||
ai:
|
||||
deepseek:
|
||||
api-key: sk-f970111b34c84a8c812919fb4fad8b65
|
||||
api-key: ${DEEPSEEK_API_KEY}
|
||||
chat:
|
||||
options:
|
||||
model: deepseek-reasoner
|
||||
model: deepseek-r1
|
||||
dashscope:
|
||||
api-key: ${DASHSCOPE_API_KEY}
|
||||
chat:
|
||||
options:
|
||||
model: qwen-max
|
||||
data:
|
||||
redis:
|
||||
host: 180.76.119.46
|
||||
|
||||
Reference in New Issue
Block a user