Azure AI 搜索中的矢量存储

Azure AI 搜索提供了用于进行矢量搜索混合搜索的矢量存储和配置。 支持在字段级别实现,这意味着你可以在同一搜索语料库中同时使用矢量字段和非矢量字段。

矢量存储在搜索索引中。 使用创建索引 REST API 或等效的 Azure SDK 方法来创建矢量存储

矢量存储相关注意事项包括以下几点:

  • 根据预期的矢量检索模式设计架构以适应用例。
  • 估计索引大小并检查搜索服务容量。
  • 管理矢量存储
  • 保护矢量存储

矢量检索模式

在 Azure AI 搜索中,有两种处理搜索结果的模式。

  • 生成式搜索。 语言模型使用 Azure AI 搜索中的数据构建对用户查询的响应。 此模式包括一个编排层,用于协调提示并维护上下文。 在此模式下,搜索结果会馈送到提示流中,并由聊天模型(如 GPT 和 Text-Davinci)接收。 此方法基于检索增强生成 (RAG) 体系结构,其中搜索索引提供上下文关联数据

  • 使用搜索栏、查询输入字符串和呈现的结果进行经典搜索。 搜索引擎接受和执行向量查询、构建响应,并在客户端应用中呈现这些结果。 在 Azure AI 搜索中,结果在平展行集中返回,可以选择包含搜索结果的字段。 由于没有聊天模型,应在响应中使用易于理解的非矢量内容来填充矢量存储(搜索索引)。 尽管搜索引擎在矢量上匹配,但应使用非矢量值来填充搜索结果。 矢量查询混合查询涵盖可为经典搜索方案制定的查询请求类型

索引架构应反映主要使用场景。 以下部分重点介绍为生成式 AI 或经典搜索而构建的解决方案的字段组合差异。

矢量存储的架构

矢量存储的索引架构需要名称、键字段(字符串)、一个或多个矢量字段与矢量配置。 建议在进行混合查询或一字不差地返回无需通过语言模型处理的易于理解的内容时,使用非矢量字段。 有关矢量配置的说明,请参阅创建矢量存储

基本矢量字段配置

矢量字段按数据类型和特定于矢量的属性进行区分。 下面是字段集合中矢量字段的显示方式:

{
    "name": "content_vector",
    "type": "Collection(Edm.Single)",
    "searchable": true,
    "retrievable": true,
    "dimensions": 1536,
    "vectorSearchProfile": "my-vector-profile"
}

矢量字段的类型为 Collection(Edm.Single)

矢量字段必须可搜索和可检索,但不可筛选、不可分面或不可排序,也不能有分析器、规范化器或同义词映射分配。

矢量字段的 dimensions 必须设置为由嵌入模型生成的嵌入数。 例如,text-embedding-ada-002 为每个文本区块生成 1,536 个嵌入。

矢量字段使用矢量搜索配置文件指示的算法编制索引,该配置文件在索引中的其他位置定义,因此在本示例中未显示。 有关详细信息,请参阅矢量搜索配置

基本矢量工作负载的字段集合

除矢量字段外,矢量存储还需要其他字段。 例如,键字段(在本示例中为 "id")是索引要求。

"name": "example-basic-vector-idx",
"fields": [
  { "name": "id", "type": "Edm.String", "searchable": false, "filterable": true, "retrievable": true, "key": true },
  { "name": "content_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": true, "dimensions": 1536, "vectorSearchProfile": null },
  { "name": "content", "type": "Edm.String", "searchable": true, "retrievable": true, "analyzer": null },
  { "name": "metadata", "type": "Edm.String", "searchable": true, "filterable": true, "retrievable": true, "sortable": true, "facetable": true }
]

其他字段(例如 "content" 字段)提供 "content_vector" 字段的人类可读等效项。 如果你专门使用语言模型进行响应表述,则可以省略非矢量内容字段,但直接将搜索结果推送到客户端应用的解决方案应具有非矢量内容。

元数据字段适用于筛选器,尤其是在元数据包含有关源文档的来源信息时。 你无法直接筛选矢量字段,但可以设置预筛选或筛选后模式,以在执行矢量查询之前或之后进行筛选。

由“导入和矢量化数据”向导生成的架构

建议使用导入和矢量化数据向导进行评估和概念证明测试。 该向导会在本部分中生成示例架构。

这种模式的偏向性在于,搜索文档是围绕数据块构建的。 如果语言模型生成了响应,就像 RAG 应用的典型情况一样,则需要围绕数据区块设计的架构。

