C#-självstudie: Använda kompetensuppsättningar för att generera sökbart innehåll i Azure AI Search

I den här självstudien får du lära dig hur du använder Azure SDK för .NET för att skapa en PIPELINE för AI-berikande för extrahering och transformering av innehåll under indexering.

Kunskapsuppsättningar lägger till AI-bearbetning till råinnehåll, vilket gör innehållet mer enhetligt och sökbart. När du vet hur kompetensuppsättningar fungerar kan du stödja en mängd olika omvandlingar: från bildanalys till bearbetning av naturligt språk till anpassad bearbetning som du tillhandahåller externt.

Den här självstudien hjälper dig att lära dig att:

  • Definiera objekt i en berikningspipeline.
  • Skapa en kompetensuppsättning. Anropa OCR, språkidentifiering, entitetsigenkänning och extrahering av nyckelfraser.
  • Kör pipelinen. Skapa och läsa in ett sökindex.
  • Kontrollera resultaten med hjälp av fulltextsökning.

Om du inte har en Azure-prenumeration öppnar du ett kostnadsfritt konto innan du börjar.

Översikt

I den här självstudien används C# och Azure.Search.Documents-klientbiblioteket för att skapa en datakälla, ett index, en indexerare och en kunskapsuppsättning.

Indexeraren kör varje steg i pipelinen och börjar med innehållsextrahering av exempeldata (ostrukturerad text och bilder) i en blobcontainer i Azure Storage.

När innehållet har extraherats kör kompetensuppsättningen inbyggda kunskaper från Microsoft för att hitta och extrahera information. Dessa kunskaper omfattar optisk teckenigenkänning (OCR) på bilder, språkidentifiering på text, extrahering av nyckelfraser och entitetsigenkänning (organisationer). Ny information som skapats av kompetensuppsättningen skickas till fält i ett index. När indexet har fyllts i kan du använda fälten i frågor, fasetter och filter.

Förutsättningar

Kommentar

Du kan använda en kostnadsfri söktjänst för den här självstudien. Den kostnadsfria nivån begränsar dig till tre index, tre indexerare och tre datakällor. I den här kursen skapar du en av varje. Innan du börjar bör du se till att du har plats för din tjänst för att acceptera de nya resurserna.

Ladda ned filer

Ladda ned en zip-fil med exempeldatalagringsplatsen och extrahera innehållet. Lär dig mer.

Ladda upp exempeldata till Azure Storage

  1. I Azure Storage skapar du en ny container och ger den namnet cog-search-demo.

  2. Ladda upp exempeldatafilerna.

  3. Hämta en lagrings-anslutningssträng så att du kan formulera en anslutning i Azure AI Search.

    1. Välj Åtkomstnycklar till vänster.

    2. Kopiera anslutningssträng för antingen nyckel ett eller nyckel två. Anslutningssträng liknar följande exempel:

      DefaultEndpointsProtocol=https;AccountName=<your account name>;AccountKey=<your account key>;EndpointSuffix=core.windows.net
      

Azure AI-tjänster

Inbyggd AI-berikning backas upp av Azure AI-tjänster, inklusive Language Service och Azure AI Vision för naturligt språk och bildbearbetning. För små arbetsbelastningar som den här självstudien kan du använda den kostnadsfria allokeringen av 20 transaktioner per indexerare. För större arbetsbelastningar kan du koppla en Azure AI Services-resurs i flera regioner till en kompetensuppsättning för betala per användning-priser.

Kopiera en url för söktjänsten och API-nyckeln

I den här självstudien kräver anslutningar till Azure AI Search en slutpunkt och en API-nyckel. Du kan hämta dessa värden från Azure-portalen.

  1. Logga in på Azure-portalen, gå till söktjänstens översiktssida och kopiera URL:en. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

  2. Under Inställningar> Nycklar kopierar du en administratörsnyckel. Administratörsnycklar används för att lägga till, ändra och ta bort objekt. Det finns två utbytbara administratörsnycklar. Kopiera någon av dem.

    Screenshot of the URL and API keys in the Azure portal.

Konfigurera din miljö

Börja med att öppna Visual Studio och skapa ett nytt Konsolappsprojekt som kan köras på .NET Core.

Installera Azure.Search.Documents

Azure AI Search .NET SDK består av ett klientbibliotek som gör att du kan hantera dina index, datakällor, indexerare och kompetensuppsättningar, samt ladda upp och hantera dokument och köra frågor, allt utan att behöva ta itu med informationen om HTTP och JSON. Det här klientbiblioteket distribueras som ett NuGet-paket.

För det här projektet installerar du version 11 eller senare av och Azure.Search.Documents den senaste versionen av Microsoft.Extensions.Configuration.

  1. I Visual Studio väljer du Verktyg>NuGet Package Manager>Hantera NuGet-paket för lösning...

  2. Bläddra efter Azure.Search.Document.

  3. Välj den senaste versionen och välj sedan Installera.

  4. Upprepa föregående steg för att installera Microsoft.Extensions.Configuration och Microsoft.Extensions.Configuration.Json.

Lägga till information om tjänstanslutning

  1. Högerklicka på projektet i Solution Explorer och välj Lägg till>nytt objekt... .

  2. Namnge filen appsettings.json och välj Lägg till.

  3. Inkludera den här filen i utdatakatalogen.

    1. Högerklicka på appsettings.json och välj Egenskaper.
    2. Ändra värdet för Kopiera till utdatakatalog till Kopiera om det är nyare.
  4. Kopiera JSON nedan till din nya JSON-fil.

    {
      "SearchServiceUri": "<YourSearchServiceUri>",
      "SearchServiceAdminApiKey": "<YourSearchServiceAdminApiKey>",
      "SearchServiceQueryApiKey": "<YourSearchServiceQueryApiKey>",
      "AzureAIServicesKey": "<YourMultiRegionAzureAIServicesKey>",
      "AzureBlobConnectionString": "<YourAzureBlobConnectionString>"
    }
    

Lägg till din söktjänst och bloblagringskontoinformation. Kom ihåg att du kan hämta den här informationen från de tjänstetableringssteg som anges i föregående avsnitt.

För SearchServiceUri anger du den fullständiga URL:en.

Lägga till namnområden

I Program.cslägger du till följande namnområden.

using Azure;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;

namespace EnrichwithAI

Skapa en klient

Skapa en instans av en SearchIndexClient och en SearchIndexerClient under Main.

public static void Main(string[] args)
{
    // Create service client
    IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json");
    IConfigurationRoot configuration = builder.Build();

    string searchServiceUri = configuration["SearchServiceUri"];
    string adminApiKey = configuration["SearchServiceAdminApiKey"];
    string azureAiServicesKey = configuration["AzureAIServicesKey"];

    SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceUri), new AzureKeyCredential(adminApiKey));
    SearchIndexerClient indexerClient = new SearchIndexerClient(new Uri(searchServiceUri), new AzureKeyCredential(adminApiKey));
}

Kommentar

Klienterna ansluter till söktjänsten. För att undvika att öppna för många anslutningar bör du försöka dela en enda instans i ditt program om det är möjligt. Metoderna är trådsäkra för att aktivera sådan delning.

Lägg till funktion för att avsluta programmet vid fel

Den här självstudien är avsedd att hjälpa dig att förstå varje steg i indexeringspipelinen. Om det finns ett kritiskt problem som hindrar programmet från att skapa datakällan, kompetensuppsättningen, indexet eller indexeraren kommer programmet att mata ut felmeddelandet och avsluta så att problemet kan förstås och åtgärdas.

Lägg till ExitProgramMain i för att hantera scenarier som kräver att programmet avslutas.

private static void ExitProgram(string message)
{
    Console.WriteLine("{0}", message);
    Console.WriteLine("Press any key to exit the program...");
    Console.ReadKey();
    Environment.Exit(0);
}

Skapa pipelinen

I Azure AI Search sker AI-bearbetning under indexering (eller datainmatning). Den här delen av genomgången skapar fyra objekt: datakälla, indexdefinition, kompetensuppsättning, indexerare.

Steg 1: Skapa en datakälla

SearchIndexerClient har en DataSourceName egenskap som du kan ange till ett SearchIndexerDataSourceConnection objekt. Det här objektet innehåller alla metoder som du behöver för att skapa, lista, uppdatera eller ta bort Azure AI Search-datakällor.

Skapa en ny SearchIndexerDataSourceConnection instans genom att anropa indexerClient.CreateOrUpdateDataSourceConnection(dataSource). Följande kod skapar en datakälla av typen AzureBlob.

