【Azure OpenAI入門】 リソース初期構築 & モデルのカスタマイズ & 外部から呼び出す

# 1. Azure OpenAIの作成

## 基本設定

**作成**をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/6db73479-3a4f-682b-f1f9-eafef73e5d7d.png)

※申請が必要です
- 「最大10営業日かかる」と書かれていましたが、1日で申請通りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/ca07c65e-42d5-d538-9374-f02a5e04b50e.png)


現在(2023年5月13日)の対応リージョンは以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/c6cb3561-23f6-5576-feea-a19524e5292b.png)


名前を入力し、価格レベルを選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/affb03a6-c80b-4625-6736-c8287b405795.png)

## ネットワーク設定

3種類の中からネットワーク設定を選びます
- ここでは、「**インターネットを含むすべてのネットワークがこのリソースにアクセスできます。**」を選択しました。
- (ローカルPCからAzure OpenAIで立てたエンドポイントへのアクセスを試したいためです)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/8ec69caa-4f0d-03b9-bf2e-7945a1612fc4.png)

## タグ設定

任意のタグを指定します。

## レビュー及び送信

設定内容を確認し、問題がなければ**作成**をクリックします。
※デプロイに時間がかかる場合があります。

## 作成完了

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/dd4e4b9b-6f9d-5bd4-c075-d40627138bd7.png)

---------------------------

# 2. 作成したリソースに移動

作成したAzure OpenAIのリソースに移動します。
「1.の作成完了」の画面から**リソースに移動**をクリックすると以下のような画面に遷移します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/ffd6cb10-1dc7-9dcc-182b-e5f128bb5ce1.png)

今回は以下のような流れで進めていきます。
- ①モデルをデプロイする
- ②モデルをカスタマイズする
- ③パラメータを調整する (必要に応じて)
- ③モデルを外部から利用する

# 3. モデルのデプロイ

モデルのデプロイを行います。
「2.のリソースに移動」の画面から、**デプロイ→作成**をクリックします。
すると画面右にデプロイするモデルの値を設定する項目が出てくるので、
- デプロイする際の名前
- 使用するモデル
- バージョン

を指定し、**保存**をクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/e7ddadc0-269a-1d5e-a306-b27c56377579.png)

ファインチューニングしたモデルの場合はトークンごとの課金に加えて、
モデルのホスティング料金もかかるみたいです。

今回はgpt-35-turboを使用していますが、他にも利用可能なモデルが多数あります。
私は以下のモデルが利用可能な状態でしたが、申請時にユースケースを問われたため、
それに合わせて選択可能なモデルが決まっていると思われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/f880ccbb-f9b0-fb35-724a-5769c90a57a8.png)

-------------------------------------

# 4. モデルをカスタマイズする

①でデプロイしたモデルを利用用途に応じてカスタマイズしていきます。
OpenAIリソース画面左側の「**概要**」をクリックして概要画面へ戻り、
「**探索**」をクリックします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/1fa03f45-a910-1417-7440-7061efd6b14c.png)

すると、**Azure OpenAI Studio**に遷移します。
Azure OpenAI Studio上で、先ほどデプロイしたモデルをカスタマイズしていきます。

ここでは、デプロイしたモデルと用意したデータを使って学習するわけではなく、
**モデルにあらかじめ与えておく入力をカスタマイズする**ことで振る舞いをカスタマイズしていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/5a5e0ae8-f4af-c5c9-6cd6-058471529648.png)


## ①プレイグラウンドでできること

Azure OpenAI Studioの画面から、**ChatGPTプレイグラウンド**をクリックします。
以下のような画面に遷移します。
画面右側に先ほどデプロイしたモデル名が設定されていることを確認します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/2420c308-6a4a-f993-7970-b6b0690df39a.png)

**アシスタントのセットアップ**では、Azure OpenAI Studioで事前定義されたテンプレートを使用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/21c61926-8ed6-dfca-dc28-4e2422cb5b27.png)

今回はDefaultを選択し、後ほど自身でカスタマイズしていきます。
Defaultでは、「**あなたは情報を探している人を助けるAIアシスタントです。**」という役割をモデルに与えています。


> **You are an AI assistant that helps people find information.**

※一般的には、日本語よりも英語で指示を与えた方が回答精度が高いと言われています。

デフォルト状態でモデルに質問を投げかけてみます。
**チャットセッションのUser message**に質問を記入し、送信ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/d0c6cf3e-85ee-5cd8-aad8-f3b0a690edc7.png)

しばらくするとモデルから回答が返ってきます。
チャットベースのアプリケーションを作った場合、ユーザに見えているのは**チャットセッション**部分です。
**アシスタントのセットアップ**で設定した情報は裏側で処理されています。
**チャットセッション→Show ral JSON**からどのような処理が行われているかを確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/4835a6de-39f3-fdba-e453-d26857756b8d.png)

ユーザの質問より前に、「**You are an AI assistant that helps people find information.**」がモデルに与えられています。
ここで指示されている内容に沿ってモデルがユーザと対話するという仕組みです。


