写点什么

面试官:如何实现大模型连续对话?

  • 2025-07-21
    福建
  • 本文字数:4584 字

    阅读完需:约 15 分钟

所有的大模型本身是不进行信息存储的,也不提供连续对话功能,所以想要实现连续对话功能需要开发者自己写代码才能实现。那怎么才能实现大模型的连续对话功能呢?

大模型连续对话功能不同的框架实现也是不同的,以行业使用最多的 Java AI 框架 Spring AI 和 Spring AI Alibaba 为例,给大家演示一下它们连续对话是如何实现的。


1.SpringAI 连续对话实现


Spring AI 以 MySQL 数据库为例,我们来实现一下它的连续对话功能。

PS:我们只有先讲对话存储起来,才能实现连续对话功能,所以我们需要借助数据库存储来连续对话。


1.1 准备工作


1.创建表

CREATE TABLE chat_message (  id BIGINT AUTO_INCREMENT PRIMARY KEY,  conversation_id VARCHAR(255) NOT NULL,  role VARCHAR(50) NOT NULL,  context TEXT NOT NULL,  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
复制代码


2.添加数据库和 MyBatisPlus 依赖:

<dependency>  <groupId>com.baomidou</groupId>  <artifactId>mybatis-plus-spring-boot3-starter</artifactId>  <version>3.5.11</version></dependency>
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope></dependency>
复制代码


3.设置配置文件:

spring:  datasource:    url: jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8    username: root    password: 12345678    driver-class-name: com.mysql.cj.jdbc.Driver# 配置打印 MyBatis 执行的 SQLmybatis-plus:  configuration:    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 配置打印 MyBatis 执行的 SQLlogging:  level:    com:      ai:        deepseek: debug
复制代码


4.编写实体类

import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.Getter;import lombok.Setter;
import java.io.Serializable;import java.util.Date;
@Getter@Setter@TableName("chat_message")public class ChatMessageDO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO) private Long id;
private String conversationId;
private String role;
private String context;
private Date createdAt;}
复制代码


5.编写 Mapper:

import com.ai.chat.entity.ChatMessageDO;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.apache.ibatis.annotations.Mapper;
@Mapperpublic interface ChatMessageMapper extends BaseMapper<ChatMessageDO> {}
复制代码


1.2 自定义 ChatMemory 类


自定义的 ChatMemory 实现类,将对话记录存储到 MySQL:

import com.ai.deepseek.entity.ChatMessageDO;import com.ai.deepseek.mapper.ChatMessageMapper;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import org.springframework.ai.chat.memory.ChatMemory;import org.springframework.ai.chat.messages.Message;import org.springframework.ai.chat.messages.UserMessage;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
import java.util.List;import java.util.stream.Collectors;
@Componentpublic class MySQLChatMemory implements ChatMemory { @Autowired private ChatMessageMapper repository;
@Override public void add(String conversationId, Message message) { ChatMessageDO entity = new ChatMessageDO(); entity.setConversationId(conversationId); entity.setRole(message.getMessageType().name()); entity.setContext(message.getText()); repository.insert(entity); }
@Override public void add(String conversationId, List<Message> messages) { messages.forEach(message -> add(conversationId, message)); }
@Override public List<Message> get(String conversationId, int lastN) { LambdaQueryWrapper<ChatMessageDO> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ChatMessageDO::getConversationId, conversationId); // queryWrapper.orderByDesc(ChatMessageDO::getId); return repository.selectList(queryWrapper) .stream() .limit(lastN) .map(e -> new UserMessage(e.getContext())) .collect(Collectors.toList()); }
@Override public void clear(String conversationId) { LambdaQueryWrapper<ChatMessageDO> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ChatMessageDO::getConversationId, conversationId); repository.delete(queryWrapper); }}
复制代码


1.3 代码调用


编写代码测试历史对话保存到 MySQL 的功能:

