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

个人主页: > for_ever_love__ <(欢迎各位大佬莅临😊)
其他栏目: > 大模型开发从0到1 <
其他栏目: > iOS项目总结大全 <
其他栏目: > 我想学python了 <
其他栏目: > iOS UI <

文章目录

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。

三、上手

python 复制代码
from langchain_community.vectorstores import FAISS  # 或其他
from langchain.retrievers import TimeWeightedVectorStoreRetriever
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
import datetime

embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_texts(["初始文本"], embeddings)

retriever = TimeWeightedVectorStoreRetriever(
    vectorstore=vectorstore,
    decay_rate=0.01,          # 衰减速率
    k=4,                      # 返回条数
    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(days=3),
                  "created_at": datetime.datetime.now() - datetime.timedelta(days=3)},
    ),
]
retriever.add_documents(docs)

results = retriever.invoke("用户叫什么")

四、两个必须设置的 metadata 字段

这个 retriever 依赖两个时间字段,缺了会报错:

字段 含义
created_at 文档创建时间
last_accessed_at 最后一次被访问的时间

last_accessed_at 会在文档被检索到时自动更新 ------

这就是关键设计:被反复想起的记忆会"保鲜" ,

像人一样,经常回忆的事不容易忘。

python 复制代码
# 内部行为(简化)
def get_relevant_documents(query):
    docs = vectorstore.similarity_search(query, k=self.k * 10)
    for d in docs:
        # 被命中就刷新访问时间
        d.metadata["last_accessed_at"] = datetime.now()
    # 按时间加权重排
    ...

五、importance:给重要记忆加权

除了时间,还可以给每条记忆一个"重要度":

python 复制代码
retriever = TimeWeightedVectorStoreRetriever(
    vectorstore=vectorstore,
    decay_rate=0.01,
    k=4,
    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 做长期记忆

这是它最典型的应用场景。

python 复制代码
import datetime
from langchain.retrievers import TimeWeightedVectorStoreRetriever
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.documents import Document

embeddings = OpenAIEmbeddings()
vs = FAISS.from_texts(["记忆库初始化"], embeddings)

memory = TimeWeightedVectorStoreRetriever(
    vectorstore=vs, decay_rate=0.05, k=5,
    other_score_keys=["importance"],
)

def remember(content: str, importance: float = 0.5):
    now = datetime.datetime.now()
    memory.add_documents([Document(
        page_content=content,
        metadata={"created_at": now, "last_accessed_at": now,
                  "importance": importance},
    )])

def recall(question: str) -> str:
    docs = memory.invoke(question)
    return "\n".join(d.page_content for d in docs)

# 对话中
remember("用户叫小明,是一名后端工程师", importance=0.9)
remember("用户在做一个 RAG 项目", importance=0.7)
remember("用户说今天有点累", importance=0.2)

# 几轮之后
print(recall("用户是做什么的?"))
# → "用户在做一个 RAG 项目"(近期 + 重要度中等,排前面)

相比 ConversationBufferMemory(全量保留历史)的优势:

  • 上下文不会无限增长;
  • 只召回和当前问题相关的记忆;
  • 旧的、不重要的记忆会自然淡出。

七、和普通检索的对比

python 复制代码
# 同样的文档,一个是一年前的,一个是昨天的
old = Document("项目用 PostgreSQL", metadata={...一年前...})
new = Document("项目改用 MySQL 了", metadata={...昨天...})

# 普通检索:问"项目用什么数据库"
# → 可能两条都召回,甚至先召回 PostgreSQL(语义更接近"数据库")

# 时间加权:问"项目用什么数据库"
# → MySQL 排前面(更新)

注意:它不会把旧文档过滤掉,只是降权。

如果你要的是"只要最新的版本",

那应该用 metadata 过滤(version == latest),

而不是时间加权------别用错了工具。

八、常见坑

现象 原因 解法
报缺少 last_accessed_at metadata 没设这两个字段 添加时务必带上
时间加权没效果 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.001;
  • metadata 必须带 created_at 和 last_accessed_at ,
    后者会在命中时自动刷新(常被想起的记忆更"保鲜");
  • 可选的 importance 字段让重要记忆不被时间冲淡;
  • 典型场景:Agent 长期记忆(替代全量历史,避免上下文膨胀);
  • ⚠️ 它只降权不过滤,要"只要最新版"请用 metadata 过滤。

下一篇讲元数据过滤与多租户隔离------生产环境怎么保证 A 公司看不到 B 公司的数据。

相关推荐
FPC_小西1 小时前
您知道嵌入式开发中八大常用接口与总线有哪些吗?
人工智能·单片机·嵌入式硬件·pcb工艺·hdi高密度互联
陈嘿萌1 小时前
CVPR 2026 | 上交&复旦&清华 3M-TI:让 RGB 成为热成像超分助手,手机也能看清细节!
人工智能·计算机视觉·智能手机·学术研究与理论基础
weixin_446260851 小时前
认知谦逊:知识冲突场景下大模型智能体的识别‑处理‑上报评测框架
人工智能
Summer-Bright1 小时前
深度 | 记忆的锁定账:模型可以随便换,记忆却搬不走
人工智能·agent·记忆
袖清暮雨1 小时前
机器学习之其他聚类(层次聚类+DBSCAN算法)
人工智能·机器学习·ai·聚类
雪雪9081 小时前
Work Agent深度解读:AI如何自主完成多步骤长程工作任务
人工智能
小宋10211 小时前
Recursive Language Models 实战:递归处理超长外部文本
人工智能·深度学习·机器学习
星云低代码开发平台1 小时前
AI 定时任务接 ERP:账号切换后的权限校验与异常状态设计
人工智能·定时任务·erp
烟雨江南7852 小时前
灵声智库-招投标会议语音识别怎么做?实时转写、多人发言与会议留痕方案
人工智能·音视频·语音识别·ai客服