Partilhar via


Crie seus próprios prompts para coletar a entrada do usuário

APLICA-SE A: SDK v4

Uma conversa entre um bot e um usuário geralmente envolve pedir (solicitar) informações ao usuário, analisar a resposta do usuário e, em seguida, agir com base nessas informações. Seu bot deve acompanhar o contexto de uma conversa, para que possa gerenciar seu comportamento e lembrar as respostas a perguntas anteriores. O estado de um bot é a informação que ele rastreia para responder adequadamente às mensagens recebidas.

Gorjeta

A biblioteca de diálogos fornece prompts integrados que oferecem mais funcionalidades que os utilizadores podem aproveitar. Exemplos desses prompts podem ser encontrados no artigo Implementar o fluxo de conversa sequencial.

Nota

Para criar agentes com sua escolha de serviços, orquestração e conhecimento de IA, considere usar o SDK de agentes do Microsoft 365. O SDK de agentes tem suporte para C#, JavaScript ou Python. Você pode saber mais sobre o SDK de agentes em aka.ms/agents. Se você estiver procurando por uma plataforma de agente baseada em SaaS, considere o Microsoft Copilot Studio. Se você tiver um bot existente criado com o SDK do Bot Framework, poderá atualizar seu bot para o SDK de agentes. Você pode revisar as principais alterações e atualizações nas diretrizes de migração do SDK do Bot Framework para o SDK de agentes. Os tíquetes de suporte para o SDK do Bot Framework não serão mais atendidos a partir de 31 de dezembro de 2025.

Pré-requisitos

Sobre o código de exemplo

O bot de exemplo faz ao usuário uma série de perguntas, valida algumas de suas respostas e salva suas entradas. O diagrama a seguir mostra a relação entre o bot, o perfil de usuário e as classes de fluxo de conversa.

Diagrama de classes para o exemplo de C#.

  • Uma UserProfile classe para as informações do usuário que o bot coletará.
  • Uma ConversationFlow classe para controlar nosso estado de conversação enquanto coleta informações do usuário.
  • Uma enumeração interna ConversationFlow.Question para rastrear onde você está na conversa.

O estado do usuário rastreará o nome, a idade e a data escolhida do usuário, e o estado da conversa rastreará o que você perguntou pela última vez ao usuário. Dado que não planeias implantar esse bot, vais configurar o estado do utilizador e da conversa para usar armazenamento de memória.

Você usa o manipulador de turno de mensagens do bot mais as propriedades de estado de usuário e conversa para gerenciar o fluxo da conversa e a coleta de entrada. Em seu bot, você registrará as informações de propriedade de estado recebidas durante cada iteração do manipulador de turno de mensagem.

Criar objetos de conversação e de utilizador

Crie os objetos de estado de usuário e conversação na inicialização e consuma-os por meio da injeção de dependência no construtor de bot.

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

Bots/CustomPromptBot.cs

private readonly BotState _userState;
private readonly BotState _conversationState;

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

Criar acessos a propriedades

Crie acessores para as propriedades do perfil de utilizador e do fluxo de conversa e, em seguida, chame GetAsync para recuperar o valor da propriedade do estado.

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

Antes que o turno termine, ligue SaveChangesAsync para gravar quaisquer alterações de estado no armazenamento.

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

Gestor de turno de mensagens

Ao manipular atividades de mensagem, o manipulador de mensagens usa um método auxiliar para gerenciar a conversa e avisar o usuário. O método auxiliar é descrito na seção a seguir.

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

Preenchimento do perfil de utilizador

O bot solicita informações ao usuário, com base em qual pergunta, se houver, que o bot fez no turno anterior. A entrada é analisada usando um método de validação.

Cada método de validação segue um desenho semelhante:

  • O valor de retorno indica se a entrada é uma resposta válida para essa pergunta.
  • Se a validação for aprovada, ela produzirá um valor analisado e normalizado para salvar.
  • Se a validação falhar, ele produzirá uma mensagem com a qual o bot pode pedir as informações novamente.

Os métodos de validação são descritos na seção a seguir.

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

Analise e valide a entrada

O bot usa os seguintes critérios para validar a entrada.

  • O nome deve ser uma cadeia de caracteres não vazia. É normalizado cortando espaços em branco.
  • A idade deve ter entre 18 e 120 anos . É normalizado retornando um inteiro.
  • A data deve ser qualquer data ou hora pelo menos uma hora à frente. Ele é normalizado retornando apenas a parte de data da entrada analisada.

Nota

Para a entrada de idade e data, o exemplo usa as bibliotecas Microsoft/Recognizers-Text para executar a análise inicial. Esta é apenas uma maneira de analisar a entrada. Para obter mais informações sobre essas bibliotecas, consulte o README do projeto.

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

Teste o bot localmente

Baixe e instale o Bot Framework Emulator para testar o bot localmente.

  1. Execute a amostra localmente na sua máquina. Se você precisar de instruções, consulte o README arquivo para o exemplo C#, o exemplo JS ou o exemplo Python.
  2. Teste-o usando o emulador.

Recursos adicionais

A biblioteca Diálogos fornece classes que automatizam muitos aspetos do gerenciamento de conversas.

Próximo passo