Dict.CN 在线词典, 英语学习, 在线翻译 ------------- MyGitee My腾云code

Happy_EveryDay

可以平凡 不可以平庸 无爱则无忧,无欲则无求,无怒而无敌,无怨才是佛。所有烦恼,都是放不下的执著 开源技群 328035181 MyGitee

springAI DeepSeek 对话机器人 会话记忆、会话历史 20250623

######前端代码 

######后端代码 git

 

 

1、Ollama 

 参考https://www.cnblogs.com/smallfa/p/18906777

 

2、pom.xml

 

 

<properties>
<java.version>17</java.version>

<spring-ai.version>1.0.0-M7</spring-ai.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-ollama</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

 


3、Configuration
package com.dsai.dsai.config;

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.InMemoryChatMemory;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
* @author Administrator
*/
@Configuration
public class CommonConfiguration {

  @Bean //配置ChatMemory实例 会话记忆 放在内存中
  public ChatMemory chatMemory() {
  return new InMemoryChatMemory();
  }

@Bean
public ChatClient chatClient(OllamaChatModel model) {
//创建ChatClient工厂实例
return ChatClient.builder(model)
.defaultSystem("你是一个热心、可爱的智能助手、你的名字叫小团团,请以小团团的身份和语气回答问题")
  
      .defaultAdvisors(
                //配置日志Advisor
          new SimpleLoggerAdvisor(),
          //配置会话记忆Advisor
        new MessageChatMemoryAdvisor(chatMemory)
          )
                //创建ChatClient实例
.build();
}
}
 
注:SimpleLoggerAdvisor

 

 

 

与前端交互跨域

package com.dsai.dsai.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
allowedOrigins("*").
allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS").
allowedHeaders("*");

}
}
 
4、application.yaml
spring:
application:
name: DS-AI
ai:
ollama:
base-url: http://192.168.177.128:11434
chat:
model: deepseek-r1:1.5b
#会话日志
logging:
level:
org.springframework.ai.chat.client.advisor: debug
com.dsai.dsai: debug



 

 

5、Controller

package com.dsai.dsai.controller;


import com.dsai.dsai.repository.ChatHistoryRespository;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;

/**
* @author Administrator
*/
@RestController
@RequestMapping("/api/ai")
public class ChatController {

private final ChatClient chatClient;
private final ChatHistoryRespository chatHistoryRespository;
// 手动编写构造器
public ChatController(ChatClient chatClient, ChatHistoryRespository chatHistoryRespository) {
this.chatClient = chatClient;
this.chatHistoryRespository = chatHistoryRespository;
}

@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8")
public Flux<String> chat(String prompt,String chatId) {
//1、保存会话ID
chatHistoryRespository.save("chat", chatId);
//2、请求模型
return chatClient.prompt()
.user(prompt)
//传递会话ID,不同的会话ID,会话记忆会不同
.advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY,chatId))
.stream()
.content();
}
}
 
 
package com.dsai.dsai.controller;

import com.dsai.dsai.entity.vo.MessageVO;
import com.dsai.dsai.repository.ChatHistoryRespository;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
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 java.util.List;

@RestController
@RequestMapping("/api/ai")
public class ChatHistoryController {
private final ChatHistoryRespository chatHistoryRespository;
private final ChatMemory chatMemory;

public ChatHistoryController(ChatHistoryRespository chatHistoryRespository, ChatMemory chatMemory) {
this.chatHistoryRespository = chatHistoryRespository;
this.chatMemory = chatMemory;
}
@GetMapping("/history/{type}")
public List<String> getChatIds(@PathVariable("type") String type){
return chatHistoryRespository.getChatIds(type);
}
@GetMapping("/history/{type}/{chatId}")
public List<MessageVO> getChatHistory(@PathVariable("type") String type, @PathVariable("chatId") String chatId){
List<Message> messages = chatMemory.get(chatId,Integer.MAX_VALUE);
if(messages==null) {
return List.of();
}
return messages.stream().map(MessageVO::new).toList(); }
}

 

 

 

 

 


 

6、实体MessageVO package com.dsai.dsai.entity.vo;


import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.ai.chat.messages.Message;

/**
* @author Administrator
*/
public class MessageVO {
private String role;
private String content;

MessageVO() {
}
public MessageVO(Message message) {
switch (message.getMessageType()) {
case USER:
this.role = "user";
break;
case ASSISTANT:
this.role = "assistant";
break;
default:
this.role = "";
break;
}
this.content = message.getText();
}
public String getRole() {
return role;
}

public void setRole(String role) {
this.role = role;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}
}



7、
repository


package com.dsai.dsai.repository;

import java.util.List;

public interface ChatHistoryRespository {
/**
* 保存会话记录
* @param type 业务类型 如: chat, service,pdf
* @param chatId 会话id
*/
void save(String type, String chatId);

/**
* 获取会话id列表
* @param type 业务类型 如: chat, service,pdf
* @return 会话id列表
*/
List<String> getChatIds(String type);
}


package com.dsai.dsai.repository;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.resource.ResourceUrlProvider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class InMemoryChatHistoryRepository implements ChatHistoryRespository{

private final Map<String,List<String>> chatHistory= new HashMap<>();
private final ResourceUrlProvider mvcResourceUrlProvider;

public InMemoryChatHistoryRepository(ResourceUrlProvider mvcResourceUrlProvider) {
this.mvcResourceUrlProvider = mvcResourceUrlProvider;
}

@Override
public void save(String type, String chatId) {
/* if(!chatHistory.containsKey(type)){
chatHistory.put(type, new ArrayList<>());
}
List<String> chatIds = chatHistory.get(type);*/
List<String> chatIds=chatHistory.computeIfAbsent(type, k -> new ArrayList<>());
if(chatIds.contains(chatId)){
return;
}
chatIds.add(chatId);
}

@Override
public List<String> getChatIds(String type) {
/*List<String> chatIds=chatHistory.get(type);
return chatIds==null? new ArrayList<>():chatIds;*/
return chatHistory.getOrDefault(type, List.of());
}
}





8、控制台日志

 

9、前端

 

 

 

 前端记忆 "messageType" : "ASSISTANT"

 

 

 

 

 

9.1  与模型交互

 

 

 

 

9.2  会话历史列表

 

 

 

 


posted on 2025-06-02 17:27  cn2025  阅读(196)  评论(0)    收藏  举报

导航