跳转到内容

记忆

CrewAI 提供了一套统一记忆系统 - 通过一个 Memory 类,替代单独的短期、长期、实体和外部记忆类型,并统一为一个智能 API。Memory 在保存内容时会使用 LLM 分析内容(推断作用域、类别和重要性),并支持自适应深度召回,使用组合评分将语义相似度、时效性和重要性融合在一起。

你可以通过四种方式使用 memory:独立使用(脚本、笔记本)、与 Crews 一起使用与 Agents 一起使用,或者在 Flows 中使用

from crewai import Memory
memory = Memory()
# Store -- the LLM infers scope, categories, and importance
memory.remember("We decided to use PostgreSQL for the user database.")
# Retrieve -- results ranked by composite score (semantic + recency + importance)
matches = memory.recall("What database did we choose?")
for m in matches:
print(f"[{m.score:.2f}] {m.record.content}")
# Tune scoring for a fast-moving project
memory = Memory(recency_weight=0.5, recency_half_life_days=7)
# Forget
memory.forget(scope="/project/old")
# Explore the self-organized scope tree
print(memory.tree())
print(memory.info("/"))

在脚本、笔记本、CLI 工具中使用 memory,或者把它作为一个独立的知识库 - 不需要 agents 或 crews。

from crewai import Memory
memory = Memory()
# Build up knowledge
memory.remember("The API rate limit is 1000 requests per minute.")
memory.remember("Our staging environment uses port 8080.")
memory.remember("The team agreed to use feature flags for all new releases.")
# Later, recall what you need
matches = memory.recall("What are our API limits?", limit=5)
for m in matches:
print(f"[{m.score:.2f}] {m.record.content}")
# Extract atomic facts from a longer text
raw = """Meeting notes: We decided to migrate from MySQL to PostgreSQL
next quarter. The budget is $50k. Sarah will lead the migration."""
facts = memory.extract_memories(raw)
# ["Migration from MySQL to PostgreSQL planned for next quarter",
# "Database migration budget is $50k",
# "Sarah will lead the database migration"]
for fact in facts:
memory.remember(fact)

传入 memory=True 可使用默认设置,也可以传入已配置好的 Memory 实例来定制行为。

from crewai import Crew, Agent, Task, Process, Memory
# Option 1: Default memory
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
process=Process.sequential,
memory=True,
verbose=True,
)
# Option 2: Custom memory with tuned scoring
memory = Memory(
recency_weight=0.4,
semantic_weight=0.4,
importance_weight=0.2,
recency_half_life_days=14,
)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, writing_task],
memory=memory,
)

memory=True 时,crew 会创建默认的 Memory(),并自动透传 crew 的 embedder 配置。除非某个 agent 有自己的 memory,否则 crew 中所有 agents 都共享 crew 的 memory。没有自定义 embedder 时,memory 会使用 OpenAI text-embedding-3-large embeddings。

每个任务完成后,crew 会自动从任务输出中提取离散事实并存储它们。每个任务开始前,agent 会从 memory 中召回相关上下文,并把它注入到任务提示中。

Agents 可以使用 crew 共享的 memory(默认),也可以获得一个带作用域的私有上下文视图。

from crewai import Agent, Memory
memory = Memory()
# Researcher gets a private scope -- only sees /agent/researcher
researcher = Agent(
role="Researcher",
goal="Find and analyze information",
backstory="Expert researcher with attention to detail",
memory=memory.scope("/agent/researcher"),
)
# Writer uses crew shared memory (no agent-level memory set)
writer = Agent(
role="Writer",
goal="Produce clear, well-structured content",
backstory="Experienced technical writer",
# memory not set -- uses crew._memory when crew has memory enabled
)

这种模式让 researcher 保留私有发现,而 writer 则从共享的 crew memory 中读取信息。

每个 Flow 都内置了 memory。你可以在任意 flow 方法中使用 self.remember()self.recall()self.extract_memories()