## ②振る舞いをカスタマイズする

今回は以下のような流れでモデルの振る舞いをカスタマイズします。

- ①「**アシスタントのセットアップ**」でモデルの振る舞いをカスタマイズ
- ②「**チャットセッション**」で期待通りの振る舞いをするか検証
- ③ 必要に応じて、「**パラメータ**」を調整

### a. アシスタントのセットアップ

今回は、「**AWSに関連する情報を分かりやすく教えてくれるチャット**」という想定でセットアップします。
具体的には、以下のような日本語を英語に翻訳したものをシステムメッセージに設定します。

>**あなたは AWS のスペシャリストです。
専門用語を極力使わず、わかりやすい言葉で説明することが求められます。
小学生でも理解できる例を用いて、ユーザーの理解を助ける必要があります。**

また、**Add Example**を使うことで、モデルの振る舞いをさらに具体的に指示することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/6b8affa5-d514-3264-209f-b8f4e36d9e8a.png)


Exampleは、複数与えることもできますが、今回は1つの例を与えます。
このように回答例を与えることは、**One-Shot Learning**と呼ばれています。

これらの機能を使い、最終的には以下のような設定になりました。

- システムメッセージ

> **あなたは AWS のスペシャリストです。
専門用語を極力使わず、わかりやすい言葉で説明することが求められます。
小学生でも理解できるたとえを用いて、ユーザーの理解を助ける必要があります。**

- ユーザ

>**AWSとは何ですか？**

- アシスタント

>**AWSは、まるで大きなお店のようなものです。お店にはたくさんの商品がありますが、AWSにもたくさんのサービスがあります。それぞれのサービスは、さまざまな目的に特化しています。例えば、写真や動画を保存するための「ストレージサービス」や、ウェブサイトを表示するための「ホスティングサービス」があります。AWSは、その柔軟性と拡張性のおかげで、たくさんの人々や企業に利用されています。小学生の皆さんにも例えるなら、AWSは大きなプレイグラウンドのようなものです。たくさんの遊び道具が揃っていて、自分の好きな遊びを見つけることができます。**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/cc728b54-36a5-43d7-5379-78818600b57e.png)


**変更の保存**をクリックし、設定を反映させます。

### b. 振る舞いの検証

**チャットセッション**から先ほど同じ質問を投げかけてみます。
期待通りの動作をしているかを確認します。

**【before】**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/b7b10870-3613-9454-5e92-ab940209ae4b.png)

**【after】**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/68f5824a-3193-0132-dc8e-bdc1ab3bd004.png)


期待通り、「**専門用語を使わず、分かりやすい例えを使って説明する**」といった振る舞いをしています。


### c. パラメータを調整する

**アシスタントのセットアップ**だけでなく、**パラメータ**を用いてモデルの振る舞いを制御できます。
以下の記事で詳細に解説されています。

https://qiita.com/AGV_morinaga/items/04c1b3f505efca8b1511#323%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

パラメータの属性を一部紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/099678e0-1e7a-f937-d89a-055b6ee437a7.png)


**```最大応答```**
>モデル応答あたりのトークン数に制限を設定します。API は、プロンプト (システム メッセージ、例、メッセージ履歴、ユーザー クエリを含む) とモデルの応答の間で共有される最大の 4000 トークンをサポートします。1 つのトークンは、一般的な英語テキストの約 4 文字です。

- モデルの回答の最大トークン数
(正確ではないですが、日本語の場合「文字数<トークン数」イメージです)
- モデルごとに最大値が決められている

**```温度 (temperature)```**
>ランダム性を制御します。温度を下げることは、モデルがより反復的および決定論的な応答を生成することを意味します。温度を上げると、予期しない応答や創造的な応答が増えます。温度または上位 P の両方ではなくどちらかを調整してみてください。


- 0に近いほどモデルの回答が一意になる
    - 答えに一貫性を持たせたいケースで使用するイメージです。
    - - 例：今回のような技術仕様などを回答させる場合
- 1に近いほどモデルの回答に多様性が現れる
    - 回答に多様性を持たせたいケースで使用するイメージです。
    - - 例：入力した情報を基にモデルにアイデア出しをしてもらう


**```上位P```**
>温度と同様に、これはランダム性を制御しますが、別の方法を使用します。上位 P を下げると、モデルのトークンの選択がより可能性が高いトークンに絞り込まれます。上位 P を上げると、確率が高いトークンと低いトークンの両方からモデルが選択できるようになります。温度または上位 P の両方ではなくどちらかを調整してみてください。

- モデルはユーザの質問を解釈し、出力候補となる単語を探す
- 候補の中から上位何パーセントをモデルの出力に使用するかを制御

## ③設定のExportとImport

画面右上にある、「**Import setup**」「**Export setup**」を使うことで、
現状の設定内容をJSON形式で保存することや保存された設定ファイルの読み込みができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/c4e8bf16-7b3a-8e27-dc96-ee7b70c968b2.png)

