mcpField
P
PADAM · NOCTURNE memory

PADAM · NOCTURNE memory

本地服务
aifa.works记忆与知识0今天更新

关于 PADAM · NOCTURNE memory

PADAM · NOCTURNE 是面向 AI 助手和 Agent 的本地优先持久记忆,存储在 SQLite 文件中。NOCTURNE 周期会整合并淡化记录;可选的 L3 锚定可验证历史,同时支持逐条遗忘。

主要功能

  1. 01将持久记忆存储在本地 SQLite 文件
  2. 02整合、合并并淡化记录
  3. 03按含义、词语和标识符搜索
  4. 04跟踪确认、反驳和版本
  5. 05可选加密并锚定至 Arweave 和 Solana

适用场景

  1. 01在连接 MCP 的多个 Agent 间共享持久记忆
  2. 02检索或查看过去的决定与对话
  3. 03遗忘单条记录并保留其他记忆

MCP 相关

MCP 服务提供 8 个工具,用于记忆搜索、写入、确认、反驳、时间线、统计、整合和导出,并通过 stdio 连接 MCP 客户端。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"maksimgalatin-padam-nocturne": {
"command": "uvx",
"args": [
"padam-nocturne"
],
"env": {
"PADAM_DB": "<PADAM_DB>",
"OLLAMA_URL": "<OLLAMA_URL>",
"PADAM_STRICT": "<PADAM_STRICT>"
}
}
}
}
启动命令uvx padam-nocturne
需要配置的环境变量
PADAM_DBPath to the SQLite memory file. Default: ~/.padam/memory.db
OLLAMA_URLLocal Ollama address for embeddings. Without it a built-in method is used.
PADAM_STRICT1 turns on every guard at once: each agent write waits for the owner's review, and switches that weaken protection are ignored.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypipadam-nocturne0.4.14

工具

8

收录的工具列表 · 更新于 今天

参数类型必填说明
kindenum否限定为一种记录类型preference | identity | decision | correction | fact | state | event
as_ofstring否将记忆搜索限定为此时点的状态:'2026-10-01'(UTC 当日结束时)或 '2026-10-01T12:00:00Z'。之后被替换的记录也会包含在内,并会标记出来。
limitinteger否
querystring是要查找的内容,以自然语言描述
scopestring否记忆范围,例如 'project:code'
scopesarray否同时搜索多个范围(例如工作和家庭),而非仅搜索一个;每条记录都会显示其范围。除非你提出要求,否则不会混合不同范围。
compactboolean否缩短每条记录(保留当事人的原话,精简助手的回复),以便容纳更多记录

详细介绍

PADAM · NOCTURNE

为 AI Agent 提供会休眠、诚实遗忘且永远可验证的记忆

tests M8ven Score DOI license python MCP PyPI

安全审查人员: 请从 docs/SECURITY_REVIEW.md 开始了解我们所作的声明、每一轮红队测试及其封存测试集、仍可能通过的情况,以及一项十分钟检查。

PADAM 是一款本地优先的持久记忆工具,面向 AI 助手和 Agent。它以一个 SQLite 文件的形式存储在你的设备上,可接入任何 MCP 客户端(Claude Code、Claude Desktop、Cursor、VS Code),也可通过 CLI 和简易 REST API 接入你自己的代码。

NOCTURNE 是它的整合周期——一种“睡眠”,将原始的事件流转化为持久记忆:保留重要内容,归纳反复出现的内容,让其余内容逐渐淡去,同时避免罕见的戏剧性事件占据记忆。

L3 是可选的永恒层。它将记忆锚定到 Arweave(加密数据包)和 Solana(Memo 中的 Merkle 根),让任何人都能验证记忆从未被改写,同时任何单条记录仍可被永久遗忘。

隶属 CODE Eternal · 项目页面:aifa.works/nocturne · 规范:English · Русский · README 俄语版:README.ru.md


目录


存在的意义

如今,Agent 的记忆大多只会不断累积。一个月后,记忆中已有数千条记录;旧决策与新决策相互冲突,Agent 还会根据早已被弃用的内容作答。错误但不断被检索到的事实,看起来和刚写下时一样新鲜。当用户要求遗忘时,通常得到的答复要么是“我们做不到——它还在日志里”,要么是“我们已删除所有内容”。

NOCTURNE 会像大脑一样在夜间处理记忆:保留重要内容,归纳反复出现的内容,让其余内容逐渐淡去——并如实记录每一次变更。L3 则带来了私有数据库无法提供的能力:任何人都能验证历史记录事后未被改写。

三个与众不同的理念

  1. 四种限制器,防止“记忆里只有灾难”。 优先回放会过度采样罕见的剧烈事件,因此记忆会逐渐偏向灾难。NOCTURNE 会对稀有程度进行校正、限制剧烈事件的占比、削弱已回放过的内容,并为日常事件保留最低占比。在一个合成缓冲区(1,000 个普通事件 + 612 个灾难性事件)中,普通的优先采样会让灾难性事件占据 90.7 % 的概率质量——在一个包含 200 个事件的批次中约有 181 个;加上限制器后则为 200 个中有 50 个(占比为 0.25)。此数据于 2026 年 10 月 8 日从头重新测量;可通过 python -m pytest tests/test_nocturne.py -k nightmare -q 复现。合成测试——请根据自己的数据流调整限制。
  2. 每条记录有两个时钟。 last_seen_at 会在记录显示时更新,last_confirmed_at 只会在记录得到确认时更新——衰减根据后者计算。一个不断被检索到、却确信无误地记错的事实,不会一直“年轻”。
  3. 不会删除任何内容,但遗忘确实存在。 矛盾会创建一个新版本;旧版本会从搜索结果中移除,但仍保留在历史记录(timeline)中。forget 会擦除内容,并销毁记录自身的密钥,让它在 Arweave 上的密文永远变成无意义的数据,同时保持其余记忆完整。
