Aracılığıyla paylaş


Kullanıcı girişi toplamak için kendi istemlerinizi oluşturma

ŞUNLAR IÇIN GEÇERLIDIR: SDK v4

Bot ve kullanıcı arasındaki konuşma genellikle kullanıcıdan bilgi istemeyi (sormayı), kullanıcının yanıtını ayrıştırmayı ve ardından bu bilgiler üzerinde hareket etmeyi içerir. Botunuz, bir konuşmanın davranışını yönetebilmesi ve önceki soruların yanıtlarını anımsayabilmesi için konuşmanın bağlamını izlemelidir. Botların durumu , gelen iletilere uygun şekilde yanıt vermek için izlediği bilgilerdir.

İpucu

İletişim kutuları kitaplığı, kullanıcıların kullanabileceği daha fazla işlev sağlayan yerleşik istemler sağlar. Bu istemlere örnekler Sıralı konuşma akışı uygulama makalesinde bulunabilir.

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 Microsoft Copilot Studio'yu kullanmayı göz önünde bulundurun ve doğru copilot çözümünü seçme hakkında bilgi edinin.

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

Önkoşullar

Örnek kod hakkında

Örnek bot kullanıcıya bir dizi soru sorar, yanıtlarından bazılarını doğrular ve girdilerini kaydeder. Aşağıdaki diyagramda bot, kullanıcı profili ve konuşma akışı sınıfları arasındaki ilişki gösterilmektedir.

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

  • UserProfile Bot tarafından toplanacak kullanıcı bilgileri için bir sınıf.
  • ConversationFlow Kullanıcı bilgilerini toplarken konuşma durumumuzu denetleyebilmek için bir sınıf.
  • Konuşmanın neresinde olduğunuzu izlemek için bir iç ConversationFlow.Question numaralandırma.

Kullanıcı durumu kullanıcının adını, yaşını ve seçilen tarihini, konuşma durumu ise kullanıcıya en son ne sorduğunu izler. Bu botu dağıtmayı planlamadığınız için, kullanıcı ve konuşma durumunu bellek depolamayı kullanacak şekilde yapılandıracaksınız.

Konuşmanın akışını ve giriş koleksiyonunu yönetmek için botun ileti dönüş işleyicisinin yanı sıra kullanıcı ve konuşma durumu özelliklerini kullanırsınız. Botunuzda, ileti dönüş işleyicisinin her yinelemesi sırasında alınan durum özelliği bilgilerini kaydedeceksiniz.

Konuşma ve kullanıcı nesneleri oluşturma

Başlangıçta kullanıcı ve konuşma durumu nesnelerini oluşturun ve bot oluşturucusunda bağımlılık ekleme yoluyla bunları tüketin.

Startup.cs

// 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.
services.AddSingleton<UserState>();

// Create the Conversation state.
services.AddSingleton<ConversationState>();

Botlar/CustomPromptBot.cs

private readonly BotState _userState;
private readonly BotState _conversationState;

public CustomPromptBot(ConversationState conversationState, UserState userState)
{
    _conversationState = conversationState;
    _userState = userState;
}

Özellik erişimcileri oluşturma

Kullanıcı profili ve konuşma akışı özellikleri için özellik erişimcileri oluşturun ve ardından durumundan özellik değerini almak için çağrısı GetAsync yapın.

Botlar/CustomPromptBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var conversationStateAccessors = _conversationState.CreateProperty<ConversationFlow>(nameof(ConversationFlow));
    var flow = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationFlow(), cancellationToken);

    var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    var profile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile(), cancellationToken);

Dönüş bitmeden önce, depolamada durum değişikliklerini yazmak için çağrısı SaveChangesAsync yapın.

    await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}

İleti dönüş işleyicisi

İleti etkinliklerini işlerken, ileti işleyicisi konuşmayı yönetmek ve kullanıcıdan istemde bulunabilmek için bir yardımcı yöntemi kullanır. Yardımcı yöntemi aşağıdaki bölümde açıklanmıştır.

