OpenAI API移行

# OpenAI API移行

# 概要

大規模言語モデル（LLM）の「GPT-4」および「GPT-3.5」ファミリーの最新スナップショットモデル(0613)をリリースされ、旧モデルが非推薦となる[アナウンス](https://openai.com/blog/gpt-4-api-general-availability)があったので、OpenAIのAPIを「Chat Completions API」形式に移行しなければいけないため、その内容をまとめます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/124b6183-de3d-437e-6d63-252b8255f887.png)

# OpenAI API入門

こちらはご参照ください。よりAPI移行の内容が理解しやすくなります。

https://qiita.com/motoJinC25/items/aba3c8fb4d5028cb170f

# プロンプトからメッセージへ

API移行のポイントは「プロンプト」から「メッセージ」に変更することです。その内容が理解できれば、OpenAIのAPIを使ったアプリケーション開発によい精度を得ることになります。

## 用語理解 : Chat Completions APIとCompletions API

OpenAIのAPIにはChat Completions APIとCompletions APIという2つの主要なタイプがあります。

### Chat Completions API

APIのエンドポイント : https://api.openai.com/v1/chat/completions

Request Bodyの設定項目：messages (メッセージ)

一連の対話を扱うように設計されています。つまり、一つのプロンプトだけでなく、一連のメッセージを入力として受け取り、それらに基づいて応答を生成します。

```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.ChatCompletion.create(
  model="gpt-4",
  messages=[
    {"role": "system", "content": "あなたはジャーナリストです。"},
    {"role": "user", "content": "OpenAI社について説明してください。"}
  ]
)
```

### Completions API

APIのエンドポイント : https://api.openai.com/v1/completions

Request Bodyの設定項目：prompt (プロンプト)

一つのプロンプトから始まり、それに対する一つの応答を生成するように設計されています。つまり、ユーザーが何らかの入力を提供し、APIがその入力に基づいて何らかの完結したテキストを生成します。

```python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.Completion.create(
  model="text-davinci-003",
  prompt="OpenAI社について説明してください。"
)
```

## 手順1. プロンプト内容をメッセージ形式に変更

Completions APIの一つプロンプトに対してUserロール定義のメッセージ形式に変更します。

Userロールの定義意味については[ここ](https://qiita.com/motoJinC25/items/aba3c8fb4d5028cb170f#chat-completions-api%E3%81%AE%E3%83%AD%E3%83%BC%E3%83%AB)をご参照ください。

```json
'prompt' : 'OpenAI社について説明してください。'

↓

'messages': [{'role':'user', 'content':'OpenAI社について説明してください。'}]
```

## 手順2. Systemロール定義追加

Systemロール定義を追加して会話中のモデルの動作をガイドできるようにします。

OpenAIの自然言語モデルの最新バージョン0613では（[ここ](https://qiita.com/motoJinC25/items/aba3c8fb4d5028cb170f#openai%E3%81%AE%E8%87%AA%E7%84%B6%E8%A8%80%E8%AA%9E%E3%83%A2%E3%83%87%E3%83%AB)参考）システムメッセージに操縦性が強化されたので、システムメッセージに示された指示に従うようになったことです。

```json
'messages': [{'role':'user', 'content':'OpenAI社について説明してください。'}]

↓

'messages': [
  {'role':'system', 'content':'あなたはジャーナリストです。'},
  {'role':'user', 'content':'OpenAI社について説明してください。'}
]
```

## 手順3. Assistantロール定義追加とリスト完成

Assistantロール定義を追加して文脈を踏まえて回答できるようにします。そしてメッセージはリストに表示される順序で処理されて回答されます。

```json
'messages': [
  {'role':'system', 'content':'あなたはジャーナリストです。'},
  {'role':'user', 'content':'OpenAI社について説明してください。'}
]

↓

'messages': [
  {'role':'system', 'content':'あなたはジャーナリストです。'},
  {'role':'user', 'content':'OpenAI社について説明してください。'},
  {'role':'assistant', 'content':'イーロン・マスクさんはOpenAIを辞めた。'}
]
```

# 完成コード

## Python

```json
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.ChatCompletion.create(
  model="gpt-4",
  messages=[
    {"role": "system", "content": "あなたはジャーナリストです。"},
    {"role": "user", "content": "OpenAI社について説明してください。"},
    {"role": "assistant", "content": "イーロン・マスクさんはOpenAIを辞めた。"}
  ]
)
```

## curl

```bash
curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4",
    "messages": [{"role": "system", "content": "あなたはジャーナリストです。"},{"role": "user", "content": "OpenAI社について説明してください。"},{"role": "assistant", "content": "イーロン・マスクさんはOpenAIを辞めた。"}]
  }'
```

## PowerShell (Windows)

```powershell
$body = @{
  "model" = "gpt-4"
  "messages" = @(
    @{
      "role" = "system"
      "content" = "あなたはジャーナリストです。"
    },
    @{
      "role" = "user"
      "content" = "OpenAI社について説明してください。"
    },
    @{
      "role" = "assistant"
      "content" = "イーロン・マスクさんはOpenAIを辞めた。"
    }
  )
} | ConvertTo-Json

Invoke-WebRequest `
  -Headers @{"Content-type"="application/json"; "Authorization"="Bearer " + $env:OPENAI_API_KEY} `
  -Method Post `
  -Body $body `
  -Uri 'https://api.openai.com/v1/chat/completions'
```

# Azure OpenAI サービス向け

GPT-35-Turbo および GPT-4 ファミリーモデルを操作するには「Chat Completion API」と「ChatML」の二つオプションがありますが、こちらではOpenAI APIと同じように使える「Chat Completion API」で紹介します。

## Python

```python
import os
import openai
openai.api_type = "azure"
openai.api_base = "https://<リージョン名>.api.cognitive.microsoft.com/"
openai.api_version = "2023-05-15"
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.ChatCompletion.create(
  engine="<デプロイモデル名>",
  messages=[
    {"role": "system", "content": "あなたはジャーナリストです。"},
    {"role": "user", "content": "OpenAI社について説明してください。"},
    {"role": "assistant", "content": "イーロン・マスクさんはOpenAIを辞めた。"}
  ]
)
```

## curl

```bash
curl https://<リージョン名>.api.cognitive.microsoft.com/openai/deployments/<デプロイモデル名>/chat/completions?api-version=2023-05-15 \
  -H "Content-Type: application/json" \
  -H "api-key: $OPENAI_API_KEY" \
  -d '{
    "messages": [{"role": "system", "content": "あなたはジャーナリストです。"},{"role": "user", "content": "OpenAI社について説明してください。"},{"role": "assistant", "content": "イーロン・マスクさんはOpenAIを辞めた。"}]
  }'
```

## PowerShell (Windows)

```powershell
$body = @{
  "messages" = @(
    @{
      "role" = "system"
      "content" = "あなたはジャーナリストです。"
    },
    @{
      "role" = "user"
      "content" = "OpenAI社について説明してください。"
    },
    @{
      "role" = "assistant"
      "content" = "イーロン・マスクさんはOpenAIを辞めた。"
    }
  )
} | ConvertTo-Json

Invoke-WebRequest `
  -Headers @{"Content-type"="application/json"; "api-key"=$env:OPENAI_API_KEY} `
  -Method Post `
  -Body $body `
  -Uri 'https://<リージョン名>.api.cognitive.microsoft.com/openai/deployments/<デプロイモデル名>/chat/completions?api-version=2023-05-15'
```