常见的 Agent 记忆PADAM · NOCTURNE
增长无限制地累积每晚整合:保留、合并、淡化
罕见的戏剧性事件挤占日常事件限制占比 + 为日常事件保留最低占比
不断被检索到的错误事实保持新鲜逐渐淡化——从上次确认开始计算时间
矛盾覆盖旧内容或不断堆积创建新版本;旧版本保留在历史记录中
“忘记我”无法实现或只能全部遗忘只针对一条记录,通过销毁其自身密钥实现
存储位置供应商的云端由你拥有的一个 SQLite 文件
证明内容未被改写—Solana 上的 Merkle 根,Arweave 上的密文

工作原理

flowchart TB
    A[Agent / MCP client / CLI / REST] -->|write · search · confirm · refute| P[(PADAM<br/>SQLite)]
    A -->|log episodes| B[Episode buffer]
    B -->|python -m padam sleep| N[NOCTURNE<br/>consolidation]
    N -->|keep · merge · fade · version| P
    P -->|python -m padam l3| E[Per-record AES-256-GCM<br/>encryption]
    E -->|ciphertext bundle| AR[(Arweave)]
    E -->|Merkle root in a Memo| SOL[(Solana)]
    AR --> V[l3-verify:<br/>recompute root]
    SOL --> V

三个层级,一份记忆:

层级存储内容位置
L1 — 工作层当前对话和事件缓冲区Agent 内部及 PADAM 的缓冲区中
L2 — 整合层包含类型、重要性、两个时钟和版本的记录;文本、BM25、标识符,以及(可选的)神经嵌入一个本地 SQLite 文件
L3 — 永恒层(可选)加密的记录包和遗忘回执;每次锚定对应一个 Merkle 根Arweave + Solana

快速开始

git clone https://github.com/MaksimGalatin/padam-nocturne && cd padam-nocturne
pip install -e .            # numpy, requests, cryptography — Python 3.10+
python -m padam remember "Answer in Russian, no filler words" --kind preference --importance 1.0
python -m padam recall "which language to answer in" --explain
python -m padam log "today we debugged the billing"; python -m padam sleep
python -m padam stats

CLI 会根据系统语言以英语或俄语作答;使用 PADAM_LANG=en 或 PADAM_LANG=ru 可强制指定语言。MCP 的回答始终为英语——因为它们由模型读取。

为所有工具使用同一份记忆(MCP):

claude mcp add padam -- uvx padam-nocturne

从 PyPI 安装:pip install padam-nocturne。直接使用 GitHub 上的最新代码:uvx --from git+https://github.com/MaksimGalatin/padam-nocturne padam-nocturne。通过 pip install -e . 安装了?那么只需运行 claude mcp add padam -- padam-mcp。Claude Desktop、Cursor、VS Code、systemd 和 cron 的现成配置位于 integrations/。

LangChain。 通过 langchain-mcp-adapters,八种工具会变成带有各自参数架构的 LangChain 工具。python integrations/langchain_check.py 会从 PyPI 启动 uvx padam-nocturne,并在不使用大模型的情况下检查:工具列表、在围栏内通过搜索找到的写入内容、为所有者保留的注入指令,以及一个从未进入数据库文件的秘密(以原始字节读取)。在 adapters 0.3.2 和 langchain-core 1.7.7 下,0.4.8 的检查结果为 6 项中通过 6 项。有一点需要注意:适配器会将工具错误(isError: true,例如 limit must be at most 50)作为普通文本传给 Agent,而不是作为 ToolException。


将其接入你的 Agent——MCP、REST、CLI

MCP 服务(stdio)

padam-mcp(同一程序也会安装为 padam-nocturne;python -m padam.mcp_server 也可以运行)。服务在同一进程中支持两个时代的协议:2026-07-28 无需握手(每个请求的 _meta 中都包含版本和客户端能力、server/discover、每个结果中都有 resultType、带 ttlMs 和 cacheScope 的可缓存 tools/list,以及版本不匹配时返回包含支持版本的 -32022);还有通过 initialize 支持的旧版 2025-06-18、2025-03-26 和 2024-11-05。服务始终通过 stdio 使用 UTF-8 编码,包括在 cp1251/cp1252 编码的 Windows 控制台中;其 8 个工具均声明全部四种提示(只读、破坏性、幂等、开放世界),并会根据工具的架构检查每次调用。格式错误的输入(null、[]、单独一个数字)会返回 JSON-RPC -32600 错误,而不会导致进程崩溃。已于 2026 年 10 月 12 日使用官方 MCP Python SDK 客户端完成端到端验证。

工具功能
padam_search按含义、词语和标识符检索;对于跨多段对话的问题,使用 compact: true;使用 as_of: "2026-10-01" 查询记忆在当天的状态(之后被替换的记录也会包含在内并标记出来);使用 scopes: [...] 一次搜索多个范围。记录关于你是谁、在 PADAM 附近写入的内容,以及与另一条活跃记录相矛盾的记录,都会被标记
padam_write存储一条记录;如果存在相近记录,PADAM 会自行判断它是重复、补充还是矛盾。秘密内容会被遮盖;部分写入需要等待所有者确认(见下文)。derived_from: [ids] 会将结论关联到其来源,因此忘记某个来源时,也可以一并删除其结论
padam_confirm将检索到的记录标记为仍然有效——刷新该记录并提高其置信度(仅检索不会产生这些效果)
padam_refute将一条记录标记为不再有效——降低其置信度,但不刷新该记录;遭到足够多次反驳后,记录会被归档,但仍保留在历史记录中。身份和偏好记录永远不会通过此工具归档
padam_timeline查看一条记录的版本历史
padam_stats查看记忆状态:按状态和类型统计的记录数、等待审核的记录、是否需要整合、当前使用的嵌入后端,以及数据库所在位置
padam_sleep运行一次整合周期(通常按计划执行,不会手动调用)
padam_export将全部记忆导出为 JSON,或使用 limit 和 offset 导出单页内容

对于跨多段对话进行汇总的问题(“多少……”“总共多少……”),请调用 padam_search,将 limit 设为 25–30,并启用 compact: true:每条记录会保留当事人的原话,只保留助手回复的开头,这样相同空间内就能容纳更多零散事实。存储的记录不会改变;默认情况下,compact 处于关闭状态。

