次の方法で共有


Teams AI ライブラリについて

Teams AI ライブラリは JavaScript をサポートし、Microsoft Teamsと対話できるボットの構築を簡素化します。 また、AI を利用した機能を使用するための既存のボットの移行も容易になります。 このライブラリでは、メッセージング、メッセージ拡張機能、アダプティブ カードの機能を新しい形式に移行できます。 これらの機能を使用して、既存の Teams アプリをアップグレードすることもできます。

以前は、BotBuilder SDK を使用して Teams 用のボットを作成しました。 Teams AI ライブラリは、このプロセスを容易にするように設計されており、組み込みの AI サポートが含まれています。 最初は、AI なしでボットをアップグレードすることもできますが、アップグレードした後は、AI ライブラリで使用できる AI または大規模な言語モデル (LLM) に接続できます。

Teams AI ライブラリでは、次の点に重点を置くことができます。

アクティビティ ハンドラー

Teams AI ライブラリでは、次のアクティビティ ハンドラーがサポートされています。

AI ライブラリを使用して、ソース ファイル内のボットとアダプティブ カード ハンドラーをスキャフォールディングする必要があります。 以降のセクションでは、 AI ライブラリ のサンプルを使用して、各機能と移行パスについて説明します。

メッセージの送受信

この機能は、Bot Framework を使用してメッセージを送受信する方法を示しています。 このサンプルでは、ユーザー メッセージをリッスンし、受信時に会話状態を削除し、会話内のメッセージ数を追跡し、ユーザーのメッセージをカウントでエコーバックします。

.NET コード サンプル

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

メッセージ拡張機能

このセクションでは、Bot Framework SDK の TeamsActivityHandlerでメッセージ拡張機能を設定する方法について説明します。 このサンプルは、アプリが検索アクションと項目タップをリッスンする方法を示しています。 検索結果は、パッケージ情報を表示するヒーロー カードとして書式設定され、メッセージング拡張機能に表示されます。

.NET コード サンプル

// 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()を使用してアダプティブ カードを返します。 また、アプリは動的検索カードからのクエリと送信ボタン アクションをリッスンします。

.NET コード サンプル

// 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 AI ライブラリが、特に OpenAI を使用して応答を求める場合に、 LightsOnLightsOff などのアクションをマッピングしてボット ロジックを管理する方法を示しています。

.NET コード サンプル

/ 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 AI ライブラリは、メッセージ拡張クエリ コマンドのハンドラーを直感的に作成する方法を提供します。 この機能は、既存の Teams Bot Framework SDK と共に機能します。

次の例は、 searchCmd コマンドのメッセージ拡張クエリを処理するコードを構成する方法を示しています。

.NET コード サンプル

// 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 AI ライブラリがアクションを予測にマッピングするためのシンプルなインターフェイスを使用して、ボットがユーザーの意図に自信を持って反応できるようにする方法について説明します。 アンビエント プレゼンスは、ボットが意図を学習し、ビジネス ロジック プロンプトを適用し、応答を生成するのに役立ちます。 提供された例では、ボットは自然な会話を介してリストを管理し、コマンドを認識します。

人間と AI アシスタント間の会話構造には、次のものが含まれます。

  • する <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}}
    
  • AI: ボット ロジックは、 addItemremoveItemなどのアクションのハンドラーによって合理化されます。 アクションとプロンプトのこの違いにより、AI が正しい操作を実行するように誘導されます。

.NET コード サンプル

            [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";
            }

次の手順