日記生成ツールの紹介と実装解説
概要
本記事では、X(旧Twitter)から取得したツイートと天気データを組み合わせて日記を生成し、さらにその日記から画像生成に必要な要素を抽出するツールの実装について解説します。このツールは、Pythonを使用して構築されており、外部APIを活用してデータ取得や生成を行います。
ソース
サンプル
Input
[
{
"created_at": "2023-05-01 00:10:00",
"text": "今日カフェで勉強してたんだけど、隣の席の人がイケメンすぎて全然集中できなかった…♀️"
},
{
"created_at": "2023-05-01 00:10:00",
"text": "課題多すぎ…終わる気がしない…誰か助けて…"
},
{
"created_at": "2023-05-03 00:10:00",
"text": "新しいスニーカー買った!めっちゃ可愛い✨ 明日どこ履いて行こうかな?"
},
{
"created_at": "2023-05-03 00:10:00",
"text": "バイト疲れたー。でも、給料日近いから頑張るしかない"
},
{
"created_at": "2023-05-03 00:10:00",
"text": "今日のランチは友達と話題のラーメン屋さんへ めちゃくちゃ美味しかった!"
}
]
Output
今日は、カフェで勉強しようと意気込んで出かけたんだけど、まさかの展開に見舞われてしまった…。隣の席に座った人が、とんでもなくかっこいい人でね、もう全然集中できなかったんだよね…!教科書を開いてはみたものの、気づけば彼の横顔をちらちらと見てしまっていて、肝心の課題は全然進まず…。
課題は山積みだし、全然終わる気がしないしで、もう八方塞がりって感じ。本当、誰か助けてほしいよ…。せめて、集中力を高める魔法とかあればいいのに!
明日は、今日の分も頑張って課題を終わらせないと、もう本当にやばいことになりそう。あのイケメンさん、明日もカフェにいるかな…?…いやいや、今は集中!集中!課題に集中して、少しでも進められるように頑張ろう。とりあえず、今日は早く寝て、明日に備えよう。
2023-05-02: 快晴
何もありませんでした。
2023-05-03: 晴時々薄曇
今日は、なんだか嬉しいことと少し疲れたことと、美味しいことで盛りだくさんの一日だったな!
まず、一番嬉しかったのは、新しいスニーカーを買ったこと!お店で見た瞬間、もう「可愛い!」って目がハートになっちゃって、即決だった。家に帰って改めて眺めていたら、ますます気に入っちゃって、ニヤニヤが止まらないの。明日はどこに履いて行こうかな? おしゃれして、どこかにお出かけしたいな!
午後からはバイトだったんだけど、今日はなんだかいつも以上に疲れてしまって…。でも、もうすぐ給料日!それを楽しみに、頑張って乗り切ったよ!頑張った自分を褒めてあげたいな。
そして、今日のランチは、友達と話題のラーメン屋さんに行ってきたんだ! 噂通り、めちゃくちゃ美味しくて、スープも全部飲んでしまった!友達と美味しいものを一緒に食べるって、本当に幸せだよね。
明日は新しいスニーカーを履いて、どこに出かけようかな。バイトも頑張って、楽しい週末を過ごしたいな!
主な機能
-
ツイート取得
- 指定されたユーザーのツイートを取得します。
- モックデータを使用するオプションもあります。
-
天気データ取得
- 指定された期間と場所の天気データを取得します。
-
日記生成
- ツイート内容を日記形式に変換します。
-
画像生成
- 日記の内容からシチュエーションや登場人物を抽出し、画像生成APIを利用して画像を生成します。
-
ファイル出力
- 生成された日記と画像を指定のディレクトリに保存します。
処理の流れ
1. 引数の解析
プログラムはコマンドライン引数を受け取り、モックデータを使用するか、実際のデータを使用するかを切り替えます。
def parse_args():
parser = ArgumentParser(description="日記生成ツール")
parser.add_argument("--mock", action="store_true", help="モックデータを使用する")
parser.add_argument("--user_name", type=str, help="Xのユーザー名")
parser.add_argument("--location_name", type=str, help="天気の取得に使う地名")
parser.add_argument("--start_date", type=str, help="開始日 (YYYY-MM-DD)")
parser.add_argument("--end_date", type=str, help="終了日 (YYYY-MM-DD)")
return parser.parse_args()
2. メタデータの読み込み
ツイートや天気データを取得するためのメタデータを読み込みます。
def _load_metadata(self):
if args.mock:
self.user_name = "mock_user"
self.location_name = "東京"
self.start_date = datetime.strptime("2023-05-01", "%Y-%m-%d")
self.end_date = datetime.strptime("2023-05-02", "%Y-%m-%d")
self.tweets = x_api.get_user_tweets_mock()
else:
self.user_name = args.user_name
self.location_name = args.location_name
self.start_date = datetime.strptime(args.start_date, "%Y-%m-%d")
self.end_date = datetime.strptime(args.end_date, "%Y-%m-%d")
self.tweets = x_api.get_user_tweets(self.user_name)
3. 天気データの取得
指定された期間の天気データを取得します。
def _load_weather_data(self):
months = {(self.start_date.year, self.start_date.month), (self.end_date.year, self.end_date.month)}
for year, month in months:
if args.mock:
path = f"mock/weather/{year}{month:02d}.json"
raw = text.load_json(path)
else:
raw = whether.get_past_weather(self.location_name, year, month)
daily = whether.extract_daily_weather(raw)
self.weather_data.update(daily)
4. 日記生成
ツイート内容を日記形式に変換します。
def tweet_to_diary(tweet_text):
prompt_template = text.read_text_file("prompt/tweet_to_diary.txt")
prompt = prompt_template.replace("###TWEET_TEXT###", tweet_text)
result = gemini_api.query(prompt)
return result
5. 画像生成
生成された日記から画像生成に必要な要素を抽出し、画像を生成します。
def extract_diary_for_image(diary_text):
prompt_template = text.read_text_file("prompt/diary_to_situation.txt")
prompt = prompt_template.replace("###DIARY_TEXT###", diary_text)
result = gemini_api.query(prompt)
return result
実行方法
-
実際のデータを使用して実行する場合:
python src/main.py --user_name <ユーザー名> --location_name <地名> --start_date <開始日> --end_date <終了日>
-
モックデータを使用して実行する場合:
python src/main.py --mock
使用技術
-
外部API
- 天気データ取得: 気象データ Web API
- 画像生成: Gemini
- ツイート取得: Tweepy
まとめ
このツールは、ツイートと天気データを組み合わせて日記を生成し、さらに画像生成まで行うユニークなアプローチを採用しています。今後は、天気データ取得を気象庁APIに変更するなど、さらなる改善を予定しています。