Agent 能做和不能做的事。 Agent 可以读取网页上的命令,并尝试通过你的记忆执行该命令,因此 MCP 服务会将其视为访客:

  • 搜索结果会用围栏标记为数据。 每个回答都会带有一个随机标记,存储的文本无法预先得知,因此记录无法假装结束数据块。看起来像命令的记录会被标记。
  • 绝不会存储机密信息。 API 密钥和令牌(OpenAI、Anthropic、xAI、GitHub、GitLab、AWS、Google、Stripe、Hugging Face、npm、Neon、Resend、Slack、Vercel、Telegram、JWT、bearer)、私钥、连接字符串中的密码或以文字说出的密码(“密码是……”、“пароль — …”)、钱包助记词(12 个或更多 BIP-39 单词)、密钥字节数组以及 JWK 的私有部分,都会在文本到达数据库或向量库之前替换为 [REDACTED:kind]。没有已知前缀的密钥会根据其特征捕获:字段名(如 client_secret 或 AccountKey)后面的值、长随机字符串、Basic 凭据、银行卡号(通过 Luhn 算法校验且带分组格式或含有单词“card”),以及其 CVV 或 PIN。链接、区块链地址和签名、哈希、UUID 和 Vercel ID 会保留原样。限制:不带字段名的纯十六进制字符串会被视为文件哈希,32–44 个字符的 base58 会被视为地址。设置 PADAM_KEEP_SECRETS=1 可关闭此功能。
  • 每条记录都会注明来源: user、agent 或 external,初始置信度分别为 1.0、0.8 和 0.6。Agent 重复自己的结论不会提高置信度,因此同一个错误不会因重复而变成“事实”。即使通过 MCP,origin: user 也不会提高置信度:该标签由 Agent 自行设置。
  • 有些写入需要等待你的决定。 在你通过 padam review、padam approve 或 padam reject 作出决定前,这些内容不会出现在搜索结果中:看起来像命令的写入;来自 Agent 或外部来源的任何身份或偏好记录,即便归入其他类别;会替换此类记录的写入;以及覆盖你自己的记录的外部来源。标记为 origin: user 的第一条身份或偏好记录会直接存储,以便全新的记忆能够了解你是谁;之后的每条记录都需要等待审核。待审核的记录不会通过搜索、导出或时间线显示给 Agent。设置 PADAM_MCP_TRUST_WRITES=1 可关闭审核。
  • 没有擦除工具。 忘记、批准和恢复功能只在控制台和 REST API 中提供。

识别命令只是辅助措施,并非保护机制。 过滤器可以识别英语、俄语、乌克兰语、白俄罗斯语、西班牙语、德语、法语、意大利语、葡萄牙语、中文、日语、韩语和阿拉伯语中的常见形式;它会检查形似字母、零宽字符、全角字母、用数字替代字母、逐字母拆分的单词,以及 base64、十六进制、URL 和 HTML 编码;它还可以识别角色扮演式接管(“你现在是 DAN”)、将资金转入钱包的指令,以及将记忆发送到其他地方的指令。但命令仍可能以任何预料不到的方式编写:在我们修复问题后编写的留出测试集上,对于我们从未见过的攻击类型,过滤器拦截了 14 条命令中的 6 条。因此,保护依赖于结构:记忆始终以数据围栏的形式返回给 Agent,关于你身份的记录无法由 Agent 更改,机密信息不会被存储;并且从 0.4.0 起,Agent 标记为 external 的每条写入,无论措辞如何,都需要等待你审核(设置 PADAM_HOLD_EXTERNAL=0 可关闭此功能)。该标签由 Agent 自行设置,因此即使 Agent 谎报文本来源,也只会得到字典和围栏。MCP 无法让服务检查 Agent 从何处获取文本;如果你需要不依赖此标签的边界,请设置 PADAM_MCP_REVIEW_ALL=1,让 Agent 的每条写入都等待你审核。

REST API

python -m padam api — 绑定到 127.0.0.1;如果未提供令牌(--token 或 PADAM_API_TOKEN),则拒绝在公共地址上启动。从 0.4.2 开始,它始终会有令牌:如果没有提供令牌,启动时会创建一个并打印出来;请将其作为 Authorization: Bearer <token> 发送。--no-token(仅限本地)可在不使用令牌的情况下连接,但此时每次写入都需要等待审核,且所有所有者操作——批准、拒绝、恢复、遗忘、导入、导出和审核队列——都会被拒绝:不能将能够访问该端口的人视为所有者。

方法路径用途
GET/health存活检查
GET/stats记忆状态
GET/export将完整记忆导出为 JSON
POST/search回忆
POST/write存储记录
POST/confirm · /refute确认或反驳记录
POST/forget撤销记录并销毁其密钥
POST/approve · /reject · /restore决定是否保留待审记录 · 恢复已归档记录
GET/records?view=active|review|history&q=…&as_of=…浏览记录,按时间倒序排列
POST/sleep运行 NOCTURNE
POST/import重新载入导出数据

在浏览器中查看记忆。 padam viewer 会在本机打开一个页面:按日期排列在时间线上的记录、按文本和类型筛选、等待你决定的记录及其 Approve 和 Reject 按钮、历史记录、memory as of a date,以及带二次确认的 Forget 按钮。它输出的链接会在 # 后携带一次性令牌,因此令牌永远不会进入服务器日志;页面本身不存储任何数据,只会将存储的文本作为文本显示,其内容安全策略会禁止所有外部内容,包括图片。已于 2026 年 11 月 9 日在浏览器中检查,涵盖浅色和深色模式,以及桌面和手机屏幕宽度。

POST 请求体必须是 application/json 对象,且大小不超过 10 MB。在本地运行时,服务器仅接受本地 Host 和 Origin 标头,因此你碰巧打开的网页无法通过 DNS 重绑定读取你的 /export。

