支持私有化部署
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


SpringAI Alibaba实战文生图、聊天记忆功能

发布日期:2025-06-01 15:38:50 浏览次数: 1650 作者:AI技术专家
推荐语

SpringAI Alibaba框架集成DashScope实现文生图和聊天记忆功能,无需额外整合。

核心内容:
1. SpringAI Alibaba框架和DashScope灵积平台的整合优势
2. 文生图功能实现步骤及DashScope模型调用方法
3. 聊天会话记忆分享的多种记录方式:内存、MySQL、Redis和SQLite

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家

SpringAI Alibaba通过DashScope灵积平台可以实现文生图和聊天记忆等功能,而且整合在Spring AI Alibaba一套框架内,无需额外再花功夫整合。其中文生图可以基于DashScope或者OpenAI模型,聊天会话记忆分享了内存、MySQL、Redis和SQLite等记录的方法。


文生图功能实现




首先需要注册阿里云百炼平台,上一篇文章已经分享过注册方法,记住APIKEY。

文生图利用DashScope底层原理是通过调用通义千问文生图模型实现,封装了一层公共工具到Spring AI。

通义千问文生图功能模型有:

我们先来搭建文本图项目,项目名称及坐标信息:


<groupId>org.example</groupId>
<artifactId>spring-ai-image</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>spring-ai-image</name>
<description>Spring AI文生图项目</description>



集成的SpringBoot父模型是3.4.0版本:


<parent>


<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
<relativePath/>
</parent>



JDK采用17版本,UTF-8编码,Maven 3.6.3配置:


<properties>


<maven.compiler.source>17</maven.compiler.source>


<maven.compiler.target>17</maven.compiler.target>


<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>


</properties>



引入SpringBoot Web模块spring-boot-starter-web,表明它是一个Web项目:


<dependency>


<groupId>org.springframework.boot</groupId>


<artifactId>spring-boot-starter-web</artifactId>


</dependency>



引入spring-ai-alibaba-starter-dashscope,即阿里巴巴灵积模型模块:


<dependency>


<groupId>com.alibaba.cloud.ai</groupId>


<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>


<version>1.0.0.1</version>


</dependency>



依赖项整体如图:

引入Maven镜像仓库:

<repositories>


<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>SpringMilestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>SpringSnapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>



然后由于是SpringBoot项目,加上Maven插件:


<build>


<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.1</version>
</plugin>
</plugins>
</build>



整体Maven镜像仓库如图:

插件用的3.4.0版本:

做完这一步,开始Maven打包:

之后刷新Maven环境:

项目环境就可用了。

在/src/main/resources目录下新建application.yml配置文件:


server:


  port:8080

spring:
  application:
    name: spring-ai-image

  ai:
    dashscope:
      api-key:"sk-DashScopeAPIKEY"

 



紧接着在源码目录/src/main/java下面新建一个包:com.hyxf,然后建立一个启动类DashScopeImageApplication:


package com.hyxf;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DashScopeImageApplication{

public static void main(String[] args){

SpringApplication.run(DashScopeImageApplication.class, args);
}

}

 



新建一个controller层,在com.hyxf.controller层下新建DashScopeImageController类:


package com.hyxf.controller;

