ChatGPT APIを使ってみよう（PowerShellで）


追記：
 拙作ではありますがPowerShellからChatGPTを含むOpenAI APIの機能を使うためのモジュール「[PSOpenAI](https://github.com/mkht/PSOpenAI)」を作成・公開しています。細かい仕組みはいいからとにかくPowerShellからChatGPTが使いたい！という方はお試しください。
https://github.com/mkht/PSOpenAI

最近とても流行っている ChatGPT が API 経由で使えるようになりました。(2023/03/02)
すでにAPIの使用法はいろいろなところで解説されていますが、[公式のリファレンスガイド](https://platform.openai.com/docs/guides/chat/introduction)も含め、多くが Python での実行例となっています。
ですので私は PowerShell を使って ChatGPT API を使用する方法をまとめることにしました。

## 0. APIの料金について
まずは大事なお金の話。
ChatGPT の API は有料で、価格は 1,000 トークンあたり $0.002 となっています。
トークンとはAIがテキストを読み取る単位のことらしいです。
つまり長い文章ほどトークンが多くなるということです。
さらにこちらからの質問文だけでなく、AIからの回答文についても課金対象のトークンとなります。
要するにAIと長文の会話をするとたくさん課金されるという仕組みです。

なお OpenAI のアカウントを作ると有効期限3か月の $18 お試しクレジットがもらえるので、
とりあえず試したいというだけであればお金はかかりません。
クレジットカードなどの登録も不要です。

## 1. APIキーの取得
まず API を実行するための認証用キーを取得します。
OpenAI のアカウントは事前に作成しておいてください。

https://platform.openai.com/account/api-keys にアクセスすると`[+ Create new secret key]`というボタンがありますので、クリックします。
するとAPIキーが生成・表示されます。
このAPIキーは一度しか表示されず、再表示できませんので必ずここでコピーしておいてください。
また、APIキーは誰かに漏らしてしまうことのないよう注意してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/177762/5550ec4b-91dd-629d-558f-eda88ca4f2e5.png)

## 2. 質問をしてみる
以下のコードは必ず PowerShell 7.2 以降で実行してください。
Windows に標準で入っている PowerShell 5.1 では実行できません。

(2023/03/05 追記)
PowerShell 5.1 でも動くように少し手を加えたコードをGistに上げました。
PowerShell 7 を導入できない環境の方はこちらを参照してください。
https://gist.github.com/mkht/1be9ee5f53ec93a5793f330bf6c35834

```PowerShell
# まず ChatGPT を使うための各種パラメータを指定します。
$Token = 'ここにAPIキーを入れてください'
$Uri   = 'https://api.openai.com/v1/chat/completions'
$PostBody = @{
  model = 'gpt-3.5-turbo'
}

# 次に質問する文章を決めます。
$PostBody.messages = @(
  @{
    role = 'user'
    content = 'ここにChatGPTへの質問を書いてください'
  }
)

# 最後に ChatGPT に質問を投げます
$Response = Invoke-WebRequest `
  -Method Post `
  -Uri $Uri `
  -ContentType 'application/json' `
  -Authentication Bearer `
  -Token (ConvertTo-SecureString -AsPlainText -String $Token) `
  -Body ([System.Text.Encoding]::UTF8.GetBytes(($PostBody | ConvertTo-Json -Compress)))

# 返ってきた回答を表示します
$Answer = ($Response.Content | ConvertFrom-Json).choices[0].message.content
Write-Output $Answer
```

上記の PowerShell コードを使って簡単な質問をしてみると、ChatGPT が答えを返してくれます。
試しに`アメリカの人口は？`と聞いてみたら、きちんと日本語で対応してくれました。
```
2021年11月時点でアメリカ合衆国の人口はおよそ330,009,000人です。
```

## 3. コードの説明
上記の PowerShell コードから ChatGPT API を使ううえでポイントになる部分を解説していきます。
```PowerShell
$PostBody = @{
  model = 'gpt-3.5-turbo'
}
```
この`model`のところには使用したいAIモデルの名前を指定します。
現在のところ`gpt-3.5-turbo`か`gpt-3.5-turbo-0301`の2つしか選べません。
（というか`gpt-3.5-turbo`を指定すると自動的に`gpt-3.5-turbo-0301`が使われるので実質1つです）
おそらく今後同じ`gpt-3.5-turbo`でも細かいバージョン違いだったり、全く違うAIモデルが選べるようになるのではないかと思います。

```PowerShell
$PostBody.messages = @(
  @{
    role = 'user'
    content = 'ここにChatGPTへの質問を書いてください'
  }
)
```
`content`のところが ChatGPT への質問文になります。
`role`に`user`を指定してますが、これは「このメッセージはこちらからAIへの質問文ですよ」という意味です。
指定できる値は以下の3種類です。

* `system`： AIの性格を指定する文を意味します。必須ではないので指定しなくてもいいです。
* `user`： こちらからAIへの質問文です。
* `assistant`： AIからの回答文です。

`user`以外の使い方は後ほど説明します。

```PowerShell
$Response = Invoke-WebRequest `
  -Method Post `
  -Uri $Uri `
  -ContentType 'application/json' `
  -Authentication Bearer `
  -Token (ConvertTo-SecureString -AsPlainText -String $Token) `
  -Body ([System.Text.Encoding]::UTF8.GetBytes(($PostBody | ConvertTo-Json -Compress)))
```
ここまで設定したパラメータで`HTTP POST`リクエストを ChatGPT API に送り、回答を得ている処理です。
読みやすくなるよう改行を入れているので長く見えますが、実際には`Invoke-WebRequest`コマンドを一回実行しているだけです。

PowerShell で実行する場合のハマりポイントとしては
最後の`-Body`で始まる行。
まず`($PostBody | ConvertTo-Json -Compress)`で PowerShell のオブジェクトをJSON形式の文字列に変換します。
さらにそのJSON形式文字列を`[System.Text.Encoding]::UTF8.GetBytes()`でUTF-8にエンコードして送らなければなりません。
（送るのが英文だけならUTF-8エンコードしなくてもいいのですが、日本語を含める場合は必須となります）

```PowerShell
$Answer = ($Response.Content | ConvertFrom-Json).choices[0].message.content
```
ChatGPTから返ってきたレスポンスには様々な情報が含まれていますが、この一行でAIの回答文章だけを抜き出しています。
レスポンスに他にどのような情報が含まれているか見てみましょう。

```PowerShell
C:\> ($Response.Content | ConvertFrom-Json)
id      : chatcmpl-7kbswwbVoTxW5mAvtnzM3Sk8LQo47
object  : chat.completion
created : 1677758378
model   : gpt-3.5-turbo-0301
usage   : @{prompt_tokens=16; completion_tokens=33; total_tokens=49}
choices : {@{message=; finish_reason=stop; index=0}}
```

注目は`usage`のところで、
　`prompt_tokens=16` ： 質問文のトークン数
　`completion_tokens=33` ： AIからの回答文のトークン数
　`total_tokens=49` ： 質問と回答の合計トークン数
となっています。
つまり、
```
私 : アメリカの人口は？
AI : 2021年11月時点でアメリカ合衆国の人口はおよそ330,009,000人です。
```
このやりとりで49トークンを消費したことになります。
1,000トークン ＝ 0.002ドル なので 0.000098ドル ≒ 0.013円 くらいかかりました。

## 4. 会話してみる
ここまでで ChatGPT に1個の質問をして、1個の回答をもらうことができました。
次は連続したやり取り、つまり会話をしてみましょう。

ChatGPT と会話をするには、AIが会話の文脈を把握できるよう、質問文と一緒にこれまでのやりとりの履歴を送る必要があります。
先ほど示した ChatGPT に質問する PowerShell コードのうち、質問文を決める箇所を以下のように変えてください。

```PowerShell
# 次に質問する文章を決めます。
$PostBody.messages = @(
  @{
    role = 'user'
    content = 'アメリカの人口は？'  #最初にした質問
  },
  @{
    role = 'assistant'
    content = '2021年11月時点でアメリカ合衆国の人口はおよそ330,009,000人です。' #最初の質問に対するAIの回答
  }
  @{
    role = 'user'
    content = 'では日本はどうですか？' #AIの回答に対する追加の質問
  }
)
```

`messages`に指定するオブジェクトを3つに増やしました。
最初の2つがこれまでの AI との会話の履歴になっていて、最後の1つが新しい質問です。
先ほど少し説明した`role`に着目すると、
`role = 'user'`はこちらからAIへの質問、
`role = 'assistant'`がAIからこちらへの回答となっていることがわかります。

コードの他の部分は何も変えずに実行すると、AIからこのような回答が返ってきました。
これまでの会話の履歴をAPIリクエストに含めて質問をしたことで、「では日本はどうですか？」という単体では何を聞いているのか不明瞭な質問文に対しても、文脈から人口を聞いているのだとAIが判断できていることが分かります。
```
2021年11月時点で日本の人口はおよそ126,365,000人です。
```

この要領で`messages`に指定するオブジェクトに次々に会話履歴と新しい質問を追加してリクエストを投げていくことで、AIと連続した会話ができるようになります。

ただし、**会話の履歴部分もトークンを消費します**のでやり取りの回数が増えるほど消費トークンはどんどん重くなっていき課金額が増えます。
長話をする場合は古い会話履歴を適度に切り捨てる、短い文章に要約するなどの工夫が必要になるかと思います。

## 5. AIの性格を変えてみる
最後にAIの性格を変えてみましょう。
`messages`オブジェクトの一番最初に`role = 'system'`を指定したメッセージを追加すると、AIの性格（回答の挙動）を指定することができます。
（ただ ChatGPT のAIモデルではこの指定はあまり重視されないらしく、狙い通りの挙動にならない場合も多いようです）

```PowerShell
# 次に質問する文章を決めます。
$PostBody.messages = @(
    @{
        role    = 'system'
        content = 'あなたはフランス人です。フランス語で回答してください' #AIの挙動指定
    }
    @{
        role    = 'user'
        content = 'アメリカの人口は？' #質問
    }
)
```

このような形で指定します。
AIのことをフランス人だと思い込ませ、質問の言語に関係なくフランス語で回答させるように指定してみました。
質問はこれまでと同じ日本語で「アメリカの人口は？」と聞いてみます。

狙い通り、AIからの回答がフランス語になりました。
（私はフランス語が読めないので文法など合っているかは不明ですが...）
```
La population des États-Unis est d'environ 330 millions d'habitants.
```

## 終わり
ChatGPTとの会話はなかなか面白いですね。
あまり長い質問をしなければ消費トークンもそれほど多くならないので、無料トライアル$18の範囲内でもかなり遊べると思います。