OpenAI を UiPath から呼び出してみる ～ APIのパラメータ編 ～

# OpenAI を UiPath から呼び出してみる ～ APIのパラメータ編 ～

今話題のチャットGPT。先回は APIキー の取得方法から、UiPath における代表的な実装例の[***記事***](https://qiita.com/Kajiita/items/d9aeeaf7d1ab722732f6)を書きました。
本記事では、***チャットGPTの WebAPI のパラメータに着目して挙動（仕様）*** をみていきたいとおもいます。

（OpenAI のアクティビティのプロパティ例）
![OpenAIコネクタ14.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/b72e0a57-03e4-c6e2-945e-20fa6b48d4b2.jpeg)

# チャットGPTにAPIのパラメータ仕様を尋ねた結果

- ***model***: 使用する GPT モデルのタイプを指定します。"gpt2" または "gpt3" を選択できます。既定値は "gpt3" です。​

- ***max_length***: チャットで許可される最大トークン数を指定します。 既定値は 100 です。​

- ***temperature***: ネットワークの予測を制御するための温度パラメーターを指定します。値が高いほど、より無作為な予測が生成されます。 既定値は 0.7 です。​

- ***top_p***: 生成テキストのトークンの累積確率分布内の割合を指定します。 トークンの選択は、トークンの確率が top_p 以下である場合、最も高い確率のトークンで行われます。 値が高いほど、ネットワークの予測は生成される確率が高くなります。 既定値は 0.9 です。​

- ***presence_penalty***: 既に生成されたテキストに存在するトークンの出現確率を減らすために使用されるペナルティを指定します。 既定値は 0 です。​

- ***frequency_penalty***: 出現しにくいトークンを選択するために使用されるペナルティを指定します。 既定値は 0 です。​

- ***stop***: Trueに設定されている場合、APIはユーザーからの入力に応答するのを停止し、何も返さずに終了します。これにより、会話を終了することができます。例えば、ユーザーが会話を終了する場合、APIにStopオプションをTrueに設定することで、すぐに停止することができます。また、AIモデルが予期せぬ返答を提供する場合も、APIにStopオプションを使用して、会話を即座に終了することができます。

- ***user***: チャットの対話を個別に識別するために使用されます。 ​このオプションを使用すると、異なるユーザーが同じ機械学習モデルを使用して対話を開始できるようになります。 具体的には、User オプションは、API に送信される要求本文の一部として提供されます。 これにより、サーバー側は、各ユーザーに対してユニークなセッション ID を割り当てることができます。これは、同じチャットルームで異なるユーザーが同時にメッセージを送信した場合、メッセージを正確に追跡し、返信するために必要な情報です。また、User オプションは、API を使用する開発者がユーザーセッションのパフォーマンスを追跡および改善するために使用することもできます。 たとえば、どのユーザーがよりよいレスポンスタイムを持っているか、どのユーザーがより多くのエラーを引き起こしているかなど、デバッグやトラブルシューティングに役立ちます。​

- ***stream***: このオプションを使用することで、リアルタイムでチャットに応答させることができます。（以下、リクエスト例）​
    ```
    POST https://api.chatgpt.com/generate?stream=true​
    ```
    これにより、リクエストがサーバーに送信され、サーバーからのレスポンスがストリーム形式で返されます。​ストリーム形式のレスポンスには、以下のような情報が含まれます。​

    - id: チャットのセッション ID​
    - text: サーバーから返されたテキストメッセージ​
    - prompt: サーバーに送信されたプロンプトテキスト​

    また、ストリーム形式のレスポンスは、以下のような形式で送信されます。​

    `{"id": "session_id", "text": "response_text", "prompt": "prompt_text"}​`

    ストリーム形式のレスポンスを使用することで、リアルタイムなチャット応答を実現することができます。

- ***N***: 生成するテキストの長さを指定します。具体的には、N オプションの引数に整数を指定することで、生成するテキストの単語数や文字数を制御できます。​たとえば、N=100 のように指定することで、100 単語分のテキストを生成することができます。また、N オプションは、コンテキスト長の制御にも使用されます。コンテキスト長とは、生成されるテキストにおいて、過去のテキストをどの程度考慮するかを決定するパラメータです。N オプションを使用することで、生成されるテキストのコンテキスト長を制御できます。たとえば、N=10 のように指定することで、過去の 10 単語分のテキストを考慮してテキストを生成することができます。注意点としては、N オプションによって生成されるテキストの品質や流暢さが大きく変わる場合があるため、適切な値を選択することが重要です。また、N オプションは他のオプションと組み合わせることで、より複雑な生成タスクを実現することができます。​

- ***Instruction***:チャットシナリオの制御に使用されます。（以下、Instruction オプションのコマンド例）​

    1. end - チャットを終了します。​
    2. jump - 指定されたステップにジャンプします。​
    3. expect - ユーザーが入力したテキストに基づいて、次のステップを決定します。​
    4. retry - ユーザーに同じ質問をもう一度するように指示します。​

    例えば、次のような Instruction オプションを持つ API リクエストを考えてみましょう。​

    `{ "instruction": {"name": "jump","step": "step2"},"message": "Hello" }​`

    このリクエストでは、"jump" コマンドが使用されており、次のステップが "step2" であることを指定しています。つまり、ユーザーが "Hello" というメッセージを入力した時点で、チャットは "step2" にジャンプします。​
Instruction オプションを使用することで、複雑なチャットシナリオを実現することができます。

# 実際の挙動（例）

#### ***Max Tokens***
プロパティの注釈によると既定値が 3840 のトークンの最大数を指定できるオプション
チャットGPTの課金単位で、***英語では1単語=1トークンです(カンマやピリオドも1トークン)。 しかし日本語の場合、ひらがなは1文字が1トークン以上、漢字だと1文字2,3トークン***になります。

Max Tokens:10 の例
![OpenAIコネクタ19.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/49d9abd0-4e4c-95aa-2861-d927ea2a6821.jpeg)
Max Tokens:3 の例
![OpenAIコネクタ18.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/4833f74c-0003-99ae-3716-d41520105fa0.jpeg)

#### ***temperature***（min 0 ～ max 1）
答えの幅が広い質問をした際の応答文に顕著な差がでます。
既定値は 0.7 ということで比較的ランダムな予測結果を出すようです。
（なお、「1＋1は？」みたいな答えが決まっているものは、指定値に関わらず「2 です。」）

temperature:1 の例
![OpenAIコネクタ39.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/99f60d5d-a73f-4313-316b-107c6991d1b1.jpeg)
temperature:0.1 の例
![OpenAIコネクタ40.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/af695637-5f80-ec38-2492-6e3c042003b9.jpeg)

値の高い方は「東京住まいでコスパの良い国内旅行先は？」の質問に対して、
`箱根温泉　／　長野県北信地方　／　京都　／　宮崎県　／　沖縄県`
とアクセス手段に飛行機を含んだ広域回答が返ってきました。
値を低くすると
`鎌倉　／　伊豆半島　／　那須高原　／　軽井沢　／　箱根`
と東京近郊の観光地を回答してくれました。

#### ***top_p***（min 0 ～ max 1）
値が小さいほど少ないトークンで返すよう考慮してくれます。既定は最大の 1 みたいです。
先ほどの temperature:0.1 の回答ですが、少々冗長なので min を指定して再度質問↓

![OpenAIコネクタ41.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/ca87907d-a61e-e580-f67c-8cfa75c4400f.jpeg)

`鎌倉　／　伊豆半島　／　富士山周辺　／　軽井沢　／　箱根`
「那須高原」を「富士山周辺」に変えてきた意図はわかりませんが、
端的に言い切るためなのか、アクセス2時間圏内だった回答が1時間にグレードアップ(笑)
レスポンスの文字数はたしかに結構スリムになってますｂ

#### ***N***（既定値 1 の整数型）
このオプションはGPTの説明する仕様と、UiPath のアクティビティのそれで差異があります。
UiPath のアクティビティ実行時の仕様は***返却する回答文の数***を指定するものです。

N:10 の例（オブジェクト型の変数（チャット応答文）の中身）
![OpenAIコネクタ42.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/c3d1558f-99d3-f59b-3e4d-5c935e16de22.jpeg)
![OpenAIコネクタ43.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/0acd76b0-55f5-3cd8-de94-43c98f426292.jpeg)

返却された回答文で最も確度の高いTextを補完するのが「Top Generated Text（String型）」です。
![OpenAIコネクタ44.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/677dded8-c969-c1b4-8b9a-c605da7733af.jpeg)

#### ***presence_penalty***（min 0 ～ max 2）
APIが以前に生成したトークンに似たものを生成しないよう制御するオプション。
値が大きければペナルティーが強い＝MECEになるってことですね。

presence_penalty:2 の例
![OpenAIコネクタ52.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/102f553c-f711-f126-5671-3a1df7a0918b.jpeg)
presence_penalty:0.1 の例
![OpenAIコネクタ53.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/966fee87-b881-82d7-8bbe-5cf3a7dc3a99.jpeg)

たしかに、値が max の 2 を指定した方はギュッとしている感があります。
値を min にした方は、パッと見ただけでも「静岡県」「自然」「富士山」という文字が2か所ありますね。


#### ***frequency_penalty***（min 0 ～ max 不明（※5くらいが試す限り最大。10だと落ちる））
出現しにくいトークンを意図的に出すオプションっぽく、
回答の幅を意識的に広げたいときに使うとよさそうです。

frequency_penalty:1 の例
![OpenAIコネクタ34.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/8a5c9bef-81f4-542e-ea26-cd9047fe9b61.jpeg)
frequency_penalty:5 の例
![OpenAIコネクタ37.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/54671f1c-08fd-ef58-f206-a3bd1c0ce667.jpeg)

流石にほぼ最大値？の5を指定した際は、どっかの学術論文とかの記述なのか
マニアックで冗長な回答が返ってきます。このオプションのさじ加減は面白いチャットに重要そうですね。

#### ***stop***（任意の文字列指定）
指定した単語が出現した時点で文章生成を打ち切ることができます。
他記事によるとリストで複数単語を渡せる模様ですが、UiPath の本アクティビティは
この stop 項目は String 型なので単一の単語しか無理そう？です。

![OpenAIコネクタ48.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/227598ca-b571-5bb2-b098-4c32eb2bd9b5.jpeg)

#### ***user***（任意のユーザー識別子を指定）
このオプションを指定することで異なるユーザーによる発言を区別することができるとのこと。
プレビュー版のためか、UiPath のアクティビティはプロパティに項目はあるものの、レスポンスの user フィールドは Null が返ってきます。
発言者の違いを確認するため、GPTに***しりとり***をさせてみました↓
![OpenAIコネクタ49.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/ad7bd7ba-53bc-0586-b70c-b846da57f82a.jpeg)
"userXYZ"をパラメータで投げてるものの、レスポンスは Null です。
パッケージが一般公開されたタイミングで再度確認してみます。

#### ***stream***（True or False）
APIからリアルタイムな応答を取得するためのオプションですが、使い方が正直わからなかったです。
そもそも出力プロパティに Stream 型の変数も居ないのでレスポンスをどうやって受けるのかが想像できない。。。
単純に「True」のチェックを入れて実行した場合は以下の様なエラーが出ます↓

![OpenAIコネクタ50.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/efd4bd6d-9e1b-bc67-8d05-dc1e45a5a11f.jpeg)

#### ***Instruction***（詳細なオプション指定）
本文パラメータで、プロンプトの設定、トークンの数、応答の生成方法などの基本的なオプションの指定はできますが、
Instruction オプションをもちいれば更に詳細な指示を与えることが可能とのこと（GPTの回答）
さしあたって、「"stop": true」の詳細指示を添えて実行してみる↓

![OpenAIコネクタ51.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/837481d9-488c-fa15-2208-208d0381f08b.jpeg)

こちらも現時点では非対応なのか、レスポンスの Instruction は Null でした。

結論、プレビュー版では以下の3オプションは利用できない可能性があります。
- ***Instruction***
- ***stream***
- ***user***

最後に、***model*** オプションの比較だけしたいとおもいます。
***『東京住まいでコスパの良い国内旅行先は？』***
の設問に対する各モデルの回答例がこちら↓↓（なお、モデルが個性を発揮しすぎないように temperature と Top P オプションで端的な回答文を要求しています。）

`text-curie-001`
![OpenAIコネクタ57.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/6227febd-7ab0-1089-6ccf-c0cbd758f1c6.jpeg)
`text-babbage-001`
![OpenAIコネクタ58.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/7306634e-d013-2ef8-af90-17509c8bc1ee.jpeg)
`text-ada-001`
![OpenAIコネクタ59.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/d0a6e00b-aee8-eb2c-dcb4-12be38695324.jpeg)
`text-davinci-001`
![OpenAIコネクタ60.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/3095aa11-39cf-47d7-7cb6-897c3b1112b1.jpeg)
`text-davinci-002`
![OpenAIコネクタ61.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/33331eff-e123-04b5-a7fd-41e729e912d9.jpeg)
`text-davinci-003`
![OpenAIコネクタ62.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301444/8cd1321c-fac4-a0c6-0023-52d96ccf1e2d.jpeg)

最も精度が高いとおもわれた`text-davinci-003`がしっかりとオチを務めてくれる優秀さよ(笑)
davinci-003 は解説によると1750億個のパラメータを持っており、従来の言語モデルよりはるかに多くの情報を学習できるみたいです。
今回の質問の回答文だけでいえば、個人的には以下の curie と davince-001 が内容や言い回しの精度が高い気がします。
酔っ払いのような回答をしてきた babbage-001 は最も小型の言語モデルの一つのようです。

長々と書きましたが最後までお読みいただきありがとうございます。
パッケージが一般公開されたら、再度挙動確認し記事をアップデートしたいとおもいますm(_ _)m

# 関連記事
https://qiita.com/Kajiita/items/d9aeeaf7d1ab722732f6

https://qiita.com/Kajiita/items/5d2dc077f57cc72848e6