Condividi tramite


Esempio: Creare una competenza personalizzata usando Python (archiviato)

Questo esempio è archiviato e non supportato. È stato illustrato come creare una competenza personalizzata dell'API Web usando Python e Visual Studio Code. Nell'esempio è stata usata una funzione di Azure che implementa l'interfaccia della competenza personalizzata.

Prerequisiti

Creare una funzione di Azure

Questo esempio usa una funzione di Azure per illustrare il concetto di hosting di un'API Web, ma sono possibili altri approcci. Se si soddisfano i requisiti di interfaccia per una competenza cognitiva, l'approccio adottato è irrilevante. Funzioni di Azure, tuttavia, semplificano la creazione di una competenza personalizzata.

Creare un progetto per la funzione

Il modello di progetto Funzioni di Azure in Visual Studio Code crea un progetto locale che può essere pubblicato in un'app per le funzioni in Azure. Un'app per le funzioni consente di raggruppare le funzioni come unità logica per la gestione, la distribuzione e la condivisione delle risorse.

  1. In Visual Studio Code premere F1 per aprire il riquadro comandi. Nel riquadro comandi cercare e selezionare Azure Functions: Create new project....
  2. Scegli un percorso di directory per l'area di lavoro del progetto e clicca su Seleziona. Non usare una cartella di progetto che fa già parte di un'altra area di lavoro.
  3. Selezionare un linguaggio per il progetto dell'app per le funzioni. Per questa esercitazione selezionare Python.
  4. Selezionare la versione di Python (la versione 3.7.5 è supportata da Funzioni di Azure).
  5. Selezionare un modello per la prima funzione del progetto. Selezionare trigger HTTP per creare una funzione attivata tramite HTTP nella nuova app per le funzioni.
  6. Specificare un nome di funzione. In questo caso, si utilizzerà Concatenator
  7. Selezionare Funzione come livello di autorizzazione. Si userà una chiave di accesso alla funzione per chiamare l'endpoint HTTP della funzione.
  8. Specificare come aprire il progetto. Per questo passaggio, selezionare Aggiungi all'area di lavoro per creare l'app per le funzioni nell'area di lavoro corrente.

Visual Studio Code crea il progetto dell'app per le funzioni in una nuova area di lavoro. Questo progetto contiene i file di configurazione host.json e local.settings.json, oltre a qualsiasi file di progetto specifico del linguaggio.

Viene creata anche una nuova funzione attivata tramite HTTP nella cartella Concatenator del progetto dell'app per le funzioni. Al suo interno sarà presente un file denominato "__init__.py", con questo contenuto:

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
        )

Ora modifichiamo quel codice per seguire l'interfaccia della competenza personalizzata. Sostituire il codice predefinito con il contenuto seguente:

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

Il metodo transform_value esegue un'operazione su un singolo record. È possibile modificare il metodo in base alle esigenze specifiche. Ricordarsi di eseguire qualsiasi convalida di input necessaria e di restituire eventuali errori e avvisi se l'operazione non può essere completata.

Eseguire il debug del codice in locale

Visual Studio Code semplifica il debug del codice. Premere "F5" o passare al menu debug e selezionare Avvia debug.

È possibile impostare qualsiasi punto di interruzione nel codice premendo "F9" sulla riga di interesse.

Dopo aver avviato il debug, la funzione verrà eseguita in locale. È possibile usare uno strumento come Postman o Fiddler per inviare la richiesta a localhost. Prendere nota della posizione del tuo endpoint locale nella finestra Terminale.

Creare un'app per le funzioni in Azure

Quando si è soddisfatti del comportamento della funzione, è possibile pubblicarlo. Finora hai lavorato localmente. In questa sezione si creerà un'app per le funzioni in Azure e quindi si distribuirà il progetto locale nell'app creata.

Creare l'app da Visual Studio Code

  1. In Visual Studio Code premere F1 per aprire il riquadro comandi. Nel riquadro comandi, cercare e selezionare Crea Funzione App in Azure.

  2. Se sono presenti più sottoscrizioni attive, selezionare la sottoscrizione per questa app.

  3. Immettere un nome univoco globale per l'app di funzioni. Digitare un nome valido per un URL.

  4. Seleziona uno stack di runtime e scegli la versione del linguaggio che hai utilizzato localmente.

  5. Selezionare una località per l'app. Se possibile, scegliere la stessa area che ospita anche il servizio di ricerca.

La creazione dell'app richiede alcuni minuti. Quando è pronta, vedrai la nuova app sotto Risorse e Funzioni App della sottoscrizione attiva.

Distribuire su Azure

  1. Sempre in Visual Studio Code premere F1 per aprire il riquadro comandi. Nella palette comandi, cercare e selezionare Distribuisci su Function App....

  2. Seleziona l'applicazione di funzione che hai creato.

  3. Conferma di voler continuare e quindi seleziona Distribuisci. È possibile monitorare lo stato della distribuzione nella finestra di output.

  4. Passare al portale di Azure , quindi selezionare Tutte le risorse. Cerca la funzione app distribuita utilizzando il nome univoco globale fornito in uno dei passaggi precedenti.

    Suggerimento

    È anche possibile fare clic con il pulsante destro del mouse sull'app per le funzioni in Visual Studio Code e selezionare Apri nel portale.

  5. Nel portale, a sinistra, selezionare Funzionie quindi selezionare la funzione creata.

  6. Nella pagina di panoramica della funzione, selezionare Recupera URL funzione nella barra dei comandi in alto. In questo modo sarà possibile copiare l'URL per chiamare la funzione.

    Screenshot del comando Recupera URL Funzione nel portale di Azure.

Testare la funzione in Azure

Usando la chiave host e l'URL predefiniti copiati, testare la funzione dal portale di Azure.

  1. A sinistra, sotto Sviluppatore, seleziona Codice + Test.

  2. Selezionare Test/Esegui nella barra dei comandi.

  3. Per l'input, usare Post, la chiave predefinita e quindi incollare il corpo della richiesta:

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

    Screenshot delle specifiche di input

Questo esempio dovrebbe produrre lo stesso risultato visualizzato in precedenza durante l'esecuzione della funzione nell'ambiente locale.

Aggiungere a un set di competenze

Ora che hai una nuova competenza personalizzata, puoi aggiungerla al tuo set di competenze. L'esempio seguente illustra come chiamare la funzione per concatenare il titolo e l'autore del documento in un singolo campo, denominato merged_title_author.

Sostituire [your-function-url-here] con l'URL della nuova funzione di 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"
            }
          ]
      }
  ]
}

Ricordarsi di aggiungere un "outputFieldMapping" nella definizione dell'indicizzatore per inviare "merged_title_author" a un campo "fullname" nell'indice di ricerca.

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