ai-agents-for-beginners

AIエージェントフレームワークを探る

(上の画像をクリックして、このレッスンの動画をご覧ください)

AIエージェントフレームワークを探る

AIエージェントフレームワークは、AIエージェントの作成、展開、管理を簡素化するために設計されたソフトウェアプラットフォームです。これらのフレームワークは、開発者に事前構築されたコンポーネント、抽象化、ツールを提供し、複雑なAIシステムの開発を効率化します。

これらのフレームワークは、AIエージェント開発における一般的な課題に対する標準化されたアプローチを提供することで、開発者がアプリケーションの独自の側面に集中できるようにします。これにより、AIシステムのスケーラビリティ、アクセシビリティ、効率性が向上します。

はじめに

このレッスンでは以下を学びます:

学習目標

このレッスンの目標は以下を理解することです:

AIエージェントフレームワークとは何か、そしてそれが開発者に何を可能にするのか?

従来のAIフレームワークは、AIをアプリに統合し、以下の方法でアプリを改善するのに役立ちます:

素晴らしい話に聞こえますが、なぜAIエージェントフレームワークが必要なのでしょうか?

AIエージェントフレームワークは、単なるAIフレームワーク以上のものを提供します。これらは、特定の目標を達成するためにユーザー、他のエージェント、環境と対話できるインテリジェントエージェントの作成を可能にするよう設計されています。これらのエージェントは自律的な行動を示し、意思決定を行い、変化する条件に適応することができます。以下は、AIエージェントフレームワークによって可能になる主要な機能のいくつかです:

要するに、エージェントはより多くのことを可能にし、自動化を次のレベルに引き上げ、環境から学び適応するインテリジェントなシステムを作成することを可能にします。

エージェントの能力を迅速にプロトタイプ化、反復、改善する方法は?

この分野は急速に進化していますが、ほとんどのAIエージェントフレームワークに共通するいくつかの要素があります。それはモジュールコンポーネント、協力ツール、リアルタイム学習です。これらについて詳しく見ていきましょう:

モジュールコンポーネントを使用する

Microsoft Semantic KernelやLangChainのようなSDKは、AIコネクタ、プロンプトテンプレート、メモリ管理などの事前構築されたコンポーネントを提供します。

チームがこれらを使用する方法: チームはこれらのコンポーネントを迅速に組み立てて、ゼロから始めることなく機能的なプロトタイプを作成し、迅速な実験と反復を可能にします。

実際の動作: ユーザー入力から情報を抽出するための事前構築されたパーサー、データを保存および取得するためのメモリモジュール、ユーザーと対話するためのプロンプトジェネレーターを使用することで、これらのコンポーネントをゼロから構築する必要がありません。

コード例: Semantic Kernel Pythonと.Netを使用して、ユーザー入力に応答するモデルを自動関数呼び出しで動作させる事前構築されたAIコネクタの使用例を見てみましょう:

# Semantic Kernel Python Example

import asyncio
from typing import Annotated

from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, AzureChatPromptExecutionSettings
from semantic_kernel.contents import ChatHistory
from semantic_kernel.functions import kernel_function
from semantic_kernel.kernel import Kernel

# Define a ChatHistory object to hold the conversation's context
chat_history = ChatHistory()
chat_history.add_user_message("I'd like to go to New York on January 1, 2025")


# Define a sample plugin that contains the function to book travel
class BookTravelPlugin:
    """A Sample Book Travel Plugin"""

    @kernel_function(name="book_flight", description="Book travel given location and date")
    async def book_flight(
        self, date: Annotated[str, "The date of travel"], location: Annotated[str, "The location to travel to"]
    ) -> str:
        return f"Travel was booked to {location} on {date}"

# Create the Kernel
kernel = Kernel()

# Add the sample plugin to the Kernel object
kernel.add_plugin(BookTravelPlugin(), plugin_name="book_travel")

# Define the Azure OpenAI AI Connector
chat_service = AzureChatCompletion(
    deployment_name="YOUR_DEPLOYMENT_NAME", 
    api_key="YOUR_API_KEY", 
    endpoint="https://<your-resource>.azure.openai.com/",
)

# Define the request settings to configure the model with auto-function calling
request_settings = AzureChatPromptExecutionSettings(function_choice_behavior=FunctionChoiceBehavior.Auto())


