Usare un dialogo per una competenza

SI APPLICA A: SDK v4

Questo articolo illustra come usare un dialogo di competenza all'interno di un consumer di competenze. Il dialogo di competenza pubblica attività dal bot principale al bot di competenza e restituisce le risposte della competenza all'utente. Il bot di competenza accessibile da questo consumer può gestire attività relative sia a messaggi che a eventi. Per un manifesto della competenza di esempio e per informazioni sull'implementazione della competenza, vedere Usare dialoghi nelle competenze.

Per informazioni sull'uso di un bot di competenza al di fuori dei dialoghi, vedere la procedura per implementare un consumer di competenze.

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

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.

Questo articolo è incentrato sull'uso di una classe skill dialog in un bot radice per gestire la competenza, inviare le attività relative a messaggi ed eventi e annullare la competenza.

Per informazioni su altri aspetti della creazione di un consumer di competenze, vedere la procedura per implementare un consumer di competenze.

Per informazioni sul bot di competenza con dialogo, vedere Usare i dialoghi nelle competenze.

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à.

Configurazione dell'applicazione

  1. Facoltativamente, aggiungere le informazioni sull'identità del bot radice al file di configurazione.
  2. Aggiungere l'endpoint host della competenza (l'URL del servizio o di callback) a cui le competenze devono rispondere al consumer di competenze.
  3. Aggiungere una voce per ogni competenza usata dal consumer di competenze. Ogni voce include:
    • ID usato dal consumer di competenze per identificare le singole competenze.
    • Facoltativamente, l'app o l'ID client del bot di competenza.
    • Endpoint di messaggistica della competenza.

Nota

Se la competenza o il consumer di competenze specifica un'identità, entrambe devono.

DialogRootBot\appsettings.json

Facoltativamente, aggiungere le informazioni sull'identità del bot radice e aggiungere l'app o l'ID client per il bot di competenza echo alla BotFrameworkSkills matrice.

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

  "SkillHostEndpoint": "http://localhost:3978/api/skills/",
  "BotFrameworkSkills": [
    {
      "Id": "DialogSkillBot",
      "AppId": "",
      "SkillEndpoint": "http://localhost:39783/api/messages"
    }
  ]
}

Logica del dialogo

Il dialogo principale del bot include un dialogo di competenza per ogni competenza usata dal bot. Il dialogo di competenza gestisce la competenza tramite i vari oggetti correlati disponibili, come ad esempio gli oggetti client di competenze e la factory dell'ID conversazione della competenza. Il dialogo principale indica anche come annullare la competenza, tramite il dialogo di competenza, in base all'input dell'utente.

La competenza usata da questo bot 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 ed è stato configurato uno strumento di riconoscimento LUIS, tenta di interpretare le finalità dell'utente.

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.