from crewai.flow.flow import Flow, listen, start
class ResearchFlow(Flow):
@start()
def gather_data(self):
findings = "PostgreSQL handles 10k concurrent connections. MySQL caps at 5k."
self.remember(findings, scope="/research/databases")
return findings
@listen(gather_data)
def write_report(self, findings):
# Recall past research to provide context
past = self.recall("database performance benchmarks")
context = "\n".join(f"- {m.record.content}" for m in past)
return f"Report:\nNew findings: {findings}\nPrevious context:\n{context}"

查看 Flows 文档 了解 flows 中 memory 的更多内容。

memory 以层级树的方式组织,类似文件系统。每个 scope 都是一个路径,例如 //project/alpha/agent/researcher/findings

/
/company
/company/engineering
/company/product
/project
/project/alpha
/project/beta
/agent
/agent/researcher
/agent/writer

Scopes 提供了上下文相关的记忆 - 当你在某个 scope 中召回时,只会搜索树的那个分支,这能同时提升准确率和性能。

当你在 remember() 中不指定 scope 时,LLM 会分析内容和现有 scope 树,然后建议最合适的放置位置。如果没有合适的现有 scope,它会创建一个新的。随着时间推移,scope 树会从内容本身自然生长出来 - 你不需要预先设计 schema。

memory = Memory()
# LLM infers scope from content
memory.remember("We chose PostgreSQL for the user database.")
# -> might be placed under /project/decisions or /engineering/database
# You can also specify scope explicitly
memory.remember("Sprint velocity is 42 points", scope="/team/metrics")
print(memory.tree())
# / (15 records)
# /project (8 records)
# /project/alpha (5 records)
# /project/beta (3 records)
# /agent (7 records)
# /agent/researcher (4 records)
# /agent/writer (3 records)
print(memory.info("/project/alpha"))
# ScopeInfo(path='/project/alpha', record_count=5,
# categories=['architecture', 'database'],
# oldest_record=datetime(...), newest_record=datetime(...),
# child_scopes=[])

MemoryScope 会将所有操作限制在树的某个分支上。使用它的 agent 或代码只能看到并写入该子树。

memory = Memory()
# Create a scope for a specific agent
agent_memory = memory.scope("/agent/researcher")
# Everything is relative to /agent/researcher
agent_memory.remember("Found three relevant papers on LLM memory.")
# -> stored under /agent/researcher
agent_memory.recall("relevant papers")
# -> searches only under /agent/researcher
# Narrow further with subscope
project_memory = agent_memory.subscope("project-alpha")
# -> /agent/researcher/project-alpha
  • 先保持扁平,让 LLM 自行组织。 不要一开始就过度设计 scope 层级。先用 memory.remember(content),让 LLM 的 scope 推断随着内容积累自动生成结构。

  • 使用 /{entity_type}/{identifier} 模式。/project/alpha/agent/researcher/company/engineering/customer/acme-corp 这样的模式很自然。

  • 按关注点分组,而不是按数据类型。/project/alpha/decisions,不要用 /decisions/project/alpha。这样相关内容会聚在一起。

  • 保持层级浅一些(2-3 层)。 过深的嵌套 scope 会变得过于稀疏。/project/alpha/architecture 是好的;/project/alpha/architecture/decisions/databases/postgresql 就太深了。

  • 已知时显式指定,不确定时让 LLM 推断。 如果你在保存已知项目决策,请传入 scope="/project/alpha/decisions"。如果你在保存自由形式的 agent 输出,就省略 scope,让 LLM 自己判断。

多项目团队:

memory = Memory()
# Each project gets its own branch
memory.remember("Using microservices architecture", scope="/project/alpha/architecture")
memory.remember("GraphQL API for client apps", scope="/project/beta/api")
# Recall across all projects
memory.recall("API design decisions")
# Or within a specific project
memory.recall("API design", scope="/project/beta")

每个 agent 的私有上下文与共享知识:

