Skip to main content

如何创建自定义的Memory类

虽然LangChain中有几种预定义的内存类型,但很可能您希望添加自己的内存类型,以便为您的应用程序提供最佳性能。本文档介绍了如何实现这一点。

在本文档中,我们将向ConversationChain添加一个自定义的内存类型。为了添加自定义的内存类,我们需要导入基本的内存类并对其进行子类化。

from langchain import OpenAI, ConversationChain  
from langchain.schema import BaseMemory
from pydantic import BaseModel
from typing import List, Dict, Any

API参考:

在这个例子中,我们将编写一个自定义的内存类,它使用spacy来提取实体并将有关它们的信息保存在一个简单的哈希表中。然后,在对话过程中,我们将查看输入文本,提取任何实体,并将有关它们的任何信息放入上下文中。

  • 请注意,这个实现非常简单且脆弱,可能在实际生产环境中没有用处。它的目的是展示您可以添加自定义的内存实现。

为此,我们需要安装spacy。

# !pip install spacy  
# !python -m spacy download en_core_web_lg
import spacy  

nlp = spacy.load("en_core_web_lg")
class SpacyEntityMemory(BaseMemory, BaseModel):  
"""用于存储实体信息的内存类。"""

# 定义用于存储实体信息的字典。
entities: dict = {}
# 定义用于将实体信息传递到提示中的键。
memory_key: str = "entities"

def clear(self):
self.entities = {}

@property
def memory_variables(self) -> List[str]:
"""定义我们要提供给提示的变量。"""
return [self.memory_key]

def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, str]:
"""加载内存变量,本例中为实体键。"""
# 获取输入文本并通过spacy运行
doc = nlp(inputs[list(inputs.keys())[0]])
# 提取已知的实体信息,如果存在的话。
entities = [
self.entities[str(ent)] for ent in doc.ents if str(ent) in self.entities
]
# 返回合并的实体信息以放入上下文中。
return {self.memory_key: "\n".join(entities)}

def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:
"""将此对话的上下文保存到缓冲区中。"""
# 获取输入文本并通过spacy运行
text = inputs[list(inputs.keys())[0]]
doc = nlp(text)
# 对于每个被提及的实体,将此信息保存到字典中。
for ent in doc.ents:
ent_str = str(ent)
if ent_str in self.entities:
self.entities[ent_str] += f"\n{text}"
else:
self.entities[ent_str] = text

现在我们定义一个提示,它接受有关实体的信息以及用户输入。

from langchain.prompts.prompt import PromptTemplate  

template = """以下是人类和AI之间友好对话的示例。AI非常健谈,并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。如果相关,您将获得有关人类提到的实体的信息。

相关实体信息:
{entities}

对话:
人类:{input}
AI:"""
prompt = PromptTemplate(input_variables=["entities", "input"], template=template)

API参考:

现在我们将它们整合在一起!

llm = OpenAI(temperature=0)  
conversation = ConversationChain(
llm=llm, prompt=prompt, verbose=True, memory=SpacyEntityMemory()
)

在第一个例子中,没有关于Harrison的先前知识,"相关实体信息"部分为空。

conversation.predict(input="Harrison likes machine learning")  
> 进入新的ConversationChain链...
格式化后的提示:
以下是人类和AI之间友好对话的示例。AI非常健谈,并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。如果相关,您将获得有关人类提到的实体的信息。

相关实体信息:


对话:
人类:Harrison likes machine learning
AI:

> 完成ConversationChain链。


"很高兴听到这个!机器学习是一个迷人的研究领域。它涉及使用算法分析数据并进行预测。您有没有学过机器学习,Harrison?"

现在在第二个例子中,我们可以看到它提取了关于Harrison的信息。

conversation.predict(
input="What do you think Harrison's favorite subject in college was?"
)
> 进入新的ConversationChain链...
格式化后的提示:
以下是人类和AI之间友好对话的示例。AI非常健谈,并从其上下文中提供了许多具体细节。如果AI不知道问题的答案,它会诚实地说不知道。如果相关,您将获得有关人类提到的实体的信息。

相关实体信息:
Harrison likes machine learning

对话:
人类:What do you think Harrison's favorite subject in college was?
AI:

> 完成ConversationChain链。


"根据我对Harrison的了解,我认为他在大学最喜欢的科目是机器学习。他对这个科目表达了浓厚的兴趣,并经常提到它。"

请再次注意,这个实现非常简单且脆弱,可能在实际生产环境中没有用处。它的目的是展示您可以添加自定义的内存实现。