Il manifesto della competenza (C#, JavaScript, Java, Python) descrive le azioni che la competenza può eseguire, i relativi parametri di input e output e gli endpoint della competenza. Si noti che la competenza può gestire un evento "BookFlight" o "GetWeather". Consente anche di gestire i messaggi.

Il dialogo principale include il codice per:

Il dialogo principale eredita dalla classe component dialog. Per altre informazioni sui dialoghi componenti, vedere la procedura per gestire la complessità dei dialoghi.

Inizializzare il dialogo principale

Il dialogo principale include dialoghi (per la gestione del flusso di conversazione all'esterno della competenza) e un dialogo di competenza (per la gestione delle competenze). Il dialogo a cascata include i passaggi seguenti, descritti in modo più dettagliato nelle sezioni successive.

  1. Chiedere all'utente di selezionare la competenza da usare. Il bot radice usa una competenza.
  2. Chiedere all'utente di selezionare l'azione da usare per la competenza. Il bot di competenza definisce tre azioni.
  3. Avviare la competenza scelta con un'attività iniziale basata sull'azione scelta.
  4. Una volta completata la competenza, visualizzare i risultati, se presenti, e quindi ripetere il dialogo a cascata.

DialogRootBot\Dialogs\MainDialog.cs

La classe MainDialog deriva da ComponentDialog. Oltre allo stato della conversazione, il dialogo richiede l'identità e i riferimenti del bot radice alla factory dell'ID conversazione competenza, al client HTTP della competenza e agli oggetti di configurazione delle competenze.

Il costruttore del dialogo controlla i parametri di input, aggiunge dialoghi di competenza, aggiunge dialoghi di richiesta e cascata per la gestione del flusso di conversazione all'esterno della competenza e crea una funzione di accesso alle proprietà per tenere traccia della competenza attiva, se presente.

Il costruttore chiama AddSkillDialogs, un metodo helper, per creare un elemento SkillDialog per ogni competenza inclusa nel file di configurazione, in base alla lettura del file di configurazione in un oggetto SkillsConfiguration.

// Helper method that creates and adds SkillDialog instances for the configured skills.
private void AddSkillDialogs(ConversationState conversationState, SkillConversationIdFactoryBase conversationIdFactory, SkillsConfiguration skillsConfig, string botId)
{
    foreach (var skillInfo in _skillsConfig.Skills.Values)
    {
        // Create the dialog options.
        var skillDialogOptions = new SkillDialogOptions
        {
            BotId = botId,
            ConversationIdFactory = conversationIdFactory,
            SkillClient = _auth.CreateBotFrameworkClient(),
            SkillHostEndpoint = skillsConfig.SkillHostEndpoint,
            ConversationState = conversationState,
            Skill = skillInfo
        };

        // Add a SkillDialog for the selected skill.
        AddDialog(new SkillDialog(skillDialogOptions, skillInfo.Id));
    }
}

Selezionare una competenza

Nel primo passaggio, il dialogo principale richiede all'utente la competenza che vuole chiamare e usa il prompt di scelta "SkillPrompt" per ottenere la risposta. Questo bot definisce solo una competenza.

DialogRootBot\Dialogs\MainDialog.cs

// Render a prompt to select the skill to call.
private async Task<DialogTurnResult> SelectSkillStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Create the PromptOptions from the skill configuration which contain the list of configured skills.
    var messageText = stepContext.Options?.ToString() ?? "What skill would you like to call?";
    var repromptMessageText = "That was not a valid choice, please select a valid skill.";
    var options = new PromptOptions
    {
        Prompt = MessageFactory.Text(messageText, messageText, InputHints.ExpectingInput),
        RetryPrompt = MessageFactory.Text(repromptMessageText, repromptMessageText, InputHints.ExpectingInput),
        Choices = _skillsConfig.Skills.Select(skill => new Choice(skill.Value.Id)).ToList()
    };

    // Prompt the user to select a skill.
    return await stepContext.PromptAsync("SkillPrompt", options, cancellationToken);
}

Selezionare un'azione della competenza

Nel passaggio successivo il dialogo principale:

  1. Salva le informazioni sulla competenza selezionata dall'utente.
  2. Richiede all'utente l'azione della competenza da usare e usa il prompt di scelta "SkillActionPrompt" per ottenere la risposta.
    • Usa un metodo helper per ottenere un elenco di azioni tra cui scegliere.
    • Per impostazione predefinita, il validator associato al prompt invierà un messaggio alla competenza se l'input dell'utente non corrisponde a una delle scelte.

Le scelte incluse nel bot consentono di testare le azioni definite per la competenza. In genere è possibile leggere le opzioni dal manifesto della competenza e presentare le opzioni all'utente in base a tale elenco.

DialogRootBot\Dialogs\MainDialog.cs

// Render a prompt to select the action for the skill.
private async Task<DialogTurnResult> SelectSkillActionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Get the skill info based on the selected skill.
    var selectedSkillId = ((FoundChoice)stepContext.Result).Value;
    var selectedSkill = _skillsConfig.Skills.FirstOrDefault(s => s.Value.Id == selectedSkillId).Value;

    // Remember the skill selected by the user.
    stepContext.Values[_selectedSkillKey] = selectedSkill;

    // Create the PromptOptions with the actions supported by the selected skill.
    var messageText = $"Select an action # to send to **{selectedSkill.Id}** or just type in a message and it will be forwarded to the skill";
    var options = new PromptOptions
    {
        Prompt = MessageFactory.Text(messageText, messageText, InputHints.ExpectingInput),
        Choices = GetSkillActions(selectedSkill)
    };

    // Prompt the user to select a skill action.
    return await stepContext.PromptAsync("SkillActionPrompt", options, cancellationToken);
}
// Helper method to create Choice elements for the actions supported by the skill.
private IList<Choice> GetSkillActions(BotFrameworkSkill skill)
{
    // Note: the bot would probably render this by reading the skill manifest.
    // We are just using hardcoded skill actions here for simplicity.

    var choices = new List<Choice>();
    switch (skill.Id)
    {
        case "DialogSkillBot":
            choices.Add(new Choice(SkillActionBookFlight));
            choices.Add(new Choice(SkillActionBookFlightWithInputParameters));
            choices.Add(new Choice(SkillActionGetWeather));
            break;
    }

    return choices;
}
// This validator defaults to Message if the user doesn't select an existing option.
private Task<bool> SkillActionPromptValidator(PromptValidatorContext<FoundChoice> promptContext, CancellationToken cancellationToken)
{
    if (!promptContext.Recognized.Succeeded)
    {
        // Assume the user wants to send a message if an item in the list is not selected.
        promptContext.Recognized.Value = new FoundChoice { Value = SkillActionMessage };
    }

    return Task.FromResult(true);
}

