如何持久保存和加载LangChain对话记忆?

13
我正在创建一个对话,就像这样:
llm = ChatOpenAI(temperature=0, openai_api_key=OPENAI_API_KEY, model_name=OPENAI_DEFAULT_MODEL)
conversation = ConversationChain(llm=llm, memory=ConversationBufferMemory())

但是我真正想要的是能够保存和加载那个ConversationBufferMemory(),以便在不同的会话之间保持持久化。似乎没有明显的教程可以做到这一点,但我注意到了"Pydantic",所以我尝试了以下方法:
saved_dict = conversation.memory.chat_memory.dict()
cm = ChatMessageHistory(**saved_dict) # or cm = ChatMessageHistory.parse_obj(saved_dict)

但这个失败了:
ValidationError: 6 validation errors for ChatMessageHistory
messages -> 0
  Can't instantiate abstract class BaseMessage with abstract method type (type=type_error)

有什么想法吗?我希望能够提供任何指南、存储库、参考资料等的链接。

1
我看到的问题是dict()输出不包括类名,因此尝试重新加载它意味着它无法确定它是HumanMessage还是AIMessage,因此它只使用BaseMessage并失败。 - Neil C. Obremski
conversation.memory.chat_memory.json() 包含类名吗? - undefined
顺便说一句,这似乎是一种特定于Langchain的模型序列化实现。(选择使用Pickling可能是最佳方法。) - undefined
4个回答

9

我决定不再浪费时间处理LangChain/Pydantic的序列化问题,而是选择直接使用Pickle整个内容,这样做效果很好:

pickled_str = pickle.dumps(conversation.memory)
conversation2 = ConversationChain(llm=llm, memory=pickle.loads(pickled_str)

谢谢您的提示。在交互式Python shell中它运行得很好,但是当我将命令保存到.py文件并运行时,就会没有这样的运气。文件已经保存了,但只有内存格式,没有聊天历史记录。agent_chain = initialize_agent(tools, llm, agent="conversational-react-description", memory=memory)print(agent_chain.run(input='我有多少辆车?'))filesv = open('Chat_mem_001.pkl', 'wb')pickle.dump(agent_chain.memory, filesv)filesv.close().... 有任何想法为什么在shell中运行良好但不在.py文件中运行? - Shane

6

我刚刚做了类似的事情,希望这会有所帮助。在高层次上:

  1. 使用ConversationBufferMemory作为传递给链初始化的内存
llm = ChatOpenAI(temperature=0, model_name='gpt-3.5-turbo-0301')
original_chain = ConversationChain(
    llm=llm,
    verbose=True,
    memory=ConversationBufferMemory()
)
original_chain.run('what do you know about Python in less than 10 words')

从内存中提取消息,形式为List[langchain.schema.HumanMessage|AIMessage](不可序列化)。
extracted_messages = original_chain.memory.chat_memory.messages

将提取的消息转换为可序列化的本地Python对象。
ingest_to_db = messages_to_dict(extracted_messages)
  1. 执行数据库操作,以写入和读取您选择的数据库,我将使用json.dumpsjson.loads进行说明。
retrieve_from_db = json.loads(json.dumps(ingest_to_db))

将检索到的序列化对象转换回List [langchain.schema.HumanMessage | AIMessage]
retrieved_messages = messages_from_dict(retrieve_from_db)

从消息中构建ChatMessageHistory
retrieved_chat_history = ChatMessageHistory(messages=retrieved_messages)

ChatMessageHistory构建ConversationBufferMemory
retrieved_memory = ConversationBufferMemory(chat_memory=retrieved_chat_history)

将内存传递回新初始化的链。
reloaded_chain = ConversationChain(
    llm=llm,
    verbose=True,
    memory=retrieved_memory
)

您可以在 GitHub链接 查找完整的代码片段。


请您看一下这个链接:https://stackoverflow.com/questions/77055206/langchain-getting-file-pydantic-main-py-line-341-in-pydantic-main-basemodel?noredirect=1#comment135842626_77055206 - undefined

0
你试试 retrieve_from_db = json.loads(json.dumps(db_chain.memory.to_json()))

你的回答可以通过提供更多的支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的回答是否正确。你可以在帮助中心找到更多关于如何撰写好回答的信息。 - undefined

0
如果你构建了一个全栈应用程序,并且想要保存用户的聊天记录,你可以采用不同的方法:
1- 你可以为每个用户创建一个聊天缓冲区,并将其保存在服务器上。但正如其名称所示,这是存储在内存中的,如果你的服务器实例重新启动,你将丢失所有保存的数据。因此,这不是真正的持久性解决方案。
2- 真正的解决方案是将所有的聊天记录保存在数据库中。当用户登录并导航到其聊天页面时,它可以通过聊天ID检索保存的历史记录。由于你的应用程序正在与“open ai api”进行聊天,你已经设置了一个链条,这个链条需要消息历史记录。因此,一旦从数据库中检索到聊天历史记录,你应该用这个聊天历史记录填充聊天链条内存。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接