async def main():
    # Make the request to the model for the given chat history and request settings
    # The Kernel contains the sample that the model will request to invoke
    response = await chat_service.get_chat_message_content(
        chat_history=chat_history, settings=request_settings, kernel=kernel
    )
    assert response is not None

    """
    Note: In the auto function calling process, the model determines it can invoke the 
    `BookTravelPlugin` using the `book_flight` function, supplying the necessary arguments. 
    
    For example:

    "tool_calls": [
        {
            "id": "call_abc123",
            "type": "function",
            "function": {
                "name": "BookTravelPlugin-book_flight",
                "arguments": "{'location': 'New York', 'date': '2025-01-01'}"
            }
        }
    ]

    Since the location and date arguments are required (as defined by the kernel function), if the 
    model lacks either, it will prompt the user to provide them. For instance:

    User: Book me a flight to New York.
    Model: Sure, I'd love to help you book a flight. Could you please specify the date?
    User: I want to travel on January 1, 2025.
    Model: Your flight to New York on January 1, 2025, has been successfully booked. Safe travels!
    """

    print(f"`{response}`")
    # Example AI Model Response: `Your flight to New York on January 1, 2025, has been successfully booked. Safe travels! ✈️🗽`

    # Add the model's response to our chat history context
    chat_history.add_assistant_message(response.content)


if __name__ == "__main__":
    asyncio.run(main())
// Semantic Kernel C# example

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using System.ComponentModel;
using Microsoft.SemanticKernel.Connectors.AzureOpenAI;

ChatHistory chatHistory = [];
chatHistory.AddUserMessage("I'd like to go to New York on January 1, 2025");

var kernelBuilder = Kernel.CreateBuilder();
kernelBuilder.AddAzureOpenAIChatCompletion(
    deploymentName: "NAME_OF_YOUR_DEPLOYMENT",
    apiKey: "YOUR_API_KEY",
    endpoint: "YOUR_AZURE_ENDPOINT"
);
kernelBuilder.Plugins.AddFromType<BookTravelPlugin>("BookTravel"); 
var kernel = kernelBuilder.Build();

var settings = new AzureOpenAIPromptExecutionSettings()
{
    FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};

var chatCompletion = kernel.GetRequiredService<IChatCompletionService>();

var response = await chatCompletion.GetChatMessageContentAsync(chatHistory, settings, kernel);

/*
Behind the scenes, the model recognizes the tool to call, what arguments it already has (location) and (date)
{

"tool_calls": [
    {
        "id": "call_abc123",
        "type": "function",
        "function": {
            "name": "BookTravelPlugin-book_flight",
            "arguments": "{'location': 'New York', 'date': '2025-01-01'}"
        }
    }
]
*/

Console.WriteLine(response.Content);
chatHistory.AddMessage(response!.Role, response!.Content!);

// Example AI Model Response: Your flight to New York on January 1, 2025, has been successfully booked. Safe travels! ✈️🗽

// Define a plugin that contains the function to book travel
public class BookTravelPlugin
{
    [KernelFunction("book_flight")]
    [Description("Book travel given location and date")]
    public async Task<string> BookFlight(DateTime date, string location)
    {
        return await Task.FromResult( $"Travel was booked to {location} on {date}");
    }
}

この例からわかるように、ユーザー入力から出発地、目的地、フライト予約リクエストの日付などの重要な情報を抽出するための事前構築されたパーサーを活用できます。このモジュールアプローチにより、高レベルのロジックに集中することが可能になります。

協力ツールを活用する

CrewAI、Microsoft AutoGen、Semantic Kernelのようなフレームワークは、複数のエージェントを作成して協力させることを容易にします。

チームがこれらを使用する方法: チームは特定の役割とタスクを持つエージェントを設計し、協力的なワークフローをテストして改善し、システム全体の効率を向上させます。

実際の動作: データ取得、分析、意思決定などの専門的な機能を持つエージェントのチームを作成できます。これらのエージェントは情報を共有し、ユーザーの問い合わせに答えたりタスクを完了したりする共通の目標を達成するために協力します。

コード例 (AutoGen):

# creating agents, then create a round robin schedule where they can work together, in this case in order

# Data Retrieval Agent
# Data Analysis Agent
# Decision Making Agent