memory = Memory()
# Researcher has private findings
researcher_memory = memory.scope("/agent/researcher")
# Writer can read from both its own scope and shared company knowledge
writer_view = memory.slice(
scopes=["/agent/writer", "/company/knowledge"],
read_only=True,
)

客户支持(按客户隔离上下文):

memory = Memory()
# Each customer gets isolated context
memory.remember("Prefers email communication", scope="/customer/acme-corp")
memory.remember("On enterprise plan, 50 seats", scope="/customer/acme-corp")
# Shared product docs are accessible to all agents
memory.remember("Rate limit is 1000 req/min on enterprise plan", scope="/product/docs")

MemorySlice 是跨越多个、可能互不相交的 scopes 的视图。与 scope(只限制在一个子树)不同,slice 允许同时从多个分支召回内容。

  • Scope:当某个 agent 或代码块只应限制在单个子树中时使用。例:只看 /agent/researcher 的 agent。
  • Slice:当你需要把多个分支的上下文合并在一起时使用。例:一个既读取自己的 scope 又读取共享 company knowledge 的 agent。

最常见的模式是:允许 agent 读取多个分支,但不允许它写入共享区域。

memory = Memory()
# Agent can recall from its own scope AND company knowledge,
# but cannot write to company knowledge
agent_view = memory.slice(
scopes=["/agent/researcher", "/company/knowledge"],
read_only=True,
)
matches = agent_view.recall("company security policies", limit=5)
# Searches both /agent/researcher and /company/knowledge, merges and ranks results
agent_view.remember("new finding") # Raises PermissionError (read-only)

当关闭只读时,你可以写入所包含的任意 scope,但必须显式指定要写入哪个 scope。

view = memory.slice(scopes=["/team/alpha", "/team/beta"], read_only=False)
# Must specify scope when writing
view.remember("Cross-team decision", scope="/team/alpha", categories=["decisions"])

召回结果会按三个信号的加权组合进行排序:

composite = semantic_weight * similarity + recency_weight * decay + importance_weight * importance

其中:

  • similarity = 来自向量索引的 1 / (1 + distance)(0 到 1)
  • decay = 0.5^(age_days / half_life_days) - 指数衰减(今天为 1.0,半衰期时为 0.5)
  • importance = 记录在编码时设置的重要性分数(0 到 1)

你可以在 Memory 构造器里直接配置这些参数:

# Sprint retrospective: favor recent memories, short half-life
memory = Memory(
recency_weight=0.5,
semantic_weight=0.3,
importance_weight=0.2,
recency_half_life_days=7,
)
# Architecture knowledge base: favor important memories, long half-life
memory = Memory(
recency_weight=0.1,
semantic_weight=0.5,
importance_weight=0.4,
recency_half_life_days=180,
)

每个 MemoryMatch 都包含一个 match_reasons 列表,这样你就能看到结果为什么排在当前位置,例如 ["semantic", "recency", "importance"]

Memory 会从三个方面使用 LLM:

  1. 保存时 - 当你省略 scope、categories 或 importance 时,LLM 会分析内容并建议 scope、categories、importance 以及元数据(实体、日期、主题)。
  2. 召回时 - 对于深度/自动召回,LLM 会分析查询(关键词、时间提示、建议 scopes、复杂度)以引导检索。
  3. 提取 memories - extract_memories(content) 会把原始文本(例如任务输出)拆成离散的 memory 语句。Agents 会在调用 remember() 保存每个语句之前先执行这一步,这样原子事实会被存为独立条目,而不是一个大块。

如果 LLM 失败,所有分析都会优雅降级 - 见 Failure Behavior

在保存新内容时,编码管线会自动检查存储中是否存在相似的旧记录。如果相似度高于 consolidation_threshold(默认 0.85),LLM 会决定如何处理:

  • keep - 现有记录仍然准确且不重复。
  • update - 现有记录需要用新信息更新(LLM 会提供合并后的内容)。
  • delete - 现有记录已过时、被替代或被新内容否定。
  • insert_new - 是否还应将新内容作为独立记录插入。