private static SearchIndexerDataSourceConnection CreateOrUpdateDataSource(SearchIndexerClient indexerClient, IConfigurationRoot configuration)
{
    SearchIndexerDataSourceConnection dataSource = new SearchIndexerDataSourceConnection(
        name: "demodata",
        type: SearchIndexerDataSourceType.AzureBlob,
        connectionString: configuration["AzureBlobConnectionString"],
        container: new SearchIndexerDataContainer("cog-search-demo"))
    {
        Description = "Demo files to demonstrate Azure AI Search capabilities."
    };

    // The data source does not need to be deleted if it was already created
    // since we are using the CreateOrUpdate method
    try
    {
        indexerClient.CreateOrUpdateDataSourceConnection(dataSource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed to create or update the data source\n Exception message: {0}\n", ex.Message);
        ExitProgram("Cannot continue without a data source");
    }

    return dataSource;
}

För en lyckad begäran returnerar metoden den datakälla som skapades. Om det uppstår ett problem med begäran, till exempel en ogiltig parameter, genererar metoden ett undantag.

Lägg nu till en rad i Main för att anropa funktionen CreateOrUpdateDataSource som du just har lagt till.

// Create or Update the data source
Console.WriteLine("Creating or updating the data source...");
SearchIndexerDataSourceConnection dataSource = CreateOrUpdateDataSource(indexerClient, configuration);

Skapa och kör lösningen. Eftersom det här är din första begäran kontrollerar du Azure-portalen för att bekräfta att datakällan skapades i Azure AI Search. På översiktssidan för söktjänsten kontrollerar du att listan Datakällor har ett nytt objekt. Du kan behöva vänta några minuter medan portalsidan uppdateras.

Data sources tile in the portal

Steg 2: Skapa en kompetensuppsättning

I det här avsnittet definierar du en uppsättning berikningssteg som du vill tillämpa på dina data. Varje berikningssteg kallas för en färdighet och en uppsättning berikningssteg, en kompetensuppsättning. I den här självstudien används inbyggda kunskaper för kompetensuppsättningen:

  • Optisk teckenigenkänning för att identifiera tryckt och handskriven text i bildfiler.

  • Textsammanslagning för att konsolidera text från en samling fält till ett enda "sammanfogat innehåll"-fält.

  • Språkidentifiering för att identifiera innehållets språk.

  • Entitetsigenkänning för att extrahera namnen på organisationer från innehåll i blobcontainern.

  • Textdelning för att dela upp stort innehåll i mindre segment innan du anropar kunskapen om extrahering av nyckelfraser och kunskapen om entitetsigenkänning. Extrahering av nyckelfraser och entitetsigenkänning accepterar indata på högst 50 000 tecken. Några av exempelfilerna måste delas upp för att rymmas inom gränsen.

  • Extrahering av nyckelfraser för att hämta viktigaste nyckelfraserna.

Under den inledande bearbetningen spricker Azure AI Search varje dokument för att extrahera innehåll från olika filformat. Text som kommer från källfilen placeras i ett genererat content fält, ett för varje dokument. Ange därför indata för "/document/content" att använda den här texten. Bildinnehåll placeras i ett genererat normalized_images fält som anges i en kompetensuppsättning som /document/normalized_images/*.

Utdata kan mappas till ett index som används som indata till en underordnad kunskap, eller både, vilket är fallet med språkkod. I indexet kan en språkkod användas för filtrering. Som indata används språkkoden av textanalyskunskaper för att informera om de språkliga reglerna kring ordnedbrytning.

Mer information om grunderna i kunskapsuppsättningar finns i Definiera en kunskapsuppsättning.

OCR-kompetens

Extraherar OcrSkill text från bilder. Den här färdigheten förutsätter att det finns ett normalized_images fält. För att generera det här fältet anger vi senare i självstudien konfigurationen "imageAction" i indexerardefinitionen till "generateNormalizedImages".

private static OcrSkill CreateOcrSkill()
{
    List<InputFieldMappingEntry> inputMappings = new List<InputFieldMappingEntry>();
    inputMappings.Add(new InputFieldMappingEntry("image")
    {
        Source = "/document/normalized_images/*"
    });

    List<OutputFieldMappingEntry> outputMappings = new List<OutputFieldMappingEntry>();
    outputMappings.Add(new OutputFieldMappingEntry("text")
    {
        TargetName = "text"
    });

    OcrSkill ocrSkill = new OcrSkill(inputMappings, outputMappings)
    {
        Description = "Extract text (plain and structured) from image",
        Context = "/document/normalized_images/*",
        DefaultLanguageCode = OcrSkillLanguage.En,
        ShouldDetectOrientation = true
    };

    return ocrSkill;
}

Sammanslagningsfärdighet

I det här avsnittet skapar du en MergeSkill som sammanfogar dokumentinnehållsfältet med texten som skapades av OCR-färdigheten.

private static MergeSkill CreateMergeSkill()
{
    List<InputFieldMappingEntry> inputMappings = new List<InputFieldMappingEntry>();
    inputMappings.Add(new InputFieldMappingEntry("text")
    {
        Source = "/document/content"
    });
    inputMappings.Add(new InputFieldMappingEntry("itemsToInsert")
    {
        Source = "/document/normalized_images/*/text"
    });
    inputMappings.Add(new InputFieldMappingEntry("offsets")
    {
        Source = "/document/normalized_images/*/contentOffset"
    });

    List<OutputFieldMappingEntry> outputMappings = new List<OutputFieldMappingEntry>();
    outputMappings.Add(new OutputFieldMappingEntry("mergedText")
    {
        TargetName = "merged_text"
    });

    MergeSkill mergeSkill = new MergeSkill(inputMappings, outputMappings)
    {
        Description = "Create merged_text which includes all the textual representation of each image inserted at the right location in the content field.",
        Context = "/document",
        InsertPreTag = " ",
        InsertPostTag = " "
    };

    return mergeSkill;
}

