LangChain-06-Memory(记忆)
LangChain之Memory记忆目录Memory概述与上下文管理ConversationBufferMemoryConversationBufferWindowMemoryConversationSummaryMemoryConversationSummaryBufferMemoryConversationTokenBufferMemoryConversationKGMemoryVectorStoreRetrieverMemoryMemory选择指南最佳实践与注意事项Memory概述与上下文管理什么是Memory在LangChain中Memory记忆组件负责在对话或交互过程中存储、检索和管理信息。它使AI能够记住之前的交互内容从而实现更连贯、更有上下文感知能力的对话。为什么需要Memory大型语言模型LLM本身是无状态的它们不会自动记住之前的对话内容。每次请求都是独立的模型无法访问之前的交互历史。Memory组件解决了这个问题通过维护对话历史存储用户和AI之间的交互记录提供上下文将相关历史信息注入到当前提示中实现连续对话使AI能够引用之前讨论过的内容个性化体验记住用户偏好和特定信息Memory的核心功能存储机制如何保存对话历史检索策略如何从历史中提取相关信息格式化输出如何将记忆内容整合到提示中容量管理如何处理长对话和限制记忆大小Memory的工作原理LangChain的Memory组件通常通过以下方式工作对话后保存每次交互完成后将对话内容存储起来提示前加载在生成新响应前从记忆中检索相关内容上下文注入将检索到的内容整合到当前提示中格式化处理将记忆内容转换为模型可理解的格式ConversationBufferMemory概述ConversationBufferMemory是最简单的Memory类型它将整个对话历史以原始形式存储在缓冲区中。它保存所有交互的完整记录并在需要时将它们提供给模型。特点简单直接无需复杂的处理逻辑完整记录保存所有对话内容不进行任何筛选或压缩线性增长记忆大小随对话长度线性增加精确上下文提供完整的对话历史实现方式fromlangchain.memoryimportConversationBufferMemoryfromlangchain.llmsimportOpenAIfromlangchain.chainsimportConversationChain# 创建记忆实例memoryConversationBufferMemory()# 创建对话链llmOpenAI(temperature0)conversationConversationChain(llmllm,memorymemory,verboseTrue)# 进行对话conversation.predict(input你好我想了解人工智能的发展历史。)conversation.predict(input能详细介绍一下深度学习吗)# 查看记忆内容print(memory.buffer)内部结构ConversationBufferMemory内部维护两个主要组件chat_memory存储消息历史的对象buffer格式化后的对话字符串适用场景短期对话适合不需要长期记忆的应用简单应用不需要复杂记忆管理的场景原型开发快速构建和测试对话系统完整上下文需要完整对话历史的场景限制与缺点内存消耗随着对话增长内存使用量线性增加Token限制可能超出模型的上下文窗口限制处理效率长对话会导致处理时间增加信息冗余可能包含大量不相关的旧信息ConversationBufferWindowMemory概述ConversationBufferWindowMemory是ConversationBufferMemory的变体它只保留最近的K轮对话而不是整个对话历史。这通过滑动窗口机制控制记忆大小。特点固定窗口只保留最近的指定数量的交互内存可控通过窗口大小限制内存使用上下文新鲜专注于最近的对话内容自动淘汰自动移除超出窗口的旧对话实现方式fromlangchain.memoryimportConversationBufferWindowMemoryfromlangchain.llmsimportOpenAIfromlangchain.chainsimportConversationChain# 创建窗口记忆实例保留最近3轮对话memoryConversationBufferWindowMemory(k3)# 创建对话链llmOpenAI(temperature0)conversationConversationChain(llmllm,memorymemory,verboseTrue)# 进行多轮对话conversation.predict(input你好我想了解机器学习。)conversation.predict(input什么是监督学习)conversation.predict(input能解释一下决策树吗)conversation.predict(input随机森林和决策树有什么区别)conversation.predict(input深度学习和机器学习的关系是什么)# 查看记忆内容只有最近3轮print(memory.buffer)窗口机制窗口记忆的工作原理初始化设置窗口大小K添加新对话将新交互添加到记忆中检查容量如果超过K轮移除最早的交互保持最新始终保留最近的K轮对话适用场景长期对话需要处理长对话但限制上下文大小资源受限内存或Token使用受限的环境关注近期更关注最近对话内容的应用流式对话连续对话但不需要完整历史的场景参数配置k窗口大小保留的对话轮数return_messages是否返回消息对象而非字符串限制与缺点信息丢失超出窗口的对话内容永久丢失上下文断裂可能丢失重要的长期上下文窗口选择选择合适的窗口大小可能需要实验话题跳跃可能无法理解跨越窗口的话题关联ConversationSummaryMemory概述ConversationSummaryMemory使用LLM来总结对话历史而不是存储原始对话内容。它定期生成对话摘要并将摘要作为记忆内容从而大大减少Token使用量。特点摘要压缩将对话内容压缩为摘要形式Token高效显著减少Token使用量动态更新随着对话进行更新摘要语义保持保留对话的核心语义信息实现方式fromlangchain.memoryimportConversationSummaryMemoryfromlangchain.llmsimportOpenAIfromlangchain.chainsimportConversationChain# 创建摘要记忆实例memoryConversationSummaryMemory(llmOpenAI(temperature0))# 创建对话链conversationConversationChain(llmOpenAI(temperature0),memorymemory,verboseTrue)# 进行多轮对话conversation.predict(input我想了解量子计算的基本原理。)conversation.predict(input量子比特和经典比特有什么区别)conversation.predict(input量子纠缠是如何工作的)# 查看摘要内容print(memory.buffer)摘要生成机制摘要记忆的工作流程初始摘要开始时为空或使用初始提示新对话添加将新交互添加到当前摘要中摘要更新使用LLM重新生成包含新内容的摘要摘要存储保存更新后的摘要作为记忆摘要提示工程摘要质量依赖于提示设计fromlangchain.promptsimportPromptTemplate# 自定义摘要提示summary_promptPromptTemplate(input_variables[summary,new_lines],templateProgressively summarize the following lines of conversation.\n\nCurrent summary:\n{summary}\n\nNew lines of conversation:\n{new_lines}\n\nNew summary:)memoryConversationSummaryMemory(llmOpenAI(temperature0),promptsummary_prompt)适用场景长对话需要处理大量交互但受Token限制主题持久对话围绕特定主题展开信息压缩需要保留核心信息但减少存储成本敏感希望减少API调用成本的应用限制与缺点信息丢失摘要可能丢失细节和微妙之处摘要质量依赖于LLM的摘要能力更新成本每次更新需要调用LLM累积误差多次摘要可能导致信息失真ConversationSummaryBufferMemory概述ConversationSummaryBufferMemory结合了摘要记忆和缓冲区记忆的优点。它保留最近的对话原始内容同时对较早的对话进行摘要实现了平衡的记忆管理。特点混合策略结合摘要和缓冲区两种方法双重存储近期对话保持原始形式早期对话存储为摘要智能切换根据对话轮数决定何时开始摘要灵活平衡在详细上下文和Token效率间取得平衡实现方式fromlangchain.memoryimportConversationSummaryBufferMemoryfromlangchain.llmsimportOpenAIfromlangchain.chainsimportConversationChain# 创建摘要缓冲区记忆实例# max_token_limit: 触发摘要的最大Token数memoryConversationSummaryBufferMemory(llmOpenAI(temperature0),max_token_limit100)# 创建对话链conversationConversationChain(llmOpenAI(temperature0),memorymemory,verboseTrue)# 进行多轮对话conversation.predict(input我想了解区块链技术。)conversation.predict(input什么是去中心化)conversation.predict(input智能合约是如何工作的)conversation.predict(input区块链有哪些实际应用)# 查看记忆内容print(Buffer:,memory.chat_memory.messages)print(Summary:,memory.summary)工作机制摘要缓冲区记忆的工作流程初始阶段对话开始时所有内容存储在缓冲区中容量监控监控缓冲区大小Token数摘要触发当超过阈值时将部分内容摘要化内容转移将摘要内容移至摘要部分保留最新内容在缓冲区动态平衡根据需要重复此过程参数配置max_token_limit触发摘要的最大Token数llm用于生成摘要的语言模型prompt自定义摘要提示模板适用场景中等长度对话比简单缓冲区长但不需要完整摘要平衡需求既需要近期细节又需要长期上下文资源优化希望在质量和效率间取得平衡动态对话对话长度不确定的应用限制与缺点复杂度增加比单一策略更复杂阈值选择需要合理设置Token阈值切换点摘要和缓冲区的切换可能不自然管理开销需要管理两种不同类型的内容ConversationTokenBufferMemory概述ConversationTokenBufferMemory基于Token数量管理对话历史而不是基于交互轮数。它保留足够的内容以保持在指定的Token限制内确保不会超出模型的上下文窗口。特点Token精确基于Token数量而非交互次数自适应裁剪根据Token限制智能裁剪内容上下文完整尽可能保留完整的对话上下文模型兼容确保记忆内容符合模型限制实现方式fromlangchain.memoryimportConversationTokenBufferMemoryfromlangchain.llmsimportOpenAIfromlangchain.chainsimportConversationChain# 创建基于Token的记忆实例memoryConversationTokenBufferMemory(llmOpenAI(temperature0),max_token_limit200# 最大Token数)# 创建对话链conversationConversationChain(llmOpenAI(temperature0),memorymemory,verboseTrue)# 进行多轮对话conversation.predict(input我想了解可再生能源技术。)conversation.predict(input太阳能和风能有什么区别)conversation.predict(input氢能源的发展前景如何)# 查看记忆内容print(memory.buffer)Token管理机制Token缓冲区记忆的工作原理Token计算计算当前对话内容的Token数量容量检查比较当前Token数与限制内容裁剪如果超限从最早的内容开始裁剪动态平衡确保总Token数不超过限制完整性保持尽可能保持对话的连续性Token计算方式fromlangchain.memoryimportConversationTokenBufferMemoryfromlangchain.llmsimportOpenAI# 使用不同的Token计算方法memoryConversationTokenBufferMemory(llmOpenAI(temperature0),max_token_limit200,# 可选自定义Token计数器# tokenizerNone # 使用默认的LLM tokenizer)# 检查当前Token使用量token_countmemory.llm.get_num_tokens(memory.buffer)print(fCurrent token count:{token_count})适用场景严格限制需要精确控制Token使用的场景多模型支持使用不同上下文大小的模型API优化希望最大化利用API Token限制成本控制需要严格控制API调用成本限制与缺点对话断裂裁剪可能导致对话上下文不完整Token计算Token计算可能增加处理开销内容丢失可能丢失重要的早期信息模型依赖Token计算依赖于特定的tokenizerConversationKGMemory概述ConversationKGMemoryKnowledge Graph Memory使用知识图谱来表示和存储对话中的实体及其关系。它从对话中提取实体和关系构建知识图谱并基于此提供上下文。特点结构化表示将对话内容转换为结构化知识图谱实体关系识别和存储实体间的语义关系上下文推理基于图谱进行推理和关联知识积累随着对话不断丰富知识图谱实现方式fromlangchain.memoryimportConversationKGMemoryfromlangchain.llmsimportOpenAIfromlangchain.chainsimportConversationChain# 创建知识图谱记忆实例memoryConversationKGMemory(llmOpenAI(temperature0))# 创建对话链conversationConversationChain(llmOpenAI(temperature0),memorymemory,verboseTrue)# 进行包含实体和关系的对话conversation.predict(input张三是AI公司的数据科学家。)conversation.predict(input他负责开发机器学习模型。)conversation.predict(input他的团队有5名工程师。)# 查看知识图谱内容print(Knowledge Graph:,memory.knowledge_graph)# 获取当前上下文print(Current entities:,memory.get_current_entities())知识图谱构建知识图谱记忆的工作流程实体识别从对话中识别关键实体关系提取分析实体间的关系图谱构建将实体和关系添加到知识图谱中上下文生成基于图谱生成对话上下文图谱更新随着新对话不断更新图谱实体和关系提取fromlangchain.promptsimportPromptTemplate# 自定义实体和关系提取提示entity_extraction_promptPromptTemplate(input_variables[chat_history,input],templateExtract entities and their relationships from the following conversation. Conversation History: {chat_history} New Input: {input} Extract entities and relationships in format: (entity1)-[relation]-(entity2) )memoryConversationKGMemory(llmOpenAI(temperature0),promptentity_extraction_prompt)适用场景关系密集对话包含大量实体和关系的场景知识积累需要长期积累和关联知识的应用复杂推理需要理解实体间复杂关系的任务专业领域特定领域的专业对话系统限制与缺点提取准确性依赖LLM的实体和关系提取能力图谱复杂度可能产生复杂且难以管理的图谱上下文生成从图谱生成自然上下文可能不自然计算开销图谱构建和查询可能增加计算成本VectorStoreRetrieverMemory概述VectorStoreRetrieverMemory使用向量存储和检索机制来管理对话记忆。它将对话内容转换为向量存储在向量数据库中并基于语义相似度检索相关内容。特点语义检索基于语义相似度而非时间顺序检索向量存储使用高效的向量数据库存储对话内容可扩展性能够处理大量对话历史灵活检索支持多种检索策略和参数实现方式fromlangchain.memoryimportVectorStoreRetrieverMemoryfromlangchain.llmsimportOpenAIfromlangchain.embeddingsimportOpenAIEmbeddingsfromlangchain.vectorstoresimportChromafromlangchain.chainsimportConversationChain# 创建向量存储embedding_modelOpenAIEmbeddings()vectorstoreChroma(embedding_functionembedding_model)# 创建检索器retrievervectorstore.as_retriever(search_kwargs{k:2})# 创建向量存储记忆memoryVectorStoreRetrieverMemory(retrieverretriever,# 当没有检索到相关内容时返回的消息memory_keyrelevant_history,input_keyinput)# 创建对话链conversationConversationChain(llmOpenAI(temperature0),memorymemory,verboseTrue)# 进行多轮对话conversation.predict(input我想了解机器学习中的过拟合问题。)conversation.predict(input如何防止过拟合)conversation.predict(input什么是正则化)# 测试记忆检索print(Retrieved context:,memory.load_memory_variables({input:过拟合}))向量化与检索机制向量存储记忆的工作流程内容向量化将对话内容转换为向量表示向量存储将向量存储在向量数据库中相似度检索基于当前输入检索相似的历史内容上下文组装将检索到的内容组装为上下文动态更新新对话内容自动添加到向量存储检索策略配置fromlangchain.memoryimportVectorStoreRetrieverMemoryfromlangchain.vectorstoresimportFAISS# 使用不同的向量存储和检索策略vectorstoreFAISS.from_texts([示例文本1,示例文本2],embedding_model)# 配置检索参数retrievervectorstore.as_retriever(search_typesimilarity_score_threshold,search_kwargs{k:5,score_threshold:0.5})memoryVectorStoreRetrieverMemory(retrieverretriever,# 自定义检索后的处理return_docsTrue)适用场景长对话历史需要处理大量历史对话的场景语义关联需要基于语义而非时间检索内容多话题对话对话涉及多个不同话题的情况知识密集需要从大量历史中检索特定知识限制与缺点上下文断裂可能丢失对话的时间顺序和连续性检索质量依赖向量化和相似度计算的质量存储需求需要额外的向量存储资源计算成本向量化和检索可能增加计算开销Memory选择指南选择考虑因素选择合适的Memory类型需要考虑以下因素对话长度短对话ConversationBufferMemory中等长度ConversationBufferWindowMemory或ConversationSummaryBufferMemory长对话ConversationSummaryMemory或VectorStoreRetrieverMemory上下文需求完整上下文ConversationBufferMemory近期上下文ConversationBufferWindowMemory语义上下文VectorStoreRetrieverMemory关系上下文ConversationKGMemory资源限制内存限制ConversationBufferWindowMemory或ConversationTokenBufferMemoryToken限制ConversationSummaryMemory或ConversationTokenBufferMemory计算资源避免VectorStoreRetrieverMemory或ConversationKGMemory应用场景简单聊天ConversationBufferMemory客服系统ConversationSummaryBufferMemory知识问答VectorStoreRetrieverMemory专业咨询ConversationKGMemory决策矩阵场景推荐Memory替代方案简单对话短期交互ConversationBufferMemoryConversationBufferWindowMemory长期对话资源受限ConversationSummaryMemoryConversationTokenBufferMemory需要近期细节和长期摘要ConversationSummaryBufferMemory自定义混合方案多话题语义检索VectorStoreRetrieverMemoryConversationKGMemory实体关系密集ConversationKGMemoryVectorStoreRetrieverMemory严格Token限制ConversationTokenBufferMemoryConversationSummaryMemory组合策略在某些复杂场景中可以组合使用多种Memory类型fromlangchain.memoryimportCombinedMemoryfromlangchain.memoryimportConversationBufferMemoryfromlangchain.memoryimportConversationSummaryMemory# 创建组合记忆conv_memoryConversationBufferMemory(memory_keychat_history)summary_memoryConversationSummaryMemory(llmOpenAI(),memory_keysummary)# 组合记忆combined_memoryCombinedMemory(memories[conv_memory,summary_memory],input_keyinput)# 在链中使用组合记忆conversationConversationChain(llmOpenAI(temperature0),memorycombined_memory,verboseTrue)最佳实践与注意事项性能优化定期清理# 定期清理过期记忆iflen(memory.chat_memory.messages)100:memory.chat_memory.messagesmemory.chat_memory.messages[-50:]异步处理# 使用异步记忆更新fromlangchain.memoryimportAsyncMemoryasyncdefupdate_memory_async(memory,input,output):awaitmemory.save_context({input:input},{output:output})批量处理# 批量保存对话历史defsave_conversation_batch(memory,conversations):forinput_text,output_textinconversations:memory.save_context({input:input_text},{output:output_text})错误处理记忆容量管理# 防止记忆溢出try:memory.save_context({input:user_input},{output:ai_response})exceptExceptionase:# 处理记忆溢出错误print(fMemory error:{e})# 清理或重置记忆memory.clear()检索失败处理# 处理检索失败try:contextmemory.load_memory_variables({input:query})exceptExceptionase:print(fRetrieval error:{e})context{history:无法检索相关历史记录}安全与隐私敏感信息过滤# 过滤敏感信息deffilter_sensitive_info(text):# 实现敏感信息过滤逻辑returnfiltered_text# 在保存前过滤memory.save_context({input:filter_sensitive_info(user_input)},{output:filter_sensitive_info(ai_response)})记忆加密# 加密敏感记忆内容fromcryptography.fernetimportFernetclassEncryptedMemory(ConversationBufferMemory):def__init__(self,key,**kwargs):super().__init__(**kwargs)self.cipherFernet(key)defsave_context(self,inputs,outputs):# 加密后保存encrypted_inputs{k:self.cipher.encrypt(v.encode())fork,vininputs.items()}encrypted_outputs{k:self.cipher.encrypt(v.encode())fork,vinoutputs.items()}super().save_context(encrypted_inputs,encrypted_outputs)通过遵循这些最佳实践您可以构建更可靠、高效和安全的LangChain记忆系统为您的应用提供强大的上下文管理能力。