agent_retrieve = AssistantAgent(
    name="dataretrieval",
    model_client=model_client,
    tools=[retrieve_tool],
    system_message="Use tools to solve tasks."
)

agent_analyze = AssistantAgent(
    name="dataanalysis",
    model_client=model_client,
    tools=[analyze_tool],
    system_message="Use tools to solve tasks."
)

# conversation ends when user says "APPROVE"
termination = TextMentionTermination("APPROVE")

user_proxy = UserProxyAgent("user_proxy", input_func=input)

team = RoundRobinGroupChat([agent_retrieve, agent_analyze, user_proxy], termination_condition=termination)

stream = team.run_stream(task="Analyze data", max_turns=10)
# Use asyncio.run(...) when running in a script.
await Console(stream)

前述のコードでは、複数のエージェントがデータを分析するタスクを協力して実行する方法を示しています。各エージェントは特定の機能を果たし、エージェント間の調整によって目的の結果を達成します。専用の役割を持つエージェントを作成することで、タスクの効率とパフォーマンスを向上させることができます。

リアルタイムで学ぶ

高度なフレームワークは、リアルタイムのコンテキスト理解と適応の機能を提供します。

チームがこれらを使用する方法: チームはフィードバックループを実装し、エージェントがインタラクションから学び、動的に行動を調整することで、能力の継続的な改善と洗練を実現します。

実際の動作: エージェントはユーザーフィードバック、環境データ、タスク結果を分析して知識ベースを更新し、意思決定アルゴリズムを調整し、時間とともにパフォーマンスを向上させます。この反復的な学習プロセスにより、エージェントは変化する条件やユーザーの好みに適応し、システム全体の効果を向上させます。

AutoGen、Semantic Kernel、Azure AI Agent Serviceのフレームワークの違いは?

これらのフレームワークを比較する方法は多くありますが、設計、機能、対象となるユースケースの観点からいくつかの重要な違いを見てみましょう:

AutoGen

AutoGenは、Microsoft ResearchのAI Frontiers Labによって開発されたオープンソースフレームワークです。イベント駆動型、分散型のエージェントアプリケーションに焦点を当てており、複数のLLMやSLM、ツール、高度なマルチエージェント設計パターンを可能にします。

AutoGenは、エージェントというコアコンセプトを中心に構築されています。エージェントは、自分の環境を認識し、意思決定を行い、特定の目標を達成するために行動を起こす自律的なエンティティです。エージェントは非同期メッセージを通じて通信し、独立して並行して動作することで、システムのスケーラビリティと応答性を向上させます。

エージェントはアクターモデルに基づいています。Wikipediaによれば、アクターは_並行計算の基本的な構成要素です。受信したメッセージに応じて、アクターは以下を行うことができます:ローカルな意思決定を行う、新しいアクターを作成する、さらにメッセージを送信する、次に受信するメッセージにどのように応答するかを決定する_。

ユースケース: コード生成の自動化、データ分析タスク、計画および研究機能のためのカスタムエージェントの構築。

以下はAutoGenの重要なコアコンセプトです:

以下はチャット機能を持つ独自のエージェントを作成する短いコードスニペットです:

```python
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.messages import TextMessage
from autogen_ext.models.openai import OpenAIChatCompletionClient


class MyAgent(RoutedAgent):
    def __init__(self, name: str) -> None:
        super().__init__(name)
        model_client = OpenAIChatCompletionClient(model="gpt-4o")
        self._delegate = AssistantAgent(name, model_client=model_client)

    @message_handler
    async def handle_my_message_type(self, message: MyMessageType, ctx: MessageContext) -> None:
        print(f"{self.id.type} received message: {message.content}")
        response = await self._delegate.on_messages(
            [TextMessage(content=message.content, source="user")], ctx.cancellation_token
        )
        print(f"{self.id.type} responded: {response.chat_message.content}")
```

前述のコードでは、MyAgentが作成され、RoutedAgentを継承しています。このエージェントにはメッセージハンドラーがあり、メッセージの内容を出力し、その後AssistantAgentデリゲートを使用して応答を送信します。特に注目すべき点は、self._delegateAssistantAgentのインスタンスを割り当てている点です。このエージェントはチャット完了を処理できる事前構築されたエージェントです。

