跳到主要内容

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 文档

有用链接