在 Azure AI Search 中配置混合搜索(文本与向量字段)
本指南提供逐步操作,用于创建索引、生成嵌入向量,并执行结合全文搜索与向量搜索的混合查询。通过 Azure AI Search 实现语义相关性与关键词匹配的协同优化。
本文内容
简明答案
混合搜索需在索引架构中添加向量字段,为文本内容生成嵌入向量,并构建包含 search 和 vectorQueries 参数的查询。结果通过反向秩融合(RRF)算法合并,可选启用语义重排序器进行重新排序。关键步骤包括:索引架构定义、嵌入生成、k 与过采样参数配置、带筛选条件和分面的查询构造、语义重排序器启用(如适用)、测试及监控配额与成本。
1. 索引架构定义(含向量与文本字段)
首先创建一个包含常规文本字段(用于全文搜索)和向量字段(用于语义搜索)的 Azure AI Search 索引。向量字段存储从文档文本推导出的数值嵌入向量。索引必须至少包含一个可搜索文本字段和一个向量字段。通过门户或 REST API 创建索引时,向量字段声明类型为 "Edm.Single" 并设置 "searchable": true,但其不用于普通全文搜索,仅用于向量相似度计算。
微软学习文档中的示例展示了一个混合查询,其中 search 参数与指向 DescriptionVector 和 Description_frVector 字段的 vectorQueries 结合使用,允许单次查询同时执行关键词搜索与语义搜索,结果由 RRF 算法合并。
重要提示:向量字段不能直接用于筛选条件。对于元数据(如类别、地理信息),需单独创建带有 filterable 和/或 facetable 属性的文本或数值字段。
POST https://my-service.search.windows.net/indexes/hotels-vector-quickstart/docs/search?api-version=2026-04-01\ncontent-type: application/JSON\n{\n "count": true,\n "search": "historic hotel walk to restaurants and shopping",\n "select": "HotelId, HotelName, Category, Description, Address/City, Address/StateProvince",\n "filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",\n "vectorFilterMode": "postFilter",\n "facets": ["Address/StateProvince"],\n "vectorQueries": [{\n "kind": "vector",\n "vector": [0.1,0.2,…],\n "k": 50,\n "fields": "DescriptionVector",\n "exhaustive": true,\n "oversampling": 20\n }],\n "skip": 0,\n "top": 10,\n "queryType": "semantic",\n "queryLanguage": "en-us",\n "semanticConfiguration": "my-semantic-config"\n}2. 为文本字段生成或导入嵌入向量
嵌入向量可通过两种方式生成:使用 Azure AI Search 内置能力(通过索引器管道调用 Azure OpenAI)或外部模型(如 OpenAI 嵌入、SBERT 等),然后将向量直接加载至索引。第一种方法中,需配置技能集自动切分文本并调用嵌入模型;第二种方法中,向量在外部生成后通过 API 在创建或更新文档时传入。
文档推荐使用 Azure OpenAI 生成嵌入,特别是 text-embedding-ada-002 模型。嵌入必须具有相同维度(例如 Ada 模型为 1536),该值在创建向量字段时指定。
通过“导入数据”向导导入数据时,可以选择向量化选项,若配置了合适的数据源和技能集,服务会自动为加载内容生成嵌入向量。
/* Example call to Azure OpenAI for obtaining an embedding */\nPOST https://my-openai-resource.openai.azure.com/openai/deployments/text-embedding-ada-002/embeddings?api-version=2024-02-15\nHeaders: api-key: YOUR_API_KEY\n{\n "input": "historic hotel walk to restaurants and shopping"\n}3. 配置向量搜索参数(k、过采样、穷举模式)
vectorQueries 中的 k 参数指定每个向量返回的最近邻数量。若启用语义重排序器,建议设置 k >= 50,以确保有足够的候选文档供重排序。
过采样参数指定超出 k 的额外候选数量,有助于提升 HNSW 索引的结果质量。典型值范围为 10 至 50,在延迟与准确率间取得良好平衡。
穷举参数指示是否使用完整扫描查找最近邻。设置 exhaustive: true 可保证找到真正的 k 个最近邻,但会增加延迟。默认为 false,大多数场景下 HNSW 已足够。
混合搜索概览文档示例展示了两个 vectorQueries:一个设 exhaustive=true 且 oversampling=20,另一个设 exhaustive=false 且 oversampling=10。配置取决于索引规模和相关性需求。
注意:增大 k 和过采样会提高准确性但也增加查询延迟。务必在代表性数据样本上测试参数值。
"vectorQueries": [{\n "kind": "vector",\n "vector": <array> ,\n "k": 50,\n "fields": "DescriptionVector",\n "exhaustive": true,\n "oversampling": 20\n }]4. 构建包含 search 与 vectorQueries 的混合查询
混合查询结合 search 参数(全文搜索)和一个或多个 vectorQueries。请求作为单个 HTTP POST 发送到索引端点,api-version=2026-04-01(或当前版本)。
服务器并行执行全文搜索与向量搜索,然后使用反向秩融合(RRF)算法合并结果。RRF 根据文档在两个结果列表中的位置为其分配综合排名,实现精确关键词搜索与语义相似性的协同优势。
在查询中可指定 queryType: semantic 启用语义重排序器,该功能利用机器阅读分析融合后的 RRF 结果,并基于查询上下文重新排序。这对概念性查询尤其有用,此时语义接近比词匹配更重要。
筛选条件和分面应用于非向量字段。例如,地理空间筛选 geo.distance 或类别筛选在 RRF 合并后作用于最终文档集。需测试 vectorFilterMode 行为(preFilter vs postFilter),因为筛选顺序会影响性能与返回文档集。
第 1 节提供的完整查询示例包含分面、筛选、vectorQueries 和 semanticConfiguration。
POST https://my-service.search.windows.net/indexes/hotels-vector-quickstart/docs/search?api-version=2026-04-01\ncontent-type: application/JSON\n{\n "count": true,\n "search": "historic hotel walk to restaurants and shopping",\n "select": "HotelId, HotelName, Category, Description, Address/City, Address/StateProvince",\n "filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",\n "vectorFilterMode": "postFilter",\n "facets": ["Address/StateProvince"],\n "vectorQueries": [{\n "kind": "vector",\n "vector": [0.1,0.2,…],\n "k": 50,\n "fields": "DescriptionVector",\n "exhaustive": true,\n "oversampling": 20\n }],\n "skip": 0,\n "top": 10,\n "queryType": "semantic",\n "queryLanguage": "en-us",\n "semanticConfiguration": "my-semantic-config"\n}5. 对非向量字段应用筛选与分面
RRF 合并后,筛选条件和分面作用于最终文档集,从而保留现有搜索功能:地理空间筛选、属性筛选、分面桶用于导航。
混合查询中的筛选条件默认在全文搜索与向量搜索完成后应用(postFilter),但可配置为 vectorFilterMode: preFilter 以在向量搜索前排除文档。测试表明 postFilter 通常更优,因筛选不会在向量搜索前限制候选文档。
分面(facets)可用于按字段划分结果,例如 Address/StateProvince,如示例所示。分面结果反映的是合并结果中的分布,而非单一搜索组件。
需牢记:向量字段不能直接筛选。任何元数据选择条件必须依赖于索引创建时标记有适当属性(filterable/facetable)的独立文本或数值字段。
"filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",\n "facets": ["Address/StateProvince"]6. 可选:启用语义重排序器进行重排序
语义重排序器可通过添加 queryType: semantic 并在请求中指定 semanticConfiguration 启用。重排序器利用机器阅读分析融合后的 RRF 结果,并根据语义对应关系对结果重新排序。
这能显著提升对概念接近性至关重要的查询的质量(如同义词、多语言搜索)。基准测试显示,启用语义重排序器的混合搜索相比纯向量或关键词搜索具有显著的相关性提升。
语义重排序器配置在索引级别设置(参见“语义配置”部分)。在请求中需指定配置名称,以及查询语言(queryLanguage)。
若无需语义重排序器,可省略 queryType: semantic。此时结果仅依据 RRF 排序,结合 BM25(文本)与 HNSW/eKNN(向量)算法。
"queryType": "semantic",\n "queryLanguage": "en-us",\n "semanticConfiguration": "my-semantic-config"7. 测试与迭代 k、过采样及筛选行为
部署后需实验 k、过采样及筛选行为(preFilter/postFilter),以找到适合您领域的速度-精度最佳平衡。
在代表性查询样本上测试不同 k 值(如 10、50、100)和过采样值(10、20、50)。注意 @search.rerankerScore 和响应中文档顺序的变化。
比较启用与禁用语义重排序器的结果。若 k 过小,语义重排序器将无法获得足够候选文档,重排序效果不佳。
监控查询延迟:增大 k 和过采样会增加响应时间。找到使用语义重排序器时仍可接受的相关性最小 k 值。
使用 Azure 门户或 REST API 调试工具:参数 count: true 可查看总匹配数,@search.rerankerScore 字段显示语义重排序器评估分数。
/* Example checking results with count */\n{\n "count": true,\n "search": "...",\n "vectorQueries": [{"kind": "vector", "vector": [...], "k": 50, ...}],\n "top": 10\n}8. 部署与监控向量索引配额与成本
确保您的搜索服务创建于 2024 年 4 月 3 日之后 - - 此类服务提供更高的向量索引配额。若服务较旧,可更新以获取更大配额。
通过 Azure OpenAI 或其他模型生成嵌入会产生来自模型提供商的费用。规划数据量与更新频率时应考虑这些成本。
通过 Azure Monitor 指标监控向量索引使用情况:向量字段数量、维度、文档数量。超出配额可能导致索引或查询错误。
对于混合搜索,监控查询延迟:较大的 k 和过采样会增加负载。若延迟不可接受,可降低过采样或重新检查 HNSW 配置。
建议设置配额超限警报,并定期检查索引状态,特别是在大批量文档导入后。
/* Checking service version and quotas */\nGET https://my-service.search.windows.net?api-version=2026-04-01\nHeaders: api-key: YOUR_API_KEY检查清单
- 索引至少包含一个可搜索文本字段和一个向量字段,且向量字段维度匹配。
- 已生成嵌入并向向量字段加载(通过索引器或直接 API)。
- 混合查询包含 search 和 vectorQueries,且 k 和 fields 参数正确。
- 启用语义重排序器时,queryType: semantic 和 semanticConfiguration 已设置。
- 筛选条件和分面引用文本或数值字段,而非向量字段。
- 服务版本不低于 2024 年 4 月 3 日,以获得更高向量配额。
- 已启用嵌入生成与查询延迟的成本监控。
适用范围
向量字段不能直接用于筛选条件。对于元数据(如类别、地理信息),需单独创建带有 filterable 和/或 facetable 属性的文本或数值字段。