Compartir a través de


Ejemplo: Creación de una aptitud personalizada mediante Python (archivado)

Este ejemplo está archivado y fuera de soporte técnico. Se explica cómo crear una aptitud personalizada de API web mediante Python y Visual Studio Code. En el ejemplo se usa una función de Azure que implementa la interfaz de aptitud personalizada.

Requisitos previos

Creación de una Función de Azure

En este ejemplo se usa una función de Azure para mostrar el concepto de hospedaje de una API web, pero hay otros enfoques posibles. Siempre que cumpla con los requisitos de interfaz de una aptitud cognitiva, no importa el enfoque que quiera usar. Sin embargo, Azure Functions facilita la creación de una aptitud personalizada.

Creación de un proyecto para la función

La plantilla del proyecto de Azure Functions de Visual Studio Code crea un proyecto local que se puede publicar en una aplicación de función en Azure. Una aplicación de función permite agrupar funciones como una unidad lógica para la administración, la implementación y el uso compartido de recursos.

  1. En Visual Studio Code, presione F1 para abrir la paleta de comandos. En la paleta de comandos, busque y seleccione Azure Functions: Create new project....
  2. Elija una ubicación de directorio para el área de trabajo del proyecto y elija Seleccionar. No use una carpeta de proyecto que ya forme parte de otra área de trabajo.
  3. Seleccione un lenguaje para el proyecto de la aplicación de funciones. Para este tutorial, seleccione Python.
  4. Seleccione la versión 3.7.5 de Python ya que es la que admite Azure Functions.
  5. Seleccione una plantilla para la primera función de su proyecto. Seleccione Desencadenador HTTP para crear una función desencadenada por HTTP en la nueva aplicación de funciones.
  6. Proporcione un nombre de función. En este caso, vamos a usar Concatenator
  7. Seleccione Función como nivel de autorización. Usará una clave de acceso a la función para llamar al punto de conexión HTTP de la función.
  8. Especifique cómo quiere que se abra el proyecto. En este paso, seleccione Add to workspace (Agregar al área de trabajo) para crear la aplicación de funciones en el área de trabajo actual.

Visual Studio Code crea el proyecto de la aplicación de función en una nueva área de trabajo. Este proyecto contiene los archivos host.json y local.settings.jsonconfiguration, además de los archivos de proyecto específicos del idioma.

También se crea una nueva función desencadenada por HTTP en la carpeta Concatenator del proyecto de la aplicación de funciones. Dentro de ella habrá un archivo denominado "__init__.py" con este contenido:

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
        )

Ahora vamos a modificar ese código para seguir la interfaz de aptitud personalizada. Reemplace el código predeterminado con el contenido siguiente:

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
                    }
            })

El método transform_value realiza una operación en un único registro. Puede modificar el método para que satisfaga sus necesidades específicas. No olvide realizar todas las validaciones de entradas necesarias y devolver los errores y advertencias si la operación no se puede completar.

Depuración local del código

Visual Studio Code facilita la depuración del código. Presione F5 o vaya al menú Depurar y seleccione Iniciar depuración.

Puede establecer todos los puntos de interrupción que desee en el código presionando "F9" en la línea de su interés.

Una vez iniciada la depuración, la función se ejecutará localmente. Puede usar una herramienta como Postman o Fiddler para emitir la solicitud a localhost. Anote la ubicación del punto de conexión local en la ventana de terminal.

Creación de una aplicación de función en Azure

Cuando esté satisfecho con el comportamiento de la función, puede publicarla. Hasta ahora ha estado trabajando localmente. En esta sección, creará una aplicación de funciones en Azure y, a continuación, implementará el proyecto local en la aplicación que ha creado.

Creación de la aplicación desde Visual Studio Code

  1. En Visual Studio Code, presione F1 para abrir la paleta de comandos. En la paleta de comandos, busque y seleccione Crear aplicación de funciones en Azure.

  2. Si tiene varias suscripciones activas, seleccione la suscripción para esta aplicación.

  3. Escriba un nombre único global para la aplicación de funciones. Escriba un nombre que sea válido en una dirección URL.

  4. Seleccione una pila de runtime y elija la versión de lenguaje en la que se ha estado ejecutando localmente.

  5. Seleccione una ubicación para la aplicación. Si es posible, elija la misma región que también hospeda el servicio de búsqueda.

La operación de creación de la aplicación tarda unos minutos. Cuando esté lista, verá la nueva aplicación en Recursos y Aplicación de funciones de la suscripción activa.

Implementar en Azure

  1. Todavía en Visual Studio Code, presione F1 para abrir la paleta de comandos. En la paleta de comandos, busque y seleccione Deploy to Function App... (Implementar en la aplicación de funciones...).

  2. Seleccione la aplicación de funciones que ha creado anteriormente.

  3. Confirme que quiere continuar y, después, seleccione Implementar. Puede supervisar el estado de la implementación en la ventana de salida.

  4. Cambia a Azure Portal y vaya a Todos los recursos. Busque la aplicación de funciones que ha implementado con el nombre único global que ha proporcionado en un paso anterior.

    Sugerencia

    También puede hacer clic con el botón derecho en la aplicación de funciones en Visual Studio Code y seleccionar Abrir en el portal.

  5. En el portal, a la izquierda, seleccione Funciones y, a continuación, seleccione la función que ha creado.

  6. En la página de información general de la función, seleccione Obtener dirección URL de la función en la barra de comandos de la parte superior. Esto le permitirá copiar la dirección URL para llamar a la función.

    Captura de pantalla del comando Obtener dirección URL de la función en Azure Portal.

Pruebe la función en Azure

Con la clave de host predeterminado y la dirección URL que ha copiado, pruebe la función desde Azure Portal.

  1. A la izquierda, en Desarrollador, seleccione Código y prueba.

  2. Seleccione Probar/Ejecutar en la barra de comandos.

  3. Para la entrada, use Post y la clave predeterminada y, a continuación, pegue el cuerpo de la solicitud:

    {
        "values": [
            {
                "recordId": "e1",
                "data":
                {
                    "text1":  "Hello",
                    "text2":  "World"
                }
            },
            {
                "recordId": "e2",
                "data": "This is an invalid input"
            }
        ]
    }
    
  4. Seleccione Run (Ejecutar).

    Captura de pantalla de la especificación de entrada.

Este ejemplo debería producir el mismo resultado que vio anteriormente al ejecutar la función en el entorno local.

Adición a un conjunto de aptitudes

Ahora que tiene una nueva aptitud personalizada, puede agregarla al conjunto de aptitudes. En el ejemplo siguiente se muestra cómo llamar a la aptitud para concatenar el título y el autor del documento en un único campo al que llamaremos merged_title_author.

Reemplace [your-function-url-here] por la dirección URL de la nueva función de 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"
            }
          ]
      }
  ]
}

Recuerde agregar un objeto "outputFieldMapping" en la definición del indexador para enviar "merged_title_author" a un campo "fullname" del índice de búsqueda.

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