Avviare una competenza

Nel passaggio successivo il dialogo principale:

  1. Recupera le informazioni sulla competenza e sull'attività relativa selezionata dall'utente.
  2. Usa un metodo helper per creare l'attività da inviare inizialmente alla competenza.
  3. Crea le opzioni del dialogo con cui avviare il dialogo di competenza. Questa operazione include l'attività iniziale da inviare.
  4. Salva lo stato prima di chiamare la competenza. Questa operazione è necessaria perché la risposta della competenza potrebbe essere destinata a un'altra istanza del consumer di competenze.
  5. Avvia il dialogo di competenza, passando l'ID competenza da chiamare e le opzioni con cui chiamarlo.

DialogRootBot\Dialogs\MainDialog.cs

// Starts the SkillDialog based on the user's selections.
private async Task<DialogTurnResult> CallSkillActionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var selectedSkill = (BotFrameworkSkill)stepContext.Values[_selectedSkillKey];

    Activity skillActivity;
    switch (selectedSkill.Id)
    {
        case "DialogSkillBot":
            skillActivity = CreateDialogSkillBotActivity(((FoundChoice)stepContext.Result).Value, stepContext.Context);
            break;

        // We can add other case statements here if we support more than one skill.
        default:
            throw new Exception($"Unknown target skill id: {selectedSkill.Id}.");
    }

    // Create the BeginSkillDialogOptions and assign the activity to send.
    var skillDialogArgs = new BeginSkillDialogOptions { Activity = skillActivity };

    // Save active skill in state.
    await _activeSkillProperty.SetAsync(stepContext.Context, selectedSkill, cancellationToken);

    // Start the skillDialog instance with the arguments. 
    return await stepContext.BeginDialogAsync(selectedSkill.Id, skillDialogArgs, cancellationToken);
}

Riepilogare il risultato della competenza

Nell'ultimo passaggio il dialogo principale:

  1. Visualizza per l'utente il risultato della competenza, se disponibile.
  2. Cancella la competenza attiva dallo stato del dialogo.
  3. Rimuove la proprietà della competenza attiva dallo stato della conversazione.
  4. Esegue il riavvio.

DialogRootBot\Dialogs\MainDialog.cs

