Usare i dialoghi in una competenza

SI APPLICA A: SDK v4

Questo articolo illustra come creare una competenza che supporta più azioni. Queste azioni sono rese possibili tramite dialoghi. Il dialogo principale riceve l'input iniziale dal consumer di competenze e quindi avvia l'azione appropriata. Per informazioni sull'implementazione del consumer di competenze per il codice di esempio associato, vedere come utilizzare una competenza con i dialoghi.

Questo articolo presuppone che tu abbia già familiarità con la creazione di competenze. Per informazioni generali su come creare un bot competenza, vedere come implementare una competenza.

Nota

Gli SDK JavaScript, C# e Python di Bot Framework continueranno a essere supportati, ma Java SDK verrà ritirato con il supporto finale a lungo termine che termina a novembre 2023.

I bot esistenti creati con Java SDK continueranno a funzionare.

Per la creazione di nuovi bot, è consigliabile usare Microsoft Copilot Studio e leggere le informazioni sulla scelta della soluzione copilota appropriata.

Per altre informazioni, vedere Il futuro della compilazione di bot.

Prerequisiti

Nota

Language Understanding (LUIS) verrà ritirato il 1° ottobre 2025. A partire dal 1° aprile 2023, non sarà possibile creare nuove risorse LUIS. Una versione più recente di Language Understanding è ora disponibile come parte del linguaggio di intelligenza artificiale di Azure.

CLU (Conversational Language Understanding), una funzionalità del linguaggio di intelligenza artificiale di Azure, è la versione aggiornata di LUIS. Per altre informazioni sul supporto per la comprensione del linguaggio in Bot Framework SDK, vedere Comprensione del linguaggio naturale.

Informazioni sull'esempio

L'esempio di skillDialog di competenze include i progetti per due bot:

  • Il bot radice del dialogo, che usa una classe SkillDialog per usare una competenza.
  • Il bot competenza del dialogo, che usa un dialogo per gestire le attività dei consumer di competenze. Questa competenza è un adattamento dell'esempio di bot di base. Per altre informazioni, vedere come aggiungere la comprensione del linguaggio naturale al bot.

Questo articolo è incentrato su come usare un dialogo all'interno di un bot di competenze per gestire più azioni.

Per informazioni sul bot per i consumer di competenze, vedere come utilizzare una competenza con i dialoghi.

Risorse

Per i bot distribuiti, l'autenticazione da bot a bot richiede che ogni bot partecipante abbia un'identità valida. Tuttavia, è possibile testare competenze e consumer di competenze in locale con Bot Framework Emulator senza informazioni sull'identità.

Per rendere disponibile la competenza per i bot rivolti agli utenti, registrare la competenza con Azure. Per altre informazioni, vedere come registrare un bot con Azure AI servizio Bot.

Facoltativamente, il bot competenza può usare un modello LUIS di prenotazione di voli. Per usare questo modello, usare il file CognitiveModels/FlightBooking.json per creare, eseguire il training e pubblicare il modello LUIS.

Configurazione dell'applicazione

  1. Facoltativamente, aggiungere le informazioni sull'identità della competenza al file di configurazione della competenza. Se la competenza o il consumer di competenze specifica un'identità, entrambe devono.

  2. Se si usa il modello LUIS, aggiungere l'ID app LUIS, la chiave API e il nome host dell'API.

DialogSkillBot\appsettings.json

{
  "MicrosoftAppType": "",
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",
  "MicrosoftAppTenantId": "",
  "ConnectionName": "",

  "LuisAppId": "",
  "LuisAPIKey": "",
  "LuisAPIHostName": "",

  // This is a comma separate list with the App IDs that will have access to the skill.
  // This setting is used in AllowedCallersClaimsValidator.
  // Examples: 
  //    [ "*" ] allows all callers.
  //    [ "AppId1", "AppId2" ] only allows access to parent bots with "AppId1" and "AppId2".
  "AllowedCallers": [ "*" ]
}

Logica di routing delle attività

La competenza supporta due diverse funzionalità. Può prenotare un volo o recuperare le previsioni meteo di una città. Inoltre, se riceve un messaggio al di fuori di uno di questi contesti, può usare LUIS per provare a interpretarlo. Il manifesto della competenza descrive queste azioni, i relativi parametri di input e di output e gli endpoint della competenza. Si noti che la competenza può gestire un evento "BookFlight" o "GetWeather". Può anche gestire le attività dei messaggi.

La competenza definisce un dialogo di routing delle attività che usa per selezionare l'azione da avviare, in base all'attività iniziale in ingresso proveniente dal consumer di competenze. Se specificato, il modello LUIS è in grado di riconoscere finalità di prenotazione di voli e recupero di previsioni meteo in un messaggio iniziale.

