Semantic Kernel×Azure OpenAI ServiceでAIサンプルアプリを開発した

# はじめに
`Semantic Kernel`の勉強を始めましたが、まだ誕生したばかりの`OSS`ということで、情報が十分になかったり新旧の情報が混在していたりして調べものに少々苦労しています。`Semantic Kernel`と`Azure OpenAI Service`を使ったサンプルアプリとして有名なものとして、[Project Miyagi](https://github.com/Azure-Samples/miyagi)がありますが、比較的大規模なシステムになっています。このような状況の中で、手軽に動かせる`Semantic Kernel`を使ったシンプルなアプリがあればいいのになあということで、実際にアプリを構築しました。こちらのアプリは、カーネル、プランナー、スキルといった`Semantic Kernel`の最低限な要素を使ったシンプルなアプリになりますので、是非`Semantic Kernel`のクイックスタートとしてご利用ください。

# Semantic Kernelとは
`Semantic Kernel`を知りたい方は、こちらの記事でまとめているので読んでみてください。

https://qiita.com/y__saito/items/e3f383a673b401b1f2ee

# サンプルアプリの概要
本記事で紹介するサンプルアプリはこちらの`GitHub`のリポジトリで公開しています。こちらのアプリは、直近1か月分のMicrosoftの株価を取得し、取得した株価のデータから特徴量からターゲットを予測する回帰モデルを学習・予測した後、その予測結果の理由を考察して出力するアプリになります。(株価変動の予測精度は保証はしないためご注意ください。)`Semantic Kernel`にこの目標を達成してもらうため今回のアプリでは、株価を取得するスキル(ネイティブ関数)、株価を予測するスキル(ネイティブ関数)、予測結果を考察するスキル(セマンティック関数)、の3つのスキルを定義しました。

https://github.com/yus04/semantic-kernel-demo/tree/master

# 使い方
まず初めに、こちらのサンプルアプリの使い方を簡単に紹介します。

## 前提条件
本サンプルアプリは、以下のものを使用するため、これらはインストール済みのものとして話を進めます。
- `Dev Container` (`Visual Studio Code`の拡張機能)
    - `Dev Container`を使わなくても、[requirements.txt](https://github.com/yus04/semantic-kernel-demo/blob/master/.devcontainer/requirements.txt) で指定されているライブラリが全てインストール済みの環境であれば、開発コンテナを使わなくてもアプリの起動は可能です。 
- `Docker`
    - `Dev Container`と同様、ローカル環境に必要なライブラリが全てインストール済みであればアプリの起動は可能です。
- `Azure OpenAI Service`
    - `GPT-35-turbo`モデルを使用します

### Dev Container
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/1f44e837-cda3-6b6f-80a5-43fe1682987b.png)

### Azure Open AI Services (Azure OpenAI Studioのポータル画面)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/80b841bd-d997-6091-6baa-465f7c4865c5.png)



## 環境構築
### .envの作成
以下のような`.env.sample`を参考にして、`.env`ファイルを作成してください。その際、必要な情報は`Azure`ポータルや`Azure OpenAI Studio`のポータルから取得してください。
```:.env.sample
AZURE_OPENAI_DEPLOYMENT_NAME=""
AZURE_OPENAI_ENDPOINT=""
AZURE_OPENAI_API_KEY=""
```

### Dev Containerの起動
`Visual Studio Code`のコマンドパレットより「`Reopen in Container`」を入力して`Enter`を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/17a34105-74f5-b5f5-86ab-ef41db5ef441.png)

すると`Dev Container`が起動し、ビルド済みのイメージファイルが存在しなければ、`Semantic Kernel`などのサンプルアプリを実行するのに必要なライブラリがインストールされてコンテナが実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/66d92fdd-258d-7146-6844-00b7da9f366c.png)

`Visual Studio Code`の左下に「`Dev Container: Python3`」と表示されていればコンテナに接続できていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/48eb60e3-22ae-aafa-4f22-4b1ce02cca78.png)