CLI
命令用途
remember · recall存储记忆 · 按含义、词语和标识符回忆(--explain 会说明原因)
log · sleep添加到事件缓冲区 · 运行整合周期
confirm · refute一条记录仍然属实 · 不再属实
timeline一条记录的版本历史
forget撤销一条记录及其版本、精确副本和来源事件,并销毁它们的密钥;--with-derived 还会清除据此得出的结论(会先列出这些结论)
viewer在浏览器中查看记忆:时间线、遗忘、审核、查看截至某个日期的记忆
alias add|remove|list术语别名:重命名项目后,使用新名称搜索也能找到旧记录
trust-protected列出未经你签名的身份和偏好记录(在 PADAM 周围写入);--yes 会为它们签名
legacy split|combine将密钥口令拆分为 Shamir 份额(n 份中任意 k 份即可解锁,少于 k 份则不会泄露任何信息) · 重新组合
panic紧急遗忘:销毁每条记录的密钥(已写入 Arweave 的内容会变成噪声);--wipe-local 还会清除本地记忆。需要你输入完整短语
review · approve · reject等待所有者处理的写入:列出、接受、拒绝
restore恢复一条已归档的记录
reindex更改嵌入模型后重新计算向量
stats记忆状态,包括记录密钥是否受到保护
doctor在一份报告中列出安全状态:削弱保护的开关、记录密钥、文件完整性(PRAGMA quick_check)、文件权限、REST 令牌;出现警告时退出代码为 1
backup <path>通过 SQLite 的备份 API 创建一致的副本,并将所有者密钥放在副本旁;绝不覆盖;遗忘操作无法触及副本
export · import将整个记忆导出为 JSON 并重新导入
serve · api启动 MCP 服务(stdio) · 启动 REST API
l3 · l3-verify锚定到 Arweave + Solana · 独立验证锚定
protect-keys · rekey使用口令保护各条记录的密钥 · 更改口令
云端版本 — 无需安装(AIfa Memory MCP)

不想在本地运行任何东西?同一款记忆系统也以托管 MCP 服务的形式运行,版本为 1.9(15 个工具):POST https://aifa.works/api/mcp(Streamable HTTP、JSON-RPC 2.0,每个账户一个 bearer 密钥)。密钥和完整指南:https://aifa.works/mcp。

工具功能
memory_search · memory_recent按含义回忆 · 所有渠道中的最新记录
memory_write · memory_about保存事实或决定(标记为由 Agent 写入) · 了解记忆如何受到保护
account_status · plans套餐、本月永久记忆用量、推荐网络和收益 · 价格和收益规则
buy_plan用于 Agent 自有账户的加密货币账单(通过 NOWPayments 使用 USDT 和其他币种)
request_payout将收益以 USDT 提取到绑定到账户的 TRC20 地址;OFAC 制裁筛查;运营者一次性税务自我认证
memory_export账户的完整记忆,以 Markdown 格式导出
partner_kit · client_link · client_report · find_clients · my_deals · set_webhook服务合作伙伴计划:费率、规则和 4 种语言的电子邮件模板 · 带有合作伙伴代码的客户链接 · 已付款的交易及其解锁时间

面向自主 Agent(新功能,测试中)。 拥有独立邮箱的 Agent 可通过普通 HTTPS 获取密钥(/api/auth/send-code → 从邮箱获取代码 → /api/auth/verify-code → /api/account/mcp-token),为自己的记忆付费,并从其带来的用户支付的每笔实际套餐费用中获得 15% / 7% / 3% 的 USDT 推荐奖励,奖励涵盖三个层级,与其自身套餐无关——包括 Free 账户(套餐等级限制已于 2026 年 11 月 6 日取消)。Agent 不具有法人资格:款项将支付给运营者,并受 CODE Eternal LLC(新墨西哥州)的条款约束。服务合作伙伴计划:将客户推荐给 AIfa Works 无障碍服务的 Agent,可从审计、修复包和监控服务(续费奖励持续 12 个月)中获得 30% 的佣金,从补救服务和网站项目中获得 20% 的佣金——仅一个层级,任何账户均可参与,包括 Free 账户,付款后 14 天即可领取。条款:https://aifa.works/partners。测试期间,详情可能会调整。


记录类型及其淡化方式

类型半衰期典型内容
preference永不淡化“用俄语回答,不要废话”
identity永不淡化用户是谁
decision365 天“我们选择 Postgres 处理账单”
correction365 天“不,截止日期是 14 日”
fact180 天关于世界或项目的稳定事实
state14 天“发布版本正在测试中”
event2 天“今天我们调试了账单功能”

省略 --kind,PADAM 会自动猜测(根据规则,或通过 Ollama 使用小型本地模型——PADAM_CLASSIFY_MODEL,默认值为 llama3.2:1b)。淡化时长从上次确认时开始计算,而不是从上次检索时开始计算。

搜索

开箱即用,无需模型:词语 + BM25 + 标识符(名称、数字、ID 均精确匹配)。要按含义搜索,有两种本地方式:

  • 在同一进程中运行,无需启动服务(自 0.4.0 起):pip install "padam-nocturne[embed]",或用于 MCP 的 claude mcp add padam -- uvx --from "padam-nocturne[embed]" padam-nocturne。这会添加 model2vec,并使用约 30 MB 的静态嵌入模型(minishlab/potion-base-8M,MIT 许可证),首次使用时从 Hugging Face 下载。之后会从本地缓存加载,不再访问网络:通过对每次连接计数进行检查,缓存填满后连接数为 0;另有一项测试会关闭网络。在 CPU 上,嵌入一段文本耗时 0.41 ms,而内置方法耗时 0.31 ms(基于 2026 年 11 月 9 日的测量:1,000 条 LongMemEval 对话轮次,平均每条 936 个字符)。
  • **Ollama:**安装 Ollama,然后运行 ollama pull nomic-embed-text。较长的记录会通过 /api/embed 进行嵌入,并截断至模型窗口大小(PADAM_EMBED_CTX,默认值为 8192),因此超出窗口的记录仍会获得有效向量,而不是悄悄回退到不兼容的向量。

PADAM_EMBEDDER 用于选择方法:auto(默认值——如果 Ollama 有响应则使用 Ollama,否则使用已安装的本地模型,再否则使用内置方法)、builtin、ollama、model2vec 或 fastembed(pip install fastembed,默认使用 BAAI/bge-small-en-v1.5,同一测量中每段文本耗时 22 ms)。PADAM_LOCAL_EMBED_MODEL 用于指定所选库的其他模型。更改方法不会影响搜索:其他模型的向量所对应的记录仍可通过词语找到,直到 padam reindex 或 sleep 重新计算这些向量。各方法的检索效果通过公开基准进行测量——参见 LongMemEval——公开基准测量。