Språkidentifieringsfärdighet

Identifierar LanguageDetectionSkill språket i indatatexten och rapporterar en enda språkkod för varje dokument som skickas på begäran. Vi använder utdata från språkidentifieringsfärdigheten som en del av inmatningen till färdigheten Textdelning .

private static LanguageDetectionSkill CreateLanguageDetectionSkill()
{
    List<InputFieldMappingEntry> inputMappings = new List<InputFieldMappingEntry>();
    inputMappings.Add(new InputFieldMappingEntry("text")
    {
        Source = "/document/merged_text"
    });

    List<OutputFieldMappingEntry> outputMappings = new List<OutputFieldMappingEntry>();
    outputMappings.Add(new OutputFieldMappingEntry("languageCode")
    {
        TargetName = "languageCode"
    });

    LanguageDetectionSkill languageDetectionSkill = new LanguageDetectionSkill(inputMappings, outputMappings)
    {
        Description = "Detect the language used in the document",
        Context = "/document"
    };

    return languageDetectionSkill;
}

Kunskap om textdelning

Nedanstående SplitSkill delar upp text efter sidor och begränsar sidlängden till 4 000 tecken mätt med String.Length. Algoritmen försöker dela upp texten i segment som är som mest maximumPageLength stora. I det här fallet gör algoritmen sitt bästa för att bryta meningen på en meningsgräns, så storleken på segmentet kan vara något mindre än maximumPageLength.

private static SplitSkill CreateSplitSkill()
{
    List<InputFieldMappingEntry> inputMappings = new List<InputFieldMappingEntry>();
    inputMappings.Add(new InputFieldMappingEntry("text")
    {
        Source = "/document/merged_text"
    });
    inputMappings.Add(new InputFieldMappingEntry("languageCode")
    {
        Source = "/document/languageCode"
    });

    List<OutputFieldMappingEntry> outputMappings = new List<OutputFieldMappingEntry>();
    outputMappings.Add(new OutputFieldMappingEntry("textItems")
    {
        TargetName = "pages",
    });

    SplitSkill splitSkill = new SplitSkill(inputMappings, outputMappings)
    {
        Description = "Split content into pages",
        Context = "/document",
        TextSplitMode = TextSplitMode.Pages,
        MaximumPageLength = 4000,
        DefaultLanguageCode = SplitSkillLanguage.En
    };

    return splitSkill;
}

Kunskap om entitetsigenkänning

Den här EntityRecognitionSkill instansen är inställd på att identifiera kategoritypen organization. EntityRecognitionSkill Kan också identifiera kategorityper person och location.

Observera att fältet "context" är inställt på med en asterisk, vilket innebär att "/document/pages/*" berikningssteget anropas för varje sida under "/document/pages".

