Azure OpenAI利用の方必見！最新OpenAI Python APIライブラリ v1.x

2023年11月に**OpenAI Python APIライブラリ**がアップグレードされ、**バージョン1.x**となりました。これまで、私も**Azure OpenAI**において**バージョン0.28.1**を利用していましたが、**バージョン1.x**を使うことにしました。この記事では、利用が多いと思われる**Chat Completion API のv0.28.1と v1.x の違い**を中心に書かせて頂いています。なお、他にもいろいろ変更がされていますので、詳細については、Microsoft社の下記のページに載っていますので参考にして頂ければと思います。また、記事の最後の方には、バージョン1.xのライブラリを使い、Windowsのコマンドプロンプト画面の中でGPTと簡易的に会話できるコードも載せました。コマンドプロンプトの黒い画面でGPTと会話してみるのもシンプルで面白いです。

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/how-to/migration?tabs=python%2Cdalle-fix#name-changes

このページによるとv0.28.1 からv1.x へのアップグレードはいわゆる**破壊的変更**であるため、コードをテストして更新する必要があると書かれています。また、openai migrate を使用したコードの自動移行は、Azure OpenAI ではサポートされていないとも書かれています。


## 主なアップデート点
・グローバルな既定値を使用する代わりに、**クライアントをインスタンス化**できるようになりました。
・明示的なクライアントのインスタンス化への切り替え。
・エラーが発生した場合のバックオフによる自動再試行。
・pip install openai または pip install openai --upgrade でOpenAI Pythonライブラリのバージョン1.xがインストールできます。

次のページにもv0.28.1 と v1.x の差異がわかるPythonコード例が載っており、シンプルでわかりやすかったので、サンプルとして、こちらのページからコード例をお借りしました。

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/how-to/chatgpt?tabs=python-new&pivots=programming-language-chat-completions#working-with-the-gpt-35-turbo-and-gpt-4-models


## Pythonにおけるコード例
Chat Completionの使用例:
旧バージョン（0.28.1）の場合:

``` Python
import os
import openai
openai.api_type = "azure"
openai.api_version = "2023-05-15" 
openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT")  # Your Azure OpenAI resource's endpoint value.
openai.api_key = os.getenv("AZURE_OPENAI_KEY")

response = openai.ChatCompletion.create(
    engine="gpt-35-turbo", # The deployment name you chose when you deployed the GPT-3.5-Turbo or GPT-4 model.
    messages=[
        {"role": "system", "content": "Assistant is a large language model trained by OpenAI."},
        {"role": "user", "content": "Who were the founders of Microsoft?"}
    ]
)

print(response)

# To print only the response content text:
# print(response['choices'][0]['message']['content'])
```

新バージョン（1.x）の場合:
``` Python
import os
from openai import AzureOpenAI

client = AzureOpenAI(
  api_key = os.getenv("AZURE_OPENAI_KEY"),  
  api_version = "2023-05-15",
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)

response = client.chat.completions.create(
    model="gpt-35-turbo", # model = "deployment_name".
    messages=[
        {"role": "system", "content": "Assistant is a large language model trained by OpenAI."},
        {"role": "user", "content": "Who were the founders of Microsoft?"}
    ]
)

#print(response)
print(response.model_dump_json(indent=2))
print(response.choices[0].message.content)
```

## 主なコードの変更点
少し細かく見て行きたいと思います。
ライブラリのimport部分は、旧バージョンではimport openaiが使用されていましたが、新バージョンではfrom openai import AzureOpenAIが使用されています。

``` Python
# v0.28.1
import openai
```
``` Python
# v1.x
from openai import AzureOpenAI
```
##
keyを含む環境変数を読み込む部分も、記述方法が変わりました。

