註
Azure AI 搜尋服務 可透過 Azure 入口網站、REST API 及 Azure SDK 取得。 它同時也是 Foundry IQ 的基礎,這是一個管理式知識層,能將企業內容轉化為可重複使用、權限感知的知識庫,供 Microsoft Foundry 入口網站中的代理使用。
如果你在為 RAG 模式或向量化而分塊內容,你可以指定 索引投影 來控制 一對多索引,其中來源內容(一個)投影到一個或多個索引(多個)。 索引投影的目的,是用來控制是否將父文件中的元素,例如檔案名稱或建立日期:
- 在單一索引中,針對每個子項目 (chunk) 重複執行
- 在同一索引中作為獨立搜尋文件被索引
- 或者被導入到獨立的索引中
我們建議在同一索引中重複父欄位,因為不同文件格式或將內容拆分成兩個索引查詢會很困難,尤其是在不支援索引連接的經典搜尋中。
在 Azure AI 搜尋服務 中,資料分塊是由技能模組執行,因此依賴於索引器。 要定義指數投影,請在 技能集中指定。
先決條件
Azure AI 搜尋服務,任何層級或區域都可以。
一個 支援的資料來源 ,裡面有你想要分割的內容。
一個接受索引器管線輸出的索引(一個或多個)。
技能包含索引子投影,可塑造一對多索引編製的資料。 技能組也可以包含其他技能,例如嵌入技能,例如 AzureOpenAIEmbedding ,如果你的情境包含整合向量化。
選擇一種方法
索引投影會為每個「父」文件產生「子」文件(區塊)。 選擇如何處理家長內容:
| 方法 | 描述 | 配置 |
|---|---|---|
| 單一索引,重複父欄位 (建議) | 每個區塊都會重複父欄位。 所有文件的形狀均一。 | 將索引器和 targetIndexName 索引投影 targetIndexName 設為同一個索引。 設定 projectionMode 為 skipIndexingParentDocuments。 |
| 單一索引,混合文件形狀 | 父文件和區塊文件是共存的。 父文件具有空值塊欄位。 | 將兩個 targetIndexName 值設為相同的索引。 設定 projectionMode 為 includeIndexingParentDocuments(或者省略,因為它是預設值)。 |
| 兩個或以上獨立的索引 | 父索引用於元資料查詢,子索引用於搜尋。 沒有查詢時間的加入。 | 將索引器 targetIndexName 設為父索引。 將索引投影 targetIndexName 設為子索引。 陣列 selectors 決定了子索引的數量和組成。 |
在大多數 RAG 情境中,採用第一種方法。 請參考classic RAG範例。
建議方法的實施步驟
如果你的資料來源支援變更追蹤,索引器會自動同步變更。
建立一對多編製索引的索引
無論你是為重複父值的區塊建立一個索引,還是為父子欄位放置建立獨立索引,主要用於搜尋的索引都是圍繞資料區塊設計的。 索引結構必須包含以下欄位:
一個文件鍵字段唯一識別每份文件。 必須用
Edm.String分析器定義為類型keyword。一個欄位,將每個區塊與其父區塊關聯起來。 必須是類型
Edm.String。 不可能是文件鍵欄位,必須設定filterable為 true。 它在範例中稱為 parent_id,而且在本文中稱為已投影的索引鍵值。其他內容欄位,例如文字或向量區塊欄位。
搜尋服務必須先有索引,才能建立技能組或啟動索引器。
selectors你在技能組中定義的欄位應該包含這些領域。
包含父欄位與子欄位的單一索引結構
RAG 和向量搜尋場景中的主要模式是設計圍繞區塊的單一索引,其中父內容會在每個區塊中重複。 透過索引投影,能夠將正確的父內容與每個區塊關聯起來。
以下結構是一個符合指數投影要求的範例。 在這個例子中:
- 父欄位是parent_id和標題,且每個區塊都會重複
- 子欄位是向量與非向量向量區塊。 chunk_id是這個索引的文件ID。
你可以使用 Azure 入口網站、REST API 或 Azure SDK 來建立索引。
使用 REST 用戶端或 Azure 入口網站Add index 動作和 JSON 選項來建立索引。
{
"name": "my_consolidated_index",
"fields": [
{"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
{"name": "parent_id", "type": "Edm.String", "filterable": true},
{"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true},
{"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
{"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
],
"vectorSearch": {
"algorithms": [{"name": "hnsw", "kind": "hnsw", "hnswParameters": {}}],
"profiles": [{"name": "hnsw", "algorithm": "hnsw"}]
}
}
將指數投影加入技能組
索引投影定義於技能組定義中,主要定義為 的 selectors陣列,每個選擇器對應搜尋服務中的不同目標索引。 本節從語法與範例開始,接著是 參數參考。
指數的預測值通常可以取得。 我們推薦最新的穩定 API:
這裡有一個索引投影定義的範例載荷,你可以用它來將 Text Split 技能 輸出的單頁投影成搜尋索引中的獨立文件。
如果父文件包含文件層級存取的權限元資料,如 metadata_user_ids、 metadata_group_ids、 metadata_spo_site_url或 ,則將這些欄位納入 mappings。 每個區塊必須繼承這些權限,查詢時的權限篩選才會套用。 欲了解更多資訊,請參閱 「選擇填入 ACL 欄位的位置(預覽)」。
"indexProjections": {
"selectors": [
{
"targetIndexName": "my_consolidated_index",
"parentKeyFieldName": "parent_id",
"sourceContext": "/document/pages/*",
"mappings": [
{
"name": "chunk",
"source": "/document/pages/*",
"sourceContext": null,
"inputs": []
},
{
"name": "chunk_vector",
"source": "/document/pages/*/chunk_vector",
"sourceContext": null,
"inputs": []
},
{
"name": "title",
"source": "/document/title",
"sourceContext": null,
"inputs": []
}
]
}
],
"parameters": {
"projectionMode": "skipIndexingParentDocuments"
}
}
參數參考
| 指標投影參數 | 定義 |
|---|---|
selectors |
一個包含主要搜尋語料庫參數的陣列,通常是以區塊為中心設計的索引。 你可以透過指定多個選擇器,將內容傳送到多個子索引。 索引結構必須先存在於搜尋服務中,才能執行索引器。 |
parameters |
一個指標投影特有配置屬性的參數字典。 |
參數定義中包含以下元素。
| 參數 | 定義 |
|---|---|
parameters.projectionMode |
一個可選參數,提供給索引器的指令。 有效的值包括 includeIndexingParentDocuments 和 skipIndexingParentDocuments。 此參數的最佳值為 skipIndexingParentDocuments。 當分塊文件是主要搜尋目標時,你應該使用它。 如果你沒為 skipIndexingParentDocuments 設定 projectionMode,就會自動獲得 includeIndexingParentDocuments,因為這是預設的。 它會在索引中新增一些搜尋文件,這些文件的區段為 null,但會填充具有父項專屬內容的資訊。 例如,若五個 PDF 貢獻 100 個區塊,索引中的文件數量為 105 份。 為父欄位建立的五份文件,其區塊(子)欄位皆有空值,與索引中大部分文件有顯著差異。 因此,我們建議 projectionMode 設定為 skipIndexingParentDocuments。 |
選擇器定義中包含以下元素。
| 選拔委員 | 定義 |
|---|---|
selectors.targetIndexName |
要在其中投影索引資料之索引的名稱。 它要麼是單一分塊索引,重複父欄位;要麼是子索引,如果你用 獨立索引 來管理父子內容。 |
selectors.parentKeyFieldName |
提供父文件鍵的欄位名稱。 |
selectors.sourceContext |
擴充註釋,其定義將資料對應至個別搜尋文件的資料細微性。 欲了解更多資訊,請參閱 技能上下文與輸入註解語言。 |
selectors.mappings |
一個將豐富資料映射到搜尋索引欄位的陣列。 每個映射由以下組成: name:搜尋索引中資料應索引的欄位名稱。 source:應該從中提取資料的擴充註釋路徑。 每個 mapping 也可以遞迴定義資料,並設有可選擇的 sourceContext 和 inputs 欄位,類似於 知識庫 或 塑形技能。 根據你的應用程式,這些參數允許你將資料塑造成搜尋索引中欄位 Edm.ComplexType 的類型。 某些 LLM 不接受搜尋結果中的複雜類型,因此您使用的 LLM 會判斷複雜類型對應是否有用。 |
這個 mappings 參數很重要。 您必須明確對應子索引中的每個欄位,但文件索引鍵與父識別碼等識別碼欄位除外。
此要求與 Azure AI 搜尋服務 中其他欄位映射慣例形成對比。 對於某些資料來源類型,索引器可以隱含地根據相似名稱或已知特徵映射欄位(例如,blob 索引器會將獨特的元資料儲存路徑作為預設文件鍵)。 不過,針對索引子投影,您必須在關聯性的「多」端明確指定每個欄位對應。
重要
不要為父鍵欄位建立欄位映射。 這樣做會干擾變更追蹤和同步資料更新。
檢閱欄位對應
索引器與三種不同類型的欄位映射相關聯。 在執行索引器之前,先檢查欄位映射,知道何時使用每種類型。
欄位映射 在索引器中定義,用來將來源欄位映射到索引欄位。 欄位對應用於從來源提取資料並傳入以進行索引編製的資料路徑,而不需要中級技能處理步驟。 通常,索引器可以自動映射具有相同名稱和類型的欄位。 只有在出現差異時才需要明確的欄位映射。 在到目前為止所討論的一對多索引編製與模式中,您可能不需要欄位對應。
輸出欄位映射 在索引器中定義,並用於將技能組產生的豐富內容映射到欄位,並映射到主索引中。 區塊因為由技能 (Text Split) 建立而被視為豐富內容,但不需要輸出欄位映射,或選擇器映射所定義的索引投影。
Selectors.mappings 定義於技能組中,並映射到子索引中的欄位。 若子索引同時包含父欄位(如 合併索引解決方案),你應該為每個有內容的欄位(包括父層級標題欄位)設置欄位映射,假設你希望標題能在每個分塊文件中顯示。 如果你使用 獨立的父索引和子索引,選擇器應該只對子層級欄位有欄位映射。
執行索引器
一旦你建立了資料來源、索引和技能集,就可以 開始建立並執行索引器了。 此步驟會將管線放入執行中。
處理結束後,你可以查詢搜尋索引來測試你的解決方案。
內容生命週期
根據底層資料來源,索引器通常能持續追蹤變更與刪除偵測。 本節說明一對多索引的內容生命週期,與資料刷新相關的關係。
對於提供變更追蹤與刪除偵測的資料來源,索引器流程可以偵測來源資料中的變更。 每次執行索引器和技能集時,如果技能組或底層來源資料有變動,索引預測都會更新。 索引器捕捉到的任何變更都會透過豐富化過程傳遞到索引中的預測,確保你的預測資料是原始資料來源內容的即時代表。 資料刷新活動會被記錄在每個分塊的預測鍵值中。 當底層資料變更時,這個值會被更新。
註
雖然你可以用 索引推送 API 手動編輯投影文件中的資料,但建議避免這麼做。 手動更新索引會在下一次管線調用時覆寫,前提是原始資料中的文件已更新,且資料來源已啟用變更追蹤或刪除偵測功能。
更新內容
如果你在資料來源新增內容,下一次索引器執行時會新增區塊或子文件到索引中。
如果你修改了資料來源中的現有內容,若資料來源支援變更追蹤和刪除偵測,區塊會在搜尋索引中逐步更新。 例如,如果文件中的某個單字或句子改變,目標索引中包含該單字或句子的區塊會在下一次索引器執行時更新。 其他類型的更新,例如更改欄位類型和某些歸因,則不支援現有欄位。 欲了解更多允許更新的資訊,請參見 「更新索引結構」。
有些資料來源如 Azure 儲存體 預設支援基於時間戳記的變更與刪除追蹤。 其他資料來源如 Microsoft OneLake、Azure SQL 或 Azure Cosmos DB 必須設定用於變更追蹤。
已刪除內容
如果來源內容已不存在(例如文字被縮短以減少區塊),搜尋索引中對應的子文件會被刪除。 剩餘的子文件也會更新金鑰,加入新的雜湊值,即使內容本身沒有改變。
若父文件從資料來源中完全刪除,對應的子文件只有在資料來源定義中被 dataDeletionDetectionPolicy 偵測到刪除時才會被刪除。 如果你沒有設定dataDeletionDetectionPolicy,並且需要從資料來源刪除父文件,那麼如果子文件不再需要的話,你應該手動刪除子文件。
預估鍵值
為了確保更新與刪除內容的資料完整性,一對多索引中的資料刷新依賴於「多」側的 預測鍵值 。 如果您使用整合向量化或 匯入資料精靈,投影的鍵值是parent_id索引中已分塊或「許多」側的欄位。
投影鍵值是索引器為每份文件產生的唯一識別碼。 它確保了唯一性,並允許變更與刪除追蹤正常運作。 此金鑰包含以下片段:
- 一個隨機雜湊值來保證唯一性。 若父文件在後續索引器執行時更新,雜湊值會改變。
- 母文件的金鑰。
- 識別所產生文件內容的擴充註解路徑。
例如,如果您將索引鍵值 "aa1b22c33" 的父文件分割成四個頁面,然後每個頁面都透過索引投影投影為自己的文件:
- aa1b22c33
- aa1b22c33_pages_0
- aa1b22c33_pages_1
- aa1b22c33_pages_2
如果父文件在來源資料中被更新,可能會導致更多分塊頁面、隨機雜湊值改變、新增更多頁面,且每個區塊的內容會更新到與原始文件相符。
獨立父子索引範例
本節展示了分開父索引與子索引的範例。 這種模式不常見,但你可能有最適合用這種方法的申請需求。 在這種情況下,你是在將父子內容投影到兩個獨立的索引中。
建立兩個索引架構。
每個結構描述都有其特定精細度的欄位,其中兩個索引通用的父識別碼欄位可用於查閱查詢 (部分機器翻譯)。 主要的搜尋語料庫是子索引,但你也可以發送查詢,取得結果中每個匹配的父欄位。 Azure AI 搜尋服務 不支援查詢時的加入,因此你的應用程式程式碼或協調層需要合併或整合結果,才能傳遞給應用程式或程序。
父索引有parent_id欄位和標題。 parent_id是文件金鑰。 除非你想在父文件層級進行向量化欄位,否則不需要向量搜尋設定。
{ "name": "my-parent-index", "fields": [ {"name": "parent_id", "type": "Edm.String", "key":true, "filterable": true}, {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true} ] }子索引包含分塊欄位和 parent_id 欄位。 如果你使用整合向量化、評分設定檔、語意排序器或分析工具,你會把這些設定在子索引中。
{ "name": "my-child-index", "fields": [ {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"}, {"name": "parent_id", "type": "Edm.String", "filterable": true}, {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true}, {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"} ], "vectorSearch": { "algorithms": [{"name": "hsnw", "kind": "hnsw", "hnswParameters": {}}], "profiles": [{"name": "hsnw", "algorithm": "hnsw"}] }, "scoringProfiles": [], "semanticConfiguration": [], "analyzers": [] }更新索引器,指定父索引為目標。
索引器的定義指定了管線的組成部分。 在索引器的定義中,要提供的索引名稱是父索引。 如果你需要父層級欄位的欄位映射,請在 outputFieldMappings 中定義它們。 對於使用獨立索引的一對多索引,索引器的定義可能如下範例。
{ "name": "my-indexer", "dataSourceName": "my-ds", "targetIndexName": "my-parent-index", "skillsetName" : "my-skillset", "parameters": { }, "fieldMappings": (optional) Maps fields in the underlying data source to fields in an index, "outputFieldMappings" : (required) Maps skill outputs to fields in an index, }將
indexProjections加入技能組合。這裡有一個索引投影定義的範例,指定索引器應該使用哪條路徑來索引內容。 它在索引投影定義中指定子索引名稱,並指定每個子節點或區塊層級欄位的映射。 這是唯一指定子索引名稱的地方。
注意
parameters是空的,並使用預設的includeIndexingParentDocuments。 索引器會填充父索引。 陣列selectors用來將塊文件投影到子索引。"indexProjections": { "selectors": [ { "targetIndexName": "my-child-index", "parentKeyFieldName": "parent_id", "sourceContext": "/document/pages/*", "mappings": [ { "name": "chunk", "source": "/document/pages/*", "sourceContext": null, "inputs": [] }, { "name": "chunk_vector", "source": "/document/pages/*/chunk_vector", "sourceContext": null, "inputs": [] } ] } ], "parameters": {} }執行索引器。 如果你之前有執行過索引器,記得先重新設定它。
你應該有兩個索引,將其填入適當的內容。 在搜尋總管查詢索引,以確認每個索引的內容是否正確。
下一步
資料分塊與一對多索引是 Azure AI 搜尋服務 經典 RAG 模式的一部分。 請繼續閱讀以下教學與程式碼範例,進一步了解相關內容。