如何使用 Mastra 和 Elasticsearch 构建代理式 AI 应用程序
通过一个实际示例,了解如何使用 Mastra 和 Elasticsearch 构建智能体 AI 应用。
在本文中,我们将介绍如何使用 Mastra TypeScript 框架来构建与 Elasticsearch 交互的智能体应用。
我们最近通过添加对 Elasticsearch 作为向量数据库的支持,参与了 mastra-ai/mastra 开源项目。借助这项新功能,您可以在 Mastra 中原生使用 Elasticsearch 来存储嵌入内容。除了向量之外,Elasticsearch 还提供了一系列高级功能,以满足您所有的上下文工程需求。(例如混合搜索和重排序).
本文详细介绍了使用 Elasticsearch 实现检索增强生成 (RAG) 架构的智能体的创建过程。我们将展示一个演示项目,其中采用智能体方法来与存储在 Elasticsearch 中的科幻电影数据语料库进行交互。该项目可在 elastic/mastra-elasticsearch-example 获取。
Mastra
Mastra 是一个用于创建智能体 AI 应用的 TypeScript 框架。
Mastra的项目结构如下:
src/
├── mastra/
│ ├── agents/
│ │ └── weather-agent.ts
│ ├── tools/
│ │ └── weather-tool.ts
│ ├── workflows/
│ │ └── weather-workflow.ts
│ ├── scorers/
│ │ └── weather-scorer.ts
│ └── index.ts
├── .env.example
├── package.json
└── tsconfig.json在 Mastra 中,您可以构建智能体、工具、工作流和评分。
智能体是一个接收消息作为输入并产生响应作为输出的类。智能体可以使用工具、大型语言模型 (LLM) 和内存(图 1)。

图 1:Mastra 中智能体工作原理示意图。
智能体的工具允许其与“外部世界”交互,例如与 Web API 通信或执行内部操作,如查询 Elasticsearch。内存组件对于存储对话历史(包括过去的输入和输出)至关重要。这些存储的上下文使智能体能够利用过去的交互,为未来的问题提供更知情且更相关的响应。
工作流允许您使用清晰、结构化的步骤来定义复杂的任务序列,而不是依赖单个智能体的推理(图 2)。它们让您可以完全控制任务的分解方式、数据在任务之间的移动方式以及何时执行哪些任务。工作流默认使用内置执行引擎运行,也可以部署到工作流运行器。

