Share via


Kullanıcı kesintilerini işleme

ŞUNLAR IÇIN GEÇERLIDIR: SDK v4

Kesintileri işleme, güçlü bir botun önemli bir yönüdür. Kullanıcılar her zaman tanımlı konuşma akışınızı adım adım izlemez. İşlemin ortasında bir soru sormayı deneyebilir veya yalnızca tamamlamak yerine iptal etmek isteyebilirler. Bu makalede, botunuzda kullanıcı kesintilerini işlemenin bazı yaygın yolları açıklanmaktadır.

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

Çekirdek bot örneği, kullanıcı amaçlarını tanımlamak için Language Understanding (LUIS) kullanır; ancak bu makalenin odak noktası kullanıcı amacını belirlemek değildir. Kullanıcı amaçlarını belirleme hakkında bilgi için bkz . Doğal dil anlama ve Botunuza doğal dil anlama ekleme.

Not

Language Understanding (LUIS) 1 Ekim 2025'te kullanımdan kaldırılacaktır. 1 Nisan 2023'e kadar yeni LUIS kaynakları oluşturamayacaksınız. Dil anlamanın daha yeni bir sürümü artık Azure AI Dili'nin bir parçası olarak kullanılabilir.

Azure AI Dili'nin bir özelliği olan konuşma dili anlama (CLU), LUIS'in güncelleştirilmiş sürümüdür. Bot Framework SDK'sında dil anlama desteği hakkında daha fazla bilgi için bkz . Doğal dil anlama.

Bu örnek hakkında

Bu makalede kullanılan örnek, kullanıcıdan uçuş bilgilerini almak için iletişim kutularını kullanan bir uçuş rezervasyon botunu modellemektedir. Kullanıcı, botla konuşma sırasında herhangi bir zamanda kesintiye neden olmak için yardım verebilir veya komutları iptal edebilir. İşlenen iki tür kesinti vardır:

  • Dönüş düzeyi: dönüş düzeyinde işlemeyi atlar, ancak sağlanan bilgilerle birlikte iletişim kutusunu yığında bırakın. Sonraki dönüşte, konuşmanın kaldığı yerden devam edin.
  • İletişim kutusu düzeyi: Botun baştan başlayabilmesi için işlemi tamamen iptal edin.

Kesinti mantığını tanımlama ve uygulama

İlk olarak, yardımı tanımlayıp uygulayın ve kesintileri iptal edin.

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

İletişim Kutuları\CancelAndHelpDialog.cs

Kullanıcı kesintilerini işlemek için sınıfını CancelAndHelpDialog uygulayın. İptal edilebilir iletişim kutuları BookingDialog ve DateResolverDialog bu sınıftan türetilir.

public class CancelAndHelpDialog : ComponentDialog

CancelAndHelpDialog sınıfında yöntemi, OnContinueDialogAsync kullanıcının normal akışı kesintiye uğratıp kesintiye uğratmadığını denetlemek için yöntemini çağırırInterruptAsync. Akış kesintiye uğrarsa temel sınıf yöntemleri çağrılır; aksi takdirde değerinden InterruptAsync döndürülen değer döndürülür.

protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
{
    var result = await InterruptAsync(innerDc, cancellationToken);
    if (result != null)
    {
        return result;
    }

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

Kullanıcı "help" (yardım) InterruptAsync yazın, yöntemi bir ileti gönderir ve ardından üstteki iletişim kutusunun kullanıcıdan yanıt beklediğini belirtmek için çağrısında DialogTurnResult (DialogTurnStatus.Waiting) bulunur. Bu şekilde, konuşma akışı yalnızca bir dönüş için kesilir ve bir sonraki dönüş konuşmanın kaldığı yerden devam eder.

Kullanıcı "iptal" oluşturursa, iletişim kutusu yığınını temizleyen ve iptal edilmiş bir durumla ve sonuç değeri olmadan çıkmasına neden olan iç iletişim kutusu bağlamını çağırır CancelAllDialogsAsync . MainDialog (daha sonra gösterilen) için, rezervasyon iletişim kutusunun sona erdiği ve kullanıcı rezervasyonunu onaylamamayı seçtiğinde olduğu gibi null döndürdüğünü göreceksiniz.

private async Task<DialogTurnResult> InterruptAsync(DialogContext innerDc, CancellationToken cancellationToken)
{
    if (innerDc.Context.Activity.Type == ActivityTypes.Message)
    {
        var text = innerDc.Context.Activity.Text.ToLowerInvariant();

        switch (text)
        {
            case "help":
            case "?":
                var helpMessage = MessageFactory.Text(HelpMsgText, HelpMsgText, InputHints.ExpectingInput);
                await innerDc.Context.SendActivityAsync(helpMessage, cancellationToken);
                return new DialogTurnResult(DialogTurnStatus.Waiting);

            case "cancel":
            case "quit":
                var cancelMessage = MessageFactory.Text(CancelMsgText, CancelMsgText, InputHints.IgnoringInput);
                await innerDc.Context.SendActivityAsync(cancelMessage, cancellationToken);
                return await innerDc.CancelAllDialogsAsync(cancellationToken);
        }
    }

    return null;
}

Her dönüşte kesinti olup olmadığını denetleyin

Kesme işleme sınıfı uygulandıktan sonra, bu bot kullanıcıdan yeni bir ileti aldığında ne olduğunu gözden geçirin.

İletişim Kutuları\MainDialog.cs

Yeni ileti etkinliği geldikçe bot çalıştırır MainDialog. Kullanıcıdan MainDialog yardımcı olabileceği şeyleri ister. Ardından yönteminde MainDialog.ActStepAsync öğesini aşağıda gösterildiği gibi çağrısıyla BeginDialogAsync başlatırBookingDialog.

private async Task<DialogTurnResult> ActStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    if (!_luisRecognizer.IsConfigured)
    {
        // LUIS is not configured, we just run the BookingDialog path with an empty BookingDetailsInstance.
        return await stepContext.BeginDialogAsync(nameof(BookingDialog), new BookingDetails(), cancellationToken);
    }

    // Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
    var luisResult = await _luisRecognizer.RecognizeAsync<FlightBooking>(stepContext.Context, cancellationToken);
    switch (luisResult.TopIntent().intent)
    {
        case FlightBooking.Intent.BookFlight:
            await ShowWarningForUnsupportedCities(stepContext.Context, luisResult, cancellationToken);

            // Initialize BookingDetails with any entities we may have found in the response.
            var bookingDetails = new BookingDetails()
            {
                // Get destination and origin from the composite entities arrays.
                Destination = luisResult.ToEntities.Airport,
                Origin = luisResult.FromEntities.Airport,
                TravelDate = luisResult.TravelDate,
            };

            // Run the BookingDialog giving it whatever details we have from the LUIS call, it will fill out the remainder.
            return await stepContext.BeginDialogAsync(nameof(BookingDialog), bookingDetails, cancellationToken);

        case FlightBooking.Intent.GetWeather:
            // We haven't implemented the GetWeatherDialog so we just display a TODO message.
            var getWeatherMessageText = "TODO: get weather flow here";
            var getWeatherMessage = MessageFactory.Text(getWeatherMessageText, getWeatherMessageText, InputHints.IgnoringInput);
            await stepContext.Context.SendActivityAsync(getWeatherMessage, cancellationToken);
            break;

        default:
            // Catch all for unhandled intents
            var didntUnderstandMessageText = $"Sorry, I didn't get that. Please try asking in a different way (intent was {luisResult.TopIntent().intent})";
            var didntUnderstandMessage = MessageFactory.Text(didntUnderstandMessageText, didntUnderstandMessageText, InputHints.IgnoringInput);
            await stepContext.Context.SendActivityAsync(didntUnderstandMessage, cancellationToken);
            break;
    }

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

Ardından, sınıfın FinalStepAsync yönteminde MainDialog rezervasyon iletişim kutusu sona erdi ve rezervasyon tamamlanmış veya iptal edilmiş olarak kabul edilir.

private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // If the child dialog ("BookingDialog") was cancelled, the user failed to confirm or if the intent wasn't BookFlight
    // the Result here will be null.
    if (stepContext.Result is BookingDetails result)
    {
        // Now we have all the booking details call the booking service.

        // If the call to the booking service was successful tell the user.

        var timeProperty = new TimexProperty(result.TravelDate);
        var travelDateMsg = timeProperty.ToNaturalLanguage(DateTime.Now);
        var messageText = $"I have you booked to {result.Destination} from {result.Origin} on {travelDateMsg}";
        var message = MessageFactory.Text(messageText, messageText, InputHints.IgnoringInput);
        await stepContext.Context.SendActivityAsync(message, cancellationToken);
    }

    // Restart the main dialog with a different message the second time around
    var promptMessage = "What else can I do for you?";
    return await stepContext.ReplaceDialogAsync(InitialDialogId, promptMessage, cancellationToken);
}

