Skip to main content

时间加权向量存储检索器

该检索器使用语义相似性和时间衰减的组合。

评分算法如下:

语义相似性 + (1.0 - 衰减率) ^ 经过的小时数  

值得注意的是,经过的小时数指的是自检索器中的对象上次访问以来经过的小时数,而不是自创建以来经过的小时数。这意味着经常访问的对象保持“新鲜”。

import faiss  

from datetime import datetime, timedelta
from langchain.docstore import InMemoryDocstore
from langchain.embeddings import OpenAIEmbeddings
from langchain.retrievers import TimeWeightedVectorStoreRetriever
from langchain.schema import Document
from langchain.vectorstores import FAISS

低衰减率 Low Decay Rate

低的衰减率(在这里,为了极端,我们将其设置为接近0)意味着记忆将被“记住”更长时间。衰减率为0意味着记忆永远不会被遗忘,使得该检索器等同于向量查找。

# 定义嵌入模型
embeddings_model = OpenAIEmbeddings()
# 初始化空的向量存储
embedding_size = 1536
index = faiss.IndexFlatL2(embedding_size)
vectorstore = FAISS(embeddings_model.embed_query, index, InMemoryDocstore({}), {})
retriever = TimeWeightedVectorStoreRetriever(vectorstore=vectorstore, decay_rate=.0000000000000000000000001, k=1)

yesterday = datetime.now() - timedelta(days=1)
retriever.add_documents([Document(page_content="hello world", metadata={"last_accessed_at": yesterday})])
retriever.add_documents([Document(page_content="hello foo")])
        ['d7f85756-2371-4bdf-9140-052780a0f9b3']
# "Hello World"被首先返回,因为它最显著,并且衰减率接近0,意味着它仍然足够新
retriever.get_relevant_documents("hello world")
        [Document(page_content='hello world', metadata={'last_accessed_at': datetime.datetime(2023, 5, 13, 21, 0, 27, 678341), 'created_at': datetime.datetime(2023, 5, 13, 21, 0, 27, 279596), 'buffer_idx': 0})]

高衰减率

使用高的衰减率(例如,多个9)时,最近性分数迅速变为0!如果将其设置为1,所有对象的最近性都为0,再次使得该检索器等同于向量查找。

# 定义嵌入模型
embeddings_model = OpenAIEmbeddings()
# 初始化空的向量存储
embedding_size = 1536
index = faiss.IndexFlatL2(embedding_size)
vectorstore = FAISS(embeddings_model.embed_query, index, InMemoryDocstore({}), {})
retriever = TimeWeightedVectorStoreRetriever(vectorstore=vectorstore, decay_rate=.999, k=1)

yesterday = datetime.now() - timedelta(days=1)
retriever.add_documents([Document(page_content="hello world", metadata={"last_accessed_at": yesterday})])
retriever.add_documents([Document(page_content="hello foo")])
        ['40011466-5bbe-4101-bfd1-e22e7f505de2']
# "Hello Foo"被首先返回,因为"hello world"已经大部分被遗忘
retriever.get_relevant_documents("hello world")
        [Document(page_content='hello foo', metadata={'last_accessed_at': datetime.datetime(2023, 4, 16, 22, 9, 2, 494798), 'created_at': datetime.datetime(2023, 4, 16, 22, 9, 2, 178722), 'buffer_idx': 1})]

虚拟时间

使用LangChain中的一些工具,您可以模拟时间组件

from langchain.utils import mock_now
import datetime

# 注意最后访问时间是该日期时间
with mock_now(datetime.datetime(2011, 2, 3, 10, 11)):
print(retriever.get_relevant_documents("hello world"))
        [Document(page_content='hello world', metadata={'last_accessed_at': MockDateTime(2011, 2, 3, 10, 11), 'created_at': datetime.datetime(2023, 5, 13, 21, 0, 27, 279596), 'buffer_idx': 0})]