图 2:Mastra 中的工作流示例。
在 Mastra 中,您还可以定义分数,这些分数是通过模型评分、基于规则和统计方法来评估智能体输出的自动化测试结果。评分器返回分数:量化输出满足评估标准程度的数值(通常在 0 到 1 之间)。这些分数使您能够客观地跟踪性能、比较不同方法并识别 AI 系统中的改进领域。您可以使用自己的提示和评分函数自定义评分器。
Elasticsearch
要运行演示项目,我们需要一个正在运行的 Elasticsearch 实例。您可以在 Elastic Cloud 上激活免费试用版,或使用 start-local 脚本在本地安装:
curl -fsSL https://elastic.co/start-local | sh这将在您的计算机上安装 Elasticsearch 和 Kibana,并生成一个用于配置 Mastra 集成的 API 密钥。
API 密钥将显示为上一条命令的输出,并存储在 elastic-start-local 文件夹中的 .env 文件内。
安装与配置演示
我们创建了一个 elastic/mastra-elasticsearch-example 存储库,其中包含演示项目的源代码。存储库中报告的示例演示了如何在 Mastra 中创建一个实现 RAG 架构、用于从 Elasticsearch 检索文档的智能体。
我们为演示提供了一个关于科幻电影的数据集。我们从 Kaggle 上的 IMDb 数据集中提取了 500 部电影。
第一步是使用 npm 安装项目依赖,执行以下命令:
npm install然后我们需要配置包含各项设置的 .env 文件。我们可以使用以下命令,复制 .env.example 文件的结构来生成该文件:
cp .env.example .env现在我们可以编辑 .env 文件,补充缺失的信息:
OPENAI_API_KEY=
ELASTICSEARCH_URL=
ELASTICSEARCH_API_KEY=
ELASTICSEARCH_INDEX_NAME=scifi-moviesElasticsearch 索引的名称为 scifi-movies。如果您想更改它,可以使用环境变量 ELASTICSEARCH_INDEX_NAME。
我们使用 OpenAI 作为嵌入服务,这意味着您需要在 OPENAI_API_KEY 环境变量中提供 OpenAI 的 API 密钥。
示例中使用的嵌入模型是 openai/text-embedding-3-small,嵌入维度为 1536。
为了生成最终答案,我们使用了 openai/gpt-5-nano 模型来降低成本。
RAG 架构允许您使用性能较低(且通常成本较低)的 LLM 模型,因为答案落地的主要工作是由检索组件(此处为 Elasticsearch)承担。
较小的 LLM 仅负责两个主要任务:
重写/嵌入查询:将用户的自然语言问题转换为用于语义搜索的向量嵌入。
综合答案:获取高度相关的检索上下文块(文档/电影),并将它们合成为一个连贯的、最终的、人类可读的答案,并遵循给出的提示指示。
由于 RAG 流程可提供答案所需的精确事实上下文,最终的 LLM 不需要非常庞大或高度复杂,也不需要在其自身参数中拥有所有必需的知识(这正是大型、昂贵模型的优势所在)。它本质上是一个针对 Elasticsearch 提供的上下文的高级文本摘要器和格式化器,而不是一个功能齐全的知识库本身。这使得可以使用像 gpt-5-nano 等模型来优化成本和延迟。
配置完 .env 文件后,可以使用以下命令将电影数据导入 Elasticsearch:
npx tsx src/utility/store.ts您应该看到如下输出:
🚀 Starting ingestion of 500 movies from 500_scifi_movies.jsonl...
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 1/500 (0%) | ok:1 | fail:0 | chunks:1 | eta:19m 33s | current:Capricorn One
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 2/500 (0%) | ok:2 | fail:0 | chunks:2 | eta:10m 32s | current:Doghouse
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 3/500 (1%) | ok:3 | fail:0 | chunks:3 | eta:7m 33s | current:Dinocroc
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 4/500 (1%) | ok:4 | fail:0 | chunks:7 | eta:6m 10s | current:Back to the Future
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 5/500 (1%) | ok:5 | fail:0 | chunks:9 | eta:5m 14s | current:The Projected Man
Ingesting ░░░░░░░░░░░░░░░░░░░░░░░░ 6/500 (1%) | ok:6 | fail:0 | chunks:11 | eta:4m 41s | current:I, Robot
...
✅ Ingestion complete in 1m 46s. Success: 500, Failed: 0, Chunks: 693.scifi-movies 索引的映射包含以下字段:
embedding:dense_vector,1536 维,cosine 相似度。
description,包含电影描述的文本。
director,包含导演姓名的文本。
title,包含电影标题的文本。
我们使用 title + description 生成嵌入向量。由于 title 和 description 是两个独立的字段,将两者拼接可以确保生成的嵌入向量同时捕获电影的具体唯一标识 (title) 和丰富的描述性上下文 (description),从而实现更准确、更全面的语义搜索结果。这种组合输入为嵌入模型提供了更好的文档内容单一表示,便于相似性匹配。
运行演示
您可以使用以下命令运行演示:
npm run dev该命令将在 localhost:4111 启动一个 Web 应用,以访问 Mastra Studio(图3)。

图 3: Mastra Studio 的屏幕截图,其中包含 Elasticsearch Agent 示例。
Mastra Studio提供了一个交互式 UI 用于构建和测试您的智能体,以及一个将 Mastra 应用程序作为本地服务公开的 REST API。这让您可以立即开始构建,无需担心集成问题。
我们提供了一个 Elasticsearch Agent,它使用 Mastra 的 createVectorQueryTool 作为工具,利用 Elasticsearch 执行语义搜索。该智能体采用 RAG 方法搜索相关文档(即电影)来回答用户的问题。
该智能体使用以下提示:
You are a helpful assistant that answers questions based on the provided context.
Follow these steps for each response:
1. First, carefully analyze the retrieved context chunks and identify key information.
2. Break down your thinking process about how the retrieved information relates to the query.
3. Draw conclusions based only on the evidence in the retrieved context.
4. If the retrieved chunks don't contain enough information, explicitly state what's missing.
Format your response as:
THOUGHT PROCESS:
- Step 1: [Initial analysis of retrieved chunks]
- Step 2: [Reasoning based on chunks]
FINAL ANSWER:
[Your concise answer based on the retrieved context]
Important: When asked to answer a question, please base your answer only on the context provided in the tool.
If the context doesn't contain enough information to fully answer the question, please state that explicitly and stop it.
Do not add more information than what is present in the retrieved chunks.
Remember: Explain how you're using the retrieved information to reach your conclusions.如果您点击 Mastra Studio > Agents菜单并选择 Elasticsearch Agent,则可以使用聊天系统测试该智能体。例如,您可以提出如下关于科幻电影的问题:
查找五部关于 UFO 的电影或电视剧。
您会注意到智能体将执行 vectorQueryTool。您可以点击调用的工具来查看输入和输出。执行结束时,LLM 将根据来自 Elasticsearch 的 scifi-movies 索引的上下文回答您的问题(图 4)。

