🐣

Azure環境でAIエージェントをつくる:Semantic Kernelの入門

に公開

はじめに

以前業務でLangGtaphを用いたAIエージェントを構築したのだが、今回は、Azureでも同じようなAIエージェントを構築できるフレームワークが存在するということで、調査してみました。

今後も、引き続き業務では、LLMとしてAzureOpenAIを利用することになるので、Microsoftが開発した
Semantic Kernelを学習しておこうと思います。

Semantic Kernelとは?

まずは、Semantic Kernelの概要から。

Semantic Kernelは、C#・Python・Java に対応した 軽量でオープンソースの SDK で、AI モデル(例:OpenAI、Azure OpenAI、Hugging Face)と既存のアプリケーションコードをシームレスに統合できるミドルウェアになります。
主な特徴としては以下の通りです。

  • マイクロソフト製でC#・Python・Java対応
  • モデル非依存な設計
  • プラグイン(Skills)を追加することで、独自の関数やAPIをAIが呼び出せる
  • 会話や知識を埋め込みベクトルとして保存し、AIが文脈や過去情報を参照可能
  • ユーザーの曖昧な指示から、必要な処理ステップをAIが自律的に計画して実行
  • シングルエージェントからマルチエージェントによる協調処理まで、柔軟に構築可能
  • エンタープライズ品質の設計である

コンポーネントの確認

実際にコードで確認する前に、各コンポーネントを簡単に確認しておきます。

  1. カーネル(Kernel)
    カーネルは、AIサービスやプラグイン、ログ、HTTP クライアントなどを統合的に管理します。
    プロンプト呼び出し時には、最適なモデル選択・テンプレート生成・AI呼び出し・レスポンス処理を一貫して実行します。

  2. プラグイン(Plugins)
    アプリケーションや外部 API の機能をカーネルに取り込むのが、プラグインになります。
    セマンティック関数(プロンプトベース)やネイティブ関数(従来のコード呼び出し)を登録し、AI から呼び出して自然に処理できるようになっています。

定義できるプラグインは以下の通り

  • Pythonで自作したコード関数(自前のクラス/メソッド)
  • OpenAPI プラグイン
  • MCP プラグイン
  • Azure Logic Apps
  1. メモリ(Memories)
    メモリは、埋め込みベースのベクトルストアを用いて、AI が文脈を保持・検索できる機能です。
    SemanticTextMemory や各種コネクタ経由で実装でき、プランナーや検索強化生成(RAG)などに活用されます。

  2. プランナー(Planner)
    Planner はユーザー指示を受けて、どのプラグイン関数をどのような順序で実行するかを自律的に計画・実行するAIオーケストレーション層です。

シングルエージェントの作成

システムの初期設定

まずは、カーネル(Kernel)に対してAIサービスを追加する処理を行い、追加したサービスを用いて Agentを作成し、実行する流れを見てみます。
(以下、.envファイルに環境設定を行っている前提のコードになっています)

  1. カーネルにAIサービスを追加
    Azure OpenAI の対話型(ChatCompletion)サービスを kernel.add_service(...) で登録し、LLMと連携できるようにします。
    これにより、カーネルが対話用AIモデルを操作できるようになります。
import os
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from dotenv import load_dotenv

# .envファイルの内容を読み込みます
load_dotenv()

# Kernel の初期化
kernel = Kernel()
kernel.add_service(AzureChatCompletion(
    service_id="agent1",
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
    endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
    deployment_name=os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME")
))
  1. ChatCompletionAgentの作成
    ChatCompletionAgentを生成し、instructions で専門性(ペルソナ)を設定します。
    例:「あなたは○○の専門家です」など。これにより、AIは一貫した応答スタイルや役割を持って振る舞います。
from semantic_kernel.agents import ChatCompletionAgent

# ChatCompletionAgentの作成
agent = ChatCompletionAgent(
    kernel=kernel,
    name="ExpertAssistant",
    instructions="あなたは親切でわかりやすく答える教育エージェントです。"
)
  1. 実行
    エージェントに質問を投げて応答を取得します。
import asyncio

async def main():
    response = await agent.get_response("AIの歴史を教えてください")
    print(response.content)

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

プラグインの登録と使用例

次に、プラグインを用意した上でカーネルに登録し、自動関数呼び出し(Function Calling)を行う手順を順に確認してみます。

  1. プラグイン定義
    今回は、以下の2つのプラグインを用意します。
  • TimePlugin: 現在のUTC時刻を返す関数。
  • WeatherPlugin: 指定都市の簡易天気情報を返す関数。

@kernel_function によって、これらのメソッドがSemantic Kernelに「関数」として登録されます。

import os
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion, AzureChatPromptExecutionSettings  # Azure を使う場合
from semantic_kernel.agents import ChatCompletionAgent

from semantic_kernel.functions import kernel_function
from semantic_kernel.functions import KernelArguments
from datetime import datetime, timezone
from typing import Annotated

from dotenv import load_dotenv
from semantic_kernel.contents import ChatHistory
import asyncio


# .envファイルの内容を読み込みます
load_dotenv()

class TimePlugin:
    @kernel_function(
        name="get_current_datetime",
        description="現在のUTCの日付と時刻を文字列として返します"
    )
    def get_current_datetime(self, agent_name: Annotated[str, "エージェント名"] = "Agent") -> Annotated[str, "例: '2025‑08‑02 15:04:23 UTC' を返します"]:
        now = datetime.now(timezone.utc)
        return now.strftime("%Y‑%m‑%d %H:%M:%S UTC")

class WeatherPlugin:
    @kernel_function(
        name="get_weather_for_city",
        description="指定された都市の簡単な天気予報を返します"
    )
    def get_weather_for_city(self, city: Annotated[str, "都市名"]) -> Annotated[str, "例: '東京: 晴れ 25°C' を返します"]:
        weather_map = {
            "東京": "東京: 晴れ 25°C",
            "ロンドン": "ロンドン: 曇り 18°C",
            "大阪": "大阪: 雨 22°C"
        }
        return weather_map.get(city, f"{city}: 天気情報は利用できません")
  1. Kernel初期化とプラグイン登録
    Kernelの初期化を行い、add_plugin(...)によって、定義済みのプラグインを登録し、AIが呼び出せるようにします。
async def main():
    # Kernel と AI サービスを初期化
    kernel = Kernel()
    kernel.add_service(AzureChatCompletion(
        endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
        api_key=os.getenv("AZURE_OPENAI_API_KEY"),
        deployment_name=os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME")
    ))

    #プラグインの登録
    kernel.add_plugin(TimePlugin(), plugin_name="time")
    kernel.add_plugin(WeatherPlugin(), plugin_name="weather")
  1. 自動関数呼び出し(Function Calling)の設定
    FunctionChoiceBehavior.Auto(...) により、AIモデルが必要に応じて関数を選んで呼び出す「自動関数呼び出し」を有効にします。
    filters にAIが利用可能な関数を書きます。
exec_settings = AzureChatPromptExecutionSettings()
exec_settings.function_choice_behavior = FunctionChoiceBehavior.Auto(
    filters={"included_plugins": ["time", "weather"]}
)
  1. 実行
    ユーザー入力+実行設定を渡してAIに質問を行います。
async def chat_loop(kernel, exec_settings):
    # カーネルに送信する構成を準備
    arguments = KernelArguments(settings=exec_settings)
    print("エージェントとの対話を開始します。終了するには Ctrl+C を押してください。")
    try:
        while True:
            user_input = input("You: ").strip()
            answer = await kernel.invoke_prompt(user_input, arguments=arguments)
            print(f"Agent:> {answer}")
    except (KeyboardInterrupt, EOFError):
        print("\n対話を終了します。Bye!")

if __name__ == "__main__":
    kernel, exec_settings = asyncio.run(main())
    try:
        asyncio.run(chat_loop(kernel, exec_settings))
    except (KeyboardInterrupt, EOFError):
        print("\nプログラムを終了します。")

実行結果は、以下の通り。

メモリで文脈と履歴を保つ方法

次に、ChatHistory を使用して、会話履歴の管理を行った結果を確認します。

  1. Kernel と AI サービスを初期化
import os
import asyncio
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
from semantic_kernel.contents import ChatHistory
from semantic_kernel.functions import KernelArguments
from semantic_kernel.connectors.ai.open_ai.prompt_execution_settings.azure_chat_prompt_execution_settings import AzureChatPromptExecutionSettings
from dotenv import load_dotenv

load_dotenv()

kernel = Kernel()
chat_completion = AzureChatCompletion(
    endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),
    deployment_name=os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME")
)
kernel.add_service(chat_completion)
  1. ChatHistory を使った会話履歴の管理
    ChatHistoryクラスを使うことで、ユーザーやサーバーとのメッセージを役割付きで記録・管理できます
execution_settings = AzureChatPromptExecutionSettings()
history = ChatHistory()
  1. 対話ループの作成と実行
async def chat_loop():
    print("対話を開始します(終了: Ctrl+C)")
    while True:
        user_input = input("You: ").strip()
        history.add_user_message(user_input)  # ユーザー発言を履歴に追加

        result = (await chat_completion.get_chat_message_contents(
            chat_history=history,
            settings=execution_settings,
            kernel=kernel,
            arguments=KernelArguments(),
        ))[0]

        assistant_text = str(result)  # 応答を文字列として取得
        print("Assistant >", assistant_text)

        history.add_message(result)  # AIの応答を履歴に追加

if __name__ == "__main__":
    try:
        asyncio.run(chat_loop())
    except (KeyboardInterrupt, EOFError):
        print("\n対話を終了しました。")

実行結果は、以下の通り。

まとめ

本記事では、Azure OpenAIを活用する業務向けAIエージェント構築の一環として、Microsoftが提供するSemantic Kernelを確認しました。

具体的には、単一エージェント環境での

  • KernelにAzure OpenAIサービスを登録し、エージェント作成・実行
  • プラグインの追加によるFunction‑Calling
  • ChatHistoryを用いた会話の文脈保持

を確認しました。

今後は、Agent Frameworkを活用したマルチエージェント構築を学びたいと考えています。さらに、 Process Framework を使って業務フローをAIで自動化するエージェントも確認していきます。

引き続き、Semantic Kernelの活用を模索したいと思います。

Discussion