教學課程:在 Azure AI 搜尋服務上建置 RAG 的編製索引管線
了解如何在 Azure AI 搜尋服務上建置 RAG 解決方案的自動化編製索引管線。 編製索引自動化是透過索引子驅動編製索引和技能集執行,針對累加式更新提供一次性或週期性的整合式資料區塊化和向量化。
在本教學課程中,您已:
- 提供上一個教學課程中的索引結構描述
- 建立新的資料來源連線
- 建立索引子
- 建立對實體進行區塊化、向量化和辨識的技能集
- 執行索引器並檢查結果
如尚未擁有 Azure 訂用帳戶,請在開始之前先建立免費帳戶。
提示
您可以使用匯入和向量化資料精靈來建立管線。 請嘗試一些快速入門: 影像搜尋 和 向量搜尋。
必要條件
具有 Python 延伸模組和 Jupyter 套件的 Visual Studio Code。 如需詳細資訊,請參閱 Visual Studio Code 中的 Python。
Azure 儲存體一般用途帳戶。 本練習會將 PDF 檔案上傳至 Blob 儲存體以進行自動編製索引。
Azure AI 搜尋服務,適用於受控識別和語意排名的基本層或更新版本。 選擇與 Azure OpenAI 和 Azure AI 服務共用的區域。
Azure OpenAI,在與 Azure AI 搜尋相同的區域中部署文字內嵌-3-large。 如需有關內嵌 RAG 解決方案中所使用模型的詳細資訊,請參閱在 Azure AI 搜尋服務中選擇適用於 RAG 的內嵌模型。
Azure AI Service 多服務帳戶,位於與 Azure AI 搜尋相同的區域中。 此資源用於偵測內容中位置的實體辨識技能。
下載範例
從 GitHub 下載 Jupyter Notebook,以將要求傳送至 Azure AI 搜尋服務。 如需相關資訊,請參閱從 GitHub 下載檔案。
提供索引結構描述
在 Visual Studio Code 中開啟或建立 Jupyter Notebook (.ipynb
),以包含組成管線的指令碼。 初始步驟會安裝套件,並收集連線的變數。 完成設定步驟之後,您即可開始使用編製索引管線的元件。
讓我們從上一個教學課程的索引結構描述開始。 其會圍繞向量化和非向量化區塊進行組織。 其中包含一個 locations
欄位,可儲存技能集所建立的 AI 生成內容。
from azure.identity import DefaultAzureCredential
from azure.identity import get_bearer_token_provider
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
SearchField,
SearchFieldDataType,
VectorSearch,
HnswAlgorithmConfiguration,
VectorSearchProfile,
AzureOpenAIVectorizer,
AzureOpenAIVectorizerParameters,
SearchIndex
)
credential = DefaultAzureCredential()
# Create a search index
index_name = "py-rag-tutorial-idx"
index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)
fields = [
SearchField(name="parent_id", type=SearchFieldDataType.String),
SearchField(name="title", type=SearchFieldDataType.String),
SearchField(name="locations", type=SearchFieldDataType.Collection(SearchFieldDataType.String), filterable=True),
SearchField(name="chunk_id", type=SearchFieldDataType.String, key=True, sortable=True, filterable=True, facetable=True, analyzer_name="keyword"),
SearchField(name="chunk", type=SearchFieldDataType.String, sortable=False, filterable=False, facetable=False),
SearchField(name="text_vector", type=SearchFieldDataType.Collection(SearchFieldDataType.Single), vector_search_dimensions=1024, vector_search_profile_name="myHnswProfile")
]
# Configure the vector search configuration
vector_search = VectorSearch(
algorithms=[
HnswAlgorithmConfiguration(name="myHnsw"),
],
profiles=[
VectorSearchProfile(
name="myHnswProfile",
algorithm_configuration_name="myHnsw",
vectorizer_name="myOpenAI",
)
],
vectorizers=[
AzureOpenAIVectorizer(
vectorizer_name="myOpenAI",
kind="azureOpenAI",
parameters=AzureOpenAIVectorizerParameters(
resource_url=AZURE_OPENAI_ACCOUNT,
deployment_name="text-embedding-3-large",
model_name="text-embedding-3-large"
),
),
],
)
# Create the search index
index = SearchIndex(name=index_name, fields=fields, vector_search=vector_search)
result = index_client.create_or_update_index(index)
print(f"{result.name} created")
建立新的資料來源連線
在此步驟中,設定範例資料和 Azure Blob 儲存體的連線。 索引子會從容器擷取 PDF。 您會在此步驟中建立容器並上傳檔案。
原始電子書的內容超過 100 頁,大小為 35 MB。 我們將其分成較小的 PDF,每頁文字一個,以維持 每個 API 呼叫 16 MB 的索引器 的檔限制,以及 AI 擴充數據限制。 為了簡單起見,我們省略此練習的影像向量化。
登入 Azure 入口網站 並尋找您的 Azure 儲存體 帳戶。
建立容器,並從 earth_book_2019_text_pages 上傳 PDF。
請確定 Azure AI 搜尋具有 資源的記憶體 Blob 資料讀取者 許可權 。
接下來,在 Visual Studio Code 中,定義索引子資料來源,以在編製索引期間提供連線資訊。
from azure.search.documents.indexes import SearchIndexerClient from azure.search.documents.indexes.models import ( SearchIndexerDataContainer, SearchIndexerDataSourceConnection ) # Create a data source indexer_client = SearchIndexerClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential) container = SearchIndexerDataContainer(name="nasa-ebooks-pdfs-all") data_source_connection = SearchIndexerDataSourceConnection( name="py-rag-tutorial-ds", type="azureblob", connection_string=AZURE_STORAGE_CONNECTION, container=container ) data_source = indexer_client.create_or_update_data_source_connection(data_source_connection) print(f"Data source '{data_source.name}' created or updated")
如果您為 Azure AI 搜尋服務設定連線的受控識別,則 連接字串 包含ResourceId=
後綴。 看起來應該類似下列範例: "ResourceId=/subscriptions/FAKE-SUBCRIPTION=ID/resourceGroups/FAKE-RESOURCE-GROUP/providers/Microsoft.Storage/storageAccounts/FAKE-ACCOUNT;"
建立技能集
技能是整合式資料區塊化和向量化的基礎。 您至少希望文字分割技能將內容區塊化,以及建立區塊化內容向量表示法的內嵌技能。
在此技能集中,會使用額外的技能在索引中建立結構化資料。 實體辨識技能可用來識別位置,其範圍可以從適當的名稱到泛型參考,例如“ocean” 或 “mountain”。 結構化資料可讓您有更多選項來建立有趣的查詢,並提升相關性。
即使您使用角色型訪問控制,也需要AZURE_AI_MULTISERVICE_KEY。 Azure AI 搜尋會使用密鑰進行計費,除非您的工作負載維持在免費限制之下,否則為必要密鑰。 如果您使用最新的預覽 API 或 Beta 套件,您也可以使用無密鑰連線。 如需詳細資訊,請參閱 將 Azure AI 多服務資源附加至技能集。
from azure.search.documents.indexes.models import (
SplitSkill,
InputFieldMappingEntry,
OutputFieldMappingEntry,
AzureOpenAIEmbeddingSkill,
EntityRecognitionSkill,
SearchIndexerIndexProjection,
SearchIndexerIndexProjectionSelector,
SearchIndexerIndexProjectionsParameters,
IndexProjectionMode,
SearchIndexerSkillset,
CognitiveServicesAccountKey
)
# Create a skillset
skillset_name = "py-rag-tutorial-ss"
split_skill = SplitSkill(
description="Split skill to chunk documents",
text_split_mode="pages",
context="/document",
maximum_page_length=2000,
page_overlap_length=500,
inputs=[
InputFieldMappingEntry(name="text", source="/document/content"),
],
outputs=[
OutputFieldMappingEntry(name="textItems", target_name="pages")
],
)
embedding_skill = AzureOpenAIEmbeddingSkill(
description="Skill to generate embeddings via Azure OpenAI",
context="/document/pages/*",
resource_url=AZURE_OPENAI_ACCOUNT,
deployment_name="text-embedding-3-large",
model_name="text-embedding-3-large",
dimensions=1024,
inputs=[
InputFieldMappingEntry(name="text", source="/document/pages/*"),
],
outputs=[
OutputFieldMappingEntry(name="embedding", target_name="text_vector")
],
)
entity_skill = EntityRecognitionSkill(
description="Skill to recognize entities in text",
context="/document/pages/*",
categories=["Location"],
default_language_code="en",
inputs=[
InputFieldMappingEntry(name="text", source="/document/pages/*")
],
outputs=[
OutputFieldMappingEntry(name="locations", target_name="locations")
]
)
index_projections = SearchIndexerIndexProjection(
selectors=[
SearchIndexerIndexProjectionSelector(
target_index_name=index_name,
parent_key_field_name="parent_id",
source_context="/document/pages/*",
mappings=[
InputFieldMappingEntry(name="chunk", source="/document/pages/*"),
InputFieldMappingEntry(name="text_vector", source="/document/pages/*/text_vector"),
InputFieldMappingEntry(name="locations", source="/document/pages/*/locations"),
InputFieldMappingEntry(name="title", source="/document/metadata_storage_name"),
],
),
],
parameters=SearchIndexerIndexProjectionsParameters(
projection_mode=IndexProjectionMode.SKIP_INDEXING_PARENT_DOCUMENTS
),
)
cognitive_services_account = CognitiveServicesAccountKey(key=AZURE_AI_MULTISERVICE_KEY)
skills = [split_skill, embedding_skill, entity_skill]
skillset = SearchIndexerSkillset(
name=skillset_name,
description="Skillset to chunk documents and generating embeddings",
skills=skills,
index_projection=index_projections,
cognitive_services_account=cognitive_services_account
)
client = SearchIndexerClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)
client.create_or_update_skillset(skillset)
print(f"{skillset.name} created")
建立並執行索引子
索引子是可設定動作中所有處理序的元件。 您可以建立處於停用狀態的索引子,但預設值是立即執行。 在本教學課程中,建立並執行索引子,以從 Blob 儲存體擷取資料、執行技能,包括區塊化和向量化,以及載入索引。
索引子需要幾分鐘的時間才能執行。 完成後,您可以繼續進行至最後一個步驟:查詢您的索引。
from azure.search.documents.indexes.models import (
SearchIndexer,
FieldMapping
)
# Create an indexer
indexer_name = "py-rag-tutorial-idxr"
indexer_parameters = None
indexer = SearchIndexer(
name=indexer_name,
description="Indexer to index documents and generate embeddings",
skillset_name=skillset_name,
target_index_name=index_name,
data_source_name=data_source.name,
# Map the metadata_storage_name field to the title field in the index to display the PDF title in the search results
field_mappings=[FieldMapping(source_field_name="metadata_storage_name", target_field_name="title")],
parameters=indexer_parameters
)
# Create and run the indexer
indexer_client = SearchIndexerClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)
indexer_result = indexer_client.create_or_update_indexer(indexer)
print(f' {indexer_name} is created and running. Give the indexer a few minutes before running a query.')
執行查詢以檢查結果
傳送查詢以確認您的索引正常運作。 此要求會將文字字串「what's NASA's website?
」轉換成向量搜尋的向量。 結果包含 SELECT 陳述式中的欄位,其中有些會列印為輸出。
此時沒有聊天或行用 AI。 結果是搜尋索引中逐字內容。
from azure.search.documents import SearchClient
from azure.search.documents.models import VectorizableTextQuery
# Vector Search using text-to-vector conversion of the querystring
query = "what's NASA's website?"
search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential, index_name=index_name)
vector_query = VectorizableTextQuery(text=query, k_nearest_neighbors=50, fields="text_vector")
results = search_client.search(
search_text=query,
vector_queries= [vector_query],
select=["chunk"],
top=1
)
for result in results:
print(f"Score: {result['@search.score']}")
print(f"Chunk: {result['chunk']}")
此查詢會傳回單一比對 (top=1
),其中包含由搜尋引擎判斷為最相關的一個區塊。 查詢的結果看起來應該類似下列範例:
Score: 0.01666666753590107
Chunk: national Aeronautics and Space Administration
earth Science
NASA Headquarters
300 E Street SW
Washington, DC 20546
www.nasa.gov
np-2018-05-2546-hQ
再多嘗試幾個查詢,了解搜尋引擎直接傳回的內容,以便您將其與啟用 LLM 的回應進行比較。 使用此查詢重新執行先前的腳本: "patagonia geography"
並將 設定 top
為 3 以傳回多個回應。
此第二個查詢的結果看起來應該類似下列結果,而結果會進行小幅度編輯以提高準確度。 輸出會從筆記本複製,這會截斷您在此範例中看到的回應。 您可以展開儲存格輸出,以檢閱完整的答案。
Score: 0.03306011110544205
Chunk:
Swirling Bloom off Patagonia
Argentina
Interesting art often springs out of the convergence of different ideas and influences.
And so it is with nature.
Off the coast of Argentina, two strong ocean currents converge and often stir up a colorful
brew, as shown in this Aqua image from
December 2010.
This milky green and blue bloom formed on the continental shelf off of Patagonia, where warmer,
saltier waters from the subtropics
meet colder, fresher waters flowing from the south. Where these currents collide, turbulent
eddies and swirls form, pulling nutrients
up from the deep ocean. The nearby Rio de la Plata also deposits nitrogen- and iron-laden
sediment into the sea. Add in some
...
while others terminate in water. The San Rafael and San Quintín glaciers (shown at the right)
are the icefield’s largest. Both have
been receding rapidly in the past 30 years.
在此範例中,更容易找出如何逐字傳回區塊,以及關鍵字和相似性搜尋如何識別最上層相符項目。 這個特定區塊肯定有巴塔哥尼亞和地理的相關信息,但它與查詢並不完全相關。 語意排名器會提升更相關的區塊,以取得更好的答案,但在下一個步驟中,讓我們瞭解如何將 Azure AI 搜尋連線到 LLM 以進行對話式搜尋。