// The SkillDialog has ended, render the results (if any) and restart MainDialog.
private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var activeSkill = await _activeSkillProperty.GetAsync(stepContext.Context, () => null, cancellationToken);

    // Check if the skill returned any results and display them.
    if (stepContext.Result != null)
    {
        var message = $"Skill \"{activeSkill.Id}\" invocation complete.";
        message += $" Result: {JsonConvert.SerializeObject(stepContext.Result)}";
        await stepContext.Context.SendActivityAsync(MessageFactory.Text(message, message, inputHint: InputHints.IgnoringInput), cancellationToken: cancellationToken);
    }

    // Clear the skill selected by the user.
    stepContext.Values[_selectedSkillKey] = null;

    // Clear active skill in state.
    await _activeSkillProperty.DeleteAsync(stepContext.Context, cancellationToken);

    // Restart the main dialog with a different message the second time around.
    return await stepContext.ReplaceDialogAsync(InitialDialogId, $"Done with \"{activeSkill.Id}\". \n\n What skill would you like to call?", cancellationToken);
}

Consentire all'utente di annullare la competenza

Il dialogo principale sostituisce il comportamento predefinito del metodo on continue dialog per consentire all'utente di annullare l'eventuale competenza corrente. All'interno del metodo :

  • Se è presente una competenza attiva e l'utente invia un messaggio di interruzione, annullare tutte le finestre di dialogo e accodare il dialogo principale da riavviare dall'inizio.
  • In seguito chiama l'implementazione di base del metodo on continue dialog per continuare l'elaborazione del turno corrente.

DialogRootBot\Dialogs\MainDialog.cs

protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
{
    // This is an example on how to cancel a SkillDialog that is currently in progress from the parent bot.
    var activeSkill = await _activeSkillProperty.GetAsync(innerDc.Context, () => null, cancellationToken);
    var activity = innerDc.Context.Activity;
    if (activeSkill != null && activity.Type == ActivityTypes.Message && activity.Text.Equals("abort", StringComparison.OrdinalIgnoreCase))
    {
        // Cancel all dialogs when the user says abort.
        // The SkillDialog automatically sends an EndOfConversation message to the skill to let the
        // skill know that it needs to end its current dialogs, too.
        await innerDc.CancelAllDialogsAsync(cancellationToken);
        return await innerDc.ReplaceDialogAsync(InitialDialogId, "Canceled! \n\n What skill would you like to call?", cancellationToken);
    }

    return await base.OnContinueDialogAsync(innerDc, cancellationToken);
}

Logica del gestore di attività

Poiché la logica delle competenze per ogni turno viene gestita da un dialogo principale, il gestore di attività avrà un aspetto analogo a quello di altri esempi di dialogo.

DialogRootBot\Bots\RootBot.cs

public class RootBot<T> : ActivityHandler
    where T : Dialog
private readonly ConversationState _conversationState;
private readonly Dialog _mainDialog;

public RootBot(ConversationState conversationState, T mainDialog)
{
    _conversationState = conversationState;
    _mainDialog = mainDialog;
}
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
{
    if (turnContext.Activity.Type != ActivityTypes.ConversationUpdate)
    {
        // Run the Dialog with the Activity.
        await _mainDialog.RunAsync(turnContext, _conversationState.CreateProperty<DialogState>("DialogState"), cancellationToken);
    }
    else
    {
        // Let the base class handle the activity.
        await base.OnTurnAsync(turnContext, cancellationToken);
    }

    // Save any state changes that might have occurred during the turn.
    await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
}

Registrazione del servizio

I servizi necessari per usare un dialogo di competenza sono gli stessi di quelli necessari per un consumer di competenze. Per una descrizione dei servizi necessari, vedere la procedura per implementare un consumer di competenze.

Testare il bot radice

È possibile testare il consumer di competenze in Emulator come se fosse un normale bot, tuttavia è necessario eseguire contemporaneamente sia il bot della competenza che il quello del consumer di competenze. Per informazioni su come configurare la competenza, vedere Usare i dialoghi in 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 l'esempio per READMEC#, JavaScript, Java, 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. Il bot chiede quindi di scegliere un'azione per la competenza. Scegliere "BookFlight".
    1. Rispondere ai prompt.
    2. La competenza viene completata e 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 al primo prompt e immettere "Abort" per interrompere la competenza.
    2. Il bot radice annulla la competenza e 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 ngrok.
  • 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

Per informazioni sull'implementazione di un consumer di competenze, vedere Implementare un consumer di competenze.