Sıralı konuşma akışını uygulama

ŞUNLAR IÇIN GEÇERLIDIR: SDK v4

Soru sorup bilgi toplamak, botun kullanıcılarla etkileşim kurmasının ana yollarından biridir. İletişim kutusu kitaplığı, belirli bir veri türüyle eşleştiğinden veya özel doğrulama kurallarına uyduğundan emin olmak için soru sormayı ve yanıtı doğrulamayı kolaylaştıran istem sınıfları gibi kullanışlı yerleşik özellikler sağlar.

İletişim kutusu kitaplığını kullanarak doğrusal ve daha karmaşık konuşma akışlarını yönetebilirsiniz. Doğrusal etkileşimde bot sabit bir adım dizisinde çalışır ve konuşma tamamlar. Bot kullanıcıdan bilgi toplaması gerektiğinde iletişim kutusu kullanışlıdır.

Bu makalede, istemler oluşturup bunları şelale iletişim kutusundan çağırarak doğrusal konuşma akışının nasıl uygulandığı gösterilmektedir. İletişim kutusu kitaplığını kullanmadan kendi istemlerinizi yazma örnekleri için Kullanıcı girişi toplamak için kendi istemlerinizi oluşturma makalesine bakın.

Not

Bot Framework JavaScript, C# ve Python SDK'ları desteklenmeye devam edecektir, ancak Java SDK'sı son uzun vadeli destek Kasım 2023'te sona erecek şekilde kullanımdan kaldırılacaktır.

Java SDK ile oluşturulan mevcut botlar çalışmaya devam edecektir.

Yeni bot derlemesi için Power Virtual Agents'ı kullanmayı göz önünde bulundurun ve doğru sohbet botu çözümünü seçme hakkında bilgi edinin.

Daha fazla bilgi için bkz . Bot oluşturmanın geleceği.

Önkoşullar

Bu örnek hakkında

Çok dönüşlü istemler örneği, kullanıcıya bir dizi soru soran doğrusal bir etkileşim oluşturmak için şelale iletişim kutusu, birkaç istem ve bileşen iletişim kutusu kullanır. Kod, şu adımlar arasında geçiş yapmak için bir iletişim kutusu kullanır:

Adımlar İstem türü
Kullanıcıdan taşıma modunu isteyin Seçim istemi
Kullanıcıdan adını isteyin Metin istemi
Kullanıcıya yaşını sağlamak isteyip istemediğini sorun İstemi onayla
Evet yanıtı verdilerse, yaşını sorun Yalnızca 0'dan büyük ve 150'den küçük yaşları kabul eden doğrulama ile numara istemi
Microsoft Teams kullanmıyorlarsa profil resmi isteyin Eksik eke izin vermek için doğrulamayla birlikte ek istemi
Toplanan bilgilerin "tamam" olup olmadığını sorun Onayla istemini yeniden kullan

Son olarak evet yanıtı verdiyseniz toplanan bilgileri görüntüleyin; aksi takdirde, kullanıcıya bilgilerinin saklanmayacağını söyleyin.

Ana iletişim kutusu oluşturma

İletişim kutularını kullanmak için Microsoft.Bot.Builder.Dialogs NuGet paketini yükleyin.

Bot, aracılığıyla UserProfileDialogkullanıcıyla etkileşim kurar. Bot DialogBot sınıfı oluşturulurken, UserProfileDialog ana iletişim kutusu olarak ayarlanır. Bot daha sonra iletişim kutusuna erişmek için bir Run yardımcı yöntemi kullanır.

C# örneği için sınıf diyagramı.

İletişim Kutuları\UserProfileDialog.cs

sınıfından türetilen ComponentDialog ve yedi adımı olan öğesini oluşturarak UserProfileDialog başlayın.

Oluşturucuda UserProfileDialog şelale adımlarını, istemlerini ve şelale iletişim kutusunu oluşturun ve bunları iletişim kutusu kümesine ekleyin. İstemlerin, kullanıldıkları iletişim kutusunda olması gerekir.

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

Ardından, iletişim kutusunun giriş isteminde kullandığı adımları ekleyin. İstemi kullanmak için, bunu iletişim kutunuzdaki bir adımdan çağırın ve kullanarak stepContext.Resultaşağıdaki adımda istem sonucunu alın. Arka planda istemler iki adımlı bir iletişim kutusu olur. İlk olarak, istem giriş ister. Ardından geçerli değeri döndürür veya geçerli bir giriş alana kadar baştan başlayıp yeniden üretmeye başlar.

