Dela via


Skapa avancerat konversationsflöde med grenar och loopar

GÄLLER FÖR: SDK v4

Du kan skapa komplexa konversationsflöden med hjälp av dialogrutebiblioteket. Den här artikeln beskriver hur du hanterar komplexa konversationer som förgrenar och loopar och hur du skickar argument mellan olika delar av dialogrutan.

Anteckning

Om du vill skapa agenter med val av AI-tjänster, orkestrering och kunskap kan du använda Microsoft 365 Agents SDK. Agents SDK har stöd för C#, JavaScript eller Python. Du kan läsa mer om Agents SDK på aka.ms/agents. Om du letar efter en SaaS-baserad agentplattform bör du överväga Microsoft Copilot Studio. Om du har en befintlig robot som skapats med Bot Framework SDK kan du uppdatera roboten till Agents SDK. Du kan granska de viktigaste ändringarna och uppdateringarna i Bot Framework SDK till agenternas SDK-migreringsvägledning. Supportärenden för Bot Framework SDK kommer inte längre att betjänas från och med den 31 december 2025.

Förutsättningar

Om det här exemplet

Det här exemplet representerar en robot som kan registrera användare för att granska upp till två företag från en lista. Roboten använder tre komponentdialogrutor för att hantera konversationsflödet. Varje komponentdialogruta innehåller en vattenfallsdialog och alla uppmaningar som behövs för att samla in användarindata. Dessa dialogrutor beskrivs mer detaljerat i följande avsnitt. Den använder konversationstillstånd för att hantera sina dialogrutor och använder användartillstånd för att spara information om användaren och vilka företag de vill granska.

Roboten härleds från aktivitetshanteraren. Liksom många av exempelrobotarna välkomnar den användaren, använder dialogrutor för att hantera meddelanden från användaren och sparar användar- och konversationstillstånd innan svängen slutar.

Om du vill använda dialogrutor installerar du NuGet-paketet Microsoft.Bot.Builder.Dialogs .

Klassdiagram för C#-exempel.

Definiera användarprofilen

Användarprofilen innehåller information som samlas in av dialogrutorna, användarens namn, ålder och företag som valts att granska.

UserProfile.cs

/// <summary>Contains information about a user.</summary>
public class UserProfile
{
    public string Name { get; set; }

    public int Age { get; set; }

    // The list of companies the user wants to review.
    public List<string> CompaniesToReview { get; set; } = new List<string>();

Skapa dialogrutorna

Den här roboten innehåller tre dialogrutor:

  • Huvuddialogrutan startar den övergripande processen och sammanfattar sedan den insamlade informationen.
  • Dialogrutan på den översta nivån samlar in användarinformation och innehåller förgreningslogik baserat på användarens ålder.
  • I dialogrutan för granskningsval kan användaren iterativt välja företag att granska. Den använder loopningslogik för att göra det.

Huvuddialogrutan

Huvuddialogrutan innehåller två steg:

  1. Starta toppnivådialogen.
  2. Hämta och sammanfatta användarprofilen som dialogrutan på den översta nivån samlade in, spara informationen i användartillståndet och signalera sedan slutet av huvuddialogrutan.

Dialogrutor\MainDialog.cs

private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    return await stepContext.BeginDialogAsync(nameof(TopLevelDialog), null, cancellationToken);
}

private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    var userInfo = (UserProfile)stepContext.Result;

    string status = "You are signed up to review "
        + (userInfo.CompaniesToReview.Count is 0 ? "no companies" : string.Join(" and ", userInfo.CompaniesToReview))
        + ".";

    await stepContext.Context.SendActivityAsync(status);

    var accessor = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    await accessor.SetAsync(stepContext.Context, userInfo, cancellationToken);

    return await stepContext.EndDialogAsync(null, cancellationToken);
}

Dialogrutan på den översta nivån

Dialogrutan på den översta nivån innehåller fyra steg:

  1. Fråga efter användarens namn.
  2. Fråga efter användarens ålder.
  3. Starta antingen dialogrutan för granskningsval eller gå vidare till nästa steg, baserat på användarens ålder.
  4. Slutligen tackar du användaren för att han eller hon deltar och returnerar den insamlade informationen.