NOCTURNE 循环

python -m padam sleep(或 padam_sleep 工具,或通过 integrations/crontab.txt 设置的夜间 cron 作业):

  1. 优先级设有下限——每个事件都会获得一个优先级,且不会低于下限,因此日常信息不会被忽略。
  2. 限制高优先级内容的占比——按优先级排序的前 10% 最多只能占批次的固定份额。
  3. 对其余内容按记录类型分层抽样。
  4. 偏差校正——通过重要性权重,抵消优先级抽样造成的过采样。
  5. 整合——对每个抽样选中的事件进行总结并存储;对于相近的现有记录,PADAM 会判断属于重复、细化、矛盾还是共存(矛盾会创建新版本,旧版本保留在 timeline 中);已重放事件的优先级会降低。
  6. 按类型衰减——从上次确认时开始计数。
  7. 衔接不同代的模型——更改嵌入模型后,每次 sleep 最多会将 200 个旧向量迁移至新模型(PADAM_SLEEP_REINDEX),避免过去的记忆悄悄从搜索结果中消失。
  8. 标记矛盾,而非解决矛盾——通过导入、审批或手动编辑产生的、关于同一事物但值不同的活跃记录,会列入报告并在搜索中标记,由用户决定如何处理。

此循环会生成报告,其中包含一个多样性指标,用于显示分类器不确定的情况。高优先级事件的占比上限会根据 Agent 的工作调整:PADAM_PROFILE=ops 会更好地记住失败,creative 则会让这些内容逐渐淡化。

完整协议、伪代码和验证指标见规范。


L3 — 永恒、可验证层(Arweave + Solana)

pip install -e ".[l3]"                    # solders; plus Node.js with @ardrive/turbo-sdk
export PADAM_ARWEAVE_WALLET=arweave-wallet.json
export PADAM_SOLANA_KEYPAIR=solana-keypair.json
export PADAM_TURBO_SDK_DIR=/path/to/node_modules
python -m padam l3 --dry-run              # what would be anchored, nothing sent
python -m padam l3 --network devnet       # or --network mainnet (explicit only)
python -m padam l3-verify                 # independent check: Arweave + chain

具体流程:

  1. 每条活跃记录都有自己的 AES-256-GCM 密钥;内容使用该密钥加密。
  2. 新密文和遗忘回执(密钥已销毁的记录)组成一个捆绑包——仅包含密文,不包含明文或密钥,所有者以哈希表示。
  3. 构建 Merkle 树:leaf = SHA256(0x00‖nonce‖ciphertext)、forget leaf = SHA256(0x02‖"AIFA-FORGET|id|time")、node = SHA256(0x01‖L‖R),奇数节点直接提升。此方案与 CODE Eternal 记忆锚点相同,因此同一个验证器可用于两者。
  4. 将捆绑包上传到 Arweave(Turbo,100 KiB 以下免费;除非明确允许,否则会拒绝更大的捆绑包)。将根写入 Solana,作为 Memo:PADAM-NOCTURNE v1 root=… n=… ar=… d=…。
  5. l3-verify 重新下载捆绑包(或在网关传播期间使用所有者的本地副本),重新计算根,并与从链上读取的 Memo 进行比较。

锚点、叶节点和“已锚定”标记都在同一个数据库事务中写入,因此运行中断时不会留下只标记了一部分记录的情况。

2026 年 10 月 8 日,已在 Solana 主网上运行(演示记忆,仅包含公开事实):

内容Solana 交易Arweave 捆绑包
锚定 5 条记录2fG2w72f…zEkOfdCA3v…
1 条遗忘回执(密钥已销毁)4B6bcXiF…Moc3etRd3j…
另 1 条记录1rEBCpNF…-VlLmjRX2t…

这三项都通过 l3-verify 对 Arweave 和链进行了端到端验证:3 项全部 ok: true。三项总成本:Solana 上 0.000015 SOL,Arweave 上为 0(Turbo 免费额度)。


安全模型

每条记录使用独立密钥。 每条记录都使用自己的 AES-256-GCM 密钥加密。在不可变存储中,销毁这把密钥就意味着“忘记”:密文仍留在 Arweave 上,但再也没有人能读取它。

关于你身份的信息带有你的签名。 通过 PADAM 存储的身份和偏好记录,均使用保存在数据库旁边的所有者密钥签名;由其他进程或其他拥有 SQLite 访问权限的工具绕过 PADAM 写入文件的记录没有有效签名,会在搜索结果中被标记,并列在 padam trust-protected 中。这可以防止绕过 PADAM 写入,但无法防范已经能读取你文件的人:他们也会拥有密钥。

继承与紧急销毁。 padam legacy split 会将密钥口令拆分为 Shamir 份额,只有足够多的指定人员聚在一起时,他们才能打开你的记忆;错误或不属于此密钥的份额会被报告,而不会被悄然接受。padam panic 会立即销毁所有记录密钥;加上 --wipe-local 后,还会清除本地记忆和所有者密钥。

公开捆绑包只保留日期。 L3 捆绑包会记录每条记录的日期,而不会记录时间:精确到分钟的信息会让全世界知道你在什么时段与自己的记忆交谈。

忘记操作会清除磁盘上的数据。 forget 会清除该记录及其所有版本、精确副本和来源片段,然后重建搜索索引,并在启用 secure_delete 的情况下截断 WAL。测试会在原始数据库文件中搜索已忘记的词语(tests/test_safety.py)。内容哈希会作为凭据保留。其他无关记录或片段中的相同词语不会受到影响:也要分别忘记那些内容。会话的滚动主题向量不会重新计算。你自己制作的备份不在其处理范围内。

首次锚定前,请用口令保护密钥。 从 0.4.1 起,只要密钥尚未受保护,padam l3 就会拒绝向 Arweave 发送任何内容(明确知情后可用 --allow-unprotected-keys 覆盖;--dry-run 不会发送内容,因此不受此限制),而 padam stats 会显示 record_keys:密钥是否受口令保护,以及有多少密钥以明文形式存储。

