Självstudie: Använda .NET och AI för att generera sökbart innehåll från Azure-blobar

Om du har ostrukturerad text eller bilder i Azure Blob Storage kan en AI-berikningspipeline extrahera information och skapa nytt innehåll för fulltextsöknings- eller kunskapsutvinningsscenarier.

I den här C#-självstudien får du lära dig att:

  • Konfigurera en utvecklingsmiljö.
  • Definiera en pipeline som använder OCR, språkidentifiering, entitetsigenkänning och extrahering av nyckelfraser.
  • Kör pipelinen för att anropa transformeringar och för att skapa och läsa in ett sökindex.
  • Utforska resultat med fulltextsökning och en rtF-frågesyntax.

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 kompetensuppsättning.

Indexeraren ansluter till exempeldata i en blobcontainer som anges i datakällans objekt och skickar allt berikat innehåll till ett sökindex.

Kompetensuppsättningen är kopplad till indexeraren. Den använder inbyggda kunskaper från Microsoft för att hitta och extrahera information. Steg i pipelinen är optisk teckenigenkänning (OCR) på bilder, språkidentifiering för text, extrahering av nyckelfraser och entitetsigenkänning (organisationer). Ny information som skapas av pipelinen lagras i nya fält i ett index. När indexet har fyllts i kan du använda fälten i frågor, faser och filter.

Förutsättningar

Anteckning

Du kan använda den kostnadsfria söktjänsten för den här självstudien. En kostnadsfri söktjänst 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 kontrollerar du att du har plats för din tjänst för att acceptera de nya resurserna.

Ladda ned filer

Exempeldata består av 14 filer av blandad innehållstyp som du laddar upp till Azure Blob Storage i ett senare steg.

  1. Hämta filerna från azure-search-sample-data/ai-enrichment-mixed-media/ och kopiera dem till din lokala dator.

  2. Hämta sedan källkoden för den här självstudien. Källkoden finns i mappen tutorial-ai-enrichment/v11 på lagringsplatsen azure-search-dotnet-samples .

1 – Skapa tjänster

Den här självstudien använder Azure Cognitive Search för indexering och frågor, Cognitive Services på serverdelen för AI-berikning och Azure Blob Storage för att tillhandahålla data. Den här självstudien ligger under den kostnadsfria allokeringen av 20 transaktioner per indexerare per dag i Cognitive Services, så de enda tjänster du behöver skapa är sökning och lagring.

Om möjligt skapar du både i samma region och resursgrupp för närhet och hanterbarhet. I praktiken kan ditt Azure Storage-konto finnas i valfri region.

Börja med Azure Storage

  1. Logga in på Azure-portalen och klicka på + Skapa resurs.

  2. Sök efter lagringskonto och välj Microsofts lagringskontoerbjudande.

    Create Storage account

  3. På fliken Grunder krävs följande objekt. Acceptera standardinställningarna för allt annat.

    • Resursgrupp. Välj en befintlig eller skapa en ny, men använd samma grupp för alla tjänster så att du kan hantera dem kollektivt.

    • Namn på lagringskonto. Om du tror att du har flera resurser av samma typ kan du använda namnet för att skilja mellan typ och region, till exempel blobstoragewestus.

    • Plats. Om möjligt väljer du samma plats som används för Azure Cognitive Search och Cognitive Services. En enda plats ogiltigförklarar bandbreddsavgifter.

    • Typ av konto. Välj standardinställningen StorageV2 (generell användning v2).

  4. Välj Granska + Skapa för att skapa tjänsten.

  5. När den har skapats väljer du Gå till resursen för att öppna sidan Översikt.

  6. Välj Blobs-tjänsten .

  7. Välj + Container för att skapa en container och ge den namnet cog-search-demo.

  8. Välj cog-search-demo och välj sedan Ladda upp för att öppna mappen där du sparade nedladdningsfilerna. Markera alla filer. Välj Överför.

    Screenshot of the files in File Explorer.

  9. Innan du lämnar Azure Storage hämtar du en anslutningssträng så att du kan formulera en anslutning i Azure Cognitive Search.

    1. Bläddra tillbaka till sidan Översikt för ditt lagringskonto (vi använde blobstragewestus som exempel).

    2. I det vänstra navigeringsfönstret väljer du Åtkomstnycklar och kopierar en av anslutningssträngarna.

    Anslutningssträngen är en URL som liknar följande exempel:

    DefaultEndpointsProtocol=https;AccountName=cogsrchdemostorage;AccountKey=<your account key>;EndpointSuffix=core.windows.net
    
  10. Spara anslutningssträngen i Anteckningar. Du behöver det senare när du konfigurerar datakällans anslutning.

Cognitive Services

AI-berikning backas upp av Cognitive Services, inklusive Språktjänst och Visuellt innehåll för naturligt språk och bildbearbetning. Om målet var att slutföra en faktisk prototyp eller ett projekt skulle du nu etablera Cognitive Services (i samma region som Azure Cognitive Search) så att du kan koppla den till indexeringsåtgärder.

I den här övningen kan du dock hoppa över resursetablering eftersom Azure Cognitive Search kan ansluta till Cognitive Services i bakgrunden och ge dig 20 kostnadsfria transaktioner per indexerare. Eftersom den här självstudien använder 14 transaktioner räcker det med den kostnadsfria allokeringen. För större projekt planerar du att etablera Cognitive Services på S0-nivån betala per användning. Mer information finns i Bifoga Cognitive Services.