'deki BookingDialog kod, kesinti işlemeyle doğrudan ilgili olmadığından burada gösterilmez. Kullanıcılardan rezervasyon ayrıntılarını istemesi için kullanılır. Bu kodu Dialogs\BookingDialogs.cs içinde bulabilirsiniz.

Beklenmeyen hataları işleme

Bağdaştırıcının hata işleyicisi, botta yakalanmamış özel durumları işler.

AdapterWithErrorHandler.cs

Örnekte, bağdaştırıcının OnTurnError işleyicisi botunuzun dönüş mantığı tarafından oluşan özel durumları alır. Bir özel durum oluşursa, işleyici botunun hatalı durumda olmasından kaynaklanan bir hata döngüsünde takılmasını önlemek için geçerli konuşmanın konuşma durumunu siler.

    {
        // Log any leaked exception from the application.
        // NOTE: In production environment, you should consider logging this to
        // Azure Application Insights. Visit https://aka.ms/bottelemetry to see how
        // to add telemetry capture to your bot.
        logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");

        // Send a message to the user
        var errorMessageText = "The bot encountered an error or bug.";
        var errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.IgnoringInput);
        await turnContext.SendActivityAsync(errorMessage);

        errorMessageText = "To continue to run this bot, please fix the bot source code.";
        errorMessage = MessageFactory.Text(errorMessageText, errorMessageText, InputHints.ExpectingInput);
        await turnContext.SendActivityAsync(errorMessage);

        if (conversationState != null)
        {
            try
            {
                // Delete the conversationState for the current conversation to prevent the
                // bot from getting stuck in a error-loop caused by being in a bad state.
                // ConversationState should be thought of as similar to "cookie-state" in a Web pages.
                await conversationState.DeleteAsync(turnContext);
            }
            catch (Exception e)
            {
                logger.LogError(e, $"Exception caught on attempting to Delete ConversationState : {e.Message}");
            }
        }

        // Send a trace activity, which will be displayed in the Bot Framework Emulator
        await turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError");
    };
}

Hizmetleri kaydetme

Startup.cs

Son olarak, içinde Startup.csbot geçici olarak oluşturulur ve her dönüşte botun yeni bir örneği oluşturulur.


// Register the BookingDialog.

Başvuru için, yukarıdaki botu oluşturmak için çağrıda kullanılan sınıf tanımları aşağıdadır.

public class DialogAndWelcomeBot<T> : DialogBot<T>
public class DialogBot<T> : ActivityHandler
    where T : Dialog
public class MainDialog : ComponentDialog

Botu test edin

  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.

Ek bilgi

  • C#, JavaScript, Python veya Java'daki24.bot-authentication-msgraph örneği, bir oturumu kapatma isteğinin nasıl işleneceğini gösterir. Kesintileri işlemek için burada gösterilene benzer bir desen kullanır.

  • Hiçbir şey yapmak yerine varsayılan bir yanıt göndermeniz ve kullanıcıyı neler olup bittiğini merak etmesi için bırakmanız gerekir. Varsayılan yanıt, kullanıcının yeniden çalışmaya devam edebilmesi için kullanıcıya botunun hangi komutları anladığını göstermelidir.

  • Sıranın herhangi bir noktasında, dönüş bağlamın yanıtlanan özelliği botunun kullanıcıya bu dönüşte bir ileti gönderip göndermediğini gösterir. Dönüş bitmeden önce botunuz, girişlerinin basit bir bildirimi olsa bile kullanıcıya ileti göndermelidir.