超初心者向けChatGPT APIの始め方

## イントロ
ハロー、ジェントルマン　アンド　マドモアゼル。
年末年始皆様いかがお過ごしでしょうか？
突然ですが皆様LLM気になっちゃいますよね？
私もそうです。
ということで、超初心者の私がChatGPT APIを使い始めたので、ちょっとメモ程度に共有させていただきます。

## 目的
ChatGPT APIを使い始めるまでの方法解説。

## 環境準備
### 前提の環境
- Ubuntu 20.04
- Python 3.10.13

### OpenAI APIキーの取得
[OpenAIのページ](https://openai.com/)に行き、APIキーを取得します。私の場合は会社で契約していたので、システム担当者にAPIキーを発行してもらいましたが。

## OpenAI quick startを試す
[OpenAIのquick start](https://platform.openai.com/docs/quickstart?context=python)ページを見て初期設定をします。
一応簡単にやることを書いておきます。

1. OpenAI quick startのための仮想環境設定
    ```bash
    cd <your_project_dir> #(e.g. cd ~/openai_quickstart)
    python -m venv openai-env
    source openai-env/bin/activate
    pip install --upgrade openai
    ```
1. OpenAI APIキーのbashrcへの登録
~.bashrcをエディタで開き、例えば一番下の行に、OpenAIのAPIキーを下記のように記入しておく。
`export OPENAI_API_KEY='your-api-key-here'`
　（これでローカルマシンでいつでも`os.environ["OPENAI_API_KEY"]`というpythonのコードでAPIキーが呼び出せます。）

1. テスト実行
以下のコードを、openai-test.pyというファイル名で保存し、`python openai-test.py`として実行する。
    ```python
    from openai import OpenAI
    client = OpenAI()
    
    completion = client.chat.completions.create(
      model="gpt-3.5-turbo",
      messages=[
        {"role": "system", "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."},
        {"role": "user", "content": "Compose a poem that explains the concept of recursion in programming."}
      ]
    )
    
    print(completion.choices[0].message)
    ```
    以下のような応答が返ってくれば成功。
    ```
    ChatCompletionMessage(content="In the realm of code, a concept does unfold,\nWhere logic dances, and stories are told,\nRecursion, dear friend, is a symphony rare,\nA loop intertwined, with a touch of flair.\n\nImagine a mirror, reflecting the light,\nA call to itself, a wondrous sight,\nA function that calls, with steps so precise,\nUnraveling mysteries, like a roll of the dice.\n\nWith each tiny step, new paths are revealed,\nAn enchanting dance, that's artfully concealed,\nAs one problem's solved, it's onto another,\nA cascade of solutions, one after the other.\n\nLike a snowflake falling, gliding through space,\nRecursive patterns, embrace the embrace,\nA chain of actions, sequenced with care,\nA graceful design, in this digital affair.\n\nFor in recursion's embrace, there lies potent truth,\nA rhythm, a dance, that echoes from youth,\nWith each repetition, a problem unraveled,\nA universe of possibilities, marvelously traveled.\n\nYet tread with caution, dear ones, heed my voice,\nRecursive abyss, can leave you no choice,\nEnd conditions must be set, the base case prepared,\nLest the loop becomes infinite, a nightmare ensnared.\n\nSo behold the magic, the power it holds,\nIn recursion's embrace, the story unfolds,\nWith elegance and wonder, it guides us along,\nIn the world of programming, where dreams become strong.", role='assistant', function_call=None, tool_calls=None)
    ```
    あとは、contentの中身を変えて、chatGPTのようにプロンプトで遊んでみましょう。

## Function callingを試す
ここまでだと、web版のchatGPTとできることが変わらなくてつまらないので、とりあえずfunction callingを試してみましょう。
　例としてsinc関数を、必要性含めてchatGPTに判断して呼び出してもらい、結果が正しいか確認してみましょう。
　超手抜きですが、以下のコードをpythonで実行してみてください。
```python
import numpy as np
def sinc(x):
    return np.sin(x) / x

sinc(0.001)

functions = [
    {
        "name": "sinc",
        "description": "sinc function",
        "parameters": {
            "type": "object",
            "properties": {
                "x": {
                    "type": "number",
                    "description": "value to calculate sine",
                },
            },
            "required": ["x"],
        },
    }
]

messages = [{"role": "user", "content": "What's the value of sinc at 0.001?"}]

response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=messages,
    functions=functions
)

response_message = response["choices"][0]["message"]

available_functions = {
    "sinc": sinc,
}
function_name = response_message["function_call"]["name"]
fuction_to_call = available_functions[function_name]
function_args = json.loads(response_message["function_call"]["arguments"])

function_response = fuction_to_call(
    x=function_args.get("x"),
)

print(function_response)
```
両方のprint文で `0.9999998333333416`　という値が表示されたので、ちゃんとsinc関数をよんでくれたようです。
ただ、`funtions=[]` の定義のところは正直怪しいので、もうちょっと勉強してみます。

## まとめ
本当はRetrieval Augmented Generation(RAG)を使ったアシスタントをつくるところまでやりたかったのですが、ちょっと時間がなくて、最後は駆け足でfunction callingを試す程度になってしまいました。
　またおいおい勉強していきます。

### 参考書
[ChatGPT/LangChainによるチャットシステム構築［実践］入門; 吉田 真吾,大嶋 勇樹](https://www.amazon.co.jp/ChatGPT-LangChain%E3%81%AB%E3%82%88%E3%82%8B%E3%83%81%E3%83%A3%E3%83%83%E3%83%88%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E6%A7%8B%E7%AF%89%EF%BC%BB%E5%AE%9F%E8%B7%B5%EF%BC%BD%E5%85%A5%E9%96%80-%E5%90%89%E7%94%B0-%E7%9C%9F%E5%90%BE/dp/4297138395)