OpenAIクラスを読む①

# 目次
1. はじめに
2. 対象
3. 環境
4. 内容
5. OpenAIクラス
6. API_Key
7. Completionsクラス
8. おわりに

# 1. はじめに
OpenAIのAPIを触るにあたって、勉強した内容を共有しようという目的です。
初めてこのような文章を書くため、読みづらいと思います。
OpenAI公式の[API Refernce](https://platform.openai.com/docs/api-reference/introduction)を読む方が参考になります。

# 2. 対象
この記事の対象は実際にOpenAIのAPIを触って動作まで行っているが、OpenAIクラスの処理がよく分からないと思っている人です。言葉を選ばずに言うなら、**インターネット上のコードをコピペしているだけの人**です。
# 3. 環境

* エディタ　 : Visual Studio Code
* 使用言語　 : Python 3.11.11
* バージョン : OpenAI 1.68.2
# 4. 内容
本記事で扱う内容をここで示しておきます。
1. OpenAIクラス
    * コンストラクタ
2. API_Key
    * 前提知識
    * 確認事項
3. Completionsクラス
    * 概要
    * createメソッド

# 5. OpenAIクラス
OpenAIクラスはopenaiパッケージの_client.pyから確認することができます。
このクラスのコンストラクタでは後に説明するAPI_Keyの設定やChatクラスなど様々な機能のコンストラクタを作成しています。引数には色々代入することができますが、準備を済ませているなら何も代入する必要はありません。
# 6. API_Key
### 前提知識 ###
API_KeyはAPIを使う上で必ず必要になるものです。API_Keyの取得に関しては色々な方が説明されていますので割愛します。問題なく動作している人は次の確認事項を飛ばしてもらって構いません。

### 確認事項 ###
openaiパッケージの_client.py 104~117行目を引用します。

```python:_client.py
        """Construct a new synchronous OpenAI client instance.

        This automatically infers the following arguments from their corresponding environment variables if they are not provided:
        - `api_key` from `OPENAI_API_KEY`
        - `organization` from `OPENAI_ORG_ID`
        - `project` from `OPENAI_PROJECT_ID`
        """
        if api_key is None:
            api_key = os.environ.get("OPENAI_API_KEY")
        if api_key is None:
            raise OpenAIError(
                "The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable"
            )
        self.api_key = api_key
```
ここで述べられていることを簡単に説明しますと、
* __API_KeyはOPENAI_API_KEYという環境変数から持ってくる。__
* __設定されていなかったらエラーを吐く。__
つまり、OpenAIクラスのコンストラクタはこのように作成することになります。
```python:example_1.py
client = OpenAI()
#dotenvを使う方法.無難.とりあえずこれで良い.
```
```python:example_2.py
OPENAI_API_KEY = "Your API Key" 
client = OpenAI()
#dotenvを使わない方法1.セキュリティが怪しい.
```
```python:example_3.py
key = "Your API Key"
client = OpenAI(api_key=key) 
#dotenvを使わない方法2.セキュリティが怪しい.
```

# 7. Completionsクラス
ほとんどが引用になってしまうため、コードは載せません。ファイル名と行数を記してありますので、ご自身の環境でご覧ください。
### 概要 ###
Completionsクラスは会話生成を行います。Chatクラスを介することで、会話履歴を踏まえた回答が返ってくるらしいです(未確認)。

### createメソッドについて ###
返答を取得するには以下のようなコードを書くことになります。
```python:example_1.py
response = client.chat.completions.create(model="gpt-4o",messages=[~~~]) 
#messagesの中身は省略した.
print(response.choices[0].message.content) #←ナニコレ.
```
ここから、おまじないのようなresponse.choices[0].message.contentについて考えていきます。
**openaiパッケージのcompletions.py 80~958行目**にcreateメソッドが書かれているので読んでみると、ここから以下の2点が分かります。

1. 引数は最低限messagesとmodelを指定すれば良い
2. ChatCompletionクラスを返す

次に、このChatCompletionクラスについて見てみます。
**chat_completion.py 43~73行目**をご覧ください。
(service_tierとsystem_fingerprintに関してはあまり分からなかったので触れません。)
このクラスの中身を分かる範囲でまとめると以下のようになっています。
* ID
* 時間
* モデル
* トークンの使用量
* 返答(Choiceクラス)のリスト

**このChoiceクラスは同ファイル内の22~40行目**です。
このクラスも同じようにまとめると以下のようになっています。
* 終了した理由
* 番号
* 生成時のログ
* ChatCompletionMessageクラス

最後にChatCompletionMessageクラスについて見てみます。
chat_completion_message.py 48~79行目です。
このクラスも同じようにまとめると以下のようになっています。
* 返答内容
* 役職
* 注釈
* ツールの呼び出し

ここでようやく返答内容が登場しました。

つまり、response.choices[0].message.contentは、

**ChatCompletionクラスの中にある、Choiceクラスのリストの1番目にある、ChatCompletionMessageクラスにある、返答内容**を指しているということになります。

# 8. おわりに
次回はEmbeddingsクラス、Filesクラスを予定しています。
何か改善点などがありましたらお教えいただければ幸いです。