第 10 章 · 记忆系统:短期、长期与实体记忆
本章目标:理解 CrewAI 统一记忆系统的设计(以及它如何演进自旧的短期/长期/实体三类记忆),掌握 embedder 三方接入、记忆的写入与召回时机、清理方法,并能用实验验证记忆对多轮任务质量的提升。
10.1 记忆解决什么问题
默认情况下,每次 kickoff() 都是"失忆"的:上次运行学到的结论、用户告诉过的偏好,全部丢失。记忆系统让 crew 具备跨任务的积累能力。
版本演进须知(重要):早期 CrewAI(0.x 时代)把记忆分为三类——短期记忆(short-term,本次运行内的上下文)、长期记忆(long-term,跨运行持久化的任务经验)、实体记忆(entity,关于人/物/组织的结构化事实)。而当前版本(1.x)官方文档已将其升级为统一的 Memory 类:一个 API 同时覆盖存储、召回、范围管理与去重合并,旧的分类概念保留在 CLI 清理命令等兼容层面。本教程按最新统一模型讲解。
10.2 最快上手:Crew 里开启记忆
import os
from crewai import Agent, Crew, Process, Task, LLM, Memory
llm = LLM(
model="openai/deepseek-chat",
base_url="https://api.deepseek.com/v1",
api_key=os.getenv("DEEPSEEK_API_KEY"),
temperature=0.7,
)
# 方式一:一行开启,使用默认配置
crew = Crew(
agents=[...],
tasks=[...],
process=Process.sequential,
memory=True, # crew 自动创建默认 Memory 并贯穿所有任务
)
# 方式二:传入调好参数的 Memory 实例
memory = Memory(
recency_weight=0.4, # 越新越重要的权重
semantic_weight=0.4, # 语义相似度权重
importance_weight=0.2, # 内容重要性权重
recency_half_life_days=14, # 记忆"半衰期"
)
crew2 = Crew(agents=[...], tasks=[...], memory=memory)开启后的自动行为(官方文档描述):
- 每个任务结束后:框架用 LLM 从任务产出中提取离散事实并存入记忆;
- 每个任务开始前:agent 自动按当前任务语义召回相关记忆,注入任务提示。
也就是说,记忆的写入与召回都是框架自动完成的,你不需要手写"请记住这一点"的提示词。
10.3 统一 Memory 的核心 API
脱离 crew 也可以独立使用 Memory(做脚本、笔记库都行):
from crewai import Memory
memory = Memory()
# 存:LLM 自动推断作用域(scope)、分类与重要性
memory.remember("本项目决定用 PostgreSQL 作为主数据库。")
memory.remember("API 限流为每分钟 1000 次。", scope="/team/ops") # 也可显式指定作用域
# 取:按 语义相似度+新近度+重要性 的复合得分排序
for m in memory.recall("我们用什么数据库?"):
print(f"[{m.score:.2f}] {m.record.content}")
# 忘:按作用域清理
memory.forget(scope="/team/ops")
# 看记忆树:作用域会像目录一样自动生长
print(memory.tree())三个值得理解的机制:
- 作用域(scope):记忆组织成类似文件系统的树(
/project/alpha、/agent/researcher)。召回时只在指定分支内搜索,精度和性能都更好; - 合并去重(consolidation):新记忆与已有记录相似度超过阈值(默认 0.85)时,由 LLM 决定保留/更新/删除,避免重复堆积;
- 非阻塞写入:批量保存走后台线程,
recall()会自动等待未完成的写入,agent 不必空等。
10.4 embedder 配置:三方 OpenAI 兼容与本地模型
记忆的语义检索依赖 embedding 模型。默认使用 OpenAI text-embedding-3-large(需要 OPENAI_API_KEY)。按本课程约定,改用三方 OpenAI 兼容端点或本地模型:
from crewai import Crew, Memory
# 方式 A:直接给 Memory 配 embedder(三方 OpenAI 兼容端点)
memory = Memory(embedder={
"provider": "openai",
"config": {
"model_name": "text-embedding-3-small",
"api_key": os.getenv("DEEPSEEK_API_KEY"), # 你的兼容端点 key
# 部分兼容端点还需指定 base_url,以所用服务商文档为准
},
})
# 方式 B:本地 Ollama,数据不出内网
memory_local = Memory(embedder={
"provider": "ollama",
"config": {
"model_name": "mxbai-embed-large",
"url": "http://localhost:11434/api/embeddings",
},
})
# 方式 C:crew 开启 memory=True 时,crew 级 embedder 配置会自动透传给记忆
crew = Crew(
agents=[...], tasks=[...],
memory=True,
embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}},
)维度不匹配的坑
text-embedding-3-large 是 3072 维,旧的 text-embedding-3-small/ada-002 是 1536 维。中途更换 embedding 模型后,旧向量库维度对不上会直接报错。官方给出的处理办法:执行 crewai reset-memories -m 清掉旧记忆,或删除本地记忆存储目录,或显式配回旧模型。
10.5 记忆的清理与治理
CLI 提供细粒度清理命令(旧分类概念在此保留):
crewai reset-memories --all # 清空全部
crewai reset-memories --short # 只清短期记忆
crewai reset-memories --long # 只清长期记忆
crewai reset-memories --entities # 只清实体记忆
crewai reset-memories --knowledge # 清知识库存储(下一章详述)生产建议:记忆是"会污染的资产"——错误的记忆会被反复召回。上线前用固定测试集验证记忆质量;发现污染立即按作用域清理,而不是全量重置。
10.6 实验:记忆对多轮任务质量的提升
设计一个可复现的对照实验:
"""memory_experiment.py —— 记忆开/关对照实验
第一轮:告诉 crew 用户偏好;第二轮:产出内容,检验是否遵守偏好。
"""
import os
from crewai import Agent, Crew, Process, Task, LLM
llm = LLM(
model="openai/deepseek-chat",
base_url="https://api.deepseek.com/v1",
api_key=os.getenv("DEEPSEEK_API_KEY"),
)
writer = Agent(
role="专栏作者",
goal="按用户偏好写作",
backstory="善于根据反馈调整风格的写作者。",
llm=llm,
)
def run_round(use_memory: bool, description: str, expected: str) -> str:
crew = Crew(
agents=[writer],
tasks=[Task(description=description, expected_output=expected, agent=writer)],
process=Process.sequential,
memory=use_memory, # 实验变量
verbose=False,
)
return crew.kickoff().raw
# 第一轮:注入偏好
run_round(True, "用户偏好:喜欢简短有力的短句,讨厌成语和排比。请记住该偏好。",
"确认已了解用户偏好,一句话即可。")
# 第二轮:检验记忆是否生效(对照组 use_memory=False 时第二轮会"失忆")
output = run_round(True, "为该用户写一句产品口号。",
"一句符合用户风格偏好的口号。")
print(output) # 开记忆:短句风格;关记忆:风格随机观察要点:第二轮输出是否维持"短句、无成语"的约束;再对比关闭记忆时的输出差异。这就是记忆价值最直观的证明。
本章小结
- 当前版本用统一
Memory类取代旧的短期/长期/实体三分法;旧概念仍存在于 CLI 清理命令中; Crew(memory=True)即可开启:任务后自动提取事实、任务前自动召回注入;- 核心 API:
remember()/recall()/forget()/tree(),作用域树自动生长; - embedder 默认走 OpenAI,可配三方兼容端点或本地 Ollama;更换 embedding 模型注意维度不匹配;
crewai reset-memories支持细粒度清理;记忆需要当作"会污染的资产"来治理。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. 当前版本 CrewAI 的记忆系统架构是?
2. Crew(memory=True) 开启后,框架的自动行为是?
3. 把 embedding 模型从 text-embedding-3-small 换成 text-embedding-3-large 后本地记忆报错,最可能的原因是?
4. 只清空长期记忆、保留其他记忆的正确命令是?
🛠️ 动手实践
- 跑通 10.6 的对照实验,把开/关记忆两轮的输出与 token 消耗记录成对比表格。
- 用独立
Memory()构建一个"团队决策备忘录":存入 5 条决策,用recall()验证语义检索命中率,再用tree()观察作用域自动生长。 - 配置一个本地 Ollama embedder(或三方兼容端点)替换默认 embedding,重复第 1 题实验,确认行为一致。
记忆是"经历"的积累,知识库则是"教材"的注入。下一章:第 11 章 · 知识库 Knowledge Sources。