微信扫码
添加专属顾问
我要投稿
SpringAI Alibaba框架集成DashScope实现文生图和聊天记忆功能,无需额外整合。核心内容: 1. SpringAI Alibaba框架和DashScope灵积平台的整合优势 2. 文生图功能实现步骤及DashScope模型调用方法 3. 聊天会话记忆分享的多种记录方式:内存、MySQL、Redis和SQLite
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+中大型企业
2024-08-13
2024-06-13
2024-08-21
2024-07-31
2024-09-23
2024-05-28
2024-08-04
2024-04-26
2024-07-09
2024-07-20