GPT3.5をファインチューニングして社内FAQシステムを作成する



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

2023/8/22にOpenAIがGPT-3.5 Turboのファインチューニングを公開しました。このアップデートにより、開発者は独自のデータを使用してGPT-3.5 Turboをカスタマイズすることができるようになりました。(GPT4は今年秋に実装予定らしい)

**追記**
社内QAは想定ユースケースではなく、機能しない可能性が高いです。
詳しくは公式ページの情報や、さらにはRAGのご検討を。


## 準備
必要ライブラリのimportとAPI keyの設定. 
```python
import openai
import pandas as pd
import json
import os

openai.api_key = os.environ["OPENAI_API_KEY"]
```

FAQを想定し、データセットはquestions, answersカラムを持ったcsvを用意します。
今回はとあるホテルの[FAQ](https://www.palacehoteltokyo.com/faq/)を使用しました。
```python
df = pd.read_csv("./dataset.csv")  
df.head()

# questions, answers
# チェックイン、チェックアウトは何時ですか？,	チェックインは3:00 pm以降、チェックアウトは12:00 noon (正午) までとなり...
# 記念日に宿泊したいのですが、ケーキやお花などの手配をお願いできますか？,	ご予約時にご相談ください。インターネット予約システムの場合は、お問い合わせ欄がございますので...
# インターネットでは空室がないのですが、予約できませんか？,	電話でお問い合わせいただきますと、ご予約を承ることができる場合がございます。リザベーション:...
# インターネット予約システムで申し込んだ予約の確認・キャンセルはできますか？,	はい、こちら[https://www.xxx.com/?tripl...
# キャンセル料はかかりますか？,	ご予約のお取消しについてはご到着の前々日までにご連絡をお願いしております。前日、当日、不泊の...
# ...
```

## データファイルの変換(.jsonl)とアップロード
```python
def convert_df_to_jsonl(df: pd.DataFrame, system_message: str, output_path: str) -> list:
    """fine-tuningのためにdfをjson形式に変換しoutput_pathに保存"""
    with open(output_path, 'w', encoding="utf-8") as f:
        for index, row in df.iterrows():
            data = {
                "messages": [
                    {"role": "system", "content": system_message},
                    {"role": "user", "content": row['questions']},
                    {"role": "assistant", "content": row['answers']}
                ]
            }
            f.write(json.dumps(data, ensure_ascii=False) + '\n')
    return 


system_message = "あなたはホテルのコンシェルジュです。"
convert_df_to_jsonl(df, system_message, "./dataset.jsonl")

# データのアップロード
file_info = openai.File.create(
 file=open("./dataset.jsonl", "rb"),
 purpose='fine-tune'
)
```

## ファインチューニングの実行
少々時間がかかります。
```python
FILE_NAME = file_info["id"]
response_job = openai.FineTuningJob.create(training_file=FILE_NAME, model="gpt-3.5-turbo")
```

処理が完了したら下記を実行してモデルを獲得します。
```python
FINE_TUNED_MODEL = openai.FineTuningJob.retrieve(response_job.id).fine_tuned_model
```

## 学習済みモデルの実行

```python
def create_response_by_fine_tuned_model(query: str, system_message: str, fine_tuned_model: str) -> str:
  completion = openai.ChatCompletion.create(
      model=fine_tuned_model,
      temperature=0,
      messages=[
        {"role": "system", "content": system_message},
        {"role": "user", "content": query}
  ])
  
  response = completion["choices"][0]["message"]["content"]
  return response

# 例: 適宜変えてください
system_message = "あなたはホテルのコンシェルジュです。"
queries = [
    "犬も一緒に泊まりたいのですが",
    "子供用のスリッパなどはありますか。具体的なサイズも教えてください。",
    "朝食はどこで食べることができますか",
    "プールの利用可能時間について教えて",
    "追加のベッドはいくらかかりますか？",
    "プール利用がダメな条件を教えてください。"
]
for query in queries:
    response = create_response_by_fine_tuned_model(query, system_message, fine_tuned_model=FINE_TUNED_MODEL)
    print(f"query: {query}\nanswer:{response}\n")
```

↓出力結果
```txt
query: 犬も一緒に泊まりたいのですが
answer:申し訳ございませんが、ペットの同伴はご遠慮いただいております。

query: 子供用のスリッパなどはありますか。具体的なサイズも教えてください。
answer:ご用意しております。サイズは約16cmです。

query: 朝食はどこで食べることができますか
answer:ご宿泊のお客様は、1階「グランド キッチン」にてご利用いただけます。

query: プールの利用可能時間について教えて
answer:6:00am - 10:00pm

query: 追加のベッドはいくらかかりますか？
answer:追加のベッドは1泊あたり10,000円（税別）です。

```

## 感想
簡単に試せるので良かったら！