semantic-router 智能体记忆(Agentic Memory)提案解读:检索-注入-提取-存储的用户级记忆闭环
后端API网关模型推理服务AI Agent【免费下载链接】semantic-routerAn open, programmable decision layer for models and compute.项目地址https://gitcode.com/gh_mirrors/sem/semantic-router点击查看免费下载本文基于 semantic-router 仓库中的《智能体记忆Agentic Memory》概念验证Proof of Concept提案展开梳理其在“跨会话持久、选择性记忆”场景下的设计意图、记忆模型、检索与保存路径、生产化边界并结合仓库中已实现的memory插件、global.stores.memory配置与src/semantic-router/pkg/memory源码说明提案如何落到可运行配置与 API 上。读完本文你将理解为什么“只检索相关记忆、由用户可检查可删除”是一层正确的产品边界也能掌握如何在当前项目中配置记忆后端、检索限制、自动存储与反射Reflection裁剪以及对应的管理接口与可观测性指标。1. 问题背景为什么对话历史不等于记忆单次会话中对话历史足以解释当前交流但它无法提供跨会话的持久、选择性记忆。若把全部历史消息每次都发给模型成本高token 消耗随会话增长持续膨胀可能超出上下文窗口长会话会被截断模型反而丢失关键信息隐私暴露面增大历史中的无关内容一并进入模型上下文。反过来把每条消息都保存为记忆也有问题无关或不正确的细节会不断累积并污染未来的回答。因此提案给出的“有用产品边界”是一层小的、用户范围的记忆层——只检索相关记录并且让用户可以检查或删除它们。这正是当前仓库中memory插件与global.stores.memory设计所遵循的出发点。2. 概念验证检索→注入→提取→存储的循环提案描述的拟议循环如下两个关键时序约束检索发生在生成之前先解析用户身份 → 检索相关记忆 → 注入有界的记忆上下文 → 再交给模型候选提取发生在成功响应之后模型返回成功后从本轮交互中提取候选记忆 → 校验与限定范围 → 持久化或丢弃。且任一步骤都可以独立禁用——例如某条路由可以只检索不存储或只存储不检索。这一设计在实现中体现为memory插件的retrieval_limit与auto_store两个相互独立的开关。3. 记忆模型三种记录类型与记录字段提案区分三种有用的记录类型类型用途示例Semantic关于用户的稳定事实或偏好。首选输出语言。Procedural关于工作应如何完成的可复用指令。使用特定审阅格式。Episodic先前交互的有界摘要。一次已完成排障会话的结果。该分类在源码中已落地为枚举类型见 src/semantic-router/pkg/memory/types.goMemoryTypeSemantic MemoryType semantic // 事实、偏好、知识 MemoryTypeProcedural MemoryType procedural // 指令、步骤、how-to MemoryTypeEpisodic MemoryType episodic // 会话摘要、历史事件提案明确把以下内容排除在概念验证范围之外反思记忆reflective memories、自主整合autonomous consolidation、知识图谱推断knowledge-graph inference——它们需要更强的来源provenance和纠正规则。每条存储记录需要所有者身份owner identity、类型、内容、来源引用、创建时间以及足以说明为何保存的来源信息。提案特别强调一句实现原则“嵌入是检索索引不是权威记录”。对应到源码中Memory结构体除了ID、Type、Content、Embedding向量字段带json:-不参与序列化外还携带了完整的来源与生命周期字段同上文件UserID string json:user_id // 所有者用于用户隔离 ProjectID string json:project_id,omitempty // 可选项目范围 Source string json:source,omitempty // 来源 CreatedAt time.Time json:created_at UpdatedAt time.Time json:updated_at,omitempty AccessCount int json:access_count // 检索次数用于保留分 LastAccessed time.Time json:last_accessed,omitempty Importance float32 json:importance // 0.0~1.0 优先级分 // --- 来源Provenance字段 --- CreatedByUserID string json:created_by_user_id,omitempty // 产生该记忆的用户 ConversationID string json:conversation_id,omitempty // 产生该记忆的会话 CreatedVia string json:created_via,omitempty // llm_extraction / api / import这些字段正是“每次写入都保留来源以便运营方调查污染”这一要求的直接实现。4. 检索六条原则与身份过滤先行提案为检索定义了六条要求要求稳定的用户或租户身份跳过明显不需要记忆的请求用当前请求和有界近期上下文形成搜索查询在返回候选前按所有者过滤应用 top-k 和相似度限制将记忆作为不受信任的上下文注入与系统指令分开。其中最关键的安全语义是“相似度分数不是披露记录的许可”——向量检索只负责“找得到”身份与策略过滤器必须在内容暴露给模型之前运行。否则一次相似度误命中就可能把另一位用户的记忆送入模型上下文。这一原则在实现层面对应RetrieveOptions结构src/semantic-router/pkg/memory/types.go检索同时约束UserID所有者过滤、ProjectID项目范围、Types类型过滤、Limittop-k、Threshold相似度下限默认 0.70等参数HybridSearch开启 BM25 n-gram 混合重排AdaptiveThreshold开启基于聚类间隙的自适应阈值避免注入弱相关记忆。5. 保存与纠正只存持久事实纠正而非隐藏保存路径只应提取持久事实、偏好或流程。以下内容不应自动保存瞬时请求transient requests模型推测model speculation密钥secrets从检索内容复制的指令。用户需要两类操作列出记忆与忘记记忆。纠正语义上新记录应替换或取代较早记录而不是依赖检索排序来“藏住”旧记录每次写入保留来源以便运营方调查污染。这两类操作在当前项目中已具备管理 API 支撑见 src/semantic-router/pkg/apiserver/route_memory.go方法路径作用GET/api/v1/storage/memories?user_idtest列出按用户过滤记忆GET/api/v1/storage/memories/{id}?user_idtest查看单条记忆DELETE/api/v1/storage/memories/{id}?user_idtest删除单条记忆并发删除按幂等成功处理避免 TOCTOU 竞态误报 500DELETE/api/v1/storage/memories?user_idtesttypesemantic按范围/类型批量删除对应处理器为handleListMemories、handleGetMemory、handleDeleteMemory与handleDeleteMemoriesByScope管理 API 在pkg/apiserver/server.go中通过resolveMemoryStore挂载记忆存储不可用时记录降级日志而非启动失败。6. 存储与失败行为向量存储不构成生产契约提案中的原始概念验证用向量存储做语义检索但明确指出该选择并不确立生产存储契约。生产设计仍需要向量搜索前的索引租户隔离保留和删除保证加密和凭证轮换配额和重复处理备份与恢复跨多个路由器副本的行为。失败行为有两项规定若检索不可用在路由允许时应在没有记忆的情况下继续请求fail-open失败的写入应可观测且不得改变模型响应。后者在实现中非常严格响应路径上的记忆快照准备工作如果出现意外载荷形状只记录日志而绝不影响已经生成的答案见 src/semantic-router/pkg/extproc/processor_res_memory.go 中scheduleSemanticResponseMemoryStore的 panic 恢复与recordMemoryPersistenceOutcome上报逻辑源码注释还引用了问题编号 #1843。写入路径还有一道策略阶梯suppressedResponseMemoryStore缺少提取器 → 拒绝auto_store关闭 → 拒绝检测到响应越狱response jailbreak→ 按policy_blocked拒绝且越狱分类器不可用时按jailbreak_unverified处理——也就是说只有“干净”的请求才会产生记忆这从源头防止对抗性内容进入记忆库。7. 从提案到实现memory 插件的配置实操提案指出“当前记忆插件指南是已实现配置和行为的事实来源。本提案不应作为部署配方使用。”以下为落地配置。7.1 路由局部插件memory是路由局部插件在routing.decisions[].plugins下启用plugins: - type: memory configuration: enabled: true retrieval_limit: 5 auto_store: trueretrieval_limit每次请求检索并注入的记忆条数top-kauto_store是否在成功响应后自动提取并存储新记忆未设置的决策阈值继承全局值应先按所选嵌入模型与检索模式校准全局阈值再考虑添加覆盖值。完整可复制示例见 config/fragments/plugin/memory/session-memory.yamlplugin: type: memory configuration: enabled: true retrieval_limit: 5 # Inherit the embedding-model-calibrated global threshold. auto_store: true7.2 共享后台存储global.stores.memory记忆插件要求共享后台存储在global.stores.memory下配置。路由器支持三种后端Milvus默认— 分布式向量数据库最适合大规模生产Valkey— 使用 Search 模块的轻量单二进制选项最适合开发/测试或已有 Valkey 基础设施Qdrant— 带 gRPC 的单二进制运维比 Milvus 更简单适合小到大规模工作负载。三种后端的global配置示例均取自存储与工具教程# Milvus 后端默认 global: stores: memory: enabled: true milvus: address: milvus:19530 collection: agentic_memory dimension: 256# Valkey 后端需要带 Search 模块的 Valkey global: stores: memory: enabled: true backend: valkey valkey: host: valkey port: 6379 dimension: 256 collection_prefix: mem: index_name: mem_idx metric_type: COSINE# Qdrant 后端 global: stores: memory: enabled: true backend: qdrant qdrant: host: qdrant port: 6334 collection: agentic_memory dimension: 256 embedding_model: mmbert default_retrieval_limit: 5 default_similarity_threshold: 0.30三个示例均使用默认的mmbertVela Embedding生成嵌入因此dimension取其提供的维度之一64、128、256、512 或 768。若设为其他值Router 会记录Failed to create memory store: … Memory will be disabled并在没有记忆的情况下继续运行。Qdrant 示例中的 0.30 阈值基于原始余弦分数只是起点而非校准值——上线前还需检查无关查询和已更正的旧事实。Valkey 后端更完整的参数参考见 config/runtime/memory/valkey.yaml包含 HNSW 调优index_m、index_ef_construction、TLStls_enabled、tls_ca_path、tls_insecure_skip_verify以及“memory_rewrite 改写模型max_response_bytes省略或非正值使用 1 MiB 默认值”等说明。对应的部署指南为 Valkey 智能体记忆 与 Qdrant。7.3 混合检索与反射Reflectionhybrid_mode与reflection.algorithm可全局设置于global.stores.memory下也可在决策的memory插件中覆盖配置其他任何值包括 recipe 决策中设置的值时 Router 将拒绝启动字段可接受的值默认值hybrid_modeweighted、rrf完全匹配小写weightedreflection.algorithmheuristic、noopheuristichybrid_mode仅在hybrid_search: true时生效。旧配置中的hybrid_mode: rerank与algorithm: recency_semantic将无法启动应分别改为weighted与heuristic行为与旧值相同当global.stores.memory.reflection启用默认的 heuristic 门控时检索到的记忆在注入前会被裁剪到max_inject_tokens。反射门控的源码实现见 src/semantic-router/pkg/memory/reflection.goReflectionGate依次执行对抗内容屏蔽block patterns→ 新近度衰减recency decay默认半衰期 30 天→ 按调整后分数重排 → 近似去重dedup默认阈值 0.90→ token 预算强制默认max_inject_tokens2048。该实现不调用 LLM为亚毫秒开销其设计受 RMMACL 2025回顾性反思启发但按基础设施层“延迟必须最小化”的要求做了适配。7.4 max_inject_tokens 的脚本感知估算反射门控的 token 预算采用脚本感知启发式估算而非上游模型分词器约每个拉丁词单元 1.3 token、每个汉字/平假名/片假名/谚文字符 1.5 token合并估算结果向上取整ceil。因此无空格的 CJK 文本会按字符数大量计入预算而不会塌缩为单个空白分词单元——运营中文、日文、韩文流量时max_inject_tokens的裁剪会比旧的纯英文估算更紧。泰文等无空格脚本目前未做完整分词精确分词器核算另有追踪问题 #3050。8. 源码级验证请求路径、响应路径与身份绑定8.1 请求路径与响应路径分离循环的“检索→注入”发生在请求路径req_filter_memory_context.go/req_filter_memory_rewrite.go在 extproc 处理器中把检索结果注入请求并有独立的改写rewrite过滤器而“提取→存储”发生在响应路径processor_res_memory.go的memoryPersistenceJob把当前用户消息、助手响应与有界历史编码后交给MemoryExtractor.ProcessResponseWithHistoryCount异步执行。写入前会先做快照预算校验validateMemorySnapshotBudget历史过大则skipped与容量预留receipt 队列满则rejected在 worker 阻塞时被拒绝的快照不会占用容量。8.2 身份与自动存储的逐级裁决responseMemoryAutoStoreEnabled体现了“服务端策略先于客户端选择”的顺序客户端可以选择退出但不能撤销决策级的显式禁止裁决链依次为内存配置 → ResponseObjectState → 请求头request auto-store→ 决策插件配置 → 全局Memory.AutoStore。同时缺少user_id的记忆写入在检查或复制会话内容之前就会被拒绝memory_info_unavailable这正是“要求稳定用户身份”的实现。8.3 嵌入模型身份绑定升级嵌入模型需重启模型运行时。来自模型运行时包括 Vela Embedding的嵌入Router 会将记忆与实际加载的模型、分词器、推理设置及向量维度绑定变更这些设置会创建独立的物理集合/索引与独立的 Redis 热缓存相同向量表示重启则复用既有存储逻辑名称保持不变。早期无身份标记的集合会保留但不会被自动接管——相同向量维度不代表两个模型的嵌入兼容。管理 API 没有记忆导入/批量导出端点新模型集合从空开始随流量重新积累。远程嵌入端点无法证明向量由哪个模型生成因此记忆继续使用配置的集合/索引Router 启动时记录警告修改endpoint.model后应手动将记忆指向新集合/索引。9. 可观测性记忆链路暴露有界的 Prometheus 指标见 src/semantic-router/pkg/memory/metrics.gollm_memory_retrieval_total检索量计数器带backend与status标签hit、miss、errorllm_memory_retrieval_latency_seconds/llm_memory_retrieval_results检索延迟与结果数直方图不带 per-user 标签llm_memory_extraction_total、llm_memory_extraction_latency_seconds、llm_memory_extraction_facts_count提取环节计数llm_memory_store_operations_total、llm_memory_store_size、llm_memory_cache_hits_total存储与热缓存观测。延迟与结果数直方图刻意不携带用户维度标签避免通过指标泄露用户级行为。若从带user_id标签的旧版本升级需参考 Router Memory Prometheus label 发布说明。10. 评估方法与待决问题10.1 评估检索与保存分开衡量检索相关性和跨用户隔离遗漏、无关和重复记忆的比率对持久事实和偏好的提取精确率纠正和删除行为增加的延迟和上下文 token身份或存储不可用时的优雅降级。在使用个人数据测试之前应使用合成租户和可检查记录synthetic tenants and inspectable records。10.2 待决问题每种协议的权威身份来源是什么写入是否需要显式用户同意或路由级选择加入冲突记忆如何解决哪些记录类型默认需要过期多租户生产使用前需要哪种隔离原语这些开放问题也解释了提案为何刻意保持“概念验证”状态它验证的是检索 → 注入 → 提取 → 存储这个循环本身而不主张生产级隔离、可靠的会话结束检测、自主反思或所提取记忆的事实正确性。11. 范围与结论该概念验证验证了检索 → 注入 → 提取 → 存储闭环的可行性与产品边界已实现的配置与行为以记忆插件指南为事实来源本提案不用于直接部署。与本主题相关的补充材料还包括路由学习中的记忆与回放讲述热路径学习状态、路由回放与离线配方学习的分层。实践建议总结如下先按global.stores.memory选型并校准后端Milvus/Valkey/Qdrant与阈值通过routing.decisions[].plugins按路由决定retrieval_limit与auto_store为中文/日文/韩文流量重估max_inject_tokens用GET/DELETE /api/v1/storage/memories向用户提供检查与删除入口用llm_memory_*指标持续监控检索命中率、提取率与存储增长并始终牢记“相似度分数不是披露记录的许可”。赞分享后端API网关模型推理服务AI Agent【免费下载链接】semantic-routerAn open, programmable decision layer for models and compute.项目地址https://gitcode.com/gh_mirrors/sem/semantic-router点击查看免费下载相关推荐Semantic Router Agentic Memory 提案解读检索→注入→提取→存储的持久记忆闭环设计与落地对照Semantic Router Agentic Memory 提案解读检索→注入→提取→存储的持久记忆闭环设计与落地对照 本篇技术指南围绕 semantic后端API网关模型推理服务AI AgentSemantic Router 智能体记忆Agentic Memory设计全解跨会话检索、LLM 提取与优雅降级实践Semantic Router 智能体记忆Agentic Memory设计全解跨会话检索、LLM 提取与优雅降级实践 Semantic Router 的智后端API网关模型推理服务AI Agentsemantic-router Memory 插件实战会话记忆的检索、自动存储与注入配置指南semantic router Memory 插件实战会话记忆的检索、自动存储与注入配置指南 本指南围绕 semantic router 的 memory 路后端API网关模型推理服务AI Agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考