Semantic Kernelの各コンポーネントの役割と機能についてまとめた

# はじめに
Microsoftが開発した開発者がAIをより活用しやすくするためのOSSである、`Semantic Kernel`の勉強を最近始めたので自分の備忘録としてまとめます。こちらの記事は、以下のMicrosoftの公式ドキュメントを参考にしています。

Semantic Kernelについて

https://learn.microsoft.com/en-us/semantic-kernel/overview/

カーネルについて

https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/kernel/?tabs=python

メモリーについて

https://learn.microsoft.com/en-us/semantic-kernel/memories/

プランナーについて

https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/planners/?tabs=python


プラグインについて

https://learn.microsoft.com/en-us/semantic-kernel/ai-orchestration/plugins/?tabs=python


# Semantic Kernelとは
`Semantic Kernel`とは、`Azure OpenAI`などのAIサービスを簡単に組み込むことができるオープンソースのSDKです。`Semantic Kernel`は開発者がAIプラグイン上で`Copilot`と同様の体験を構築できることを目的として開発され、AIプラグインのオーケストレーションとして機能します。`Semantic Kernel`を使用することで、`Microsoft 365 Copilot`や`Bing`を動かすのと同じAIオーケストレーションパターンを独自のアプリで活用することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/61ab5b57-644f-ab9b-4e41-c640d3b97ca5.png)

# Semantic Kernelの構成要素
`Semantic Kernel`は以下のコンポーネントから構成されます。
|段階|要素|説明|
|---|---|---|
|1|依頼|ユーザーがSemantic Kernelに目標を送信。|
|2|カーネル|開発者によって定義されたパイプライン/チェーンを実行。チェーンの実行中、カーネルによって共通のコンテキストが提供され、関数間でデータ共有が可能。|
|2.1|メモリー|開発者はコンテキストを呼び出してベクターデータベースに保存可能。|
|2.2|プランナー|開発者はSemantic Kernelに、ユーザーのニーズに対応するチェーンの自動作成を依頼可能。|
|2.3|コネクター|Microsoft Graph Connector kit 等の構成済みプラグインや、開発したカスタムコネクタを利用可能。|
|2.4|プラグイン|新しいAI機能を追加したり、既存のアプリやサービスをセマンティックカーネルに統合することが可能。|
|3|回答|ユーザーにプロセスの完了を知らせるための応答。|

これらのコンポーネントは以下の図のように関わり合い、AIがユーザーの複雑なタスクを自動化する高度なパイプラインが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/833187f9-2732-c890-b28f-58fdb1767ac7.png)

## カーネル
カーネルは、AIアプリケーションのコードを実行するためリソースを管理する要素です。具体的には、ネイティブ関数とセマンティック関数を同等に扱うための構成、サービス管理、プラグイン管理、などがあります。カーネルによってセマンティック関数とネイティブ関数を同等に扱うことが可能なため、それぞれ同じ方法でトリガーできます。以下の図はネイティブ関数とセマンティック関数を同等に扱うことで実現する、両方の関数を1つのパイプラインで一緒に実行できることを表した図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/961f9447-8bdd-3dda-79c7-7413ab93697f.png)

## メモリー
メモリーは、ユーザーからの質問をより広いコンテキストで理解するためのコンポーネントです。メモリーには主に3種類あり、キーペア、ローカルストレージ、セマンティックメモリがあります。セマンティックメモリはテキスト情報を、埋め込みと呼ばれる数値の長いベクトルとして記憶したものです。埋め込みの方法として基本的には、文、段落、テキストのページ全体を取得し、対応する埋め込みベクトルを生成します。また、クエリが実行されると、クエリは埋め込み表現に変換され、既存のすべての埋め込みベクトルに対して検索が実行され、最も類似したものが見つかります。これは、`Bing`で検索クエリを実行する場合と似ています。

## プランナー
プランナーとは、ユーザーの質問を受け取って要求を実行する方法に関する計画を返す機能です。プランナーは、カーネルに登録されているプラグインを組み合わせて、目標を達成するためのワークフローを作成することができます。開発者の想定を超えた関数の組み合わせをする場合もあるため、責任のあるAIの原則に則った運用も重要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/63250942-87d4-0e90-95ae-ccb806cce999.png)

