AWS、Azureの最新情報を取得して生成AIにつぶやき形式で投稿するRSSリーダーをDifyを使って実現してみる。
RSSフィードを使った最新情報取得はたくさんありふれていると思います。
今回はそれをDifyを使うことで生成AIを活用しわかりやすく簡潔に要約をさせるというものを作成してみたいと思います。作っている途中でAzureも追加しようということでマルチなRSSから取得する形になりました。
なお、AWSについて日本語フィードよりも英語フィードの方が情報が早い時があるため英語版の記事をもとにしながらも生成AIにより日本語でまとめさせるという形です。
そんなに難しい内容ではないかもしれないですが、実際に手を動かして、かつ実際動く楽しみを感じることができるかと思います。
ちなみに送信先はSlackやDiscord、メール自由に変えれます。
この記事でわかること
・AWSやAzureのRSSフィードを先の内容を読み込ませて日本語でまとめさせる
・今回使用するDifyのDSLをダウンロードできる
コンテンツ
RSSフィードとは?
RSSフィードとはRSSという形式の配信内容です。ちなみにRSSとはウェブサイトの記事の見出しなどを配信するためのXMLベースのデータフォーマットです。つまり機械に読み込ませやすい形式という感じです。
実際に見てみましょう。
https://aws.amazon.com/jp/about-aws/whats-new/recent/feed/
AWSはいくつものRSSフィードがありますがその一つを実際に見るとこのような感じです。
これをEventBridgeとLambdaとDynamoDBとDifyを使う。
EventBridgeのスケジュール機能でLambdaを定期的に動かす。そしてその結果をDynamoDBに格納しながらDifyにも送信してDifyから各種ツールに送信するという感じです。
まずDifyから
Difyは非常にシンプルです。ワークフローで作成し、URLが来たものをWEB SCRAPERで本文を読み込む。その内容をLLMに送信。それをslackに送信です。LLMへのプロンプトはこのような感じです。
目的: 英語の技術発表文を、簡潔でプロフェッショナルかつわかりやすい日本語の要約(140文字以内)にする。
指示:
提供された英語の文章から、初心者にも理解しやすい言葉で要点を抽出し、簡潔にまとめる。
専門用語は適切に使用するが、必要に応じて簡潔な説明を補う(例: “オリジン” → “配信元サーバー(オリジン)”)。
製品や機能の利点を具体的に示し、読者が用途をイメージしやすく書く。
曖昧な表現や「詳しくはこちら」などは含めず、内容に集中する。
文中のアクションや結果を明確にすることで、読む人が価値を理解しやすくする。
最大140文字以内で、要点がしっかり伝わるように書く。
LLMは好きなのを。Claude 3.5 Haikuでもいいと思います。コスト面を意識するとGPT-4o-miniにするのもありです。今回はGPT-4o-miniにしました。
DSLは以下よりダウンロードしてzipになっているので回答して中のyml(ヤムル)ファイルをアップロードすればそのままインポートできます。
で、ワークフローの通りAWSだけWEB SCRAPERを使ったのか。以下の比較をご確認ください。
AWS(WEB SCRAPERあり)
https://aws.amazon.com/about-aws/whats-new/2024/11/future-dated-amazon-ec2-capacity-reservations/
Amazon EC2のキャパシティ予約に、将来の日付でのリクエスト機能が追加されました。これにより、特定の地域でのコンピューティング能力を事前に確保でき、重要なスケーリングイベントに備えることが可能です。AWS(URL直)
https://aws.amazon.com/about-aws/whats-new/2024/11/future-dated-amazon-ec2-capacity-reservations/
将来の日付でのAmazon EC2キャパシティ予約が可能になり、特定の期間に必要な計算リソースを確保できます。これにより、予測的なワークロード計画が容易になります。
4o-miniに直でURLを渡しても内容を把握してくれます。ただし少し簡素になりすぎるのです。何度やっても、記事を変えてもです。
おそらくURL内の検索の深度なのかもしれないのですが一度全文を出してその文章に対して要約させた方が全体的に精度が上がるようです。そのため一度WEB SCRAPERで処理をしました。
ただWEB SCRAPERはAWSは行けたのですがAzuruはいけなかったので直接URLを渡す形式にした形にしました。
続いてDynamoDB
DynamoDBはデータベースです。例えばAWSのRSSフィードは直近100件取れるのですが、毎回直近100件通知するわけにもいかないので差分を特定することで最新の情報だけを配信できるようにするため取得情報を保存します。DynamoDBを選ぶのはオンデマンドモードであればコストを最小限にできるからです。一定期間や件数で削除すればコストが増えていくこともほぼありません。
DynamoDBにアクセスします。
テーブル名は「SentArticles」
パーティションキーは「id」で文字列
にしました。
もしテーブル名を変えたときは次のLambdaのコードがかわります。
これだけです。これでURLなどの情報受け入れる器ができました。
そしてLambda
ではこれをDifyに送信するのと、DynamoDBに送信するLambda関数を作ります。
import boto3
import feedparser
import requests
import json
import os
from datetime import datetime
import pytz
from dateutil import parser
# DynamoDBリソース
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('SentArticles') # テーブル名を指定
# Dify API設定
DIFY_API_URL = "https://api.dify.ai/v1/workflows/run"
DIFY_API_KEY = os.environ.get("DIFY_API_KEY") # Lambda環境変数からAPIキー取得
HEADERS = {
"Authorization": f"Bearer {DIFY_API_KEY}",
"Content-Type": "application/json"
}
# RSSフィードURLリスト
RSS_URLS = [
"https://aws.amazon.com/about-aws/whats-new/recent/feed/",
"https://www.microsoft.com/releasecommunications/api/v2/azure/rss"
]
def is_already_sent(article_id):
"""
DynamoDBで記事が送信済みか確認
"""
response = table.get_item(Key={'id': article_id})
return 'Item' in response
def mark_as_sent(article_data):
"""
DynamoDBに記事を送信済みとして記録
"""
table.put_item(Item=article_data)
def convert_to_jst(utc_date):
"""
UTCの日付をJSTに変換
"""
try:
# 自動的に日付をパース
utc = parser.parse(utc_date)
utc = utc.replace(tzinfo=pytz.utc) # UTCタイムゾーンを明示
jst = utc.astimezone(pytz.timezone('Asia/Tokyo')) # JSTに変換
return jst.strftime("%Y-%m-%d %H:%M:%S") # フォーマットして文字列として返す
except Exception as e:
print(f"日付変換エラー: {utc_date}, エラー内容: {e}")
return None # 変換できない場合はNoneを返す
def send_to_dify(url):
"""
Dify Workflow APIに記事のURLを送信
"""
payload = {"inputs": {"URL": url}, "response_mode": "blocking", "user": "unique_user_id"}
response = requests.post(DIFY_API_URL, headers=HEADERS, data=json.dumps(payload))
if response.status_code == 200:
print(f"成功: {url} をDifyに送信しました")
return True
else:
print(f"失敗: {url} の送信に失敗しました。ステータスコード: {response.status_code}, レスポンス: {response.text}")
return False
def process_rss_feed(feed_url):
"""
指定されたRSSフィードを処理
"""
# フィードの名前を動的に決定
source_name = "AWS" if "aws.amazon.com" in feed_url else "Microsoft"
feed = feedparser.parse(feed_url)
# 古い順に並び替えて処理
for entry in sorted(feed.entries, key=lambda x: x.published_parsed):
article_id = entry.guid # フィード内のIDを使用
if not is_already_sent(article_id): # 未送信か確認
# JSTの日付を取得
jst_published = convert_to_jst(entry.published)
if jst_published is None: # 日付変換に失敗した場合はスキップ
continue
article_data = {
'id': article_id,
'title': entry.title,
'link': entry.link,
'published': entry.published, # UTCの公開日
'published_jst': jst_published, # JSTの公開日
'category': entry.get("category", "N/A"), # カテゴリが存在しない場合のデフォルト
'author': entry.get("author", "N/A"), # 著者が存在しない場合のデフォルト
'source': source_name # AWSやMicrosoftなどの出所を記録
}
if send_to_dify(article_data['link']): # Difyに送信
mark_as_sent(article_data) # DynamoDBに記録
def lambda_handler(event, context):
"""
Lambdaエントリポイント
"""
# 各RSSフィードを順に処理
for rss_url in RSS_URLS:
process_rss_feed(rss_url)
return {
"statusCode": 200,
"body": "全RSSフィードのチェックとDifyへの送信が完了しました"
}
ライブラリは
・feedparser
・requests
・pytz
の三つを使いますのでレイヤー登録をしてください。以下はレイヤー化したものです。
設定→環境変数でDIFY_API_KEYを登録を行ってください。
最後にEventBridge
0/5 9-19 ? * MON-FRI *
今回は月曜から金曜の朝9時から19時の間で通知することにしました。
アメリカ時間で配信されることが多いため深夜に通知が飛びやすいので、不要な目覚ましにならないようにです。リアルタイムでなくても最短で通知が飛ぶ感じにしました。
上記が設定できていると以下のようになります。9時にどっときます
まとめ
自作することで自由度が高いですし、Difyにすることでプロンプトを気軽に変えれたり、新しいLLMモデルがでたらすぐにGUIでかえれる保守性が高いところがポイントです。
この記事を書いた人
資料
ダウンロード
マスタデータのメンテナンスに関わる機能をまとめたSaaS「SMOOZ」
SMOOZはリレーショナルデータベースの課題を解決するサービスです。
オンラインデモで気軽に試すことが可能です。