Criar um repositório de conhecimento usando REST

Na IA do Azure Search, um repositório de conhecimento é um repositório de conteúdo gerado pela IA usado para cenários que não são de pesquisa. Crie o repositório de conhecimento usando um indexador e um conjunto de habilidades e especifique o Armazenamento do Microsoft Azure para armazenar a saída. Depois que o repositório de conhecimento é populado, utilize ferramentas como o Gerenciador de Armazenamento ou o Power BI para explorar o conteúdo.

Neste artigo, você usará a API REST para ingerir, enriquecer e explorar um conjunto de resenhas de clientes sobre estadias de hotel em um repositório de conhecimento. O repositório de conhecimento contém o conteúdo de texto original obtido da origem, além do conteúdo gerado por IA que inclui uma pontuação de sentimento, extração de frases-chave, detecçã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, primeiro, as avaliações de hotéis são importadas 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 Tabelas do Azure.

Dica

Esse artigo usa REST para obter explicações detalhadas de cada etapa. Baixe o arquivo REST se você 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 nestes exemplos 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 acionados nos bastidores para fornecer processamento gratuito para até 20 transações diárias. Uma carga de trabalho pequena significa que você pode ignorar a criação ou a anexação de um recurso de vários serviços de IA do Azure.

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

  1. Baixe HotelReviews_Free.csv. O CSV contém 19 peças de comentários de cliente sobre um único hotel (originários 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 na 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 completo tem o seguinte formato:

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

Observação

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

Copiar uma chave e URL

Nesse exemplo, as chamadas REST exigem o ponto de extremidade do serviço de pesquisa e 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 de extremidade de exemplo pode parecer com https://mydemo.search.windows.net.

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

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

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

Crie um índice

Criar índice (REST) cria um índice de pesquisa no serviço de pesquisa. O í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 do repositório 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 extensão de arquivo .rest.

  4. Cole o 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 solicitação. Você deve ter uma resposta HTTP/1.1 201 Created e o corpo da resposta deve incluir a representação JSON do esquema de índice.

Criar uma fonte de dados

Criar fonte de dados cria uma conexão de fonte de dados na Pesquisa de IA do Azure.

  1. Cole o 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 solicitação.

Criar um conjunto de habilidades

Um conjunto de habilidades define enriquecimentos (habilidades) e seu repositório de conhecimento. Criar Conjunto de Habilidades cria o objeto em seu serviço de pesquisa.

  1. Cole o 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 do Shaper é importante para a definição do repositório de conhecimento. Ela especifica como os dados fluem para as tabelas do repositório 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, os objetos e os blobs do repositório de conhecimento. Cada item de projeção especifica o "name" da coluna ou campo a ser criado no Armazenamento do Azure. "source" Especifica qual parte da saída do shaper é atribuída a esse campo ou coluna.

Criar um indexador

Criar Indexador cria e executa o indexador. A execução do indexador começa desbloqueando 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 o 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 objeto parameters/configuration controla como o indexador ingere os dados. Nesse caso, os dados de entrada estão em um só arquivo CSV contendo uma linha de cabeçalho e valores separados por vírgula.

  • Os 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 campo de saída especificam como os campos enriquecidos são mapeados para os campos em um índice de pesquisa. Mapeamentos de campo de saída não são usados em repositórios de conhecimento (eles usam formas e projeções para expressar as estruturas de dados físicas).

Verificar o status

Após você enviar cada solicitação, o serviço de pesquisa deve responder com uma mensagem de êxito 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 vários minutos, você pode consultar o índice para inspecionar o conteúdo. Mesmo que você não esteja usando o índice, essa etapa é uma maneira conveniente de confirmar que o conjunto de habilidades produziu a saída esperada.

### 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, acesse sua conta do Armazenamento do Microsoft Azure e use o Navegador de Armazenamento para exibir as novas tabelas. Você deve ver seis tabelas, uma para cada projeção definida no conjunto de habilidades.

Cada tabela é gerada com as IDs necessárias para a vinculação cruzada das tabelas em consultas. Ao abrir uma tabela, role para além desses 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 formatar e estruturar uma tabela. As tabelas de um a três usam a saída de uma habilidade de formatação para determinar as colunas e as linhas. As tabelas de quatro a seis são criadas com base nas instruções de formatação embutidas, inseridas na própria projeção. Você pode usar qualquer uma das abordagens para chegar ao mesmo resultado.

Tabela Descrição
hotelReviews1Document Contém campos obtidos 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 contendo apenas as frases-chave.
hotelReviews4InlineProjectionDocument Alternativa à primeira tabela, usando a forma embutida em vez da habilidade de Shaper para formatar dados para a projeção.
hotelReviews5InlineProjectionPages Alternativa à segunda tabela, usando a forma embutida.
hotelreviews6InlineProjectionKeyPhrases Alternativa à terceira tabela, usando a forma embutida.

Limpar

Quando você está trabalhando em sua própria assinatura, é uma boa ideia identificar, no final de um projeto, se você ainda precisa dos recursos criados. Recursos deixados em execução podem custar dinheiro. Você pode excluir os recursos individualmente ou excluir o grupo de recursos para excluir todo o conjunto de recursos.

Você pode localizar e gerenciar recursos no portal usando o link Todos os recursos ou Grupos de recursos no painel de navegação à esquerda.

Próximas etapas

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