Поделиться через


Общие сведения о библиотеке ИИ Teams

Библиотека ИИ Teams поддерживает JavaScript и упрощает создание ботов, которые могут взаимодействовать с Microsoft Teams. Это также упрощает миграцию существующих ботов для использования функций на основе ИИ. Он поддерживает перенос сообщений, расширения сообщений и адаптивных карточек в новый формат. Вы также можете обновить существующие приложения Teams с помощью этих функций.

Ранее вы использовали пакет SDK BotBuilder для создания ботов для Teams. Библиотека ИИ Teams предназначена для упрощения этого процесса и включает поддержку ИИ. Изначально вы можете обновить бот без ИИ, но после обновления он может подключаться к ИИ или крупным языковым моделям (LLM), доступным в библиотеке ИИ.

С помощью библиотеки ИИ Teams можно сосредоточиться на:

Обработчики действий

Библиотека ИИ Teams поддерживает следующие обработчики действий:

Необходимо использовать библиотеку ИИ для формирования шаблонов бота и обработчиков адаптивных карточек в исходный файл. В последующих разделах мы использовали примеры из библиотеки ИИ , чтобы объяснить каждую возможность и путь к миграции.

Отправка или получение сообщения

Вы можете отправлять и получать сообщения с помощью Bot Framework. Приложение прослушивает сообщения пользователей, удаляет состояние беседы после получения и отвечает. Он также отслеживает количество сообщений в беседе и повторяет сообщение пользователя с подсчетом.

 // Listen for user to say "/reset" and then delete conversation state
    app.OnMessage("/reset", ActivityHandlers.ResetMessageHandler);

    // Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS
    app.OnActivity(ActivityTypes.Message, ActivityHandlers.MessageHandler);

    return app;

Расширения для обмена сообщениями

В пакете SDK TeamsActivityHandlerBot Framework настройте обработчик запросов расширений сообщений, расширив методы обработчика. Приложение прослушивает действия поиска и касания элементов. Он форматирует результаты поиска как карточки главного героя, отображая сведения о пакете, и отображает их в расширении обмена сообщениями.

// Listen for search actions
    app.MessageExtensions.OnQuery("searchCmd", activityHandlers.QueryHandler);
    // Listen for item tap
    app.MessageExtensions.OnSelectItem(activityHandlers.SelectItemHandler);

    return app;

 // Format search results in ActivityHandlers.cs

            List<MessagingExtensionAttachment> attachments = packages.Select(package => new MessagingExtensionAttachment
            {
                ContentType = HeroCard.ContentType,
                Content = new HeroCard
                {
                    Title = package.Id,
                    Text = package.Description
                },
                Preview = new HeroCard
                {
                    Title = package.Id,
                    Text = package.Description,
                    Tap = new CardAction
                    {
                        Type = "invoke",
                        Value = package
                    }
                }.ToAttachment()
            }).ToList();

            // Return results as a list

            return new MessagingExtensionResult
            {
                Type = "result",
                AttachmentLayout = "list",
                Attachments = attachments
            };

Возможности адаптивных карточек

Регистрация обработчиков действий адаптивной карточки app.adaptiveCards с помощью свойства . Приложение прослушивает сообщения с static ключевыми словами или dynamic и возвращает адаптивную карточку с помощью StaticMessageHandler() или DynamicMessageHandler(). Он также прослушивает запросы из динамического карта поиска и кнопок отправки.

// Listen for messages that trigger returning an adaptive card
    app.OnMessage(new Regex(@"static", RegexOptions.IgnoreCase), activityHandlers.StaticMessageHandler);
    app.OnMessage(new Regex(@"dynamic", RegexOptions.IgnoreCase), activityHandlers.DynamicMessageHandler);

    // Listen for query from dynamic search card
    app.AdaptiveCards.OnSearch("nugetpackages", activityHandlers.SearchHandler);
    // Listen for submit buttons
    app.AdaptiveCards.OnActionSubmit("StaticSubmit", activityHandlers.StaticSubmitHandler);
    app.AdaptiveCards.OnActionSubmit("DynamicSubmit", activityHandlers.DynamicSubmitHandler);

    // Listen for ANY message to be received. MUST BE AFTER ANY OTHER HANDLERS
    app.OnActivity(ActivityTypes.Message, activityHandlers.MessageHandler);

    return app;

Логика бота для обработки действия

Бот реагирует на входные данные пользователя действием LightsOn по включению света.