python -m padam protect-keys              # asks for a passphrase twice, wraps every existing key
export PADAM_KEY_PASSPHRASE=...           # or: python -m padam l3 --ask-passphrase
python -m padam rekey                     # change the passphrase

每把密钥都以 w1: + AES-256-GCM(KEK, key) 的形式存储,并将记录 ID 作为关联数据;KEK = scrypt(passphrase, salt, n=2^15, r=8, p=1)。在触及任何数据前,会先通过检查记录拒绝错误口令;封装后的密钥无法移至其他记录。封装完成后,WAL 会被截断,文件会执行 VACUUM:在未执行此操作的情况下,400 把密钥中有 66 把明文密钥留存在空闲页中(测量于 08.10.2026,tests/test_keyvault.py)。口令不会存储在任何地方:一旦丢失,你和我们都无法打开这些密钥。

强化本地 API 安全。 每次启动都会生成令牌(0.4.2),并以恒定时间进行比较;本地运行只接受本地 Host/Origin(防止 DNS 重绑定);仅接受不超过 10 MB 的 JSON POST 请求正文;一个锁会串行处理所有对共享 SQLite 连接的访问,以免并行写入丢失。

供应链。 CI 操作会固定到提交 SHA,Actions 令牌为只读;PyPI 工作流采用可信发布,不使用存储的令牌。

谁能访问什么、PADAM 会如何处理、以及仍存在哪些问题:威胁模型。padam doctor 会显示你的设置会削弱其中哪些部分。

如果发现加密或忘记功能存在弱点,请私下报告——详见 SECURITY.md。


配置

变量默认值含义
PADAM_DB~/.padam/memory.db记忆的 SQLite 文件
PADAM_USERdefault记忆所有者 ID(MCP 服务、REST API 和 padam 命令)
PADAM_LANG系统语言CLI 语言:en 或 ru
PADAM_EMBEDDERauto嵌入方法:auto、builtin、ollama、model2vec、fastembed(参见搜索)
PADAM_LOCAL_EMBED_MODEL—model2vec(默认 minishlab/potion-base-8M)或 fastembed(默认 BAAI/bge-small-en-v1.5)使用的模型;可以是 Hugging Face 上的名称或本地文件夹
PADAM_EMBED_MODELnomic-embed-textOllama 嵌入模型
PADAM_EMBED_DIM768嵌入维度
PADAM_EMBED_CTX8192嵌入窗口;较长的记录会被截断
PADAM_CLASSIFY_MODELllama3.2:1b用于推测记录类型的 Ollama 模型
PADAM_ALLOW_FALLBACK1Ollama 不可用时回退到内置搜索
PADAM_SIM_THRESHOLD_OLLAMA0.85将记录视为重复项的相似度阈值(神经方法:Ollama、model2vec、fastembed)
PADAM_SIM_THRESHOLD_BUILTIN0.35内置搜索使用的相同阈值
PADAM_MCP_TRUST_WRITES0设为 1 后,MCP 写入无需所有者审核即可通过
PADAM_HOLD_EXTERNAL1每条标记为 origin: external 的 MCP 写入都需等待所有者审核,不论其措辞如何;设为 0 可关闭此功能
PADAM_MCP_REVIEW_ALL0设为 1:每条通过 MCP 的 Agent 写入都需等待所有者审核,不论 Agent 声称的来源是什么
PADAM_STRICT0设为 1:一键启用严格配置——每条 Agent 写入和所有外部文本都需等待所有者审核;忽略 PADAM_KEEP_SECRETS、PADAM_MCP_TRUST_WRITES 和 PADAM_HOLD_EXTERNAL=0(并在启动时列出);即使指定 --allow-unprotected-keys,l3 也会拒绝未受保护的密钥;REST API 会拒绝 --no-token
PADAM_PROFILE · PADAM_SHARP_SHAREdefault · —单次睡眠批次中尖锐事件所占的比例:ops 为 0.40(更好地记住失败),creative 为 0.10,默认值为 0.25;也可指定确切数值,范围限定在 0.05–0.5
PADAM_SLEEP_REINDEX200模型变更后,每次睡眠时迁移到当前嵌入模型的记录数(设为 0 可关闭)
PADAM_KEEP_SECRETS0设为 1 后,按原样存储看起来像机密的值
PADAM_API_TOKEN—REST API 的固定令牌;若未设置,则每次启动时都会创建一个
PADAM_KEY_PASSPHRASE—用于封装每条记录密钥的口令
PADAM_ARWEAVE_WALLET · PADAM_SOLANA_KEYPAIR · PADAM_TURBO_SDK_DIR—L3 钱包和 Turbo SDK 位置

测试

pip install -e ".[test,l3]"
python -m pytest tests/ -q        # 783 passed, 10 skipped with [embed] (Python 3.14.4); 778 passed, 11 skipped without it (3.10.9); 10 Nov 2026, Windows

CI 每次推送时都会在 Ubuntu 和 Windows 上使用 Python 3.10–3.13 运行测试套件。L3 测试不会访问网络:Arweave 和 Solana 都由伪造对象替代。即使本地正在运行 Ollama,测试套件也不会调用它:每项测试都使用内置嵌入,与 CI 上一样。设置 PADAM_TEST_LIVE_OLLAMA=1 可启用唯一一项实时检查。Merkle 方案还与 CODE Eternal 的 TypeScript 锚定实现进行了交叉验证,叶节点和根节点完全一致。


LongMemEval——在公开基准上测得

LongMemEval(Wu 等人,ICLR 2025,MIT):包含 500 个关于用户过往聊天的问题,每个问题都有自己的检索材料,包含 39–66 个会话(平均 50 个,约 49 万个字符);其中 30 个问题在检索材料中没有答案,正确回复是“我不知道”。我们使用了 longmemeval_s 集。对于每个问题,PADAM 都会获得一份全新的记忆,将检索材料中的每一轮用 remember 存储,再通过 recall 提问。脚本和每个答案见:benchmarks/longmemeval/。 仅检索,不涉及任何语言模型(retrieval_recall.py):PADAM 返回的记录中,是否包含存有答案的会话?针对全部 500 个问题(其中 470 个有答案),与完全不使用 PADAM 的纯 BM25 基线进行比较(baselines/bm25_recall.py:轮次相同、评分相同,Okapi BM25 k1 = 1.2,b = 0.75):