Her zaman bir şelale adımından null DialogTurnResult olmayan bir değer döndürmelisiniz. Aksi takdirde iletişim kutunuz tasarlandığı gibi çalışmayabilir. Şelale iletişim kutusunda uygulaması aşağıda NameStepAsync gösterilmiştir.

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

içinde AgeStepAsync, istem ayrıştıramadığı bir biçimde olduğundan veya giriş doğrulama ölçütlerinde başarısız olduğundan kullanıcının girişi doğrulanamadığından için bir yeniden deneme istemi belirtin. Bu durumda, yeniden deneme istemi sağlanmamışsa, istem ilk istem metnini kullanarak kullanıcıyı giriş için yeniden oluşturur.

private async Task<DialogTurnResult> AgeStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    if ((bool)stepContext.Result)
    {
        // User said "yes" so we will be prompting for the age.
        // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
        var promptOptions = new PromptOptions
        {
            Prompt = MessageFactory.Text("Please enter your age."),
            RetryPrompt = MessageFactory.Text("The value entered must be greater than 0 and less than 150."),
        };

        return await stepContext.PromptAsync(nameof(NumberPrompt<int>), promptOptions, cancellationToken);
    }
    else
    {
        // User said "no" so we will skip the next step. Give -1 as the age.
        return await stepContext.NextAsync(-1, cancellationToken);
    }
}

UserProfile.cs

Kullanıcının taşıma, ad ve yaş modu sınıfın UserProfile bir örneğine kaydedilir.

public class UserProfile
{
    public string Transport { get; set; }

    public string Name { get; set; }

    public int Age { get; set; }

    public Attachment Picture { get; set; }
}

İletişim Kutuları\UserProfileDialog.cs

Son adımda, önceki şelale adımında adı verilen iletişim kutusu tarafından döndürüleni denetleyin stepContext.Result . Dönüş değeri true ise, kullanıcı profili erişimcisi kullanıcı profilini alır ve güncelleştirir. Kullanıcı profilini almak için öğesini çağırın GetAsync ve ardından , userProfile.NameuserProfile.Age ve userProfile.Picture özelliklerinin değerlerini userProfile.Transportayarlayın. Son olarak, iletişim kutusunu sona erdiren çağrısından EndDialogAsyncönce kullanıcının bilgilerini özetleyin. İletişim kutusunu sonlandırmak, iletişim kutusu yığınını kapatır ve iletişim kutusunun üst öğesine isteğe bağlı bir sonuç döndürür. Üst öğe, yeni sona eren iletişim kutusunu başlatan iletişim kutusu veya yöntemdir.

    else
    {
        msg += $" Your profile will not be kept.";
    }

    await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);

    // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is the end.
    return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
}

private async Task<DialogTurnResult> SummaryStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    stepContext.Values["picture"] = ((IList<Attachment>)stepContext.Result)?.FirstOrDefault();

    // Get the current profile object from user state.
    var userProfile = await _userProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile(), cancellationToken);

    userProfile.Transport = (string)stepContext.Values["transport"];
    userProfile.Name = (string)stepContext.Values["name"];
    userProfile.Age = (int)stepContext.Values["age"];
    userProfile.Picture = (Attachment)stepContext.Values["picture"];

    var msg = $"I have your mode of transport as {userProfile.Transport} and your name as {userProfile.Name}";

    if (userProfile.Age != -1)
    {
        msg += $" and your age as {userProfile.Age}";
    }

    msg += ".";

    await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);

    if (userProfile.Picture != null)
    {
        try
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(userProfile.Picture, "This is your profile picture."), cancellationToken);
        }
        catch
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Text("A profile picture was saved but could not be displayed here."), cancellationToken);

İletişim kutusunu çalıştırma

Botlar\DialogBot.cs

İşleyici, OnMessageActivityAsync iletişim kutusunu başlatmak veya devam etmek için yöntemini kullanır RunAsync . OnTurnAsync , depolamada yapılan durum değişikliklerini kalıcı hale getirmek için botunun durum yönetimi nesnelerini kullanır. ActivityHandler.OnTurnAsync yöntemi gibi OnMessageActivityAsyncçeşitli etkinlik işleyici yöntemlerini çağırır. Bu şekilde, ileti işleyicisi tamamlandıktan sonra ancak dönüş tamamlanmadan önce durum kaydedilir.

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
{
    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);
}

Bot için hizmetleri kaydetme