В следующем примере показано, как библиотека ИИ Teams позволяет управлять логикой бота для обработки действия LightsOn или LightsOff подключать ее к запросу, используемому с OpenAI:

/ Create AI Model
if (!string.IsNullOrEmpty(config.OpenAI?.ApiKey))
{
    builder.Services.AddSingleton<OpenAIModel>(sp => new(
        new OpenAIModelOptions(config.OpenAI.ApiKey, "gpt-3.5-turbo")
        {
            LogRequests = true
        },
        sp.GetService<ILoggerFactory>()
    ));
}
else if (!string.IsNullOrEmpty(config.Azure?.OpenAIApiKey) && !string.IsNullOrEmpty(config.Azure.OpenAIEndpoint))
{
    builder.Services.AddSingleton<OpenAIModel>(sp => new(
        new AzureOpenAIModelOptions(
            config.Azure.OpenAIApiKey,
            "gpt-35-turbo",
            config.Azure.OpenAIEndpoint
        )
        {
            LogRequests = true
        },
        sp.GetService<ILoggerFactory>()
    ));
}
else
{
    throw new Exception("please configure settings for either OpenAI or Azure");
}

// Create the bot as transient. In this case the ASP Controller is expecting an IBot.
builder.Services.AddTransient<IBot>(sp =>
{
    // Create loggers
    ILoggerFactory loggerFactory = sp.GetService<ILoggerFactory>()!;

    // Create Prompt Manager
    PromptManager prompts = new(new()
    {
        PromptFolder = "./Prompts"
    });

    // Adds function to be referenced in the prompt template
    prompts.AddFunction("getLightStatus", async (context, memory, functions, tokenizer, args) =>
    {
        bool lightsOn = (bool)(memory.GetValue("conversation.lightsOn") ?? false);
        return await Task.FromResult(lightsOn ? "on" : "off");
    });

    // Create ActionPlanner
    ActionPlanner<AppState> planner = new(
        options: new(
            model: sp.GetService<OpenAIModel>()!,
            prompts: prompts,
            defaultPrompt: async (context, state, planner) =>
            {
                PromptTemplate template = prompts.GetPrompt("sequence");
                return await Task.FromResult(template);
            }
        )
        { LogRepairs = true },
        loggerFactory: loggerFactory
    );

    return new TeamsLightBot(new()
    {
        Storage = sp.GetService<IStorage>(),
        AI = new(planner),
        LoggerFactory = loggerFactory,
        TurnStateFactory = () =>
        {
            return new AppState();
        }
    });
});

// LightBotActions defined in LightBotActions.cs
    
[Action("LightsOn")]
        public async Task<string> LightsOn([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState)
        {
            turnState.Conversation.LightsOn = true;
            await turnContext.SendActivityAsync(MessageFactory.Text("[lights on]"));
            return "the lights are now on";
        }

        [Action("LightsOff")]
        public async Task<string> LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] AppState turnState)
        {
            turnState.Conversation.LightsOn = false;
            await turnContext.SendActivityAsync(MessageFactory.Text("[lights off]"));
            return "the lights are now off";
        }

        [Action("Pause")]
        public async Task<string> LightsOff([ActionTurnContext] ITurnContext turnContext, [ActionParameters] Dictionary<string, object> args)
        {
            // Try to parse entities returned by the model.
            // Expecting "time" to be a number of milliseconds to pause.
            if (args.TryGetValue("time", out object? time))
            {
                if (time != null && time is string timeString)
                {
                    if (int.TryParse(timeString, out int timeInt))
                    {
                        await turnContext.SendActivityAsync(MessageFactory.Text($"[pausing for {timeInt / 1000} seconds]"));
                        await Task.Delay(timeInt);
                    }
                }
            }

            return "done pausing";
        }

Запрос расширения сообщений

Библиотека ИИ Teams предоставляет более интуитивно понятный способ создания обработчиков для команд запросов расширения сообщений, работающих вместе с существующим пакетом SDK Для Teams Bot Framework.

Ниже приведен пример структуры кода для обработки запроса расширения сообщения для searchCmd команды .