Botlar/CustomPromptBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    var conversationStateAccessors = _conversationState.CreateProperty<ConversationFlow>(nameof(ConversationFlow));
    var flow = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationFlow(), cancellationToken);

    var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));
    var profile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile(), cancellationToken);

    await FillOutUserProfileAsync(flow, profile, turnContext, cancellationToken);

    // Save changes.
    await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await _userState.SaveChangesAsync(turnContext, false, cancellationToken);
}

Kullanıcı profilini doldurma

Bot, kullanıcıdan bir önceki dönüşte sorduğu soruyu (varsa) temel alarak bilgi ister. Giriş bir doğrulama yöntemi kullanılarak ayrıştırılır.

Her doğrulama yöntemi benzer bir tasarıma sahiptir:

  • Dönüş değeri girişin bu soru için geçerli bir yanıt olup olmadığını gösterir.
  • Doğrulama başarılı olursa, kaydetmek için ayrıştırılmış ve normalleştirilmiş bir değer üretir.
  • Doğrulama başarısız olursa, botunun bilgileri yeniden isteyebileceği bir ileti oluşturur.

Doğrulama yöntemleri aşağıdaki bölümde açıklanmıştır.

Botlar/CustomPromptBot.cs

{
    var input = turnContext.Activity.Text?.Trim();
    string message;

    switch (flow.LastQuestionAsked)
    {
        case ConversationFlow.Question.None:
            await turnContext.SendActivityAsync("Let's get started. What is your name?", null, null, cancellationToken);
            flow.LastQuestionAsked = ConversationFlow.Question.Name;
            break;
        case ConversationFlow.Question.Name:
            if (ValidateName(input, out var name, out message))
            {
                profile.Name = name;
                await turnContext.SendActivityAsync($"Hi {profile.Name}.", null, null, cancellationToken);
                await turnContext.SendActivityAsync("How old are you?", null, null, cancellationToken);
                flow.LastQuestionAsked = ConversationFlow.Question.Age;
                break;
            }
            else
            {
                await turnContext.SendActivityAsync(message ?? "I'm sorry, I didn't understand that.", null, null, cancellationToken);
                break;
            }

        case ConversationFlow.Question.Age:
            if (ValidateAge(input, out var age, out message))
            {
                profile.Age = age;
                await turnContext.SendActivityAsync($"I have your age as {profile.Age}.", null, null, cancellationToken);
                await turnContext.SendActivityAsync("When is your flight?", null, null, cancellationToken);
                flow.LastQuestionAsked = ConversationFlow.Question.Date;
                break;
            }
            else
            {
                await turnContext.SendActivityAsync(message ?? "I'm sorry, I didn't understand that.", null, null, cancellationToken);
                break;
            }

        case ConversationFlow.Question.Date:
            if (ValidateDate(input, out var date, out message))
            {
                profile.Date = date;
                await turnContext.SendActivityAsync($"Your cab ride to the airport is scheduled for {profile.Date}.");
                await turnContext.SendActivityAsync($"Thanks for completing the booking {profile.Name}.");
                await turnContext.SendActivityAsync($"Type anything to run the bot again.");
                flow.LastQuestionAsked = ConversationFlow.Question.None;
                profile = new UserProfile();
                break;
            }
            else
            {
                await turnContext.SendActivityAsync(message ?? "I'm sorry, I didn't understand that.", null, null, cancellationToken);
                break;
            }
    }
}

Girişi ayrıştırma ve doğrulama

Bot, girişi doğrulamak için aşağıdaki ölçütleri kullanır.

  • Ad boş olmayan bir dize olmalıdır. Boşluk kırpılarak normalleştirilir.
  • Yaş 18 ile 120 arasında olmalıdır. Tamsayı döndürülerek normalleştirilir.
  • Tarih, gelecekte en az bir saat içinde herhangi bir tarih veya saat olmalıdır. Ayrıştırılan girişin yalnızca tarih bölümü döndürülerek normalleştirilir.

