Con i dialoghi componenti è possibile creare dialoghi indipendenti per gestire scenari specifici, suddividendo un set di dialoghi di grandi dimensioni in parti più gestibili. Ognuno di questi componenti ha il proprio set di dialoghi ed evita eventuali conflitti di nomi con i set di dialoghi esterni. I dialoghi componenti sono riutilizzabili in quanto possono essere:
Aggiunti a un altro ComponentDialog o DialogSet nel bot.
Esportati come parte di un pacchetto.
Usati all'interno di altri bot.
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.
Nell'esempio di richiesta a più turni si usa un dialogo a cascata, alcune richieste e un dialogo componente per creare un'interazione che chiede all'utente una serie di domande. Il codice usa un dialogo per scorrere questi passaggi:
Passaggi
Tipo di richiesta
Chiedere all'utente la modalità di trasporto
Richiesta di scelta
Chiedere all'utente il nome
Richiesta di testo
Chiedere all'utente se vuole fornire la propria età
Richiesta di conferma
Se hanno risposto sì, chiedere la loro età
Richiesta di numeri con convalida per accettare solo età maggiori di 0 e minori di 150.
Chiedere se le informazioni raccolte sono "ok"
Riutilizzo della richiesta di conferma
Infine, se hanno risposto sì, visualizzare le informazioni raccolte; in caso contrario, indicare all'utente che le informazioni non verranno mantenute.
Implementare la finestra di dialogo del componente
Nell'esempio di richiesta a più turni si usa un dialogo a cascata, alcune richieste e un dialogo componente per creare un'interazione che chiede all'utente una serie di domande.
Un dialogo componente racchiude uno o più dialoghi. Il dialogo componente contiene un set di dialoghi interno e i dialoghi e le richieste che si aggiungono a questo set di dialoghi interno hanno propri ID, visibili solo all'interno del dialogo componente.
Per usare i dialoghi, installare il pacchetto NuGet Microsoft.Bot.Builder.Dialogs.
Dialogs\UserProfileDialog.cs
In questo caso la classe UserProfileDialog deriva dalla classe ComponentDialog.
public class UserProfileDialog : ComponentDialog
All'interno del costruttore il metodo AddDialog aggiunge dialoghi e richieste al dialogo componente. Il primo elemento aggiunto con questo metodo viene impostato come finestra di dialogo iniziale. È possibile modificare la finestra di dialogo iniziale impostando in modo esplicito la InitialDialogId proprietà . Quando si avvia un dialogo componenti, viene avviato il relativo dialogo iniziale.
public UserProfileDialog(UserState userState)
: base(nameof(UserProfileDialog))
{
_userProfileAccessor = userState.CreateProperty<UserProfile>("UserProfile");
// This array defines how the Waterfall will execute.
var waterfallSteps = new WaterfallStep[]
{
TransportStepAsync,
NameStepAsync,
NameConfirmStepAsync,
AgeStepAsync,
PictureStepAsync,
SummaryStepAsync,
ConfirmStepAsync,
};
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
AddDialog(new TextPrompt(nameof(TextPrompt)));
AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
AddDialog(new AttachmentPrompt(nameof(AttachmentPrompt), PicturePromptValidatorAsync));
// The initial child Dialog to run.
InitialDialogId = nameof(WaterfallDialog);
}
Il codice seguente rappresenta il primo passaggio del dialogo a cascata.
private static async Task<DialogTurnResult> NameStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
stepContext.Values["transport"] = ((FoundChoice)stepContext.Result).Value;
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") }, cancellationToken);
}
Per usare i dialoghi, è necessario installare il pacchetto npm botbuilder-dialogs per il progetto.
dialogs/userProfileDialog.js
In questo caso la classe UserProfileDialog estende ComponentDialog.
class UserProfileDialog extends ComponentDialog {
All'interno del costruttore il metodo AddDialog aggiunge dialoghi e richieste al dialogo componente. Il primo elemento aggiunto con questo metodo viene impostato come finestra di dialogo iniziale. È possibile modificare la finestra di dialogo iniziale impostando in modo esplicito la InitialDialogId proprietà . Quando si avvia un dialogo componenti, viene avviato il relativo dialogo iniziale.
Il codice seguente rappresenta il primo passaggio del dialogo a cascata.
async transportStep(step) {
// WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
// Running a prompt here means the next WaterfallStep will be run when the user's response is received.
return await step.prompt(CHOICE_PROMPT, {
prompt: 'Please enter your mode of transport.',
choices: ChoiceFactory.toChoices(['Car', 'Bus', 'Bicycle'])
});
}
In questo caso la classe UserProfileDialog deriva dalla classe ComponentDialog.
public class UserProfileDialog extends ComponentDialog {
All'interno del costruttore il metodo addDialog aggiunge dialoghi e richieste al dialogo componente. Il primo elemento aggiunto con questo metodo viene impostato come finestra di dialogo iniziale. È possibile modificare il dialogo iniziale chiamando il setInitialDialogId metodo e specificando il nome del dialogo iniziale. Quando si avvia un dialogo componenti, viene avviato il relativo dialogo iniziale.
public UserProfileDialog(UserState withUserState) {
super("UserProfileDialog");
userProfileAccessor = withUserState.createProperty("UserProfile");
WaterfallStep[] waterfallSteps = {
UserProfileDialog::transportStep,
UserProfileDialog::nameStep,
this::nameConfirmStep,
this::ageStep,
UserProfileDialog::pictureStep,
this::confirmStep,
this::summaryStep
};
// Add named dialogs to the DialogSet. These names are saved in the dialog state.
addDialog(new WaterfallDialog("WaterfallDialog", Arrays.asList(waterfallSteps)));
addDialog(new TextPrompt("TextPrompt"));
addDialog(new NumberPrompt<Integer>("NumberPrompt", UserProfileDialog::agePromptValidator, Integer.class));
addDialog(new ChoicePrompt("ChoicePrompt"));
addDialog(new ConfirmPrompt("ConfirmPrompt"));
addDialog(new AttachmentPrompt("AttachmentPrompt", UserProfileDialog::picturePromptValidator));
// The initial child Dialog to run.
setInitialDialogId("WaterfallDialog");
}
Il codice seguente rappresenta il primo passaggio del dialogo a cascata.
private static CompletableFuture<DialogTurnResult> nameStep(WaterfallStepContext stepContext) {
stepContext.getValues().put("transport", ((FoundChoice) stepContext.getResult()).getValue());
PromptOptions promptOptions = new PromptOptions();
promptOptions.setPrompt(MessageFactory.text("Please enter your name."));
return stepContext.prompt("TextPrompt", promptOptions);
}
Per usare i dialoghi, installare i pacchetti PyPI botbuilder-dialogs e botbuilder-ai eseguendo pip install botbuilder-dialogs e pip install botbuilder-ai in un terminale.
dialogs/user_profile_dialog.py
In questo caso la classe UserProfileDialog estende ComponentDialog.
class UserProfileDialog(ComponentDialog):
All'interno del costruttore il metodo add_dialog aggiunge dialoghi e richieste al dialogo componente. Il primo elemento aggiunto con questo metodo viene impostato come finestra di dialogo iniziale. È possibile modificare la finestra di dialogo iniziale impostando in modo esplicito la initial_dialog_id proprietà . Quando si avvia un dialogo componenti, viene avviato il relativo dialogo iniziale.
Il codice seguente rappresenta il primo passaggio del dialogo a cascata.
async def transport_step(
self, step_context: WaterfallStepContext
) -> DialogTurnResult:
# WaterfallStep always finishes with the end of the Waterfall or with another dialog;
# here it is a Prompt Dialog. Running a prompt here means the next WaterfallStep will
# be run when the users response is received.
return await step_context.prompt(
ChoicePrompt.__name__,
PromptOptions(
prompt=MessageFactory.text("Please enter your mode of transport."),
choices=[Choice("Car"), Choice("Bus"), Choice("Bicycle")],
),
)
In fase di esecuzione il dialogo componente mantiene il proprio stack di dialoghi. Quando viene avviato il dialogo componente:
Un'istanza viene creata e aggiunta allo stack di dialoghi esterno
Viene creato uno stack di dialoghi interno che viene aggiunto al relativo stato
Viene avviato il dialogo iniziale che viene aggiunto allo stack di dialoghi interno.
Il contesto padre vede il componente come finestra di dialogo attiva. Tuttavia, al contesto all'interno del componente, sembra che il dialogo iniziale sia il dialogo attivo.
Chiamare il dialogo dal bot
Nel set di dialoghi esterno, quello a cui è stato aggiunto il dialogo componente, la finestra di dialogo componente ha l'ID con cui è stato creato. Nel set esterno, il componente risulta come un singolo dialogo, in modo analogo alle richieste.
Per usare una finestra di dialogo componente, aggiungerla al set di dialoghi del bot.
Nell'esempio questa operazione viene eseguita usando il metodo RunAsync che viene chiamato dal metodo OnMessageActivityAsync del bot.
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
Logger.LogInformation("Running dialog with Message Activity.");
// Run the Dialog with the new message Activity.
await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}
dialogs/userProfileDialog.js
Nell'esempio è stato aggiunto un metodo run nel dialogo del profilo utente.
Il metodo run viene chiamato dal metodo onMessage del bot.
this.onMessage(async (context, next) => {
console.log('Running dialog with Message Activity.');
// Run the Dialog with the new message Activity.
await this.dialog.run(context, this.dialogState);
await next();
});
DialogBot.java
Nell'esempio questa operazione viene eseguita usando il metodo run che viene chiamato dal metodo onMessageActivity del bot.
@Override
protected CompletableFuture<Void> onMessageActivity(
TurnContext turnContext
) {
LoggerFactory.getLogger(DialogBot.class).info("Running dialog with Message Activity.");
// Run the Dialog with the new message Activity.
return Dialog.run(dialog, turnContext, conversationState.createProperty("DialogState"));
}
helpers/dialog_helper.py
Nell'esempio è stato aggiunto un metodo run_dialog nel dialogo del profilo utente.
Avviare l'emulatore, connettersi al bot e inviare messaggi come mostrato di seguito.
Informazioni aggiuntive
Funzionamento dell'annullamento per i dialoghi componente
Se si chiama cancel all dialogs dal contesto del dialogo componente, il dialogo componente annullerà tutti i dialoghi nel relativo stack interno e quindi termina, restituendo il controllo al dialogo successivo nello stack esterno.
Se si chiama annullano tutti i dialoghi dal contesto esterno, il componente viene annullato, insieme al resto dei dialoghi nel contesto esterno.
Passaggi successivi
Informazioni su come creare conversazioni complesse che creano rami e cicli.