Delen via


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

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.

  1. Meld u aan bij Azure Portal en zoek uw Azure Storage-account.

  2. Maak een container en upload de PDF-bestanden vanuit earth_book_2019_text_pages.

  3. Zorg ervoor dat Azure AI Search machtigingen voor opslagblobgegevenslezer heeft voor de resource.

  4. 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.

Volgende stap