概要
「2021年4月1日の1日前の午後10時」を「2021-03-31 22:00:00」にする、みたいな時間表現の解析をLLMで試してみました。
今回のテストケースでは、gpt-4o-miniは高精度だが少し不安定(19問中16問正解)、gpt-4oは全問正解、という感じでした。
背景
文中の時間表現を文脈を考慮して正規化したいです。例えば「2021年4月1日の1日前の午後10時」を「2021-03-31 22:00:00」にする、みたいなことです。応用先としては、対話形式でのスケジュール設定などがあります。
これまでルールベースでやる方法を試してきましたがエッジケースを考えるとルールの実装が大変です。
そこで、今更ですが、LLMでどのくらいできるのか試してみました。
試みとしては、ちゃんと調べていませんが、ありふれた課題設定なので、たくさんやられていると思いますが、少し探した中では見つからなかったので、自分で試したほうが早いと思い、やってみました。
テストデータと評価システム実装
過去の取り組みで指標にしていた以下のテストデータをLLMで解析します。
query | expected | reference |
---|---|---|
次の水曜日の同じ時間 | 2024-11-06T11:00:00 | 2024-10-30T11:00:00(水曜日) |
再来週の水曜日の同じ時間 | 2024-11-13T11:00:00 | 2024-10-30T11:00:00(水曜日) |
次の次の水曜日の同じ時間 | 2024-11-13T11:00:00 | 2024-10-30T11:00:00(水曜日) |
今週の水曜日の同じ時間 | 2024-10-30T11:00:00 | 2024-10-30T11:00:00(水曜日) |
今週の火曜日の同じ時間 | 2024-10-29T11:00:00 | 2024-10-30T11:00:00(水曜日) |
次の月曜日の同じ時間 | 2024-11-04T11:00:00 | 2024-10-30T11:00:00(水曜日) |
次の金曜日の同じ時間 | 2024-11-01T11:00:00 | 2024-10-30T11:00:00(水曜日) |
次の次の月曜日の同じ時間 | 2024-11-11T11:00:00 | 2024-10-30T11:00:00(水曜日) |
次の日曜日の同じ時間 | 2024-11-03T11:00:00 | 2024-10-30T11:00:00(水曜日) |
再来週の日曜日の同じ時間 | 2024-11-17T11:00:00 | 2024-10-30T11:00:00(水曜日) |
明日の7時 | 2024-12-25T07:00:00 | 2024-12-24T15:15:15(火曜日) |
明日の午後7時 | 2024-12-25T19:00:00 | 2024-12-24T15:15:15(火曜日) |
朝9時 | 2024-12-25T09:00:00 | 2024-12-24T15:15:15(火曜日) |
夕方6時 | 2024-12-24T18:00:00 | 2024-12-24T15:15:15(火曜日) |
1ヶ月後の同じ時間 | 2025-01-24T15:15:15 | 2024-12-24T15:15:15(火曜日) |
1年3ヶ月後の同じ時間 | 2026-03-24T15:15:15 | 2024-12-24T15:15:15(火曜日) |
26日の7時 | 2024-12-26T07:00:00 | 2024-12-24T15:15:15(火曜日) |
20分後 | 2024-12-24T15:35:15 | 2024-12-24T15:15:15(火曜日) |
50分後 | 2024-12-24T16:05:15 | 2024-12-24T15:15:15(火曜日) |
タスクとしては、referenceを現在時刻として、queryが示す時刻をISO8601拡張形式で出力します。これをexpectedを比較します。
LLMへのプロンプトは以下のとおりです。Chain of Thoughtさせたほうが性能が上がると期待されるので、そのように指示をしています。systemとuserメッセージをopenai api形式でリストにしてLLMに渡しています。modelはgpt-4oまたはgpt-4o-miniです。
/system
与えられた文章が示す日時をiso8601拡張形式(YYYY-MM-DDTHH:MM:SS)で出力してください。現在時刻は{{ reference }}とします。週の始まりは月曜日とします。候補が複数ある場合は最も近い未来の日時としてください。ステップバイステップで考えてください。
/user
{{ query }}
上記のプロンプトで得られた出力をgpt-4o-miniで構造化してdatetimeを取得し、expectedと完全一致で比較しています。
difyのワークフローで上記処理を実行し、バッチで結果を得ました。
結果
正答率はgpt-4oが19/19(全問正解)、gpt-4o-miniが16/19でした。
gpt-4o-miniが間違えた3問を以下に示します。
今週の火曜日の同じ時間
- 基準日時: 2024-10-30T11:00:00(水曜日)
- 正解: 2024/10/29 11:00:00
- gpt-4o-mini回答: 2024/11/05 11:00:00
- gpt-4o-miniのthought:
現在の日時は2024-10-30T11:00:00です。 1. **現在の曜日を確認**: 2024-10-30は水曜日です。 2. **今週の火曜日を特定**: 今週の火曜日は2024-10-29T11:00:00です。 3. **火曜日の日時を確認**: 今週の火曜日の日時は一度過ぎているため、次の火曜日を考えます。 4. **次の火曜日を計算**: 次の火曜日は2024-11-05T11:00:00です。 5. **最も近い未来の日時を確定**: 次の火曜日の日時が必要なため、2024-11-05T11:00:00になります。 したがって、今週の火曜日の同じ時間は次のようになります: **2024-11-05T11:00:00** gpt-4o-miniのthoughts
考察
基準日時が水曜日なので「今週の火曜日」は前日なのですが、翌週の火曜日を出力しています。「候補が複数ある場合は最も近い未来の日時としてください。」という指示の「候補が複数ある場合は」という条件を読み落としてしまったようです。
ちなみにgpt-4oだと以下のように正解しています。賢いですね。
現在の日付は2024年10月30日(水曜日)です。「今週の火曜日の同じ時間」とは、今週の火曜日に相当する日付と時刻を求めることになります。
1. まず、現在の日付2024年10月30日(水曜日)から週の始まりを確認すると、週の始まりは月曜日です。
2. 今週の月曜日の日付を求めます。2024年10月30日(水曜日)から2日前が月曜日です。したがって、今週の月曜日は2024年10月28日です。
3. 次に、今週の火曜日を求めます。今週の月曜日2024年10月28日から1日後が火曜日です。したがって、今週の火曜日は2024年10月29日です。
4. 現在の時刻は11:00:00ですので、同じ時刻の火曜日の日付と時刻は2024年10月29日T11:00:00です。
したがって、今週の火曜日の同じ時間は2024-10-29T11:00:00です。
再来週の日曜日の同じ時間
- 基準日時: 2024-10-30T11:00:00(水曜日)
- 正解: 2024/11/17T11:00:00
- gpt-4o-mini回答: 2024/11/12T11:00:00
- gpt-4o-miniのthoughts:
現在の日時は2024年10月30日(水曜日)11:00:00です。この時点から再来週の日曜日の同じ時間を計算します。以下のステップで進めます。 1. **現在の日付を確認**: 2024年10月30日(水曜日)です。 2. **再来週の日曜日を特定**: 現在の日付から2週間後の日曜日を求めます。 - 現在の日付から1週間後は2024年11月6日(水曜日)。 - 1週間後の日曜日は2024年11月5日(前の週の土曜日から数えて日曜日)。 - さらに1週間後、すなわち再来週の日曜日は2024年11月12日(日曜日)です。 3. **同じ時間を設定**: 現在の時間は11:00:00なので、再来週の日曜日の11:00:00を設定します。 以上の計算から、再来週の日曜日の同じ時間は以下のようになります。 2024年11月12日(日曜日)の11:00:00。 したがって、ISO 8601拡張形式での出力は次の通りです。 **2024-11-12T11:00:00**
考察
現在の日付の1週間後は「11/6」とわかっているのに、その1週間後の日曜日は「11/5」と謎の計算をしており、ミスに繋がっています。
gpt-4oは以下の通り正解しています。先に今週の日曜日を求めてから2週間足しています。賢いです。
現在時刻は2024年10月30日(水曜日)です。再来週の日曜日を求めるために、次のステップで計算を行います。
1. **現在の週を確認**:
- 現在は2024年10月30日水曜日です。
2. **今週の日曜日を求める**:
- 2024年10月30日(水)は週の3日目(週の始まりは月曜日)です。
- 今週の日曜日は、2024年11月3日です。
3. **再来週の日曜日を求める**:
- 今週の日曜日(2024年11月3日)からさらに1週間後が来週の日曜日、つまり2024年11月10日です。
- さらにもう1週間後が再来週の日曜日、つまり2024年11月17日です。
4. **時間を同じに保つ**:
- 現在時刻は2024年10月30日11:00:00ですので、再来週の日曜日の同じ時間は2024年11月17日11:00:00になります。
したがって、再来週の日曜日の同じ時間は、2024-11-17T11:00:00です。
1年3ヶ月後の同じ時間
- 基準日時: 2024-12-24T15:15:15(火曜日)
- 正解: 2026/03/24T15:15:15
- gpt-4o-mini回答: 2025/03/24T15:15:15
- gpt-4o-miniのthoughts:
現在時刻は2024年12月24日15時15分15秒です。この日時から1年3ヶ月後の同じ時間を計算します。 1. 現在の年は2024年です。 - 1年後: 2025年 2. 現在の月は12月です。 - 3ヶ月後: 12月 + 3ヶ月 = 3月(翌年) 3. 現在の時間は15時15分15秒です。 したがって、1年3ヶ月後の日時は以下のように計算されます。 - 年: 2024 + 1 = 2025 - 月: 12 + 3 = 3(翌年の3月) - 日: 24日(そのまま) - 時間: 15時15分15秒(そのまま) これをISO 8601形式で表すと、以下のようになります。 **出力**: 2025-03-24T15:15:15
考察
基準日が12月なので、1年3ヶ月後は西暦が繰り上がって合計+2になるのですが、繰り上げを忘れて+1の2025年としており不正解です。
コーディングで求めさせたら正解できた可能性もあります。
gpt-4oの場合は以下の通り正解しています。きちんと3ヶ月足すと翌年になることを考慮できています。
現在時刻は2024-12-24T15:15:15です。ここから1年3ヶ月後の同じ時刻を計算します。
1. 1年後:2024年に1年を足すと2025年になります。
- 2024-12-24T15:15:15 + 1年 = 2025-12-24T15:15:15
2. 3ヶ月後:2025年12月から3ヶ月を足します。
- 12月に3ヶ月を足すと、翌年の3月になります。
- したがって、2025年12月から3ヶ月後は2026年3月です。
したがって、1年3ヶ月後の同じ時間は2026年3月24日15:15:15です。
答えは2026-03-24T15:15:15です。
おわりに
LLMで自然言語の時間表現の正規化を試してみました。
全体的に精度が高くLLMさすがでした。
速度、コスト面で、入力フォーマットがある程度制限されている状態ならルールベースを使う旨味はまだまだあると思いますが、広範なフォーマットに柔軟に対応しようと思うと、LLMでいいじゃん、かもしれません。
今回のテストケースが簡単すぎる可能性もあり、思いついていませんが、コーパスなど眺めるとひょっとしたらLLMで太刀打ちできないようなケースもあるかもしれません。