private static EntityRecognitionSkill CreateEntityRecognitionSkill()
{
    List<InputFieldMappingEntry> inputMappings = new List<InputFieldMappingEntry>();
    inputMappings.Add(new InputFieldMappingEntry("text")
    {
        Source = "/document/pages/*"
    });

    List<OutputFieldMappingEntry> outputMappings = new List<OutputFieldMappingEntry>();
    outputMappings.Add(new OutputFieldMappingEntry("organizations")
    {
        TargetName = "organizations"
    });

    EntityRecognitionSkill entityRecognitionSkill = new EntityRecognitionSkill(inputMappings, outputMappings)
    {
        Description = "Recognize organizations",
        Context = "/document/pages/*",
        DefaultLanguageCode = EntityRecognitionSkillLanguage.En
    };
    entityRecognitionSkill.Categories.Add(EntityCategory.Organization);

    return entityRecognitionSkill;
}

Extraheringsfärdighet för nyckelfraser

Precis som den EntityRecognitionSkill instans som just skapades KeyPhraseExtractionSkill anropas för varje sida i dokumentet.

private static KeyPhraseExtractionSkill CreateKeyPhraseExtractionSkill()
{
    List<InputFieldMappingEntry> inputMappings = new List<InputFieldMappingEntry>();
    inputMappings.Add(new InputFieldMappingEntry("text")
    {
        Source = "/document/pages/*"
    });
    inputMappings.Add(new InputFieldMappingEntry("languageCode")
    {
        Source = "/document/languageCode"
    });

    List<OutputFieldMappingEntry> outputMappings = new List<OutputFieldMappingEntry>();
    outputMappings.Add(new OutputFieldMappingEntry("keyPhrases")
    {
        TargetName = "keyPhrases"
    });

    KeyPhraseExtractionSkill keyPhraseExtractionSkill = new KeyPhraseExtractionSkill(inputMappings, outputMappings)
    {
        Description = "Extract the key phrases",
        Context = "/document/pages/*",
        DefaultLanguageCode = KeyPhraseExtractionSkillLanguage.En
    };

    return keyPhraseExtractionSkill;
}

Skapa och skapa kompetensuppsättningen

Skapa med hjälp av SearchIndexerSkillset de kunskaper du skapade.

private static SearchIndexerSkillset CreateOrUpdateDemoSkillSet(SearchIndexerClient indexerClient, IList<SearchIndexerSkill> skills,string azureAiServicesKey)
{
    SearchIndexerSkillset skillset = new SearchIndexerSkillset("demoskillset", skills)
    {
        // Azure AI services was formerly known as Cognitive Services.
        // The APIs still use the old name, so we need to create a CognitiveServicesAccountKey object.
        Description = "Demo skillset",
        CognitiveServicesAccount = new CognitiveServicesAccountKey(azureAiServicesKey)
    };

    // Create the skillset in your search service.
    // The skillset does not need to be deleted if it was already created
    // since we are using the CreateOrUpdate method
    try
    {
        indexerClient.CreateOrUpdateSkillset(skillset);
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine("Failed to create the skillset\n Exception message: {0}\n", ex.Message);
        ExitProgram("Cannot continue without a skillset");
    }

    return skillset;
}

Lägg till följande rader i Main.

// Create the skills
Console.WriteLine("Creating the skills...");
OcrSkill ocrSkill = CreateOcrSkill();
MergeSkill mergeSkill = CreateMergeSkill();
EntityRecognitionSkill entityRecognitionSkill = CreateEntityRecognitionSkill();
LanguageDetectionSkill languageDetectionSkill = CreateLanguageDetectionSkill();
SplitSkill splitSkill = CreateSplitSkill();
KeyPhraseExtractionSkill keyPhraseExtractionSkill = CreateKeyPhraseExtractionSkill();

// Create the skillset
Console.WriteLine("Creating or updating the skillset...");
List<SearchIndexerSkill> skills = new List<SearchIndexerSkill>();
skills.Add(ocrSkill);
skills.Add(mergeSkill);
skills.Add(languageDetectionSkill);
skills.Add(splitSkill);
skills.Add(entityRecognitionSkill);
skills.Add(keyPhraseExtractionSkill);

SearchIndexerSkillset skillset = CreateOrUpdateDemoSkillSet(indexerClient, skills, azureAiServicesKey);

Steg 3: Skapa ett index

