※この記事は以下の記事を参考に「Slackへの投稿」を「メールへの送信」に変更したものです.内容の大部分をリンク先から拝借していることを予め記しておきます.
最新の論文をChatGPTで要約して毎朝Slackに共有してくれるbotを作る!
目標
こんな形で指定した時刻にメールを送ってもらいます.
(左上の目隠しは送信元,右上の目隠しは受信先のメールアドレスです)
手順
- OpenAIのアカウントを作成しOpenAIのAPIキーを取得
- Gmailからメールを送るためにアプリパスワードを取得
- Pythonコードを作成
- Google Cloud Platform(GCP)でコードの実行を自動化
手順の大部分とPythonコードのほぼ全てを元記事(上述)から引用しています.
1. OpenAIのAPIキーを取得
以下の記事を参考にOpenAIのAPIキーを取得します.
取得したAPIキーはPythonコードの中で必要になります.メモしておいてください.
2. Googleアカウントでアプリパスワードを取得
この記事ではGoogleのGmailからメールを送信することを想定します.他のメールを送信元に用いる際は送信元のSMPTサーバーとポート番号の情報が必要になります.
以下の記事などを参考にアプリパスワードと呼ばれるパスワードを取得します.
【google】アプリでG-Mailなどを使うためのアプリパスワード発行のやりかた♪
アプリパスワードとはアプリケーションやプログラムからGmailを呼び出す際に必要となる16文字のアルファベット文字列です.アプリパスワードもメモしておいてください.
3. Pythonコードを作成
上述の元記事のコードをほぼコピペしてます.ただし,Slackとの連携部分を削除し,その代わりにメール送信をするためのコードに書き換えています.
-
コメント
- arXivでの検索条件は「クエリ」で指定.詳細はArxiv APIこちらを参考に.
- num_papersを大きくすると失敗することがある.
- 「ローカルで実行可能なテストコード」は
Python 3.11.2
で動作確認済み.- バージョン確認はターミナルで
python3 --version
と打つ.
- バージョン確認はターミナルで
- 「ローカルで実行可能なテストコード」の実行手順は元記事作者さんのGitの記載に従う
pip install -r requirement.dat
python3 local_arxiv_mail.py
- GPTに送るプロンプトやメール本文は好みに応じて整形可能.
以下のコード実行に必要なPythonパッケージ
aiohttp==3.8.4
aiosignal==1.3.1
arxiv==1.4.3
async-timeout==4.0.2
attrs==22.2.0
certifi==2022.12.7
charset-normalizer==3.1.0
feedparser==6.0.10
frozenlist==1.3.3
idna==3.4
multidict==6.0.4
openai==0.27.2
requests==2.28.2
sgmllib3k==1.0.0
slack==0.0.2
slack-sdk==3.20.2
tqdm==4.65.0
urllib3==1.26.15
yarl==1.8.2
自動実行するコード
import os
import arxiv
import openai
import random
import smtplib
#OpenAIのapiキー
openai.api_key = '(メモしたOpenAIのAPIキー)'
def get_summary(result):
#GPTに送るプロンプトを元記事から少し変更しています.
system = """与えられた論文の要点を3点のみでまとめ、以下のフォーマットで日本語で出力してください。```
タイトル(英語)
・要点1
・要点2
・要点3
```"""
text = f"title: {result.title}\nbody: {result.summary}"
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{'role': 'system', 'content': system},
{'role': 'user', 'content': text}
],
temperature=0.25,
)
summary = response['choices'][0]['message']['content']
title_en = result.title
title, *body = summary.split('\n')
body = '\n'.join(body)
date_str = result.published.strftime("%Y-%m-%d %H:%M:%S")
message = f"発行日: {date_str}\n{result.entry_id}\n{title_en}\n{title}\n{body}\n"
return message
def main(event, context):
query ='ti:%22 scalar meson %22' #私が使っているクエリです
# arxiv APIで最新の論文情報を取得する
search = arxiv.Search(
query=query, # 検索クエリ
max_results=100, # 取得する論文数
sort_by=arxiv.SortCriterion.SubmittedDate, # 論文を投稿された日付でソートする
sort_order=arxiv.SortOrder.Descending, # 新しい論文から順に取得する
)
#searchの結果をリストに格納
result_list = []
for result in search.results():
result_list.append(result)
#ランダムにnum_papersの数だけ選ぶ
num_papers = 3
results = random.sample(result_list, k=num_papers)
#送信元のメールアドレス
sender_email = "hogehoge@gmail.com"
#送信先のメールアドレス
receiver_email = "hogehogehoge@hogehoge"
#Gmailアカウントのユーザー名とアプリパスワード
username = "hogehoge@gmail.com"
password = "(取得したアプリパスワード)"
# SMTPサーバーの設定:Gmailは以下の情報で固定です
smtp_server = "smtp.gmail.com"
port = 587
#論文情報をメールに送信する
for i,result in enumerate(results):
# メールに送るメッセージを組み立てる
subject = "今日の論文です! " + str(i+1) + "本目\n"
body = get_summary(result)
# メールを送信する
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(username, password)
message = f"Subject: {subject}\n\n{body}"
message = message.encode('utf-8')
server.sendmail(sender_email, receiver_email, message)
print("メールを送信しました")
ローカルで実行可能なテストコード
import os
import arxiv
import openai
import random
import smtplib
#OpenAIのapiキー
openai.api_key = '(メモしたOpenAIのAPIキー)'
def get_summary(result):
system = """与えられた論文の要点を3点のみでまとめ、以下のフォーマットで日本語で出力してください。```
タイトル(英語)
・要点1
・要点2
・要点3
```"""
text = f"title: {result.title}\nbody: {result.summary}"
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{'role': 'system', 'content': system},
{'role': 'user', 'content': text}
],
temperature=0.25,
)
summary = response['choices'][0]['message']['content']
title_en = result.title
title, *body = summary.split('\n')
body = '\n'.join(body)
date_str = result.published.strftime("%Y-%m-%d %H:%M:%S")
message = f"発行日: {date_str}\n{result.entry_id}\n{title_en}\n{title}\n{body}\n"
return message
query ='ti:%22 scalar meson %22'
# arxiv APIで最新の論文情報を取得する
search = arxiv.Search(
query=query, # 検索クエリ
max_results=100, # 取得する論文数
sort_by=arxiv.SortCriterion.SubmittedDate, # 論文を投稿された日付でソートする
sort_order=arxiv.SortOrder.Descending, # 新しい論文から順に取得する
)
#searchの結果をリストに格納
result_list = []
for result in search.results():
result_list.append(result)
#ランダムにnum_papersの数だけ選ぶ
num_papers = 3
results = random.sample(result_list, k=num_papers)
#送信元のメールアドレス
sender_email = "hogehoge@gmail.com"
#送信先のメールアドレス
receiver_email = "hogehogehoge@hogehoge"
#Gmailアカウントのユーザー名とアプリパスワード
username = "hogehoge@gmail.com"
password = "(取得したアプリパスワード)"
# SMTPサーバーの設定
smtp_server = "smtp.gmail.com"
port = 587
#論文情報をメールに送信する
for i,result in enumerate(results):
# メールに送るメッセージを組み立てる
subject = "今日の論文です! " + str(i+1) + "本目\n"
body = get_summary(result)
# メールを送信する
with smtplib.SMTP(smtp_server, port) as server:
server.starttls()
server.login(username, password)
message = f"Subject: {subject}\n\n{body}"
message = message.encode('utf-8')
server.sendmail(sender_email, receiver_email, message)
print("メールを送信しました")
4. Google Cloud Platform(GCP)でコードの実行を自動化
元記事でも引用されている[サーバーレス + Pythonで定期的にスクレイピングを行う方法]この解説を参考にGCPにのせる.このリンク先の記事で完結しているのでおすすめです.
自分は毎朝6時にメールを送ってもらっています.
終わりに
Slack投稿をメール送信に書き換える際に,GPTくんの力を借りました.その他にも多くのサイトを参考にさせていただきました.先人の皆様,ありがとうございました.また,元記事の作者であるズシさんにはここで改めて感謝申し上げます.ありがとうございました.