Agent Zero Memory 插件实战:基于 FAISS 的持久向量记忆、知识预加载与自动策展体系
【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero
Agent Zero 的_memory插件为 Agent 提供持久化、基于向量的长期记忆:它将记忆与知识片段以嵌入(embedding)形式存入 FAISS 向量数据库,暴露memory_save/memory_load等工具,并通过扩展点在每轮对话中自动召回相关记忆、自动沉淀新的持久信息,再配合 Web 仪表盘完成人工浏览、编辑与删除。读完本文,你将理解该插件的存储模型与目录隔离机制、全部配置参数的含义与默认值、五大记忆工具的使用方式,以及“自动记忆 → 整合 → 召回”这条完整链路的源码实现,从而能自主调优 Agent Zero 的长期记忆行为。
插件定位与整体能力
插件元数据定义了该插件的身份:
name: _memory title: Memory description: Provides persistent memory capabilities to Agent Zero agents. version: 1.0.0 settings_sections: - agent per_project_config: true per_agent_config: true几个关键点:
- 配置归属
agent设置区:所有记忆相关开关都出现在 Agent 设置中; - 支持按项目、按 Agent 覆盖配置(
per_project_config: true、per_agent_config: true),这意味着同一个部署里,不同 Agent 或不同项目可以拥有完全不同的记忆策略(例如一个研究型 Agent 开启激进记忆、一个轻量 Agent 关闭自动记忆)。
从 README 的 “Main Behavior” 一节可以归纳出插件的六大能力,后文逐一展开:
- 持久化向量存储(FAISS 索引 + 嵌入元数据);
- 知识预加载(Knowledge preloading);
- 记忆工具(保存/加载/删除/遗忘/行为调整);
- 自动对话记忆(过滤瞬态信息后沉淀持久信息);
- 仪表盘 API(搜索、删除、批量删除、更新、子目录列表);
- 作用域存储(按子目录隔离不同上下文或 Agent 的记忆)。
存储引擎:FAISS 索引、嵌入缓存与索引自愈
核心引擎在 helpers/memory.py。Memory类以memory_subdir(记忆子目录)为键维护一个进程内索引缓存Memory.index: dict[str, MyFaiss],每个子目录对应一个独立的 FAISS 库。
目录与文件布局
usr/memory/<subdir>/:每个记忆子目录一个 FAISS 库目录,内含index.faiss、embedding.json等;tmp/memory/embeddings/:嵌入结果的缓存存储(LocalFileStore),源码注释明确写着 “just caching, no need to parameterize”,即该缓存可以安全重建;- 项目场景下,
projects/<name>子目录会被abs_db_dir()重定向到项目元数据目录内的memory/子目录,这是项目记忆隔离的物理基础(见后文)。
初始化与嵌入模型绑定
Memory.initialize()的初始化流程值得拆解:
- 通过
models.get_embedding_model()构建嵌入模型,并用CacheBackedEmbeddings.from_bytes_store()包一层本地字节缓存,缓存命名空间为provider_model的安全化文件名——相同文本不会重复调用嵌入 API; - 若库目录已存在
index.faiss,先做哈希校验:_write_index_hash()每次保存索引时都会写一份index.faiss.sha256,加载时_verify_index_hash()比对,不一致则打印警告并触发整库重建,防止加载损坏索引; - 读取
embedding.json元文件,核对其中的model_provider与model_name是否与当前配置一致;只要嵌入模型发生过变更,旧文档就会被取出(get_all_docs())后用新模型整库重新索引——这就是 README 所说 “Stores embedding metadata so the index can be rebuilt if the embedding model changes” 的底层实现; - 新建索引使用
faiss.IndexFlatIP(内积),配合DistanceStrategy.COSINE与自定义_cosine_normalizer,将余弦相似度归一到0~1区间,并夹取浮点误差(如1.0000000596046448)到[0, 1]。
此外还有一组扩展点配合自愈:embedding_model_changed/_10_memory_reload.py 在检测到嵌入模型变更时清空Memory.index强制所有库重新加载。
安全过滤:filter 表达式的白名单求值
向量检索支持按 metadata 过滤(如area=='main'),其实现_get_comparator()是一个安全敏感点:
- 过滤条件长度上限 512,且必须先通过一个字符白名单正则(只允许字母、数字、下划线、点、引号、比较/逻辑符号等),否则直接拒绝并返回恒假比较器;
- 通过白名单后使用
simpleeval.simple_eval在metadata字典的命名空间上求值,不开放任何函数(functions={})。
这意味着 Agent 调用memory_load时传入的filter无法执行任意 Python,属于仓库内置的注入防护。
记忆分区(Area)与知识预加载
Memory.Area枚举定义了三个分区:
| 分区 | 用途 |
|---|---|
main | 一般性记忆与知识(未显式指定 area 时默认落入此处) |
fragments | 自动记忆管线沉淀的对话碎片 |
solutions | 问题解决方案 |
召回阶段会按分区分别检索(见“自动召回”一节),删除与替换逻辑也按分区过滤,避免误伤。
知识目录的加载规则
preload_knowledge()在数据库初始化时执行(memory.py#L259-L335):
- 读取
<db_dir>/knowledge_import.json增量索引(每个知识文件对应的文档 ID 列表); - 对每个知识子目录:根目录下的文件直接归入
main分区(非递归);fragments/、solutions/等子目录则归入同名分区(递归); - 依据索引中的
state字段做增量维护:状态为changed的文件先删除旧 ID 再插入新文档;状态为removed的文件只删除旧 ID; - 维护完成后把
state、documents等临时字段从索引中剥离再落盘,使索引长期保持轻量。
知识导入的解析逻辑由 helpers/knowledge_import.py 承担,而api/import_knowledge.py与api/knowledge_reindex.py提供从 Web 端触发导入与重建索引的入口。
作用域隔离:子目录、项目与 Agent
helpers/memory.py 中的get_agent_memory_subdir()决定了 Agent 实际使用哪个记忆库,优先级如下:
- 若插件配置
project_memory_isolation为真(默认true)且当前上下文处于某个项目中,返回projects/<项目名>; - 否则回退到
agent_memory_subdir配置项(默认default)。
物理路径映射(abs_db_dir()/abs_knowledge_dir()):
- 标准子目录 →
usr/memory/<subdir>(记忆)、knowledge/(default)或usr/knowledge/<subdir>(自定义); projects/<name>前缀 → 项目元数据目录下的memory/与knowledge/,从而项目记忆与全局记忆在文件层面完全隔离。
get_existing_memory_subdirs()会同时枚举usr/memory/下的子目录和所有含memory/index.faiss的项目目录,供仪表盘的 “Memory Directory” 下拉框使用。这种设计使“按上下文/Agent 拆分记忆”(README 的 Scoped storage 条目)成为开箱即用能力:你只需为不同 Agent 配置不同的agent_memory_subdir。
五大记忆工具
工具实现集中在 plugins/_memory/tools/,其行为说明由提示词 agent.system.tool.memory.md 注入系统提示。各工具签名与语义如下:
memory_save — 保存记忆
tools/memory_save.py:execute(self, text="", area="", **kwargs)。未指定area时默认main;其余 kwargs 全部并入文档 metadata 一并存储。返回fw.memory_saved.md模板并附带memory_id,Agent 可以据此后续精确操作该条记忆。
memory_load — 相似度检索
tools/memory_load.py:
| 参数 | 默认值 | 说明 |
|---|---|---|
query | 必填 | 检索语句 |
threshold | 0.7 | 余弦相似度阈值,0~1 |
limit | 10 | 返回条数上限 |
filter | "" | metadata 过滤表达式,如area=='main' |
一个值得注意的细节:threshold与limit接受原生数字或数字字符串,工具内部会强制float()/int()转换后再进入向量检索——这是对 LLM 工具调用经常传出字符串参数的防御性处理(在 AGENTS.md 的 Local Contracts 一节也有明确约定)。无结果时返回fw.memories_not_found.md模板而非报错。
memory_delete — 按 ID 删除(级联)
tools/memory_delete.py 接收逗号分隔的ids,调用delete_documents_by_ids(ids, cascade=True)。cascade=True会触发_find_related_docs_by_ids():扫描全库 metadata,凡引用了被删 ID 的文档(如整合派生的碎片/方案记录)一并删除,保证删除是“干净”的。
memory_forget — 按语义“遗忘”
tools/memory_forget.py 按query+threshold(默认0.7)+filter删除,对应底层delete_documents_by_query():
- 以
k=100分批做相似度搜索,直到命中数小于批大小为止,避免一次删除被 k 截断; include_exact=True会额外做精确文本匹配兜底:把 query 归一化(小写、压空白)后在全文+metadata JSON 中做子串扫描(要求 query 长度 ≥ 3 字符),清除向量检索可能漏掉的完全重复项;cascade=True同memory_delete,清理派生记录。
系统提示词还给出了使用纪律:不要仅因记忆“老”就遗忘它,只有在当前证据表明它过时、错误、被取代、重复或 unwanted 时才遗忘;对可变事实(如偏好更新)应先 load 相关旧记忆 → forget/delete 被取代版本 → 保存唯一的新版本,而不是追加第二条。
behaviour_adjustment — 行为规则持久化
tools/behaviour_adjustment.py 是一个特殊工具:它不操作向量库,而是维护记忆目录下的behaviour.md规则文件:
- 读取当前规则集(无
behaviour.md时回退到默认模板agent.system.behaviour_default.md); - 用工具模型(utility model)把“现有规则 + 用户要求的调整”合并成新规则集,并流式记录到日志;
normalize_ruleset()做文本规整:剥掉代码围栏、统一换行、去重结构行、压缩连续空行;- 写回
get_custom_rules_file()指向的记忆目录内behavior.md。
与之配套,system_prompt/_20_behaviour_prompt.py 扩展点会把该规则文件注入系统提示,实现“用户说一次,Agent 永久改变行为习惯”的闭环。
自动记忆管线:从对话到碎片再到整合
README 的 “Automatic conversation memory” 能力由extensions/python/下的扩展点串成一条流水线。
召回:message_loop_prompts_after/_50_recall_memories.py
RecallMemories 扩展在提示词组装后介入,逻辑如下:
- 受
memory_recall_enabled总开关控制; - 按
memory_recall_interval(默认 3)控制触发频率:每 N 个循环迭代触发一次(第一次也触发); - 查询构造有两条路径:
memory_recall_query_prep=true时,调用工具模型基于“最近memory_recall_history_len(默认 10000)字符的对话历史 + 当前用户消息”生成一段精炼检索查询,失败则跳过本次检索;- 关闭时,直接拼接用户消息与对话历史作为查询;
- 检索设置 30 秒超时(
asyncio.wait_for),且把任务句柄放进 agent data(_recall_memories_task),供 _91_recall_wait.py 在需要时等待完成; - 分区检索:
main+fragments按memory_recall_memories_max_search(默认 12)取,solutions按memory_recall_solutions_max_search(默认 8)取,均受memory_recall_similarity_threshold(默认 0.7)约束; memory_recall_post_filter=true时,再调用一次工具模型对候选做二次筛选(输出 JSON 下标列表,经dirty_json.try_parse解析),剔除相关性不足的条目;- 最终截断到
memory_recall_memories_max_result(默认 5)与memory_recall_solutions_max_result(默认 3),分别渲染进 agent.system.memories.md 与 agent.system.solutions.md 两个系统提示片段,完成“记忆进上下文”。
沉淀:monologue_end/_50_memorize_fragments.py
MemorizeMemories 扩展在独白(monologue)结束时运行:
- 受
memory_memorize_enabled控制,且整个流程放到后台线程(DeferredTask)执行,不阻塞主循环; - 取对话历史(截断到最近 80000 字符以防工具模型上下文溢出),用工具模型按 memory.memories_sum.sys.md 提示词抽取“持久信息”,输出经
DirtyJson容错解析; - 关键质量关口:
filter_auto_memory_fragments()(实现于 helpers/memory_quality.py)在入库前过滤瞬态的行动历史碎片——这正是 README “filtering transient action-history fragments before insertion” 与 AGENTS 文档 “Avoid storing transient action-history noise as durable memory” 契约的代码落点; - 入库策略分两种:
memory_memorize_consolidation=true(默认):走 memory_consolidation.py 的智能整合。create_memory_consolidator()以相似度阈值 0.7、最多 8 条相似记忆、LLM 上下文最多 4 条记忆为参数,对每条新碎片先检索近邻,再决定是替换、合并还是新增,从而让碎片库有界、去重;- 关闭整合时:若
memory_memorize_replace_threshold > 0(默认 0.9),先按该阈值删除 fragments 分区中的高相似旧碎片,再插入新碎片——即用一条新记忆直接顶替旧记忆。
另有 _51_memorize_solutions.py 以同样机制把“问题 → 解决方案”沉淀到solutions分区。
初始化:monologue_start/_10_memory_init.py
MemoryInit 扩展在独白开始时调用Memory.get(agent),确保该 Agent 对应的向量库已加载并完成知识预加载,之后所有工具与扩展才能安全使用。
配置参数全解
default_config.yaml 给出全部默认值,配合 plugin.yaml 的settings_sections: [agent]与两个 per-config 开关,可在 全局 / 项目 / Agent 三层覆盖。
# 作用域 project_memory_isolation: true # 项目内记忆隔离到 projects/<name> 库 agent_memory_subdir: default # 非项目场景使用的记忆子目录 # 自动召回(recall) memory_recall_enabled: true # 自动召回总开关 memory_recall_delayed: false # 召回任务是否延迟等待 memory_recall_interval: 3 # 每 N 个循环迭代触发一次召回 memory_recall_history_len: 10000 # 参与召回的历史字符数上限 memory_recall_memories_max_search: 12 # main+fragments 检索候选上限 memory_recall_solutions_max_search: 8 # solutions 检索候选上限 memory_recall_memories_max_result: 5 # 注入提示词的记忆条数上限 memory_recall_solutions_max_result: 3 # 注入提示词的方案条数上限 memory_recall_similarity_threshold: 0.7 # 相似度阈值(余弦,0~1) memory_recall_query_prep: false # 是否用工具模型生成精炼检索查询 memory_recall_post_filter: false # 是否用工具模型对候选做二次筛选 # 自动沉淀(memorize) memory_memorize_enabled: true # 自动记忆总开关 memory_memorize_consolidation: true # 智能整合(替换/合并/新增) memory_memorize_replace_threshold: 0.9 # 非整合模式下替换旧碎片的相似度阈值调参建议(基于实现行为):
- 想降低召回噪音:提高
memory_recall_similarity_threshold或调小两个max_result;开启query_prep会多花一次工具模型调用但查询更聚焦; - 想控制记忆库膨胀:保持
consolidation=true,整合器会把碎片归并;关闭整合时把memory_memorize_replace_threshold设为接近 1 的值(如 0.9)可自动顶替高度重复的碎片; - 多 Agent 协作场景:给不同 Agent 配置不同
agent_memory_subdir,在文件层面实现记忆互不干扰。
仪表盘 API 与 Web 界面
api/memory_dashboard.py 的MemoryDashboard处理器按action字段分派六个动作:
| action | 说明 |
|---|---|
search | 按memory_subdir/area/search/limit(默认 100)/threshold(默认 0.6)检索;无查询词时返回按时间倒序的全量(受 limit 截断),并统计知识条目与对话记忆条目数 |
delete | 按memory_id单条删除 |
bulk_delete | 按 ID 列表批量删除,返回成功/失败计数 |
update | 以原文档 ID 为键执行“删旧插新”(update_documents),支持编辑内容与 metadata |
get_memory_subdirs | 列出所有可用记忆子目录(含项目库) |
get_current_memory_subdir | 解析当前上下文的记忆子目录(无上下文回退default) |
每条记忆返回给前端的结构(_format_memory_for_dashboard)包含id、area、timestamp(经本地化时区转换)、完整内容、knowledge_source/source_file/file_type(知识来源信息)、consolidation_action与完整 metadata,memory-dashboard.html 等 Web 组件据此渲染行列表、详情弹窗(memory-detail-modal.html)与批量操作。
日常使用:像园艺一样管理记忆
记忆系统再自动也需要人工策展——官方使用指南 docs/guides/memory.md 给出了完整的操作建议,值得作为实践清单保留:
- 保留什么:稳定的用户偏好、项目约定、验证过仍有效的命令、需要跨会话持久的决策、重复问题的已知解法;
- 删除什么:过时的环境参数(旧路径/端口/命令)、被当成事实保存的失败猜测、临时实验、从混乱对话里复制的记忆、不应被记住的隐私数据;
- 行为异常时的排查回路:先按反复出现的短语或命令搜索记忆 → 打开可疑条目通读 → 有用但不准的编辑修正,纯粹错误的直接删除 → 在聊天里给出明确纠正后重试;
- 批量清理要克制:先导出备份、用窄范围检索代替按大类删除、优先删明显垃圾、保留仍然有效的老解法。
从源码结构看,编辑与删除最终都走update_documents()/delete_documents_by_ids()(级联清理派生记录),且删除后_save_db()立即持久化并刷新index.faiss.sha256哈希,因此仪表盘操作与实际向量库状态是强一致的。
小结
_memory插件的设计可以用三层来概括:存储层用“每子目录一个 FAISS 库 + 嵌入元数据 + SHA256 校验”保证可重建、可换模型、防损坏;自动化层用扩展点在对话循环的召回/沉淀两端挂接工具模型,把“检索—筛选—注入”与“抽取—过滤—整合—入库”做成无需人工触发的闭环;治理层用五个工具加仪表盘 API 提供精确的增删改查与级联清理,配合项目隔离与分区(main/fragments/solutions)控制记忆的作用域与质量。理解并调好 default_config.yaml 里的阈值与开关,是让 Agent Zero 的长期记忆从“能记住”走向“记得对”的关键。
【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考