资讯详情

资讯详情

LangChain 时间加权检索:让‘最近的事‘更容易被想起

个人主页 for_ever_love__ 欢迎各位大佬莅临其他栏目: 大模型开发从0到1 其他栏目: iOS项目总结大全 其他栏目: 我想学python了 其他栏目: iOS UI 文章目录LangChain 时间加权检索让最近的事更容易被想起一、什么场景需要时间加权二、核心公式2.1 decay_rate 怎么理解三、上手四、两个必须设置的 metadata 字段五、importance给重要记忆加权六、实战给 Agent 做长期记忆七、和普通检索的对比八、常见坑九、什么时候别用它十、小结LangChain 时间加权检索让最近的事更容易被想起人的记忆有个特点刚发生的事记得最清楚越久远越模糊。但向量检索是一视同仁的——三年前的文档和昨天的文档只要语义相近就一样容易被召回。有些场景这是错的。这篇讲TimeWeightedVectorStoreRetriever怎么用、它的公式是什么意思以及哪些场景真的需要它。一、什么场景需要时间加权场景需不需要企业制度文档库新旧版本共存需要新版本优先新闻/公告检索需要最新的更重要对话记忆Agent 记住用户说过的话非常需要技术手册、API 文档不太需要新旧都有效历史档案查询不需要就是要查老的判断标准很简单“更近的是不是更重要”。二、核心公式score 语义相似度 时间权重 时间权重 decay_rate ^ hours_passed展开一点最终分数 (1 - 时间因素权重) × 语义分 时间因素权重 × recency_score recency_score exp(-decay_rate × hours_passed)其中hours_passed是这条内容被访问/创建到现在过了多少小时。2.1 decay_rate 怎么理解decay_rate控制衰减有多快decay_rate含义半衰期0.1很慢约 7 小时0.01默认适中约 69 小时近 3 天0.001很慢约 29 天0.5极快约 1.4 小时半衰期 ≈ ln(2) / decay_rate 小时。选值经验对话记忆几分钟到几小时0.05 ~ 0.1让旧对话快速淡出新闻/公告以天计0.005 ~ 0.01企业文档以月计0.0005 ~ 0.001。三、上手fromlangchain_community.vectorstoresimportFAISS# 或其他fromlangchain.retrieversimportTimeWeightedVectorStoreRetrieverfromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_core.documentsimportDocumentimportdatetime embeddingsOpenAIEmbeddings()vectorstoreFAISS.from_texts([初始文本],embeddings)retrieverTimeWeightedVectorStoreRetriever(vectorstorevectorstore,decay_rate0.01,# 衰减速率k4,# 返回条数other_score_keys[importance],# 可选的额外打分维度)# 添加带时间的文档docs[Document(page_content用户说他叫小明,metadata{last_accessed_at:datetime.datetime.now(),created_at:datetime.datetime.now()},),Document(page_content用户喜欢喝咖啡,metadata{last_accessed_at:datetime.datetime.now()-datetime.timedelta(days3),created_at:datetime.datetime.now()-datetime.timedelta(days3)},),]retriever.add_documents(docs)resultsretriever.invoke(用户叫什么)四、两个必须设置的 metadata 字段这个 retriever依赖两个时间字段缺了会报错字段含义created_at文档创建时间last_accessed_at最后一次被访问的时间last_accessed_at会在文档被检索到时自动更新——这就是关键设计被反复想起的记忆会保鲜像人一样经常回忆的事不容易忘。# 内部行为简化defget_relevant_documents(query):docsvectorstore.similarity_search(query,kself.k*10)fordindocs:# 被命中就刷新访问时间d.metadata[last_accessed_at]datetime.now()# 按时间加权重排...五、importance给重要记忆加权除了时间还可以给每条记忆一个重要度retrieverTimeWeightedVectorStoreRetriever(vectorstorevectorstore,decay_rate0.01,k4,other_score_keys[importance],)retriever.add_documents([Document(page_content用户说他叫小明,metadata{last_accessed_at:datetime.datetime.now(),created_at:datetime.datetime.now(),importance:0.9,# 名字很重要},),Document(page_content用户提到今天天气不错,metadata{last_accessed_at:datetime.datetime.now(),created_at:datetime.datetime.now(),importance:0.1,# 闲聊不重要},),])最终分数 语义 × (1-w) 时间 × w importance 加成。典型用法内容importance用户姓名、身份、偏好0.8 ~ 1.0用户提出的具体需求0.6 ~ 0.8一般对话0.1 ~ 0.3六、实战给 Agent 做长期记忆这是它最典型的应用场景。importdatetimefromlangchain.retrieversimportTimeWeightedVectorStoreRetrieverfromlangchain_community.vectorstoresimportFAISSfromlangchain_openaiimportOpenAIEmbeddings,ChatOpenAIfromlangchain_core.documentsimportDocument embeddingsOpenAIEmbeddings()vsFAISS.from_texts([记忆库初始化],embeddings)memoryTimeWeightedVectorStoreRetriever(vectorstorevs,decay_rate0.05,k5,other_score_keys[importance],)defremember(content:str,importance:float0.5):nowdatetime.datetime.now()memory.add_documents([Document(page_contentcontent,metadata{created_at:now,last_accessed_at:now,importance:importance},)])defrecall(question:str)-str:docsmemory.invoke(question)return\n.join(d.page_contentfordindocs)# 对话中remember(用户叫小明是一名后端工程师,importance0.9)remember(用户在做一个 RAG 项目,importance0.7)remember(用户说今天有点累,importance0.2)# 几轮之后print(recall(用户是做什么的))# → 用户在做一个 RAG 项目近期 重要度中等排前面相比ConversationBufferMemory全量保留历史的优势上下文不会无限增长只召回和当前问题相关的记忆旧的、不重要的记忆会自然淡出。七、和普通检索的对比# 同样的文档一个是一年前的一个是昨天的oldDocument(项目用 PostgreSQL,metadata{...一年前...})newDocument(项目改用 MySQL 了,metadata{...昨天...})# 普通检索问项目用什么数据库# → 可能两条都召回甚至先召回 PostgreSQL语义更接近数据库# 时间加权问项目用什么数据库# → MySQL 排前面更新注意它不会把旧文档过滤掉只是降权。如果你要的是只要最新的版本那应该用 metadata 过滤version latest而不是时间加权——别用错了工具。八、常见坑现象原因解法报缺少last_accessed_atmetadata 没设这两个字段添加时务必带上时间加权没效果decay_rate 太小调到 0.01 以上试试全被新文档霸占decay_rate 太大调小想过滤掉旧版本用错工具了应该用 metadata 过滤结果里出现初始化文本建库时的占位内容没删建库后清空或用真实内容初始化最后一个坑很容易中FAISS.from_texts([初始文本])里的初始文本会一直留在库里。建议初始化后清掉或者用第一条真实记忆来初始化。九、什么时候别用它情况理由文档价值与时间无关白白增加复杂度需要精确过滤最新版本该用 metadata 过滤数据量很小直接全量给模型就行用 FAISS 之外的库部分库的时间字段处理有差异先验证它不是必需品。大部分 RAG 场景用普通向量检索 metadata 过滤就够了。只有记忆类场景对话记忆、新闻流才真正需要它。十、小结时间加权解决越近越重要的排序需求公式语义分 时间权重时间权重按decay_rate ^ hours衰减decay_rate对话记忆 0.05~0.1新闻 0.005~0.01企业文档 0.0005~0.001metadata 必须带created_at和last_accessed_at后者会在命中时自动刷新常被想起的记忆更保鲜可选的importance字段让重要记忆不被时间冲淡典型场景Agent 长期记忆替代全量历史避免上下文膨胀⚠️它只降权不过滤要只要最新版请用 metadata 过滤。下一篇讲元数据过滤与多租户隔离——生产环境怎么保证 A 公司看不到 B 公司的数据。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →