Criar um repositório de conhecimento usando REST

No Azure AI Search, um repositório de conhecimento é um repositório de conteúdo gerado por IA que é usado para cenários que não são de pesquisa. Você cria o repositório de conhecimento usando um indexador e um conjunto de habilidades e especifica o Armazenamento do Azure para armazenar a saída. Depois que o repositório de conhecimento for preenchido, use ferramentas como o Gerenciador de Armazenamento ou o Power BI para explorar o conteúdo.

Neste artigo, você usa a API REST para ingerir, enriquecer e explorar um conjunto de avaliações de clientes sobre estadias em hotéis em um repositório de conhecimento. O armazenamento de conhecimento contém conteúdo de texto original extraído da fonte, além de conteúdo gerado por IA que inclui uma pontuação de sentimento, extração de frases-chave, deteção de idioma e tradução de texto de comentários de clientes que não estão em inglês.

Para disponibilizar o conjunto de dados inicial, as avaliações de hotéis são importadas primeiro para o Armazenamento de Blobs do Azure. Após o processamento, os resultados são salvos como um repositório de conhecimento no Armazenamento de Tabela do Azure.

Gorjeta

Este artigo usa REST para explicações detalhadas de cada etapa. Baixe o arquivo REST se quiser apenas executar os comandos. Como alternativa, você também pode criar um repositório de conhecimento no portal do Azure.

Pré-requisitos

O conjunto de habilidades neste exemplo usa os Serviços de IA do Azure para enriquecimentos. Como a carga de trabalho é muito pequena, os serviços de IA do Azure são aproveitados nos bastidores para fornecer processamento gratuito para até 20 transações diárias. Uma pequena carga de trabalho significa que você pode ignorar a criação ou anexação de um recurso multisserviço da IA do Azure.

Carregar dados para o Armazenamento do Azure e obter uma cadeia de conexão

  1. Faça o download HotelReviews_Free.csv. Este CSV contém 19 comentários dos clientes sobre um único hotel (originário de Kaggle.com).

  2. No portal do Azure, localize sua conta de armazenamento e use o Navegador de Armazenamento para criar um contêiner de blob chamado hotel-reviews.

  3. Selecione Carregar na parte superior da página para carregar o arquivo HotelReviews-Free.csv que você baixou da etapa anterior.

    Screenshot of Storage Browser with uploaded file and left nav pane

  4. À esquerda, selecione Chaves de Acesso, selecione Mostrar Chaves e copie a cadeia de conexão para key1 ou key2. Uma cadeia de conexão de acesso total tem o seguinte formato:

"knowledgeStore": {
    "storageConnectionString": "DefaultEndpointsProtocol=https;AccountName=<YOUR-ACCOUNT-NAME>;AccountKey=<YOUR-ACCOUNT-KEY>;EndpointSuffix=core.windows.net;"
}

Nota

Consulte Conectar usando uma identidade gerenciada se não quiser fornecer dados confidenciais na cadeia de conexão.

Copiar uma chave e um URL

Neste exemplo, as chamadas REST exigem o ponto de extremidade do serviço de pesquisa e usam uma chave de API em cada solicitação. Você pode obter esses valores no portal do Azure.

  1. Entre no portal do Azure, navegue até a página Visão geral e copie a URL. Um ponto final de exemplo poderá ser parecido com https://mydemo.search.windows.net.

  2. Em Teclas de Configurações>, copie uma chave de administrador. As chaves de administrador são usadas para adicionar, modificar e excluir objetos. Existem duas chaves de administração intercambiáveis. Copie qualquer uma delas.

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

Uma chave de API válida estabelece confiança, por solicitação, entre o aplicativo que envia a solicitação e o serviço de pesquisa que a manipula.

Criar um índice

Criar índice (REST) cria um índice de pesquisa no serviço de pesquisa. Um índice de pesquisa não está relacionado a um repositório de conhecimento, mas o indexador requer um. O índice de pesquisa contém o mesmo conteúdo que o armazenamento de conhecimento, que você pode explorar enviando solicitações de consulta.

  1. Abra um novo arquivo de texto no Visual Studio Code.

  2. Defina variáveis para o ponto de extremidade de pesquisa e a chave de API coletada anteriormente.

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-URL-HERE
    @apiKey = PUT-YOUR-ADMIN-API-KEY-HERE
    @storageConnection = PUT-YOUR-STORAGE-CONNECTION-STRING-HERE
    @blobContainer = PUT-YOUR-CONTAINER-NAME-HERE (hotel-reviews)
    
  3. Salve o arquivo com uma .rest extensão de arquivo.

  4. Cole no exemplo a seguir para criar a solicitação de índice.

    ### Create a new index
    POST {{baseUrl}}/indexes?api-version=2023-11-01  HTTP/1.1
        Content-Type: application/json
        api-key: {{apiKey}}
    
        {
            "name": "hotel-reviews-kstore-idx",  
            "fields": [
                { "name": "name", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false },
                { "name": "reviews_date", "type": "Edm.DateTimeOffset", "searchable": false, "filterable": false, "sortable": false, "facetable": false },
                { "name": "reviews_rating", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false },
                { "name": "reviews_text", "type": "Edm.String", "filterable": false,  "sortable": false, "facetable": false },
                { "name": "reviews_title", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false },
                { "name": "reviews_username", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false },
                { "name": "AzureSearch_DocumentKey", "type": "Edm.String", "searchable": false, "filterable": false, "sortable": false, "facetable": false, "key": true },
                { "name": "language", "type": "Edm.String", "filterable": true, "sortable": false, "facetable": true },
                { "name": "translated_text", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false },
                { "name": "sentiment", "type": "Collection(Edm.String)", "searchable": false, "filterable": true, "retrievable": true, "sortable": false, "facetable": true },
                { "name": "keyphrases", "type": "Collection(Edm.String)", "filterable": true, "sortable": false, "facetable": true }
            ]
        }
    
  5. Selecione Enviar pedido. Você deve ter uma HTTP/1.1 201 Created resposta e o corpo da resposta deve incluir a representação JSON do esquema de índice.

Criar uma origem de dados

Criar Fonte de Dados cria uma conexão de fonte de dados no Azure AI Search.

  1. Cole no exemplo a seguir para criar a fonte de dados.

    ### Create a data source
    POST {{baseUrl}}/datasources?api-version=2023-11-01  HTTP/1.1
      Content-Type: application/json
      api-key: {{apiKey}}
    
        {
            "name": "hotel-reviews-kstore-ds",
            "description": null,
            "type": "azureblob",
            "subtype": null,
            "credentials": {
                "connectionString": "{{storageConnectionString}}"
            },
            "container": {
                "name": "{{blobContainer}}",
                "query": null
            },
            "dataChangeDetectionPolicy": null,
            "dataDeletionDetectionPolicy": null
        }
    
  2. Selecione Enviar pedido.

Criar um conjunto de competências

