Dela via


Definiera en indexprojektion för överordnad-underordnad indexering

För index som innehåller segmenterade dokument anger en indexprojektion hur överordnat-underordnat innehåll mappas till fält i ett sökindex för en-till-många-indexering. Genom en indexprojektion kan du skicka innehåll till:

  • Ett enda index, där de överordnade fälten upprepas för varje segment, men indexets korn är på segmentnivå. RAG-självstudien är ett exempel på den här metoden.

  • Två eller flera index, där det överordnade indexet har fält relaterade till det överordnade dokumentet, och det underordnade indexet är ordnat runt segment. Det underordnade indexet är den primära sök corpusen, men det överordnade indexet kan användas för sökningsfrågor när du vill hämta de överordnade fälten i ett visst segment eller för oberoende frågor.

De flesta implementeringar är ett enda index som är organiserat kring segment med överordnade fält, till exempel dokumentfilnamnet, som upprepas för varje segment. Systemet är dock utformat för att stödja separata och flera underordnade index om det är ditt behov. Azure AI Search stöder inte indexkopplingar, så programkoden måste hantera vilket index som ska användas.

En indexprojektion definieras i en kompetensuppsättning. Den ansvarar för att samordna indexeringsprocessen som skickar innehållssegment till ett sökindex, tillsammans med det överordnade innehållet som är associerat med varje segment. Det förbättrar hur intern datasegmentering fungerar genom att ge dina fler alternativ för att styra hur överordnat-underordnat innehåll indexeras.

Den här artikeln beskriver hur du skapar indexschema- och indexerarprojektionsmönster för en-till-många-indexering.

Förutsättningar

  • En indexerarbaserad indexeringspipeline.

  • Ett index (ett eller flera) som accepterar utdata från indexerarens pipeline.

  • En datakälla som stöds med innehåll som du vill segment. Det kan vara vektor- eller icke-bevektorinnehåll.

  • En färdighet som delar upp innehåll i segment, antingen färdigheten Textdelning eller en anpassad färdighet som ger motsvarande funktioner.

Kompetensuppsättningen innehåller indexerarens projektion som formar data för en-till-många-indexering. En kompetensuppsättning kan också ha andra färdigheter, till exempel en inbäddningsfärdighet som AzureOpenAIEmbedding om ditt scenario innehåller integrerad vektorisering.

Beroende av indexerarens bearbetning

En-till-många-indexering är beroende av kunskapsuppsättningar och indexerarbaserad indexering som innehåller följande fyra komponenter:

  • En datakälla
  • Ett eller flera index för ditt sökbara innehåll
  • En kompetensuppsättning som innehåller en indexprojektion*
  • En indexerare

Dina data kan komma från alla datakällor som stöds, men antagandet är att innehållet är tillräckligt stort för att du vill segmentera det, och orsaken till segmenteringen är att du implementerar ett RAG-mönster som ger grunddata till en chattmodell. Eller så implementerar du vektorsökning och behöver uppfylla kraven på mindre indatastorlek för inbäddningsmodeller.

Indexerare läser in indexerade data till ett fördefinierat index. Hur du definierar schemat och om du vill använda ett eller flera index är det första beslutet att fatta i ett en-till-många-indexeringsscenario. I nästa avsnitt beskrivs indexdesign.

Skapa ett index för en-till-många-indexering

Oavsett om du skapar ett index för segment som upprepar överordnade värden eller separata index för överordnad-underordnad fältplacering, är det primära index som används för sökning utformat kring datasegment. Den måste ha följande fält:

  • Ett dokumentnyckelfält som unikt identifierar varje dokument. Den måste definieras som typ Edm.String med analysatorn keyword .

  • Ett fält som associerar varje segment med dess överordnade segment. Den måste vara av typen Edm.String. Det kan inte vara dokumentets nyckelfält och måste ha filterable angetts till sant. Det kallas parent_id i exemplen och som ett beräknat nyckelvärde i den här artikeln.

  • Andra fält för innehåll, till exempel text eller vektoriserade segmentfält.

Det måste finnas ett index i söktjänsten innan du skapar kunskapsuppsättningen eller kör indexeraren.

Ett indexschema inklusive överordnade och underordnade fält

Ett enda index som är utformat runt segment med överordnat innehåll som upprepas för varje segment är det dominerande mönstret för RAG- och vektorsökningsscenarier. Möjligheten att associera rätt överordnat innehåll med varje segment aktiveras via indexprojektioner.

