LLM(GPT)使って自然言語の日程調整を効率化した話

## きっかけ

仕事で、日程を調整する機会多いですよね。

社内の日程調整であればGoogleカレンダーを全社員で共有しているため、カレンダーから空いている日程を探してポチッと押すだけでいいんです。

一方、社外の人と日程調整をする場合は、カレンダーの共有などができないため、

```text
以下の時間の中で30分ほどご都合の良い時間はありませんでしょうか？
    10月 28日 (月曜日)⋅13:00～14:00、15:00～16:00
    10月 29日 (火曜日)⋅16:00～17:00
    10月 31日 (木曜日)⋅13:00～14:00
```

といった感じの日程候補の文章をもらい、これで日程調整をすることになります。

この場合、自分のGoogleカレンダーとにらめっこして、空いている場所を探すんですが、これが面倒なんですよね〜

そこで、これをLLMを使って効率化することを試みました！

(この記事は [GO Inc. Advent Calendar 2024](https://adventar.org/calendars/10481)の1日目です)


## 初期バージョン

OpenAIのGPTのAPIに対して、以下のようなプロンプトを投入することで、日程調整できないかこころみました。

OpenAIのGPTのAPIは、システムプロンプトとして役割の説明を、ユーザプロンプトとして処理してほしいデータを、それぞれ渡すことができます

システムプロンプトには役割の説明を書きます。

**システムプロンプト** 
```
あなたは、日程調整役です。最初に私のスケジュールを教えますので、それを元に相手からもらった日程候補の中で、私が空いている時間を教えて下さい。

以下のJSON形式で出力してください。出力に「```json」や「```」といった文字は不要です。

{
  "time_range_list":[
    {"start":"YYYY/MM/DD HH:MM","end":"YYYY/MM/DD HH:MM"},
    {"start":"YYYY/MM/DD HH:MM","end":"YYYY/MM/DD HH:MM"},
  ]
}

time_range_listは、相手が提案した日程候補の中で、私が空いている時間のリストです。
startは開始時間、endは終了時間です。
```



ユーザープロンプトには処理して欲しいデータを指定します。私のスケジュールと、相手から来た日程調整の文章を、結合して指定します。なお、私のスケジュールの文字列は、Google カレンダーのAPIを使って、機械的に生成しています。

**ユーザープロンプト** 
```
## 私のスケジュール

10/28(月)10:30〜11:00 マネージャ定例 
10/28(月)13:00〜13:30 1 on 1 山田さん
10/28(月)14:30〜15:00 1 on 1 井上さん
10/28(月)15:00〜15:30 エンジニアチームWeekly Sync 
10/29(火)11:00〜11:30 インシデントの件の認識合わせ
10/29(火)12:00〜13:00 昼飯 

## 相手から来た日程調整の文章

以下の時間の中で30分ほどご都合の良い時間はありませんでしょうか？
    10月 28日 (月曜日)⋅13:00～14:00、15:00～16:00
    10月 29日 (火曜日)⋅10:00～11:00

```







でてきた結果は以下の通り

**1回目の結果**
```json
{"time_range_list":[
  {"start":"2023/10/28 13:30","end":"2023/10/28 14:00"},
  {"start":"2023/10/28 15:30","end":"2023/10/28 16:00"},
  {"start":"2023/10/29 10:00","end":"2023/10/29 10:30"}
]}
```

惜しい！出てきた３件はいずれも正解なんですが、１件足りない。10月 29日 (火曜日)⋅10:30～11:00も結果に入っているべきでしたが、漏れたようです。



試しに同じプロンプトで再度実行した所、

**2回目の結果**
```json
{"time_range_list":[
  {"start":"2023/10/28 15:30","end":"2023/10/28 16:00"},
  {"start":"2023/10/29 10:00","end":"2023/10/29 10:30"}
]}
```

さっきよりも馬鹿になっている orz　　出力がより少なくなりました。

その後も何度か試しましたが、なかなか出力が安定せず、また、日程候補が複雑になればなるほど間違いやすくなったので、このアプローチは諦めました。。。

## 改善バージョン

初期バージョンの反省を踏まえて、日程候補まで全部をGPTにお願いするのではなく、
相手から来た自然言語を解析する部分だけをGPTにお願いする作戦に変えました。

具体的には、相手の依頼文を、30分毎に区切った日付の配列に変換してもらうことだけを、GPTに依頼しました。

**システムプロンプト（役割の説明）**

```
次に示す会話の中に登場する、会議の時間候補を、30分ごとに区切って出力してください。

会話の中で、年が省略されている場合は、2024年としてください。

以下のJSON形式で出力してください。出力に「```json」や「```」といった文字は不要です。

{
  "time_range_list":[
    {"start":"YYYY/MM/DD HH:MM","end":"YYYY/MM/DD HH:MM"},
    {"start":"YYYY/MM/DD HH:MM","end":"YYYY/MM/DD HH:MM"},
  ]
}

time_range_listは、相手が提案した日程候補の中で、私が空いている時間のリストです。
startは開始時間、endは終了時間です。
```

ユーザプロントには、相手から来た日程調整の文章を、指定します

**ユーザープロンプト（処理して欲しいデータ）**

```
以下の時間の中で30分ほどご都合の良い時間はありませんでしょうか？
    10月 28日 (月曜日)⋅13:00～14:00、15:00～16:00
    10月 29日 (火曜日)⋅10:00～11:00
```

でてきた結果は以下の通り

**結果**
```json
{"time_range_list":[
  {"start":"2024/10/28 13:00","end":"2024/10/28 13:30"},
  {"start":"2024/10/28 13:30","end":"2024/10/28 14:00"},
  {"start":"2024/10/28 15:00","end":"2024/10/28 15:30"},
  {"start":"2024/10/28 15:30","end":"2024/10/28 16:00"},
  {"start":"2024/10/29 10:00","end":"2024/10/29 10:30"},
  {"start":"2024/10/29 10:30","end":"2024/10/29 11:00"}
]}
```

これはバッチリ！完璧に自然言語から30分ごとの時間幅のリストに変換できています！

あとは、この結果を元に、普通のプログラミングで、空いている時間を計算すればツールの完成です！

## できたツール

日程調整の文言を入れたら、自分のGoogleカレンダーの予定をみて、空いている時間を計算するWebツールを作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33447/30d66784-60ba-f4e2-b2a7-53994a27a1e1.png)

こんな感じで、相手からの文章を入れて調整ボタンを押せば、空いている時間を教えてくれます。ついでに付近の自分の予定も表示しくれているので、結果の確かさも検証できます。

このツールは[こちらのgithub](https://github.com/fetaro/ai_schedule_coordinator)で公開しています。

ツールの簡単な特徴は

* Python 3.11 で書いています。ライブラリは[rye](https://rye.astral.sh/)で管理しています
* [GoogleカレンダーAPI](https://developers.google.com/calendar/api/guides/overview?hl=ja)を使っています
* LLMは[OpenAIのGPT-4o](https://platform.openai.com/docs/overview)を使っています
* Web画面は[Streamlit](https://streamlit.io/)で作りました

## まとめ

最初は、日程調整まで全部GPTにやらせようと思いましたが、無理でした。そこでGPTには相手の自然言語の依頼文を解析する部分だけを依頼し、残りは普通のプログラムで完成させました。

いくらGPTさんが賢いとはいえ、得手不得手があります。自然言語を構造化したデータに変換するのは得意ですが、結果が明確に定まる普通の計算は苦手です。もともと、GPTは「次に来る単語を予測する」という機能であるため、どうしても結果が定まりにくいです。結果が明確に定まるタスクをさせるのは不向きだと思いました。