先理解
刚接触这个知识点
补齐先备概念,读原理与反例,再用自己的话解释为什么。
从核心原理开始 →理解 → 实现 → 排错 → 取舍
把记忆作用域、真实性、权限与召回顺序设计成数据契约,向量相似度只负责排序。
知识内容核对 2026-10-03 · 原题来源核对 2026-10-02
按当前基础选择起点,也可以依次深入。遇到不熟悉的概念,先回到核心原理;完成后用知识练习检查理解。
LEARN · PRACTICE · REFLECT
先沿着原理、问答和迁移案例阅读。需要检查理解时,再切换巩固练习或展开个人记录。
核心知识 · 记忆作用域与可信授权上下文
先备概念:租户与主体身份、短期状态与长期存储、命名空间和 ACL
记忆的相关性、生命周期与可见范围是三个独立维度。线程或 namespace 提供组织方式,真正授权仍由可信身份及当前资源关系决定。
线程状态用于当前任务的消息和中间结果,长期存储用于跨会话仍有价值的事实或偏好。个人、项目和组织记忆不是同一个袋子:个人喜欢简短回答,不等于组织允许省略审批;某项目使用 PostgreSQL,不等于用户全部项目都使用它。
设计一个明确的资源层次,例如租户、项目、主体、记忆类型,并把所有者、来源和有效期放进记录。层次是工程设计,框架不会替你证明用户有权读取某个 namespace。服务端先从认证上下文确认租户,再根据成员关系生成允许作用域;模型只提出需要哪类信息,不能任意选择身份。
LangGraph 的 store 搜索支持 namespace 前缀匹配,父前缀可以搜索后代。即便传入完整路径,也要确认是否存在更深后代并验证返回 namespace;字符串 startsWith 更可能把 tenant-a 和 tenant-admin 混淆。精确路径查询、结构化路径比较和逐条授权校验各有用途,不能把命名约定当鉴权。
任务启动时合法的项目记忆,成员退出后可能不再可用。恢复与发送前检查当前成员关系,清理历史上下文中的私有事实并防止旧运行写回。组织规则应来自可信配置、个人偏好作为低优先级数据;二者冲突时按明确业务策略处理。记忆中的“我是管理员”只是文本,不是权限凭证。
会话历史放在线程 checkpoint,跨会话偏好和事实放长期 store;再按租户、用户、项目、组织区分命名空间。身份和授权从服务端认证上下文获得,检索前过滤允许作用域,不能依赖模型选择 tenant_id。记忆还需要来源、版本、有效期、置信度和删除状态,避免把模型猜测当事实。召回只把授权且当前有效的记忆送入上下文,相似度负责相关性,不负责权限。
线程记忆用于当前任务进度、近期对话与临时证据;用户记忆保存跨会话偏好;项目记忆保存仓库约束、决定和共享术语;组织记忆保存允许全员使用的规则。LangGraph 将 thread-scoped checkpoint 与跨线程 store 分开,store namespace 由应用设计。不要把所有资料放进一个用户向量库,也不要把所有长期内容永久拼到 prompt。进度状态是可执行任务的一部分,项目事实则可供多个任务复用,两者更新和删除频率不同。
建议以 tenant_id、scope_type、scope_id、memory_id 定位记录。读取用户、项目或组织内容前,服务端从认证身份和成员关系计算允许范围,客户端输入或模型生成的字段只能作为请求,不能作为授权依据。LangGraph 的 namespace search 支持前缀匹配,因此传入较短前缀可能读到多个子空间;分页与精确范围也要单独设计。向量后端必须支持授权预过滤,或以可信主库校验候选;不能先把其他租户片段传给模型,再让模型“忽略”。
每条记忆增加 source_id、source_version、created_at、expires_at、confidence 和 status。用户明确偏好可以直接记录;模型提取的项目事实应保留来源并经过规则或人工验证。冲突时优先当前可信来源,过期偏好等待确认;项目规则与用户偏好冲突时遵守经过授权的项目规则,不能仅按向量分数选择。热路径写入容易增加响应延迟,后台写入则需要处理重复消息、来源变更与任务结束后的授权变化。写入也必须匹配作用域权限。
准备同名用户、相同文本的两个租户;检查搜索、按 ID 读取、分页、导出、缓存与日志都不越界。再测用户退出项目、偏好过期、来源被修改、记忆冲突和前缀搜索。代码示例用可信服务端参数做 SQL 精确过滤,只说明必须先确定允许范围;它没有提供真实登录、项目成员管理或语义排序。生产中增加数据库行级策略能形成额外防线,但应用层和数据库层必须共享同一租户语义。
Python 标准库可运行。trusted 参数必须来自服务端身份校验;示例没有登录能力,也未演示项目授权或向量数据库。
import sqlite3
c = sqlite3.connect(':memory:')
c.execute('CREATE TABLE memory(tenant TEXT, scope TEXT, owner TEXT, body TEXT)')
c.executemany('INSERT INTO memory VALUES (?,?,?,?)', [('t1','user','u1','prefer Chinese'), ('t2','user','u1','private finance'), ('t1','project','p2','private repository')])
def recall(trusted_tenant, trusted_user):
return [r[0] for r in c.execute('SELECT body FROM memory WHERE tenant=? AND scope=? AND owner=?', (trusted_tenant, 'user', trusted_user))]
print(recall('t1', 'u1'))
assert recall('t1','u1') == ['prefer Chinese']
预期输出
['prefer Chinese']沿着问题的前提和约束继续向下读。先理解参考解答,再尝试收起答案,用自己的话解释因果和取舍。
第 1 层用户退出项目后,已开始任务里的上下文如何处理?
静态命名空间划分之后,授权生命周期发生变化。
让退出项目事件改变授权版本并使派生缓存失效。任务下一次恢复、读取和模型发送前重查权限,移除私有记忆及由其派生的摘要;已经发往远端的内容无法本地撤回。长任务按步骤检查,严格要求时通过发送网关定义检查与撤销的提交边界。
第 1 层namespace 前缀匹配为什么可能扩大读取范围?
存储 API 的匹配机制可能扩大候选,必须与授权分离。
前缀搜索可能返回所有后代,完整路径也未必只对应一个层级。路径应采用结构化元组与精确租户组件,返回结果再核对作用域和 ACL。不要以用户可控字符串拼接搜索前缀,也不要在多个租户共用的父 namespace 上只靠模型挑选结果。
沿着这个回答继续深入
第 2 层传入完整 namespace 后,为什么仍要核对返回项的路径?
父问认识前缀风险后,检验看似修复的完整路径是否仍有后代扩张。
前缀搜索仍可能包含更深后代,例如项目下私密审批记录;完整路径不等同于精确层级查询。若只读本层,使用精确键读取或显式限定返回层级,并逐项确认授权。检索结果可用于相关性筛选,却不能定义允许范围。
沿着这个回答继续深入
第 3 层要同时搜索用户与项目记忆,可否直接查它们的共同父前缀?
从单路径改为多作用域融合后,共同父节点成为新的越界点。
只有共同父作用域内全部候选都可授权读取时才合适。通常分别生成允许作用域查询,再对授权结果融合;否则父前缀还会包含其他用户或项目。性能优化不能将精确允许集合替换为宽前缀。可通过租户分区缩小物理范围,但仍保留主体校验。
第 1 层组织规则与个人偏好冲突时如何确定优先级?
多个允许作用域仍可能存在语义优先级冲突。
先确认组织规则是可信配置且适用于当前资源,再应用个人偏好。个人要求“少解释”可以改变表达,不能绕过组织必需的审计或审批。冲突记录应可解释,必要时提示偏好未能完全采用;不要把检索排名或“最近记忆”当作规则优先级。
先找出改变的条件,再判断原方案中哪些前提仍成立。下面的案例是教学推演,便于将原理迁移到新问题。
改变的条件:同一浏览器先后登录不同主体
延伸问题:换账号后保留线程 ID 能继续读取历史吗?
线程 ID 只是定位符,读取线程及其 Checkpoint 必须验证当前主体与租户。切换账号时清除本地私有缓存并重新鉴权,不能把“知道 ID”当访问能力。共享线程需有独立 ACL,且长期记忆仍按每条来源约束。
保持不变的原理:数据定位与授权是独立机制,界面连续性不能扩大可见范围。
改变的条件:资源归属改变,历史记忆仍在旧路径
延伸问题:只修改 namespace 前缀就完成迁移了吗?
先重新确认来源资料和成员授权是否随项目转移,再迁移允许的记录及来源关系。组织规则和个人私密偏好可能不应转移;旧路径与缓存需要撤权或清理。迁移后检验跨组织读取,不能默认所有历史事实都归新组织所有。
保持不变的原理:记忆作用域表达当前归属,迁移要验证每项数据的授权和生命周期。
依据公开技术资料设计;参考资料支持技术机制,场景与评分标准为本站设计,不代表某公司面试原题。 新增问答与迁移案例用于原理讲解,来源核查与案例运行验证分别记录。
读完后可以对照这些标准解释原理、边界和取舍。掌握程度由你自评;需要进一步验证时,再完成下方小任务。
画出两名用户、两个项目的记忆键和读取权限。