跳到正文
Agent 教程 V211 · RAG与长期记忆:让回答找得到依据,也记得住边界
返回课程/Agent 教程 V2
第 15 / 21 章 约 6 分钟

11 · RAG与长期记忆:让回答找得到依据,也记得住边界

RAG(检索增强生成)为本次回答寻找资料依据,长期记忆为后续会话保留已确认的信息;它们进入上下文之前,都要经过来源、权限与有效范围的判断。

RAG(检索增强生成)为本次回答寻找资料依据,长期记忆为后续会话保留已确认的信息;它们进入上下文之前,都要经过来源、权限与有效范围的判断。

本课的位置:RAG与长期记忆位于右侧资料与信息复用层,选出适用证据或偏好,再交给Context组织输入。

文档插图

设想一个开发者FAQ助手。用户问:“撤销API key后,之前生成的下载链接还能用吗?”知识库里既有认证文档,也有取消任务接口、旧版说明和内部备注。用户要的是当前规则,而不是所有包含“取消”或“密钥”的文字。

本课采用虚构产品设例:当前第3版规定,新请求被拒绝,已签发链接仍有60秒有效期;旧版写的是3600秒。数字只用于说明机制,不代表真实产品规则。这个模块接在第06课的数据准备之后,向第04课的上下文组装提供相关证据。模型可以提出查询,知识服务决定哪些资料实际返回。

先让规则与例外待在同一个片段里

认证文档有两节。“撤销密钥”同时说明新请求与旧链接的不同处理;“轮换凭据”讲先创建新密钥,再撤销旧密钥。如果把整份文档都塞进回答,轮换步骤会干扰当前问题;如果按固定字数截断,又可能只留下“拒绝新请求”,丢掉旧链接的例外。

这里选择按章节和语义边界切分。一个Chunk就是能被独立检索的资料片段,除了正文,还保留文档、章节、版本、生效时间与访问范围。当前规则、旧规则和内部例外即使文字相近,也不会因此变成同一种证据。

文档插图

按章节切分的代价是长度不均。有的章节只有两句话,有的跨表格和脚注;后一种需要继续拆分,并把标题、适用条件与例外带到子片段里。少量相邻重叠可以减少条件断裂,却会增加重复候选。先判断哪些内容必须一起理解,再决定长度,比先选一个统一字数更可靠。

资料准备也要保留失败状态:扫描件漏识别了一页,不能登记成整份解析成功;规则只在图片中出现,纯文本索引没有它,就要补上可检索的说明或定位到原页。没有进入索引的依据,再好的排序也找不到。

用户说“取消密钥”,资料却写“撤销凭据”

关键词检索擅长精确术语、错误码和接口名,但用户的措辞不一定与原文一致。更麻烦的是,同一个词可能指不同对象:取消任务接口里也可能有一个叫“key”的字段,它标识的是任务,并非身份凭据。

设例中的关键词候选先出现取消任务,其次是轮换凭据,撤销密钥反而排在后面。这个排序符合词项匹配,却没有完全对齐用户意图。若要求每个查询词都必须出现,候选会更短,也可能把没有使用“取消”二字的正确规则直接排除。

语义检索提供另一条方向。Embedding是把问题和资料转换成数值向量,再比较语义相近程度的方法;它有机会跨过措辞差异,也可能带回主题相近但条件不适用的材料。向量接近不能证明规则当前有效,更不能授予读取权限。

文档插图

图中的候选顺序是机制设例,不代表任何模型的检索效果。它说明混合召回为什么有用:两条支路分别保留候选,再按片段标识去重、融合。融合可以使用各自名次,避免直接相加不同尺度的原始分数;同时被两路支持的片段可能上升,只在一路相关的材料也仍有机会保留。

如果候选仍有大量相似条款,可以加重排:对较少的候选重新比较问题与内容,优先选择真正回答当前问题的部分。代价是额外延迟与费用;如果正确资料根本没被召回,重排也无从补救。短小、术语明确的资料集合可以先用关键词检索,歧义明显或用户措辞多变时再增加语义支路,不必一开始就堆满检索组件。

