Compartilhar via


Exemplo: criar uma habilidade personalizada usando Python (arquivado)

Este exemplo é arquivado e sem suporte. Ele explicou como criar uma habilidade personalizada de API Web usando Python e Visual Studio Code. O exemplo usou uma Função do Azure que implementa a interface de habilidade personalizada.

Pré-requisitos

Criar uma Função do Azure

Este exemplo usa uma função do Azure para demonstrar o conceito de Hospedagem de uma API da Web, mas outras abordagens são possíveis. Desde que você atenda aos requisitos da interface para uma habilidade cognitiva, a abordagem que você adota é irrelevante. No entanto, o Azure Functions facilita a criação de uma habilidade personalizada.

Criar um projeto para a função

O modelo de projeto do Azure Functions no Visual Studio Code cria um projeto que pode ser publicado em um aplicativo de funções no Azure. Um aplicativo de funções permite a você agrupar funções como uma unidade lógica para o gerenciamento, implantação e compartilhamento de recursos.

  1. No Visual Studio Code, pressione F1 para abrir a paleta de comandos. Na paleta de comandos, pesquise e selecione Azure Functions: Create new project....
  2. Escolha um local de diretório para o workspace do projeto e escolha Selecionar. Não use uma pasta de projeto que já faça parte de outro workspace.
  3. Selecione uma linguagem de programação para o seu projeto de aplicativo de função. Para este tutorial, selecione Python.
  4. Selecione a versão do Python, (a versão 3.7.5 é compatível com o Azure Functions).
  5. Selecione um modelo para a primeira função do projeto. Selecione gatilho HTTP para criar uma função disparada por HTTP no novo aplicativo de funções.
  6. Forneça um nome de função. Nesse caso, vamos usar Concatenador
  7. Selecione Função como o nível de autorização. Você usará uma chave de acesso de função para chamar o ponto de extremidade HTTP da função.
  8. Selecione como deseja abrir o projeto. Para esta etapa, selecione Adicionar ao espaço de trabalho para criar o aplicativo de funções no espaço de trabalho atual.

O Visual Studio Code cria o projeto de aplicativo de função em um novo workspace. Este projeto contém os arquivos host.json e local.settings.jsonconfiguration, além de arquivos de projeto específicos do idioma.

Uma nova função disparada por HTTP também é criada na pasta Concatenador do projeto do aplicativo de função. Dentro, haverá um arquivo chamado "__init__.py", com este conteúdo:

import logging

import azure.functions as func


def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello {name}!")
    else:
        return func.HttpResponse(
             "Please pass a name on the query string or in the request body",
             status_code=400
        )

Agora, vamos modificar esse código para seguir a interface de habilidade personalizada. Substitua o código padrão pelo seguinte código:

import logging
import azure.functions as func
import json

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        body = json.dumps(req.get_json())
    except ValueError:
        return func.HttpResponse(
             "Invalid body",
             status_code=400
        )
    
    if body:
        result = compose_response(body)
        return func.HttpResponse(result, mimetype="application/json")
    else:
        return func.HttpResponse(
             "Invalid body",
             status_code=400
        )


def compose_response(json_data):
    values = json.loads(json_data)['values']
    
    # Prepare the Output before the loop
    results = {}
    results["values"] = []
    
    for value in values:
        output_record = transform_value(value)
        if output_record != None:
            results["values"].append(output_record)
    return json.dumps(results, ensure_ascii=False)

## Perform an operation on a record
def transform_value(value):
    try:
        recordId = value['recordId']
    except AssertionError  as error:
        return None

    # Validate the inputs
    try:         
        assert ('data' in value), "'data' field is required."
        data = value['data']        
        assert ('text1' in data), "'text1' field is required in 'data' object."
        assert ('text2' in data), "'text2' field is required in 'data' object."
    except AssertionError  as error:
        return (
            {
            "recordId": recordId,
            "errors": [ { "message": "Error:" + error.args[0] }   ]       
            })

    try:                
        concatenated_string = value['data']['text1'] + " " + value['data']['text2']  
        # Here you could do something more interesting with the inputs

    except:
        return (
            {
            "recordId": recordId,
            "errors": [ { "message": "Could not complete operation for record." }   ]       
            })

    return ({
            "recordId": recordId,
            "data": {
                "text": concatenated_string
                    }
            })

O método transform_value executa uma operação em um único registro. Você pode modificar o método para atender a necessidades específicas. Lembre-se de fazer a validação de entrada necessária e retornar erros e avisos se a operação não puder ser concluída.