Import/Export時には、どの属性を含めるかを選択することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/b443580a-59fb-b532-5dd0-cd61c40fa4d1.png)

今回の設定内容をJSONファイルにExportし、ファイルの中身を確認すると以下のようになっていました。

```json:AWS_Support.json
{
    "systemPrompt":"You are an AWS specialist.\nAvoid using technical jargon and explain in easy-to-understand language.\nYou need to help users understand with analogies that even elementary school students can understand.",
    "fewShotExamples":[
        {
            "chatbotResponse":"AWS is like a big store. There are many products in the store, but AWS also has many services. Each service specializes in different purposes. For example, there are “storage services” that store photos and videos, and “hosting services” that display websites. AWS is used by many people and businesses due to its flexibility and scalability. AWS is like a big playground for elementary school students. There are many play tools, so you can find your favorite play.",
            "userInput":"What is AWS?"
        }      
    ],
    "chatParameters":{
        "deploymentName":"gpt-35-turbo",
        "maxResponseLength":800,
        "temperature":0.7,
        "topProbablities":0.5,
        "stopSequences":null,
        "pastMessagesToInclude":10
        }
}
```

-------------------------------------

# 5. モデルを外部から利用する

**プレイグラウンド→チャットセッション→コードの表示**をクリックすると、サンプルコードが表示されます。
しかし、モデルの振る舞いを検証していた場合は、検証時にやり取りした内容までサンプルコードに含まれてしまうため、
**チャットをクリアする→コードの表示**の順でコードを表示します。
サンプルコードが表示されます。現状は、json, python, c#, curlの中から選べます。
APIキーをコピーしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/434d338c-a382-7002-2719-df755b7b03f9.png)

今回は ~~curl~~ Pythonからモデルに対して質問を投げかけます。
サンプルコードはそのままでは実行できないため、以下2点を修正します。

- ①APIキーを環境変数に格納し、Pythonスクリプト上で展開されるように反映
    - 私の環境がWindowsのため以下コマンドはPowershellコマンドとなっています
    
```posh:
$Env:OPENAI_API_KEY="先ほどコピーしたAPIキー"
```

- ② ```messages```に質問文を追加する
    - messagesリストに、```{Key:Value}```形式でユーザからの質問を付け足します
    - 今回は```{"role":"user","content":"AWSのルートテーブルとは何ですか？"}```を足しています。


最終的に以下のようなソースコードになりました。

```py:chat_test.py
import os
import openai
openai.api_type = "azure"
openai.api_base = "https://my-openai-testenv.openai.azure.com/"
openai.api_version = "2023-03-15-preview"
openai.api_key = os.getenv("OPENAI_API_KEY")

response = openai.ChatCompletion.create(
  engine="gpt-35-turbo",
  messages = [{"role":"system","content":"You are an AWS specialist.\nAvoid using technical jargon and explain in easy-to-understand language.\nYou need to help users understand with analogies that even elementary school students can understand."},{"role":"user","content":"What is AWS?"},{"role":"assistant","content":"AWS is like a big store. There are many products in the store, but AWS also has many services. Each service specializes in different purposes. For example, there are “storage services” that store photos and videos, and “hosting services” that display websites. AWS is used by many people and businesses due to its flexibility and scalability. AWS is like a big playground for elementary school students. There are many play tools, so you can find your favorite play."},{"role":"user","content":"AWSのルートテーブルとは何ですか？"}],
  temperature=0.7,
  max_tokens=800,
  top_p=0.5,
  frequency_penalty=0,
  presence_penalty=0,
  stop=None)

print(response.choices[0].message.content)
```

ソースコード修正の他、Pythonパッケージも必要です。

```sh:
pip install openai
```

これで実行環境は整ったため、実行してみます。

```sh:
$ python chat_test.py
AWSのルートテーブルは、道路地図のようなものです。
道路地図には、どの道を通って目的地に行くかを示すルートがあります。
同様に、AWSのルートテーブルには、どのネットワークにどの方向に通信するかを示すルートがあります。
ルートテーブルは、AWSの仮想ネットワーク内でトラフィックを送信するために使用されます。
例えば、あなたがウェブサイトをホストしている場合、
ルートテーブルは、どの方向にトラフィックを送信するかを決定します。
```

先ほどカスタマイズしたモデルの振る舞いを確認できます。
分かりやすい例を用いて説明してくれています。


# まとめ
プレイグラウンドで色々と試せるのは便利な機能であると感じました。
しかし、今回試したAzure OpenAIの機能は**エンドポイントの作成**にとどまっており、
外部から利用する・システムに組み込むとなると、Azure OpenAI以外の作りこみがかなり必要になるのではないかと思いました。この辺りみなさんどうされているんでしょうか、、
次回は、チャット形式のアプリケーションにAzure OpenAIを組み込みます。

https://qiita.com/sakue_103/items/2b4eeb7fa6384f68e132