Det första steget skapar en tom användarprofil som en del av dialogtillståndet. Dialogrutan börjar med en tom profil och lägger till information i profilen när den fortskrider. När den är slut returnerar det sista steget den insamlade informationen.

I det tredje steget (startval) förgrenar konversationsflödet, baserat på användarens ålder.

Dialogrutor\TopLevelDialog.cs

            stepContext.Values[UserInfo] = new UserProfile();

            var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") };

            // Ask the user to enter their name.
            return await stepContext.PromptAsync(nameof(TextPrompt), promptOptions, cancellationToken);
        }

        private async Task<DialogTurnResult> AgeStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Set the user's name to what they entered in response to the name prompt.
            var userProfile = (UserProfile)stepContext.Values[UserInfo];
            userProfile.Name = (string)stepContext.Result;

            var promptOptions = new PromptOptions { Prompt = MessageFactory.Text("Please enter your age.") };

            // Ask the user to enter their age.
            return await stepContext.PromptAsync(nameof(NumberPrompt<int>), promptOptions, cancellationToken);
        }

        private async Task<DialogTurnResult> StartSelectionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Set the user's age to what they entered in response to the age prompt.
            var userProfile = (UserProfile)stepContext.Values[UserInfo];
            userProfile.Age = (int)stepContext.Result;

            if (userProfile.Age < 25)
            {
                // If they are too young, skip the review selection dialog, and pass an empty list to the next step.
                await stepContext.Context.SendActivityAsync(
                    MessageFactory.Text("You must be 25 or older to participate."),
                    cancellationToken);
                return await stepContext.NextAsync(new List<string>(), cancellationToken);
            }
            else
            {
                // Otherwise, start the review selection dialog.
                return await stepContext.BeginDialogAsync(nameof(ReviewSelectionDialog), null, cancellationToken);
            }
        }

        private async Task<DialogTurnResult> AcknowledgementStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            // Set the user's company selection to what they entered in the review-selection dialog.
            var userProfile = (UserProfile)stepContext.Values[UserInfo];
            userProfile.CompaniesToReview = stepContext.Result as List<string> ?? new List<string>();

            // Thank them for participating.
            await stepContext.Context.SendActivityAsync(
                MessageFactory.Text($"Thanks for participating, {((UserProfile)stepContext.Values[UserInfo]).Name}."),
                cancellationToken);

            // Exit the dialog, returning the collected user information.
            return await stepContext.EndDialogAsync(stepContext.Values[UserInfo], cancellationToken);
        }
    }
}

Dialogrutan för val av granskning

Dialogrutan för granskningsval har två steg:

  1. Be användaren att välja ett företag att granska eller done för att avsluta.
    • Om dialogrutan har startats med någon inledande information är informationen tillgänglig via egenskapen "options" i vattenfallsstegskontexten. Dialogrutan för granskningsval kan starta om sig själv och den använder den för att tillåta användaren att välja fler än ett företag att granska.
    • Om användaren redan har valt ett företag att granska tas företaget bort från de tillgängliga alternativen.
    • Ett done val läggs till så att användaren kan avsluta loopen tidigt.
  2. Upprepa den här dialogrutan eller avsluta efter behov.
    • Om användaren har valt ett företag att granska lägger du till det i listan.
    • Om användaren har valt två företag eller väljer att avsluta dialogrutan avslutar du dialogrutan och returnerar den insamlade listan.
    • Annars startar du om dialogrutan och initierar den med innehållet i listan.

Dialoger\ReviewSelectionDialog.cs