数据分块对于保持在语言模型的输入限制内是必需的,但当查询可以与从多个父文档提取的较小内容区块进行匹配时,它也能提高相似性搜索的精准率。

在以下示例中,每个搜索文档都有一个区块 ID、区块、标题和矢量字段。 区块 ID 和父 ID 由向导使用 blob 元数据(路径)的 base 64 编码进行填充。 区块和标题派生自 blob 内容和 blob 名称。 仅矢量字段是完全生成的。 它是区块字段的矢量化版本。 嵌入是通过调用你提供的 Azure OpenAI 嵌入模型生成的。

"name": "example-index-from-import-wizard",
"fields": [
  {"name": "chunk_id",  "type": "Edm.String", "key": true, "searchable": true, "filterable": true, "retrievable": true, "sortable": true, "facetable": true, "analyzer": "keyword"},
  { "name": "parent_id", "type": "Edm.String", "searchable": true, "filterable": true, "retrievable": true, "sortable": true},
  { "name": "chunk", "type": "Edm.String", "searchable": true, "filterable": false, "retrievable": true, "sortable": false},
  { "name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "retrievable": true, "sortable": false},
  { "name": "vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": true, "dimensions": 1536, "vectorSearchProfile": "vector-1707768500058-profile"}
]

RAG 和聊天样式应用的架构

如果要为生成式搜索设计存储,可以为要为其编制索引和进行矢量化处理的静态内容创建单独的索引,然后为可在提示流中使用的对话创建第二个索引。 以下索引是从 chat-with-your-data-solution-accelerator 加速器创建的

加速器创建的索引的屏幕截图。

支持生成式搜索体验的聊天索引中的字段:

"name": "example-index-from-accelerator",
"fields": [
  { "name": "id", "type": "Edm.String", "searchable": false, "filterable": true, "retrievable": true },
  { "name": "content", "type": "Edm.String", "searchable": true, "filterable": false, "retrievable": true },
  { "name": "content_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": true, "dimensions": 1536, "vectorSearchProfile": "my-vector-profile"},
  { "name": "metadata", "type": "Edm.String", "searchable": true, "filterable": false, "retrievable": true },
  { "name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "retrievable": true, "facetable": true },
  { "name": "source", "type": "Edm.String", "searchable": true, "filterable": true, "retrievable": true  },
  { "name": "chunk", "type": "Edm.Int32", "searchable": false, "filterable": true, "retrievable": true },
  { "name": "offset", "type": "Edm.Int32", "searchable": false, "filterable": true, "retrievable": true }
]

支持业务流程和聊天历史记录的对话索引中的字段:

"fields": [
    { "name": "id", "type": "Edm.String", "key": true, "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": false },
    { "name": "conversation_id", "type": "Edm.String", "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": true },
    { "name": "content", "type": "Edm.String", "searchable": true, "filterable": false, "retrievable": true },
    { "name": "content_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": true, "dimensions": 1536, "vectorSearchProfile": "default-profile" },
    { "name": "metadata", "type": "Edm.String", "searchable": true, "filterable": false, "retrievable": true },
    { "name": "type", "type": "Edm.String", "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": true },
    { "name": "user_id", "type": "Edm.String", "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": true },
    { "name": "sources", "type": "Collection(Edm.String)", "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": true },
    { "name": "created_at", "type": "Edm.DateTimeOffset", "searchable": false, "filterable": true, "retrievable": true },
    { "name": "updated_at", "type": "Edm.DateTimeOffset", "searchable": false, "filterable": true, "retrievable": true }
]

下面的屏幕截图显示了搜索资源管理器中对话索引的搜索结果。 搜索分数为 1.00,因为搜索不合格。 请注意支持业务流程和提示流的字段。 聊天 ID 可标识特定聊天。 "type" 可指示内容是来自用户还是助手。 日期用于将历史记录中的聊天设置为过时。

搜索资源管理器的屏幕截图,其中包含专为 RAG 应用设计的索引的结果。

物理结构和大小

在 Azure AI 搜索中,索引的物理结构主要是内部实现。 你可以访问其架构、加载并查询其内容、监视其大小和管理容量,但群集本身(索引、分片以及其他文件和文件夹)是由 Microsoft 在内部管理的。

索引的大小和实质内容取决于:

  • 文档的数量和组合
  • 单个字段的属性。 例如,可筛选字段需要更多存储。
  • 索引配置,包括根据你是选择 HNSW 还是详尽 KNN 进行相似性搜索来指定如何创建内部导航结构的矢量配置。

Azure AI 搜索将对矢量存储施加限制,这有助于为所有工作负载维护均衡稳定的系统。 为了帮助你保持在限制之下,将会在 Azure 门户中单独跟踪和报告矢量使用情况,并通过服务和索引统计信息以编程方式进行。

以下屏幕截图显示了配置有一个分区和一个副本的 S1 服务。 此特定服务具有 24 个小型索引,平均每个索引包含一个矢量字段,并且每个字段包含 1536 个嵌入。 第二个磁贴则显示矢量索引的配额和使用情况。 矢量索引是为每个矢量字段创建的内部数据结构。 因此,矢量索引的存储始终是索引总体使用的存储的一部分。 其他非矢量字段和数据结构则使用其余部分。

显示存储、矢量索引和索引计数的使用情况磁贴的屏幕截图。

有关矢量索引限制和估算,请参阅另一篇文章,但首先需要强调两点,即最大存储因服务层级而异,也因搜索服务的创建时间会有所不同。 较新的同层服务可为矢量索引提供显著的更多容量。 出于这些原因,请执行以下操作:

  • 检查搜索服务的部署日期。 如果它是在 2024 年 4 月 3 日之前创建的,请考虑创建新的搜索服务来获得更高的容量。

  • 如果预计矢量存储要求会发生波动,请选择可缩放层。 基本层固定在更旧的搜索服务上的一个分区上。 请考虑使用标准 1 (S1) 层及更高层级来获得更大的灵活性和更快的性能,或者创建新的搜索服务,在每个可计费层级上使用更高的限制和更多分区。

基本操作和交互

本部分介绍矢量运行时操作,包括连接到和保护单个索引。

注意

管理索引时,请注意,没有用于移动或复制索引的门户或 API 支持。 相反,客户通常将其应用程序部署解决方案指向不同的搜索服务(如果使用相同的索引名称),或者修改名称以在当前的搜索服务上创建副本,然后再生成它。

持续可用

索引在第一个文档编制索引后可立即用于查询,但在所有文档编制索引后才能完全运行。 索引在内部是跨分区分布的,并在副本上执行。 物理索引在内部管理。 逻辑索引由你管理。

索引将持续可用,无法暂停或脱机。 由于它专为连续操作而设计,因此针对其内容的任何更新或向索引本身添加内容的操作都实时发生。 因此,如果请求与文档更新一致,查询可能会暂时返回不完整的结果。

注意,对于文档操作(刷新或删除)和不影响现有结构或当前索引完整性的修改(例如添加新的字段),存在查询连续性。 如需更新结构(更改现有字段),通常可在开发环境中使用“丢弃并重新生成”工作流进行管理,也可在生产服务上创建新版索引。

为了避免索引重新生成,一些只进行细小改动的客户会选择创建与以前版本共存的新字段,以对字段进行“版本控制”。 随着时间的推移,这会导致出现孤立内容(采用过时字段或过时的自定义分析器定义形式),特别是在复制成本很高的生产索引中。 可在索引生命周期管理过程中,通过计划更新中处理这些问题。

终结点连接

所有矢量索引和查询请求均以索引为目标。 终结点通常是以下其中一项:

终结点 连接和访问控制
<your-service>.search.azure.cn/indexes 以索引集合为目标。 在创建、列出或删除索引时使用。 这些操作需要管理员权限,通过管理员 API 密钥搜索参与者角色可获得该权限。
<your-service>.search.azure.cn/indexes/<your-index>/docs 以单个索引的文档集合为目标。 在查询索引或数据刷新时使用。 对于查询,读取权限就已足够,通过查询 API 密钥或“数据读取者”角色可获得该权限。 对于数据刷新,需要管理员权限。
  1. 请确保你拥有权限API 访问密钥。 除非要查询现有索引,否则需要管理员权限或参与者角色分配才能管理和查看搜索服务上的内容。

  2. 从 Azure 门户开始。 创建搜索服务的人员可以查看和管理搜索服务,包括通过“访问控制(IAM)”页向其他人授予访问权限

  3. 继续前往其他客户端进行编程访问。 建议使用快速入门和示例,以便执行第一步:

保护对矢量数据的访问

Azure AI 搜索可通过 Microsoft Entra ID 实现数据加密、无 Internet 方案的专用连接,以及角色分配来进行安全访问。 Azure AI 搜索中的安全箱概述了各种企业安全功能。

管理矢量存储

Azure 提供了包括诊断日志记录和警报的监视平台。 建议采用以下最佳做法:

另请参阅