这可以防止重复项累积。例如,如果你三次保存 “CrewAI ensures reliable operation”,consolidation 会识别重复并只保留一条记录。

在使用 remember_many() 时,同一批次中的项目会在写入存储前彼此比较。如果两个项目的 cosine similarity >= batch_dedup_threshold(默认 0.98),后者会被静默丢弃。这样无需任何 LLM 调用(纯向量运算)就能捕获单批次中的完全或近似重复项。

# Only 2 records are stored (the third is a near-duplicate of the first)
memory.remember_many([
"CrewAI supports complex workflows.",
"Python is a great language.",
"CrewAI supports complex workflows.", # dropped by intra-batch dedup
])

remember_many()非阻塞的 - 它会把编码管线提交到后台线程并立即返回。这意味着 agent 可以在 memory 正在保存时继续执行下一个任务。

# Returns immediately -- save happens in background
memory.remember_many(["Fact A.", "Fact B.", "Fact C."])
# recall() automatically waits for pending saves before searching
matches = memory.recall("facts") # sees all 3 records

每次 recall() 调用都会在搜索前自动调用 drain_writes(),确保查询总能看到最新的已持久化记录。这是透明的 - 你无需手动思考这一步。

当 crew 结束时,kickoff() 会在其 finally 块中排空所有待处理的 memory 保存,因此即使 crew 在后台保存进行中完成,也不会丢失保存内容。

对于没有 crew 生命周期的脚本或笔记本,请显式调用 drain_writes()close()

memory = Memory()
memory.remember_many(["Fact A.", "Fact B."])
# Option 1: Wait for pending saves
memory.drain_writes()
# Option 2: Drain and shut down the background pool
memory.close()

每条 memory 记录都可以带有用于溯源追踪的 source 标签,以及用于访问控制的 private 标志。

source 参数用于标识 memory 的来源:

# Tag memories with their origin
memory.remember("User prefers dark mode", source="user:alice")
memory.remember("System config updated", source="admin")
memory.remember("Agent found a bug", source="agent:debugger")
# Recall only memories from a specific source
matches = memory.recall("user preferences", source="user:alice")

只有当 source 匹配时,私有 memory 才会在召回时可见:

# Store a private memory
memory.remember("Alice's API key is sk-...", source="user:alice", private=True)
# This recall sees the private memory (source matches)
matches = memory.recall("API key", source="user:alice")
# This recall does NOT see it (different source)
matches = memory.recall("API key", source="user:bob")
# Admin access: see all private records regardless of source
matches = memory.recall("API key", include_private=True)

这在多用户或企业部署中特别有用,因为不同用户的 memory 需要彼此隔离。

recall() 支持两种深度:

  • depth="shallow" - 直接进行向量搜索并使用组合评分。速度快(约 200ms),不调用 LLM。
  • depth="deep"(默认) - 运行多步骤 RecallFlow:查询分析、scope 选择、并行向量搜索、基于置信度的路由,以及在置信度较低时的可选递归探索。

智能 LLM 跳过:短于 query_analysis_threshold(默认 200 个字符)的查询会完全跳过 LLM 查询分析,即使在 deep 模式下也是如此。像 “What database do we use?” 这样的短查询本身就已经是不错的搜索短语 - LLM 分析增益不大。这样对于常见短查询,每次 recall 可节省约 1-3 秒。只有较长的查询(例如完整的任务描述)才会通过 LLM 被提炼成定向子查询。

# Shallow:纯向量搜索,不使用 LLM
matches = memory.recall("What did we decide?", limit=10, depth="shallow")
# Deep(默认):对长查询进行 LLM 分析的智能检索
matches = memory.recall(
"Summarize all architecture decisions from this quarter",
limit=10,
depth="deep",
)

控制 RecallFlow 路由器的置信度阈值可以配置:

memory = Memory(
confidence_threshold_high=0.9, # Only synthesize when very confident
confidence_threshold_low=0.4, # Explore deeper more aggressively
exploration_budget=2, # Allow up to 2 exploration rounds
query_analysis_threshold=200, # Skip LLM for queries shorter than this
)