private async Task<DialogTurnResult> SelectionStepAsync(
    WaterfallStepContext stepContext,
    CancellationToken cancellationToken)
{
    // Continue using the same selection list, if any, from the previous iteration of this dialog.
    var list = stepContext.Options as List<string> ?? new List<string>();
    stepContext.Values[CompaniesSelected] = list;

    // Create a prompt message.
    string message;
    if (list.Count is 0)
    {
        message = $"Please choose a company to review, or `{DoneOption}` to finish.";
    }
    else
    {
        message = $"You have selected **{list[0]}**. You can review an additional company, " +
            $"or choose `{DoneOption}` to finish.";
    }

    // Create the list of options to choose from.
    var options = _companyOptions.ToList();
    options.Add(DoneOption);
    if (list.Count > 0)
    {
        options.Remove(list[0]);
    }

    var promptOptions = new PromptOptions
    {
        Prompt = MessageFactory.Text(message),
        RetryPrompt = MessageFactory.Text("Please choose an option from the list."),
        Choices = ChoiceFactory.ToChoices(options),
    };

    // Prompt the user for a choice.
    return await stepContext.PromptAsync(nameof(ChoicePrompt), promptOptions, cancellationToken);
}

private async Task<DialogTurnResult> LoopStepAsync(
    WaterfallStepContext stepContext,
    CancellationToken cancellationToken)
{
    // Retrieve their selection list, the choice they made, and whether they chose to finish.
    var list = stepContext.Values[CompaniesSelected] as List<string>;
    var choice = (FoundChoice)stepContext.Result;
    var done = choice.Value == DoneOption;

    if (!done)
    {
        // If they chose a company, add it to the list.
        list.Add(choice.Value);
    }

    if (done || list.Count >= 2)
    {
        // If they're done, exit and return their list.
        return await stepContext.EndDialogAsync(list, cancellationToken);
    }
    else
    {
        // Otherwise, repeat this dialog, passing in the list from this iteration.
        return await stepContext.ReplaceDialogAsync(InitialDialogId, list, cancellationToken);
    }
}

Kör dialoger

Klassen dialogrobot utökar aktivitetshanteraren och innehåller logiken för att köra dialogrutorna. Klassen dialogrobot och välkomstrobot utökar dialogroboten för att även välkomna en användare när de ansluter till konversationen.

Robotens turhanterare upprepar konversationsflödet som definieras av de tre dialogerna. När det tar emot ett meddelande från användaren:

  1. Den kör huvuddialogen.
    • Om dialogstacken är tom startar huvuddialogrutan.
    • Annars är dialogrutorna fortfarande under processen och detta kommer att fortsätta den aktiva dialogrutan.
  2. Det sparar tillstånd, så att alla uppdateringar av användaren, konversationen och dialogtillståndet sparas.

Robotar\DialogBot.cs

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    await base.OnTurnAsync(turnContext, cancellationToken);

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

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

Registrera tjänster för roboten

Skapa och registrera tjänster efter behov:

  • Grundläggande tjänster för roboten: en adapter och robotimplementeringen.
  • Tjänster för att hantera tillstånd: lagring, användartillstånd och konversationstillstånd.
  • Rotdialogen som roboten ska använda.

Startup.cs

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient().AddControllers().AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth;
    });

    // Create the Bot Framework Authentication to be used with the Bot Adapter.
    services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

    // Create the Bot Adapter with error handling enabled.
    services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

    // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
    services.AddSingleton<IStorage, MemoryStorage>();

    // Create the User state. (Used in this bot's Dialog implementation.)
    services.AddSingleton<UserState>();

Anteckning

Minneslagring används endast i testsyfte och är inte avsett för produktionsanvändning. Se till att använda en beständig typ av lagring för en produktionsrobot.

Testa roboten

  1. Om du inte redan har gjort det installerar du Bot Framework-emulatorn.

  2. Kör exemplet lokalt på datorn.

  3. Starta emulatorn, anslut till roboten och skicka meddelanden enligt nedan.

    Exempel på avskrift från en konversation med den komplexa dialogroboten.

Ytterligare resurser

För en introduktion om hur du implementerar en dialog, se implementera sekventiellt konversationsflöde, som använder en enda vattenfallsdialog och några uppmaningar för att ställa en serie frågor till användaren.

Dialogbiblioteket innehåller grundläggande validering för uppmaningar. Du kan också lägga till anpassad validering. Mer information finns i samla in användarindata med hjälp av en dialogruta.

För att flera robotar ska kunna förenkla din dialogkod och återanvända delar av en dialogsats kan du definiera dessa delar som en separat klass. Mer information finns i återanvändningsdialogrutor.

Nästa steg