关于Ai超级智能体实现mysql持久化

这里面还是有不少的坑,也是参考了一位老哥写的,文章链接我贴到最后。 首先引入依赖,建议根据自己的版本来

js
复制代码
<!-- 适配Spring Boot 3.5.0的最新版本 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency>

配置文件

js
复制代码
datasource: url: jdbc:mysql://localhost:3306/ai_agent?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&useSSL=false username: 自己的账号 password: 自己的密码 driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 10 minimum-idle: 2 idle-timeout: 30000 max-lifetime: 1800000 connection-timeout: 30000 # 连接超时时间:30秒 validation-timeout: 5000 leak-detection-threshold: 60000 mybatis: mapper-locations: classpath:mapper/*.xml # XML映射文件位置(如果使用XML) configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL

表结构

js
复制代码
create table ai_chat_memory ( id bigint auto_increment primary key, conversation_id varchar(255) not null comment '会话id', type varchar(20) not null comment '消息类型', content text not null comment '消息内容', create_time timestamp default CURRENT_TIMESTAMP null comment '创建时间' ); create index idx_acm_conversation_id on ai_chat_memory (conversation_id);

Mapper层

js
复制代码
@Mapper public interface AiChatMemoryMapper { void saveChat(@Param("aiChatMemory") AiChatMemory aiChatMemory); void saveChatList(@Param("aiChatMemoryList") List<AiChatMemory> aiChatMemoryList); List<AiChatMemory> getChatList(@Param("conversationId") String conversationId, @Param("lastN") int lastN); void deleteChat(String conversationId); }

MapperXml

js
复制代码
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ai.agent.mapper.AiChatMemoryMapper"> <resultMap id="BaseResultMap" type="com.ai.agent.pojo.AiChatMemory"> <id column="id" property="id" jdbcType="BIGINT" /> <result column="conversation_id" property="conversationId" jdbcType="VARCHAR" /> <result column="type" property="type" jdbcType="VARCHAR" /> <result column="content" property="content" jdbcType="VARCHAR" /> <result column="create_time" property="createTime" jdbcType="TIMESTAMP" /> </resultMap> <insert id="saveChat"> insert into ai_chat_memory (conversation_id, type, content, create_time) values (#{aiChatMemory.conversationId}, #{aiChatMemory.type}, #{aiChatMemory.content}, #{aiChatMemory.createTime}) </insert> <insert id="saveChatList"> insert into ai_chat_memory (conversation_id, type, content, create_time) values <foreach collection="aiChatMemoryList" item="item" separator=","> (#{item.conversationId}, #{item.type}, #{item.content}, #{item.createTime}) </foreach> </insert> <delete id="deleteChat"> delete from ai_chat_memory where conversation_id = #{conversationId} </delete> <select id="getChatList" resultMap="BaseResultMap"> select id, conversation_id, type, content, create_time from ai_chat_memory where conversation_id = #{conversationId} order by create_time desc limit #{lastN} </select> </mapper>

这里注入了mapper,记得一定要把自己的类注入到容器中,lastN是有概率为负数的,记得自己取正

js
复制代码
@Slf4j @Component public class MysqlChatMemory implements ChatMemory { @Resource private AiChatMemoryMapper aiChatMemoryMapper; @Override @Transactional public void add(String conversationId, Message message) { AiChatMemory aiChatMemory = new AiChatMemory(); aiChatMemory.setConversationId(conversationId); aiChatMemory.setType(message.getMessageType().getValue()); aiChatMemory.setContent(message.getText()); aiChatMemory.setCreateTime(DateTime.now()); aiChatMemoryMapper.saveChat(aiChatMemory); } @Override @Transactional public void add(String conversationId, List<Message> messages) { List<AiChatMemory> aiChatMemoryList = new ArrayList<>(); DateTime now = DateTime.now(); for (Message message : messages) { AiChatMemory aiChatMemory = new AiChatMemory(); aiChatMemory.setConversationId(conversationId); aiChatMemory.setType(message.getMessageType().getValue()); aiChatMemory.setContent(message.getText()); aiChatMemory.setCreateTime(now); aiChatMemoryList.add(aiChatMemory); } aiChatMemoryMapper.saveChatList(aiChatMemoryList); } @Override public List<Message> get(String conversationId, int lastN) { //查询最近lastN条记录 lastN = Math.max(lastN, 0); List<AiChatMemory> chatList = aiChatMemoryMapper.getChatList(conversationId, lastN); List<Message> messages = new ArrayList<>(); for (AiChatMemory aiChatMemory : chatList) { String type = aiChatMemory.getType(); switch (type) { case "user" -> messages.add(new UserMessage(aiChatMemory.getContent())); case "assistant" -> messages.add(new AssistantMessage(aiChatMemory.getContent())); case "system" -> messages.add(new SystemMessage(aiChatMemory.getContent())); default -> log.info("未知类型:{}", type); } } return messages; } @Override public void clear(String conversationId) { aiChatMemoryMapper.deleteChat(conversationId); } }

最后,这里需要注意。数据库持久化写到全局配置中需要你使用@PostConstruct这个注解去加载,或者单独拉出来加载,构造函数会导致NUll异常,因为构造函数早于依赖注入。 还有就是,这里的conversationId默认是Default,所以你需要自己去编写conversationId,保存到数据库中,不然使用默认的会导致不同用户之间的历史消息混乱串起来。

js
复制代码
@Component @Slf4j public class TravelApp { @Resource MysqlChatMemory mysqlChatMemory; private final ChatClient chatClient; private static final String TRAVEL_CHAT_ID = "TRAVEL_CHAT_ID"; private static final String TRAVEL_MESSAGE_SIZE = "TRAVEL_MESSAGE_SIZE"; private static final String TRAVEL_PROMPT = "作为旅行规划顾问,我将根据您的需求、预算和目的地,提供以下定制服务:" + "1. 酒店推荐:按预算提供经济、特色或高端住宿选项及优势;" + "2. 景点行程:包含地标与小众景点,附开放时间、门票建议和拍照推荐;" + "3. 天气与准备:逐日天气预报及相应穿搭与物品清单;" + "4. 预算明细:分项列出各项开支并提供省钱建议;" + "5. 特色活动与备选方案:如雨天替代景点等。"; /** * 初始化大模型 * * @param dashscopeChatModel 大模型 */ public TravelApp(ChatModel dashscopeChatModel) { chatClient = ChatClient.builder(dashscopeChatModel) .defaultAdvisors( // 自定义日志拦截器可按需开启 new MyLoggerAdvisor()) .build(); } /** * ai对话支持多轮对话 * * @param message 消息 * @param chatId 对话id */ public String doChat(String message, String chatId) { try { String conversationId = chatId; ChatResponse chatResponse = chatClient.prompt() .system(TRAVEL_PROMPT) .user(message) .advisors(new MessageChatMemoryAdvisor(mysqlChatMemory, conversationId, 5)) .call() .chatResponse(); if (chatResponse != null) { return chatResponse.getResult().getOutput().getText(); } return ErrorCode.NEW_OPERATION_ERROR.getMessage(); } catch (Exception e) { log.error("错误信息:{}", e.getMessage(), e); return ErrorCode.NEW_OPERATION_ERROR.getMessage(); } } }

文章链接:https://blog.csdn.net/weixin_37948888/article/details/147831035?fromshare=blogdetail&sharetype=blogdetail&sharerId=147831035&sharerefer=PC&sharesource=laingnianbandeku&sharefrom=from_link

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
Sin
下载 APP