Share via


Konuşmanın süresi dolduğunda

ŞUNLAR IÇIN GEÇERLIDIR: SDK v4

Botların bazen konuşmayı en baştan yeniden başlatması gerekir. Örneğin, bir kullanıcı belirli bir süre sonra yanıt vermezse. Bu makalede konuşmanın süresinin dolması için iki yöntem açıklanmaktadır:

  • Bir kullanıcıdan iletinin en son ne zaman alındığını izleyin ve kullanıcıdan sonraki iletiyi aldıktan sonra süre önceden yapılandırılmış bir uzunluktan uzunsa durumu temizleyin. Daha fazla bilgi için kullanıcı etkileşimi süre sonu bölümüne bakın.
  • Önceden yapılandırılmış bir sürenin ardından durumu otomatik olarak temizlemek için Cosmos DB Yaşam Süresi (TTL) gibi bir depolama katmanı özelliği kullanın. Daha fazla bilgi için depolama süre sonu bölümüne 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

Bu makaledeki örnek kod, çok dönüşlü bir botun yapısıyla başlar ve ek kod ekleyerek (aşağıdaki bölümlerde sağlanır) bu botun işlevselliğini genişletir. Bu genişletilmiş kod, belirli bir süre geçtikten sonra konuşma durumunun nasıl temizlendiğini gösterir.

Kullanıcı Etkileşimi Süre Sonu

Bu süre sonu konuşması türü, botun konuşma durumuna son erişilen zaman özelliği eklenerek gerçekleştirilir. Bu özellik değeri daha sonra etkinlikleri işlemeden önce etkinlik işleyicisi içindeki geçerli saatle karşılaştırılır.

Not

Bu örnekte, bu düzeni test etme kolaylığı için 30 saniyelik bir zaman aşımı kullanılır.

appsettings.json

İlk olarak, appsettings.json için bir ExpireAfterSeconds ayar ekleyin:

{
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",
  "ExpireAfterSeconds": 30
}

Botlar\DialogBot.cs

Ardından , ve DialogStateProperty alanlarını bot sınıfına ekleyin ExpireAfterSecondsLastAccessedTimePropertyve bot oluşturucusunda başlatın. Ayrıca, değerin alındığı ExpireAfterSeconds oluşturucuya bir IConfiguration parametre ekleyin.

yönteminde satır içi iletişim durumu özellik erişimcisini OnMessageActivityAsync oluşturmak yerine başlatma sırasında oluşturup kaydediyorsunuz. Bot, yalnızca iletişim kutusunu çalıştırmak için değil, aynı zamanda iletişim durumunu temizlemek için de durum özelliği erişimcisine ihtiyaç duyar.

protected readonly int ExpireAfterSeconds;
protected readonly IStatePropertyAccessor<DateTime> LastAccessedTimeProperty;
protected readonly IStatePropertyAccessor<DialogState> DialogStateProperty;

// Existing fields omitted...

public DialogBot(IConfiguration configuration, ConversationState conversationState, UserState userState, T dialog, ILogger<DialogBot<T>> logger)
{
    ConversationState = conversationState;
    UserState = userState;
    Dialog = dialog;
    Logger = logger;

    ExpireAfterSeconds = configuration.GetValue<int>("ExpireAfterSeconds");
    DialogStateProperty = ConversationState.CreateProperty<DialogState>(nameof(DialogState));
    LastAccessedTimeProperty = ConversationState.CreateProperty<DateTime>(nameof(LastAccessedTimeProperty));
}

