LangMem 帮助AIAgent随着时间的推移从交互中学习和适应。
它提供工具来从对话中提取重要信息,通过提示改进来优化代理行为,并维持长期记忆。
它提供了可与任何存储系统一起使用的功能原语以及与 LangGraph 存储层的本机集成。
这使您的代理能够不断改进、个性化他们的响应并在会话中保持一致的行为。
官方地址:
https://langchain-ai.github.io/langmem
主要特点¶
- 🧩可与任何存储系统配合使用的核心内存 API
- 🧠内存管理工具,代理可以使用它来记录和搜索“热路径”中的活动对话期间的信息
- ⚙️后台内存管理器,可自动提取、合并和更新代理知识
- ⚡与 LangGraph 的长期记忆存储原生集成,所有 LangGraph 平台部署中默认可用
在LangMem中,长期记忆分为以下三种类型。
- Semantic(语义记忆)
- Episodic(情节记忆)
- Procedural(过程记忆)
安装¶
注意Python要求3.11,亲测3.10有问题
pip install -U langmem
使用您最喜欢的 LLM 提供商的 API 密钥配置您的环境:
export ANTHROPIC_API_KEY="sk-..." # Or another supported LLM provider
增加了代码解释后的完整内容
# Import core components from langgraph.prebuilt import create_react_agent from langgraph.store.memory import InMemoryStore from langmem import create_manage_memory_tool, create_search_memory_tool # 功能:初始化一个 InMemoryStore 对象,作为内存中的向量数据库,用于存储和检索数据(此处为用户的记忆或偏好)。 # 关键组件: # InMemoryStore:可能是 LangGraph 或 Langmem 提供的类,用于在内存中存储向量数据。它是非持久化的(数据在程序终止后丢失),适合开发、测试或临时存储场景。 # index:配置向量索引的参数: # "dims": 1536:指定向量嵌入的维度为 1536。这是 OpenAI 的 text-embedding-3-small 模型生成的嵌入向量维度,表示每个存储的记忆会被转换为一个 1536 维的向量。 # "embed": "openai:text-embedding-3-small":指定使用的嵌入模型为 OpenAI 的 text-embedding-3-small。该模型将文本(如用户的输入“Remember that I prefer dark mode”)转换为向量,以便在存储和搜索时进行相似性比较。 # 工作原理: # 当用户输入文本时,InMemoryStore 会调用 OpenAI 的嵌入模型将文本转换为 1536 维向量。 # 这些向量存储在内存中,支持后续的向量搜索(如基于余弦相似度的查询)。 # 注意事项: # InMemoryStore 适合小规模或测试用途,因为数据不会持久化到磁盘。 # 确保 OpenAI API 密钥已配置,因为嵌入模型需要调用外部 API。 store = InMemoryStore( index={ "dims": 1536, "embed": "openai:text-embedding-3-small", } ) # 功能:创建一个 ReAct(Reasoning and Acting)代理,基于 Anthropic 的 Claude-3.5-Sonnet 模型,配备记忆管理和搜索工具,并连接到前面定义的 store。 # 关键组件: # create_react_agent:Langmem 或 LangGraph 提供的函数,用于创建 ReAct 代理。ReAct 是一种代理架构,结合了推理(Reasoning)和行动(Acting),使代理能够根据输入选择合适的工具并生成响应。 # "anthropic:claude-3-5-sonnet-latest":指定代理使用的语言模型为 Anthropic 的 Claude-3.5-Sonnet(最新版本)。Claude 是一个强大的对话模型,擅长理解上下文和生成自然语言响应。 # tools:代理配备的工具列表,用于扩展功能: # create_manage_memory_tool(namespace=("memories",)):创建一个工具,用于管理记忆(例如存储或更新)。namespace=("memories",) 表示记忆存储在一个名为“memories”的命名空间中,用于组织数据。 # create_search_memory_tool(namespace=("memories",)):创建一个工具,用于搜索存储的记忆。同样使用“memories”命名空间,允许代理通过向量相似性搜索查找相关记忆。 # store=store:将前面定义的 InMemoryStore 传递给代理,确保记忆工具使用该存储进行数据操作。 # 工作原理: # ReAct 代理的工作流程是: # 接收用户输入(如“Remember that I prefer dark mode”)。 # 通过推理决定是否调用工具(例如调用 manage_memory_tool 存储记忆)。 # 使用 Claude 模型生成自然语言响应或处理工具的输出。 # 记忆工具依赖 InMemoryStore 进行数据持久化,manage_memory_tool 负责写入数据,search_memory_tool 负责查询数据。 # 注意事项: # 确保 Anthropic API 已配置,因为 Claude 模型需要外部 API 调用。 # 命名空间“memories”用于隔离不同类型的数据,防止冲突。 agent = create_react_agent( "anthropic:claude-3-5-sonnet-latest", tools=[ # Memory tools use LangGraph's BaseStore for persistence (4) create_manage_memory_tool(namespace=("memories",)), create_search_memory_tool(namespace=("memories",)), ], store=store, ) # # 功能:通过Agent存储用户的偏好(“我喜欢暗色模式”)到 InMemoryStore 中。 # 输入结构: # agent.invoke:调用代理,处理输入消息并返回响应。 # {"messages": [...]}:输入是一个消息列表,符合对话模型的常见格式: # role: "user":表示消息来自用户。 # content: "Remember that I prefer dark mode.":用户的指令,要求代理记住偏好。 # 工作原理: # 代理接收输入后,Claude 模型解析消息内容,识别出“Remember”是一个存储指令。 # 代理调用 manage_memory_tool,将文本“Remember that I prefer dark mode.”转换为 1536 维向量(通过 openai:text-embedding-3-small)。 # 向量和相关元数据存储到 InMemoryStore 的“memories”命名空间中。 # 代理可能返回一个确认响应(代码未显示输出),例如“Got it, I’ve remembered that you prefer dark mode.” # 注意事项: # 存储的记忆可能包括原始文本、嵌入向量和元数据(如时间戳或用户 ID),具体取决于 manage_memory_tool 的实现。 # 如果 API 调用失败(例如网络问题或配额限制),存储可能失败。 agent.invoke( {"messages": [{"role": "user", "content": "Remember that I prefer dark mode."}]} ) # # 功能:通过代理查询用户的照明偏好,并打印代理的响应。 # 输入结构: # 类似于存储记忆,输入是一个消息列表: # content: "What are my lighting preferences?":用户询问存储的偏好。 # 工作原理: # 代理接收查询,Claude 模型解析问题,识别出需要检索与“lighting preferences”相关的记忆。 # 代理调用 search_memory_tool,将查询文本转换为向量(通过 openai:text-embedding-3-small)。 # search_memory_tool 在 InMemoryStore 的“memories”命名空间中执行向量搜索,找到与查询向量最相似的记忆(即“我喜欢暗色模式”)。 # Claude 模型根据搜索结果生成自然语言响应,例如“You prefer dark mode.” # 响应存储在 response["messages"] 中,[-1] 取最后一个消息(代理的回答)。 # 输出: # print(response["messages"][-1].content):打印代理的回答,预期输出类似“You prefer dark mode.” # 注意事项: # 搜索的准确性依赖于向量相似度。如果存储的记忆与查询不匹配(例如查询“color preferences”),可能返回空结果或不相关内容。 # 输出格式取决于 Claude 模型的生成逻辑,可能包含额外说明或格式化。 # Retrieve the stored memory response = agent.invoke( {"messages": [{"role": "user", "content": "What are my lighting preferences?"}]} ) print(response["messages"][-1].content) # Output: "You've told me that you prefer dark mode."
可能出现的错误: 1. AttributeError: module ‘typing’ has no attribute ‘NotRequired’
个人测试下来就是个坑。Python3.10就会出现这个问题,使用3.11 就没有这个问题。
但是官方文档没有任何明显位置确定这个版本要求。
2 尝试使用Qwen的嵌入模型
不行。只能用上述列表中的。
尝试用Azure的替换,最终我们使用Ollama代替了嵌入模型。但是由于使用到bind_tools的高级功能,Ollama本身还没有支持,我们LLMProvider还是使用Azure或者Grok了。
Paragoger衍生者AI训练营