I det här avsnittet definierar du indexschemat genom att ange vilka fält som ska ingå i det sökbara indexet och sökattributen för varje fält. Fält har en typ och kan ta attribut som bestämmer hur fältet ska användas (sökbart, sorteringsbart och så vidare). Fältnamn i ett index krävs inte för att identiskt matcha fältnamnen i källan. I ett senare steg lägger du till fältmappningar i en indexerare för att ansluta källa-mål-fält. För det här steget definiera indexet med fältnamnkonventioner som är relevanta för ditt sökprogram.

Den här övningen använder följande fält och fälttyp:

Fält-namn: Fälttyper
id Edm.String
content Edm.String
languageCode Edm.String
keyPhrases Lista<Edm.String>
organizations Lista<Edm.String>

Skapa DemoIndex-klass

Fälten för det här indexet definieras med hjälp av en modellklass. Varje egenskap för modellklassen har attribut som avgör sökrelaterade beteenden för motsvarande indexfält.

Vi lägger till modellklassen i en ny C#-fil. Högerklicka på projektet och välj Lägg till>nytt objekt..., välj "Klass" och ge filen DemoIndex.csnamnet och välj sedan Lägg till.

Se till att ange att du vill använda typer från namnrymderna Azure.Search.Documents.Indexes och System.Text.Json.Serialization .

Lägg till modellklassdefinitionen nedan i DemoIndex.cs och inkludera den i samma namnområde där du skapar indexet.

using Azure.Search.Documents.Indexes;
using System.Text.Json.Serialization;

namespace EnrichwithAI
{
    // The SerializePropertyNamesAsCamelCase is currently unsupported as of this writing. 
    // Replace it with JsonPropertyName
    public class DemoIndex
    {
        [SearchableField(IsSortable = true, IsKey = true)]
        [JsonPropertyName("id")]
        public string Id { get; set; }

        [SearchableField]
        [JsonPropertyName("content")]
        public string Content { get; set; }

        [SearchableField]
        [JsonPropertyName("languageCode")]
        public string LanguageCode { get; set; }

        [SearchableField]
        [JsonPropertyName("keyPhrases")]
        public string[] KeyPhrases { get; set; }

        [SearchableField]
        [JsonPropertyName("organizations")]
        public string[] Organizations { get; set; }
    }
}

Nu när du har definierat en modellklass Program.cs kan du skapa en indexdefinition ganska enkelt. Namnet på det här indexet blir demoindex. Om det redan finns ett index med det namnet tas det bort.

private static SearchIndex CreateDemoIndex(SearchIndexClient indexClient)
{
    FieldBuilder builder = new FieldBuilder();
    var index = new SearchIndex("demoindex")
    {
        Fields = builder.Build(typeof(DemoIndex))
    };

    try
    {
        indexClient.GetIndex(index.Name);
        indexClient.DeleteIndex(index.Name);
    }
    catch (RequestFailedException ex) when (ex.Status == 404)
    {
        //if the specified index not exist, 404 will be thrown.
    }

    try
    {
        indexClient.CreateIndex(index);
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine("Failed to create the index\n Exception message: {0}\n", ex.Message);
        ExitProgram("Cannot continue without an index");
    }

    return index;
}

Under testningen kanske du försöker skapa indexet mer än en gång. Därför kontrollerar du om det index som du ska skapa redan finns innan du försöker skapa det.

Lägg till följande rader i Main.

// Create the index
Console.WriteLine("Creating the index...");
SearchIndex demoIndex = CreateDemoIndex(indexClient);

Lägg till följande instruktion för att lösa den tvetydiga referensen.

using Index = Azure.Search.Documents.Indexes.Models;

Mer information om indexbegrepp finns i Skapa index (REST API).

Steg 4: Skapa och köra en indexerare

Hittills har du skapat en datakälla, en kunskapsuppsättning och ett index. De här tre komponenterna blir en del av en indexerare som sammanför varje del till en enda åtgärd i flera faser. Om du vill sammanfoga dem i en indexerare måste du definiera fältmappningar.

  • FieldMappings bearbetas före kompetensuppsättningen och mappar källfält från datakällan till målfält i ett index. Om fältnamn och typer är samma i båda ändar krävs ingen mappning.

  • OutputFieldMappings bearbetas efter kompetensuppsättningen och refererar till sourceFieldNames som inte finns förrän dokumentet spricker eller berikar skapar dem. targetFieldName är ett fält i ett index.

Förutom att koppla indata till utdata kan du även använda fältmappningar för att platta ut datastrukturer. Mer information finns i Mappa berikade fält till ett sökbart index.