Följande schema är ett exempel som uppfyller kraven för indexprognoser. I det här exemplet är överordnade fält parent_id och rubriken. Underordnade fält är vektor- och icke-vektorsegmenten. Chunk_id är dokument-ID:t för det här indexet. Parent_id och titel upprepas för varje segment i indexet.

Du kan använda Azure Portal, REST API:er eller en Azure SDK för att skapa ett index.

{
    "name": "my_consolidated_index",
    "fields": [
        {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
        {"name": "parent_id", "type": "Edm.String", "filterable": true},
        {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true},
        {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
        {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
    ],
    "vectorSearch": {
        "algorithms": [{"name": "hsnw", "kind": "hnsw", "hnswParameters": {}}],
        "profiles": [{"name": "hsnw", "algorithm": "hnsw"}]
    }
}

Lägga till indexprojektioner i en kompetensuppsättning

Indexprojektioner definieras i en kompetensuppsättningsdefinition och definieras främst som en matris med selectors, där varje väljare motsvarar ett annat målindex i söktjänsten. Det här avsnittet börjar med syntax och exempel för kontext, följt av parameterreferens.

Välj en flik för de olika API-syntaxerna. Det finns för närvarande inget portalstöd för att konfigurera projektioner, förutom att redigera JSON-definitionen för kompetensuppsättningen. Se REST-exemplet för JSON.

Indexprognoser är allmänt tillgängliga. Vi rekommenderar det senaste stabila API:et:

Här är ett exempel på en nyttolast för en indexprojektionsdefinition som du kan använda för att projicera enskilda sidors utdata med färdigheten Textdelning som egna dokument i sökindexet.

"indexProjections": {
    "selectors": [
        {
            "targetIndexName": "my_consolidated_index",
            "parentKeyFieldName": "parent_id",
            "sourceContext": "/document/pages/*",
            "mappings": [
                {
                    "name": "chunk",
                    "source": "/document/pages/*",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "chunk_vector",
                    "source": "/document/pages/*/chunk_vector",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "title",
                    "source": "/document/title",
                    "sourceContext": null,
                    "inputs": []
                }
            ]
        }
    ],
    "parameters": {
        "projectionMode": "skipIndexingParentDocuments"
    }
}

Parameterreferens

Indexprojektionsparametrar Definition
selectors Parametrar för huvudsök corpus, vanligtvis den som är utformad runt segment.
projectionMode En valfri parameter som ger instruktioner till indexeraren. Det enda giltiga värdet för den här parametern är skipIndexingParentDocuments, och det används när segmentindexet är den primära sökkorusen och du måste ange om överordnade fält indexeras som extra sökdokument i det segmenterade indexet. Om du inte anger skipIndexingParentDocumentsfår du extra sökdokument i ditt index som är null för segment, men som endast fylls med överordnade fält. Om fem dokument till exempel bidrar med 100 segment till indexet är antalet dokument i indexet 105. De fem dokument som skapats eller överordnat fält har nullvärden för segmentfält (underordnade), vilket gör att de skiljer sig avsevärt från huvuddelen av dokumenten i indexet. Vi rekommenderar att projectionMode du anger till skipIndexingParentDocument.

Väljare har följande parametrar som en del av definitionen.

Väljareparametrar Definition
targetIndexName Namnet på indexet som indexdata projiceras till. Det är antingen det enskilda segmenterade indexet med upprepande överordnade fält, eller så är det det underordnade indexet om du använder separata index för överordnat-underordnat innehåll.
parentKeyFieldName Namnet på fältet som anger nyckeln för det överordnade dokumentet.
sourceContext Berikningsanteckningen som definierar kornigheten för att mappa data till enskilda sökdokument. Mer information finns i Kunskapskontext och indataanteckningsspråk.
mappings En matris med mappningar av berikade data till fält i sökindexet. Varje mappning består av:
name: Namnet på fältet i sökindexet som data ska indexeras till.
source: Den berikningsanteckningssökväg som data ska hämtas från.

Var mapping och en kan också rekursivt definiera data med ett valfritt fält och fält, som liknar kunskapsarkivet eller Shaper Skill.Each can also recursively define data with an optional sourceContext and inputs field, similar to the knowledge store or Shaper Skill. Beroende på ditt program kan du med de här parametrarna forma data till fält av typen Edm.ComplexType i sökindexet. Vissa LLM-datorer accepterar inte en komplex typ av sökresultat, så den LLM som du använder avgör om en komplex typmappning är användbar eller inte.

Parametern mappings är viktig. Du måste uttryckligen mappa alla fält i det underordnade indexet, förutom ID-fälten, till exempel dokumentnyckeln och det överordnade ID:t.

Det här kravet står i kontrast till andra fältmappningskonventioner i Azure AI Search. För vissa typer av datakällor kan indexeraren implicit mappa fält baserat på liknande namn eller kända egenskaper (till exempel använder blobindexerare den unika lagringssökvägen för metadata som standarddokumentnyckel). För indexerareprojektioner måste du dock uttryckligen ange varje fältmappning på "många"-sidan av relationen.

Skapa inte en fältmappning för det överordnade nyckelfältet. Detta stör ändringsspårning och synkroniserad datauppdatering.

Hantera överordnade dokument

Nu när du har sett flera mönster för en-till-många-indexeringar kan du jämföra viktiga skillnader om varje alternativ. Indexprojektioner genererar effektivt "underordnade" dokument för varje "överordnat" dokument som körs genom en kompetensuppsättning. Du har flera alternativ för att hantera "överordnade" dokument.

  • Om du vill skicka överordnade och underordnade dokument till separata index anger du indexeringsdefinitionen targetIndexName för indexeraren till det överordnade indexet och anger targetIndexName i indexprojektionsväljaren till det underordnade indexet.

  • Om du vill behålla överordnade och underordnade dokument i samma index anger du indexeraren targetIndexName och indexprojektionen targetIndexName till samma index.

  • Om du vill undvika att skapa överordnade sökdokument och se till att indexet endast innehåller underordnade dokument med ett enhetligt korn anger du targetIndexName för både indexerarens definition och väljaren till samma index, men lägger till ett extra parameters objekt efter selectors, med en projectionMode nyckel inställd på skipIndexingParentDocuments, som du ser här:

    "indexProjections": {
        "selectors": [
            ...
        ],
        "parameters": {
            "projectionMode": "skipIndexingParentDocuments"
        }
    }
    

Granska fältmappningar

Indexerare är kopplade till tre olika typer av fältmappningar. Innan du kör indexeraren kontrollerar du fältmappningarna och vet när du ska använda varje typ.

Fältmappningar definieras i en indexerare och används för att mappa ett källfält till ett indexfält. Fältmappningar används för datasökvägar som lyfter data från källan och skickar in dem för indexering, utan mellanliggande kompetensbearbetningssteg. Vanligtvis kan en indexerare automatiskt mappa fält som har samma namn och typ. Explicita fältmappningar krävs bara när det finns avvikelser. I en-till-många-indexering och de mönster som diskuterats hittills kanske du inte behöver fältmappningar.

Mappningar av utdatafält definieras i en indexerare och används för att mappa berikat innehåll som genereras av en kompetensuppsättning till ett fält till huvudindexet. I de en-till-många-mönster som beskrivs i den här artikeln är detta det överordnade indexet i en tvåindexlösning. I exemplen som visas i den här artikeln är det överordnade indexet glest, med bara ett rubrikfält, och det fältet är inte fyllt med innehåll från kompetensuppsättningsbearbetningen, så vi inte mappar utdatafält.

Indexerareprojektionsfältmappningar används för att mappa kunskapsuppsättningsgenererat innehåll till fält i det underordnade indexet. Om det underordnade indexet även innehåller överordnade fält (som i den konsoliderade indexlösningen) bör du konfigurera fältmappningar för varje fält som har innehåll, inklusive rubrikfältet på överordnad nivå, förutsatt att du vill att rubriken ska visas i varje segmenterat dokument. Om du använder separata överordnade och underordnade index bör indexerarens projektioner ha fältmappningar för bara de underordnade fälten.

Kommentar

Både utdatafältmappningar och indexerareprojektionsfältmappningar accepterar berikade dokumentträdnoder som källindata. Det är viktigt att du vet hur du anger en sökväg till varje nod för att konfigurera datasökvägen. Mer information om sökvägssyntax finns i Referera till en sökväg till berikade noder och definition av kompetensuppsättningar för exempel.

Köra indexeraren

När du har skapat en datakälla, index och kompetensuppsättning är du redo att skapa och köra indexeraren. Det här steget placerar pipelinen i körning.

Du kan köra frågor mot ditt sökindex när bearbetningen har slutförts för att testa lösningen.

Innehållslivscykel

Beroende på den underliggande datakällan kan en indexerare vanligtvis tillhandahålla löpande identifiering av ändringsspårning och borttagning. I det här avsnittet beskrivs innehållslivscykeln för en-till-många-indexering när det gäller datauppdatering.

För datakällor som tillhandahåller identifiering av ändringsspårning och borttagning kan en indexerarprocess hämta ändringar i dina källdata. Varje gång du kör indexeraren och kunskapsuppsättningen uppdateras indexprognoserna om kunskapsuppsättningen eller underliggande källdata har ändrats. Alla ändringar som hämtas av indexeraren sprids genom berikningsprocessen till projektionerna i indexet, vilket säkerställer att dina beräknade data är en aktuell representation av innehåll i den ursprungliga datakällan. Datauppdateringsaktiviteten samlas in i ett beräknat nyckelvärde för varje segment. Det här värdet uppdateras när underliggande data ändras.

Kommentar

Även om du kan redigera data manuellt i de planerade dokumenten med hjälp av index-push-API:et bör du undvika att göra det. Manuella uppdateringar av ett index skrivs över vid nästa pipelineanrop, förutsatt att dokumentet i källdata uppdateras och att datakällan har aktiverat ändringsspårning eller borttagningsidentifiering.

Uppdaterat innehåll

Om du lägger till nytt innehåll i datakällan läggs nya segment eller underordnade dokument till i indexet vid nästa indexeringskörning.

Om du ändrar befintligt innehåll i datakällan uppdateras segment stegvis i sökindexet om datakällan som du använder stöder identifiering av ändringsspårning och borttagning. För exammple uppdateras segmentet i målindexet som innehåller ordet eller meningen vid nästa indexkörning om ett ord eller en mening ändras i ett dokument. Andra typer av uppdateringar, till exempel att ändra en fälttyp och vissa attribut, stöds inte för befintliga fält. Mer information om tillåtna uppdateringar finns i Uppdatera ett indexschema.

Vissa datakällor som Azure Storage stöder ändrings- och borttagningsspårning som standard, baserat på tidsstämpeln. Andra datakällor som OneLake, Azure SQL eller Azure Cosmos DB måste konfigureras för ändringsspårning.

Borttaget innehåll

Om källinnehållet inte längre finns (till exempel om texten förkortas till att ha färre segment) tas motsvarande underordnade dokument i sökindexet bort. De återstående underordnade dokumenten uppdateras också för att inkludera ett nytt hash-värde, även om deras innehåll annars inte ändrades.

Om ett överordnat dokument tas bort helt från datakällan tas motsvarande underordnade dokument bara bort om borttagningen identifieras av en dataDeletionDetectionPolicy definierad i datakällans definition. Om du inte har konfigurerat dataDeletionDetectionPolicy och behöver ta bort ett överordnat dokument från datakällan bör du ta bort de underordnade dokumenten manuellt om de inte längre är önskade.

Beräknat nyckelvärde

För att säkerställa dataintegriteten för uppdaterat och borttaget innehåll förlitar sig datauppdateringen i en-till-många-indexering på ett beräknat nyckelvärde på "många"-sidan. Om du använder integrerad vektorisering eller guiden Importera och vektorisera data är parent_id det beräknade nyckelvärdet fältet i en segmenterad eller "många" sida av indexet.

Ett beräknat nyckelvärde är en unik identifierare som indexeraren genererar för varje dokument. Det säkerställer unikhet och gör det möjligt för spårning av ändringar och borttagning att fungera korrekt. Den här nyckeln innehåller följande segment:

  • En slumpmässig hash för att garantera unikhet. Denna hash ändras om det överordnade dokumentet uppdateras vid efterföljande indexerarekörningar.
  • Det överordnade dokumentets nyckel.
  • Den berikningsanteckningssökväg som identifierar den kontext som dokumentet genererades från.

Om du till exempel delar upp ett överordnat dokument med nyckelvärdet "aa1b22c33" i fyra sidor, och var och en av dessa sidor projiceras som ett eget dokument via indexprojektioner:

  • aa1b22c33
  • aa1b22c33_pages_0
  • aa1b22c33_pages_1
  • aa1b22c33_pages_2

Om det överordnade dokumentet uppdateras i källdata, vilket kanske resulterar i fler segmenterade sidor, ändras de slumpmässiga hash-ändringarna, fler sidor läggs till och innehållet i varje segment uppdateras så att det matchar det som finns i källdokumentet.

Exempel på separata överordnade och underordnade index

Det här avsnittet visar exempel för separata överordnade och underordnade index. Det är ett ovanligt mönster, men det är möjligt att du har programkrav som bäst uppfylls med den här metoden. I det här scenariot projicerar du överordnat-underordnat innehåll i två separata index.

Varje schema har fälten för sitt specifika korn, med det överordnade ID-fältet gemensamt för båda indexen för användning i en sökningsfråga. Den primära sök corpus är det underordnade indexet, men utfärda sedan en sökningsfråga för att hämta de överordnade fälten för varje matchning i resultatet. Azure AI Search stöder inte kopplingar vid frågetillfället, så programkoden eller orkestreringslagret måste sammanfoga eller sortera resultat som kan skickas till en app eller process.

Det överordnade indexet har ett parent_id fält och rubrik. Parent_id är dokumentnyckeln. Du behöver inte konfigurera vektorsökning om du inte vill vektorisera fält på den överordnade dokumentnivån.

{
    "name": "my-parent-index",
    "fields": [

        {"name": "parent_id", "type": "Edm.String", "filterable": true},
        {"name": "title", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "retrievable": true},
    ]
}

Det underordnade indexet har segmenterade fält, plus fältet parent_id. Om du använder integrerad vektorisering, bedömningsprofiler, semantisk rankning eller analysverktyg anger du dessa i det underordnade indexet.

{
    "name": "my-child-index",
    "fields": [
        {"name": "chunk_id", "type": "Edm.String", "key": true, "filterable": true, "analyzer": "keyword"},
        {"name": "parent_id", "type": "Edm.String", "filterable": true},
         {"name": "chunk", "type": "Edm.String","searchable": true,"retrievable": true},
        {"name": "chunk_vector", "type": "Collection(Edm.Single)", "searchable": true, "retrievable": false, "stored": false, "dimensions": 1536, "vectorSearchProfile": "hnsw"}
    ],
    "vectorSearch": {
        "algorithms": [{"name": "hsnw", "kind": "hnsw", "hnswParameters": {}}],
        "profiles": [{"name": "hsnw", "algorithm": "hnsw"}]
    },
    "scoringProfiles": [],
    "semanticConfiguration": [],
    "analyzers": []
}

Här är ett exempel på en indexprojektionsdefinition som anger den datasökväg som indexeraren ska använda för att indexeras innehåll. Den anger det underordnade indexnamnet i indexprojektionsdefinitionen och anger mappningarna för varje under- eller segmentnivåfält. Det här är den enda platsen där det underordnade indexnamnet har angetts.

"indexProjections": {
    "selectors": [
        {
            "targetIndexName": "my-child-index",
            "parentKeyFieldName": "parent_id",
            "sourceContext": "/document/pages/*",
            "mappings": [
                {
                    "name": "chunk",
                    "source": "/document/pages/*",
                    "sourceContext": null,
                    "inputs": []
                },
                {
                    "name": "chunk_vector",
                    "source": "/document/pages/*/chunk_vector",
                    "sourceContext": null,
                    "inputs": []
                }
            ]
        }
    ]
}

Indexerarens definition anger komponenterna i pipelinen. I indexerarens definition är det indexnamn som ska anges det överordnade indexet. Om du behöver fältmappningar för de överordnade fälten definierar du dem i outputFieldMappings. För en-till-många-indexering som använder separata index kan indexerardefinitionen se ut som i följande exempel.

{
  "name": "my-indexer",
  "dataSourceName": "my-ds",
  "targetIndexName": "my-parent-index",
  "skillsetName" : "my-skillset"
  "parameters": { },
  "fieldMappings": (optional) Maps fields in the underlying data source to fields in an index,
  "outputFieldMappings" : (required) Maps skill outputs to fields in an index,
}

Gå vidare

Datasegmentering och en-till-många-indexering är en del av RAG-mönstret i Azure AI Search. Fortsätt till följande självstudie och kodexempel om du vill veta mer om det.