## コネクター
`Semantic Kernel`は開発者がAIサービスを既存のアプリに柔軟に組み込むことができるように開発されているため、多くのコネクターが用意されており、AIアプリの「脳」に相当するメモリーやモデルを簡単に接続することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/a01acd46-0325-d46b-97a0-622e6da893a4.png)

## プラグイン
プラグインは AI アプリやサービスに公開できる関数のグループです(プラグインは昔はスキルと呼ばれていました)。プラグインにより、`ChatGPT`、`Bing`、`Microsoft 365`などの主要なAIアプリとサービスのすべてで使用できる相互運用可能であり、コードを書き直すことなくAI機能の範囲を広げることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/d71c789e-4bf9-72c1-7da5-64aef2ce0497.png)
`Semantic Kernel`では、これらの関数を手動で直接呼び出すことも、プランナーを利用して自動的に呼び出すことも可能です。ただし、プラグインは関数を提供するだけで作ることはできません。なぜなら関数定義だけでは関数の挙動をAIが理解できないためです。そのため、関数の入力、出力、など、どのように動作するかを意味的に詳細に記述する必要があります。関数の挙動記述することでプランナーは、次の図のようにユーザーの要求を満たすために呼び出す最適な関数を選択することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/bf1c7e2c-2221-c5a2-422a-3c2771cc314f.png)
プラグインは拡張性にも優れているため、`Semantic Kernel`は簡単に機能を追加することができます。プラグインはAIアプリの「身体」に相当する、セマンティック関数(プロンプト)とネイティブ関数で構成されています。これらの関数はトリガーに応答してアクションを実行することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/3926da74-2a33-5294-9989-239ef6a48985.png)

### セマンティック関数
セマンティック関数を身体に例えるなら、AIの「耳」と「口」に相当します。AI アプリはユーザーの要求を聞き取り、自然言語応答で応答できます。そして「耳」と「口」を「脳」に接続するために、`Semantic Kernel`はコネクタを使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/9c57648c-18d2-b2aa-5979-eea6b2331ea6.png)
セマンティック関数の挙動をプランナーに理解してもらうためには、`config.json`を設定する必要があります。
```json:config.json
{
  "schema": 1,
  "type": "completion",
  "description": "Summarize given text or any text document",
  "completion": {
    "max_tokens": 512,
    "temperature": 0.0,
    "top_p": 0.0,
    "presence_penalty": 0.0,
    "frequency_penalty": 0.0
  },
  "input": {
    "parameters": [
      {
        "name": "input",
        "description": "Text to summarize",
        "defaultValue": ""
      }
    ]
  }
}
```

### ネイティブ関数
ネイティブ関数を身体に例えるなら、AIの「手」に相当します。ネイティブ関数を使用すると、カーネルで`C#`や`Python`のコードを直接呼び出すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/9c17ee3f-c2e9-699b-3de0-bf99061b448e.png)
ネイティブ関数の挙動をプランナーに理解してもらうためには、コード内に注釈を使用する必要があります。
```python:Python
@sk_function(
    description="Adds value to a value",
    name="Add",
    input_description="The value to add",
)
@sk_function_context_parameter(
    name="Amount",
    description="Amount to add",
)
def add(self, initial_value_text: str, context: SKContext) -> str:
    """
    Returns the Addition result of initial and amount values provided.

    :param initial_value_text: Initial value as string to add the specified amount
    :param context: Contains the context to get the numbers from
    :return: The resulting sum as a string
    """
    return MathSkill.add_or_subtract(initial_value_text, context, add=True)
```

# おわりに
`Semantic Kernel`で登場するコンポーネントについて簡単にまとめました。コンポーネントごとに役割と機能が明確に分けられて定義されているため、それぞれの役割と機能をちゃんと理解することで、管理しやすいAIシステムの構築が可能になる便利なSDKだと感じました。