Spara användar- och konversationsdata

GÄLLER FÖR: SDK v4

En robot är i sig tillståndslös. När roboten har distribuerats kanske den inte körs i samma process eller på samma dator från en tur till en annan. Din robot kan dock behöva spåra kontexten för en konversation så att den kan hantera sitt beteende och komma ihåg svar på tidigare frågor. Med tillstånds- och lagringsfunktionerna i Bot Framework SDK kan du lägga till tillstånd i roboten. Robotar använder tillståndshanterings- och lagringsobjekt för att hantera och bevara tillstånd. Tillståndshanteraren tillhandahåller ett abstraktionslager som gör att du kan komma åt tillståndsegenskaper med hjälp av egenskapsåtkomster, oberoende av typen av underliggande lagring.

Kommentar

Bot Framework JavaScript-, C#- och Python-SDK:erna fortsätter att stödjas, men Java SDK dras tillbaka med slutligt långsiktigt stöd som slutar i november 2023. Endast kritiska säkerhets- och felkorrigeringar på den här lagringsplatsen utförs.

Befintliga robotar som skapats med Java SDK fortsätter att fungera.

Om du vill skapa en ny robot bör du överväga att använda Power Virtual Agents och läsa om hur du väljer rätt chattrobotlösning.

Mer information finns i Framtiden för robotbygge.

Förutsättningar

Om det här exemplet

När du tar emot användarindata kontrollerar det här exemplet det lagrade konversationstillståndet för att se om användaren tidigare har uppmanats att ange sitt namn. Annars begärs användarens namn och indata lagras i användartillstånd. I så fall används namnet som lagras i användartillståndet för att samtala med användaren och deras indata, tillsammans med den tid som tas emot och indatakanal-ID, returneras tillbaka till användaren. Värdena för tids- och kanal-ID hämtas från användarkonversationens data och sparas sedan i konversationstillstånd. Följande diagram visar relationen mellan roboten, användarprofilen och konversationsdataklasserna.

Definiera klasser

Det första steget i att konfigurera tillståndshantering är att definiera de klasser som innehåller den information som ska hanteras i användar- och konversationstillståndet. Exemplet som används i den här artikeln definierar följande klasser:

  • I UserProfile.cs definierar du en UserProfile klass för den användarinformation som roboten ska samla in.
  • I ConversationData.cs definierar du en ConversationData klass för att styra vårt konversationstillstånd när du samlar in användarinformation.

Följande kodexempel visar definitionerna för klasserna UserProfile och ConversationData .

UserProfile.cs

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

ConversationData.cs

public class ConversationData
{
    // The time-stamp of the most recent incoming message.
    public string Timestamp { get; set; }

    // The ID of the user's channel.
    public string ChannelId { get; set; }

    // Track whether we have already asked the user's name
    public bool PromptedUserForName { get; set; } = false;
}

Skapa konversations- och användartillståndsobjekt

Därefter registrerar MemoryStorage du som används för att skapa UserState och ConversationState objekt. Användar- och konversationstillståndsobjekt skapas vid Startup och beroendet matas in i robotkonstruktorn. Andra tjänster för en robot som är registrerad är: en autentiseringsprovider, ett kort och robotimplementeringen.

Startup.cs

// {
//     TypeNameHandling = TypeNameHandling.All,
// var storage = new BlobsStorage("<blob-storage-connection-string>", "bot-state");

// With a custom JSON SERIALIZER, use this instead.
// var storage = new BlobsStorage("<blob-storage-connection-string>", "bot-state", jsonSerializer);

/* END AZURE BLOB STORAGE */

Bots/StateManagementBot.cs

private BotState _conversationState;
private BotState _userState;

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

Lägga till tillståndsegenskapsåtkomster

Nu skapar du egenskapsåtkomster med hjälp av metoden CreateProperty som tillhandahåller ett handtag till BotState objektet. Med varje tillståndsegenskapsåtkomst kan du hämta eller ange värdet för den associerade tillståndsegenskapen. Innan du använder tillståndsegenskaperna använder du varje accessor för att läsa in egenskapen från lagringen och hämta den från tillståndscacheminnet. Om du vill hämta rätt omfångsnyckel som är associerad med tillståndsegenskapen GetAsync anropar du metoden.

Bots/StateManagementBot.cs