:::note info
コンテナへの接続を解除するときは、コマンドパレットで「`Close Remote Connection`」と入力して`Enter`を押すことで解除できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2452857/facc4f02-cbd9-fbf2-e060-b6436aa5fd7d.png)
:::

## 実行方法
`main.py`を実行します。
```python:main.py
python main.py
```

## 実行結果
ここで、サンプルアプリを実行した結果を載せます。(実行結果は、直近1か月の株価データやモデル学習のためのトレーニングデータの分け方に依存します。)
```bash:実行結果
vscode ➜ /workspaces/semantic-kernel-demo (master) $ python main.py 
Generated Plan:
{
    "input": "Microsoft Stock Price Analysis",
    "subtasks": [
        {"function": "GetStockPrice.GetStockPrice"},
        {"function": "PredictStockPrice.predict"},
        {"function": "AnalyzeReason.analyze"}
    ]
}
result:
Based on the provided data, the stock price of Microsoft has been fluctuating within a range over the past month.
It opened at $320.54 and reached a high of $340.86, but closed at $338.7.
This indicates a potential upward trend in the stock price.

Considering this information, it is advisable to "Buy" Microsoft stocks.
The stock has shown resilience and has the potential to continue its upward trajectory.
Additionally, Microsoft is a well-established and profitable company, making it a reliable investment option.

However, it is important to conduct further research and analysis before making any investment decisions.
Factors such as market conditions, company performance, and personal financial goals should be taken into account.
```
英語ですが、実行計画とAIによる提案内容が出力されています。実行計画については、`GetStockPrice`、`PredicdtStockPrice`、`AnalyzeReason`、の順序でスキルを実行するように計画されていることがわかります。AIによる提案については、直近1か月のMicrosoftの株価データの解説と、株価データから学習された回帰モデルから「Buy」することを勧める提案がされています。

# 解説
次に、このサンプルアプリを構成する各ファイルの説明をします。

## フォルダ構成
このサンプルアプリの主なフォルダ構成は次の通りです。
```:フォルダ構成
.
├─ .devcontainer
│　├ devcontainer.json
│  └ requirements.txt
├─ skills
│  ├ AnalyzeReason
│  │  └ analyze
│  │  　├ config.json
│  │  　└ skprompt.txt
│  ├ GetStockPrice
│  │  └ native_function.py
│  └ PredictStockPrice
│     └ native_function.py
├─ .env
└─ main.py
```

## .devcontainer
`Visual Studio Code`の拡張機能`Dev Container`を使って立ち上げるコンテナ開発環境のための設定ファイルを含むディレクトリになります。`devcontainer.json`は開発コンテナに関する設定ファイルであり、イメージファイルの設定や、コンテナ起動後に実行するコマンドなどを指定することができます。`requirements.txt`は`Semantic Kernel`や`scikit-learn`などの、アプリを実行する時に必要なライブラリ一覧となっており、`pip`で一括でインストールされます。

## skills
今回はスキルと表現していますが、プラグインとも呼ばれています。スキルは関数のグループであり、今回は`AnalyzeReaon/analyze`、`GetStockPrice`、`PredictStockPrice`の3つのスキルがあります。サンプルアプリでカーネルに与えたプロンプトが「直近1か月分ののMicrosoftの株価を取得して、今後に株価が上がりそうなら「買い」下がりそうなら「売り」と出力し、そのように判断した理由も教えてください。」なので、これらの3つのスキルは以下の順序で実行されます。
1. `GetStockPrice`
1. `PredictStockPrice`
1. `AnalyzeReaon/analyze`

## .env
`Azure OpenAI Service`を使用するためのシークレット情報などを含んだ環境変数ファイルになります。

# おわりに
`Semantic Kernel`は現在も急速に発展している新しいOSSなので、スキルがプラグインと呼ばれるようになったりしている例が挙げられるように、昔と今の情報が混在している点などで、学習のハードルを少し感じました。`Semantic Kernel`のような、常に進化し続ける技術はブログ記事よりも公式ドキュメントを読んで学ぶ方が間違いはないと思います。