``` Python
# v0.28.1
openai.api_type = "azure"
openai.api_version = "2023-05-15" 
openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT")  # Your Azure OpenAI resource's endpoint value.
openai.api_key = os.getenv("AZURE_OPENAI_KEY")

```
``` Python
# v1.x
client = AzureOpenAI(
  api_key = os.getenv("AZURE_OPENAI_KEY"),  
  api_version = "2023-05-15",
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
)
```
##
Completions部分では、旧バージョンではopenai.Completion.create()が使用されていましたが、新バージョンでは**client**.chat.completion**s**.create()が使用されています。"completion"には**s**が付いています。（こう言う細かな仕様は気づかないとはまりそうです。。。）

``` Python
# v0.28.1
response = openai.ChatCompletion.create()
```
``` Python
# v1.x
response = client.chat.completions.create()
```
##
response部分も変わりました。

``` Python
# v0.28.1
print(response['choices'][0]['message']['content'])
```
``` Python
# v1.x
print(response.choices[0].message.content)
```
##
その他多くの多くのメソッド名やクラス名が変更されています。例えば、**openai.api_base**は、**openai.base_url**に、**openai.InvalidRequestError**は、**openai.BadRequestError**に、__openai.Embedding.create()__ は、__client.embeddings.create()__ といった具合です。また、**openai.api_version**や**openai.Engine**等、削除されたメソッド名やクラス名もあります。これらにつきましては、最初に紹介させて頂いたMicrosoft社のページの下の方に一覧表がありますので参考にして頂ければと思います。

## バージョン1.xを使い簡易的な会話コードを書いてみました。
・WIndowsのコマンドプロンプトで試しています。
・実行後、最初に"3"もしくは"4"を入力することでgpt3.5とgpt4を切り替えて使えるようにしています。
・消費されたトークン数を表示するようにしました。
・requirements.txtも載せています。

``` Python
#main.py

import os
from openai import AzureOpenAI
from dotenv import load_dotenv

load_dotenv(".env")

client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_KEY"),
    api_version="2023-05-15",
    azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
)

# モデル選択
model_choice = input("Select the gpt-model. Enter gpt3.5='3' or gpt4='4': ")

if model_choice == "3":
    model_name = "gpt3.5"  # gpt3.5 を選択
elif model_choice == "4":
    model_name = "gpt4"  # gpt4 を選択
else:
    print("Invalid model choice.")
    exit()

conversation = [{"role": "system", "content": "The world's most intelligent AI"}]

while True:
    user_input = input(">>> ")
    if user_input == "":
        break
    conversation.append({"role": "user", "content": user_input})

    response = client.chat.completions.create(model=model_name, messages=conversation)

    generated_message = response.choices[0].message.content
    generated_tokens = response.usage.total_tokens

    conversation.append({"role": "assistant", "content": generated_message})
    print("\n" + generated_message + "\n")
    print("Consumed tokens:", generated_tokens)
```
``` Python
# requirements.txt
annotated-types==0.6.0
anyio==3.7.1
certifi==2023.7.22
click==8.1.7
colorama==0.4.6
distro==1.8.0
h11==0.14.0
httpcore==1.0.2
httpx==0.25.1
idna==3.4
mypy-extensions==1.0.0
openai==1.3.0
packaging==23.2
pathspec==0.11.2
platformdirs==4.0.0
pydantic==2.5.1
pydantic_core==2.14.3
python-dotenv==1.0.0
sniffio==1.3.0
tqdm==4.66.1
typing_extensions==4.8.0
```

### main.pyを実行した画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537852/c8a5f9f4-8d3b-7193-02d3-3587eb521816.png)

（プログラムを終了させる時は CTL + C で終了させて下さい。） 

## おわりに
私もまだまだ理解の途中なのですが、この記事を通じて、Azure OpenAI サービスにおけるOpenAI Python APIライブラリのバージョンアップとそれに伴う主な変更点の理解の一助になれば幸いです。最新バージョンの機能を活用して、セキュアでパワフルなAzure OpenAIサービスを利用して行ければと考えています。