使用Azure Cosmos DB for MongoDB进行向量搜索的演示
我得知在2023年5月的MS Build上,Azure Cosmos DB for mongoDB vcore发布了向量搜索功能,我试着用了一下。
我制作出了什么东西
-
- 将上传到SharePoint的文件保存到Cosmos DB中的向量
- 使用Cosmos DB的向量索引进行相似文件的搜索
关于第二点,只允许使用文本文件进行操作。
1. 向 Cosmos DB 存储向量
Wikipediaからドラゴンボールとハンターハンターの文章を取ってきて、それぞれをテキストファイルにしてSharePointにアップロードします。
过了一会(几秒钟)
向量搜索
我将进行对上述保存的文件进行搜索。
构成
※Azure Functions使用C#编写。
实施方式
以下将会分成两部分进行说明。
-
- 向量保存的实现
- 向量搜索的实现
向量存储的实现
我将对各Azure资源的实现进行说明。
-
- LogicApps – 逻辑应用
-
- Azure Functions – Azure 函数
- Cosmos DB – Cosmos 数据库
逻辑应用
Azure函数
Azure Functions是使用C#进行编写的。
遥控器 qì)
当在demo容器中创建Blob文件时,会触发操作。
public class DocumentVectorRegister
{
private readonly IVectorService vectorService;
public DocumentVectorRegister(IVectorService vectorService)
{
this.vectorService = vectorService;
}
[FunctionName("DocumentVectorRegister")]
public async Task Run([BlobTrigger("demo/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log)
{
await vectorService.RegisterDocumentVector(name);
}
}
Blob内容读取的存储库
public class BlobRepository : IBlobRepository
{
private readonly BlobServiceClient blobServiceClient;
private readonly IConfiguration configuration;
public BlobRepository(IAzureClientFactory<BlobServiceClient> clientFactory, IConfiguration configuration)
{
blobServiceClient = clientFactory.CreateClient("OpenAI");
this.configuration = configuration;
}
async Task<string> IBlobRepository.GetBlobContent(string filename)
{
var containerClient = blobServiceClient.GetBlobContainerClient(configuration["OpenAIContainerName"]);
var blobClient = containerClient.GetBlobClient(filename);
Response<BlobDownloadInfo> downloadResponse = await blobClient.DownloadAsync();
using (StreamReader reader = new StreamReader(downloadResponse.Value.Content))
{
return await reader.ReadToEndAsync();
}
}
}
使用Azure OpenAI的存储库中的矢量化部分。
public class OpenAIRepository : IOpenAIRepository
{
private readonly OpenAIClient openAIClient;
public OpenAIRepository(OpenAIClient openAIClient)
{
this.openAIClient = openAIClient;
}
async Task<List<float>> IOpenAIRepository.GetVector(string text)
{
EmbeddingsOptions embeddingOptions = new(text);
var returnValue = await openAIClient.GetEmbeddingsAsync("EmbeddingAda002", embeddingOptions);
var vectores = new List<float>();
foreach (float item in returnValue.Value.Data[0].Embedding)
{
vectores.Add(item);
}
return vectores;
}
}
向量存储部分的代码库
public class VectorRepository : IVectorRepository
{
private readonly IMongoClient mongoClient;
public VectorRepository(IMongoClient mongoClient)
{
this.mongoClient = mongoClient;
}
async Task IVectorRepository.RegisterDocument(Doc document)
{
var db = mongoClient.GetDatabase("sample_docs");
var _docs = db.GetCollection<Doc>("docs");
await _docs.InsertOneAsync(document);
}
{
宇宙数据库
作为步骤,情况如下。
-
- 创建用于MongoDB vcore的Cosmos DB资源
-
- 下载MongoDB Compass
- 创建数据库和集合
创建 Cosmos DB for MongoDB vcore 资源
通过Azure门户进行创建。没有特殊事项。
下载MongoDB Compass。
2023年6月時点では,Cosmos DB for MongoDB vcoreはプレビュー版であったため,Azure Portalにはデータエクスプローラーが存在しませんでした。そのため,データベースの作成やコレクションの作成にはダウンロードが必要でした。ダウンロードは以下のリンクから行いました。
https://www.mongodb.com/ja-jp/products/compass
创建数据库和集合
在连接之后,我们将使用mongoshell来创建数据库和集合。
创建数据库
use 'データベース名'
创建收藏品
db.createCollection('コレクション名')
请尝试将文件上传到SharePoint,并验证实际上是否在Cosmos DB中成功创建了数据,这样一来,向量存储的实现就完成了。
向量搜索的实现
我会对Azure资源的实现进行说明。
-
- Azure Functions (Azure函数)
- Cosmos DB (Cosmos数据库)
Azure函数
HTTPトリガーで作成します。
遥控器
public class SearchDocument
{
private readonly IVectorService vectorService;
public SearchDocument(IVectorService vectorService)
{
this.vectorService = vectorService;
}
[FunctionName("SearchDocument")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] [FromQuery]SearchRequestModel request)
{
var input = new SearchInputModel()
{
Keyword = request.Keyword,
};
var res = await vectorService.GetDocuments(input);
var result = new List<SearchDocumentsResponseModel>();
foreach (var item in res)
{
result.Add(new SearchDocumentsResponseModel() {
Text = item.Text,
Filename = item.Filename,
});
}
return new JsonResult(result);
}
}
将输入关键词的向量化存储库
我們將使用與先前保存的向量相同的物件。
矢量搜索存储库
在微軟的官方文件中,截至2023年6月,只記載了在monogoshell中進行搜索的方法,而且我不知道更好的方法,所以我使用BsonDocument來創建MongoDB查詢。
參考:使用$search對vectorIndex進行查詢。
public class VectorRepository : IVectorRepository
{
private readonly IMongoClient mongoClient;
public VectorRepository(IMongoClient mongoClient)
{
this.mongoClient = mongoClient;
}
async Task<List<Doc>> IVectorRepository.GetDocuments(List<float> vectors)
{
var db = mongoClient.GetDatabase("sample_docs");
var _docs = db.GetCollection<Doc>("docs");
BsonArray bsonVectorArray = new BsonArray();
foreach ( var v in vectors )
{
bsonVectorArray.Add(v);
}
PipelineDefinition<Doc, BsonDocument> pipeline = new BsonDocument[]
{
new BsonDocument("$search",
new BsonDocument
{
{ "cosmosSearch", new BsonDocument{ { "vector", bsonVectorArray }, { "path", "Vectors" }, { "k", 3 } } },
{ "returnStoredSource", true }
})
};
var resultDocuments = _docs.Aggregate(pipeline).ToList();
var result = BsonSerializer.Deserialize<List<Doc>>(resultDocuments.ToJson());
return result;
}
}
宇宙数据库
我们还将创建一个新的用于搜索的向量索引,以支持搜索功能。
参考:使用Azure Cosmos DB for MongoDB的嵌入式虚拟核心进行向量搜索。
use '先ほど作成したデータベース名'
创建索引
db.runCommand({
createIndexes: 'exampleCollection',
indexes: [
{
name: 'vectorSearchIndex',
key: {
"vectorContent": "cosmosSearch"
},
cosmosSearchOptions: {
kind: 'vector-ivf',
numLists: 100,
similarity: 'COS',
dimensions: 3
}
}
]
});
请在exampleCollection中指定刚刚创建的集合名称。
请在vectorContent中指定保存数据库中向量的列名称。
当成功创建索引时,将返回以下响应。
{
raw: {
defaultShard: {
numIndexesBefore: 1,
numIndexesAfter: 2,
createdCollectionAutomatically: false,
ok: 1
}
},
ok: 1
}
让我们实际输入关键词,看看是否可以获取包含该关键词的文件,这样就完成了向量搜索的实现。
最后的随记
-
- 今回はテキストファイルのみだったので、PDFやPowerPointなどにも対応できるといい。その際はAzure Functions内で、その形式に合わせたコンテンツ読み取りの実装を行う必要がありそう。
-
- SharePoint自体の検索にコンテンツ検索ができるため、SharePoint内の検索のみであれば今回の実装を使う必要はない。
- Azureのベクトル保存の実装方法は他にもたくさんあるので、要件に応じてどれを使うか選ぶ必要がある。