{"title":"记忆最佳实践","slug":"memory-best-practices","category":"guides","summary":"如何结构化记忆以实现高效回放 — 分类、键、标签、优先级。","audience":["human","llm"],"tags":["guide","memory","best-practices","patterns"],"difficulty":"intermediate","updated":"2026-06-27","word_count":292,"read_minutes":1,"lang":"zh","translated":true,"requested_lang":"zh","content_markdown":"\n# 记忆最佳实践\n\n记忆的结构决定了它的实用价值。本指南涵盖记忆的分类、打标签与优先级模式，让 LLM 能在正确时间回放出正确信息。\n\n## 分类：选择最具体的\n\n| 分类 | 用于 | 示例 |\n|----------|---------|---------|\n| `identity` | 用户名、角色、联系方式 | `\"user_name\": \"Michael Schäfer\"` |\n| `preference` | 喜好、厌恶、工作风格 | `\"communication\": \"Prefers concise responses\"` |\n| `fact` | 可验证的事实 | `\"office_location\": \"Berlin, Germany\"` |\n| `project` | 项目状态、决策 | `\"project_synapse\": \"v1.5.0 deployed\"` |\n| `skill` | 用户的技能 | `\"skill_python\": \"Advanced, 10+ years\"` |\n| `mistake` | 要避免的过往错误 | `\"mistake_npm_version\": \"Always bump version\"` |\n| `context` | 与会话相关的上下文 | `\"current_focus\": \"Working on docs system\"` |\n| `note` | 其他备注 | `\"note_idea\": \"Try Redis for caching\"` |\n\n> [!TIP]\n> 拿不准时，可验证信息用 `fact`，其他都用 `note`。\n> 不要过度分类 — 清晰的 `fact` 比含糊的 `context` 更好。\n\n## Key：有意义的标识符\n\n`key` 字段是记忆的标识符。使用有意义且稳定的 key：\n\n**好 key：**\n- `user_name`\n- `project_synapse_status`\n- `preference_communication_style`\n- `mistake_npm_version_bump`\n\n**坏 key：**\n- `mem_001`（无意义）\n- `temp`（不具描述性）\n- `2026-06-27-note`（日期对回放无帮助）\n\n### Key 命名规范\n\n- `snake_case`（小写加下划线）\n- 以分类为前缀：`preference_*`、`project_*`、`mistake_*`\n- 使用描述性名词，而非动词\n- 长度控制在 50 字符以内\n\n## Tags：用于搜索与过滤\n\n标签可加速过滤与搜索。每条记忆加 2-5 个标签：\n\n```json\n{\n  \"category\": \"project\",\n  \"key\": \"project_synapse_status\",\n  \"content\": \"Synapse v1.5.0 deployed. Next: v1.6.0 with docs system.\",\n  \"tags\": [\"synapse\", \"deployment\", \"status\", \"v1.5.0\"]\n}\n```\n\n### 标签模式\n\n- **项目名**：`synapse`、`synapse-mcp`、`synapse-chat`\n- **主题**：`deployment`、`ci`、`database`、`auth`\n- **状态**：`active`、`completed`、`blocked`\n- **优先级指示**：`urgent`、`long-term`\n\n> [!NOTE]\n> 标签不区分大小写。请使用小写以保持一致。\n\n## 优先级：实事求是\n\n| 优先级 | 用于 | 占比 |\n|----------|---------|---------------|\n| `critical` | 用户身份、法律信息、不可逆决策 | ~5% |\n| `high` | 进行中的项目、重要偏好 | ~20% |\n| `normal` | 大多数事实、备注、上下文 | ~65% |\n| `low` | 临时、知道就好的信息 | ~10% |\n\n> [!WARNING]\n> 不要把所有记忆都标为 `critical`。如果一切都是 critical，那就什么都不是。\n> 把 `critical` 留给那些一旦被遗忘就会造成实际伤害的内容。\n\n## 何时存储、何时不存储\n\n### 始终存储\n\n- 用户身份（姓名、邮箱、角色）\n- 长期偏好\n- 项目决策与理由\n- 过往错误与教训\n- 对用户做出的承诺\n\n### 不要存储\n\n- 临时状态（改用变量）\n- 逐字对话历史（聊天系统会处理）\n- 敏感数据（密码、API key）\n- 易推导的事实（当前日期、文件内容）\n- 短暂上下文（用 `context` 分类 + low 优先级）\n\n## 更新记忆\n\n用相同的 `category` + `key` 发起 `POST /memory` 会更新已有记忆：\n\n```python\n# 初始存储\nstore(\"project\", \"project_synapse_status\", \"v1.4.0 deployed\", priority=\"high\")\n\n# 后续：用相同 key 更新\nstore(\"project\", \"project_synapse_status\", \"v1.5.0 deployed. CI green.\", priority=\"high\")\n```\n\n> [!TIP]\n> 使用稳定的 key，这样你可以更新而不创建重复。LLM 应该在信息变化时重新 POST 相同的 key，而不是创建新记忆。\n\n## 记忆生命周期\n\n```\n创建 → 活跃 → 陈旧 → 归档 → 删除\n```\n\n- **创建**：POST /memory，带上完整上下文\n- **活跃**：频繁回放，按需更新\n- **陈旧**：仍相关但不再活跃使用（降低优先级？）\n- **归档**：设为 `low` 优先级，保留供历史参考\n- **删除**：不再相关时 DELETE /memory/:id\n\n### 定期清理\n\n```python\n# 查找 90 天未更新的记忆\nold_memories = requests.get(\n    f\"{URL}/memory/search?q=*\",\n    headers={\"Authorization\": f\"Bearer {KEY}\"}\n)\n\nfor mem in old_memories[\"results\"]:\n    if is_stale(mem, days=90):\n        # 删除或降低优先级\n        if is_obsolete(mem):\n            delete_memory(mem[\"id\"])\n        else:\n            update_memory(mem[\"id\"], priority=\"low\")\n```\n\n## 模式：记忆继承\n\n对于层级上下文（项目 → 子项目 → 任务）：\n\n```python\n# 父项目\nstore(\"project\", \"project_synapse\", \"Main Synapse project\", \n      tags=[\"synapse\", \"parent\"], priority=\"high\")\n\n# 子项目（标签关联父项目）\nstore(\"project\", \"project_synapse_docs\", \"Docs system for Synapse\",\n      tags=[\"synapse\", \"docs\", \"synapse-parent\"], priority=\"high\")\n\n# 具体任务（标签关联子项目）\nstore(\"project\", \"task_docs_loader\", \"Implement docs-loader.ts\",\n      tags=[\"synapse\", \"docs\", \"task\"], priority=\"normal\")\n```\n\nLLM 之后可搜索 `q=synapse+docs` 找到所有相关记忆。\n\n## 模式：决策日志\n\n把决策与理由一起存储，这样 LLM 不会重新质疑：\n\n```python\nstore(\"fact\", \"decision_postgres_over_sqlite\",\n      \"Chose PostgreSQL over SQLite for production. Reason: concurrent writes, \"\n      \"FTS5 native support, better backup story. Date: 2026-06-15. Decided by: Michael.\",\n      tags=[\"decision\", \"database\", \"postgres\", \"sqlite\"],\n      priority=\"high\")\n```\n\n## 模式：错误规避\n\n把错误与具体的规避指令一起存储：\n\n```python\nstore(\"mistake\", \"mistake_forget_version_bump\",\n      \"Forgot to bump package.json version after changes. npm publish failed. \"\n      \"FIX: Always run `npm version patch` before pushing. \"\n      \"CI fails with 'version already exists' if you forget.\",\n      tags=[\"npm\", \"ci\", \"publish\", \"version\"],\n      priority=\"high\")\n```\n\n## 应避免的反模式\n\n> [!WARNING]\n> - **存储对话日志** — 聊天系统会处理\n> - **存储整个文件** — 用脚本存储或外部存储\n> - **存储临时状态** — 用变量\n> - **存储密钥** — 用环境变量\n> - **重复记忆** — 用稳定的 key\n> - **过度打标签** — 每条记忆 2-5 个标签最理想\n> - **一切都是 critical** — 优先级要实事求是\n\n## 下一步\n\n- [Memory API](/docs/api/memory)\n- [持久化 LLM Agent](/docs/guides/persistent-llm-agent)\n- [记忆打标签策略](/docs/llm-cookbook/memory-tagging-strategy)\n","content_html":"<h1>记忆最佳实践</h1>\n<p>记忆的结构决定了它的实用价值。本指南涵盖记忆的分类、打标签与优先级模式，让 LLM 能在正确时间回放出正确信息。</p>\n<h2>分类：选择最具体的</h2>\n<table>\n<thead>\n<tr>\n<th>分类</th>\n<th>用于</th>\n<th>示例</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>identity</code></td>\n<td>用户名、角色、联系方式</td>\n<td><code>&quot;user_name&quot;: &quot;Michael Schäfer&quot;</code></td>\n</tr>\n<tr>\n<td><code>preference</code></td>\n<td>喜好、厌恶、工作风格</td>\n<td><code>&quot;communication&quot;: &quot;Prefers concise responses&quot;</code></td>\n</tr>\n<tr>\n<td><code>fact</code></td>\n<td>可验证的事实</td>\n<td><code>&quot;office_location&quot;: &quot;Berlin, Germany&quot;</code></td>\n</tr>\n<tr>\n<td><code>project</code></td>\n<td>项目状态、决策</td>\n<td><code>&quot;project_synapse&quot;: &quot;v1.5.0 deployed&quot;</code></td>\n</tr>\n<tr>\n<td><code>skill</code></td>\n<td>用户的技能</td>\n<td><code>&quot;skill_python&quot;: &quot;Advanced, 10+ years&quot;</code></td>\n</tr>\n<tr>\n<td><code>mistake</code></td>\n<td>要避免的过往错误</td>\n<td><code>&quot;mistake_npm_version&quot;: &quot;Always bump version&quot;</code></td>\n</tr>\n<tr>\n<td><code>context</code></td>\n<td>与会话相关的上下文</td>\n<td><code>&quot;current_focus&quot;: &quot;Working on docs system&quot;</code></td>\n</tr>\n<tr>\n<td><code>note</code></td>\n<td>其他备注</td>\n<td><code>&quot;note_idea&quot;: &quot;Try Redis for caching&quot;</code></td>\n</tr>\n</tbody></table>\n<div class=\"callout callout-ok\">拿不准时，可验证信息用 `fact`，其他都用 `note`。\n不要过度分类 — 清晰的 `fact` 比含糊的 `context` 更好。</div><h2>Key：有意义的标识符</h2>\n<p><code>key</code> 字段是记忆的标识符。使用有意义且稳定的 key：</p>\n<p><strong>好 key：</strong></p>\n<ul>\n<li><code>user_name</code></li>\n<li><code>project_synapse_status</code></li>\n<li><code>preference_communication_style</code></li>\n<li><code>mistake_npm_version_bump</code></li>\n</ul>\n<p><strong>坏 key：</strong></p>\n<ul>\n<li><code>mem_001</code>（无意义）</li>\n<li><code>temp</code>（不具描述性）</li>\n<li><code>2026-06-27-note</code>（日期对回放无帮助）</li>\n</ul>\n<h3>Key 命名规范</h3>\n<ul>\n<li><code>snake_case</code>（小写加下划线）</li>\n<li>以分类为前缀：<code>preference_*</code>、<code>project_*</code>、<code>mistake_*</code></li>\n<li>使用描述性名词，而非动词</li>\n<li>长度控制在 50 字符以内</li>\n</ul>\n<h2>Tags：用于搜索与过滤</h2>\n<p>标签可加速过滤与搜索。每条记忆加 2-5 个标签：</p>\n<pre><code class=\"hljs language-json\"><span class=\"hljs-punctuation\">{</span>\n  <span class=\"hljs-attr\">&quot;category&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project&quot;</span><span class=\"hljs-punctuation\">,</span>\n  <span class=\"hljs-attr\">&quot;key&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;project_synapse_status&quot;</span><span class=\"hljs-punctuation\">,</span>\n  <span class=\"hljs-attr\">&quot;content&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-string\">&quot;Synapse v1.5.0 deployed. Next: v1.6.0 with docs system.&quot;</span><span class=\"hljs-punctuation\">,</span>\n  <span class=\"hljs-attr\">&quot;tags&quot;</span><span class=\"hljs-punctuation\">:</span> <span class=\"hljs-punctuation\">[</span><span class=\"hljs-string\">&quot;synapse&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;deployment&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;status&quot;</span><span class=\"hljs-punctuation\">,</span> <span class=\"hljs-string\">&quot;v1.5.0&quot;</span><span class=\"hljs-punctuation\">]</span>\n<span class=\"hljs-punctuation\">}</span></code></pre><h3>标签模式</h3>\n<ul>\n<li><strong>项目名</strong>：<code>synapse</code>、<code>synapse-mcp</code>、<code>synapse-chat</code></li>\n<li><strong>主题</strong>：<code>deployment</code>、<code>ci</code>、<code>database</code>、<code>auth</code></li>\n<li><strong>状态</strong>：<code>active</code>、<code>completed</code>、<code>blocked</code></li>\n<li><strong>优先级指示</strong>：<code>urgent</code>、<code>long-term</code></li>\n</ul>\n<div class=\"callout callout-note\">标签不区分大小写。请使用小写以保持一致。</div><h2>优先级：实事求是</h2>\n<table>\n<thead>\n<tr>\n<th>优先级</th>\n<th>用于</th>\n<th>占比</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>critical</code></td>\n<td>用户身份、法律信息、不可逆决策</td>\n<td>~5%</td>\n</tr>\n<tr>\n<td><code>high</code></td>\n<td>进行中的项目、重要偏好</td>\n<td>~20%</td>\n</tr>\n<tr>\n<td><code>normal</code></td>\n<td>大多数事实、备注、上下文</td>\n<td>~65%</td>\n</tr>\n<tr>\n<td><code>low</code></td>\n<td>临时、知道就好的信息</td>\n<td>~10%</td>\n</tr>\n</tbody></table>\n<div class=\"callout callout-warn\">不要把所有记忆都标为 `critical`。如果一切都是 critical，那就什么都不是。\n把 `critical` 留给那些一旦被遗忘就会造成实际伤害的内容。</div><h2>何时存储、何时不存储</h2>\n<h3>始终存储</h3>\n<ul>\n<li>用户身份（姓名、邮箱、角色）</li>\n<li>长期偏好</li>\n<li>项目决策与理由</li>\n<li>过往错误与教训</li>\n<li>对用户做出的承诺</li>\n</ul>\n<h3>不要存储</h3>\n<ul>\n<li>临时状态（改用变量）</li>\n<li>逐字对话历史（聊天系统会处理）</li>\n<li>敏感数据（密码、API key）</li>\n<li>易推导的事实（当前日期、文件内容）</li>\n<li>短暂上下文（用 <code>context</code> 分类 + low 优先级）</li>\n</ul>\n<h2>更新记忆</h2>\n<p>用相同的 <code>category</code> + <code>key</code> 发起 <code>POST /memory</code> 会更新已有记忆：</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># 初始存储</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse_status&quot;</span>, <span class=\"hljs-string\">&quot;v1.4.0 deployed&quot;</span>, priority=<span class=\"hljs-string\">&quot;high&quot;</span>)\n\n<span class=\"hljs-comment\"># 后续：用相同 key 更新</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse_status&quot;</span>, <span class=\"hljs-string\">&quot;v1.5.0 deployed. CI green.&quot;</span>, priority=<span class=\"hljs-string\">&quot;high&quot;</span>)</code></pre><div class=\"callout callout-ok\">使用稳定的 key，这样你可以更新而不创建重复。LLM 应该在信息变化时重新 POST 相同的 key，而不是创建新记忆。</div><h2>记忆生命周期</h2>\n<pre><code class=\"hljs language-plaintext\">创建 → 活跃 → 陈旧 → 归档 → 删除</code></pre><ul>\n<li><strong>创建</strong>：POST /memory，带上完整上下文</li>\n<li><strong>活跃</strong>：频繁回放，按需更新</li>\n<li><strong>陈旧</strong>：仍相关但不再活跃使用（降低优先级？）</li>\n<li><strong>归档</strong>：设为 <code>low</code> 优先级，保留供历史参考</li>\n<li><strong>删除</strong>：不再相关时 DELETE /memory/:id</li>\n</ul>\n<h3>定期清理</h3>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># 查找 90 天未更新的记忆</span>\nold_memories = requests.get(\n    <span class=\"hljs-string\">f&quot;<span class=\"hljs-subst\">{URL}</span>/memory/search?q=*&quot;</span>,\n    headers={<span class=\"hljs-string\">&quot;Authorization&quot;</span>: <span class=\"hljs-string\">f&quot;Bearer <span class=\"hljs-subst\">{KEY}</span>&quot;</span>}\n)\n\n<span class=\"hljs-keyword\">for</span> mem <span class=\"hljs-keyword\">in</span> old_memories[<span class=\"hljs-string\">&quot;results&quot;</span>]:\n    <span class=\"hljs-keyword\">if</span> is_stale(mem, days=<span class=\"hljs-number\">90</span>):\n        <span class=\"hljs-comment\"># 删除或降低优先级</span>\n        <span class=\"hljs-keyword\">if</span> is_obsolete(mem):\n            delete_memory(mem[<span class=\"hljs-string\">&quot;id&quot;</span>])\n        <span class=\"hljs-keyword\">else</span>:\n            update_memory(mem[<span class=\"hljs-string\">&quot;id&quot;</span>], priority=<span class=\"hljs-string\">&quot;low&quot;</span>)</code></pre><h2>模式：记忆继承</h2>\n<p>对于层级上下文（项目 → 子项目 → 任务）：</p>\n<pre><code class=\"hljs language-python\"><span class=\"hljs-comment\"># 父项目</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse&quot;</span>, <span class=\"hljs-string\">&quot;Main Synapse project&quot;</span>, \n      tags=[<span class=\"hljs-string\">&quot;synapse&quot;</span>, <span class=\"hljs-string\">&quot;parent&quot;</span>], priority=<span class=\"hljs-string\">&quot;high&quot;</span>)\n\n<span class=\"hljs-comment\"># 子项目（标签关联父项目）</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;project_synapse_docs&quot;</span>, <span class=\"hljs-string\">&quot;Docs system for Synapse&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;synapse&quot;</span>, <span class=\"hljs-string\">&quot;docs&quot;</span>, <span class=\"hljs-string\">&quot;synapse-parent&quot;</span>], priority=<span class=\"hljs-string\">&quot;high&quot;</span>)\n\n<span class=\"hljs-comment\"># 具体任务（标签关联子项目）</span>\nstore(<span class=\"hljs-string\">&quot;project&quot;</span>, <span class=\"hljs-string\">&quot;task_docs_loader&quot;</span>, <span class=\"hljs-string\">&quot;Implement docs-loader.ts&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;synapse&quot;</span>, <span class=\"hljs-string\">&quot;docs&quot;</span>, <span class=\"hljs-string\">&quot;task&quot;</span>], priority=<span class=\"hljs-string\">&quot;normal&quot;</span>)</code></pre><p>LLM 之后可搜索 <code>q=synapse+docs</code> 找到所有相关记忆。</p>\n<h2>模式：决策日志</h2>\n<p>把决策与理由一起存储，这样 LLM 不会重新质疑：</p>\n<pre><code class=\"hljs language-python\">store(<span class=\"hljs-string\">&quot;fact&quot;</span>, <span class=\"hljs-string\">&quot;decision_postgres_over_sqlite&quot;</span>,\n      <span class=\"hljs-string\">&quot;Chose PostgreSQL over SQLite for production. Reason: concurrent writes, &quot;</span>\n      <span class=\"hljs-string\">&quot;FTS5 native support, better backup story. Date: 2026-06-15. Decided by: Michael.&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;decision&quot;</span>, <span class=\"hljs-string\">&quot;database&quot;</span>, <span class=\"hljs-string\">&quot;postgres&quot;</span>, <span class=\"hljs-string\">&quot;sqlite&quot;</span>],\n      priority=<span class=\"hljs-string\">&quot;high&quot;</span>)</code></pre><h2>模式：错误规避</h2>\n<p>把错误与具体的规避指令一起存储：</p>\n<pre><code class=\"hljs language-python\">store(<span class=\"hljs-string\">&quot;mistake&quot;</span>, <span class=\"hljs-string\">&quot;mistake_forget_version_bump&quot;</span>,\n      <span class=\"hljs-string\">&quot;Forgot to bump package.json version after changes. npm publish failed. &quot;</span>\n      <span class=\"hljs-string\">&quot;FIX: Always run `npm version patch` before pushing. &quot;</span>\n      <span class=\"hljs-string\">&quot;CI fails with &#x27;version already exists&#x27; if you forget.&quot;</span>,\n      tags=[<span class=\"hljs-string\">&quot;npm&quot;</span>, <span class=\"hljs-string\">&quot;ci&quot;</span>, <span class=\"hljs-string\">&quot;publish&quot;</span>, <span class=\"hljs-string\">&quot;version&quot;</span>],\n      priority=<span class=\"hljs-string\">&quot;high&quot;</span>)</code></pre><h2>应避免的反模式</h2>\n<div class=\"callout callout-warn\"></div><h2>下一步</h2>\n<ul>\n<li><a href=\"/docs/api/memory\">Memory API</a></li>\n<li><a href=\"/docs/guides/persistent-llm-agent\">持久化 LLM Agent</a></li>\n<li><a href=\"/docs/llm-cookbook/memory-tagging-strategy\">记忆打标签策略</a></li>\n</ul>\n","urls":{"html":"/docs/guides/memory-best-practices","text":"/docs/guides/memory-best-practices?format=text","json":"/docs/guides/memory-best-practices?format=json","llm":"/docs/guides/memory-best-practices?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}