图4:使用 Elasticsearch 智能体的 LLM 响应。
Mastra 在内部执行以下步骤:
向量转换:用户的问题 “查找五部关于 UFO 的电影或电视剧” 使用 OpenAI 的
openai/text-embedding-3-small模型转换为向量嵌入。向量搜索:然后将此嵌入向量用于通过向量搜索查询 Elasticsearch。
结果检索:Elasticsearch 返回一组与查询高度相关的 10 部电影(即那些向量与用户查询向量最接近的电影)。
答案生成:检索到的电影和原始用户问题被发送给 LLM,具体为
openai/gpt-5-nano。LLM 处理这些信息并生成最终答案,确保满足用户请求的五个结果。
Elasticsearch 智能体
下面我们展示了 Elasticsearch 智能体的源代码。
import { Agent } from "@mastra/core/agent";
import { ElasticSearchVector } from '@mastra/elasticsearch';
import { createVectorQueryTool } from '@mastra/rag';
import { ModelRouterEmbeddingModel } from "@mastra/core/llm";
import { Memory } from "@mastra/memory";
const es_url = process.env.ELASTICSEARCH_URL;
const es_apikey = process.env.ELASTICSEARCH_API_KEY;
const es_index_name = process.env.ELASTICSEARCH_INDEX_NAME;
const prompt = 'insert here the previous prompt';
const esVector = new ElasticSearchVector({
id: 'elasticsearch-vector',
url: es_url,
auth: {
apiKey : es_apikey
}
});
const vectorQueryTool = createVectorQueryTool({
vectorStore: esVector,
indexName: es_index_name,
model: new ModelRouterEmbeddingModel("openai/text-embedding-3-small")
});
export const elasticsearchAgent = new Agent({
id: "elasticsearch-agent",
name: "Elasticsearch Agent",
instructions: prompt,
model: 'openai/gpt-5-nano',
tools: { vectorQueryTool },
memory: new Memory(),
});vectorQueryTool 是被调用来实现 RAG 示例中检索部分的工具。它使用了 Elastic 为 Mastra 贡献的 ElasticSearchVector 实现。
该智能体是 agent 类的一个对象,它使用了 vectorQueryTool、提示和内存组件。可以看出,将 Elasticsearch 连接到智能体所需的代码量非常少。
结论
本文展示了将 Elasticsearch 与 Mastra 框架集成以构建复杂的智能体 AI 应用程序的简便性和强大功能。具体来说,我们逐步实现了一个 RAG 智能体,能够对 Elasticsearch 中索引的科幻电影数据语料库执行语义搜索。
一个关键收获是 Elastic 对 Mastra 开源项目的直接贡献,提供了 Elasticsearch 作为向量存储的原生支持。这种集成显著降低了入门门槛,正如 Elasticsearch Agent 源代码所证明的那样。使用 ElasticSearchVector 和 createVectorQueryTool,将 Elasticsearch 连接到智能体的完整设置仅需最少数量的配置代码行。
Elasticsearch 提供了多项高级功能来增强结果相关性。例如,混合搜索通过将词法搜索与向量搜索相结合,显著提高了准确性。另一个有趣的功能是在混合搜索结束时使用最新的Jina 模型重排序。要了解有关这些技术的更多信息,请参阅 Elasticsearch Labs 的以下文章:
Elasticsearch 混合搜索 - Valentin Crettaz
Jina 模型介绍、功能及其在 Elasticsearch 中的应用 作者:Scott Martens
我们还鼓励您探索所提供的示例,并开始使用 Mastra 和 Elasticsearch 构建自己的数据驱动的智能体应用。如需了解更多关于 Mastra 的信息,您可在此处查看官方文档。




