首页 » 软件开发 » AI编程之手把手教你使用langchain4j编写一个有记忆的聊天机器人(机器人记忆手把手教你编程聊天)

AI编程之手把手教你使用langchain4j编写一个有记忆的聊天机器人(机器人记忆手把手教你编程聊天)

乖囧猫 2024-07-24 05:58:38 0

扫一扫用手机浏览

文章目录 [+]

用户:你好,我叫leoAI机器人:嗨,leo,有什么可以帮您的吗?用户:我叫什么名字?AI机器人:你叫Leo。

本文手把手教你用langchain4j来实现这样的记忆功能。

STEP0:基本环境准备和编程入门回顾,请参考我的AI文章系列:

AI编程之手把手教你在CentOS安装Postgresql的Vector向量数据库

AI编程之手把手教你使用langchain4j编写一个有记忆的聊天机器人(机器人记忆手把手教你编程聊天) 软件开发
(图片来自网络侵删)

AI编程之手把手教你使用postgresql向量数据库建设知识库JAVA版

AI编程之手把手教你使用langchain和postgresql向量库Python版

AI编程之手把手教你使用JAVA语言编写大模型RAG

STEP1: 安装Postgresql+pgvector向量库

请参考我之前的文章: AI编程之手把手教你在CentOS安装Postgresql的Vector向量数据库

STEP2: 建表存放记忆内容

CREATE TABLE chat_memory (memory_id INT NOT NULL PRIMARY KEY,chat_messages TEXT NULL);

STEP3: 实现一个基于postgresql的记忆存储

LangChain4j提出了ChatMemory的概念,它的本质是ChatMessage的容器。

ChatMemory是一个接口定义,它内部封装了一个ChatMessage的容器,提供了追加条目和清除记忆存储两个方法。

LangChain4j提供了两种ChatMemory实现:

MessageWindowChatMemory提供了一种简单的文本化存储方式,按照条数存储,FIFO模式,如果超出条数,最老的一条被淘汰。
注意,只能存储一条SystemMessage,如果加入另一条SystemMessage,前一条SystemMessage会被淘汰。
TokenWindowChatMemory提供了token化的存储方式,按照token数量存储,FIFO模式,如果超出token数量,最老的一条消息将会被淘汰。
注意,只能存储一条SystemMessage,如果加入另一条SystemMessage,前一条SystemMessage会被淘汰。

ChatMemoryStore定义了一个用来持久化ChatMemory里存储的信息。

定义了查询、更新、删除持久化数据的能力。

我们主要需要实现的是使用Postgresql做为持久化的ChatMemoryStore。
代码如下:

//ChatMemory存储具体实现@Slf4j@Servicepublic class PersistentChatMemoryStore implements ChatMemoryStore {@ResourceChatMemoryMapper chatMemoryMapper;@Overridepublic List<ChatMessage> getMessages(Object memoryId) {ChatMemoryEntity chatMemoryEntity = chatMemoryMapper.queryForChatMemory((Integer)memoryId);if(null == chatMemoryEntity){return messagesFromJson(null);}return messagesFromJson(chatMemoryEntity.getChatMessages());}@Overridepublic void updateMessages(Object memoryId, List<ChatMessage> messages) {String json = messagesToJson(messages);ChatMemoryEntity chatMemoryEntity = new ChatMemoryEntity();chatMemoryEntity.setMemoryId((Integer) memoryId);chatMemoryEntity.setChatMessages(json);ChatMemoryEntity chatMemoryEntity1 = chatMemoryMapper.queryForChatMemory((Integer)memoryId);if (null == chatMemoryEntity1){chatMemoryMapper.insertChatMemory(chatMemoryEntity);}else {chatMemoryMapper.updateChatMemory(chatMemoryEntity);}}@Overridepublic void deleteMessages(Object memoryId) {chatMemoryMapper.deleteForChatMemory((Integer)memoryId);}}

数据库Mapper代码:

@Mapperpublic interface ChatMemoryMapper extends BaseMapper<ChatMemoryEntity> {ChatMemoryEntity queryForChatMemory(Integer memoryId);void updateChatMemory(@Param("chatMemoryEntity") ChatMemoryEntity chatMemoryEntity);void insertChatMemory(@Param("chatMemoryEntity") ChatMemoryEntity chatMemoryEntity);void deleteForChatMemory(Integer memoryId);}

