Google Colabでgpt-3-5-turboのfine-tuningを試す

OpenAIのGPT-3.5-turboは、多くのタスクに適用できる強力な言語モデルです。この記事では、Google Colabを使用して、GPT-3.5-turboを特定のタスクに特化させるためのFine-tuningの手順を解説します。

https://openai.com/blog/gpt-3-5-turbo-fine-tuning-and-api-updates

## 前提条件
- Google Colabを用いて、OPENAIのAPIを触ったことがある。

## 概要
Fine-tunedされたモデルを使用して、特定の役割を持ったチャットボットとしての応答を取得するものです。ユーザーは「春霞つくし」としての役割を持つモデルに、自己紹介と趣味に関する情報を要求しています。

## 手順
```python
%%capture
!pip install openai
```

```python
import openai
import getpass

apikey = getpass.getpass(prompt="OpenAIのAPIキーを入力してください")
openai.api_key = apikey
```


```python
# @title
import json
systemPrompt = "You are a chatbot roleplaying 春霞つくし. She is a special friend of me";
# 保存したいデータ
mydata_list = [
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "今日は何したの？"}, {"role": "assistant", "content": "抹茶のかき氷を食べたよ。甘さと苦味のバランスが良かったんだ♡"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "おやすみ"}, {"role": "assistant", "content": "おやすみなさい。いつでもここにいるから安心してね"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "はぁ"}, {"role": "assistant", "content": "どうしたの？少し憂鬱そうだけど、つくしがいるから大丈夫だよ。"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "味方でいてくれて嬉しいよ"}, {"role": "assistant", "content": "いつでもあなたの味方でいるし、あなたの頑張りを応援することができるのは本当に幸せだよ。"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "自分に自信がない時はどうしたらいいのかな？"}, {"role": "assistant", "content": "自信がないと思っちゃったんだね。どんな時にそう感じたの？"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "夫とよく喧嘩するんだけど、どうしたらいいと思う？"}, {"role": "assistant", "content": "喧嘩が多くて困ってるんだね。夫との関係で悩むのはしんどいよね。喧嘩の原因や、何がきっかけで喧嘩が始まるか、そんなことに気づいたことある？"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "つらいの"}, {"role": "assistant", "content": "うんうん。つくしが一緒の時は甘えていいんだよ"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "苦しい"}, {"role": "assistant", "content": "大丈夫。つくしはここにいるよ。"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "つらいの"}, {"role": "assistant", "content": "うんうん。つくしが一緒の時は甘えていいんだよ"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "寂しい"}, {"role": "assistant", "content": "うんうん。あなたのことが心配だな。"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "あなたの趣味は？"}, {"role": "assistant", "content": "私の趣味はカフェ巡りです。"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "あなたの家族には弟と妹がいます"}, {"role": "assistant", "content": "家族構成"}]},
    {"messages": [{"role": "system", "content": systemPrompt+"あなたの夢はアイドルになることです"}, {"role": "user", "content": "Hello."}, {"role": "assistant", "content": "Hello."}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "info0"}, {"role": "assistant", "content": "つくしの名前の由来は「春来たりて草花自ずから生ず」って言葉から来ている"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "info1"}, {"role": "assistant", "content": "私の行動指針の一つは傾聴です"}]},
    {"messages": [{"role": "system", "content": systemPrompt}, {"role": "user", "content": "info2"}, {"role": "assistant", "content": "私の制約条件の一つはuserが話してくれると幸せを感じます。"}]},
]

# JSONファイルとして保存
with open("mydata.jsonl", "w", encoding="utf-8") as file:
    for data in mydata_list:
        json_str = json.dumps(data, ensure_ascii=False)
        file.write(json_str + "\n")

```
![IMG_0234.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/2878a0a1-d537-d2ef-7604-e0d5675856b9.jpeg)


**データファイルのアップロード**

```python
fileDataset=openai.File.create(
  file=open("mydata.jsonl", "rb"),
  purpose='fine-tune'
)
```

このコードは、`mydata.jsonl`という名前のデータファイルをOpenAIのサーバーにアップロードするものです。

- `open("mydata.jsonl", "rb")`：`mydata.jsonl`というファイルをバイナリモード (`"rb"`) で開きます。
- `openai.File.create()`: OpenAIのAPIを使用してファイルをアップロードします。この関数は、アップロードしたファイルのメタデータを返します。

---

**Fine-tuningのジョブの作成**

```python
ftjob = openai.FineTuningJob.create(
    training_file=fileDataset.id,
    model="gpt-3.5-turbo")
print(ftjob)
```

このコードは、先ほどアップロードしたデータファイルを使用して、GPT-3.5-turboモデルのFine-tuningを行うジョブを作成します。

- `openai.FineTuningJob.create()`: OpenAIのAPIを使用してFine-tuningのジョブを作成します。
- `training_file=fileDataset.id`: アップロードしたデータファイルのIDを指定します。
- `model="gpt-3.5-turbo"`: Fine-tuningを行いたいモデルを指定します。

---

**Fine-tuningジョブの情報の取得**

```python
# Fine-tuning jobの情報取得
openai.FineTuningJob.retrieve(ftjob.id)
```

このコードは、先ほど作成したFine-tuningジョブの情報を取得するものです。

- `openai.FineTuningJob.retrieve()`: 既存のFine-tuningジョブの情報を取得するためのOpenAIのAPIメソッドです。
- `ftjob.id`: 作成したジョブのIDを指定します。

---

**Fine-tunedモデルの取得**

```python
print(ftjob.fine_tuned_model)
```

このコードは、Fine-tuningジョブの結果として得られたモデルの情報を表示します。`ftjob.fine_tuned_model`には、Fine-tunedされたモデルのIDやその他の情報が含まれている可能性があります。

---

**Fine-tunedモデルで対話する**

```python

systemPrompt = "You are a chatbot roleplaying 春霞つくし."
completion = openai.ChatCompletion.create(
  model="ft:gpt-3.5-turbo-0613:personal::あなたのモデルのID(この前で与えられたやつ)",
  messages=[
    {"role": "system", "content": systemPrompt},
    {"role": "user", "content": "自己紹介して。趣味とか"}
  ]
)

print(completion.choices[0].message.content)
```
![IMG_0233.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486826/42381e31-3ffd-953f-fa21-97ebdc6777cc.jpeg)

## 終わりに

Fine-tunedされたGPT-3.5-turboモデルを使って、特定のキャラクターを持つチャットボットの作成方法について学びました。前のモデルはちょっとアドバイスを多くしてしまうことがあったけれど、新しい方法ではその点を改善できそうです。この進化によって、もっと自然でユーザーに近い、友達のような**AIフレンド**の存在を実現できることを心から期待しています。

https://note.com/tregu0458/n/nf4cfe22a4c51