generated at
arxivの論文を、自動要約・翻訳してDiscordに飛ばす

毎時決まった時間帯に、AI論文を自動翻訳/要約して、Discordへ流す機能を実装する。
GASとDiscordのWebhook機能を使う

Discordの設定
自分専用のDiscordサーバーがない方は、こちらの記事を参照

ボットから情報を受け取りたいチャネル(paperチャネル)を右クリックし、チャネルの編集(Edit channel)を行う

連携サービス(integration) -> create webhook
「新しいウェブフック」を選択し、作成されたウェブフックをURLをコピー(あとで使うので、どこかへ保存)



GASの設定
Google Driveの画面へ行く
任意のフォルダを作成(例えば、scriptsフォルダ)し、右クリック -> その他 -> Google Apps Scriptを押す

以下の画面が開くので、コードを書いていく。


GASとDiscordを連結する
まずは、接続を確認

js
const WEBHOOK_URL = "https://xxxxxxxxx" //ご自身のウェブフックURLに置き換えてください function myFunction() { const payload = { "content": "Hello, World!" }; const options = { "method": "post", "payload": payload }; UrlFetchApp.fetch(WEBHOOK_URL, options); }

command Sで保存して、コードを実行
権限を確認 -> gmailアカウントクリック -> 詳細 -> 安全ではないページに移動をクリック -> 許可
GASの実行ログとともに、Discordへも Hello World が届いていることが確認される。


GASでarxivの論文を取得する
以下のコードを貼り付ける

js
// OpenAI の API keys (https://platform.openai.com/account/api-keys) // スクリプトプロパティにAPIキーを保存するには、スクリプトエディタで「ファイル」>「プロジェクトのプロパティ」>「スクリプトプロパティ」を選択し、OPENAI_API_KEYとしてAPIキーを追加してください。 const OPENAI_API_KEY = PropertiesService.getScriptProperties().getProperty("OPENAI_API_KEY"); const OPENAI_API_ENDPOINT = "https://api.openai.com/v1/chat/completions" const OPENAI_API_MODEL = "gpt-3.5-turbo-0125" const WEBHOOK_URL = "" // 上でコピーしたWebhook urlを貼り付けてください。 // 検索クエリ const QUERY = "ChatGPT OR GPTs OR OpenAI"; // 検索対象日数 const TERM = 1; // 検索時のヒット論文で要約する論文の本数の上限 const MAX_PAPER_COUNT = 3; // ChatGPT に渡す命令 const PROMPT_PREFIX = "あなたは情報教育、テクノロジーに詳しい教師です。\n以下の論文を、タイトルと要約の2点をそれぞれ改行で分けて、専門用語を使わず、簡素で平易な日本語で説明してください。\n要点は箇条書きでお願いします。\n## 出力形式 \nタイトル: {タイトル}\n要約: {要約}"; function getDateBeforeDays(days) { const date = new Date(); date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); date.setDate(date.getDate() - days); return date.toISOString().split("T")[0]; } function getArxivPapers(query, fromDate, toDate) { const options = { muteHttpExceptions: true, }; const url = `http://export.arxiv.org/api/query?search_query=${query}&start=0&max_results=20&sortBy=submittedDate&sortOrder=descending` const xmlText = UrlFetchApp.fetch(url, options).getContentText(); const document = XmlService.parse(xmlText); const root = document.getRootElement(); const entries = root.getChildren("entry", XmlService.getNamespace("http://www.w3.org/2005/Atom")); const papers = entries .map((entry) => { const title = entry.getChild("title", XmlService.getNamespace("http://www.w3.org/2005/Atom")).getText(); const abstract = entry.getChild("summary", XmlService.getNamespace("http://www.w3.org/2005/Atom")).getText(); const id = entry.getChild("id", XmlService.getNamespace("http://www.w3.org/2005/Atom")).getText(); const published = entry.getChild("published", XmlService.getNamespace("http://www.w3.org/2005/Atom")).getText(); return { title: title, abstract: abstract, url: id, published: published, }; }).filter((paper) => { const publishedDate = new Date(paper.published); const from = new Date(fromDate); const to = new Date(toDate); to.setDate(to.getDate() + 1); return publishedDate >= from && publishedDate < to; }); console.log(`フィルタリング後の論文数: ${papers.length}`); return papers; } function callChatGPT(input) { const messages = [ { role: "user", content: PROMPT_PREFIX + "\n" + input, }, ]; const options = { "method": "post", "headers": { "Authorization": `Bearer ${OPENAI_API_KEY}`, "Content-Type": "application/json", }, "payload": JSON.stringify({ model: OPENAI_API_MODEL, messages, }), }; return JSON.parse(UrlFetchApp.fetch(OPENAI_API_ENDPOINT, options).getContentText()); } function main() { if (!OPENAI_API_KEY) { console.log("ERROR: OPEN_API_KEY を指定してください"); return; } const fromDate = getDateBeforeDays(TERM); const toDate = getDateBeforeDays(0); console.log(`検索範囲の開始日: ${fromDate}`); console.log(`検索範囲の終了日: ${toDate}`); const arxivPapers = getArxivPapers(QUERY, fromDate, toDate); console.log(`取得された論文数: ${arxivPapers.length}`); const papers = arxivPapers; let output = "新着論文のお知らせ\n\n"; let paperCount = 0; if (papers.length === 0) { output += "指定された期間内に、検索クエリに一致する新しい論文は見つかりませんでした。\n\n"; } else { for (const paper of papers) { if (++paperCount > MAX_PAPER_COUNT) break; console.log(`論文${paperCount}: ${paper.title}`); const title = paper.title; const abstract = paper.abstract; const url = paper.url; const input = "\n" + "title: " + title + "\n" + "abstract: " + abstract; const res = callChatGPT(input); console.log(`ChatGPTからのレスポンス: ${JSON.stringify(res, null, 2)}`); const paragraphs = res.choices.map((c) => c.message.content.trim()); output += `${paragraphs.join("\n")}\n\n${url}\n\n\n`; } } output = output.trim(); console.log(`最終結果: ${output}`); const payload = { "content": output }; const options = { "method": "post", "payload": payload }; UrlFetchApp.fetch(WEBHOOK_URL, options); }
WEBHOOK_URLに、上で設定した値を貼り付ける