Mybatis配置代码:

<?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="org.leo.llm.dao.ChatMemoryMapper"><!-- 定义 ResultMap --><resultMap id="chatmemoryResultMap" type="org.leo.llm.entity.ChatMemoryEntity"><id property="memoryId" column="memory_id" /><result property="chatMessages" column="chat_messages" /></resultMap><select id="queryForChatMemory" resultMap="chatmemoryResultMap">SELECT a.memory_id , a.chat_messagesFROM chat_memory a WHERE a.memory_id = #{memoryId}</select><update id="updateChatMemory" >UPDATE chat_memory SET chat_messages = #{chatMemoryEntity.chatMessages}WHERE memory_id = #{chatMemoryEntity.memoryId}</update><insert id="insertChatMemory" >insert into chat_memory (memory_id , chat_messages)values (#{chatMemoryEntity.memoryId},#{chatMemoryEntity.chatMessages})</insert><delete id="deleteForChatMemory" >delete from chat_memorywhere memory_id = #{chatMemoryEntity.memoryId}</delete></mapper>

STEP4: 实现一个有记忆的聊天机器人

我们仍然使用AiServices快速包装产生聊天机器人。

public String chatWithMemory(Integer userId,String chatMessage) {OpenAiChatModel chatModel = OpenAiChatModel.builder().baseUrl("https://oneapi.xty.app/v1").apiKey("sk-1234567890abcdef").modelName("gpt-3.5-turbo").build();ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder().id(memoryId).maxMessages(10).chatMemoryStore(persistentChatMemoryStore).build();LLMAssistant agent = AiServices.builder(LLMAssistant.class).chatLanguageModel(chatModel).chatMemoryProvider(chatMemoryProvider).build();return agent.chat(userId,chatMessage);}

STEP5: 运行起来看看效果

经过几次对话,我们看看历史记录:

我:我叫leoAI机器人:你好,leo!
有什么可以帮助你的吗?我:我叫什么名字?AI机器人:你叫Leo。
--把应用重启了一遍。
重启之后我:我叫什么名字?AI机器人:你叫Leo。

Postgresql里也存入了记忆数据:

通过引入聊天历史,这个简单的聊天机器人具备了记忆能力。

STEP6: 后续

后续将使用Langchain和postgresql实现更多的CASE,敬请关注。

作者简介:

leo,互联网大厂AI架构师,欢迎私信交流

我的Dify AI case by case系列文章:

dify.ai 学习 case by case 第一弹

dify.ai 学习 case by case 第二弹,爆款小红书内容生成Agent

dify.ai 学习 case by case 第三弹,调用dify的API运行流程

dify.ai 学习 case by case 第四弹,复杂的case:用dify生成一篇论文

STEP by STEP 训练一个transformer模型

相关文章

语言中的借用,文化交融的桥梁

自古以来,人类社会的交流与发展离不开语言的传播。在漫长的历史长河中,各民族、各地区之间的文化相互碰撞、交融,产生了许多独特的语言现...

软件开发 2025-01-01 阅读1 评论0

机顶盒协议,守护数字生活的新卫士

随着科技的飞速发展,数字家庭逐渐走进千家万户。在这个时代,机顶盒成为了连接我们与丰富多彩的数字世界的重要桥梁。而机顶盒协议,作为保...

软件开发 2025-01-01 阅读1 评论0

语言基础在现代社会的重要性及方法步骤

语言是人类沟通的桥梁,是社会发展的基础。语言基础作为语言学习的基石,对于个人、社会乃至国家的发展具有重要意义。本文将从语言基础在现...

软件开发 2025-01-01 阅读2 评论0

粤语电影,传承文化,点亮时代之光

粤语电影,作为中国电影产业的一朵奇葩,以其独特的地域特色、丰富的文化内涵和鲜明的艺术风格,赢得了广大观众的喜爱。本文将从粤语电影的...

软件开发 2025-01-01 阅读3 评论0

苹果游戏语言,塑造未来娱乐体验的基石

随着科技的飞速发展,游戏产业逐渐成为全球娱乐市场的重要支柱。在我国,游戏产业更是蓬勃发展,吸引了无数玩家和投资者的目光。而在这其中...

软件开发 2025-01-01 阅读1 评论0