Son olarak, konuşma çok eskiyse iletişim durumunu temizlemek için botunun OnTurnAsync yöntemine kod ekleyin.

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
{
    // Retrieve the property value, and compare it to the current time.
    var lastAccess = await LastAccessedTimeProperty.GetAsync(turnContext, () => DateTime.UtcNow, cancellationToken).ConfigureAwait(false);
    if ((DateTime.UtcNow - lastAccess) >= TimeSpan.FromSeconds(ExpireAfterSeconds))
    {
        // Notify the user that the conversation is being restarted.
        await turnContext.SendActivityAsync("Welcome back!  Let's start over from the beginning.").ConfigureAwait(false);

        // Clear state.
        await ConversationState.ClearStateAsync(turnContext, cancellationToken).ConfigureAwait(false);
    }

    await base.OnTurnAsync(turnContext, cancellationToken).ConfigureAwait(false);

    // Set LastAccessedTime to the current time.
    await LastAccessedTimeProperty.SetAsync(turnContext, DateTime.UtcNow, cancellationToken).ConfigureAwait(false);

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

Depolama Süre Sonu

Cosmos DB, belirli bir zaman aralığından sonra kapsayıcıdan öğeleri otomatik olarak silmenize olanak tanıyan bir Yaşam Süresi (TTL) özelliği sağlar. Bu, Azure portalından veya kapsayıcı oluşturma sırasında (dile özgü Cosmos DB SDK'ları kullanılarak) yapılandırılabilir.

Bot Framework SDK'sı TTL yapılandırma ayarını kullanıma sunmaz. Ancak kapsayıcı başlatma geçersiz kılınabilir ve Cosmos DB SDK'sı Bot Framework depolama başlatmadan önce TTL'yi yapılandırmak için kullanılabilir.

Çok aşamalı istem örneğinin yeni bir kopyasıyla başlayın ve NuGet paketini projeye ekleyinMicrosoft.Bot.Builder.Azure.

appsettings.json

Cosmos DB depolama seçeneklerini içerecek şekilde appsettings.json güncelleştirin:

{
  "MicrosoftAppId": "",
  "MicrosoftAppPassword": "",

  "CosmosDbTimeToLive": 30,
  "CosmosDbEndpoint": "<endpoint-for-your-cosmosdb-instance>",
  "CosmosDbAuthKey": "<your-cosmosdb-auth-key>",
  "CosmosDbDatabaseId": "<your-database-id>",
  "CosmosDbUserStateContainerId": "<no-ttl-container-id>",
  "CosmosDbConversationStateContainerId": "<ttl-container-id>"
}

biri için ve ConversationStatebiri için UserState olan iki ContainerId'ye dikkat edin. Varsayılan TTL kapsayıcıda ConversationState ayarlanır, ancak üzerinde UserStateayarlanmaz.

CosmosDb Depolama InitializerHostedService.cs

Ardından, yapılandırılan Yaşam Süresi ile kapsayıcıyı oluşturacak bir CosmosDbStorageInitializerHostedService sınıf oluşturun.

// Add required using statements...

public class CosmosDbStorageInitializerHostedService : IHostedService
{
    readonly CosmosDbPartitionedStorageOptions _storageOptions;
    readonly int _cosmosDbTimeToLive;

    public CosmosDbStorageInitializerHostedService(IConfiguration config)
    {
        _storageOptions = new CosmosDbPartitionedStorageOptions()
        {
            CosmosDbEndpoint = config["CosmosDbEndpoint"],
            AuthKey = config["CosmosDbAuthKey"],
            DatabaseId = config["CosmosDbDatabaseId"],
            ContainerId = config["CosmosDbConversationStateContainerId"]
        };

        _cosmosDbTimeToLive = config.GetValue<int>("CosmosDbTimeToLive");
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        using (var client = new CosmosClient(
            _storageOptions.CosmosDbEndpoint,
            _storageOptions.AuthKey,
            _storageOptions.CosmosClientOptions ?? new CosmosClientOptions()))
        {
            // Create the contaier with the provided TTL
            var containerResponse = await client
                .GetDatabase(_storageOptions.DatabaseId)
                .DefineContainer(_storageOptions.ContainerId, "/id")
                .WithDefaultTimeToLive(_cosmosDbTimeToLive)
                .WithIndexingPolicy().WithAutomaticIndexing(false).Attach()
                .CreateIfNotExistsAsync(_storageOptions.ContainerThroughput)
                .ConfigureAwait(false);
        }
    }

    public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

Startup.cs

Son olarak, depolama başlatıcısını kullanacak şekilde güncelleştirin Startup.cs ve durum için Cosmos DB'yi kullanın:

// Existing code omitted...

// commented out MemoryStorage, since we are using CosmosDbPartitionedStorage instead
// services.AddSingleton<IStorage, MemoryStorage>();

// Add the Initializer as a HostedService (so it's called during the app service startup)
services.AddHostedService<CosmosDbStorageInitializerHostedService>();

// Create the storage options for User state
var userStorageOptions = new CosmosDbPartitionedStorageOptions()
{
    CosmosDbEndpoint = Configuration["CosmosDbEndpoint"],
    AuthKey = Configuration["CosmosDbAuthKey"],
    DatabaseId = Configuration["CosmosDbDatabaseId"],
    ContainerId = Configuration["CosmosDbUserStateContainerId"]
};

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

// Create the storage options for Conversation state
var conversationStorageOptions = new CosmosDbPartitionedStorageOptions()
{
    CosmosDbEndpoint = Configuration["CosmosDbEndpoint"],
    AuthKey = Configuration["CosmosDbAuthKey"],
    DatabaseId = Configuration["CosmosDbDatabaseId"],
    ContainerId = Configuration["CosmosDbConversationStateContainerId"]
};

// Create the Conversation state. (Used by the Dialog system itself.)
services.AddSingleton(new ConversationState(new CosmosDbPartitionedStorage(conversationStorageOptions)));

// Existing code omitted...

Cosmos DB artık 30 saniye etkinlik dışı kalma süresinden sonra konuşma durumu kayıtlarını otomatik olarak silecektir.

Daha fazla bilgi için bkz . Azure Cosmos DB'de yaşam süresini yapılandırma

Botu test etmek için

  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. Öykünücüyü başlatın, botunuza bağlanın ve ileti gönderin.
  4. İstemlerden birinin ardından, yanıt vermeden önce 30 saniye bekleyin.