Memory 需要一个 embedding 模型将文本转换为向量,以便进行语义搜索。默认情况下,Memory() 使用 OpenAI text-embedding-3-large embeddings,生成 3072 维向量。请设置 OPENAI_API_KEY 走默认路径,或者用以下三种方式之一配置自定义 embedder。

from crewai import Memory
# As a config dict
memory = Memory(embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-large"}})
# As a pre-built callable
from crewai.rag.embeddings.factory import build_embedder
embedder = build_embedder({"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}})
memory = Memory(embedder=embedder)

当使用 memory=True 时,crew 的 embedder 配置会被透传:

from crewai import Crew
crew = Crew(
agents=[...],
tasks=[...],
memory=True,
embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-large"}},
)
OpenAI(默认)
memory = Memory(embedder={
"provider": "openai",
"config": {
"model_name": "text-embedding-3-large",
# "api_key": "sk-...", # or set OPENAI_API_KEY env var
},
})
Ollama(本地,私有)
memory = Memory(embedder={
"provider": "ollama",
"config": {
"model_name": "mxbai-embed-large",
"url": "http://localhost:11434/api/embeddings",
},
})
Azure OpenAI
memory = Memory(embedder={
"provider": "azure",
"config": {
"deployment_id": "your-embedding-deployment",
"api_key": "your-azure-api-key",
"api_base": "https://your-resource.openai.azure.com",
"api_version": "2024-02-01",
},
})
Google AI
memory = Memory(embedder={
"provider": "google-generativeai",
"config": {
"model_name": "gemini-embedding-001",
# "api_key": "...", # or set GOOGLE_API_KEY env var
},
})
Google Vertex AI
memory = Memory(embedder={
"provider": "google-vertex",
"config": {
"model_name": "gemini-embedding-001",
"project_id": "your-gcp-project-id",
"location": "us-central1",
},
})
Cohere
memory = Memory(embedder={
"provider": "cohere",
"config": {
"model_name": "embed-english-v3.0",
# "api_key": "...", # or set COHERE_API_KEY env var
},
})
VoyageAI
memory = Memory(embedder={
"provider": "voyageai",
"config": {
"model": "voyage-3",
# "api_key": "...", # or set VOYAGE_API_KEY env var
},
})
AWS Bedrock
memory = Memory(embedder={
"provider": "amazon-bedrock",
"config": {
"model_name": "amazon.titan-embed-text-v1",
# Uses default AWS credentials (boto3 session)
},
})
Hugging Face
memory = Memory(embedder={
"provider": "huggingface",
"config": {
"model_name": "sentence-transformers/all-MiniLM-L6-v2",
},
})
Jina
memory = Memory(embedder={
"provider": "jina",
"config": {
"model_name": "jina-embeddings-v2-base-en",
# "api_key": "...", # or set JINA_API_KEY env var
},
})
IBM WatsonX
memory = Memory(embedder={
"provider": "watsonx",
"config": {
"model_id": "ibm/slate-30m-english-rtrvr",
"api_key": "your-watsonx-api-key",
"project_id": "your-project-id",
"url": "https://us-south.ml.cloud.ibm.com",
},
})
自定义 Embedder
# Pass any callable that takes a list of strings and returns a list of vectors
def my_embedder(texts: list[str]) -> list[list[float]]:
# Your embedding logic here
return [[0.1, 0.2, ...] for _ in texts]
memory = Memory(embedder=my_embedder)
ProviderKeyTypical ModelNotes
OpenAIopenaitext-embedding-3-large默认。设置 OPENAI_API_KEY
Ollamaollamamxbai-embed-large本地,无需 API key。
Azure OpenAIazuretext-embedding-3-large默认模型。需要 deployment_id
Google AIgoogle-generativeaigemini-embedding-001设置 GOOGLE_API_KEY
Google Vertexgoogle-vertexgemini-embedding-001需要 project_id
Coherecohereembed-english-v3.0多语言支持较强。
VoyageAIvoyageaivoyage-3针对检索进行了优化。
AWS Bedrockamazon-bedrockamazon.titan-embed-text-v1使用 boto3 凭据。
Hugging Facehuggingfaceall-MiniLM-L6-v2本地 sentence-transformers。
Jinajinajina-embeddings-v2-base-en设置 JINA_API_KEY
IBM WatsonXwatsonxibm/slate-30m-english-rtrvr需要 project_id
Sentence Transformersentence-transformerall-MiniLM-L6-v2本地,无需 API key。
Customcustom需要 embedding_callable

Memory 会使用 LLM 进行保存分析(scope、categories、importance 推断)、consolidation 决策,以及 deep recall 的查询分析。你可以配置要使用的模型。

from crewai import Memory, LLM
# Default: gpt-4o-mini
memory = Memory()
# Use a different OpenAI model
memory = Memory(llm="gpt-4o")
# Use Anthropic
memory = Memory(llm="anthropic/claude-3-haiku-20240307")
# Use Ollama for fully local/private analysis
memory = Memory(llm="ollama/llama3.2")
# Use Google Gemini
memory = Memory(llm="gemini/gemini-2.0-flash")
# Pass a pre-configured LLM instance with custom settings
llm = LLM(model="gpt-4o", temperature=0)
memory = Memory(llm=llm)

LLM 是延迟初始化的 - 只有在第一次需要时才会创建。这意味着即使 API keys 没有设置,Memory() 在构造阶段也不会失败。只有当 LLM 真正被调用时,错误才会显现(例如在没有显式 scope/categories 时保存,或在 deep recall 期间)。

如果要完全离线/私有运行,请同时为 LLM 和 embedder 使用本地模型:

memory = Memory(
llm="ollama/llama3.2",
embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}},
)
  • 默认:LanceDB,存储在 ./.crewai/memory 下(或者 $CREWAI_STORAGE_DIR/memory,如果设置了该环境变量;或者你通过 storage="path/to/dir" 传入的路径)。
  • 自定义后端:实现 StorageBackend 协议(见 crewai.memory.storage.backend),并将实例传给 Memory(storage=your_backend)

查看 scope 层级、categories 和 records:

memory.tree() # Formatted tree of scopes and record counts
memory.tree("/project", max_depth=2) # Subtree view
memory.info("/project") # ScopeInfo: record_count, categories, oldest/newest
memory.list_scopes("/") # Immediate child scopes
memory.list_categories() # Category names and counts
memory.list_records(scope="/project/alpha", limit=20) # Records in a scope, newest first

如果 LLM 在分析过程中失败(网络错误、速率限制、无效响应),memory 会优雅降级:

  • Save analysis - 会记录警告,并且 memory 仍然会被保存,但会使用默认 scope /、空 categories 和 importance 0.5
  • Extract memories - 整个内容会作为单条 memory 保存,这样不会丢失任何内容。
  • Query analysis - recall 会退回到简单的 scope 选择和向量搜索,因此你仍然能得到结果。

这些分析失败不会抛出异常;只有存储或 embedder 失败才会抛错。

memory 内容会发送给你配置的 LLM 进行分析(保存时的 scope/categories/importance、查询分析,以及可选的 deep recall)。如果数据敏感,请使用本地 LLM(例如 Ollama)或确保你的 provider 满足合规要求。

所有 memory 操作都会发出 source_type="unified_memory" 的事件。你可以监听耗时、错误和内容。

EventDescriptionKey Properties
MemoryQueryStartedEventQuery beginsquery, limit
MemoryQueryCompletedEventQuery succeedsquery, results, query_time_ms
MemoryQueryFailedEventQuery failsquery, error
MemorySaveStartedEventSave beginsvalue, metadata
MemorySaveCompletedEventSave succeedsvalue, save_time_ms
MemorySaveFailedEventSave failsvalue, error
MemoryRetrievalStartedEventAgent retrieval startstask_id
MemoryRetrievalCompletedEventAgent retrieval donetask_id, memory_content, retrieval_time_ms

示例:监控查询耗时:

from crewai.events import BaseEventListener, MemoryQueryCompletedEvent
class MemoryMonitor(BaseEventListener):
def setup_listeners(self, crewai_event_bus):
@crewai_event_bus.on(MemoryQueryCompletedEvent)
def on_done(source, event):
if getattr(event, "source_type", None) == "unified_memory":
print(f"Query '{event.query}' completed in {event.query_time_ms:.0f}ms")

Memory 没有持久化?

  • 确保存储路径可写(默认 ./.crewai/memory)。传入 storage="./your_path" 使用其他目录,或者设置 CREWAI_STORAGE_DIR 环境变量。
  • 使用 crew 时,确认已设置 memory=Truememory=Memory(...)

召回很慢?

  • 对常规 agent 上下文使用 depth="shallow"。把 depth="deep" 留给复杂查询。
  • 提高 query_analysis_threshold,让更多查询跳过 LLM 分析。

日志里有 LLM 分析错误?

  • Memory 仍会使用安全默认值完成保存/召回。如果想要完整的 LLM 分析,请检查 API keys、速率限制和模型可用性。

日志里有后台保存错误?

  • Memory 保存会在后台线程中运行。错误会以 MemorySaveFailedEvent 发出,但不会让 agent 崩溃。查看日志以定位根因(通常是 LLM 或 embedder 连接问题)。

Embedding 维度不匹配?

  • 现有本地 memory 存储可能是用不同的 embedding 模型创建的。默认 OpenAI memory embedder 现在是 text-embedding-3-large(3072 维),而旧存储通常使用 1536 维 embeddings。进行本地测试时,运行 crewai reset-memories -m、删除本地 memory 存储目录,或者显式配置旧的 embedder 模型。

并发写入冲突?

  • LanceDB 操作使用共享锁串行化,并会在冲突时自动重试。这可以处理指向同一数据库的多个 Memory 实例(例如 agent memory + crew memory)。无需额外操作。

从终端浏览 memory:

Terminal window
crewai memory # Opens the TUI browser
crewai memory --storage-path ./my_memory # Point to a specific directory

重置 memory(例如用于测试):

crew.reset_memories(command_type="memory") # Resets unified memory
# Or on a Memory instance:
memory.reset() # All scopes
memory.reset(scope="/project/old") # Only that subtree

所有配置都作为关键字参数传给 Memory(...)。每个参数都有合理的默认值。

ParameterDefaultDescription
llm"gpt-4o-mini"用于分析的 LLM(模型名或 BaseLLM 实例)。
storage"lancedb"存储后端("lancedb"、路径字符串,或 StorageBackend 实例)。
embedderNone(OpenAI text-embedding-3-largeembedder(配置字典、可调用对象,或 None 表示默认 OpenAI)。
recency_weight0.3组合评分中时效性的权重。
semantic_weight0.5组合评分中语义相似度的权重。
importance_weight0.2组合评分中重要性的权重。
recency_half_life_days30时效性分数减半所需天数(指数衰减)。
consolidation_threshold0.85保存时触发 consolidation 的相似度。设为 1.0 可禁用。
consolidation_limit5consolidation 期间比较的最大旧记录数。
default_importance0.5未提供且跳过 LLM 分析时使用的重要性。
batch_dedup_threshold0.98remember_many() 批次中丢弃近似重复项的 cosine similarity 阈值。
confidence_threshold_high0.8recall 置信度高于此值时直接返回结果。
confidence_threshold_low0.5recall 置信度低于此值时触发更深的探索。
complex_query_threshold0.7对于复杂查询,低于此置信度时继续深入探索。
exploration_budget1deep recall 期间允许的 LLM 驱动探索轮数。
query_analysis_threshold200短于此长度(字符数)的查询在 deep recall 中会跳过 LLM 分析。