Elasticsearch 是一个分布式、RESTful 搜索引擎,针对生产规模工作负载的速度和相关性进行了优化。它支持使用 k-最近邻 (kNN) 算法的向量搜索,还支持 用于自然语言处理的自定义模型 (NLP)。
您可以 在此处 阅读有关 Elasticsearch 中向量搜索支持的更多信息。
本指南提供了使用 Elasticsearch 向量存储的快速概述。有关所有 ElasticVectorSearch 功能和配置的详细文档,请参阅 API 参考。
集成细节
安装和设置
安装包
要使用 Elasticsearch 向量存储,您需要安装 @langchain/community 集成包。
LangChain.js 接受 @elastic/elasticsearch 作为 Elasticsearch 向量存储的客户端。您需要将其作为对等依赖项安装。
本指南还将使用 OpenAI 嵌入,这需要您安装 @langchain/openai 集成包。如果您愿意,也可以使用 其他支持的嵌入模型。
npm install @langchain/community @elastic/elasticsearch @langchain/openai @langchain/core
设置 Elasticsearch
可以通过三种方式开始使用 Elasticsearch:
选项 1:start-local(建议用于开发)
在本地设置 Elasticsearch 进行开发和测试的最快方法是使用 start-local 脚本。此脚本使用单个命令在 Docker 中设置 Elasticsearch 和 Kibana。
curl -fsSL https://elastic.co/start-local | sh
此脚本创建一个包含以下内容的 elastic-start-local 文件夹:
- Elasticsearch 和 Kibana 的配置文件
- 带有连接详细信息和凭据的
.env 文件
运行脚本后,您可以在 .env 文件中找到您的凭据:
cd elastic-start-local
cat .env
.env 文件包含 ES_LOCAL_URL 和 ES_LOCAL_API_KEY,您可以使用它们进行连接:
const config: ClientOptions = {
node: process.env.ES_LOCAL_URL ?? "http://localhost:9200",
auth: {
apiKey: process.env.ES_LOCAL_API_KEY,
},
};
要停止和启动服务:
# Stop the services
./elastic-start-local/stop.sh
# Start the services
./elastic-start-local/start.sh
# Uninstall completely
./elastic-start-local/uninstall.sh
有关更多信息,请参阅 start-local GitHub 存储库。
选项 2:Docker(手动设置)
您可以使用 官方 Docker 镜像 开始。运行禁用安全性的单节点 Elasticsearch 实例。不建议用于生产环境。
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" -e "xpack.security.http.ssl.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:8.17.0
选项 3:Elastic Cloud
Elastic Cloud 是托管的 Elasticsearch 服务。您可以注册 免费试用。
- 创建部署
- 获取您的 Cloud ID:
- 在 Elastic Cloud 控制台 中,单击部署旁边的“管理”
- 复制 Cloud ID 并将其粘贴到您的配置中
- 创建 API 密钥:
- 在 Elastic Cloud 控制台 中,单击部署旁边的“打开”
- 在左侧菜单中,转到“堆栈管理”,然后转到“API 密钥”
- 单击“创建 API 密钥”
- 输入 API 密钥的名称,然后单击“创建”
- 复制 API 密钥并将其粘贴到您的配置中
有关连接到 Elastic Cloud 的信息,您可以阅读 此处 报告的有关获取 API 密钥的文档。
如果您在本指南中使用 OpenAI 嵌入,您还需要设置您的 OpenAI 密钥:
process.env.OPENAI_API_KEY = "YOUR_API_KEY";
如果您想获取模型调用的自动跟踪,您还可以通过取消注释以下内容来设置您的 LangSmith API 密钥:
// process.env.LANGSMITH_TRACING="true"
// process.env.LANGSMITH_API_KEY="your-api-key"
ElasticVectorSearch
ElasticVectorSearch 类将 Elasticsearch 作为向量存储提供,支持标准向量搜索和混合搜索。
实例化
实例化 Elasticsearch 会因您的实例托管位置而异。
import {
ElasticVectorSearch,
type ElasticClientArgs,
} from "@langchain/community/vectorstores/elasticsearch";
import { OpenAIEmbeddings } from "@langchain/openai";
import { Client, type ClientOptions } from "@elastic/elasticsearch";
import * as fs from "node:fs";
const embeddings = new OpenAIEmbeddings({
model: "text-embedding-3-small",
});
const config: ClientOptions = {
node: process.env.ELASTIC_URL ?? "https://127.0.0.1:9200",
};
if (process.env.ELASTIC_API_KEY) {
config.auth = {
apiKey: process.env.ELASTIC_API_KEY,
};
} else if (process.env.ELASTIC_USERNAME && process.env.ELASTIC_PASSWORD) {
config.auth = {
username: process.env.ELASTIC_USERNAME,
password: process.env.ELASTIC_PASSWORD,
};
}
// Local Docker deploys require a TLS certificate
if (process.env.ELASTIC_CERT_PATH) {
config.tls = {
ca: fs.readFileSync(process.env.ELASTIC_CERT_PATH),
rejectUnauthorized: false,
}
}
const clientArgs: ElasticClientArgs = {
client: new Client(config),
indexName: process.env.ELASTIC_INDEX ?? "test_vectorstore",
};
const vectorStore = new ElasticVectorSearch(embeddings, clientArgs);
addDocuments
向向量存储添加文档。
import type { Document } from "@langchain/core/documents";
const document1: Document = {
pageContent: "The powerhouse of the cell is the mitochondria",
metadata: { source: "https://example.com" }
};
const document2: Document = {
pageContent: "Buildings are made out of brick",
metadata: { source: "https://example.com" }
};
const document3: Document = {
pageContent: "Mitochondria are made out of lipids",
metadata: { source: "https://example.com" }
};
const document4: Document = {
pageContent: "The 2024 Olympics are in Paris",
metadata: { source: "https://example.com" }
}
const documents = [document1, document2, document3, document4];
await vectorStore.addDocuments(documents, { ids: ["1", "2", "3", "4"] });
delete
按 ID 从向量存储中删除文档。
await vectorStore.delete({ ids: ["4"] });
similaritySearch
执行相似性搜索以查找与查询相似的文档。
const filter = [{
operator: "match",
field: "source",
value: "https://example.com",
}];
const similaritySearchResults = await vectorStore.similaritySearch("biology", 2, filter);
for (const doc of similaritySearchResults) {
console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);
}
* The powerhouse of the cell is the mitochondria [{"source":"https://example.com"}]
* Mitochondria are made out of lipids [{"source":"https://example.com"}]
向量存储支持 Elasticsearch 过滤器语法 运算符。
similaritySearchWithScore
执行相似性搜索并返回分数。
const similaritySearchWithScoreResults = await vectorStore.similaritySearchWithScore("biology", 2, filter)
for (const [doc, score] of similaritySearchWithScoreResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent} [${JSON.stringify(doc.metadata)}]`);
}
* [SIM=0.374] The powerhouse of the cell is the mitochondria [{"source":"https://example.com"}]
* [SIM=0.370] Mitochondria are made out of lipids [{"source":"https://example.com"}]
asRetriever
将向量存储转换为检索器以在链中使用。
const retriever = vectorStore.asRetriever({
// Optional filter
filter: filter,
k: 2,
});
await retriever.invoke("biology");
[
Document {
pageContent: 'The powerhouse of the cell is the mitochondria',
metadata: { source: 'https://example.com' },
id: undefined
},
Document {
pageContent: 'Mitochondria are made out of lipids',
metadata: { source: 'https://example.com' },
id: undefined
}
]
HybridRetrievalStrategy
混合搜索需要 Elasticsearch 8.9+ 以支持 RRF(倒数排名融合)。
混合搜索使用倒数排名融合 (RRF) 将 kNN 向量搜索与 BM25 全文搜索相结合,以提高搜索相关性。当您想利用语义相似性和关键字匹配时,这很有用。
配置选项
| Parameter | Type | Default | Description |
|---|
rankWindowSize | number | 100 | 考虑用于 RRF 的文档数 |
rankConstant | number | 60 | 用于分数归一化的 RRF 常数 |
textField | string | "text" | 用于 BM25 全文搜索的字段 |
基本用法
要启用混合搜索,请将 HybridRetrievalStrategy 传递给构造函数:
import {
ElasticVectorSearch,
HybridRetrievalStrategy,
type ElasticClientArgs,
} from "@langchain/community/vectorstores/elasticsearch";
const hybridVectorStore = new ElasticVectorSearch(embeddings, {
client: new Client(config),
indexName: "test_hybrid_search",
strategy: new HybridRetrievalStrategy({
rankWindowSize: 100, // Number of documents to consider for RRF
rankConstant: 60, // RRF constant for score normalization
textField: "text", // Field to use for BM25 full-text search
}),
});
配置后,混合搜索将自动用于所有相似性搜索:
// This now uses hybrid search (vector + BM25 + RRF)
const results = await hybridVectorStore.similaritySearch(
"how to prevent muscle soreness while running",
5
);
完整的混合搜索示例
import { Client, ClientOptions } from "@elastic/elasticsearch";
import { OpenAIEmbeddings } from "@langchain/openai";
import {
ElasticClientArgs,
ElasticVectorSearch,
HybridRetrievalStrategy,
} from "@langchain/community/vectorstores/elasticsearch";
import { Document } from "@langchain/core/documents";
// Configure Elasticsearch client
const config: ClientOptions = {
node: process.env.ES_LOCAL_URL ?? "http://127.0.0.1:9200",
};
if (process.env.ES_LOCAL_API_KEY) {
config.auth = {
apiKey: process.env.ES_LOCAL_API_KEY,
};
}
const embeddings = new OpenAIEmbeddings();
// Create vector store with hybrid search strategy
const clientArgs: ElasticClientArgs = {
client: new Client(config),
indexName: "test_hybrid_search",
strategy: new HybridRetrievalStrategy({
rankWindowSize: 100,
rankConstant: 60,
textField: "text",
}),
};
const vectorStore = new ElasticVectorSearch(embeddings, clientArgs);
// Add documents
await vectorStore.addDocuments([
new Document({
pageContent: "Running improves cardiovascular health and endurance",
metadata: { category: "fitness" },
}),
new Document({
pageContent: "Proper hydration prevents muscle cramps during exercise",
metadata: { category: "fitness" },
}),
new Document({
pageContent: "Stretching before running reduces injury risk",
metadata: { category: "fitness" },
}),
]);
// Search using hybrid (vector + BM25)
const results = await vectorStore.similaritySearch(
"how to prevent muscle soreness while running",
3
);
console.log(results);
用于检索增强生成的用法
有关如何将此向量存储用于检索增强生成 (RAG) 的指南,请参阅以下部分:
API 参考
有关所有 ElasticVectorSearch 功能和配置的详细文档,请参阅 API 参考.
相关资源