Depurar seu código localmente

O Visual Studio Code facilita a depuração do código. Pressione "F5" ou vá para o menu Depurar e selecione Iniciar Depuração.

Você pode definir pontos de interrupção no código clicando em "F9" na linha de interesse.

Depois de iniciar a depuração, sua função será executado localmente. Você pode usar uma ferramenta como Postman ou Fiddler para emitir a solicitação para localhost. Observe o local do ponto de extremidade local na janela do Terminal.

Criar um aplicativo de funções no Azure

Quando estiver satisfeito com o comportamento da função, você poderá publicá-la. Até agora você trabalhou localmente. Nesta seção, você criará um aplicativo de funções no Azure e implantará o projeto local no aplicativo criado.

Criar o aplicativo usando o Visual Studio Code

  1. No Visual Studio Code, pressione F1 para abrir a paleta de comandos. Na paleta de comandos, procure e selecione Criar aplicativo de funções no Azure.

  2. Se você tiver várias assinaturas, selecione uma para este aplicativo.

  3. Insira um nome exclusivo globalmente para o aplicativo de funções. Digite um nome que seja válido para uma URL.

  4. Escolha a pilha de runtime e a versão da linguagem da execução local atual.

  5. Selecione um local para o aplicativo. Se possível, escolha a mesma região que também hospeda o serviço de pesquisa.

São necessários alguns minutos para criar o aplicativo. Quando o aplicativo estiver pronto, ele será exibido em Recursos e Aplicativo de Funções da assinatura ativa.

Implantar no Azure

  1. Ainda no Visual Studio Code, pressione F1 para abrir a paleta de comandos. Na paleta de comandos, pesquise e selecione Implantar para aplicativo de funções… .

  2. Selecione o aplicativo de funções que você criou.

  3. Confirme se deseja continuar e selecione Implantar. Você pode monitorar o status da implantação na janela de saída.

  4. Mude para o portal do Azure, navegue até Todos os Recursos. Procure o aplicativo de funções implantado usando o nome global exclusivo fornecido em uma etapa anterior.

    Dica

    Você também pode clicar com o botão direito do mouse no aplicativo de funções no Visual Studio Code e selecionar Abrir no Portal.

  5. No portal, à esquerda, selecione Funções e escolha a função que você criou.

  6. Na página de visão geral da função, selecione Obter URL da Função na barra de comandos na parte superior. Isso permitirá que você copie a URL para chamar a função.

    Captura de tela do comando Obter URL da função no portal do Azure.

Testar a função no Azure

Usando a chave de host padrão e a URL que você copiou, teste a função de dentro de portal do Azure.

  1. À esquerda, em Desenvolvedor, selecione Código + Teste.

  2. Selecione Testar/Executar na barra de comandos.

  3. Para entrada, use Postar, a chave padrão e cole no corpo da solicitação:

    {
        "values": [
            {
                "recordId": "e1",
                "data":
                {
                    "text1":  "Hello",
                    "text2":  "World"
                }
            },
            {
                "recordId": "e2",
                "data": "This is an invalid input"
            }
        ]
    }
    
  4. Selecione Executar.

    Captura de tela da especificação de entrada.

Este exemplo deve gerar o mesmo resultado que você viu anteriormente ao executar a função no ambiente local.

Adição a um conjunto de habilidades

Agora que você tem uma nova habilidade personalizada, você pode adicioná-la ao seu conjunto de qualificações. O exemplo abaixo mostra como chamar a habilidade para concatenar o Título e o Autor do documento em um só campo que chamamos de merged_title_author.

Substitua [your-function-url-here] pela URL da nova Função do Azure.

{
    "skills": [
      "[... other existing skills in the skillset are here]",  
      {
        "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
        "description": "Our new search custom skill",
        "uri": "https://[your-function-url-here]",        
          "context": "/document/merged_content/organizations/*",
          "inputs": [
            {
              "name": "text1",
              "source": "/document/metadata_title"
            },
            {
              "name": "text2",
              "source": "/document/metadata_author"
            },
          ],
          "outputs": [
            {
              "name": "text",
              "targetName": "merged_title_author"
            }
          ]
      }
  ]
}

Lembre-se de adicionar um "outputFieldMapping" na definição do indexador para enviar "merged_title_author" a um campo "fullname" no índice de pesquisa.

"outputFieldMappings": [
    {
        "sourceFieldName": "/document/content/merged_title_author",
        "targetFieldName": "fullname"
    }
]