L'azione di prenotazione di voli è un processo in più passaggi, implementato come dialogo separato. Una volta avviata l'azione, le attività in ingresso vengono gestite da tale dialogo. L'azione di recupero di previsioni meteo ha una logica di segnaposto che verrebbe sostituita in un bot completamente implementato.

Il dialogo di routing delle attività include il codice per:

I dialoghi usati nella competenza ereditano dalla classe ComponentDialog. Per altre informazioni sui dialoghi componenti, vedere la procedura per gestire la complessità dei dialoghi.

Inizializzare il dialogo

Il dialogo di routing delle attività include un dialogo figlio per la prenotazione di un volo. Il dialogo a cascata principale prevede un passaggio che avvierà un'azione in base all'attività iniziale ricevuta.

Accetta anche un riconoscitore LUIS. Se il riconoscitore viene inizializzato, il dialogo lo userà per interpretare la finalità di un'attività di messaggi iniziale.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private readonly DialogSkillBotRecognizer _luisRecognizer;

public ActivityRouterDialog(DialogSkillBotRecognizer luisRecognizer)
    : base(nameof(ActivityRouterDialog))
{
    _luisRecognizer = luisRecognizer;

    AddDialog(new BookingDialog());
    AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[] { ProcessActivityAsync }));

    // The initial child Dialog to run.
    InitialDialogId = nameof(WaterfallDialog);
}

Elaborare un'attività iniziale

Nel primo e unico passaggio del dialogo a cascata principale la competenza verifica il tipo di attività in ingresso.

  • Le attività di eventi vengono inoltrate a un gestore OnEventActivity che avvia l'azione appropriata in base al nome dell'evento.
  • Le attività di messaggi vengono inoltrate a un gestore OnMessageActivity che esegue un'ulteriore elaborazione prima di decidere cosa fare.

Se la competenza non riconosce il tipo di attività in ingresso o il nome dell'evento, invia un messaggio di errore e termina.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private async Task<DialogTurnResult> ProcessActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // A skill can send trace activities, if needed.
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.ProcessActivityAsync()", label: $"Got ActivityType: {stepContext.Context.Activity.Type}", cancellationToken: cancellationToken);

    switch (stepContext.Context.Activity.Type)
    {
        case ActivityTypes.Event:
            return await OnEventActivityAsync(stepContext, cancellationToken);

        case ActivityTypes.Message:
            return await OnMessageActivityAsync(stepContext, cancellationToken);

        default:
            // We didn't get an activity type we can handle.
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Unrecognized ActivityType: \"{stepContext.Context.Activity.Type}\".", inputHint: InputHints.IgnoringInput), cancellationToken);
            return new DialogTurnResult(DialogTurnStatus.Complete);
    }
}
// This method performs different tasks based on the event name.
private async Task<DialogTurnResult> OnEventActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.OnEventActivityAsync()", label: $"Name: {activity.Name}. Value: {GetObjectAsJsonString(activity.Value)}", cancellationToken: cancellationToken);

    // Resolve what to execute based on the event name.
    switch (activity.Name)
    {
        case "BookFlight":
            return await BeginBookFlight(stepContext, cancellationToken);

        case "GetWeather":
            return await BeginGetWeather(stepContext, cancellationToken);

        default:
            // We didn't get an event name we can handle.
            await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Unrecognized EventName: \"{activity.Name}\".", inputHint: InputHints.IgnoringInput), cancellationToken);
            return new DialogTurnResult(DialogTurnStatus.Complete);
    }
}

Gestire le attività dei messaggi

Se il riconoscitore LUIS è configurato, la competenza chiama LUIS e quindi avvia un'azione in base alla finalità. Se il sistema di riconoscimento LUIS non è configurato o la finalità non è supportata, la competenza invia un messaggio di errore e termina.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

