Route reminders by tool availability, not keyword matching

「7時にモーニングコールをお願い。」のような、REMINDER_KEYWORDS のどれとも
一致しない言い回しがリマインド機能を素通りし、ただの雑談として処理されて
いた(本番の api_logs で実例を確認)。「モーニングコール」「起こして」を
キーワードに追加しても、次の言い回しでまた同じことが起きるだけなので、
キーワード判定そのものをやめる。

discord_bot.on_message は雑談・天気のキーワード分岐はそのまま残し、それ以外の
全メンションで create_reminder / list_reminders / cancel_reminder の3ツールを
常に同席させる(reminders.build_tool_hint() が現在時刻の文脈を添える)。
使うかどうかはLLM自身の判断に委ねるため、キーワード一覧を事前に尽くす必要が
なくなる。本番のBedrock Nova 2 Liteで、実際に失敗していた文言が
create_reminder を正しく呼ぶことを確認済み。

reminders.handle_reminder_request() は resolve_reminder_tools(messages, ctx,
model) に一般化し、discord_bot 側で組み立てたmessages(人格プロンプト+天気
コンテキスト+ツール文脈)をそのまま受け取れるようにした。tool calling
非対応のモデルが設定されていた場合は、1ラウンド目の例外を検知してツール
なしの通常応答にフォールバックする。ツール呼び出しが一般会話の呼び出しに
統合された以上、それだけ別モデルを割り当てる余地がなくなったため
REMINDER_MODEL は廃止する。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 01:17:03 +09:00
co-authored by Claude Opus 5
parent 0ee9fac3f7
commit c6108a1b29
6 changed files with 75 additions and 81 deletions
+15 -7
View File
@@ -181,14 +181,19 @@ data: {"type":"error","value":"エラー内容"} # 例外発生時
`main.py` の lifespan が `start_discord_bot()`(メンション応答)と `start_scheduler()`(定期ジョブ)を起動する。
`on_message` はメンション本文をキーワードで見て分岐する。判定順は **リマインド → 雑談 → 天気** で、
先にマッチしたものが返信を返して終わる。
`on_message` はメンション本文をキーワードで見て分岐する。判定順は **雑談 → 天気** で、
先にマッチしたものが返信を返して終わる。どちらにも当てはまらなければ通常応答へ進む。
| 分岐 | キーワード例 | 動作 |
|---|---|---|
| リマインド | リマインド / 忘れないように / 覚えといて / アラーム | `reminders.handle_reminder_request()` に渡す |
| 雑談 | どうでもいい / 雑談 / 暇 | 『どうでもいいTips』へ誘導しつつ、話題に近いタグで Tips を1本投稿 |
| 天気 | 天気 / 洗濯 / 雨 | 気象庁の明日の予報を system メッセージに足してから返信 |
| 通常応答 | (上記に当てはまらない全て) | `reminders.resolve_reminder_tools()` に渡す |
リマインドはキーワードで振り分けない。雑談以外の全メンション(天気キーワード込み)で
`create_reminder` / `list_reminders` / `cancel_reminder` の 3 ツールを常に同席させ、使うかどうかは
LLM 自身に判断させる。以前はキーワード一覧(リマインド / アラーム 等)で振り分けていたが、
「モーニングコール」のように一覧に無い言い回しを取りこぼす実例があったため、この方式に変えた。
APScheduler に登録されるジョブは 3 つ。
@@ -202,11 +207,14 @@ APScheduler に登録されるジョブは 3 つ。
一回きりのリマインドのみを扱う(繰り返しには非対応)。
- **登録**: LLM に `create_reminder` / `list_reminders` / `cancel_reminder` の 3 ツールを渡し、
自然言語から日時と用件を取り出させる。system メッセージに現在時刻と曜日を入れてあるので、
- **登録**: `resolve_reminder_tools()` が `discord_bot.on_message` の全メンションで
`create_reminder` / `list_reminders` / `cancel_reminder` の 3 ツールを差し込み、自然言語から
日時と用件を取り出させる。`build_tool_hint()` が現在時刻と曜日を system メッセージに足すので、
『明日』『30分後』といった相対表現はモデル側が絶対日時に直す。使うモデルは
`REMINDER_MODEL` →`WEATHER_NOTIFY_MODEL` → `DEFAULT_MODEL` の順にフォールバックするが、
**tool calling 対応モデルでないと動かない**(非対応時はエラー文を返す)
discord_bot 側が渡す `WEATHER_NOTIFY_MODEL`(未設定なら `DEFAULT_MODEL`)で、一般会話・天気応答と
共通。**tool calling 対応モデルであることが望ましい** — 非対応モデルがツール付き呼び出し自体を
拒否した場合は、1 ラウンド目の例外を検知してツールなしの通常応答にフォールバックする
(リマインド機能は使えないが、一般会話・天気応答は道連れにならない)
- **バリデーション**: 過去・`REMINDER_MAX_AHEAD_DAYS` より先・解釈不能な日時はツール結果として
エラー文をモデルに返し、モデルに聞き直させる
- **配信先**: Webhook ではなく Bot クライアントから、登録されたチャンネルへ依頼者をメンションして投稿する。