Bu bot aşağıdaki hizmetleri kullanır:

  • Bot için temel hizmetler: kimlik bilgisi sağlayıcısı, bağdaştırıcı ve bot uygulaması.
  • Durumu yönetmeye yönelik hizmetler: depolama, kullanıcı durumu ve konuşma durumu.
  • Bot tarafından kullanılacak iletişim kutusu.

Startup.cs

içindeki bot Startupiçin hizmetleri kaydedin. Bu hizmetler, bağımlılık ekleme yoluyla kodun diğer bölümleri için kullanılabilir.

{
    // 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>();

        // Create the Conversation state. (Used by the Dialog system itself.)
        services.AddSingleton<ConversationState>();

Not

Bellek depolama yalnızca test amacıyla kullanılır ve üretim kullanımı için tasarlanmamıştır. Üretim botu için kalıcı bir depolama türü kullandığınızdan emin olun.

Botunuzu test etme

  1. Henüz yapmadıysanız Bot Framework Öykünücüsü'ni yükleyin.
  2. Örneği makinenizde yerel olarak çalıştırın.
  3. Emulator'ı başlatın, botunuza bağlanın ve aşağıda gösterildiği gibi ileti gönderin.

Çok aşamalı istem botuyla yapılan bir konuşmanın örnek transkripti.

Ek bilgi

İletişim kutusu ve bot durumu hakkında

Bu botta iki durum özelliği erişimcisi tanımlanır:

  • İletişim durumu özelliği için konuşma durumunda oluşturulan bir tane. İletişim kutusu durumu, kullanıcının bir iletişim kutusu kümesinin iletişim kutuları içinde nerede olduğunu izler ve iletişim kutusu bağlamı tarafından (örneğin, başlangıç iletişim kutusu veya devam iletişim kutusu yöntemleri çağrıldığında) güncelleştirilir.
  • Kullanıcı profili özelliği için kullanıcı durumu içinde oluşturulan bir tane. Bot, kullanıcı hakkında sahip olduğu bilgileri izlemek için bunu kullanır ve iletişim kutusu kodunda bu durumu açıkça yönetmeniz gerekir.

Durum özelliği erişimcisinin get ve set yöntemleri, durum yönetimi nesnesinin önbelleğinde özelliğin değerini alır ve ayarlar. Bir durum özelliğinin değeri ilk kez istenildiğinde önbellek doldurulur, ancak açıkça kalıcı olması gerekir. Bu durum özelliklerinin her ikisinde de değişiklikleri kalıcı hale getirmek için, karşılık gelen durum yönetimi nesnesinin save changes yöntemine bir çağrı gerçekleştirilir.

Bu örnek, iletişim kutusunun içinden kullanıcı profili durumunu güncelleştirir. Bu uygulama bazı botlarda kullanılabilir, ancak bir iletişim kutusunu botlar arasında yeniden kullanmak istiyorsanız çalışmaz.

İletişim kutusu adımlarını ve bot durumunu ayrı tutmak için çeşitli seçenekler vardır. Örneğin, iletişim kutunuz tüm bilgileri topladıktan sonra şunları yapabilirsiniz:

  • Toplanan verileri üst bağlama geri dönüş değeri olarak sağlamak için end iletişim kutusu yöntemini kullanın. Bu, bot'un dönüş işleyicisi veya iletişim kutusu yığınındaki daha önceki etkin bir iletişim kutusu olabilir ve istem sınıfları bu şekilde tasarlanır.
  • Uygun bir hizmete istek oluşturun. Botunuz daha büyük bir hizmet için ön uç işlevi görüyorsa bu işlem iyi sonuç verebilir.

İstem doğrulayıcı yönteminin tanımı

UserProfileDialog.cs

Aşağıda yöntem tanımı için bir doğrulayıcı kod örneği verilmiştir AgePromptValidatorAsync . promptContext.Recognized.Value , sayı istemi için burada bir tamsayı olan ayrıştırılmış değeri içerir. promptContext.Recognized.Succeeded , istemin kullanıcının girişini ayrıştırıp ayrıştıramayacağını gösterir. Doğrulayıcı değerin kabul edilmediğini ve istem iletişim kutusunun kullanıcıyı yeniden üretmesi gerektiğini belirtmek için false döndürmelidir; aksi takdirde girişi kabul etmek ve istem iletişim kutusundan dönmek için true değerini döndürebilirsiniz. Senaryonuza göre doğrulayıcıdaki değeri değiştirebilirsiniz.

    }

    // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
    return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Is this ok?") }, cancellationToken);
}

Sonraki adımlar