Självstudie: Skapa en indexeringspipeline för RAG i Azure AI Search
Lär dig hur du skapar en automatiserad indexeringspipeline för en RAG-lösning i Azure AI Search. Indexeringsautomatisering sker via en indexerare som driver körning av indexering och kompetensuppsättningar, vilket ger integrerad datasegmentering och vektorisering en gång eller återkommande för inkrementella uppdateringar.
I den här kursen får du:
- Ange indexschemat från föregående självstudie
- Skapa en datakällaanslutning
- Skapa en indexerare
- Skapa en kompetensuppsättning som segmenterar, vektoriserar och identifierar entiteter
- Kör indexeraren och kontrollera resultaten
Om du inte har någon Azure-prenumeration skapar du ett kostnadsfritt konto innan du börjar.
Dricks
Du kan använda guiden Importera och vektorisera data för att skapa din pipeline. Prova några snabbstarter: Bildsökning och Vektorsökning.
Förutsättningar
Visual Studio Code med Python-tillägget och Jupyter-paketet. Mer information finns i Python i Visual Studio Code.
Konto för generell användning i Azure Storage . Den här övningen laddar upp PDF-filer till bloblagring för automatisk indexering.
Azure AI Search, Basic-nivå eller högre för hanterad identitet och semantisk rangordning. Välj en region som delas med Azure OpenAI och Azure AI Services.
Azure OpenAI, med en distribution av text-embedding-3-large, i samma region som Azure AI Search. Mer information om inbäddning av modeller som används i RAG-lösningar finns i Välja inbäddningsmodeller för RAG i Azure AI Search.
Azure AI Service multiservice-konto i samma region som Azure AI Search. Den här resursen används för kunskaper om entitetsigenkänning som identifierar platser i ditt innehåll.
Hämta exemplet
Ladda ned en Jupyter-anteckningsbok från GitHub för att skicka begäranden till Azure AI Search. Mer information finns i Ladda ned filer från GitHub.
Ange indexschemat
Öppna eller skapa en Jupyter-anteckningsbok (.ipynb
) i Visual Studio Code för att innehålla skripten som utgör pipelinen. Initiala steg installerar paket och samlar in variabler för anslutningarna. När du har slutfört installationsstegen är du redo att börja med komponenterna i indexeringspipelinen.
Vi börjar med indexschemat från föregående självstudie. Den är organiserad kring vektoriserade och icke-belagda segment. Det innehåller ett locations
fält som lagrar AI-genererat innehåll som skapats av kompetensuppsättningen.
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")
Skapa en datakällaanslutning
I det här steget konfigurerar du exempeldata och en anslutning till Azure Blob Storage. Indexeraren hämtar PDF-filer från en container. Du skapar containern och laddar upp filer i det här steget.
Den ursprungliga e-boken är stor, över 100 sidor och 35 MB stor. Vi delade upp den i mindre PDF-filer, en per sida med text, för att hålla oss under dokumentgränsen för indexerare på 16 MB per API-anrop och även datagränserna för AI-berikning. För enkelhetens skull utelämnar vi bildvektorisering för den här övningen.
Logga in på Azure Portal och hitta ditt Azure Storage-konto.
Skapa en container och ladda upp PDF-filerna från earth_book_2019_text_pages.
Kontrollera att Azure AI Search har behörigheter för Storage Blob Data Reader på resursen.
I Visual Studio Code definierar du sedan en indexerares datakälla som tillhandahåller anslutningsinformation under indexeringen.
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")
Om du konfigurerar en hanterad identitet för Azure AI Search för anslutningen innehåller anslutningssträng ett ResourceId=
suffix. Det bör se ut ungefär som i följande exempel: "ResourceId=/subscriptions/FAKE-SUBCRIPTION=ID/resourceGroups/FAKE-RESOURCE-GROUP/providers/Microsoft.Storage/storageAccounts/FAKE-ACCOUNT;"
Skapa en kunskapsuppsättning
Färdigheter är grunden för integrerad datasegmentering och vektorisering. Du vill minst att en kunskap om textdelning ska segmentera ditt innehåll och en inbäddningsfärdighet som skapar vektorrepresentationer av ditt segmenterade innehåll.
I den här kompetensuppsättningen används en extra färdighet för att skapa strukturerade data i indexet. Entitetsigenkänningsfärdigheten används för att identifiera platser, som kan sträcka sig från rätt namn till generiska referenser, till exempel "ocean" eller "mountain". Med strukturerade data får du fler alternativ för att skapa intressanta frågor och öka relevansen.
AZURE_AI_MULTISERVICE_KEY behövs även om du använder rollbaserad åtkomstkontroll. Azure AI Search använder nyckeln i faktureringssyfte och krävs såvida inte dina arbetsbelastningar håller sig under den kostnadsfria gränsen. Du kan också en nyckellös anslutning om du använder det senaste förhandsversions-API:et eller betapaketen. Mer information finns i Koppla en Azure AI-resurs med flera tjänster till en kompetensuppsättning.
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")
Skapa och köra indexeraren
Indexerare är den komponent som sätter alla processer i rörelse. Du kan skapa en indexerare i inaktiverat tillstånd, men standardvärdet är att köra den direkt. I den här självstudien skapar och kör du indexeraren för att hämta data från Blob Storage, kör färdigheterna, inklusive segmentering och vektorisering, och läser in indexet.
Indexeraren tar flera minuter att köra. När det är klart kan du gå vidare till det sista steget: fråga ditt index.
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.')
Köra en fråga för att kontrollera resultaten
Skicka en fråga för att bekräfta att indexet fungerar. Den här begäran konverterar textsträngen "what's NASA's website?
" till en vektor för en vektorsökning. Resultaten består av fälten i select-instruktionen, varav några skrivs ut som utdata.
Det finns ingen chatt eller generativ AI just nu. Resultatet är ordagrant innehåll från ditt sökindex.
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']}")
Den här frågan returnerar en enskild matchning (top=1
) som består av ett segment som bestäms av sökmotorn som mest relevant. Resultatet från frågan bör se ut ungefär som i följande exempel:
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
Prova några frågor till för att få en uppfattning om vad sökmotorn returnerar direkt så att du kan jämföra den med ett LLM-aktiverat svar. Kör föregående skript igen med den här frågan: "patagonia geography"
och ange top
till 3 för att returnera fler än ett svar.
Resultatet från den andra frågan bör se ut ungefär som följande resultat, som redigeras lätt för koncision. Utdata kopieras från anteckningsboken, vilket trunkerar svaret på det du ser i det här exemplet. Du kan expandera cellutdata för att granska det fullständiga svaret.
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.
I det här exemplet är det enklare att se hur segment returneras ordagrant och hur nyckelords- och likhetssökning identifierar de bästa matchningarna. Det här specifika segmentet har definitivt information om Patagonien och geografin, men det är inte direkt relevant för frågan. Semantisk ranker skulle främja mer relevanta segment för ett bättre svar, men som ett nästa steg ska vi se hur du ansluter Azure AI Search till en LLM för konversationssökning.