了解如何在 Azure AI 搜尋服務上建置 RAG 解決方案的自動化編製索引管線。 索引自動化是透過索引器推動索引和技能集執行,提供一次性或定期的整合式資料分塊和向量化,以便進行累加式更新。
在本教學課程中,您已:
- 提供上一個教學課程中的索引結構描述
- 建立新的資料來源連線
- 建立索引子
- 建立對實體進行區塊化、向量化和辨識的技能集
- 執行索引器並檢查結果
如尚未擁有 Azure 訂用帳戶,請在開始之前先建立免費帳戶。
秘訣
您可以使用匯入和向量化資料精靈來建立管線。 請嘗試一些快速入門 影像搜尋 或 向量搜尋,以深入瞭解管線及其移動元件。
必要條件
具有 Python 延伸模組和 Jupyter 套件的 Visual Studio Code。 如需詳細資訊,請參閱 Visual Studio Code 中的 Python。
Azure 儲存體一般用途帳戶。 本練習會將 PDF 檔案上傳至 Blob 儲存體以進行自動編製索引。
Azure AI 搜尋服務,適用於受控識別和語意排名的基本層或更新版本。 選擇與 Azure AI 服務共用的區域。
Azure OpenAI,部署 text-embedding-3-large 模型。 如需有關內嵌 RAG 解決方案中所使用模型的詳細資訊,請參閱在 Azure AI 搜尋服務中選擇適用於 RAG 的內嵌模型。
Azure AI 服務多服務帳戶,位於與 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 AI Search 到 Azure Blob 儲存體的連線。 索引子會從容器擷取 PDF。 您會在此步驟中建立容器並上傳檔案。
原始電子書的內容超過 100 頁,大小為 35 MB。 我們將其分成較小的 PDF,每頁文字一個,以維持 每次 API 呼叫 16 MB 的文件索引器限制,以及 AI 資料強化限制。 為了簡單起見,我們省略此練習的影像向量化。
登入 Azure 入口網站 並尋找您的 Azure 儲存體 帳戶。
建立容器,並從 earth_book_2019_text_pages 上傳 PDF。
請確定您的 Azure AI 搜尋服務受控識別在 Azure 儲存體上具有儲存體 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 記憶體的 Azure AI 搜尋服務連線設定受控識別,數據源連接字串會包含 ResourceId=
後綴。 看起來應該類似下列範例: "ResourceId=/subscriptions/FAKE-SUBSCRIPTION-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 以進行對話式搜尋。