次に、このエージェントタイプをAutoGenに知らせ、プログラムを開始します:

```python

# main.py
runtime = SingleThreadedAgentRuntime()
await MyAgent.register(runtime, "my_agent", lambda: MyAgent())

runtime.start()  # Start processing messages in the background.
await runtime.send_message(MyMessageType("Hello, World!"), AgentId("my_agent", "default"))
```

前述のコードでは、エージェントがランタイムに登録され、その後エージェントにメッセージが送信され、以下の出力が得られます:

```text
# Output from the console:
my_agent received message: Hello, World!
my_assistant received message: Hello, World!
my_assistant responded: Hello! How can I assist you today?
```

前述のコードでは、GroupChatManagerがランタイムに登録されています。このマネージャーは、ライター、イラストレーター、編集者、ユーザーなどの異なるタイプのエージェント間のやり取りを調整する役割を果たします。

Semantic Kernel + エージ

これらの事実は、メモリコレクションSummarizedAzureDocsに保存されます。これは非常に簡略化された例ですが、LLMが使用するための情報をメモリに保存する方法がわかります。

これがSemantic Kernelフレームワークの基本ですが、Agent Frameworkについてはどうでしょうか?

Azure AI Agent Service

Azure AI Agent Serviceは、Microsoft Ignite 2024で導入された比較的新しい追加機能です。これにより、Llama 3、Mistral、CohereなどのオープンソースLLMを直接呼び出すような、より柔軟なモデルを使用してAIエージェントを開発・展開することが可能になります。

Azure AI Agent Serviceは、より強力なエンタープライズセキュリティメカニズムとデータ保存方法を提供し、企業向けアプリケーションに適しています。

このサービスは、AutoGenやSemantic Kernelのようなマルチエージェントオーケストレーションフレームワークとすぐに連携して動作します。

現在、このサービスはPublic Preview段階にあり、PythonとC#を使用してエージェントを構築することができます。

Semantic Kernel Pythonを使用して、ユーザー定義のプラグインを持つAzure AI Agentを作成することができます:

import asyncio
from typing import Annotated

from azure.identity.aio import DefaultAzureCredential

from semantic_kernel.agents import AzureAIAgent, AzureAIAgentSettings, AzureAIAgentThread
from semantic_kernel.contents import ChatMessageContent
from semantic_kernel.contents import AuthorRole
from semantic_kernel.functions import kernel_function


# Define a sample plugin for the sample
class MenuPlugin:
    """A sample Menu Plugin used for the concept sample."""

    @kernel_function(description="Provides a list of specials from the menu.")
    def get_specials(self) -> Annotated[str, "Returns the specials from the menu."]:
        return """
        Special Soup: Clam Chowder
        Special Salad: Cobb Salad
        Special Drink: Chai Tea
        """

    @kernel_function(description="Provides the price of the requested menu item.")
    def get_item_price(
        self, menu_item: Annotated[str, "The name of the menu item."]
    ) -> Annotated[str, "Returns the price of the menu item."]:
        return "$9.99"


async def main() -> None:
    ai_agent_settings = AzureAIAgentSettings.create()

    async with (
        DefaultAzureCredential() as creds,
        AzureAIAgent.create_client(
            credential=creds,
            conn_str=ai_agent_settings.project_connection_string.get_secret_value(),
        ) as client,
    ):
        # Create agent definition
        agent_definition = await client.agents.create_agent(
            model=ai_agent_settings.model_deployment_name,
            name="Host",
            instructions="Answer questions about the menu.",
        )

        # Create the AzureAI Agent using the defined client and agent definition
        agent = AzureAIAgent(
            client=client,
            definition=agent_definition,
            plugins=[MenuPlugin()],
        )

        # Create a thread to hold the conversation
        # If no thread is provided, a new thread will be
        # created and returned with the initial response
        thread: AzureAIAgentThread | None = None

        user_inputs = [
            "Hello",
            "What is the special soup?",
            "How much does that cost?",
            "Thank you",
        ]

        try:
            for user_input in user_inputs:
                print(f"# User: '{user_input}'")
                # Invoke the agent for the specified thread
                response = await agent.get_response(
                    messages=user_input,
                    thread_id=thread,
                )
                print(f"# {response.name}: {response.content}")
                thread = response.thread
        finally:
            await thread.delete() if thread else None
            await client.agents.delete_agent(agent.id)


