在构建大型语言模型(LLM)应用时,记忆功能扮演着至关重要的角色。它使得AI能够保持上下文连贯性,提供更加智能和个性化的响应。本文将深入探讨LangChain框架中的记忆组件,详细分析其运行流程和源码实现,为开发者提供全面的技术洞察。
1. LangChain-ChatMessageHistory组件解析
1.1 BaseChatMessageHistory:记忆管理的基石
在LangChain中,记忆功能的实现主要涉及两个核心问题:
存储的历史信息是什么?
如何检索与处理历史信息?
为了解决这些问题,LangChain封装了一个管理历史信息的基类——BaseChatMessageHistory。这是一个抽象类,用于管理历史消息,包括添加消息、清空历史消息、查看历史消息列表和查看历史消息文本等功能。
所有扩展的消息历史组件都继承自BaseChatMessageHistory,包括自定义消息历史组件。其中,InMemoryChatMessageHistory是langchain_core包中内置的对话消息历史类,可以将对话消息存储到临时内存中。其他第三方集成的聊天消息历史组件则通过langchain_community包进行导入。
1.2 实现记忆功能:以FileChatMessageHistory为例
FileChatMessageHistory是一个将对话历史存储到本地文件的组件。我们可以结合原生的OpenAI SDK,使用这个记忆组件在命令行界面实现带有记忆功能的对话。以下是一个具体的实现示例:
1 import dotenv 2 from langchain_community.chat_message_histories import FileChatMessageHistory 3 from langchain_core.messages import HumanMessage, AIMessage 4 from openai import OpenAI 5 6 dotenv.load_dotenv() 7 8 # 1.创建客户端&记忆 9 client = OpenAI() 10 chat_history = FileChatMessageHistory("./memory.txt") 11 12 # 2.循环对话 13 while True: 14 # 3.获取用户的输入 15 query = input("Human: ") 16 17 # 4.检测用户是否退出对话 18 if query == "q": 19 exit(0) 20 21 # 5.发起聊天对话 22 print("AI: ", flush=True, end="") 23 system_prompt = ( 24 "你是由OpenAI开发的ChatGPT聊天机器人,可以根据对应的上下文回复用户信息,上下文里存放的是人类和您交互。\n\n" 25 f"<context>\n{chat_history}\n</context>\n\n" 26 ) 27 response = client.chat.completions.create( 28 model='gpt-3.5-turbo-16k', 29 messages=[ 30 {"role": "system", "content": system_prompt}, 31 {"role": "user", "content": query} 32 ], 33 stream=True, 34 ) 35 ai_content = "" 36 for chunk in response: 37 content = chunk.choices[0].delta.content 38 if content is None: 39 break 40 ai_content += content 41 print(content, flush=True, end="") 42 chat_history.add_messages([HumanMessage(query), AIMessage(ai_content)]) 43 print("")
这段代码实现了一个简单的命令行聊天界面,它使用FileChatMessageHistory来存储对话历史。即使在关闭对话后,下次运行代码时,仍然可以读取到之前的对话内容,实现了持久化的记忆功能。
2. Memory组件运行流程及分类
2.1 Memory组件概述
LangChain中的Memory组件基于BaseMemory基类构建。这个基类封装了许多基础方法,如memory_variables、load_memory_variables、save_context、clear等。
从BaseMemory衍生出两个主要子类:
SimpleMemory:当LLM应用不需要记忆功能,但又不想更改代码结构时,可以使用这个组件。它实现了记忆组件的相关方法,但不存储任何记忆。
BaseChatMemory:这是LangChain中内置的其他记忆组件的基类,专门针对对话历史进行了封装,适用于聊天模型对话场景。
2.2 BaseChatMemory运行流程及源码分析
BaseChatMemory组件中的关键属性和方法包括:
chat_memory:管理记忆中的历史消息对话。
output_key:定义AI内容输出键。
input_key:定义Human内容输入键。
return_messages:决定load_memory_variables函数是否返回消息列表。
save_context:存储上下文到记忆组件中。
load_memory_variables:生成加载到链的记忆字典信息。
clear:清除记忆中的对话消息历史。
以下是BaseChatMemory的核心源码及注释:
1 class BaseChatMemory(BaseMemory, ABC): 2 chat_memory: BaseChatMessageHistory = Field( 3 default_factory=InMemoryChatMessageHistory 4 ) 5 output_key: Optional[str] = None 6 input_key: Optional[str] = None 7 return_messages: bool = False 8 9 def _get_input_output( 10 self, inputs: Dict[str, Any], outputs: Dict[str, str] 11 ) -> Tuple[str, str]: 12 """从输入和输出字典中提取对应的字符串(人类提问、AI输出)""" 13 # ... (省略具体实现) 14 15 def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None: 16 """保存对话上下文到记忆缓冲区""" 17 input_str, output_str = self._get_input_output(inputs, outputs) 18 self.chat_memory.add_messages( 19 [HumanMessage(content=input_str), AIMessage(content=output_str)] 20 ) 21 22 async def asave_context( 23 self, inputs: Dict[str, Any], outputs: Dict[str, str] 24 ) -> None: 25 """异步保存对话上下文到记忆缓冲区""" 26 # ... (省略具体实现) 27 28 def clear(self) -> None: 29 """清除所有记忆""" 30 self.chat_memory.clear() 31 32 async def aclear(self) -> None: 33 """异步清除所有记忆""" 34 await self.chat_memory.aclear()
结论
LangChain的记忆组件为开发者提供了强大而灵活的工具,用于管理和利用对话历史。通过深入理解BaseChatMessageHistory和BaseChatMemory的实现,我们可以更好地利用这些组件来构建具有上下文感知能力的AI应用。
无论是简单的文件存储还是复杂的分布式记忆系统,LangChain的记忆组件都能够满足各种应用场景的需求。通过合理使用这些组件,开发者可以显著提升AI应用的交互质量和智能水平。
在实际应用中,我们可以根据具体需求选择合适的记忆组件,或者基于现有组件进行自定义扩展。深入理解这些组件的工作原理,将有助于我们更好地设计和优化AI系统的记忆管理策略
标签:chat,LangChain,content,源码,记忆,str,组件,对话 From: https://www.cnblogs.com/muzinan110/p/18539573