Megosztás a következőn keresztül:


Saját kérések létrehozása felhasználói bemenetek gyűjtéséhez

A KÖVETKEZŐKRE VONATKOZIK: SDK v4

A robotok és a felhasználók közötti beszélgetések gyakran magukban foglalják a felhasználó információkérését (kérését), a felhasználó válaszának elemzését, majd az információk alapján történő cselekvést. A robotnak nyomon kell követnie egy beszélgetés kontextusát, hogy kezelni tudja a viselkedését, és emlékezzen a korábbi kérdésekre adott válaszokra. A robot állapota olyan információ, amelyet nyomon követ, hogy megfelelően válaszoljon a bejövő üzenetekre.

Tipp.

A párbeszédpaneltár beépített utasításokat biztosít, amelyek további funkciókat biztosítanak a felhasználók számára. Ezekre a kérdésekre példákat az Implement szekvenciális beszélgetési folyamat című cikkben talál.

Feljegyzés

A Bot Framework JavaScript, C# és Python SDK-k továbbra is támogatottak lesznek, a Java SDK-t azonban 2023 novemberében végső hosszú távú támogatással kivonják.

A Java SDK-val létrehozott meglévő robotok továbbra is működni fognak.

Az új robotépítéshez fontolja meg a Microsoft Copilot Studio használatát, és olvassa el a megfelelő copilot-megoldás kiválasztását.

További információ: A robotépítés jövője.

Előfeltételek

  • A jelen cikkben szereplő kód a Felhasználók kérése bemeneti mintán alapul. Szüksége lesz a C#-minta, a JavaScript-minta, a Java-minta vagy a Python-minta másolatára.
  • Az állapot kezelésének és a felhasználói és beszélgetési adatok mentésének ismerete.

A mintakód ismertetése

A mintarobot kérdések sorozatát kérdezi fel a felhasználótól, ellenőrzi a válaszok egy részét, és menti a bemenetét. Az alábbi ábra a robot, a felhasználói profil és a beszélgetési folyamat osztályai közötti kapcsolatot mutatja be.

A C#-minta osztálydiagramja.

  • A UserProfile robot által gyűjtött felhasználói adatok osztálya.
  • Egy ConversationFlow osztály, amely szabályozza a beszélgetés állapotát a felhasználói adatok összegyűjtése közben.
  • Belső ConversationFlow.Question számbavétel a beszélgetés helyének nyomon követéséhez.

A felhasználói állapot nyomon követi a felhasználó nevét, életkorát és választott dátumát, a beszélgetés állapota pedig nyomon követi, hogy mit kért a felhasználótól. Mivel nem tervezi üzembe helyezni ezt a robotot, a felhasználó és a beszélgetés állapotát úgy fogja konfigurálni, hogy memóriatárolót használjon.

A robot üzenetkonfiguráció-kezelőjét, valamint a felhasználói és beszélgetési állapot tulajdonságait használva kezelheti a beszélgetés folyamatát és a bemenetek gyűjteményét. A robotban rögzíteni fogja az üzenetkontraszt kezelőjének minden iterációja során kapott állapottulajdonság-adatokat.

Beszélgetés és felhasználói objektumok létrehozása

Hozza létre a felhasználó- és beszélgetésállapot-objektumokat indításkor, és használja fel őket függőséginjektáláson keresztül a robotkonstruktorban.

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

Robotok/CustomPromptBot.cs

private readonly BotState _userState;
private readonly BotState _conversationState;

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

Tulajdonságkiegészítők létrehozása

Hozzon létre tulajdonság-tartozékokat a felhasználói profil és a beszélgetési folyamat tulajdonságaihoz, majd hívja meg GetAsync a tulajdonság értékét az állapotból.

Robotok/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);

Mielőtt a forduló véget ér, hívja meg SaveChangesAsync , hogy írjon bármilyen állapotváltozást a tárolóba.

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

Üzenetkontraszt kezelője

Üzenettevékenységek kezelésekor az üzenetkezelő segédmetódussal kezeli a beszélgetést, és kéri a felhasználót. A segédmetódus leírása a következő szakaszban található.

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

A felhasználói profil kitöltése

A robot információt kér a felhasználótól, amely alapján a robot az előző fordulóban feltett kérdés alapján kérdezett rá. A bemenet egy érvényesítési módszerrel van elemezve.

Minden érvényesítési módszer hasonló kialakítást követ:

  • A visszatérési érték azt jelzi, hogy a bemenet érvényes válasz-e erre a kérdésre.
  • Ha az ellenőrzés sikeres, elemzési és normalizált értéket hoz létre a mentéshez.
  • Ha az ellenőrzés sikertelen, egy üzenetet hoz létre, amellyel a robot újra kérheti az információkat.

Az érvényesítési módszereket a következő szakaszban ismertetjük.

Robotok/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;
            }
    }
}

Bemenet elemzése és ellenőrzése

A robot a következő feltételek alapján ellenőrzi a bemenetet.

  • A névnek nem üres sztringnek kell lennie. Normalizálódik a térköz levágásával.
  • Az életkornak 18 és 120 év közöttinek kell lennie. Egy egész szám visszaadásával normalizálódik.
  • A dátumnak bármilyen dátumnak vagy időpontnak kell lennie, legalább egy órával később. Normalizálva van, ha csak az elemzési bemenet dátumrészét adja vissza.

Feljegyzés

A kor- és dátumbemenethez a minta a Microsoft/Recognizers-Text kódtárakat használja a kezdeti elemzés végrehajtásához. Ez csak egy módja a bemenet elemzésének. Ezekről a kódtárakról további információt a projekt README című témakörében talál.

Robotok/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;
}

A robot helyi tesztelése

Töltse le és telepítse a Bot Framework Emulatort a robot helyi teszteléséhez.

  1. Futtassa a mintát helyileg a számítógépen. Ha útmutatásra van szüksége, tekintse meg a README C#-mintához, a JS-mintához vagy a Python-mintához tartozó fájlt.
  2. Tesztelje az Emulator használatával.

További erőforrások

A Párbeszédpanelek kódtár olyan osztályokat biztosít, amelyek automatizálják a beszélgetések kezelésének számos aspektusát.

Következő lépés