お久しぶりです。石川です。
気がついたら1年以上ブログを書いていなかったようです。時間作りたいですね。。。
さて、今回は最近話題のChatGPTネタです。
以下のこの記事にもあるようにMicrosoftがOpenAIとパートナーシップを結び、Azure上にOpenAI Serviceの展開を開始しています。
手元のサブスクリプションでAzure OpenAI ServiceおよびそのGPT-4プレビュー利用が承認されたのでサクッとSlackのBot化してみようと思います。
※以降の情報は執筆時(2023/04/13)の情報を基にしています。
※現在Azure OpenAI Service、GPT-4モデルのデプロイは承認制となっており、承認が降りていないサブスクリプションでは作成できませんのでご注意ください。
Azure OpenAI Serviceの作成
Azure PortalからOpenAIと検索するとCognitive Servicesの一角にAzure OpenAIが登場しています。
既に一つ存在してますが一旦置いといてリソース作成をしてみます。
特に設定項目は多くありません。
「インスタンスの詳細」 の 「名前」 が直接エンドポイントになるのでちょっと注意しましょう。
次の画面ではネットワーク設定が可能です。一番上から
- 全ネットワークからアクセス可能(インターネット含)
- 選択したネットワーク(VNet)、IPレンジからアクセス可能
- プライベートエンドポイントからのみアクセス可能
の3つから選択です。要件に応じて決めましょう。
今回は一番上の "All networks, including the internet, can access this resource." (全ネットワークからアクセス可能)を選択します。
他に目立った設定項目はないので、内容確認の後問題なければ作成をポチ。
デプロイが開始されるので完了までしばし待ちます。
………
……
…
思ってたよりかかりました。
デプロイ完了しましたが、このままでは使えないのでリソースの画面へ移動します。
モデルのデプロイとキーの確認
OpenAI Serviceはいくつかのモデルを使用することができます。
現時点で使えるものは
- text-ada-001
- text-curie-001
- text-davinci-002
- gpt-35-turbo (version 0301)
- gpt-4 (別途承認制)
- gpt-4-32k (別途承認制)
- text-davinci-003
- code-davinci-002
- text-similarity-ada-001
- text-similarity-curie-001
- text-embedding-ada-002
の11種です。OpenAI APIで使えるもののようですね。
今回は gpt-4 を使用したいので gpt-4 モデルをデプロイします。
まずは モデルデプロイ の画面に遷移し、左上の 作成ボタン をクリックします。
すると画面右側にデプロイするモデルの設定画面が表示されるので、それぞれ項目を埋めていきます。
埋めるとこんな感じ。問題なければ 保存 をクリック。(モデルデプロイ名はAPI利用する際に使用されるのでちょっと注意が必要です)
デプロイが完了すると一覧に表示されます。
状態が "Succeeded" になっているので既に利用可能です。
早速お試しでチャットをすることもできるのですが、ちょっと我慢。チャットをするには Azure Portal から Azure OpenAI Studio に移動しないといけません。後からでもいいのですが、先にAPIアクセスを行う際のキーを確認しておきましょう。
キーとエンドポイントをクリックします。
キーの表示 ボタンをクリックすると ***** となっている部分が解除されます。
見えないままでもコピーボタンは機能するのでコピーしてどこかにメモしておきます。
試しにチャットしてみる
モデルのデプロイまで完了し、利用可能になっているので試しにWeb上でチャットしてみます。
まずは、 Azure OpenAI Studio に移動しなければいけないので、リソースの概要ページへ移動し、表示されているリンクをクリックしましょう。
クリックすると↓のような画面に遷移します。
今回はサクッとチャットしてみたいだけなので左側メニューの「プレイグラウンド」内の「チャット」を選択。
画面中央の「チャット セッション」のところからチャットできるのでちょっと会話してみましょう。
あ、AzureにきてもOpenAIって自己紹介になるんですね。とりあえずOpenAIのモデルが動いていそうなのは確認できたのでAPI繋いでみることにします。
Azure OpenAI ServiceのAPIを利用する
最終的にSlackのbotにするので、グローバルでアクセスできるところにデプロイが必要です。Azure App Serviceにデプロイする想定で .NET を使います。
.NET で直接エンドポイントを叩いてもいいのですが、 NuGet に "Azure.AI.OpenAI" というパッケージが公開されているのでこれを使います。
コード自体は結構シンプルです。
C#private readonly OpenAIClient client = new OpenAIClient(
new Uri("https://<リソース名>.openai.azure.com"),
new AzureKeyCredential("<モデルデプロイ後にコピーしたキー>"));
上記のコードで OpenAIClient を生成し、
C#var response = await client.GetChatCompletionsAsync(
"<モデルデプロイ名>",
new ChatCompletionsOptions()
{
Messages =
{
new ChatMessage(ChatRole.System, @""),
new ChatMessage(ChatRole.User, "<ここにユーザーの入力を入れる>")
},
// 温度パラメータ
Temperature = (float)0.7,
// 最大トークン数パラメータ
MaxTokens = 800,
// 上位Pパラメータ
NucleusSamplingFactor = (float)0.95,
FrequencyPenalty = 0,
PresencePenalty = 0
}
);
このコードで非ストリーミングなレスポンスの取得を行います。
レスポンスの取得後、結果は
C#var result = response.Value;
Console.WriteLine(result.Choices[0].Message.Content);
でAPIからの返答が確認可能です。
Slackにくっつける - 実装
まず、Slack上でbotを作成します。
※Slackのbotアカウントの作成方法やEventの受信設定などは少々複雑なのでここでは割愛します。
Eventを受信し、自分(botアカウント)へのメンションがあったときに反応するように実装します。
botプログラムは全てを自前実装すると とてもたいへん なので SlackNet を利用します。SlackのAPIをwrapしたライブラリで大きな手間をかけることなく、botが実装できます。
j前提
- .NET: 7.0
- SlackNet.AspNetCore: 0.10.22
- SlackNet.Extensions.DependencyInjection: 0.10.22
- Azure.AI.OpenAI: 1.0.0-beta.5 (プレビュー版なので注意)
まずは Program.cs で SlackNet を DIコンテナ に登録します。
C#builder.Services.AddSlackNet(c => c
.UseApiToken("<xoxbから始まるAPIトークン>")
.RegisterEventHandler<MessageEvent, BotHandler>());
var app = builder.Build(); // 自動生成で記載あり
app.UseSlackNet(c => c
.UseSigningSecret("<SigningSecret>")
.UseSocketMode(false));
BotHandler クラスでメッセージが送信された時のイベントを処理するように設定します。
UseApiToken, UseSigningSecret は Slack の botアカウント設定画面より取得します。コード上にベタ書きはとてもおすすめできませんので、環境変数から読むようにするなど工夫をするといいです。
次に、BotHandlerクラスの実装です。
C#public class BotHandler : IEventHandler<MessageEvent>
{
public const string Trigger = "<botアカウントID>";
private readonly ISlackApiClient _slack;
private readonly OpenAIClient client = new OpenAIClient(
new Uri("https://openaiforblog.openai.azure.com"),
new AzureKeyCredential("<ひみつ>"));
public BotHandler(ISlackApiClient slack)
{
_slack = slack;
}
public async Task Handle(MessageEvent slackEvent)
{
if (slackEvent.Text?.Contains(Trigger, StringComparison.OrdinalIgnoreCase) == true)
{
var responseWithoutStream = await client.GetChatCompletionsAsync(
"gpt4",
new ChatCompletionsOptions()
{
Messages =
{
// システムプロンプトは何も与えない
new ChatMessage(ChatRole.System, @""),
// 入力からメンションを切り捨ててプロンプトに
new ChatMessage(ChatRole.User, slackEvent.Text.Remove(0, 12))
},
Temperature = (float)0.7,
MaxTokens = 800,
NucleusSamplingFactor = (float)0.95,
FrequencyPenalty = 0,
PresencePenalty = 0
});
var result = responseWithoutStream.Value;
await _slack.Chat.PostMessage(new Message
{
Text = result.Choices[0].Message.Content,
// 返信先チャンネルID
Channel = slackEvent.Channel,
// 返信先スレッドタイムスタンプ
ThreadTs = slackEvent.EventTs,
});
}
}
}
botアカウントのID宛てにメンションをするので頭のメンション部分を切り捨ててOpenAIへの入力として使います。
Slackから受信 → Azure OpenAIを叩く → Azure OpenAIのレスポンスを使ってSlackへレスポンスを返す
という処理の流れです。
あとはこれをAzure App Serviceにデプロイすれば実装完了です。大したことしてません。
Slackにくっつける - 結果
デプロイとか疎通確認とか諸々が完了したら試してみましょう。
すごい
そんなこんなでSlackにChatGPT(GPT-4)が召喚できちゃいました。メインで使っているSlackから利用できるようにすることでSlackに入っている人であれば誰でも使えるようになり、便利です。業務効率も使われ方次第で上がるかなーと思います。
Azure OpenAI Serviceを使うことで得られる利点
いろいろあると思うのですが、データ保護が一番大きな利点かなと個人的には思います。
OpenAI(Web版)ではオプトアウトしない限りデータが保護されない (=OpenAIによって再学習などに用いられる)
のに対して、
Azure OpenAI Serviceでは、
Training data provided by the customer is only used to fine-tune the customer's model and is not used by Microsoft to train or improve any Microsoft models.
- https://learn.microsoft.com/en-us/legal/cognitive-services/openai/data-privacy より
とあるため、情報漏洩リスクの軽減が図れます。
ある意味では情報漏洩リスクを回避しつつChatGPTで業務効率化とも言えるかもしれませんね。
他には VNet と統合ができるため既存Azure VDIなどを展開している場合VDIからのみアクセス可能なAzure OpenAIの機能を持った業務アプリを作る といった場合には有用かと思います。
おわりに
サクっとbotが作れる世の中最高。
便利なもの作ったので効率よく仕事も捌いていきたいですね。
それでは。
余談
タイトルはChatGPTに考えてもらったのをちょっといじってます