Not

Yaş ve tarih girişi için örnek, ilk ayrıştırma işlemini gerçekleştirmek için Microsoft/Recognizers-Text kitaplıklarını kullanır. Bu, girişi ayrıştırmak için yalnızca bir yoldur. Bu kitaplıklar hakkında daha fazla bilgi için projenin BENİOKU bölümüne bakın.

Botlar/CustomPromptBot.cs

private static bool ValidateName(string input, out string name, out string message)
{
    name = null;
    message = null;

    if (string.IsNullOrWhiteSpace(input))
    {
        message = "Please enter a name that contains at least one character.";
    }
    else
    {
        name = input.Trim();
    }

    return message is null;
}

private static bool ValidateAge(string input, out int age, out string message)
{
    age = 0;
    message = null;

    // Try to recognize the input as a number. This works for responses such as "twelve" as well as "12".
    try
    {
        // Attempt to convert the Recognizer result to an integer. This works for "a dozen", "twelve", "12", and so on.
        // The recognizer returns a list of potential recognition results, if any.

        var results = NumberRecognizer.RecognizeNumber(input, Culture.English);

        foreach (var result in results)
        {
            // The result resolution is a dictionary, where the "value" entry contains the processed string.
            if (result.Resolution.TryGetValue("value", out var value))
            {
                age = Convert.ToInt32(value);
                if (age >= 18 && age <= 120)
                {
                    return true;
                }
            }
        }

        message = "Please enter an age between 18 and 120.";
    }
    catch
    {
        message = "I'm sorry, I could not interpret that as an age. Please enter an age between 18 and 120.";
    }

    return message is null;
}

private static bool ValidateDate(string input, out string date, out string message)
{
    date = null;
    message = null;

    // Try to recognize the input as a date-time. This works for responses such as "11/14/2018", "9pm", "tomorrow", "Sunday at 5pm", and so on.
    // The recognizer returns a list of potential recognition results, if any.
    try
    {
        var results = DateTimeRecognizer.RecognizeDateTime(input, Culture.English);

        // Check whether any of the recognized date-times are appropriate,
        // and if so, return the first appropriate date-time. We're checking for a value at least an hour in the future.
        var earliest = DateTime.Now.AddHours(1.0);

        foreach (var result in results)
        {
            // The result resolution is a dictionary, where the "values" entry contains the processed input.
            var resolutions = result.Resolution["values"] as List<Dictionary<string, string>>;

            foreach (var resolution in resolutions)
            {
                // The processed input contains a "value" entry if it is a date-time value, or "start" and
                // "end" entries if it is a date-time range.
                if (resolution.TryGetValue("value", out var dateString)
                    || resolution.TryGetValue("start", out dateString))
                {
                    if (DateTime.TryParse(dateString, out var candidate)
                        && earliest < candidate)
                    {
                        date = candidate.ToShortDateString();
                        return true;
                    }
                }
            }
        }

        message = "I'm sorry, please enter a date at least an hour out.";
    }
    catch
    {
        message = "I'm sorry, I could not interpret that as an appropriate date. Please enter a date at least an hour out.";
    }

    return false;
}

Botu yerel olarak test edin

Botu yerel olarak test etmek için Bot Framework Emulator'ı indirin ve yükleyin.

  1. Örneği makinenizde yerel olarak çalıştırın. Yönergelere ihtiyacınız varsa C# örneği, JS örneği veya Python örneği için dosyaya bakınREADME.
  2. Öykünücü'yü kullanarak test edin.

Ek kaynaklar

İletişim Kutuları kitaplığı, konuşmaları yönetmenin birçok yönünü otomatik hale getiren sınıflar sağlar.

Sonraki adım