Um conjunto de habilidades define enriquecimentos (habilidades) e seu armazenamento de conhecimento. Create Skillset cria o objeto no seu serviço de pesquisa.

  1. Cole no exemplo a seguir para criar o conjunto de habilidades.

    ### Create a skillset
    POST {{baseUrl}}/skillsets?api-version=2023-11-01  HTTP/1.1
        Content-Type: application/json
        api-key: {{apiKey}}
    
        {
            "name": "hotel-reviews-kstore-ss",
            "description": "Skillset to detect language, translate text, extract key phrases, and score sentiment",
            "skills": [ 
                {
                    "@odata.type": "#Microsoft.Skills.Text.SplitSkill", 
                    "context": "/document/reviews_text", "textSplitMode": "pages", "maximumPageLength": 5000,
                    "inputs": [ 
                        { "name": "text", "source": "/document/reviews_text" }
                    ],
                    "outputs": [
                        { "name": "textItems", "targetName": "pages" }
                    ]
                },
                {
                    "@odata.type": "#Microsoft.Skills.Text.V3.SentimentSkill",
                    "context": "/document/reviews_text/pages/*",
                    "inputs": [
                        { "name": "text", "source": "/document/reviews_text/pages/*" },
                        { "name": "languageCode", "source": "/document/language" }
                    ],
                    "outputs": [
                        { "name": "sentiment", "targetName": "sentiment" }
                    ]
                },
                {
                    "@odata.type": "#Microsoft.Skills.Text.LanguageDetectionSkill",
                    "context": "/document",
                    "inputs": [
                        { "name": "text", "source": "/document/reviews_text" }
                    ],
                    "outputs": [
                        { "name": "languageCode", "targetName": "language" }
                    ]
                },
                {
                    "@odata.type": "#Microsoft.Skills.Text.TranslationSkill",
                    "context": "/document/reviews_text/pages/*",
                    "defaultFromLanguageCode": null,
                    "defaultToLanguageCode": "en",
                    "inputs": [
                        { "name": "text", "source": "/document/reviews_text/pages/*" }
                    ],
                    "outputs": [
                        { "name": "translatedText", "targetName": "translated_text" }
                    ]
                },
                {
                    "@odata.type": "#Microsoft.Skills.Text.KeyPhraseExtractionSkill",
                    "context": "/document/reviews_text/pages/*",
                    "inputs": [
                        { "name": "text",  "source": "/document/reviews_text/pages/*" },
                        { "name": "languageCode",  "source": "/document/language" }
                    ],
                    "outputs": [
                        { "name": "keyPhrases" , "targetName": "keyphrases" }
                    ]
                },
                {
                    "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
                    "context": "/document",
                    "inputs": [
                        { "name": "name",  "source": "/document/name" },
                        { "name": "reviews_date",  "source": "/document/reviews_date" },
                        { "name": "reviews_rating",  "source": "/document/reviews_rating" },
                        { "name": "reviews_text",  "source": "/document/reviews_text" },
                        { "name": "reviews_title",  "source": "/document/reviews_title" },
                        { "name": "reviews_username",  "source": "/document/reviews_username" },
                        { "name": "AzureSearch_DocumentKey",  "source": "/document/AzureSearch_DocumentKey" },
                        {
                        "name": "pages",
                        "sourceContext": "/document/reviews_text/pages/*",
                        "inputs": [
                            {
                            "name": "languageCode",
                            "source": "/document/language"
                            },
                            {
                            "name": "translatedText",
                            "source": "/document/reviews_text/pages/*/translated_text"
                            },
                            { 
                            "name": "sentiment",
                            "source": "/document/reviews_text/pages/*/sentiment"
                            },
                            {
                            "name": "keyPhrases",
                            "source": "/document/reviews_text/pages/*/keyphrases/*"
                            },
                            {
                            "name": "Page",
                            "source": "/document/reviews_text/pages/*"
                            }
                        ]
                        }
                    ],
                    "outputs": [
                        { "name": "output" , "targetName": "tableprojection" }
                    ]
                }
            ],
            "knowledgeStore": {
                "storageConnectionString": "{{storageConnectionString}}",
                "projections": [
                    {
                        "tables": [
                            { "tableName": "hotelReviews1Document", "generatedKeyName": "Documentid", "source": "/document/tableprojection" },
                            { "tableName": "hotelReviews2Pages", "generatedKeyName": "Pagesid", "source": "/document/tableprojection/pages/*" },
                            { "tableName": "hotelReviews3KeyPhrases", "generatedKeyName": "KeyPhrasesid", "source": "/document/tableprojection/pages/*/keyPhrases/*" }
                        ],
                        "objects": []
                    },
                    {
                        "tables": [
                            { 
                                "tableName": "hotelReviews4InlineProjectionDocument", "generatedKeyName": "Documentid", "sourceContext": "/document",
                                "inputs": [
                                    { "name": "name", "source": "/document/name"},
                                    { "name": "reviews_date", "source": "/document/reviews_date"},
                                    { "name": "reviews_rating", "source": "/document/reviews_rating"},
                                    { "name": "reviews_username", "source": "/document/reviews_username"},
                                    { "name": "reviews_title", "source": "/document/reviews_title"},
                                    { "name": "reviews_text", "source": "/document/reviews_text"},
                                    { "name": "AzureSearch_DocumentKey", "source": "/document/AzureSearch_DocumentKey" }
                                ]
                            },
                            { 
                                "tableName": "hotelReviews5InlineProjectionPages", "generatedKeyName": "Pagesid", "sourceContext": "/document/reviews_text/pages/*",
                                "inputs": [
                                    { "name": "Sentiment", "source": "/document/reviews_text/pages/*/sentiment"},
                                    { "name": "LanguageCode", "source": "/document/language"},
                                    { "name": "Keyphrases", "source": "/document/reviews_text/pages/*/keyphrases"},
                                    { "name": "TranslatedText", "source": "/document/reviews_text/pages/*/translated_text"},
                                    { "name": "Page", "source": "/document/reviews_text/pages/*" }
                                ]
                            },
                            { 
                                "tableName": "hotelReviews6InlineProjectionKeyPhrases", "generatedKeyName": "kpidv2", "sourceContext": "/document/reviews_text/pages/*/keyphrases/*",
                                "inputs": [
                                    { "name": "Keyphrases", "source": "/document/reviews_text/pages/*/keyphrases/*" }
                                ]
                            }
                        ],
                        "objects": []
                    }
                ]
            }
        }
    

