Last active
May 5, 2023 04:14
-
-
Save resnant/d42ae67315f0c073e3c244a913f6d408 to your computer and use it in GitHub Desktop.
arXiv新着論文のChatGPTによる日本語要約をメール送信するGoogle App Script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 使い方: | |
// 1. OpenAIのAPI keyを取得する→(https://platform.openai.com/account/api-keys | |
// 2. https://script.google.com/home/ にアクセスし、新しいプロジェクトを作成する。 | |
// 3. 作成したプロジェクトを開き、このコード全文をエディタにコピペする。API Keyとメールアドレスを埋める。 | |
// 4. この時点でコードエディタ画面上部の実行ボタン(再生マーク)を押して正しく実行できるか確認しておくと良い | |
// 5. 左カラムからトリガー設定画面(目覚ましアイコン)を開き、よしなに自動実行を設定する。 | |
// 参考にさせていただいたスクリプト: | |
// https://script.google.com/home/projects/1M6yhI6PTaFpvcZeRVycmJZoh2LhUL_Zk64pxwDYCLjD1K14Qirf7Nov- | |
// https://twitter.com/niniziv/status/1638155751515631617 | |
// OpenAI の API keyを入力↓ | |
const OPENAI_API_KEY = "sk-"; | |
// ChatGPT に渡すプロンプト(適宜変えること) | |
const PROMPT_PREFIX = "あなたは機械学習と材料科学に精通した研究者で、論文を簡潔に要約することに優れています。以下の論文を、タイトルと要約の2点をそれぞれ改行で分けて日本語で説明してください。要点は箇条書きで4-8行程度にまとめること。"; | |
// 結果メールの送信先を入力↓ | |
const EMAIL_RECIPIENT = ""; | |
// 結果メールのタイトル | |
const EMAIL_SUBJECT = "arXivの新着論文のお知らせ"; | |
// 結果メールの送信者の名前 | |
const EMAIL_SENDER = "arXiv要約Bot"; | |
// 検索クエリを定義(適宜修正する) | |
// 例:cond-mat.mtrl-sciカテゴリの論文のうち、タイトルか要旨にmachine learningもしくはdeep learningを含む論文を検索する場合↓ | |
const ARXIV_QUERY = "cat:cond-mat.mtrl-sci AND (ti:machine learning OR ti:deep learning OR abs:machine learning OR abs:deep learning)"; | |
const MAX_PAPER_COUNT = 10; // 最大結果数 | |
const ARXIV_API_URL = `http://export.arxiv.org/api/query`; | |
const ARXIV_TERM = 7; // 過去何日分の記事を検索するか | |
function main() { | |
if (!OPENAI_API_KEY) { | |
console.log("ERROR: OPEN_API_KEY を指定してください"); | |
return; | |
} | |
const yesterday = new Date(); | |
yesterday.setDate(yesterday.getDate() - ARXIV_TERM); | |
const { entries, namespace } = getEntriesOn(yesterday); | |
let output = "arXivの新着論文のお知らせ\n\n"; | |
let paperCount = 0; | |
entries.forEach(entry => { | |
const arxivUrl = entry.getChild('id', namespace).getText(); | |
const title = entry.getChild("title", namespace).getText(); | |
if (++paperCount > MAX_PAPER_COUNT) return; | |
const authors = entry.getChildren("author", namespace); | |
const authorNames = authors.map(author => author.getChild("name", namespace).getText()).join(", "); | |
const summary = entry.getChild("summary", namespace).getText(); | |
const input = "\n" + "title: " + title + "\n" + "summary: " + summary; | |
const res = callChatGPT([ | |
{ | |
role: "user", | |
content: PROMPT_PREFIX + "\n" + input, | |
}, | |
]); | |
const paragraphs = res.choices.map((c) => c.message.content.trim()); | |
output += `Title: ${title}\nAuthors: ${authorNames}\n\n ${paragraphs.join("\n")}\n\n${arxivUrl}\n------------------------\n\n\n`; | |
}); | |
output = output.trim(); | |
console.log(output); | |
sendEmail(output); | |
} | |
function toYYYYMMDD(date) { | |
return [date.getFullYear(), date.getMonth() + 1, date.getDate()].join("-"); | |
} | |
function getEntriesOn(date) { | |
const url = `${ARXIV_API_URL}?search_query=${ARXIV_QUERY}&sortBy=lastUpdatedDate&sortOrder=descending&max_results=${MAX_PAPER_COUNT}&start=0&start=0&submitted_date[from]=${toYYYYMMDD(date)}&submitted_date[to]=${toYYYYMMDD(date)}`; | |
// console.log(url); | |
const feed = UrlFetchApp.fetch(url).getContentText(); | |
// console.log(feed); | |
const xml = UrlFetchApp.fetch(url).getContentText(); | |
// const xml = XmlService.parse(feed); | |
// console.log(xml); | |
const xmlDocs = XmlService.parse(xml); | |
const namespace = XmlService.getNamespace('', 'http://www.w3.org/2005/Atom'); | |
const entries = xmlDocs.getRootElement().getChildren('entry', namespace); | |
// console.log(entries); | |
return { entries, namespace }; | |
} | |
function callChatGPT(messages) { | |
const url = "https://api.openai.com/v1/chat/completions"; | |
const options = { | |
"method": "post", | |
"headers": { | |
Authorization: `Bearer ${OPENAI_API_KEY}`, | |
"Content-Type": "application/json", | |
}, | |
"payload": JSON.stringify({ | |
model: "gpt-3.5-turbo", | |
messages, | |
}), | |
}; | |
return JSON.parse(UrlFetchApp.fetch(url, options).getContentText()); | |
} | |
function sendEmail(body) { | |
const recipient = EMAIL_RECIPIENT; | |
const subject = EMAIL_SUBJECT; | |
const options = { name: EMAIL_SENDER }; | |
GmailApp.sendEmail(recipient, subject, body, options); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment