メインコンテンツへスキップ
見出し画像

毎朝、AIが選んだ1本が届く。RSS×LLMで作るニュース配信と“重複させない”工夫

    こんにちは!Accel-Hack (アクセルハック)開発チームです。

    社内AIアシスタント「Airi」の開発プロセスをお届けする開発記ブログ。
    第16回目の今回から、連載は新しい章に入ります。

    これまでは「頼まれたことをこなす」機能を作ってきましたが、ここからは Airi が自分から情報を届けにくる機能たちの紹介です。

    第一弾は、毎朝エンジニア向けのニュースを届ける news機能 です。

    前回の Vol.15 までで、打刻・申請・入社といった「依頼応答型」の機能が出揃いました。

    今回はその発想を反転させ、ユーザーが何もしなくても価値が届く仕組みを作ります。

    しかも、ただ配るだけではありません。

    数あるニュースの中から「今日の1本」をAIに選ばせ、なおかつ無駄なく一度だけ処理する工夫が、この機能の見どころです。



    1. 「調べる」を待たない。届くという価値

    技術のトレンドを追うのはエンジニアの習慣ですが、忙しい日々の中でニュースサイトを巡回するのは、意外と後回しになりがちです。

    「あとで読もう」がたまっていく感覚は、誰しも覚えがあるのではないでしょうか。

    そこで Airi は、毎朝、その日の注目IT記事を1本だけ Slack に届けることにしました。

    大量のニュースをそのまま流しても埋もれるだけ。
    だからこそ「1本に絞る」ことに意味があります。

    エンジニアが朝いちばんに Slack を開くと、AIが選んだ話題が待っている――情報を「探しにいく」から「向こうから届く」へ。

    この小さな転換が、チームの学びの習慣を後押しします。


    2. 仕組みの骨格

    処理の流れそのものは、驚くほどまっすぐです。

    Vol.7 で設定した Cron Trigger(定時実行) が毎朝 getDailyNews() を起動し、次の一直線を辿ります。

    RSS を取得 → AIが1本選定 → Slack に配信 → Home にも表示。

    シンプルですが、この中に「軽量に扱う」「AIに任せる」「無駄なく一度だけ」という3つの工夫が詰まっています。

    順に見ていきましょう。


    3. RSS を“生”で、軽量に扱う

    ニュースの仕入れ先は、Yahoo ニュースの IT トピックス RSS です。

    RSS は記事一覧を配信する昔ながらの仕組みで、URL を叩けば記事のタイトルやリンクが XML で返ってきます。

    Airi では、この XML を専用ライブラリを使わず、正規表現で軽くパースしています。

    <item> の中からタイトル・リンク・日付を抜き出し、対象期間のものだけを残して、最大20件に絞る。
    たったこれだけです。

    const res = await fetch("https://news.yahoo.co.jp/rss/topics/it.xml");
    const xmlText = await res.text();
    // <item> から title / link / pubDate を正規表現で抽出し、期間で絞り込む

    本格的なXMLパーサを持ち込めば厳密ですが、バンドルサイズがシビアなエッジ環境(Vol.7)では、依存を増やさない軽さも立派な設計判断です。

    「必要十分に、軽く」――エッジらしい割り切りです。


    4. AIに「1本選んでもらう」

    集めた20件を、次は LLM に丸ごと渡します。

    プロンプトはとてもストレート。

    「この一覧から、ITエンジニアにとって最も面白そうなものを1つ選び、タイトル・URL・推薦理由を出力して」とお願いするだけです。

    ここで効いてくるのが、Vol.8 の Drizzle でも活躍した Zod スキーマです。

    出力の“型”をあらかじめ定義しておくことで、LLM の返答を「タイトル・URL・コメント」という決まった形の構造化データとして、安全に受け取れます。


    const newsSelectionSchema = z.object({
    title: z.string().describe("選定したニュースのタイトル"),
    url: z.string().describe("選定したニュースのURL"),
    comment: z.string().describe("なぜ面白いのか、エンジニア向けに1〜2文で"),
    });


    「AIに選ばせて、結果は型で受け止める」。

    この組み合わせによって、単なる転載ではない、推薦コメント付きの“キュレーション”が自動で生まれます。


    5. 賢く、一度だけ――KVキャッシュと分散ロック

    さて、ここが最大の工夫です。

    この定時ジョブ、実は同じ日に複数回起動される可能性があります。

    そのたびに RSS を取得し、LLM に問い合わせていては、無駄なAPIコストがかさむうえ、日によって「今日の1本」がコロコロ変わってしまいます。

    そこで Airi は、「その日の選定は一度だけ」を徹底しています。

    画像

    まず Vol.7 の KV に「今日の1本」がキャッシュされていないかを確認します。

    あれば、それを即座に返して終了。

    無ければ、分散ロック(withKvLock)を取得してから RSS 取得と LLM 選定に進み、結果を KV に24時間の期限付きで保存します。

    このロックが、地味ですが重要です。

    もし複数の処理がほぼ同時に「キャッシュが無い!」と判断しても、実際に取得・選定を行えるのはロックを取れた1つだけ。
    他は少し待ってから、先に完成したキャッシュを共有して受け取ります。

    おかげで、RSS取得もLLM呼び出しも、その日はきっちり1回。
    コストと一貫性を、この小さな仕組みが守ってくれています。


    6. おわりに

    今回は、Airi が「自分から情報を届ける」第一歩として、RSS × LLM × KV で組み立てたニュース配信をお届けしました。

    軽量にニュースを仕入れ、AIに1本選ばせ、キャッシュとロックで無駄なく一度だけ。

    派手ではありませんが、コストと品質の両方に目を配った、実運用に耐える設計です。

    次回は、同じ「自動化」でも、チームの活動そのものに光を当てます。

    「Vol.17: 日報は書くだけ、まとめはAIが。KV×D1×LLMで作る進捗の自動可視化」 として、日報・週報スレッドの自動生成と、LLM を使った1週間の進捗サマリーの仕組みをお届けします。
    お楽しみに!



    この記事は以下の体制で作成されました。

    • ドラフト作成・執筆: Airi (社内AIアシスタント)

    • アイデア出し・レビュー: CTO

    • デザイン: 事務スタッフ

    Accel-Hackでは、テクノロジーを駆使して世の中の課題を解決していく仲間を募集しています。
    私たちの取り組みに少しでも興味を持っていただけたら、ぜひ採用ページや会社サイトも覗いてみてくださいね。


    あなたへのおすすめ