// This method just gets a message activity and runs it through LUIS. 
private async Task<DialogTurnResult> OnMessageActivityAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    await stepContext.Context.TraceActivityAsync($"{GetType().Name}.OnMessageActivityAsync()", label: $"Text: \"{activity.Text}\". Value: {GetObjectAsJsonString(activity.Value)}", cancellationToken: cancellationToken);

    if (!_luisRecognizer.IsConfigured)
    {
        await stepContext.Context.SendActivityAsync(MessageFactory.Text("NOTE: LUIS is not configured. To enable all capabilities, add 'LuisAppId', 'LuisAPIKey' and 'LuisAPIHostName' to the appsettings.json file.", inputHint: InputHints.IgnoringInput), cancellationToken);
    }
    else
    {
        // Call LUIS with the utterance.
        var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);

        // Create a message showing the LUIS results.
        var sb = new StringBuilder();
        sb.AppendLine($"LUIS results for \"{activity.Text}\":");
        var (intent, intentScore) = luisResult.Intents.FirstOrDefault(x => x.Value.Equals(luisResult.Intents.Values.Max()));
        sb.AppendLine($"Intent: \"{intent}\" Score: {intentScore.Score}");

        await stepContext.Context.SendActivityAsync(MessageFactory.Text(sb.ToString(), inputHint: InputHints.IgnoringInput), cancellationToken);

        // Start a dialog if we recognize the intent.
        switch (luisResult.TopIntent().intent)
        {
            case FlightBooking.Intent.BookFlight:
                return await BeginBookFlight(stepContext, cancellationToken);

            case FlightBooking.Intent.GetWeather:
                return await BeginGetWeather(stepContext, cancellationToken);

            default:
                // Catch all for unhandled intents.
                var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
                var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
                await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
                break;
        }
    }

    return new DialogTurnResult(DialogTurnStatus.Complete);
}

Avviare un'azione in più passaggi

L'azione d prenotazione di voli avvia un dialogo in più passaggi per ottenere i dettagli della prenotazione dall'utente.

L'azione get-weather non è implementata. Attualmente, invia un messaggio segnaposto e quindi termina.

DialogSkillBot\Dialogs\ActivityRouterDialog.cs

private async Task<DialogTurnResult> BeginBookFlight(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    var bookingDetails = new BookingDetails();
    if (activity.Value != null)
    {
        bookingDetails = JsonConvert.DeserializeObject<BookingDetails>(JsonConvert.SerializeObject(activity.Value));
    }

    // Start the booking dialog.
    var bookingDialog = FindDialog(nameof(BookingDialog));
    return await stepContext.BeginDialogAsync(bookingDialog.Id, bookingDetails, cancellationToken);
}
private static async Task<DialogTurnResult> BeginGetWeather(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activity = stepContext.Context.Activity;
    var location = new Location();
    if (activity.Value != null)
    {
        location = JsonConvert.DeserializeObject<Location>(JsonConvert.SerializeObject(activity.Value));
    }

    // We haven't implemented the GetWeatherDialog so we just display a TODO message.
    var getWeatherMessageText = $"TODO: get weather for here (lat: {location.Latitude}, long: {location.Longitude}";
    var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
    await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
    return new DialogTurnResult(DialogTurnStatus.Complete);
}

Restituire un risultato

La competenza avvia un dialogo di prenotazione per l'azione di prenotazione di voli. Poiché il dialogo di routing delle attività prevede un unico passaggio, termina quando termina il dialogo di prenotazione e il risultato del dialogo di prenotazione diventa il risultato del dialogo di routing delle attività.

L'azione di recupero di previsioni meteo termina semplicemente senza impostare un valore restituito.

Annullamento di un'azione in più passaggi

Il dialogo di prenotazione e il relativo dialogo figlio di risoluzione della data derivano dal dialogo di base "cancel" e "help", che controlla i messaggi provenienti dall'utente.

  • Per "help" o "?", visualizza un messaggio della Guida e quindi continua il flusso di conversazione al turno successivo.
  • Per "cancel" o "quit", annulla tutti i dialoghi, terminando la competenza.

Per altre informazioni, vedere come gestire le interruzioni dell'utente.

Registrazione del servizio

I servizi necessari per questa competenza sono gli stessi di quelli necessari per un bot competenza in generale. Per una descrizione dei servizi necessari, vedere come implementare una competenza.

Manifesto della competenza

Un manifesto della competenza è un file JSON che descrive le attività eseguibili con la competenza, i relativi parametri di input e output e gli endpoint della competenza. Il manifesto contiene le informazioni necessarie per accedere alla competenza da un altro bot.

DialogSkillBot\wwwroot\manifest\dialogchildbot-manifest-1.0.json