import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.image.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/ai")
public class DashScopeImageController{

private final ImageModel imageModel;

private static final String DEFAULT_PROMPT="为人工智能生成一张富有科技感的图片!";

public DashScopeImageController(ImageModel imageModel){
this.imageModel= imageModel;
}

@GetMapping("/image")
public void image(HttpServletResponse response){

ImageResponse imageResponse= imageModel.call(new ImagePrompt(DEFAULT_PROMPT));
String imageUrl= imageResponse.getResult().getOutput().getUrl();

try{
URL url= URI.create(imageUrl).toURL();
InputStream in= url.openStream();

response.setHeader("Content-Type",MediaType.IMAGE_PNG_VALUE);
response.getOutputStream().write(in.readAllBytes());
response.getOutputStream().flush();
}catch(IOException e){
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}

/**
* Generates multiple images from single prompt.
*/
@GetMapping("/image/multiPrompt")
public ResponseEntity<Collection<String>> generateImageWithMultiPrompt(
@RequestParam(value="prompt", defaultValue="一只会编程的猫")String prompt,
@RequestParam(defaultValue="2")int count){

ImageOptions options=ImageOptionsBuilder.builder()
.N(count)
.build();
ImageResponse response= imageModel.call(new ImagePrompt(prompt, options));
Set<String> imageSet= response.getResults().stream().map(result-> result.getOutput().getUrl()).collect(Collectors.toSet());
return ResponseEntity.ok(imageSet);
}

/**
* multi condition and safe to generation image
*/
@GetMapping("/image/multipleConditions")
public ResponseEntity<?> multipleConditions(
@RequestParam(value="subject", defaultValue="一只会编程的猫")String subject,
@RequestParam(value="environment", defaultValue="办公室")String environment,
@RequestParam(value="height", defaultValue="1024")Integer height,
@RequestParam(value="width", defaultValue="1024")Integer width,
@RequestParam(value="style", defaultValue="生动")String style){

String prompt=String.format(
"一个%s,置身于%s的环境中,使用%s的艺术风格,高清4K画质,细节精致",
subject, environment, style
);

ImageOptions options=ImageOptionsBuilder.builder()
.height(height)
.width(width)
.build();

try{
ImageResponse response= imageModel.call(new ImagePrompt(prompt, options));
return ResponseEntity.ok(response.getResult().getOutput().getUrl());
}catch(Exception e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"error","图像生成失败",
"message", e.getMessage(),
"timestamp",LocalDateTime.now()
));
}
}

}

 



如图:

其中


private final ImageModel imageModel;



使用的是

import org.springframework.ai.image.*;



依赖,Spring AI已经整合好ImageModel够大家使用。

ImageModel也需要注入Controller:


public DashScopeImageController(ImageModel imageModel){


this.imageModel= imageModel;


}



调用图片模型,获取返回的response数据,并显示图片:


@GetMapping("/image")
public void image(HttpServletResponse response){

ImageResponse imageResponse= imageModel.call(new ImagePrompt(DEFAULT_PROMPT));
String imageUrl= imageResponse.getResult().getOutput().getUrl();

try{
URL url= URI.create(imageUrl).toURL();
InputStream in= url.openStream();

response.setHeader("Content-Type",MediaType.IMAGE_PNG_VALUE);
response.getOutputStream().write(in.readAllBytes());
response.getOutputStream().flush();
}catch(IOException e){
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}



启动项目DashScopeImageApplication类,查看运行:

在浏览器输入:http://localhost:8080/ai/image

生成了一张科技感的图片:

你还可以修改指令:


private static final String DEFAULT_PROMPT="为人工智能生成一张富有科技感的图片!";



来生成各式各样的图片,根据指令提示词。

生成多张图片,根据指令和图片生成数量,修改ImageModel参数,来生成要求的图片:


@GetMapping("/image/multiPrompt")
public ResponseEntity<Collection<String>> generateImageWithMultiPrompt(
@RequestParam(value="prompt", defaultValue="一只会编程的猫")String prompt,
@RequestParam(defaultValue="2")int count){

ImageOptions options=ImageOptionsBuilder.builder()
.N(count)
.build();
ImageResponse response= imageModel.call(new ImagePrompt(prompt, options));
Set<String> imageSet= response.getResults().stream().map(result-> result.getOutput().getUrl()).collect(Collectors.toSet());
return ResponseEntity.ok(imageSet);
}



其中ImageOptions设置了张数,根据指令并入ImageModel参数,来获取结果,我们打开浏览器:

http://localhost:8080/ai/image/multiPrompt?prompt=一只机械狗&count=3

运行查看结果,出来三张图片url路径:

我们将路径复制到浏览器查看,下载到本地,打开看图片:

帮我们生成了机械狗照片。

手动设置指令,动态传入参数示例:


@GetMapping("/image/multipleConditions")
public ResponseEntity<?>multipleConditions(
@RequestParam(value="subject", defaultValue="一只会编程的猫")String subject,
@RequestParam(value="environment", defaultValue="办公室")String environment,
@RequestParam(value="height", defaultValue="1024")Integer height,
@RequestParam(value="width", defaultValue="1024")Integer width,
@RequestParam(value="style", defaultValue="生动")String style){

String prompt=String.format(
"一个%s,置身于%s的环境中,使用%s的艺术风格,高清4K画质,细节精致",
subject, environment, style
);

ImageOptions options=ImageOptionsBuilder.builder()
.height(height)
.width(width)
.build();

try{
ImageResponse response= imageModel.call(new ImagePrompt(prompt, options));
return ResponseEntity.ok(response.getResult().getOutput().getUrl());
}catch(Exception e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"error","图像生成失败",
"message", e.getMessage(),
"timestamp",LocalDateTime.now()
));
}
}



