资讯动态

INMS 论文笔记:给 LLM Agents 装上 Memory Sharing 的配置骨架

发布时间:2026/9/29 2:23:25 来源:尧图企业网站定制
1. 多智能体协作里记忆为什么总是各存各的如果你正在做多智能体Multi-Agent系统大概率遇到过这个场景一个 Agent 负责查资料一个 Agent 负责写代码还有一个负责跑测试。查资料的 Agent 已经确认了某个 API 的返回格式写代码的 Agent 却还在按旧文档瞎猜测试 Agent 发现了一个边界条件写代码的 Agent 下一轮又踩进同一个坑。三个 Agent 各自维护一份上下文谁也不服谁。这就是 INMSMemory Sharing for Large Language Model based Agents这篇论文想解决的核心问题。它讨论的不是“怎么让单个 Agent 更聪明”而是“怎么让多个 Agent 在共享记忆的前提下协同工作”。论文里把记忆分成几个层次短期工作记忆、长期经验记忆、以及跨 Agent 可共享的公共记忆。关键点在于共享不是简单地把所有历史塞进一个池子而是要有选择地写入、有策略地读取、有机制地淘汰。落到工程上这件事的难点不在算法而在配置。你需要一套能跑起来的骨架记忆存储用什么、共享范围怎么划、读写权限怎么控、模型调用走哪个入口。我试过用一套统一的 Key 接入多个 Agent 的模型调用配合本地记忆存储能把整个链路跑通。下面就把这套配置骨架拆开讲包括 settings.json 和 config.toml 两种格式以及怎么验证记忆读写和共享是否真的生效。2. TaoToken 前置统一 Key 接入多 Agent 模型调用在 INMS 的落地场景里多个 Agent 可能调用不同的模型——有的用 Claude 做推理有的用 GPT 做总结有的用轻量模型做路由。如果每个 Agent 都单独配一套 Key 和 endpoint管理成本会很高而且共享记忆的读写日志也没法统一追踪。TaoToken 在这里的角色是提供一个统一的 API 入口。你可以在官网注册后拿到一个 Key然后在各个 Agent 的配置里都指向同一个 base_url。这样做的直接好处是记忆共享层只需要记录一次调用日志就能覆盖所有 Agent 的模型交互切换模型时也不用改多个配置文件。具体操作路径先访问官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 了解接入方式然后到 API Keys 页面生成一个 Key。这个 Key 会用在后面的 settings.json 和 config.toml 里。注意API 的基础地址是 https://taotoken.net/api不要加 UTM 参数那是给网页链接用的。如果你后面要做长期编码类的 Agent比如让多个 Agent 轮流改同一个仓库可以关注 Coding Plan 页面那里有更适合持续调用的配置方案。但本篇的重点是记忆共享骨架所以先把基础接入跑通。3. 可复制配置settings.json 与 config.toml 骨架3.1 settings.json面向 Claude Code 风格的 Agent 配置假设你的多 Agent 系统里有一个主 Agent 负责调度两个子 Agent 分别负责检索和编码。settings.json 可以这样写{ agent_id: orchestrator, model: { provider: taotoken, base_url: https://taotoken.net/api, api_key: sk-your-taotoken-key, model_name: claude-3-5-sonnet, max_tokens: 4096, temperature: 0.3 }, memory: { shared: true, store_type: sqlite, store_path: ./memory/shared_memory.db, namespace: inms_project_alpha, read_scope: [orchestrator, retriever, coder], write_scope: [orchestrator, retriever, coder], ttl_seconds: 86400, max_entries: 5000 }, tools: { shell: true, file_read: true, file_write: true, memory_read: true, memory_write: true } }这里几个参数值得展开说。namespace是记忆隔离的关键不同项目用不同 namespace避免串数据。read_scope和write_scope控制哪些 Agent 能读、哪些能写。INMS 论文里强调共享记忆要有权限分层不能让所有 Agent 无差别地写否则公共记忆会被低质量信息污染。ttl_seconds是过期时间超过 24 小时的短期记忆自动清理模拟人类的工作记忆衰减。3.2 config.toml面向通用 Agent 框架的配置如果你的框架用 TOML 格式等价配置如下[agent] id orchestrator role scheduler [model] provider taotoken base_url https://taotoken.net/api api_key sk-your-taotoken-key model_name claude-3-5-sonnet max_tokens 4096 temperature 0.3 [memory] shared true store_type sqlite store_path ./memory/shared_memory.db namespace inms_project_alpha read_scope [orchestrator, retriever, coder] write_scope [orchestrator, retriever, coder] ttl_seconds 86400 max_entries 5000 [memory.retrieval] top_k 5 similarity_threshold 0.75 rerank true [tools] shell true file_read true file_write true memory_read true memory_write true注意[memory.retrieval]这一段它对应 INMS 里的“记忆读取策略”。top_k控制每次召回多少条记忆similarity_threshold是相似度阈值低于这个值的记忆不会被注入 Prompt。rerank开启后会对召回结果做二次排序优先选最近使用过的、或者被多个 Agent 引用过的记忆。3.3 记忆共享层的核心逻辑配置只是骨架真正让共享生效的是记忆读写逻辑。下面这段 Python 伪代码展示了 Agent 如何在每轮循环里读写共享记忆import sqlite3 import json from datetime import datetime, timedelta class SharedMemory: def __init__(self, db_path, namespace, agent_id): self.conn sqlite3.connect(db_path) self.namespace namespace self.agent_id agent_id self._init_table() def _init_table(self): self.conn.execute( CREATE TABLE IF NOT EXISTS memory ( id INTEGER PRIMARY KEY AUTOINCREMENT, namespace TEXT, agent_id TEXT, content TEXT, embedding BLOB, created_at TIMESTAMP, last_accessed TIMESTAMP, access_count INTEGER DEFAULT 0 ) ) self.conn.commit() def write(self, content, embeddingNone): now datetime.now() self.conn.execute( INSERT INTO memory (namespace, agent_id, content, embedding, created_at, last_accessed) VALUES (?, ?, ?, ?, ?, ?), (self.namespace, self.agent_id, content, embedding, now, now) ) self.conn.commit() def read(self, query_embedding, top_k5, threshold0.75): cutoff datetime.now() - timedelta(seconds86400) rows self.conn.execute( SELECT id, content, embedding, last_accessed, access_count FROM memory WHERE namespace ? AND created_at ?, (self.namespace, cutoff) ).fetchall() scored [] for row in rows: sim cosine_similarity(query_embedding, row[2]) if sim threshold: scored.append((sim, row)) scored.sort(keylambda x: x[0], reverseTrue) results [] for sim, row in scored[:top_k]: self.conn.execute( UPDATE memory SET last_accessed ?, access_count access_count 1 WHERE id ?, (datetime.now(), row[0]) ) results.append(row[1]) self.conn.commit() return results这段代码的关键点写入时记录 agent_id读取时按 namespace 过滤并且更新 last_accessed 和 access_count。INMS 论文里提到共享记忆的淘汰策略应该结合“最近使用时间”和“被引用次数”这两个字段就是为淘汰准备的。4. 验证请求确认记忆读写与共享真的生效配置写好了怎么知道记忆共享真的在工作不能只看代码跑没跑通要做几个具体验证。4.1 验证模型调用是否走通先用一个最简单的请求确认 TaoToken 的 Key 和 base_url 没问题curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-your-taotoken-key \ -H Content-Type: application/json \ -d { model: claude-3-5-sonnet, messages: [{role: user, content: 回复 OK}], max_tokens: 10 }如果返回里有正常的 completion说明模型接入没问题。这一步是后面所有验证的前提。4.2 验证记忆写入让 Agent A 执行一个任务然后检查数据库里有没有新记录agent_a SharedMemory(./memory/shared_memory.db, inms_project_alpha, retriever) agent_a.write(API 返回格式为 JSON字段 data.items 是数组)然后查库sqlite3 ./memory/shared_memory.db SELECT agent_id, content FROM memory WHERE namespaceinms_project_alpha;应该能看到 retriever 写入的那条记录。4.3 验证记忆共享让 Agent B 读取同一个 namespace 的记忆agent_b SharedMemory(./memory/shared_memory.db, inms_project_alpha, coder) results agent_b.read(query_embedding, top_k3) print(results)如果 Agent B 能读到 Agent A 写入的内容说明共享生效。这里要注意query_embedding 需要和写入时的 embedding 用同一个模型生成否则相似度计算会不准。4.4 验证记忆是否真的影响了 Agent 行为最直接的验证方式让 Agent B 在不知道 API 格式的情况下写代码看它是否引用了共享记忆里的信息。比如prompt f 你是一个编码 Agent。当前任务解析 API 返回的数据。 以下是共享记忆中的相关信息 {chr(10).join(results)} 请写出解析代码。 response call_llm(prompt) print(response)如果输出里出现了data.items这样的字段名说明共享记忆被正确注入并影响了决策。5. 本篇常见错排查5.1 记忆写入成功但读取为空最常见的原因是 namespace 不一致。写入时用了inms_project_alpha读取时写成了inms_project_alpha末尾有空格或者大小写不同。SQLite 的字符串比较是大小写敏感的建议在代码里统一做一次strip().lower()。另一个原因是created_at过滤条件。如果写入时间超过了ttl_seconds读取时会被过滤掉。调试时先把 ttl 设大一点确认链路通了再调回来。5.2 相似度阈值设太高导致召回为空similarity_threshold设成 0.75 在某些 embedding 模型下可能偏高。不同模型的相似度分布不一样有的模型正常相关文本的余弦相似度只有 0.6 左右。建议先用一批已知相关的文本对跑一下看实际相似度落在什么区间再定阈值。5.3 多个 Agent 同时写入导致数据库锁SQLite 在并发写入时会锁库。如果多个 Agent 同时写可能出现database is locked错误。解决方案有两个一是改用 WAL 模式在连接时执行PRAGMA journal_modeWAL;二是把写入操作串行化用一个队列来管理。INMS 论文里也提到共享记忆的写入应该有一个协调者避免并发冲突。5.4 模型调用返回 401 或 403先检查 Key 有没有复制完整有没有多余空格。然后确认 base_url 是https://taotoken.net/api不要写成带 UTM 参数的网页地址。如果还是不行到 API Keys 页面重新生成一个 Key 试试。5.5 记忆内容太长导致 Prompt 超限top_k设太大或者单条记忆内容太长会把 Prompt 撑爆。建议在写入时就对内容做截断或摘要读取时控制总 token 数。可以在[memory.retrieval]里加一个max_total_tokens参数读取时累加计算超过就停止召回。6. 把共享记忆接进你的 Agent 循环INMS 的 Memory Sharing 机制落到工程上核心就是三件事统一模型接入、结构化记忆存储、可控的读写策略。上面给的 settings.json 和 config.toml 骨架可以直接复制到你的项目里改一下 namespace 和 store_path 就能跑。验证的时候不要只看代码有没有报错要实际检查数据库里的记录、检查 Agent 的输出有没有引用共享记忆。如果你后面要做更复杂的多 Agent 协作比如让 Agent 之间互相评审代码、共享测试结果可以到模型对话页面先手动试几轮感受一下不同模型在共享上下文下的表现差异。长期跑编码任务的话Coding Plan 里有更适合持续调用的配置。接入文档在 doc 页面API Keys 在 console 里管理。先把单机共享记忆跑通再扩展到多机分布式这条路会稳很多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