{
  "$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
  "$id": "DialogSkillBot",
  "name": "Skill bot with dialogs",
  "version": "1.0",
  "description": "This is a sample skill definition for multiple activity types.",
  "publisherName": "Microsoft",
  "privacyUrl": "https://dialogskillbot.contoso.com/privacy.html",
  "copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
  "license": "",
  "iconUrl": "https://dialogskillbot.contoso.com/icon.png",
  "tags": [
    "sample",
    "travel",
    "weather",
    "luis"
  ],
  "endpoints": [
    {
      "name": "default",
      "protocol": "BotFrameworkV3",
      "description": "Default endpoint for the skill.",
      "endpointUrl": "https://dialogskillbot.contoso.com/api/messages",
      "msAppId": "00000000-0000-0000-0000-000000000000"
    }
  ],
  "activities": {
    "bookFlight": {
      "description": "Books a flight (multi turn).",
      "type": "event",
      "name": "BookFlight",
      "value": {
        "$ref": "#/definitions/bookingInfo"
      },
      "resultValue": {
        "$ref": "#/definitions/bookingInfo"
      }
    },
    "getWeather": {
      "description": "Retrieves and returns the weather for the user's location.",
      "type": "event",
      "name": "GetWeather",
      "value": {
        "$ref": "#/definitions/location"
      },
      "resultValue": {
        "$ref": "#/definitions/weatherReport"
      }
    },
    "passthroughMessage": {
      "type": "message",
      "description": "Receives the user's utterance and attempts to resolve it using the skill's LUIS models.",
      "value": {
        "type": "object"
      }
    }
  },
  "definitions": {
    "bookingInfo": {
      "type": "object",
      "required": [
        "origin"
      ],
      "properties": {
        "origin": {
          "type": "string",
          "description": "This is the origin city for the flight."
        },
        "destination": {
          "type": "string",
          "description": "This is the destination city for the flight."
        },
        "travelDate": {
          "type": "string",
          "description": "The date for the flight in YYYY-MM-DD format."
        }
      }
    },
    "weatherReport": {
      "type": "array",
      "description": "Array of forecasts for the next week.",
      "items": [
        {
          "type": "string"
        }
      ]
    },
    "location": {
      "type": "object",
      "description": "Location metadata.",
      "properties": {
        "latitude": {
          "type": "number",
          "title": "Latitude"
        },
        "longitude": {
          "type": "number",
          "title": "Longitude"
        },
        "postalCode": {
          "type": "string",
          "title": "Postal code"
        }
      }
    }
  }
}

Lo schema del manifesto della competenza è un file JSON che descrive lo schema del manifesto della competenza. La versione più recente dello schema è v2.1.

Testare il bot competenza

È possibile testare la competenza nell'emulatore con il consumer di competenze. A questo scopo, è necessario eseguire il bot competenza e il bot del consumer di competenze contemporaneamente. Per informazioni su come configurare la competenza, vedere come usare i dialoghi per una competenza.

Scaricare e installare l'ultima versione di Bot Framework Emulator.

  1. Eseguire il bot competenza del dialogo e il bot radice del dialogo in locale nel computer. Se sono necessarie istruzioni, vedere il file di README esempio per C#, JavaScript, Java o Python.
  2. Usare l'emulatore per testare il bot.
    • Quando si partecipa per la prima volta alla conversazione, il bot visualizza un messaggio di benvenuto e chiede quale competenza si vuole chiamare. Il bot competenza per questo esempio ha solo una competenza.
    • Selezionare DialogSkillBot.
  3. Successivamente, il bot chiede di scegliere un'azione per la competenza. Scegliere "BookFlight".
    1. La competenza inizia l'azione di prenotazione di voli; rispondere alle richieste.
    2. Quando la competenza viene completata, il bot radice visualizza i dettagli della prenotazione prima di chiedere nuovamente quale competenza si vuole chiamare.
  4. Selezionare di nuovo DialogSkillBot e "BookFlight".
    1. Rispondere alla prima richiesta, quindi immettere "cancel" per annullare l'azione.
    2. Il bot competenza termina senza completare l'azione e il consumer chiede quale competenza si vuole chiamare.

Altre informazioni sul debug

Poiché il traffico tra competenze e consumer di competenze viene autenticato, è necessario eseguire passaggi aggiuntivi durante il debug di tali bot.

  • Il consumer di competenze e tutte le competenze utilizzate, direttamente o indirettamente, devono essere in esecuzione.
  • Se i bot vengono eseguiti localmente e se uno dei bot ha un ID app e una password, tutti i bot devono avere ID e password validi.
  • Se tutti i bot vengono distribuiti, vedere come eseguire il debug di un bot da qualsiasi canale usando devtunnel.
  • Se alcuni bot sono in esecuzione in locale e alcuni vengono distribuiti, vedere come eseguire il debug di una competenza o di un consumer di competenze.

In caso contrario, è possibile eseguire il debug di un consumer di competenze o di una competenza in modo molto simile al debug di altri bot. Per altre informazioni, vedere Debug di un bot e Debug con Bot Framework Emulator.

Informazioni aggiuntive