You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Semantic Kernel在CosmosDB对象数组中执行向量搜索

问题分析与解决方案

核心问题

你要实现的是单文档内嵌套数组元素的向量搜索,但Semantic Kernel默认的向量存储集成只支持集合级别的文档搜索(每个文档对应一条向量记录),当前的实体类设计和索引策略无法适配这种嵌套场景。

问题根源

  1. 实体注解无效:BgBomVectorItem上的[VectorStoreRecordKey]注解没用,Semantic Kernel只会识别根实体的键字段,嵌套类的这个注解不会被处理。
  2. CosmosDB索引限制:默认向量索引是针对文档级字段的,没法直接给嵌套数组里的向量字段建有效索引,导致数组内的向量搜索无法正常执行。
  3. SK API局限:现有向量搜索API都是针对整个容器的文档,没有直接支持先筛选单个文档、再对其数组字段做向量搜索的方法。

可行解决方案

方案1:重构数据结构(推荐)

把BgBomVectorItem拆成独立的CosmosDB容器,每个条目关联对应的模型ID:

// 独立的向量条目实体
public class BgBomVectorItem
{
    [VectorStoreRecordKey]
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    // 关联所属模型的ID
    public string ModelId { get; set; }

    [VectorStoreRecordData(IsFullTextSearchable = true)]
    public string Information { get; set; }

    [VectorStoreRecordVector(4, DistanceFunction.EuclideanDistance, IndexKind.Flat)]
    public ReadOnlyMemory<float> DescriptionEmbedding { get; set; }
}

操作流程:

  • 新建CosmosDB容器(比如bombvectoritems)存储拆分后的条目
  • 原BgBomVectorModel只保留基础信息,移除BomItemsInformation数组
  • 搜索时先通过ModelId筛选,再执行向量搜索:
// Semantic Kernel 示例代码
var vectorStore = kernel.Services.GetRequiredService<IVectorStore>();
var searchResults = await vectorStore.SearchAsync<BgBomVectorItem>(
    queryEmbedding: 你的查询向量,
    limit: 6,
    filter: $"ModelId eq '{选中的模型ID}'"
);

优势:完全适配Semantic Kernel的向量搜索能力,CosmosDB可以给ModelId和向量字段建复合索引,性能最优。

方案2:保留原结构,用CosmosDB原生SQL查询

如果不能重构数据,直接用CosmosDB的SQL结合向量函数,绕开Semantic Kernel的向量存储封装:

SELECT TOP 6 item
FROM c
JOIN item IN c.BomItemsInformation
WHERE c.id = @modelId
ORDER BY VECTOR_DISTANCE(item.DescriptionEmbedding, @queryVector, 'Euclidean') ASC

C#代码实现:

var cosmosClient = new CosmosClient("你的连接字符串");
var container = cosmosClient.GetContainer("数据库名", "vectormodels");

var queryDefinition = new QueryDefinition(
    "SELECT TOP 6 item " +
    "FROM c " +
    "JOIN item IN c.BomItemsInformation " +
    "WHERE c.id = @modelId " +
    "ORDER BY VECTOR_DISTANCE(item.DescriptionEmbedding, @queryVector, 'Euclidean') ASC"
)
.WithParameter("@modelId", 选中的模型ID)
.WithParameter("@queryVector", 你的查询向量.ToArray());

var iterator = container.GetItemQueryIterator<BgBomVectorItem>(queryDefinition);
var results = new List<BgBomVectorItem>();
while (iterator.HasMoreResults)
{
    var response = await iterator.ReadNextAsync();
    results.AddRange(response.Resource);
}

注意事项:

  • 必须手动给BomItemsInformation[*].DescriptionEmbedding字段创建向量索引,索引策略示例:
{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/BomItemsInformation/*/DescriptionEmbedding/?",
            "indexes": [
                {
                    "kind": "Vector",
                    "dataType": "float32",
                    "dimensions": 4,
                    "distanceFunction": "Euclidean"
                }
            ]
        }
    ]
}

劣势:没法直接用Semantic Kernel的向量存储抽象,需要自己处理CosmosDB的查询逻辑。

原实体类修正建议

如果坚持用原结构,要删掉BgBomVectorItem上的[VectorStoreRecordKey]注解,这个注解只对根实体有效:

public class BgBomVectorItem
{
    // 移除[VectorStoreRecordKey],改用普通属性
    public string id { get; set; }

    [VectorStoreRecordData(IsFullTextSearchable = true)]
    public string Information { get; set; }

    [VectorStoreRecordVector(4, DistanceFunction.EuclideanDistance, IndexKind.Flat)]
    public ReadOnlyMemory<float> DescriptionEmbedding { get; set; }
}

内容的提问来源于stack exchange,提问作者Андрій Гуцалюк

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:22:04