private static SearchIndexer CreateDemoIndexer(SearchIndexerClient indexerClient, SearchIndexerDataSourceConnection dataSource, SearchIndexerSkillset skillSet, SearchIndex index)
{
    IndexingParameters indexingParameters = new IndexingParameters()
    {
        MaxFailedItems = -1,
        MaxFailedItemsPerBatch = -1,
    };
    indexingParameters.Configuration.Add("dataToExtract", "contentAndMetadata");
    indexingParameters.Configuration.Add("imageAction", "generateNormalizedImages");

    SearchIndexer indexer = new SearchIndexer("demoindexer", dataSource.Name, index.Name)
    {
        Description = "Demo Indexer",
        SkillsetName = skillSet.Name,
        Parameters = indexingParameters
    };

    FieldMappingFunction mappingFunction = new FieldMappingFunction("base64Encode");
    mappingFunction.Parameters.Add("useHttpServerUtilityUrlTokenEncode", true);

    indexer.FieldMappings.Add(new FieldMapping("metadata_storage_path")
    {
        TargetFieldName = "id",
        MappingFunction = mappingFunction

    });
    indexer.FieldMappings.Add(new FieldMapping("content")
    {
        TargetFieldName = "content"
    });

    indexer.OutputFieldMappings.Add(new FieldMapping("/document/pages/*/organizations/*")
    {
        TargetFieldName = "organizations"
    });
    indexer.OutputFieldMappings.Add(new FieldMapping("/document/pages/*/keyPhrases/*")
    {
        TargetFieldName = "keyPhrases"
    });
    indexer.OutputFieldMappings.Add(new FieldMapping("/document/languageCode")
    {
        TargetFieldName = "languageCode"
    });

    try
    {
        indexerClient.GetIndexer(indexer.Name);
        indexerClient.DeleteIndexer(indexer.Name);
    }
    catch (RequestFailedException ex) when (ex.Status == 404)
    {
        //if the specified indexer not exist, 404 will be thrown.
    }

    try
    {
        indexerClient.CreateIndexer(indexer);
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine("Failed to create the indexer\n Exception message: {0}\n", ex.Message);
        ExitProgram("Cannot continue without creating an indexer");
    }

    return indexer;
}

Lägg till följande rader i Main.

// Create the indexer, map fields, and execute transformations
Console.WriteLine("Creating the indexer and executing the pipeline...");
SearchIndexer demoIndexer = CreateDemoIndexer(indexerClient, dataSource, skillset, demoIndex);

Förvänta dig att indexerarens bearbetning tar lite tid att slutföra. Trots att datauppsättningen är liten är analytiska kunskaper beräkningsintensiva. Vissa kunskaper, som bildanalys, är tidskrävande.

Dricks

När en indexerare skapas anropas pipelinen. Om det uppstår problem med att ansluta till data, mappningsindata eller -utdata eller ordningen på åtgärder visas dem i det här stadiet.

Utforska hur du skapar indexeraren

Koden anges "maxFailedItems" till -1, vilket instruerar indexeringsmotorn att ignorera fel under dataimporten. Detta är användbart eftersom det finns det så få dokument i demo-datakällan. För en större datakälla skulle du ställa in värdet på större än 0.

Observera också att är inställt på "dataToExtract""contentAndMetadata". Den här instruktionen anger att indexeraren automatiskt ska extrahera innehållet från olika filformat samt metadata som är relaterade till varje fil.

När innehållet har extraherats kan du ställa in imageAction på att extrahera text från avbildningar som hittades i datakällan. Konfigurationsuppsättningen "imageAction""generateNormalizedImages" , kombinerad med OCR Skill and Text Merge Skill, instruerar indexeraren att extrahera text från bilderna (till exempel ordet "stopp" från en trafikstoppsskylt) och bädda in den som en del av innehållsfältet. Det här beteendet gäller både avbildningarna som är inbäddade i dokumenten (tänk på en avbildning i en PDF) samt avbildningar som hittas i datakällan, till exempel en JPG-fil.

Övervaka indexering

När du har definierat indexeraren körs den automatiskt när du skickar din begäran. Beroende på vilka kunskaper du har definierat kan indexeringen ta längre tid än förväntat. Använd metoden för att ta reda på om indexeraren fortfarande körs GetStatus .

