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>SpringAI文生图项目</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:
packagecom.hyxf;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
publicclassDashScopeImageApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(DashScopeImageApplication.class,args);
}
}
新建一个controller层,在com.hyxf.controller层下新建DashScopeImageController类:
packagecom.hyxf.controller;
importjakarta.servlet.http.HttpServletResponse;
importorg.springframework.ai.image.*;
importorg.springframework.http.HttpStatus;
importorg.springframework.http.MediaType;
importorg.springframework.http.ResponseEntity;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importorg.springframework.web.bind.annotation.RestController;
importjava.io.IOException;
importjava.io.InputStream;
importjava.net.URI;
importjava.net.URL;
importjava.time.LocalDateTime;
importjava.util.Collection;
importjava.util.Map;
importjava.util.Set;
importjava.util.stream.Collectors;
@RestController
@RequestMapping("/ai")
publicclassDashScopeImageController{
privatefinalImageModelimageModel;
privatestaticfinalStringDEFAULT_PROMPT="为人工智能生成一张富有科技感的图片!";
publicDashScopeImageController(ImageModelimageModel){
this.imageModel=imageModel;
}
@GetMapping("/image")
publicvoidimage(HttpServletResponseresponse){
ImageResponseimageResponse=imageModel.call(newImagePrompt(DEFAULT_PROMPT));
StringimageUrl=imageResponse.getResult().getOutput().getUrl();
try{
URLurl=URI.create(imageUrl).toURL();
InputStreamin=url.openStream();
response.setHeader("Content-Type",MediaType.IMAGE_PNG_VALUE);
response.getOutputStream().write(in.readAllBytes());
response.getOutputStream().flush();
}catch(IOExceptione){
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
/**
* Generates multiple images from single prompt.
*/
@GetMapping("/image/multiPrompt")
publicResponseEntity<Collection<String>>generateImageWithMultiPrompt(
@RequestParam(value="prompt",defaultValue="一只会编程的猫")Stringprompt,
@RequestParam(defaultValue="2")intcount){
ImageOptionsoptions=ImageOptionsBuilder.builder()
.N(count)
.build();
ImageResponseresponse=imageModel.call(newImagePrompt(prompt,options));
Set<String>imageSet=response.getResults().stream().map(result->result.getOutput().getUrl()).collect(Collectors.toSet());
returnResponseEntity.ok(imageSet);
}
/**
* multi condition and safe to generation image
*/
@GetMapping("/image/multipleConditions")
publicResponseEntity<?>multipleConditions(
@RequestParam(value="subject",defaultValue="一只会编程的猫")Stringsubject,
@RequestParam(value="environment",defaultValue="办公室")Stringenvironment,
@RequestParam(value="height",defaultValue="1024")Integerheight,
@RequestParam(value="width",defaultValue="1024")Integerwidth,
@RequestParam(value="style",defaultValue="生动")Stringstyle){
Stringprompt=String.format(
"一个%s,置身于%s的环境中,使用%s的艺术风格,高清4K画质,细节精致",
subject,environment,style
);
ImageOptionsoptions=ImageOptionsBuilder.builder()
.height(height)
.width(width)
.build();
try{
ImageResponseresponse=imageModel.call(newImagePrompt(prompt,options));
returnResponseEntity.ok(response.getResult().getOutput().getUrl());
}catch(Exceptione){
returnResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of(
"error","图像生成失败",
"message",e.getMessage(),
"timestamp",LocalDateTime.now()
));
}
}
}
如图:
其中
privatefinalImageModelimageModel;
使用的是
importorg.springframework.ai.image.*;
依赖,Spring AI已经整合好ImageModel够大家使用。
ImageModel也需要注入Controller:
publicDashScopeImageController(ImageModelimageModel){
this.imageModel=imageModel;
}
调用图片模型,获取返回的response数据,并显示图片:
@GetMapping("/image")
publicvoidimage(HttpServletResponseresponse){
ImageResponseimageResponse=imageModel.call(newImagePrompt(DEFAULT_PROMPT));
StringimageUrl=imageResponse.getResult().getOutput().getUrl();
try{
URLurl=URI.create(imageUrl).toURL();
InputStreamin=url.openStream();
response.setHeader("Content-Type",MediaType.IMAGE_PNG_VALUE);
response.getOutputStream().write(in.readAllBytes());
response.getOutputStream().flush();
}catch(IOExceptione){
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
启动项目DashScopeImageApplication类,查看运行:
在浏览器输入:http://localhost:8080/ai/image
生成了一张科技感的图片:
你还可以修改指令:
privatestaticfinalStringDEFAULT_PROMPT="为人工智能生成一张富有科技感的图片!";
来生成各式各样的图片,根据指令提示词。
生成多张图片,根据指令和图片生成数量,修改ImageModel参数,来生成要求的图片:
@GetMapping("/image/multiPrompt")
publicResponseEntity<Collection<String>>generateImageWithMultiPrompt(
@RequestParam(value="prompt",defaultValue="一只会编程的猫")Stringprompt,
@RequestParam(defaultValue="2")intcount){
ImageOptionsoptions=ImageOptionsBuilder.builder()
.N(count)
.build();
ImageResponseresponse=imageModel.call(newImagePrompt(prompt,options));
Set<String>imageSet=response.getResults().stream().map(result->result.getOutput().getUrl()).collect(Collectors.toSet());
returnResponseEntity.ok(imageSet);
}
其中ImageOptions设置了张数,根据指令并入ImageModel参数,来获取结果,我们打开浏览器:
http://localhost:8080/ai/image/multiPrompt?prompt=一只机械狗&count=3
运行查看结果,出来三张图片url路径:
我们将路径复制到浏览器查看,下载到本地,打开看图片:
帮我们生成了机械狗照片。
手动设置指令,动态传入参数示例:
@GetMapping("/image/multipleConditions")
publicResponseEntity<?>multipleConditions(
@RequestParam(value="subject",defaultValue="一只会编程的猫")Stringsubject,
@RequestParam(value="environment",defaultValue="办公室")Stringenvironment,
@RequestParam(value="height",defaultValue="1024")Integerheight,
@RequestParam(value="width",defaultValue="1024")Integerwidth,
@RequestParam(value="style",defaultValue="生动")Stringstyle){
Stringprompt=String.format(
"一个%s,置身于%s的环境中,使用%s的艺术风格,高清4K画质,细节精致",
subject,environment,style
);
ImageOptionsoptions=ImageOptionsBuilder.builder()
.height(height)
.width(width)
.build();
try{
ImageResponseresponse=imageModel.call(newImagePrompt(prompt,options));
returnResponseEntity.ok(response.getResult().getOutput().getUrl());
}catch(Exceptione){
returnResponseEntity.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包,包中新建启动类:
packagecom.hyxf;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
publicclassChatMemoryApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(ChatMemoryApplication.class,args);
}
}
此外,还需要Spring AI Memory配置文件,我们新建com.hyxf.config包,在包下新建MemoryConfig文件:
packagecom.hyxf.config;
importcom.alibaba.cloud.ai.memory.jdbc.MysqlChatMemoryRepository;
importcom.alibaba.cloud.ai.memory.jdbc.SQLiteChatMemoryRepository;
importcom.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.jdbc.core.JdbcTemplate;
importorg.springframework.jdbc.datasource.DriverManagerDataSource;
@Configuration
publicclassMemoryConfig{
@Value("${spring.ai.memory.redis.host}")
privateStringredisHost;
@Value("${spring.ai.memory.redis.port}")
privateintredisPort;
@Value("${spring.ai.memory.redis.password}")
privateStringredisPassword;
@Value("${spring.ai.memory.redis.timeout}")
privateintredisTimeout;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.jdbc-url}")
privateStringmysqlJdbcUrl;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.username}")
privateStringmysqlUsername;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.password}")
privateStringmysqlPassword;
@Value("${spring.ai.chat.memory.repository.jdbc.mysql.driver-class-name}")
privateStringmysqlDriverClassName;
@Bean
publicSQLiteChatMemoryRepositorysqliteChatMemoryRepository(){
DriverManagerDataSourcedataSource=newDriverManagerDataSource();
dataSource.setDriverClassName("org.sqlite.JDBC");
dataSource.setUrl("jdbc:sqlite:spring-ai-dashscope-memory/src/main/resources/chat-memory.db");
JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
returnSQLiteChatMemoryRepository.sqliteBuilder()
.jdbcTemplate(jdbcTemplate)
.build();
}
@Bean
publicMysqlChatMemoryRepositorymysqlChatMemoryRepository(){
DriverManagerDataSourcedataSource=newDriverManagerDataSource();
dataSource.setDriverClassName(mysqlDriverClassName);
dataSource.setUrl(mysqlJdbcUrl);
dataSource.setUsername(mysqlUsername);
dataSource.setPassword(mysqlPassword);
JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
returnMysqlChatMemoryRepository.mysqlBuilder()
.jdbcTemplate(jdbcTemplate)
.build();
}
@Bean
publicRedisChatMemoryRepositoryredisChatMemoryRepository(){
returnRedisChatMemoryRepository.builder()
.host(redisHost)
.port(redisPort)
// 若没有设置密码则注释该项
// .password(redisPassword)
.timeout(redisTimeout)
.build();
}
}
注入ChatMemory地址,其中SQLite这个项目名称需要替换为你的实际项目名称:
然后可以开始写controller接口层了,新建InMemoryController类,注入聊天客户端:
privatefinalChatClientchatClient;
导入的功能包如下,其中CONVERSATION_ID表示聊天记录会话id:
importorg.springframework.ai.chat.client.ChatClient;
importorg.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
importorg.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
importorg.springframework.ai.chat.memory.MessageWindowChatMemory;
importorg.springframework.ai.chat.messages.Message;
importstaticorg.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;
内存存储聊天记录,并设置最大消息条数:
privatefinalInMemoryChatMemoryRepositorychatMemoryRepository=newInMemoryChatMemoryRepository();
privatefinalintMAX_MESSAGES=100;
privatefinalMessageWindowChatMemorymessageWindowChatMemory=MessageWindowChatMemory.builder()
.chatMemoryRepository(chatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();
Controller设置聊天工具:
publicInMemoryController(ChatClient.Builderbuilder){
this.chatClient=builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}
调用聊天信息,并存储记录:
@GetMapping("/call")
publicStringcall(@RequestParam(value="query",defaultValue="你好,我的外号是阿紫,请记住呀")Stringquery,
@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId
){
returnchatClient.prompt(query)
.advisors(
a->a.param(CONVERSATION_ID,conversationId)
)
.call().content();
}
如图:
启动项目,打开PostMan,输入url:
http://localhost:8080/advisor/memory/in/call
设置记忆参数,取外号:
记住了我的外号,再输入新的聊天指令:
这些聊天记录已被存储到内存中,再看看获取聊天记录的接口:
@GetMapping("/messages")
publicList<Message>messages(@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId){
returnmessageWindowChatMemory.get(conversationId);
}
POSTMAN调用:http://localhost:8080/advisor/memory/in/messages?conversation_id=azi
存储了历史记录信息:
接下来我们来试试MySQL存储历史记录的功能,新建Controller:
packagecom.hyxf.controller;
importcom.alibaba.cloud.ai.memory.jdbc.MysqlChatMemoryRepository;
importorg.springframework.ai.chat.client.ChatClient;
importorg.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
importorg.springframework.ai.chat.memory.MessageWindowChatMemory;
importorg.springframework.ai.chat.messages.Message;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importorg.springframework.web.bind.annotation.RestController;
importjava.util.List;
importstaticorg.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;
@RestController
@RequestMapping("/advisor/memory/mysql")
publicclassMysqlMemoryController{
privatefinalChatClientchatClient;
privatefinalintMAX_MESSAGES=100;
privatefinalMessageWindowChatMemorymessageWindowChatMemory;
publicMysqlMemoryController(ChatClient.Builderbuilder,MysqlChatMemoryRepositorymysqlChatMemoryRepository){
this.messageWindowChatMemory=MessageWindowChatMemory.builder()
.chatMemoryRepository(mysqlChatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();
this.chatClient=builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}
@GetMapping("/call")
publicStringcall(@RequestParam(value="query",defaultValue="你好,我的外号是阿紫,请记住呀")Stringquery,
@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId
){
returnchatClient.prompt(query)
.advisors(
a->a.param(CONVERSATION_ID,conversationId)
)
.call().content();
}
@GetMapping("/messages")
publicList<Message>messages(@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId){
returnmessageWindowChatMemory.get(conversationId);
}
}
具体存储信息采用的是
MysqlChatMemoryRepository
来存储历史记录,会自动创建表存储历史信息。
将新建的ai_chat_memory表执行以下命令,修改字符集:
--修改数据库字符集
ALTER DATABASE your_database CHARACTER SET utf8mb4COLLATEutf8mb4_unicode_ci;
--修改数据表字符集
ALTER TABLE ai_chat_memoryCONVERT TO CHARACTER SET utf8mb4COLLATEutf8mb4_unicode_ci;
--单独修改某一列(如 content)
ALTER TABLE ai_chat_memoryMOdify content TEXT CHARACTER SET utf8mb4COLLATEutf8mb4_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接口:
packagecom.hyxf.controller;
importcom.alibaba.cloud.ai.memory.redis.RedisChatMemoryRepository;
importorg.springframework.ai.chat.client.ChatClient;
importorg.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
importorg.springframework.ai.chat.memory.MessageWindowChatMemory;
importorg.springframework.ai.chat.messages.Message;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importorg.springframework.web.bind.annotation.RestController;
importjava.util.List;
importstaticorg.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;
@RestController
@RequestMapping("/advisor/memory/redis")
publicclassRedisMemoryController{
privatefinalChatClientchatClient;
privatefinalintMAX_MESSAGES=100;
privatefinalMessageWindowChatMemorymessageWindowChatMemory;
publicRedisMemoryController(ChatClient.Builderbuilder,RedisChatMemoryRepositoryredisChatMemoryRepository){
this.messageWindowChatMemory=MessageWindowChatMemory.builder()
.chatMemoryRepository(redisChatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();
this.chatClient=builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}
@GetMapping("/call")
publicStringcall(@RequestParam(value="query",defaultValue="你好,我的外号是阿紫,请记住呀")Stringquery,
@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId
){
returnchatClient.prompt(query)
.advisors(
a->a.param(CONVERSATION_ID,conversationId)
)
.call().content();
}
@GetMapping("/messages")
publicList<Message>messages(@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId){
returnmessageWindowChatMemory.get(conversationId);
}
}
其中使用了RedisChatMemoryRepository作为存储历史记录数据库。
打开PostMan运行:
http://localhost:8080/advisor/memory/redis/call
再问一个问题
我们调用查看及历史记录接口:
http://localhost:8080/advisor/memory/redis/messages?conversation_id=azi
最后来测试下SQLite功能,新建SQLite历史记录接口:
packagecom.hyxf.controller;
importcom.alibaba.cloud.ai.memory.jdbc.SQLiteChatMemoryRepository;
importorg.springframework.ai.chat.client.ChatClient;
importorg.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
importorg.springframework.ai.chat.memory.MessageWindowChatMemory;
importorg.springframework.ai.chat.messages.Message;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importorg.springframework.web.bind.annotation.RestController;
importjava.util.List;
importstaticorg.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;
@RestController
@RequestMapping("/advisor/memory/sqlite")
publicclassSqliteMemoryController{
privatefinalChatClientchatClient;
privatefinalintMAX_MESSAGES=100;
privatefinalMessageWindowChatMemorymessageWindowChatMemory;
publicSqliteMemoryController(ChatClient.Builderbuilder,SQLiteChatMemoryRepositorysqliteChatMemoryRepository){
this.messageWindowChatMemory=MessageWindowChatMemory.builder()
.chatMemoryRepository(sqliteChatMemoryRepository)
.maxMessages(MAX_MESSAGES)
.build();
this.chatClient=builder
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(messageWindowChatMemory)
.build()
)
.build();
}
@GetMapping("/call")
publicStringcall(@RequestParam(value="query",defaultValue="你好,我的外号是阿紫,请记住呀")Stringquery,
@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId
){
returnchatClient.prompt(query)
.advisors(
a->a.param(CONVERSATION_ID,conversationId)
)
.call().content();
}
@GetMapping("/messages")
publicList<Message>messages(@RequestParam(value="conversation_id",defaultValue="azi")StringconversationId){
returnmessageWindowChatMemory.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分别存储历史记录的方法,可灵活应用。
| 欢迎光临 链载Ai (https://www.lianzai.com/) | Powered by Discuz! X3.5 |