import com.ai.deepseek.component.MySQLChatMemory;import org.springframework.ai.chat.client.ChatClient;import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import reactor.core.publisher.Flux;
@RestController@RequestMapping("/multi")public class MultiChatController {
@Autowired private ChatClient chatClient; @Autowired private MySQLChatMemory chatMemory;
@RequestMapping("/chat") public Flux<String> chat(@RequestParam("msg") String msg, @RequestParam(defaultValue = "default") String sessionId) { // 添加MessageChatMemoryAdvisor,自动管理上下文 MessageChatMemoryAdvisor advisor = new MessageChatMemoryAdvisor(chatMemory, sessionId, 10); // 保留最近5条历史 return chatClient.prompt() .user(msg) .advisors(advisor) // 关键:注入记忆管理 .stream() .content(); }}
复制代码


以上程序执行结果如下:



2.SpringAIAlibaba 实现连续对话


Spring AI Alibaba 连续对话的实现就简单很多了,因为它内置了 MySQL 和 Redis 的连续对话存储方式,接下来以 Redis 为例演示 SAA 的连续对话实现,它的实现步骤如下:

  1. 添加依赖。

  2. 设置配置文件,配置 Redis 连接信息。

  3. 添加 Redis 配置类,注入 RedisChatMemoryRepository 对象。

  4. 配置 ChatClient 实现连续对话。

具体实现如下。


2.1 添加依赖

<dependency>  <groupId>com.alibaba.cloud.ai</groupId>  <artifactId>spring-ai-alibaba-starter-memory-redis</artifactId></dependency>
复制代码


2.2 设置配置文件


设置配置文件,配置 Redis 连接信息:

spring:  ai:    memory:      redis:        host: localhost        port: 6379        timeout: 5000
复制代码


2.3 添加 Redis 配置类


添加 Redis 配置类,注入 RedisChatMemoryRepository 对象,实现 Redis 自定义存储器注入:

import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
@Configurationpublic class RedisMemoryConfig {
@Value("${spring.ai.memory.redis.host}") private String redisHost; @Value("${spring.ai.memory.redis.port}") private int redisPort; // @Value("${spring.ai.memory.redis.password}") // private String redisPassword; @Value("${spring.ai.memory.redis.timeout}") private int redisTimeout;
@Bean public RedisChatMemoryRepository redisChatMemoryRepository() { return RedisChatMemoryRepository.builder() .host(redisHost) .port(redisPort) // 若没有设置密码则注释该项 // .password(redisPassword) .timeout(redisTimeout) .build(); }}
复制代码


2.4 配置 ChatClient 实现连续对话

import com.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;import org.springframework.ai.chat.client.ChatClient;import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;import org.springframework.ai.chat.memory.MessageWindowChatMemory;import org.springframework.ai.chat.model.ChatModel;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;
@RestController@RequestMapping("/redis")public class RedisMemoryController {
private final ChatClient chatClient; private final int MAXMESSAGES = 10; private final MessageWindowChatMemory messageWindowChatMemory;
public RedisMemoryController(ChatModel dashscopeChatModel, RedisChatMemoryRepository redisChatMemoryRepository) { this.messageWindowChatMemory = MessageWindowChatMemory.builder() .chatMemoryRepository(redisChatMemoryRepository) .maxMessages(MAXMESSAGES) .build();
this.chatClient = ChatClient.builder(dashscopeChatModel) .defaultAdvisors( MessageChatMemoryAdvisor.builder(messageWindowChatMemory) .build() ) .build(); }
@GetMapping("/call") public String call(String msg, String cid) { return chatClient.prompt(msg) .advisors( a -> a.param(CONVERSATION_ID, cid) ) .call().content(); }}
复制代码


小结


通过以上代码大家也可以看出来,使用 Spring AI 实现连续对话是比较复杂的,需要自己实现数据库增删改查的代码,并且重写 ChatMemory 才能实现连续对话功能;而 Spring AI Alibaba 因为内置了连续对话的多种实现(Redis 和其他数据库),所以只需要简单配置就可以实现了。


文章转载自:磊哥|www.javacn.site

原文链接:https://www.cnblogs.com/vipstone/p/18991755

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
面试官:如何实现大模型连续对话?_面试_量贩潮汐·WholesaleTide_InfoQ写作社区