主题
MongoDB Atlas
MongoDB Atlas 是一款可在 AWS、Azure 与 GCP 上使用的托管云数据库。它对 MongoDB 文档数据支持原生向量搜索与全文搜索(BM25 算法)。
Atlas Vector Search 功能允许你在 MongoDB 文档中存储嵌入、创建向量搜索索引,并使用一种名为分层可导航小世界(HNSW)的近似最近邻算法执行 KNN 搜索。MongoDB 与 LangChain4j 的集成在内部通过 $vectorSearch 聚合阶段来实现 Atlas Vector Search。
你可以将 Atlas Vector Search 与 LangChain4j 一起用于对你的数据执行语义搜索,并构建一个简单的 RAG 实现。要查看执行这些任务的完整教程,参见 MongoDB Atlas 文档中的 Get Started with the LangChain4j Integration 教程。
前置条件
你必须有运行以下 MongoDB Server 版本的部署,才能使用 Atlas Vector Search:
- 6.0.11 或更新版本
- 7.0.2 或更新版本
MongoDB 提供一个永久免费集群。参见 Get Started with Atlas 教程,了解更多关于设置账户并连接到部署的内容。
你还必须拥有一个有额度的 API 密钥,用于提供嵌入模型的 LLM 服务,例如提供免费档的 Voyage AI。对于 RAG 应用,你还必须拥有一个具备聊天模型功能的服务的 API 密钥,例如 OpenAI 或来自 HuggingFace 的模型。
环境与安装
- 在你偏好的 IDE 中创建一个新的 Java 应用。
- 向你的应用添加以下依赖,以安装 LangChain4j 与 MongoDB Java Sync Driver:
xml
<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>1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
你还必须安装一个嵌入模型的依赖,例如 Voyage AI:
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-voyage-ai</artifactId>
</dependency>1
2
3
4
2
3
4
我们也建议添加 LangChain4j BOM:
xml
<dependencyManagement>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>1.22.0-beta32</version>
<type>pom</type>
</dependency>
</dependencyManagement>1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
将 MongoDB Atlas 用作嵌入存储
- 实例化一个嵌入模型。
- 将 MongoDB Atlas 实例化为嵌入存储。
你可以在构建 MongoDbEmbeddingStore 实例时向 createIndex() 方法传入 true,以启用自动索引创建。
java
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();1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
将数据存入 MongoDB
这段代码演示了如何将你的文档持久化到嵌入存储。embed() 方法会为你文档中 text 字段的值生成嵌入。
java
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);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
执行语义/相似度搜索
这段代码演示了如何创建一个搜索请求,它将你的查询转换为一个向量并返回语义上相似的文档。所得的 EmbeddingMatch 实例既包含文档内容,也包含一个描述每个结果与你查询匹配程度的分数。
java
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());
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
元数据过滤
你可以在构建 EmbeddingSearchRequest 时通过 filter() 方法实现元数据过滤。filter() 方法接受一个继承自 Filter 的参数。
这段代码对 website 取值属于所列值之一的文档实现元数据过滤。
java
EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder()
.queryEmbedding(queryEmbedding)
.filter(new IsIn("website", List.of("Our Earth", "Natural Habitats")))
.maxResults(3)
.build();1
2
3
4
5
2
3
4
5
RAG
要查看以 MongoDB Atlas 作为向量存储实现 RAG 的说明,参见 Atlas 文档中 LangChain4j 教程的 Use Your Data to Answer Questions 部分。