可以调整宽高和指令,动态控制,我们打开浏览器输入:http://localhost:8080/ai/image/multipleConditions

将路径拷贝至浏览器,下载查看:

生成了一只编程猫,1024*1024像素。

这些是文生图功能,接下来进入聊天记忆功能。


模型聊天会话记忆功能




大家在使用大模型聊天过程中,常常需要上下文功能,来补足对话,如果不能记得上下文,大模型可能会出现幻觉等状况,胡说八道。

这个时候就需要模型记忆功能了。

模型记忆的核心在于Spring AI提供的三个Memory模块:

内存记忆模块:


<dependency>


<groupId>com.alibaba.cloud.ai</groupId>


<artifactId>spring-ai-alibaba-starter-memory</artifactId>


<version>1.0.0.1</version>


</dependency>



JDBC记忆模块:


<dependency>


<groupId>com.alibaba.cloud.ai</groupId>


<artifactId>spring-ai-alibaba-starter-memory-jdbc</artifactId>


<version>1.0.0.1</version>


</dependency>



Redis记忆模块:


<dependency>


<groupId>com.alibaba.cloud.ai</groupId>


<artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>


<version>1.0.0.1</version>


</dependency>



此外还需要引入Redis、MySQL驱动包:


<dependency>


<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>



如果要用到SQLite,还需SQLite驱动:


<dependency>


<groupId>org.xerial</groupId>


<artifactId>sqlite-jdbc</artifactId>


<version>3.49.1.0</version>


</dependency>



引入向量数据库和ES作为知识库底蕴:


<dependency>


<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.15.5</version>
</dependency>



其中SpringBoot父模块还是3.4.0:


<parent>


<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
<relativePath/>
</parent>



JDK依然是17,UTF-8编码:


<properties>


<maven.compiler.source>17</maven.compiler.source>


<maven.compiler.target>17</maven.compiler.target>


<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>


</properties>



引入Spring Boot Web和DashScope模型:


<dependency>


<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.0.0.1</version>
</dependency>



Maven私服镜像不要忘了:

Maven打包插件神器:

右边Maven Install之后记得刷新Maven环境:

之后将chat-memory.db SQLite数据库文件放入/src/main/resources目录下,下载方式:

下载下来拷贝到/src/main/resources目录下:

在你的电脑环境中确保Redis和MySQL已安装,没有安装的话去查看相关Redis和MySQL安装方式。

然后在/src/main/resources目录下新建application.yml文件,内容如下:


server:


  port:8080

spring:
  ai:
    dashscope:
      api-key:"sk-DashScopeAPIKEY"
    memory:
      redis:
        host: localhost
        port:6379
        password:
        timeout:5000
    chat:
      memory:
        repository:
          jdbc:
            mysql:
              jdbc-url: jdbc:mysql://localhost:3306/spring_ai_alibaba_mysql?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&tinyInt1isBit=false&allowLoadLocalInfile=true&allowLocalInfile=true&allowUrl
              username: root
              password:123456
              driver-class-name:com.mysql.cj.jdbc.Driver
              enabled:true

 



其中spring.ai.memory.redis配置Redis连接存储地址,请配置为你环境中的Redis。

spring.ai.chat.memory.repository.jdbc设置JDBC连接存储地址,配置为你电脑环境中的Redis。

如图:

新建com.hyxf包,包中新建启动类:


package com.hyxf;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude ={DataSourceAutoConfiguration.class})
public class ChatMemoryApplication{

public static void main(String[] args){

SpringApplication.run(ChatMemoryApplication.class, args);
}

}

 



此外,还需要Spring AI Memory配置文件,我们新建com.hyxf.config包,在包下新建MemoryConfig文件:


package com.hyxf.config;

import com.alibaba.cloud.ai.memory.jdbc.MysqlChatMemoryRepository;
import com.alibaba.cloud.ai.memory.jdbc.SQLiteChatMemoryRepository;
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;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

@Configuration
public class MemoryConfig{

@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;

@Value("${spring.ai.chat.memory.repository.jdbc.mysql.jdbc-url}")
private String mysqlJdbcUrl;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.username}")
private String mysqlUsername;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.password}")
private String mysqlPassword;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.driver-class-name}")
private String mysqlDriverClassName;

@Bean
public SQLiteChatMemoryRepository sqliteChatMemoryRepository(){
DriverManagerDataSource dataSource =new DriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:spring-ai-dashscope-memory/src/main/resources/chat-memory.db");
JdbcTemplate jdbcTemplate =new JdbcTemplate(dataSource);
return SQLiteChatMemoryRepository.sqliteBuilder()
.jdbcTemplate(jdbcTemplate)
.build();
}

@Bean
public MysqlChatMemoryRepository mysqlChatMemoryRepository(){
DriverManagerDataSource dataSource =new DriverManagerDataSource();
dataSource.setDriverClassName(mysqlDriverClassName);
dataSource.setUrl(mysqlJdbcUrl);
dataSource.setUsername(mysqlUsername);
dataSource.setPassword(mysqlPassword);
JdbcTemplate jdbcTemplate =new JdbcTemplate(dataSource);
return MysqlChatMemoryRepository.mysqlBuilder()
.jdbcTemplate(jdbcTemplate)
.build();
}

@Bean
public RedisChatMemoryRepository redisChatMemoryRepository(){
return RedisChatMemoryRepository.builder()
.host(redisHost)
.port(redisPort)
// 若没有设置密码则注释该项
// .password(redisPassword)
.timeout(redisTimeout)
.build();
}
}

 



注入ChatMemory地址,其中SQLite这个项目名称需要替换为你的实际项目名称:

然后可以开始写controller接口层了,新建InMemoryController类,注入聊天客户端:


private final ChatClient chatClient;



导入的功能包如下,其中CONVERSATION_ID表示聊天记录会话id:


import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;



内存存储聊天记录,并设置最大消息条数:


private final InMemoryChatMemoryRepository chatMemoryRepository =new InMemoryChatMemoryRepository();
private final int MAX_MESSAGES =100;
private final MessageWindowChatMemory messageWindowChatMemory =MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();



Controller设置聊天工具:


public InMemoryController(ChatClient.Builder builder){
this.chatClient = builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}



调用聊天信息,并存储记录:


@GetMapping("/call")
public String call(@RequestParam(value ="query", defaultValue ="你好,我的外号是阿紫,请记住呀")String query,
@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId
){
return chatClient.prompt(query)
.advisors(
                        a -> a.param(CONVERSATION_ID, conversationId)
)
.call().content();
}



如图:

启动项目,打开PostMan,输入url:

http://localhost:8080/advisor/memory/in/call

设置记忆参数,取外号:

记住了我的外号,再输入新的聊天指令:

这些聊天记录已被存储到内存中,再看看获取聊天记录的接口:


@GetMapping("/messages")
public List<Message> messages(@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId){
return messageWindowChatMemory.get(conversationId);
}



POSTMAN调用:http://localhost:8080/advisor/memory/in/messages?conversation_id=azi

存储了历史记录信息:

接下来我们来试试MySQL存储历史记录的功能,新建Controller:


package com.hyxf.controller;

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.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;

