RSSフィードの未読記事をまとめてAIで要約するツール「RSS Summarizer」を作成・公開しています。
FreshRSSのGoogle Reader互換API経由で未読記事を取得し、要約結果を出力するCLIツールです。
もともとはGoogle Gemini専用の要約ツールとして作り始めました。
しかし、ローカルLLMや各種クラウドAIの選択肢が増えたため、最新のコードでは複数AIを選択できるように設計を変更しました。
さくらインターネットの生成AI APIやOpenAI互換エンドポイントをLangChain経由で切り替えて利用できます。
開発中に直面した主な問題と、それを解決するための工夫をいくつか取り入れています。
トークン数制限と入力文字数の調整
大量の未読記事タイトルを一括でプロンプトに流し込む際、モデルのトークン数上限に達する前に、APIエンドポイントの受け入れ文字列サイズ制限でエラーが発生するケースがありました。
単にトークン数だけで管理しようとするとリクエスト生成時に落ちることがあったため、安全マージンとして文字数上限(MAX_CHARS)を設定し、あらかじめプロンプト文字列を切り詰める処理を入れています。
試行錯誤の結果、エラーを発生させずに安定して動作する適切なデフォルト値を導き出すことができました。
TinyDBによる条件判定付きローカルキャッシュ
要約処理を頻繁に実行すると、APIの利用コストが嵩む上、結果の取得に時間がかかります。
そこで、TinyDBを利用した軽量なキャッシュ機構を組み込みました。
実行時の時刻(時単位)、対象時間(delta_hours)、取得件数(max_items)、使用モデル(summarizer_method)、プロンプトの構成要素を組み合わせたキーを保持しています。
直前と同一条件での実行時はAPI呼び出しをスキップし、キャッシュされた過去の要約結果を即座に表示します。
Markdown形式でのクリッピング機能
生成された要約は端末に表示するだけでなく、Markdownファイルとして保存する機能を用意しました。
保存時には作成日時、設定パラメータ、要約対象となった記事のドメイン一覧などを抽出してYAMLフロントマターとして自動付与します。
Obsidianなどのメモアプリへそのまま保存して、後から見返す情報ベースとして活用しやすくしています。