private static void CheckIndexerOverallStatus(SearchIndexerClient indexerClient, SearchIndexer indexer)
{
    try
    {
        var demoIndexerExecutionInfo = indexerClient.GetIndexerStatus(indexer.Name);

        switch (demoIndexerExecutionInfo.Value.Status)
        {
            case IndexerStatus.Error:
                ExitProgram("Indexer has error status. Check the Azure Portal to further understand the error.");
                break;
            case IndexerStatus.Running:
                Console.WriteLine("Indexer is running");
                break;
            case IndexerStatus.Unknown:
                Console.WriteLine("Indexer status is unknown");
                break;
            default:
                Console.WriteLine("No indexer information");
                break;
        }
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine("Failed to get indexer overall status\n Exception message: {0}\n", ex.Message);
    }
}

demoIndexerExecutionInfo representerar den aktuella status- och körningshistoriken för en indexerare.

Varningar är vanliga med vissa kombinationer av källfiler och kunskaper och indikerar inte alltid ett problem. I den här självstudien är varningarna ofarliga (till exempel inga textindata från JPEG-filerna).

Lägg till följande rader i Main.

// Check indexer overall status
Console.WriteLine("Check the indexer overall status...");
CheckIndexerOverallStatus(indexerClient, demoIndexer);

I azure AI Search-självstudiekonsolappar lägger vi vanligtvis till en fördröjning på 2 sekunder innan vi kör frågor som returnerar resultat, men eftersom berikning tar flera minuter att slutföra stänger vi konsolappen och använder en annan metod i stället.

Det enklaste alternativet är Sökutforskaren i portalen. Du kan först köra en tom fråga som returnerar alla dokument eller en mer riktad sökning som returnerar nytt fältinnehåll som skapats av pipelinen.

  1. I Azure-portalen går du till sököversiktssidan och väljer Index.

  2. Sök demoindex i listan. Den bör ha 14 dokument. Om antalet dokument är noll körs indexeraren fortfarande eller så har sidan inte uppdaterats ännu.

  3. Välj demoindex. Sökutforskaren är den första fliken.

  4. Innehållet kan sökas efter så snart det första dokumentet har lästs in. Kontrollera att innehållet finns genom att köra en ospecificerad fråga genom att klicka på Sök. Den här frågan returnerar alla för närvarande indexerade dokument, vilket ger dig en uppfattning om vad indexet innehåller.

  5. Klistra sedan in följande sträng för mer hanterbara resultat: search=*&$select=id, languageCode, organizations

Återställa och köra igen

I de tidiga experimentella utvecklingsfaserna är det mest praktiska sättet att utforma iteration att ta bort objekten från Azure AI Search och låta koden återskapa dem. Resursnamn är unika. Om du tar bort ett objekt kan du återskapa det med samma namn.

Exempelkoden för den här självstudien söker efter befintliga objekt och tar bort dem så att du kan köra koden igen. Du kan också använda portalen för att ta bort index, indexerare, datakällor och kompetensuppsättningar.

Lärdomar

Den här självstudien visade de grundläggande stegen för att skapa en berikad indexeringspipeline genom att skapa komponentdelar: en datakälla, kompetensuppsättning, index och indexerare.

Inbyggda färdigheter introducerades, tillsammans med kompetensuppsättningsdefinition och mekaniken för sammanlänkning av färdigheter genom indata och utdata. Du har också lärt dig att outputFieldMappings i indexerarens definition krävs för att dirigera berikade värden från pipelinen till ett sökbart index på en Azure AI-tjänsten Search.

Slutligen lärde du dig att testa resultat och återställa systemet för ytterligare iterationer. Du har lärt dig att när du utfärdar frågor mot indexet returneras utdata som skapades av pipelinen för berikande indexering. Du har också lärt dig att kontrollera indexerarstatus, och vilka objekt du ska ta bort innan du kör en pipeline igen.

Rensa resurser

När du arbetar i din egen prenumeration i slutet av ett projekt är det en bra idé att ta bort de resurser som du inte längre behöver. Resurser som fortsätter att köras kostar pengar. Du kan ta bort enstaka resurser eller hela resursgruppen om du vill ta bort alla resurser.

Du kan hitta och hantera resurser i portalen med hjälp av länken Alla resurser eller Resursgrupper i det vänstra navigeringsfönstret.

Nästa steg

Nu när du är bekant med alla objekt i en AI-berikningspipeline ska vi titta närmare på definitioner för kompetensuppsättningar och individuella färdigheter.