Semantic recall
如果你问朋友上周末做了什么,他们会在记忆中搜索与"上周末"相关的事件,然后告诉你他们做了什么。这大致就是 Mastra 中语义召回的工作方式。
观看 Mastra semantic recall,了解 agent 如何从过去的对话中检索相关消息。
语义召回的工作原理语义召回的工作原理的直接链接
语义召回是一种基于 RAG 的搜索,当消息不再位于最近消息历史中时,它帮助 agent 在较长的交互中保持上下文。
它使用消息的向量 embedding 进行相似度搜索,并与向量存储集成,同时支持在检索到的消息周围配置上下文窗口。
启用后,新消息会被用于查询向量数据库,以寻找语义相似的消息。
从 LLM 获得响应后,所有新消息(user、assistant 以及工具调用/结果)都会被插入向量数据库,以便在后续交互中召回。
快速开始快速开始的直接链接
语义召回默认禁用。要启用它,请在 options 中设置 semanticRecall: true,并提供 vector 存储和 embedder。对于自行生成 embedding 的存储(例如使用 Automated Embedding 的 MongoDB),则无需提供 embedder。参见服务端 embedding。
- LibSQL
- MongoDB
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { LibSQLStore, LibSQLVector } from '@mastra/libsql'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
const agent = new Agent({
id: 'support-agent',
name: 'SupportAgent',
instructions: 'You are a helpful support agent.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
storage: new LibSQLStore({
id: 'agent-storage',
url: 'file:./local.db',
}),
vector: new LibSQLVector({
id: 'agent-vector',
url: 'file:./local.db',
}),
embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
options: {
semanticRecall: true,
},
}),
})
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { MongoDBStore, MongoDBVector } from '@mastra/mongodb'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
const agent = new Agent({
id: 'support-agent',
name: 'SupportAgent',
instructions: 'You are a helpful support agent.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
storage: new MongoDBStore({
id: 'agent-storage',
uri: process.env.MONGODB_URI,
dbName: process.env.MONGODB_DB_NAME,
}),
vector: new MongoDBVector({
id: 'agent-vector',
uri: process.env.MONGODB_URI,
dbName: process.env.MONGODB_DB_NAME,
}),
embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
options: {
semanticRecall: true,
},
}),
})
使用 recall() 方法using-the-recall-method的直接链接
listMessages 按 thread ID 检索消息并支持基本的分页,而 recall() 增加了语义搜索支持。当你需要按含义而非时间新近度查找消息时,请使用带 vectorSearchString 的 recall():
const memory = await agent.getMemory()
// Basic recall - similar to listMessages
const { messages } = await memory!.recall({
threadId: 'thread-123',
perPage: 50,
})
// Semantic recall - find messages by meaning
const { messages: relevantMessages } = await memory!.recall({
threadId: 'thread-123',
vectorSearchString: 'What did we discuss about the project deadline?',
threadConfig: {
semanticRecall: true,
},
})
存储配置存储配置的直接链接
语义召回依赖存储和向量数据库来存储消息及其 embedding。
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { LibSQLStore, LibSQLVector } from '@mastra/libsql'
const agent = new Agent({
memory: new Memory({
// this is the default storage db if omitted
storage: new LibSQLStore({
id: 'agent-storage',
url: 'file:./local.db',
}),
// this is the default vector db if omitted
vector: new LibSQLVector({
id: 'agent-vector',
url: 'file:./local.db',
}),
options: {
semanticRecall: true,
},
}),
})
下面每个向量存储页面都包含安装说明、配置参数和使用示例:
- Astra
- Chroma
- Cloudflare Vectorize
- Convex
- Couchbase
- DuckDB
- Elasticsearch
- LanceDB
- libSQL
- MongoDB
- OpenSearch
- OracleDB
- Pinecone
- PostgreSQL
- Qdrant
- S3 Vectors
- Turbopuffer
- Upstash
召回配置召回配置的直接链接
以下选项控制语义召回行为:
- topK:要检索的相似消息数量
- messageRange:每个匹配项要包含的周围消息
- scope:是搜索当前 thread,还是搜索某个 resource 的所有 thread
- filter:限制搜索结果的元数据条件
const agent = new Agent({
id: 'agent',
memory: new Memory({
options: {
semanticRecall: {
topK: 3, // Retrieve 3 similar messages
messageRange: 2, // Include 2 messages before and after each match
scope: 'resource', // Search all threads for this resource
filter: { projectId: { $eq: 'project-a' } },
},
},
}),
})
LibSQL、OracleDB、PostgreSQL、MongoDB 和 Upstash 存储适配器支持 scope: 'resource'。
元数据过滤元数据过滤的直接链接
filter 选项将语义召回结果限制为 thread 元数据匹配的消息。
const agent = new Agent({
id: 'agent',
memory: new Memory({
options: {
semanticRecall: {
scope: 'resource',
filter: {
projectId: { $eq: 'project-a' },
category: { $in: ['work', 'personal'] },
},
},
},
}),
})
过滤器匹配的是消息保存时存储在消息 embedding 上的元数据。如果 thread 元数据之后发生更改,现有 embedding 会保留先前的元数据,直到这些消息被再次保存或索引。
支持的过滤器操作符:
$and:逻辑与$eq:等于$gt:大于$gte:大于或等于$in:在数组中$lt:小于$lte:小于或等于$ne:不等于$nin:不在数组中$or:逻辑或
以下示例演示了常见用例的元数据过滤器:
// Filter by project
const options = {
semanticRecall: { filter: { projectId: { $eq: 'my-project' } } },
}
// Filter by multiple categories
const options = {
semanticRecall: { filter: { category: { $in: ['work', 'research'] } } },
}
// Filter by project and priority
const options = {
semanticRecall: {
filter: {
$and: [{ projectId: { $eq: 'project-a' } }, { priority: { $gte: 3 } }],
},
},
}
服务端 embedding服务端 embedding的直接链接
某些向量存储会自行生成 embedding。使用这类存储时,语义召回无需 embedder 即可运行:数据库在写入时对每条消息进行 embedding,在搜索文本到达时对其进行 embedding。embedding 提供商完全不需要出现在你的应用中。
MongoDB 通过 Automated Embedding 实现这一点:在向量存储上指定一个 Voyage AI 模型,并省略 embedder。
import { Memory } from '@mastra/memory'
import { MongoDBStore, MongoDBVector } from '@mastra/mongodb'
const memory = new Memory({
storage: new MongoDBStore({
id: 'agent-storage',
uri: process.env.MONGODB_URI,
dbName: process.env.MONGODB_DB_NAME,
}),
vector: new MongoDBVector({
id: 'agent-vector',
uri: process.env.MONGODB_URI,
dbName: process.env.MONGODB_DB_NAME,
autoEmbed: { model: 'voyage-4' },
}),
options: {
semanticRecall: { topK: 3, messageRange: 2 },
},
})
消息以文本形式存储,由 MongoDB 对其进行 embedding,因此模型选择和向量维度属于索引,而不属于你的应用。通过 agent 和通过 recall() 的召回方式相同。
MongoDB 在后台对新写入的消息进行 embedding。刚刚保存的消息可能无法立即被召回。
其他所有存储都要求你的应用提供向量,并且仍然需要 embedder。在既没有 embedder 也没有服务端 embedding 存储的情况下启用语义召回,会抛出错误并同时指出这两个选项。
Embedder 配置Embedder 配置的直接链接
语义召回依赖 embedding 模型将消息转换为 embedding。Mastra 通过 model router 支持使用 provider/model 字符串指定 embedding 模型,你也可以使用任何与 AI SDK 兼容的 embedding 模型。
使用 Model Router(推荐)使用 Model Router(推荐)的直接链接
最简单的方式是使用带自动补全支持的 provider/model 字符串:
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
const agent = new Agent({
id: 'agent',
memory: new Memory({
embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
options: {
semanticRecall: true,
},
}),
})
支持的 embedding 模型:
- OpenAI:
text-embedding-3-small、text-embedding-3-large、text-embedding-ada-002 - Google:
gemini-embedding-001 - OpenRouter:访问来自多个提供商的 embedding 模型
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
const agent = new Agent({
id: 'agent',
memory: new Memory({
embedder: new ModelRouterEmbeddingModel({
providerId: 'openrouter',
modelId: 'openai/text-embedding-3-small',
}),
}),
})
model router 会自动处理从环境变量(OPENAI_API_KEY、GOOGLE_API_KEY、OPENROUTER_API_KEY)检测 API key。Google 模型还会回退到 GOOGLE_GENERATIVE_AI_API_KEY。
使用 AI SDK 包使用 AI SDK 包的直接链接
你也可以直接使用 AI SDK 的 embedding 模型:
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { ModelRouterEmbeddingModel } from '@mastra/core/llm'
const agent = new Agent({
id: 'agent',
memory: new Memory({
embedder: new ModelRouterEmbeddingModel('openai/text-embedding-3-small'),
}),
})
使用 FastEmbed(本地)使用 FastEmbed(本地)的直接链接
要使用 FastEmbed(本地 embedding 模型),请安装 @mastra/fastembed:
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/fastembed@latest
pnpm add @mastra/fastembed@latest
yarn add @mastra/fastembed@latest
bun add @mastra/fastembed@latest
然后在 memory 中配置它:
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { fastembed } from '@mastra/fastembed'
const agent = new Agent({
id: 'agent',
memory: new Memory({
embedder: fastembed,
}),
})
FastEmbed 还为非英文内容提供了多语言 E5 模型。E5 是非对称的,因此它作为两个模型暴露:multilingualE5LargePassage 用于你索引的文本,multilingualE5LargeQuery 用于搜索文本。
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { fastembed } from '@mastra/fastembed'
const agent = new Agent({
id: 'agent',
memory: new Memory({
embedder: fastembed.multilingualE5LargePassage,
}),
})
Memory 在存储和召回消息时使用同一个 embedder,因此请选择这两个模型之一并一致地使用它。仅当你能控制流水线两端时(例如用 passage 模型建立索引、用 query 模型搜索的 RAG 工作流),才使用配对的 multilingualE5LargeQuery 模型。
多语言 E5 生成 1024 维向量。你的向量索引必须以匹配的维度创建,并且 E5 向量不能与同一索引中来自其他 embedder 的向量混用。
FastEmbed 模型每个输入最多嵌入 512 个 token(约 2,000 到 2,500 个英文字符)。更长的输入会被截断,因此超出限制的文本不会影响 embedding,也无法被语义召回找到。发生这种情况时,AI SDK v3 FastEmbed 模型会返回警告,旧版 v1 和 v2 模型则不会。如果你使用 FastEmbed 嵌入长文档,请将其分块以适应窗口,例如在 MDocument.chunk() 中使用 maxSize: 1500。
PostgreSQL 索引优化PostgreSQL 索引优化的直接链接
使用 PostgreSQL 作为向量存储时,你可以通过配置向量索引来优化语义召回性能。这对于拥有数千条消息的大规模部署尤为重要。
PostgreSQL 同时支持 IVFFlat 和 HNSW 索引。默认情况下,Mastra 会创建 IVFFlat 索引,但 HNSW 索引通常能提供更好的性能,尤其是对使用内积距离的 OpenAI embedding。
import { Memory } from '@mastra/memory'
import { PostgresStore, PgVector } from '@mastra/pg'
const agent = new Agent({
memory: new Memory({
storage: new PostgresStore({
id: 'agent-storage',
connectionString: process.env.DATABASE_URL,
}),
vector: new PgVector({
id: 'agent-vector',
connectionString: process.env.DATABASE_URL,
}),
options: {
semanticRecall: {
topK: 5,
messageRange: 2,
indexConfig: {
type: 'hnsw', // Use HNSW for better performance
metric: 'dotproduct', // Best for OpenAI embeddings
m: 16, // Number of bi-directional links (default: 16)
efConstruction: 64, // Size of candidate list during construction (default: 64)
},
},
},
}),
})
有关索引配置选项和性能调优的详细信息,请参阅 PgVector 配置指南。
禁用语义召回禁用语义召回的直接链接
语义召回默认禁用(semanticRecall: false)。每次调用都会增加延迟,因为新消息在 LLM 接收之前需要被转换为 embedding 并用于查询向量数据库。
在以下情况下应保持语义召回禁用:
- 消息历史已为当前对话提供足够的上下文。
- 你正在构建性能敏感的应用,例如实时双向音频,其中 embedding 和向量查询的延迟较为明显。
查看召回的消息查看召回的消息的直接链接
启用 tracing 后,通过语义召回检索到的任何消息都会出现在 agent 的 trace 输出中,与最近消息历史(如果已配置)并列展示。