Dela via


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

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.

  1. Logga in på Azure Portal och hitta ditt Azure Storage-konto.

  2. Skapa en container och ladda upp PDF-filerna från earth_book_2019_text_pages.

  3. Kontrollera att Azure AI Search har behörigheter för Storage Blob Data Reader på resursen.

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

Gå vidare