Zelfstudie: Een indexeringspijplijn bouwen voor RAG in Azure AI Search
Meer informatie over het bouwen van een geautomatiseerde indexeringspijplijn voor een RAG-oplossing in Azure AI Search. Indexeringsautomatisering is via een indexeerfunctie die de uitvoering van indexering en vaardighedensets aanstuurt, waardoor geïntegreerde gegevenssegmentering en vectorisatie op eenmalige of terugkerende basis worden geboden voor incrementele updates.
In deze zelfstudie hebt u:
- Geef het indexschema op uit de vorige zelfstudie
- Een gegevensbronverbinding maken
- Een indexeerfunctie maken
- Een vaardighedenset maken die segmenten, vectoren maakt en entiteiten herkent
- Voer de indexeerfunctie uit en controleer de resultaten
Als u geen Azure-abonnement hebt, maakt u een gratis account voordat u begint.
Tip
U kunt de wizard Gegevens importeren en vectoriseren gebruiken om uw pijplijn te maken. Probeer enkele quickstarts: Afbeeldingen zoeken en Vector zoeken.
Vereisten
Visual Studio Code met de Python-extensie en het Jupyter-pakket. Zie Python in Visual Studio Code voor meer informatie.
Azure Storage-account voor algemeen gebruik. In deze oefening worden PDF-bestanden geüpload naar blobopslag voor geautomatiseerde indexering.
Azure AI Search, Basic-laag of hoger voor beheerde identiteit en semantische classificatie. Kies een regio die wordt gedeeld met Azure OpenAI en Azure AI Services.
Azure OpenAI, met een implementatie van tekst-insluiten-3-groot, in dezelfde regio als Azure AI Search. Zie Insluitmodellen kiezen voor RAG in Azure AI Search voor meer informatie over het insluiten van modellen die worden gebruikt in RAG-oplossingen.
Azure AI Service-account voor meerdere services, in dezelfde regio als Azure AI Search. Deze resource wordt gebruikt voor de vaardigheid Entiteitsherkenning waarmee locaties in uw inhoud worden gedetecteerd.
Het voorbeeld downloaden
Download een Jupyter-notebook vanuit GitHub om de aanvragen naar Azure AI Search te verzenden. Zie Bestanden downloaden van GitHub voor meer informatie.
Geef het indexschema op
Open of maak een Jupyter-notebook (.ipynb
) in Visual Studio Code om de scripts te bevatten die de pijplijn vormen. Initiële stappen installeren pakketten en verzamelen variabelen voor de verbindingen. Nadat u de installatiestappen hebt voltooid, kunt u beginnen met de onderdelen van de indexeringspijplijn.
Laten we beginnen met het indexschema uit de vorige zelfstudie. Het is georganiseerd rond gevectoriseerde en niet-gevectoriseerde segmenten. Het bevat een locations
veld waarin door AI gegenereerde inhoud wordt opgeslagen die is gemaakt door de vaardighedenset.
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")
Een gegevensbronverbinding maken
In deze stap stelt u de voorbeeldgegevens en een verbinding met Azure Blob Storage in. De indexeerfunctie haalt PDF-bestanden op uit een container. U maakt de container en uploadt bestanden in deze stap.
Het oorspronkelijke ebook is groot, meer dan 100 pagina's en 35 MB groot. We hebben het opgesplitst in kleinere PDF's, één per pagina met tekst, om onder de documentlimiet te blijven voor indexeerfuncties van 16 MB per API-aanroep en ook de limieten voor AI-verrijkingsgegevens. Ter vereenvoudiging laten we afbeeldingsvectorisatie weg voor deze oefening.
Meld u aan bij Azure Portal en zoek uw Azure Storage-account.
Maak een container en upload de PDF-bestanden vanuit earth_book_2019_text_pages.
Zorg ervoor dat Azure AI Search machtigingen voor opslagblobgegevenslezer heeft voor de resource.
Vervolgens definieert u in Visual Studio Code een indexeerfunctiegegevensbron die verbindingsgegevens levert tijdens het indexeren.
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")
Als u een beheerde identiteit instelt voor Azure AI Search voor de verbinding, bevat de verbindingsreeks een ResourceId=
achtervoegsel. Het moet er ongeveer uitzien als in het volgende voorbeeld: "ResourceId=/subscriptions/FAKE-SUBCRIPTION=ID/resourceGroups/FAKE-RESOURCE-GROUP/providers/Microsoft.Storage/storageAccounts/FAKE-ACCOUNT;"
Een vaardighedenset maken
Vaardigheden vormen de basis voor geïntegreerde gegevenssegmentering en vectorisatie. U wilt ten minste een vaardigheid tekst splitsen om uw inhoud te segmenteren en een insluitvaardigheid waarmee vectorweergaven van uw gesegmenteerde inhoud worden gemaakt.
In deze vaardighedenset wordt een extra vaardigheid gebruikt om gestructureerde gegevens in de index te maken. De vaardigheid Entiteitsherkenning wordt gebruikt om locaties te identificeren, die kunnen variëren van de juiste namen tot algemene verwijzingen, zoals 'oceaan' of 'berg'. Als u gestructureerde gegevens hebt, hebt u meer opties voor het maken van interessante query's en het stimuleren van relevantie.
De AZURE_AI_MULTISERVICE_KEY is nodig, zelfs als u op rollen gebaseerd toegangsbeheer gebruikt. Azure AI Search gebruikt de sleutel voor factureringsdoeleinden en is vereist, tenzij uw workloads onder de gratis limiet blijven. U kunt ook een sleutelloze verbinding maken als u de meest recente preview-API of bètapakketten gebruikt. Zie Een Azure AI-resource voor meerdere services koppelen aan een vaardighedenset voor meer informatie.
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")
De indexeerfunctie maken en uitvoeren
Indexeerfuncties zijn het onderdeel waarmee alle processen in beweging worden ingesteld. U kunt een indexeerfunctie met een uitgeschakelde status maken, maar de standaardwaarde is dat deze onmiddellijk wordt uitgevoerd. In deze zelfstudie maakt en voert u de indexeerfunctie uit om de gegevens op te halen uit Blob Storage, de vaardigheden uit te voeren, waaronder segmentering en vectorisatie, en de index te laden.
Het uitvoeren van de indexeerfunctie duurt enkele minuten. Wanneer u klaar bent, kunt u verdergaan met de laatste stap: een query uitvoeren op uw 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.')
Een query uitvoeren om de resultaten te controleren
Verzend een query om te bevestigen dat uw index operationeel is. Met deze aanvraag wordt de tekenreeks 'what's NASA's website?
' geconverteerd naar een vector voor een vectorzoekopdracht. Resultaten bestaan uit de velden in de select-instructie, waarvan sommige als uitvoer worden afgedrukt.
Er is op dit moment geen chat of generatieve AI. De resultaten zijn exacte inhoud uit uw zoekindex.
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']}")
Deze query retourneert één overeenkomst (top=1
) die bestaat uit het ene segment dat wordt bepaald door de zoekmachine om het meest relevant te zijn. Resultaten van de query moeten er ongeveer uitzien als in het volgende voorbeeld:
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
Probeer nog een paar query's om een idee te krijgen van wat de zoekmachine rechtstreeks retourneert, zodat u deze kunt vergelijken met een LLM-antwoord. Voer het vorige script opnieuw uit met deze query: "patagonia geography"
en stel in op top
3 om meer dan één antwoord te retourneren.
Resultaten van deze tweede query moeten er ongeveer uitzien als de volgende resultaten, die licht worden bewerkt voor concisie. De uitvoer wordt gekopieerd uit het notebook, waarmee het antwoord wordt afgekapt naar wat u in dit voorbeeld ziet. U kunt de uitvoer van de cel uitbreiden om het volledige antwoord te controleren.
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.
In dit voorbeeld is het eenvoudiger om te zien hoe segmenten letterlijk worden geretourneerd en hoe trefwoorden en overeenkomsten de belangrijkste overeenkomsten identificeren. Dit specifieke segment heeft zeker informatie over De geografie en De geografie van De Stad, maar het is niet precies relevant voor de query. Met een semantische rangschikking worden relevantere segmenten gepromoot voor een beter antwoord, maar als volgende stap gaan we kijken hoe u Azure AI Search kunt verbinden met een LLM voor gesprekszoekopdrachten.