検索をカスタマイズをしたい時
arxivのAPIマニュアルを見ながら、以下のコードを修正する。

js
// 検索クエリ const QUERY = "ChatGPT"; // 検索対象日数 const TERM = 1; // 検索時のヒット論文で要約する論文の本数の上限 const MAX_PAPER_COUNT = 2; // ChatGPT に渡す命令 const PROMPT_PREFIX = "あなたは情報教育、テクノロジーに詳しい教師です。\n以下の論文を、タイトルと要約の2点をそれぞれ改行で分けて、専門用語を使わず、簡素で平易な日本語で説明してください。\n要点は箇条書きでお願いします。\n## 出力形式 \nタイトル: {タイトル}\n要約: {要約}";

例えば、AND OR検索、著者別検索、カテゴリー検索などができる

js
const QUERY = "ChatGPT OR GPTs OR OpenAI"; const QUERY = "au:"Grisha Perelman"; //著者がGrisha Perelmanさん const QUERY = "cat:cs.AI"; //カテゴリーがAI

なお、自分はこの設定とする。
js
// 検索クエリ const QUERY = "ChatGPT OR GPTs OR OpenAI"; // 検索対象日数 const TERM = 1; // 検索時のヒット論文で要約する論文の本数の上限 const MAX_PAPER_COUNT = 3; // ChatGPT に渡す命令 const PROMPT_PREFIX = "あなたは情報教育、テクノロジーに詳しい教師です。\n以下の論文を、タイトルと要約の2点をそれぞれ改行で分けて、専門用語を使わず、簡素で平易な日本語で説明してください。\n要点は箇条書きでお願いします。\n## 出力形式 \nタイトル: {タイトル}\n要約: {要約}";


続いて、OpenAIのAPI keyを設定する。
API keyはこちらのリンクから取得する。

サイドバーのプロジェクトの設定をクリック


スクロールするとスクリプトプロパティの項目が表示されるので、「スクリプトプロパティを追加」を選択。

プロパティに「OPENAI_API_KEY」と入れて、値に事前に取得したChatGPTのAPIキーをコピペし、「スクリプトプロパティを保存」をクリック。

正常動作するか確認するために、エディタに戻り、main関数を実行する

通信がうまくいっていれば、このようになる。


GASでトリガーを設定し、定期実行する
毎日決まったタイミングで処理を行うために、設定を行う。
>💡これが便利よね。cloud functionsとか書かなくても、簡単に実行できて楽ちん

左のサイドバーのトリガーを選択



右下のトリガーの追加から、以下の画面を設定する。(一例)

これで、毎朝午前7時-8時に、論文の翻訳/要約が届くようになった。

最後に、エディターからデプロイ -> ウェブアプリを選択して完成です。


お疲れ様でした!

関連

参考


hr
もっと、たくさんのAI情報を知りたいあなたへ...
現在週に1度の頻度で、AIの最新情報や活用ノウハウを、メルマガ限定で発信しております。

一人でも多くの方にとって、「AI人材としてのスキルアップ」につながれば幸いです^^

また、現在、登録者限定で「AIをフル活用した新しい知的生産管理」の実演解説動画を配布中です 🎁
※ ご登録完了のメールに、URlのリンクを添付いたします。

以下のリンクから、ぜひお受け取りください👇