if __name__ == "__main__":
    asyncio.run(main())

コアコンセプト

Azure AI Agent Serviceには以下のコアコンセプトがあります:

ユースケース: Azure AI Agent Serviceは、セキュアでスケーラブル、柔軟なAIエージェント展開を必要とする企業向けアプリケーション向けに設計されています。

これらのフレームワークの違いは何ですか?

これらのフレームワークには多くの重複があるように聞こえますが、設計、機能、対象となるユースケースにおいていくつかの重要な違いがあります:

まだどれを選ぶべきか迷っていますか?

ユースケース

いくつかの一般的なユースケースを通じて、選択を助けましょう:

Q: 実験、学習、概念実証エージェントアプリケーションを構築しており、迅速に構築・実験したいです。

A: AutoGenはこのシナリオに適しています。イベント駆動型、分散型エージェントアプリケーションに焦点を当てており、高度なマルチエージェント設計パターンをサポートしています。

Q: このユースケースにおいて、AutoGenがSemantic KernelやAzure AI Agent Serviceよりも優れている理由は何ですか?

A: AutoGenはイベント駆動型、分散型エージェントアプリケーション向けに特別に設計されており、コード生成やデータ分析タスクの自動化に適しています。複雑なマルチエージェントシステムを効率的に構築するための必要なツールと機能を提供します。

Q: Azure AI Agent Serviceもここで使えるように思えます。コード生成などのツールもありますよね?

A: はい、Azure AI Agent Serviceはエージェント向けのプラットフォームサービスであり、複数のモデル、Azure AI Search、Bing Search、Azure Functionsの組み込み機能を追加しています。Foundry Portalでエージェントを簡単に構築し、スケール展開することができます。

Q: まだ混乱しています。一つの選択肢を教えてください。

A: 最初にSemantic Kernelでアプリケーションを構築し、その後Azure AI Agent Serviceを使用してエージェントを展開するのが良い選択肢です。このアプローチにより、Semantic Kernelでマルチエージェントシステムを構築する力を活用しながら、エージェントを簡単に永続化できます。さらに、Semantic KernelにはAutoGenとのコネクターがあり、両方のフレームワークを簡単に併用できます。

以下に主要な違いを表にまとめます:

フレームワーク 焦点 コアコンセプト ユースケース
AutoGen イベント駆動型、分散型エージェントアプリケーション エージェント、ペルソナ、関数、データ コード生成、データ分析タスク
Semantic Kernel 人間のようなテキスト内容の理解と生成 エージェント、モジュールコンポーネント、コラボレーション 自然言語理解、コンテンツ生成
Azure AI Agent Service 柔軟なモデル、エンタープライズセキュリティ、コード生成、ツール呼び出し モジュール性、コラボレーション、プロセスオーケストレーション セキュアでスケーラブル、柔軟なAIエージェント展開

各フレームワークの理想的なユースケースは何ですか?

既存のAzureエコシステムツールを直接統合できますか、それとも独立したソリューションが必要ですか?

答えは「はい」です。特にAzure AI Agent Serviceは、他のAzureサービスとシームレスに連携するように設計されているため、既存のAzureエコシステムツールを直接統合できます。例えば、Bing、Azure AI Search、Azure Functionsを統合することが可能です。また、Azure AI Foundryとの深い統合もあります。

AutoGenやSemantic KernelでもAzureサービスと統合できますが、コードからAzureサービスを呼び出す必要がある場合があります。もう一つの統合方法として、Azure SDKを使用してエージェントからAzureサービスと対話することができます。さらに、前述のように、AutoGenやSemantic Kernelで構築したエージェントのオーケストレーターとしてAzure AI Agent Serviceを使用することで、Azureエコシステムへの簡単なアクセスが可能になります。

AIエージェントフレームワークについてさらに質問がありますか?

Azure AI Foundry Discordに参加して、他の学習者と交流したり、オフィスアワーに参加したり、AIエージェントに関する質問に答えてもらいましょう。

参考資料

前のレッスン

AIエージェントとそのユースケースの紹介

次のレッスン

エージェント設計パターンの理解


免責事項:
この文書は、AI翻訳サービスCo-op Translatorを使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。