@RestController
@RequestMapping("/advisor/memory/mysql")
public class MysqlMemoryController{

private final ChatClient chatClient;
private final int MAX_MESSAGES =100;
private final MessageWindowChatMemory messageWindowChatMemory;

public MysqlMemoryController(ChatClient.Builder builder,MysqlChatMemoryRepository mysqlChatMemoryRepository){
this.messageWindowChatMemory =MessageWindowChatMemory.builder()
.chatMemoryRepository(mysqlChatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();

this.chatClient = builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}

@GetMapping("/call")
public String call(@RequestParam(value ="query", defaultValue ="你好,我的外号是阿紫,请记住呀")String query,
@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId
){
return chatClient.prompt(query)
.advisors(
                        a -> a.param(CONVERSATION_ID, conversationId)
)
.call().content();
}

@GetMapping("/messages")
public List<Message> messages(@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId){
return messageWindowChatMemory.get(conversationId);
}
}



具体存储信息采用的是

MysqlChatMemoryRepository



来存储历史记录,会自动创建表存储历史信息。

将新建的ai_chat_memory表执行以下命令,修改字符集:


-- 修改数据库字符集
   ALTER DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 修改数据表字符集
   ALTER TABLE ai_chat_memory CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 单独修改某一列(如 content)
   ALTER TABLE ai_chat_memory MOdify content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

 



打开POSTMAN运行:

http://localhost:8080/advisor/memory/mysql/call

然后再问一个问题:

我们查看ai_chat_memory,表中已经有了历史记录:

我们运行查看历史记录url的接口:

http://localhost:8080/advisor/memory/mysql/messages?conversation_id=azi

接下来我们来测试Redis历史记录的功能,新建Controller接口:


package com.hyxf.controller;

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.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;

@RestController
@RequestMapping("/advisor/memory/redis")
public class RedisMemoryController{

private final ChatClient chatClient;
private final int MAX_MESSAGES =100;
private final MessageWindowChatMemory messageWindowChatMemory;

public RedisMemoryController(ChatClient.Builder builder,RedisChatMemoryRepository redisChatMemoryRepository){
this.messageWindowChatMemory =MessageWindowChatMemory.builder()
.chatMemoryRepository(redisChatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();

this.chatClient = builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}

@GetMapping("/call")
public String call(@RequestParam(value ="query", defaultValue ="你好,我的外号是阿紫,请记住呀")String query,
@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId
){
return chatClient.prompt(query)
.advisors(
                        a -> a.param(CONVERSATION_ID, conversationId)
)
.call().content();
}

@GetMapping("/messages")
public List<Message> messages(@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId){
return messageWindowChatMemory.get(conversationId);
}
}



其中使用了RedisChatMemoryRepository作为存储历史记录数据库。

打开PostMan运行:

http://localhost:8080/advisor/memory/redis/call

再问一个问题

我们调用查看及历史记录接口:

http://localhost:8080/advisor/memory/redis/messages?conversation_id=azi

最后来测试下SQLite功能,新建SQLite历史记录接口:


package com.hyxf.controller;

import com.alibaba.cloud.ai.memory.jdbc.SQLiteChatMemoryRepository;
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.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;

@RestController
@RequestMapping("/advisor/memory/sqlite")
public class SqliteMemoryController{

private final ChatClient chatClient;
private final int MAX_MESSAGES =100;
private final MessageWindowChatMemory messageWindowChatMemory;

public SqliteMemoryController(ChatClient.Builder builder,SQLiteChatMemoryRepository sqliteChatMemoryRepository){
this.messageWindowChatMemory =MessageWindowChatMemory.builder()
.chatMemoryRepository(sqliteChatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();

this.chatClient = builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}

@GetMapping("/call")
public String call(@RequestParam(value ="query", defaultValue ="你好,我的外号是阿紫,请记住呀")String query,
@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId
){
return chatClient.prompt(query)
.advisors(
                        a -> a.param(CONVERSATION_ID, conversationId)
)
.call().content();
}

@GetMapping("/messages")
public List<Message> messages(@RequestParam(value ="conversation_id", defaultValue ="azi")String conversationId){
return messageWindowChatMemory.get(conversationId);
}
}

 



打开PostMan发送消息给SQLite:

http://localhost:8080/advisor/memory/sqlite/call

再问个问题

查看SQLite历史记录:

http://localhost:8080/advisor/memory/sqlite/messages?conversation_id=azi

如果大家想新设置会话窗口,只需要传入新的conversation_id即可。

在实际AI应用中,会话聊天记忆功能非常重要,介绍了内存、MySQL、Redis、SQLite分别存储历史记录的方法,可灵活应用。

如果不错,可以一键三连。

本项目源码地址:https://gitee.com/javagongfu/spring-ai-alibaba-use-examples

有问题也可以添加微信号:liyue199011咨询。


53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询