Pontos principais:

  • A habilidade Shaper é importante para a definição da loja de conhecimento. Ele especifica como os dados fluem para as tabelas do armazenamento de conhecimento. As entradas são as partes do documento enriquecido que você deseja armazenar. A saída é uma consolidação dos nós em uma única estrutura.

  • As projeções especificam as tabelas, objetos e blobs do seu repositório de conhecimento. Cada item de projeção especifica a coluna ou campo "name" a ser criado no Armazenamento do Azure. O "source" especifica qual parte da saída do shaper é atribuída a esse campo ou coluna.

Criar um indexador

Create Indexer cria e executa o indexador. A execução do indexador começa quebrando os documentos, extraindo texto e imagens e inicializando o conjunto de habilidades. O indexador verifica os outros objetos que você criou: a fonte de dados, o índice e o conjunto de habilidades.

  1. Cole no exemplo a seguir para criar o indexador.

    ### Create indexer
    POST {{baseUrl}}/indexers?api-version=2023-11-01  HTTP/1.1
        Content-Type: application/json
        api-key: {{apiKey}}
    
        {
            "name": "hotel-reviews-kstore-idxr",
            "dataSourceName": "hotel-reviews-kstore-ds",
            "skillsetName": "hotel-reviews-kstore-ss",
            "targetIndexName": "hotel-reviews-kstore-idx",
            "parameters": {
                "configuration": {
                    "dataToExtract": "contentAndMetadata",
                    "parsingMode": "delimitedText",
                    "firstLineContainsHeaders": true,
                    "delimitedTextDelimiter": ","
        }
    },
    "fieldMappings": [
        {
            "sourceFieldName": "AzureSearch_DocumentKey",
            "targetFieldName": "AzureSearch_DocumentKey",
            "mappingFunction": { "name": "base64Encode" }
        }
    ],
    "outputFieldMappings": [
        { "sourceFieldName": "/document/reviews_text/pages/*/Keyphrases/*", "targetFieldName": "Keyphrases" },
        { "sourceFieldName": "/document/Language", "targetFieldName": "Language" },
        { "sourceFieldName": "/document/reviews_text/pages/*/Sentiment", "targetFieldName": "Sentiment" }
        ]
    }
    
  2. Selecione Enviar solicitação para criar e executar o indexador. Esta etapa leva vários minutos para ser concluída.

