跳至内容

内存类型

LangMem 提供三种类型的内存来帮助你的聊天机器人回忆关于用户和对话的重要信息:用户状态、语义记忆和追加式状态。每种类型都在结构和灵活性之间取得了不同的平衡。

用户状态

用户状态是一个结构化的配置文件,LangMem 为每个用户维护。它非常适合跟踪符合预定义模式的关键用户属性。

如何定义

提供一个或多个结构化模式,表示你的助手应该了解用户的属性。

from pydantic import BaseModel, Field
from langmem import Client

class UserProfile(BaseModel):
   name: str = Field(description="The user's name")
   age: int = Field(description="The user's age")
   interests: List[str] = Field(description="The user's interests")
   relationships: Dict[str, str] = Field(
       description="The user's friends, family, pets,and other relationships."
   )
   ai_instructions: List[str] = Field(
       description="Prompt instructions that you as the AI assistant"
       " should always retain in subsequent conversations."
   )

client = Client()
memory_function = await client.create_memory_function(
   UserProfile,
   target_type="user_state",
   custom_instructions="Remember that this schema must be useful for prompt engineering an AI assistant."
)

查询

使用用户 ID 和模式 ID 对用户的状态进行 GET 调用。LangMem 会根据你的模式返回最新的对象,准备包含在你的系统提示中。

直接调用

state = client.get_user_memory(user_id, memory_function_id=memory_function["id"])

组合查询

memory_response = client.query_user_memory(
    user_id, text="Foo", states_to_return=[memory_function["id"]],
)
state = memory_response["state"][0]

管理

每当发布消息时,LangMem 会自动处理新信息并确定要修改当前用户状态的哪些内容(如果有)。这主要通过函数调用完成。

语义记忆

语义记忆是一个非结构化的内存,从对话中生成知识三元组。它通过让 LangMem 确定哪些信息值得记忆,提供最大的灵活性。

如何定义

无需配置!这种内存会自动表示为知识三元组。

查询

发送查询文本(表示上下文、最近的对话轮次等)。LangMem 返回一个按排名排列的非结构化内存列表,例如“用户 X 喜歡早上喝咖啡”或“用户 X 有个兄弟叫 Zihan”。结果根据语义相关性、重要性和最近程度进行排名。你可以选择控制每个因素的权重。

memory_response = client.query_user_memory(user_id, text="Foo")
state = [mem["text"] for mem in memory_response["memories"]]

自定义如何权衡内存强度的不同方面。

memory_response = client.query_user_memory(
    user_id, 
    text="Foo",
    weights={
        "recency": 1.0,
        "importance": 0,
        "relevance": 0,
    }
)

管理

当发布消息时,LangMem 会提取重要的信息和其他内存并自动存储。

追加式状态

追加式状态是用户状态和语义记忆之间的混合体。它允许你自定义内存模式,同时仍然可以根据相关性和最近程度检索信息。

如何定义

提供一个或多个结构化模式,表示你的助手应该从对话中提取和保留的见解。

class UserPreference(BaseModel):
   preference: str = Field(description="The preference.")
   why: str = Field(description="Why the user prefers this.")
   context: str = Field(description="The context in which this prefernce is appropriate")
   source_comment: str = Field(description="The raw user utterance where you identified this preference.")

client = Client()
memory_function = await client.create_memory_function(
   UserPreference,
   target_type="user_append_state",
   custom_instructions="Extract as many preferences from the conversation as you are able."
)

查询

发送查询文本,并可以选择一个模式子集。LangMem 会返回一个按排名排列的内存对象列表,基于语义相似性和最近程度。如果指定了模式,则只返回那些类型的内存对象。

管理

每当发布消息时,LangMem 会提取任何相关的内存对象。这些对象将附加到该模式 ID 的用户内存中。

线程摘要

除了用户特定的内存,LangMem 还可以生成整个对话线程的摘要。你可以定义一个自定义模式来填充每个线程。这种类型要包含的常见字段包括

  • 标题:对话的独特标题
  • 摘要:交互的高级概述
  • 主题:对话中讨论的关键主题
  • 参与者:参与对话的用户
  • 行动项:(如果在工作环境中使用)

线程摘要在发布消息时会自动生成,可以通过 API 检索,以帮助组织和理解对话历史。

如何定义

from pydantic import BaseModel, Field
from langmem import Clientl

class ThreadSummary(BaseModel):
   titles: str = Field(description="Concise 2-5 word title for the conversation.")
   summary: str
   topics: List[str] = Field(description="Topics discussed")
   questions: List[str] = Field(descriptin="Any questions you'd like to follow up on next time.")

thread_memory_function = await client.create_memory_function(
   ThreadSummary,
   target_type="thread_summary",
   custom_instructions="Summarize this thread."
)

查询

thread_memory = client.get_thread_memory(thread_id, memory_function_id=thread_memory_function["id"])

作为组合查询的一部分

memory_response = client.query_user_memory(
    user_id, 
    # Query semantic memory
    text="Foo", 
    # Also include thread summaries from this function
    thread_summaries=[thread_memory_function["id"]]
    # Include up to the three most recent summaries for each thread_summary_function
    thread_summaries_k=3
)
thread_summaries = memory_response["thread_summaries"][thread_memory_function["id"]]

选择合适的内存类型

1. 用户状态:

  1. 如果你想将 langmem 用于“用户分析”,这比其他类型更有用 → 你拥有一个代表所有用户相关特征的单一真实来源
  2. 它最容易符合你应用程序中的内存“面板”,你可以在那里让最终用户手动更新聊天机器人“知道”的关于他们的信息
  3. 它也是最简单的注入到你的助手中的,因为你不需要考虑如何查询内存

2. 追加式状态(事件)

这些内存类型提供了控制和透明度的连续性。

  1. 你可以定义哪些内容是突出的

    • 这意味着,如果某些特定领域的知识很重要,LangMem 更有可能以适当的格式提取它,而不是如果你只使用非结构化内存。
  2. 你可以查询与你的上下文相关的信息

    • 这可能比拥有一个巨大的用户状态更容易。你可以将它视为一个版本化的用户状态表,你可以在任何时候查询所有版本。
    • 要考虑的一个技巧是在模式中包含上下文信息(例如导致发现信息的源句子或上下文),这可能有助于在下游回忆和合并知识(你的助手更容易知道上下文是否/何时相关)
    • 助手永远不会“忘记”

    • 我们从未在模式中明确删除字段(尽管检索机制会随着时间的推移降低对旧内存的权重,你可以手动删除内容),所以你不必担心系统会自动覆盖用户状态

3. 非结构化

  1. 如果你不想将系统限制在特定的内存内容,请使用它
  2. 如果你的领域非常开放式,并且你想要让内存服务灵活地确定它想要存储的其他内存,这很有用
  3. 它通常是最简洁的,因为每个“内存”都是关于用户的简短断言/陈述