var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
var userStateAccessors = _userState.CreateProperty<UserProfile>(nameof(UserProfile));

Åtkomsttillstånd från din robot

Föregående avsnitt beskriver initieringstidsstegen för att lägga till tillståndsegenskapsåtkomster till roboten. Nu kan du använda dessa åtkomster vid körning för att läsa och skriva tillståndsinformation. Exempelkoden nedan använder följande logikflöde:

  • Om userProfile.Name är tomt och conversationData.PromptedUserForName är sant hämtar du det angivna användarnamnet och lagrar det i användartillstånd.
  • Om userProfile.Name är tomt och conversationData.PromptedUserForName är falskt ber du om användarens namn.
  • Om userProfile.Name har lagrats tidigare hämtar du meddelandetid och kanal-ID från användarens indata, upprepar alla data tillbaka till användaren och lagrar hämtade data i konversationstillstånd.

Bots/StateManagementBot.cs

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    // Get the state properties from the turn context.

    var conversationStateAccessors = _conversationState.CreateProperty<ConversationData>(nameof(ConversationData));
    var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData());

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

    if (string.IsNullOrEmpty(userProfile.Name))
    {
        // First time around this is set to false, so we will prompt user for name.
        if (conversationData.PromptedUserForName)
        {
            // Set the name to what the user provided.
            userProfile.Name = turnContext.Activity.Text?.Trim();

            // Acknowledge that we got their name.
            await turnContext.SendActivityAsync($"Thanks {userProfile.Name}. To see conversation data, type anything.");

            // Reset the flag to allow the bot to go through the cycle again.
            conversationData.PromptedUserForName = false;
        }
        else
        {
            // Prompt the user for their name.
            await turnContext.SendActivityAsync($"What is your name?");

            // Set the flag to true, so we don't prompt in the next turn.
            conversationData.PromptedUserForName = true;
        }
    }
    else
    {
        // Add message details to the conversation data.
        // Convert saved Timestamp to local DateTimeOffset, then to string for display.
        var messageTimeOffset = (DateTimeOffset)turnContext.Activity.Timestamp;
        var localMessageTime = messageTimeOffset.ToLocalTime();
        conversationData.Timestamp = localMessageTime.ToString();
        conversationData.ChannelId = turnContext.Activity.ChannelId.ToString();

        // Display state data.
        await turnContext.SendActivityAsync($"{userProfile.Name} sent: {turnContext.Activity.Text}");
        await turnContext.SendActivityAsync($"Message received at: {conversationData.Timestamp}");
        await turnContext.SendActivityAsync($"Message received from: {conversationData.ChannelId}");
    }
}

Innan du avslutar turhanteraren använder du tillståndshanteringsobjektens SaveChangesAsync() -metod för att skriva tillbaka alla tillståndsändringar till lagringen.

Bots/StateManagementBot.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);
}

Testa din robot

  1. Ladda ned och installera den senaste Bot Framework-emulatorn
  2. Kör exemplet lokalt på datorn. Om du behöver instruktioner kan du läsa README för C#, JavaScript, Java eller Python.
  3. Använd emulatorn för att testa exempelroboten.

Ytterligare information

I den här artikeln beskrivs hur du kan lägga till tillstånd i roboten. Mer information om relaterade ämnen finns i följande tabell.

Ämnesnamn OBS!
Sekretess Om du tänker lagra användarens personuppgifter bör du se till att den följer den allmänna dataskyddsförordningen.
Tillståndshantering Alla tillståndshanteringsanrop är asynkrona och senaste skriv-vinner som standard. I praktiken bör du hämta, ange och spara tillstånd så nära varandra i roboten som möjligt. En diskussion om hur du implementerar optimistisk låsning finns i Implementera anpassad lagring för din robot.
Viktiga affärsdata Använd robottillstånd för att lagra inställningar, användarnamn eller det sista de beställde, men använd det inte för att lagra viktiga affärsdata. För kritiska data skapar du egna lagringskomponenter eller skriver direkt till lagringen.
Recognizer-Text Exemplet använder Biblioteken Microsoft/Recognizers-Text för att parsa och verifiera användarindata. Mer information finns på översiktssidan.

Nästa steg

Lär dig hur du ställer en rad frågor till användaren, validerar deras svar och sparar indata.