Pontos principais:

  • O parameters/configuration objeto controla como o indexador ingere os dados. Nesse caso, os dados de entrada estão em um único arquivo CSV que tem uma linha de cabeçalho e valores separados por vírgula.

  • Mapeamentos de campo criam "AzureSearch_DocumentKey" é um identificador exclusivo para cada documento gerado pelo indexador de blob (com base no caminho de armazenamento de metadados).

  • Os mapeamentos de campos de saída especificam como os campos enriquecidos são mapeados para campos em um índice de pesquisa. Os mapeamentos de campo de saída não são usados em armazenamentos de conhecimento (os armazenamentos de conhecimento usam formas e projeções para expressar as estruturas de dados físicas).

Verificar estado

Depois de enviar cada solicitação, o serviço de pesquisa deve responder com uma mensagem de sucesso 201.

### Get Indexer Status (wait several minutes for the indexer to complete)
GET {{baseUrl}}/indexers/hotel-reviews-kstore-idxr/status?api-version=2023-11-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}

Após alguns minutos, você pode consultar o índice para inspecionar o conteúdo. Mesmo que você não esteja usando o índice, esta etapa é uma maneira conveniente de confirmar que o conjunto de habilidades produziu o resultado esperado.

### Query the index (indexer status must be "success" before querying the index)
POST {{baseUrl}}/indexes/hotel-reviews-kstore-idxr/docs/search?api-version=2023-11-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}
  
  {
    "search": "*",
    "select": "reviews_title, reviews_username, language, translated_text, sentiment",
    "count": true
  }

Verificar tabelas no portal do Azure

No portal do Azure, mude para a sua conta de Armazenamento do Azure e utilize o Browser de Armazenamento para ver as novas tabelas. Você deve ver seis tabelas, uma para cada projeção definida no conjunto de habilidades.

Cada tabela é gerada com os IDs necessários para cruzar as tabelas em consultas. Ao abrir uma tabela, passe por esses campos para exibir os campos de conteúdo adicionados pelo pipeline.

Screenshot of the knowledge store tables in Storage Browser

Neste passo a passo, o repositório de conhecimento é composto por várias tabelas que mostram diferentes maneiras de moldar e estruturar uma tabela. As tabelas de um a três usam a saída de uma habilidade Shaper para determinar as colunas e linhas. As tabelas quatro a seis são criadas a partir de instruções de modelagem em linha, incorporadas dentro da própria projeção. Você pode usar qualquer uma das abordagens para obter o mesmo resultado.

Table Description
hotelReviews1Document Contém campos transportados do CSV, como reviews_date e reviews_text.
hotelReviews2Pages Contém campos enriquecidos criados pelo conjunto de habilidades, como pontuação de sentimento e texto traduzido.
hotelReviews3KeyPhrases Contém uma longa lista apenas das frases-chave.
hotelReviews4InlineProjectionDocument Alternativa à primeira tabela, usando a modelagem embutida em vez da habilidade Shaper para moldar dados para a projeção.
hotelReviews5InlineProjectionPages Alternativa à segunda tabela, usando modelagem em linha.
hotelreviews6InlineProjectionKeyPhrases Alternativa à terceira tabela, usando modelagem em linha.

Limpeza

Ao trabalhar na sua própria subscrição, recomendamos que verifique, depois de concluir um projeto, se ainda vai precisar dos recursos que criou. Os recursos que deixar em execução podem custar dinheiro. Pode eliminar recursos individualmente ou eliminar o grupo de recursos para eliminar todo o conjunto de recursos.

Você pode encontrar e gerenciar recursos no portal, usando o link Todos os recursos ou Grupos de recursos no painel de navegação esquerdo.

Próximos passos

Agora que você enriqueceu seus dados usando os serviços de IA do Azure e projetou os resultados em um repositório de conhecimento, você pode usar o Gerenciador de Armazenamento ou outros aplicativos para explorar seu conjunto de dados enriquecido.