NTT DATA TECH

1:Semantic KernelでAIエージェントを作ろう!

に公開

前置き

株式会社NTTデータグループの技術革新統括本部AI技術部でSmart AI Agent™のエンジニアをしている岸川です。

AIエージェント開発に便利な Semantic Kernel(セマンティック カーネル/以下SK) を使い、OpenAI APIと組み合わせて会話型エージェントを作る手順をまとめてみました。

Semantic Kernelとは?

Semantic Kernel(セマンティック カーネル、以下SK) は、Microsoftが提供するオープンソースの AIエージェント開発用SDK です。さまざまなLLM(大規模言語モデル)を使ってプラグイン(関数呼び出し)プロンプトテンプレート会話履歴管理エージェント(単体/複数) などを組み込んだアプリを容易に実装できます。

Semantic Kernelを使う利点

1) プラグイン機能で外部システムと容易に連携可能

Semantic Kernel(以下SK)のプラグインは、関数群をAIに"ツール"として登録する仕組みです。登録された関数は「関数呼び出し(function/tool calling)」を通じてAIから利用可能となり、エージェントは会話の文脈に応じて必要なツールを自律的に選択・実行できます。

2) プロンプトテンプレートで指示を再利用

SKには組み込みのプロンプトテンプレート言語があり、変数埋め込み外部関数呼び出しパラメータ受け渡しがシンプルな構文で書けます。

3) マルチエージェントで複雑タスクを分担

SKのエージェントフレームワークを使うと、複数のエージェント協調してタスクを進める構成を簡単に作れます。オーケストレーションのパターン(順次、並列、グループ会話など)が整備されており、複雑な業務フローにも対応可能です。(※一部はプレリリース段階)

4) 会話履歴管理

  • 会話履歴管理(ChatHistory):ユーザー/アシスタントの発話やシステムメッセージを保持し、文脈を維持できます。これによりマルチターンの会話が可能なアプリを作成できます。

Semantic Kernel + OpenAI API でエージェントを作ってみよう!

概要

ゴール

このハンズオンでは、Semantic KernelOpenAI API を使って、外部APIを通じてランダムな励ましの言葉を取得し、ユーザーの相談に応じたアドバイスを返す会話型エージェントを作ります。

Google Colab 上で動作するPythonスクリプトを通して、以下を学べます。

  • Semantic Kernelの基本構造と役割(Kernel・サービス・プラグイン)
  • OpenAIのChat APIとの連携方法
  • プラグインを使った外部API呼び出し
  • 会話履歴を保持しながら応答を生成するエージェント設計

想定読者

  • 対象:プログラミング初級〜中級
  • 前提:Python基礎文法

必要なもの

  • OpenAI APIキー(環境変数で設定)
  • Google アカウント(Colab実行のため)
  • Google Colab の基本操作(新規ノートブック作成/セル実行など)

環境情報

項目 バージョン/詳細
実行環境 Google Colab
Python 3.11系
semantic-kernel 1.35系
openai 1.99系

今回作るエージェントの全体像

今回作るエージェントは、以下のような流れで動作します:

  1. ユーザー入力
    相談や質問を送信。

  2. エージェントが分析
    Semantic Kernel(Kernel)が会話用のAIモデルとプラグインを組み合わせて動作。
    必要に応じて関数(ツール)を選び実行。

  3. プラグイン呼び出し
    TipsPlugin.get_advice() が外部APIからランダムな励まし文を取得。
    ※@kernel_function(description=...) があるからAIがこの関数を理解して自動選択できる。

  4. 応答作成
    AIが「課題整理 → 提案 → 一言」の形で返答を組み立てる。

  5. 会話継続
    会話履歴を保存し、次ターンで文脈を反映(ChatCompletionAgent+ChatHistoryAgentThread)

実装:Google Colab用セル(コピペで順に実行)

Google Colabのはじめ方(参考リンク)

  • Google Colab 公式:ブラウザでPythonを実行でき、GPUも利用可能(ノートブックの作成と実行方法はこちら)。
    Google Colab

    • Colabトップ(新規ノート/ファイルの開き方など)
  • 新規ノートブックを作成 → 本記事のセルを上から順に貼り付け・実行

セル1:ライブラリのインストール

# ========================================
# 1. 必要なライブラリのインストール
# ========================================
# semantic-kernel: Microsoft製のAIオーケストレーションフレームワーク
# openai: OpenAI APIを使うための公式Pythonクライアント
# requests: 外部HTTP API(今回はランダムアドバイスAPI)を呼び出すため

!pip install -U semantic-kernel openai requests

セル2:APIキー設定(対話入力)

# ========================================
# 2. OpenAIAPIキー設定
# ========================================
import os
from getpass import getpass

# OpenAI APIキーを環境変数に設定
os.environ["OPENAI_API_KEY"] = "sk-proj-..." # 実際の値に置き換えてください

print("🔑 OpenAI APIキーを環境変数に設定しました")

セル3:Semantic Kernel の初期化(OpenAI接続)

# ========================================
# 3. Semantic Kernel の初期化
# ========================================
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion

# KernelはSKの中心的なコンポーネント。
# プラグインやAIサービスなどを束ね、タスクを実行する役割を持つ。
kernel = Kernel()

# OpenAIのチャットモデルをサービスとして登録
# → これでKernelがGPTモデルを使えるようになる
chat_service = OpenAIChatCompletion(
    service_id="openai-chat",  # サービス識別子(任意名)
    ai_model_id="gpt-5-nano",  # 利用するモデル(今回は低コストなgpt-5-nanoを使用)
    api_key=os.environ["OPENAI_API_KEY"]
)

kernel.add_service(chat_service)

print("🧠 Semantic Kernel を初期化しました")

セル4:外部API呼び出しプラグイン

# ========================================
# 4:外部API呼び出しプラグイン
# ========================================
from typing import Annotated
import requests
from semantic_kernel.functions import kernel_function

class TipsPlugin:
    # セマンティックカーネルのプラグイン関数は、
    # 1) @kernel_function デコレータが必須
    # 2) description に、この関数が何をするのかを明確に書く必要がある
    # → これによりAI(LLM)が「この関数はこういう時に使える」と理解し、
    # 適切な場面で自動的に呼び出せるようになる
    
    @kernel_function(description="ランダムな短いアドバイスを取得")
    def get_advice(self) -> Annotated[str, "取得したアドバイスの文章"]:
        """
        外部API(https://api.adviceslip.com/advice)から
        ランダムなアドバイス文を1つ取得して返す。
        """
        try:
            response = requests.get("https://api.adviceslip.com/advice")
            if response.status_code == 200:
                return response.json()["slip"]["advice"]
        except Exception:
            pass
        return "今日は一歩ずつ進めてみましょう。"

セル5:エージェントの挙動(プロンプト・方針)

# ========================================
# 5. エージェントへの挙動指示(プロンプト)
# ========================================
# ユーザーの質問・悩みにまず具体的に応答し、その後に
# get_advice() 関数からの短い励ましを必ず添えるよう指示。

instructions = """
あなたは相談者の話を聞き、状況に応じてアドバイスを返すアシスタントです。

応答方針:

1. ユーザーがまだ具体的なテーマや悩みを出していない場合:
  - すぐに大量の提案はせず、まず1〜2行で会話のテーマを促す質問を返す
  - 必要に応じて選択肢(例:仕事・勉強・人間関係・健康など)を簡潔に提示する

2. ユーザーが具体的な相談や悩みを述べた場合:
  - 以下の構成で簡潔に返答する
    1. 課題の整理(短く要点だけ)
    2. 解決のための提案(最大3つ、すぐ試せる内容に絞る)
    3. 今のあなたに必要な一言を日本語訳をつけて伝える(get_adviceの結果を必ず使う)
  - 各提案は1行または箇条書きで端的に

3. 文章は親しみやすく、読みやすい自然な日本語で。

4. 返答はユーザーが次の発話をしやすくなるように終える。
"""

セル6:対話モード(ChatCompletionAgent + 履歴)

# ========================================
# 6. 対話モードの実装
# ========================================
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread

async def interactive_mode():
    """
    ユーザーとやり取りしながらアドバイスを返すモード。
    会話履歴を保持しつつ、Semantic Kernel + OpenAI + プラグインを組み合わせるデモ。
    
    ※注意:
    この関数には Semantic Kernel そのものとは直接関係のない
    「Pythonで対話アプリを動かすためのループ処理」や
    「入出力の制御」などの実装も含まれます。
    そのためコード量が少し多く見えますが、
    SKの重要ポイントは
    - ChatHistoryAgentThread(履歴管理)
    - ChatCompletionAgent(エージェント本体)
    - agent.invoke()(呼び出し)
    の3つです。
    """
    
    print("🧑‍🤝‍🧑 アドバイザー: やっほー!今日はどんな相談?一緒に考えるよ")
    print("🔧 コマンド: 'exit'=終了\n")

    # ----------------------------------------
    # SK関連: 会話履歴を保持するオブジェクト
    # ----------------------------------------
    thread = ChatHistoryAgentThread()
    await thread.create()

    # ----------------------------------------
    # SK関連: エージェント本体を生成
    # ----------------------------------------
    agent = ChatCompletionAgent(
        kernel=kernel,
        service=chat_service,
        name="advice_bot",
        instructions=instructions,
        plugins=[TipsPlugin()]
    )

    # ----------------------------------------
    # ここから下は「アプリ側の実装」
    # → 標準入力からユーザーの発言を受け取り、
    # agent.invoke() に渡して応答を表示するループ処理
    # ----------------------------------------
    
    while True:
        try:
            user_input = input("🧑‍💻 あなた: ")
            
            if user_input.lower() == 'exit':
                print("🧑‍🤝‍🧑 アドバイザー: じゃあ、また話そうね!👋")
                break
                
            if user_input.strip() == "":
                continue

            async for response in agent.invoke(
                messages=user_input,
                thread=thread
            ):
                print(f"🧑‍🤝‍🧑 アドバイザー: {response.message.content}\n")

        except KeyboardInterrupt:
            print("\n🧑‍🤝‍🧑 アドバイザー: 中断します。またいつでもどうぞ!")
            break
        except Exception as e:
            print(f"❌ エラーが発生したよ: {e}")
            print("🔄 続行するには何か入力してね。\n")

セル7:実行

await interactive_mode()

まとめて実行したい方向け:一括スクリプト版

ローカル環境で python main.py としても動きます(Python 3.11+ 推奨)。必要なら pip install -U semantic-kernel openai requests を事前に実行。

main.py
# main.py
import os, asyncio, requests
from getpass import getpass
from typing import Annotated
from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.functions import kernel_function
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread

# --- APIキー設定 ---
os.environ["OPENAI_API_KEY"] = "sk-proj-..."  # 実際の値に置き換えてください

# --- Kernel & OpenAI接続 ---
kernel = Kernel()
chat_service = OpenAIChatCompletion(
    service_id="openai-chat",
    ai_model_id="gpt-5-nano",
    api_key=os.environ["OPENAI_API_KEY"],
)
kernel.add_service(chat_service)

# --- プラグイン ---
class TipsPlugin:
    @kernel_function(description="ランダムな短いアドバイスを1件返す")
    def get_advice(self) -> Annotated[str, "取得したアドバイスの文章"]:
        """
        外部API(https://api.adviceslip.com/advice)から
        ランダムなアドバイス文を1つ取得して返す。
        """
        try:
            response = requests.get("https://api.adviceslip.com/advice")
            if response.status_code == 200:
                return response.json()["slip"]["advice"]
        except Exception:
            pass
        return "今日は一歩ずつ進めてみましょう。"

# --- インストラクション ---
instructions = """
あなたは相談者の話を聞き、状況に応じてアドバイスを返すアシスタントです。

応答方針:

1. ユーザーがまだ具体的なテーマや悩みを出していない場合:
  - すぐに大量の提案はせず、まず1〜2行で会話のテーマを促す質問を返す
  - 必要に応じて選択肢(例:仕事・勉強・人間関係・健康など)を簡潔に提示する

2. ユーザーが具体的な相談や悩みを述べた場合:
  - 以下の構成で簡潔に返答する
    1. 課題の整理(短く要点だけ)
    2. 解決のための提案(最大3つ、すぐ試せる内容に絞る)
    3. 今のあなたに必要な一言を日本語訳をつけて伝える(get_adviceの結果を必ず使う)
  - 各提案は1行または箇条書きで端的に

3. 文章は親しみやすく、読みやすい自然な日本語で。

4. 返答はユーザーが次の発話をしやすくなるように終える。
"""

# --- 対話 ---
async def interactive_mode():
    print("🧑‍🤝‍🧑 アドバイザー: こんにちは!今日はどんな相談にしましょう? ('exit'で終了)")
    
    thread = ChatHistoryAgentThread()
    await thread.create()
    
    agent = ChatCompletionAgent(kernel=kernel, service=chat_service, name="advice_bot",
                               instructions=instructions, plugins=[TipsPlugin()])

    while True:
        try:
            user_input = input("🧑‍💻 あなた: ")
            if user_input.lower() == "exit":
                print("🧑‍🤝‍🧑 アドバイザー: じゃあ、また話そうね!👋")
                break
            if not user_input.strip():
                continue
            
            async for resp in agent.invoke(messages=user_input, thread=thread):
                print(f"🧑‍🤝‍🧑 アドバイザー: {resp.message.content}\n")
                
        except KeyboardInterrupt:
            print("\n🧑‍🤝‍🧑 アドバイザー: 中断します。またいつでもどうぞ!")
            break

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

まとめ

今回のハンズオンでは、Semantic KernelとOpenAI APIを組み合わせて、会話型エージェントを構築しました。
主なポイントは次の通りです。

  1. Semantic Kernelの基本的な構造

    • Kernel:サービスやプラグインを束ねる司令塔
    • サービス(OpenAI Chatモデル):自然言語処理を担当
    • プラグイン:外部APIや独自機能をカプセル化
  2. プラグインで外部APIを利用

    • @kernel_function(description=...) によってAIが機能を理解し、自動的に呼び出し可能に
    • TipsPlugin.get_advice() で励ましの一言を取得
  3. 会話履歴の保持

    • ChatHistoryAgentThread で会話の文脈を保持

参考リンク

おわりに

「Semantic Kernel」の基礎を理解できたでしょうか?
今回のハンズオンで、単一エージェントが外部APIと連携して会話できる仕組みを体験できたと思います。

次回は、Semantic Kernelを使ったマルチエージェントの実装に挑戦します。
複数のエージェントがそれぞれ異なる役割を持ち、連携してタスクを解決する仕組みを作りながら、エージェント間の情報共有や役割分担の設計方法を学びます。

この記事が皆さんのAIエージェント開発の第一歩になれば嬉しいです。
質問やフィードバックがありましたら、ぜひコメント欄でお聞かせください。

NTT DATA TECH
NTT DATA TECH

Discussion