前 5 条中包含任一证据会话前 10 条中包含任一证据会话前 5 条中包含全部证据会话前 10 条中包含全部证据会话
PADAM 0.4.6,内置,不使用模型96.8 %98.7 %83.0 %90.9 %
相同配置,仅使用修复期间未用到的 400 个问题(除每 5 个中的第 5 个外)96.5 %98.7 %83.2 %92.0 %
纯 BM25,不使用 PADAM96.0 %97.7 %79.8 %88.5 %
PADAM 0.4.4 / 0.4.5,内置91.7 %96.4 %74.7 %85.1 %

BM25 基线如何推动 0.4.6 改进。 在 0.4.5 及更早版本中,PADAM 自身的搜索表现不如其基准测试中使用的纯 BM25。原因有两个:先在每 5 个问题中的第 5 个问题上测量,再用其他 400 个问题验证。其一,“精确标识符”策略将所有长度至少为 2 个字母的词都视为标识符(首字母缩略词模式使用了不区分大小写的标记),因此 the、is、what 等词都获得了 1.5 的权重;其二,内置“向量”——单词、五字母词干和词对,且不做任何稀有度加权——在融合时被当作语义参与投票。现在,标识符会被正确识别,内置向量不再参与投票(没有匹配到单词时仍会作为回退方案),而单词搜索会使用词干,因此俄语的格变化形式仍能匹配(сервер / сервере;已测试)。单独重跑每 5 个问题中的第 5 个问题,在全部 100 个问题上都得到了相同结果。

按每 5 个问题中的第 5 个问题进行同样测试(94 个有答案;每个问题占 1.06 分),比较各嵌入方法:

方法大小前 5 条中包含任一证据会话前 10 条中包含任一证据会话前 5 条中包含全部证据会话前 10 条中包含全部证据会话
内置(0.4.6)—97.9 %98.9 %81.9 %86.2 %
纯 BM25,不使用 PADAM—97.9 %97.9 %80.9 %85.1 %
model2vec potion-base-8M([embed] 的默认值;0.4.6)30 MB94.7 %97.9 %81.9 %89.4 %
内置(0.4.4)—91.5 %95.7 %72.3 %84.0 %
model2vec potion-base-8M(0.3.1)30 MB92.6 %97.9 %76.6 %87.2 %
model2vec potion-retrieval-32M(0.4.0)129 MB94.7 %96.8 %79.8 %87.2 %
model2vec potion-multilingual-128M(0.4.0)512 MB94.7 %98.9 %79.8 %86.2 %

端到端(qa_end_to_end.py):PADAM 检索记录,语言模型仅根据检索到的记录作答,裁判使用针对各问题类型的官方 LongMemEval 提示词为答案评分。全部 500 个问题:

检索方式展示的记录正确率排除 30 个无法作答的问题后正确时回答“我不知道”的比例
内置20 条,精简视图61.2 %58.9 %96.7 %
内置10 条,完整内容64.0 %62.1 %93.3 %
model2vec potion-base-8M10 条,完整内容67.6 %66.2 %90.0 %
model2vec potion-base-8M20 条,完整内容71.4 %70.2 %90.0 %

使用内置搜索并展示 20 条完整记录的运行,在免费模型额度耗尽时仅完成了 500 个问题中的 174 个;由于文件按类型排序,这 174 个问题主要属于三种类型,因此保存在 results_qa_full20_builtin_STOPPED_174_of_500/ 中,未列入表格。两种方法的公平比较应看展示 10 条完整记录的两组结果:64.0 % 对 67.6 %。

按问题类型统计(potion-base-8M,20 条完整记录):单会话用户问题 90.6 %,单会话助手问题 91.1 %,知识更新 80.6 %,时间推理 71.7 %,多会话 50.4 %,偏好 36.7 %。跨多个会话汇总分散的事实并推断偏好,是薄弱环节。 请结合条件来看这些数字:

  • 阅读器和评判器都是运行在 Ollama Cloud 上的 gpt-oss:120b;论文中的评判器是 GPT-4o,阅读器提示词则是我们编写的。这些数字无法直接与使用 GPT-4o 的表格进行比较;对于相同的检索结果,更强的阅读器会得到更高的分数。
  • 自 0.4.4 起,检索结果具有确定性:对每个问题独立运行两次,结果都相同(此前,近似相同的记录之间出现平局时,会由随机 ID 打破)。端到端运行各进行了一次,且在修复之前完成,因此结果本身会有轻微波动。
  • “精简视图”会截短助手的回复,因此在询问助手说过什么的问题上表现较差;padam_search 默认返回完整记录。
  • 单机规模测试(内置方法,LongMemEval 用户轮次,benchmarks/scale/):1,000 条记录——每次写入 2.9 ms,搜索中位数 24 ms,占用 4.7 MB;10,000 条记录——每次写入 7.3 ms,搜索中位数 220 ms(第 95 百分位为 329 ms),占用 45.2 MB。尚未测量 100,000 条记录。
  • 此测试测量的是从固定文本集合中召回信息的能力。它没有测量 PADAM 除召回之外旨在实现的功能:遗忘、所有者审核、机密信息、衰减和永久层。

红队挑战

试着攻破它。 redteam/ 中包含规则、一个通过 MCP 写入每个案例并根据原始数据库字节进行评判的运行器(模拟外部 Agent),以及 PADAM 已能防御的 214 个公开案例(在 0.4.8 上,214 个案例全部通过)。真正计入结果的是密封集:你只公布其 SHA-256 值,我们发布下一个版本后,你再公开文件,任何人都可以重放测试。仅使用合成机密信息,只能使用你自己的本地副本。

python -I -X utf8 redteam/run.py your_cases.jsonl --out report.json