Den tredje komponenten är Azure Cognitive Search, som du kan skapa i portalen eller hitta en befintlig söktjänst i din prenumeration.

Du kan använda den kostnadsfria nivån för att slutföra den här genomgången.

För att interagera med din Azure Cognitive Search-tjänst behöver du tjänstens URL och en åtkomstnyckel.

  1. Logga in på Azure-portalen och hämta namnet på söktjänsten på söktjänstens översiktssida . Du kan bekräfta tjänstnamnet genom att granska slutpunkts-URL:en. Om slutpunkts-URL:en var https://mydemo.search.windows.netskulle tjänstnamnet vara mydemo.

  2. I Inställningar>nycklar hämtar du en administratörsnyckel för fullständiga rättigheter för tjänsten. Du kan kopiera antingen den primära eller sekundära nyckeln.

Get the service name and admin key

En giltig nyckel upprättar förtroende, i varje begäran, mellan programmet som skickar begäran och tjänsten som hanterar den.

2 – Konfigurera din miljö

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

Installera Azure.Search.Documents

Azure Cognitive 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 hantera information om HTTP och JSON. Det här klientbiblioteket distribueras som ett NuGet-paket.

Installera version 11 eller senare av och den senaste versionen av Azure.Search.DocumentsMicrosoft.Extensions.Configurationför det här projektet.

  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 klicka sedan på Installera.

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

Lägg 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 nedanstående JSON till din nya JSON-fil.

    {
      "SearchServiceUri": "Put your search service URI here",
      "SearchServiceAdminApiKey": "Put your primary or secondary API key here",
      "SearchServiceQueryApiKey": "Put your query API key here",
      "AzureBlobConnectionString": "Put your Azure Blob connection string here",
    }
    

Lägg till din söktjänst och bloblagringskontoinformation. Kom ihåg att du kan hämta den här informationen från stegen för tjänstetablering som angavs 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 cognitiveServicesKey = configuration["CognitiveServicesKey"];

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

Anteckning

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 möjliggöra 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 ExitProgram till Main 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);
}

3 – Skapa pipelinen

I Azure Cognitive 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 Cognitive 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 cognitive 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, utlöser 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 har skapats i Azure Cognitive 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 kognitiva färdigheter för kompetensuppsättningen:

  • Optisk teckenläsning för att känna igen 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 färdigheten extrahering av nyckelfraser och entitetsigenkänningsfärdigheten. 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 första bearbetningen knäcker Azure Cognitive 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 som "/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-färdighet

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

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

LanguageDetectionSkill identifierar 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;
}

Färdighet för 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 i storlek. 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 "/document/pages/*" på med en asterisk, vilket innebär att 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;
}

Kunskap om extrahering av 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 som du skapade.

private static SearchIndexerSkillset CreateOrUpdateDemoSkillSet(SearchIndexerClient indexerClient, IList<SearchIndexerSkill> skills,string cognitiveServicesKey)
{
    SearchIndexerSkillset skillset = new SearchIndexerSkillset("demoskillset", skills)
    {
        Description = "Demo skillset",
        CognitiveServicesAccount = new CognitiveServicesAccountKey(cognitiveServicesKey)
    };

    // 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, cognitiveServicesKey);

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 matcha fältnamn identiskt 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ältnamn 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 i modellklassen har attribut som avgör motsvarande indexfälts sökrelaterade beteende.

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 upptäcker att du försöker skapa indexet mer än en gång. Därför kontrollerar du om det index som du håller på att 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 using-instruktion för att lösa disambiguate-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ältnamnen och typerna ä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 berikandet 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 bearbetningen av indexeraren tar lite tid att slutföra. Trots att datauppsättningen är liten är analytiska kunskaper beräkningsintensiva. Vissa kunskaper, som bildanalys, är tidskrävande.

Tips

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 anger "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 "contentAndMetadata"är inställt på "dataToExtract" . 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" , i kombination med OCR-färdigheten och sammanslagningsfärdigheten för text, instruerar indexeraren att extrahera text från bilderna (till exempel ordet "stoppa" från en trafikstoppskylt) 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.

4 – Övervaka indexering

När du har definierat indexeraren körs den automatiskt när du skickar din begäran. Beroende på vilka kognitiva kunskaper du har definierat kan indexeringen ta längre tid än väntat. Om du vill ta reda på om indexeraren fortfarande körs använder du GetStatus metoden .

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 statusen och körningshistoriken för en indexerare.

Varningar är vanliga med vissa källfils- och kunskapskombinationer och är inte alltid tecken på 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 Cognitive Search-självstudiekursens konsolappar 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öksidan Översikt 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 är sökbart 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 utvecklingsstadierna är den mest praktiska metoden för designiteration att ta bort objekten från Azure Cognitive 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 demonstrerade 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 indexerardefinitionen krävs för att dirigera berikade värden från pipelinen till ett sökbart index i en Azure Cognitive Search-tjänst.

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 är det en bra idé att ta bort de resurser som du inte längre behöver i slutet av ett projekt. Resurser som fortsätter att köras kostar pengar. Du kan ta bort resurser individuellt eller ta bort resursgruppen om du vill ta bort hela uppsättningen 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 ta en närmare titt på definitioner för kompetensuppsättningar och enskilda färdigheter.