跳到主要内容

MongoDB Atlas

MongoDB Atlas 是一项全托管云数据库服务,可在 AWS、Azure 和 GCP 上使用。它支持在 MongoDB 文档数据上原生使用 向量搜索(Vector Search)以及全文搜索(BM25 算法)。

Atlas Vector Search 功能允许你将嵌入向量存储在 MongoDB 文档中、创建向量搜索索引, 并使用一种称为 Hierarchical Navigable Small Worlds(分层可导航小世界)的近似最近邻算法 执行 KNN 搜索。 LangChain4j 与 MongoDB 的集成在内部通过 $vectorSearch 聚合阶段实现 Atlas Vector Search。

你可以将 Atlas Vector Search 与 LangChain4j 结合使用,对数据进行语义搜索, 并构建简单的 RAG 实现。若要查看完成这些任务的完整教程,请参阅 MongoDB Atlas 文档中的 Get Started with the LangChain4j Integration 教程。

先决条件​

要使用 Atlas Vector Search,部署必须运行以下 MongoDB Server 版本之一:

  • 6.0.11 或更高版本
  • 7.0.2 或更高版本

MongoDB 提供永久免费的集群。请参阅 Get Started with Atlas 教程, 了解如何创建账户并连接到部署。

你还必须拥有带额度的 API 密钥,用于提供嵌入模型的 LLM 服务,例如 Voyage AI(提供免费层级)。对于 RAG 应用,你还必须拥有支持聊天模型功能的服务的 API 密钥,例如 OpenAI 或来自 HuggingFace 的模型。

环境与安装​

  1. 在你喜欢的 IDE 中创建新的 Java 应用程序。
  2. 向应用程序添加以下依赖项,以安装 LangChain4j 和 MongoDB Java Sync Driver:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-mongodb-atlas</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>5.4.0</version>
</dependency>

你还必须安装嵌入模型的依赖项,例如 Voyage AI:

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-voyage-ai</artifactId>
</dependency>

我们还建议添加 LangChain4j BOM:

<dependencyManagement>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.18.1-beta28</version>
<type>pom</type>
</dependency>
</dependencyManagement>

将 MongoDB Atlas 用作嵌入存储​

  1. 实例化一个嵌入模型。
  2. 将 MongoDB Atlas 实例化为嵌入存储。

构建 MongoDbEmbeddingStore 实例时,可以通过向 createIndex() 方法传入 true 来启用自动索引创建。

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.voyageai.VoyageAiEmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.EmbeddingSearchResult;
import dev.langchain4j.store.embedding.filter.comparison.*;
import dev.langchain4j.store.embedding.mongodb.IndexMapping;
import dev.langchain4j.store.embedding.mongodb.MongoDbEmbeddingStore;
import org.bson.Document;

import java.io.*;
import java.util.*;

String embeddingApiKey = System.getenv("VOYAGE_AI_KEY");
String uri = System.getenv("MONGODB_URI");

EmbeddingModel embeddingModel = VoyageAiEmbeddingModel.builder()
.apiKey(embeddingApiKey)
.modelName("voyage-3")
.build();

MongoClient mongoClient = MongoClients.create(uri);

System.out.println("Instantiating the embedding store...");

// Set to false if the vector index already exists
Boolean createIndex = true;

IndexMapping indexMapping = IndexMapping.builder()
.dimension(embeddingModel.dimension())
.metadataFieldNames(new HashSet<>())
.build();

MongoDbEmbeddingStore embeddingStore = MongoDbEmbeddingStore.builder()
.databaseName("search")
.collectionName("langchaintest")
.createIndex(createIndex)
.indexName("vector_index")
.indexMapping(indexMapping)
.fromClient(mongoClient)
.build();

将数据存储到 MongoDB​

以下代码演示如何将文档持久化到嵌入存储。 embed() 方法会为文档中 text 字段的值生成嵌入向量。

ArrayList<Document> docs = new ArrayList<>();

docs.add(new Document()
.append("text", "Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates.")
.append("metadata", new Metadata(Map.of("website", "Science Direct"))));

docs.add(new Document()
.append("text", "Emperor penguins are amazing birds. They not only survive the Antarctic winter, but they breed during the worst weather conditions on earth.")
.append("metadata", new Metadata(Map.of("website", "Our Earth"))));

docs.add(...);

System.out.println("Persisting document embeddings...");

for (Document doc : docs) {
TextSegment segment = TextSegment.from(
doc.getString("text"),
doc.get("metadata", Metadata.class)
);
Embedding embedding = embeddingModel.embed(segment).content();
embeddingStore.add(embedding, segment);
}

执行语义 / 相似度搜索​

以下代码演示如何创建搜索请求:将查询转换为向量, 并返回语义上相似的文档。得到的 EmbeddingMatch 实例 包含文档内容,以及描述每个结果与查询匹配程度的分数。

String query = "Where do penguins live?";
Embedding queryEmbedding = embeddingModel.embed(query).content();

EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.maxResults(3)
.build();

System.out.println("Performing the query...");

EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(searchRequest);
List<EmbeddingMatch<TextSegment>> matches = searchResult.matches();

for (EmbeddingMatch<TextSegment> embeddingMatch : matches) {
System.out.println("Response: " + embeddingMatch.embedded().text());
System.out.println("Author: " + embeddingMatch.embedded().metadata().getString("author"));
System.out.println("Score: " + embeddingMatch.score());
}

元数据过滤​

你可以在构建 EmbeddingSearchRequest 时使用 filter() 方法实现元数据过滤。 filter() 方法接受一个继承自 Filter 的参数。

以下代码实现了元数据过滤,仅保留 website 的值属于所列值之一的文档。

EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.filter(new IsIn("website", List.of("Our Earth", "Natural Habitats")))
.maxResults(3)
.build();

RAG​

若要查看以 MongoDB Atlas 作为向量存储实现 RAG 的说明,请参阅 Atlas 文档中 LangChain4j 教程的 Use Your Data to Answer Questions 部分。

API 文档​

有用链接​