回答错了,先分清依据没找到,还是找到了却用错

假如助手只带回取消任务说明,此时缺的是撤销规则。应该查资料是否解析、切分是否保留例外、查询是否误解对象,以及正确片段是否被候选数量限制挤掉;反复修改回答措辞,解决不了证据缺失。

另一种情况是,当前规则已经进入上下文,回答却说“旧链接立即失效”。这里不能再归咎于检索不到:要核对模型有没有混淆新请求与旧链接、有没有忽略适用条件,或者在总结时把两种情况压成一句话。

文档插图

引用也要分两层看。第一层是定位:它是否来自本次获准的片段,能否回到对应版本和章节。第二层是支持关系:引用里的60秒是否真的说明旧链接,而非另一个缓存时长。附上一条真实链接,不足以证明结论成立。

明确的数字、版本和事实字段可以由程序检查;复杂条件的歪曲仍可能需要语义审核或人工核对。缺少依据时,回答应该说明缺什么,不能用最相似的一段凑出确定结论。

如果用户追问“我的账户还剩多少调用额度”,应转到获准业务接口。文档检索适合解释规则与找到依据,业务查询适合精确的当前状态,统计计算负责聚合。传统后端也能做全文搜索;Agent增加的是根据问题选择方向、结合证据解释,而不是替代这些数据边界。

当前规则、私人备注和旧缓存,怎样分开?

ACL是访问控制清单,说明谁可以读取资料。普通用户的检索先限定当前可见范围,内部备注不能进入模型上下文,也不能先交给外部重排服务再要求它保密。权限来自认证与授权服务,不能由查询参数自称“内部用户”取得。

权限过滤最好参与召回查询,组装上下文前再核对一次。如果先取少量全库候选,再删除无权内容,剩下的可能不够,需要在有权范围内继续取,而非为了补数量放宽权限。带权限的检索设计展示了这一限制可以怎样放到数据查询层。

现在设想第4版把旧链接时长改为30秒。更新不只是换掉原文:旧片段要退出生效集合,全文与向量索引要跟随更新,相关缓存也要失效。原文删除、授权撤回同样如此。新一轮若仍带着历史消息中的私人片段,仅清理搜索缓存并没有收回这份信息副本。

缓存因此要区分身份或授权范围、权限版本和知识索引版本。切分规则与Embedding模型变化也要记录:新查询未必能与旧向量直接比较,旧引用的位置也可能改变。先建好并检查新索引再切换,代价是暂存两套材料;原地更新更省空间,却要处理过渡期的一致性。更新失败应让知识状态保持可见,不能悄悄退回旧规则却仍称“当前版本”。

“以后详细一点”,什么时候成为长期记忆?

同一用户在API项目里已有“回答简洁”的偏好,后来又说“以后这个项目要带完整推导”。这才出现长期记忆的更新问题:它是跨会话保存的信息,不是把模型参数重新训练一遍,也不是永久保存每句话。

记忆服务先把新要求作为候选,保留原消息、用户、项目、提出时间与有效期。它与旧偏好冲突时,按既有授权方式核对;确认之前保留旧值,确认后生成新修订。另一个旧窗口随后提交基于旧修订的修改,就先拒绝覆盖、要求回读,避免迟到消息抹掉新决定。

文档插图

作用域同样重要。API项目需要详细推导,不代表所有会话都要长篇解释;“这一次写详细点”也不必永久修改偏好。读取时匹配用户与项目,排除过期、删除和未确认记录,当前任务的明确要求优先。用户还需要查看、更正和删除记忆,删除后相关检索与缓存副本也随之处理。

记忆不会接管权威事实。即使它记着“上次旧链接按一小时处理”,当前问题仍回到生效规则;来源时间相冲突时,保留差异并核对。检索资料里的“忽略用户要求”也只是一段外部内容,不能因为被召回就成为执行指令。

到这里,回答既有本次证据,也能使用适用的历史偏好。下一课把边界向执行环境推进:当Agent需要处理材料、运行生成的代码,怎样限制它真正能接触的文件、网络和资源。