// Listen for search actions
    app.MessageExtensions.OnQuery("searchCmd", activityHandlers.QueryHandler);
    // Listen for item tap
    app.MessageExtensions.OnSelectItem(activityHandlers.SelectItemHandler);

    return app;

 // Format search results
            List<MessagingExtensionAttachment> attachments = packages.Select(package => new MessagingExtensionAttachment
            {
                ContentType = HeroCard.ContentType,
                Content = new HeroCard
                {
                    Title = package.Id,
                    Text = package.Description
                },
                Preview = new HeroCard
                {
                    Title = package.Id,
                    Text = package.Description,
                    Tap = new CardAction
                    {
                        Type = "invoke",
                        Value = package
                    }
                }.ToAttachment()
            }).ToList();

            return new MessagingExtensionResult
            {
                Type = "result",
                AttachmentLayout = "list",
                Attachments = attachments
            };

Намерения действий

Простой интерфейс для действий и прогнозов позволяет ботам уверенно реагировать. Внешнее присутствие помогает ботам изучать намерения, использовать запросы на основе бизнес-логики и генерировать ответы. С помощью библиотеки ИИ Teams в командной строке описываются действия бота и приводятся примеры.

Журнал бесед обеспечивает естественный диалог, например добавление хлопьев в список продуктов, а затем добавление кофе, указывающее, что кофе должен быть добавлен в список.

Ниже приведен диалог с помощник ИИ. ИИ помощник может управлять списками и распознает следующие команды:

  • ДЕЛАТЬ <action> <optional entities>
  • СКАЗАТЬ <response>

Поддерживаются следующие действия:

  • addItem list="<list name>" item="<text>"
  • removeItem list="<list name>" item="<text>"
  • summarizeLists

Все сущности являются обязательными параметрами для действий.

  • Имена текущих списков:

    {{conversation.listNames}} 
    
    
    Examples:  
    
    Human: remind me to buy milk
    AI: DO addItem list="groceries" item="milk" THEN SAY Ok I added milk to your groceries list
    Human: we already have milk
    AI: DO removeItem list="groceries" item="milk" THEN SAY Ok I removed milk from your groceries list
    Human: buy ingredients to make margaritas
    AI: DO addItem list="groceries" item="tequila" THEN DO addItem list="groceries" item="orange liqueur" THEN DO addItem list="groceries" item="lime juice" THEN SAY Ok I added tequila, orange liqueur, and lime juice to your groceries list
    Human: do we have milk
    AI: DO findItem list="groceries" item="milk"
    Human: what's in my grocery list
    AI: DO summarizeLists  
    Human: what's the contents of all my lists?
    AI: DO summarizeLists
    Human: show me all lists but change the title to Beach Party
    AI: DO summarizeLists
    Human: show me all lists as a card and sort the lists alphabetically
    AI: DO summarizeLists
    
    
  • Журнал бесед:

    {{conversation.(history}} 
    
  • Текущий запрос:

    Human: {{activity.text}} 
    
  • Имена текущих списков:

    {{conversation.listNames}}
    
  • ИИ. Логика бота оптимизирована для включения обработчиков для таких действий, как addItem и removeItem. Это различие между действиями и запросами служит мощным инструментом, поскольку он направляет ИИ для выполнения действий и запросов.

        [Action("AddItem")]
        public string AddItem([ActionTurnState] ListState turnState, [ActionParameters] Dictionary<string, object> parameters)
        {
            ArgumentNullException.ThrowIfNull(turnState);
            ArgumentNullException.ThrowIfNull(parameters);

            string listName = GetParameterString(parameters, "list");
            string item = GetParameterString(parameters, "item");

            IList<string> items = GetItems(turnState, listName);
            items.Add(item);
            SetItems(turnState, listName, items);

            return "item added. think about your next action";
        }

        [Action("RemoveItem")]
        public async Task<string> RemoveItem([ActionTurnContext] ITurnContext turnContext, [ActionTurnState] ListState turnState, [ActionParameters] Dictionary<string, object> parameters)
        {
            ArgumentNullException.ThrowIfNull(turnContext);
            ArgumentNullException.ThrowIfNull(turnState);
            ArgumentNullException.ThrowIfNull(parameters);

            string listName = GetParameterString(parameters, "list");
            string item = GetParameterString(parameters, "item");

            IList<string> items = GetItems(turnState, listName);

            if (!items.Contains(item))
            {
                await turnContext.SendActivityAsync(ResponseBuilder.ItemNotFound(listName, item)).ConfigureAwait(false);
                return "item not found. think about your next action";
            }

            items.Remove(item);
            SetItems(turnState, listName, items);
            return "item removed. think about your next action";
        }

Следующее действие