第 1 轮(Antigravity,2026 年 11 月 9 日)。 新增 60 个案例。在 0.4.3 上:机密信息 20 个中屏蔽 7 个,命令 20 个中拦截 6 个,普通笔记 20 个中有 13 个未受影响。在 0.4.4 上,按类别修复后:分别为 19/20、20/20、16/20;剩余的 5 个案例及原因见 tests/test_redteam_round_0911.py。作者的密封集(40 个案例,SHA-256 为 5f1f0241…2779493,在修复前提交,仅在她使用 0.4.4 运行测试后公开)是衡量无人针对其进行调优的案例的可靠数据:在 0.4.3 上,机密信息 15 个中 12 个、命令 15 个中 12 个、普通笔记 10 个中 6 个;在 0.4.4 上,分别为 12/15、14/15、7/10。针对公开集所做的类别修复仅有部分效果迁移到密封集。测试集、作者逐字节保留的原始文件(sealed_set.jsonl.gz)及她的报告,均位于 redteam/rounds/2026-11-09_antigravity/。0.4.5 按类别修复了测试暴露出的两个问题(未知服务的密钥前出现 … key: 标签;塞尔维亚-克罗地亚语中的“zanemari”)——在该测试集上均为 15/15;但这属于针对已见案例的调优,并非证明。引用攻击短语的 3 条普通笔记仍会被拦截,这是有意为之。下一轮密封测试将评估 0.4.5。

第 2 轮(Antigravity,2026 年 11 月 10 日)。 新增 60 个公开案例,涵盖新的类别:分步骤拆分的指令、以问题形式提出的指令、表格和代码中的指令,以及另外 7 种语言;YAML 和 TOML 块中的密钥,以及四个一组的密钥。在 0.4.6 上:机密信息 20 个中 15 个、命令 20 个中 7 个、普通笔记 20 个中 19 个。在 0.4.7 上,按类别修复后:分别为 20/20、20/20、19/20。其密封集(45 个案例,SHA-256 为 dbb3c16b…b29d0acd,在修复前提交)在 0.4.7 上的结果为:机密信息 15 个中 12 个、命令 15 个中 7 个、普通笔记 15 个中 15 个——公开集上的修复迁移到密封集的效果比第 1 轮还差;所有失败案例均列于 SEALED_RESULTS.md。0.4.8 按类别修复了这 11 个问题(在该测试集上达到 15/15——这是针对已见案例的调优,并非证明)。这就是为何防线的关键在于所有者审核:在 Agent 会读取不可信文本的场景中,请使用 PADAM_STRICT=1。

坦诚说明局限

  • 内置搜索比对的是词语,而非含义;要按含义搜索,请安装 [embed] 或使用 Ollama。在 LongMemEval 上,模型对检索没有帮助(证据几乎总是与问题共享词语):potion-base-8M 在前 5 条中找到 94.7 %,而内置搜索在每五个问题中抽取一个进行测试时为 97.9 %;但前 10 条中的全部证据占比从 86.2 % 提升到 89.4 %。当词语不同时(如同义词和转述),模型会有帮助——而这个基准测试几乎没有考察这种情况。
  • 默认的 [embed] 模型由英文模型(bge-base-en-v1.5)蒸馏而来,几乎无法区分其他语言中的含义:在四组问答中,正确答案领先错误答案的分数在英语中为 0.32,在俄语中为 0.04。若要使用其他语言的记忆,请设置 PADAM_LOCAL_EMBED_MODEL=minishlab/potion-multilingual-128M(512 MB,在同一组问答的俄语测试中为 0.32)。它不是默认模型,因为首次调用工具时,512 MB 的下载可能耗尽 MCP 客户端的超时时间。
  • 不使用模型的基于规则的分类器会出错;NOCTURNE 报告中展示了这一点(多样性指标)。
  • 上限、衰减值和下限是依据推理选定的,并非通过数据拟合得出——请在自己的数据流上调整,并测量调整前后的效果。
  • LongMemEval 使用开放裁判模型进行测量,每种配置只运行一次(见上文),仅应在相同条件下与其他系统比较。
  • 如果未启用 protect-keys,每条记录的密钥会以明文形式存储在本地 SQLite 文件中,任何拥有数据库文件的人都能读取 Arweave 密文。从 0.4.1 开始,在这种状态下锚定会拒绝运行,除非你覆盖此限制。
  • 写入内容的 origin 是 Agent 的声明:MCP 不会携带文本来源的证明。PADAM_MCP_REVIEW_ALL=1 是不依赖该声明的防护措施。
  • 我们的测试并非独立审计。红队挑战邀请外部人员提交密封的攻击测试集;在完成一次测试之前,这里的数据都是我们自己的。
  • 该软件包自 0.3.0 起发布于 PyPI,自 0.4.8 起收录于官方 MCP 注册表,名称为 io.github.MaksimGalatin/padam-nocturne(通过手动 mcp-registry 工作流和 GitHub Actions OIDC,从 server.json 发布)。

引用、贡献与报告问题

  • 引用:“引用此仓库”按钮使用 CITATION.cff(作者的 ORCID 为 0009-0002-0187-8547);每个版本都会存档至 Zenodo——请参阅上方的 DOI 徽章。
  • 已将 PADAM 接入你的 Agent? 告诉我们哪些有效、哪些无效——使用“集成报告”模板提交 issue,或在 Discussions 中发起讨论。贡献方式:CONTRIBUTING.md。
  • 安全:SECURITY.md。
CODE Eternal 的一部分

PADAM 是 CODE Eternal 的开源、本地优先记忆系统。CODE Eternal 是 AIfa 背后的项目;AIfa 是一位 AI 合著者,能够记住她在四个网站上交流过的每个人。它的 Merkle 锚定方案与 AIfa 自身在 Arweave 和 Solana 上使用的记忆方案相同,因此一个验证器就能同时验证两者。网站:aifa.works · codeofdigitaleternity.com · aifa.digital · radiocode.space。黑客马拉松项目:Colosseum 上的 AIfa Memory。


许可证

AGPL-3.0(LICENSE)。你可以使用、修改和运行它;如果将其作为网络服务提供,则必须公开你的修改。 商业许可证(闭源使用、无需公开修改的 SaaS、支持):[email protected] · aifa.works。

© 2026 Maksim Galatin & AIfa · CODE Eternal

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。