GASでAI活用【Google Apps ScriptとLLMの連携】
GASとAIを組み合わせれば、Googleサービスの自動化がさらに進化します。
この記事では、Google Apps ScriptでAIを活用する方法を解説します。
1. GAS×AIでできること
活用例
| 用途 | 内容 |
|---|---|
| データ分類 | スプレッドシートのデータを自動分類 |
| 要約生成 | 長文を自動要約 |
| メール下書き | 定型メールを自動作成 |
| 問い合わせ対応 | フォーム回答を自動処理 |
| レポート生成 | データから報告書を自動作成 |
利用できるAI
【Google AI】 ・Gemini API(推奨) ・Vertex AI 【外部API】 ・OpenAI API ・Anthropic API ・ローカルLLM(Ollama)
2. Gemini APIの利用
APIキーの取得
1. Google AI Studioにアクセス https://makersuite.google.com/ 2. 「Get API key」をクリック 3. APIキーを生成 4. キーを安全に保管
基本的な呼び出し
JavaScript (GAS)
function callGemini(prompt) {
const API_KEY = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${API_KEY}`;
const payload = {
contents: [{
parts: [{
text: prompt
}]
}]
};
const options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload)
};
const response = UrlFetchApp.fetch(url, options);
const json = JSON.parse(response.getContentText());
return json.candidates[0].content.parts[0].text;
}
// 使用例
function testGemini() {
const result = callGemini("日本の首都は?");
Logger.log(result);
}
APIキーの安全な管理
JavaScript (GAS)
// スクリプトプロパティに保存
function setApiKey() {
PropertiesService.getScriptProperties().setProperty('GEMINI_API_KEY', 'your-api-key');
}
// 取得
function getApiKey() {
return PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
}
3. スプレッドシート連携
テキスト分類
JavaScript (GAS)
function classifyTexts() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('データ');
const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) {
const text = data[i][0]; // A列:テキスト
if (text && !data[i][1]) { // B列が空なら処理
const category = classifyText(text);
sheet.getRange(i + 1, 2).setValue(category);
// API制限対策
Utilities.sleep(1000);
}
}
}
function classifyText(text) {
const prompt = `
以下のテキストを分類してください。
カテゴリ:問い合わせ、クレーム、要望、その他
1つだけ回答してください。
テキスト:${text}
`;
return callGemini(prompt).trim();
}
要約の自動生成
JavaScript (GAS)
function summarizeColumn() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const lastRow = sheet.getLastRow();
for (let i = 2; i <= lastRow; i++) {
const originalText = sheet.getRange(i, 1).getValue(); // A列
const summaryCell = sheet.getRange(i, 2); // B列
if (originalText && !summaryCell.getValue()) {
const summary = summarizeText(originalText);
summaryCell.setValue(summary);
Utilities.sleep(1000);
}
}
}
function summarizeText(text) {
const prompt = `以下の文章を50文字以内で要約してください:\n\n${text}`;
return callGemini(prompt);
}
カスタム関数として使用
JavaScript (GAS)
/**
* AIで要約を生成
* @param {string} text 要約したいテキスト
* @return {string} 要約結果
* @customfunction
*/
function AI_SUMMARIZE(text) {
if (!text) return '';
const cacheKey = 'summary_' + Utilities.computeDigest(
Utilities.DigestAlgorithm.MD5,
text
).join('');
const cache = CacheService.getScriptCache();
const cached = cache.get(cacheKey);
if (cached) return cached;
const result = summarizeText(text);
cache.put(cacheKey, result, 3600); // 1時間キャッシュ
return result;
}
4. メール自動処理
問い合わせメールの自動分類
JavaScript (GAS)
function classifyEmails() {
const threads = GmailApp.search('label:問い合わせ is:unread', 0, 10);
for (const thread of threads) {
const message = thread.getMessages()[0];
const subject = message.getSubject();
const body = message.getPlainBody();
const category = classifyInquiry(subject, body);
// ラベルを付与
const label = GmailApp.getUserLabelByName(category)
|| GmailApp.createLabel(category);
thread.addLabel(label);
// 分類結果をスプレッドシートに記録
logClassification(subject, category);
Utilities.sleep(1000);
}
}
function classifyInquiry(subject, body) {
const prompt = `
以下のメールを分類してください。
カテゴリ:見積依頼、技術相談、クレーム、その他
件名:${subject}
本文:${body.substring(0, 500)}
カテゴリ名のみ回答:
`;
return callGemini(prompt).trim();
}
返信メールの下書き作成
JavaScript (GAS)
function createReplyDraft() {
const threads = GmailApp.search('label:要返信 is:unread', 0, 5);
for (const thread of threads) {
const message = thread.getMessages()[0];
const subject = message.getSubject();
const body = message.getPlainBody();
const from = message.getFrom();
const replyText = generateReply(subject, body);
// 下書きを作成
thread.createDraftReply(replyText);
Utilities.sleep(1000);
}
}
function generateReply(subject, body) {
const prompt = `
以下のメールに対する返信を作成してください。
丁寧なビジネスメールの形式で。
件名:${subject}
本文:${body.substring(0, 500)}
返信文:
`;
return callGemini(prompt);
}
5. ドキュメント生成
議事録の自動生成
JavaScript (GAS)
function createMeetingMinutes() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メモ');
const memo = sheet.getRange('A1').getValue();
const minutes = generateMinutes(memo);
// Googleドキュメントを作成
const doc = DocumentApp.create('議事録_' + Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd'));
doc.getBody().setText(minutes);
// URLをスプレッドシートに記録
sheet.getRange('B1').setValue(doc.getUrl());
}
function generateMinutes(memo) {
const prompt = `
以下のメモから議事録を作成してください。
形式:
# 議事録
## 日時・参加者
## 議題
## 決定事項
## アクション項目
メモ:
${memo}
`;
return callGemini(prompt);
}
報告書の自動生成
JavaScript (GAS)
function generateMonthlyReport() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('月次データ');
const data = sheet.getDataRange().getValues();
// データを整形
const dataText = formatDataForAI(data);
const report = generateReport(dataText);
// スライドを作成
const presentation = SlidesApp.create('月次報告_' + Utilities.formatDate(new Date(), 'JST', 'yyyyMM'));
const slide = presentation.getSlides()[0];
slide.getShapes()[0].getText().setText(report);
}
function formatDataForAI(data) {
let text = '';
const headers = data[0];
for (let i = 1; i < data.length; i++) {
for (let j = 0; j < headers.length; j++) {
text += `${headers[j]}:${data[i][j]}\n`;
}
text += '\n';
}
return text;
}
function generateReport(dataText) {
const prompt = `
以下のデータから月次報告のサマリーを作成してください。
3〜5行で簡潔にまとめてください。
データ:
${dataText}
`;
return callGemini(prompt);
}
6. 実践的な活用例
フォーム回答の自動処理
JavaScript (GAS)
function onFormSubmit(e) {
const responses = e.values;
const name = responses[1];
const inquiry = responses[2];
// 問い合わせ内容を分析
const analysis = analyzeInquiry(inquiry);
// スプレッドシートに分析結果を追加
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const lastRow = sheet.getLastRow();
sheet.getRange(lastRow, 4).setValue(analysis.category);
sheet.getRange(lastRow, 5).setValue(analysis.urgency);
sheet.getRange(lastRow, 6).setValue(analysis.summary);
// 緊急の場合は通知
if (analysis.urgency === '高') {
sendUrgentNotification(name, inquiry, analysis);
}
}
function analyzeInquiry(inquiry) {
const prompt = `
以下の問い合わせを分析してください。
JSON形式で回答:
{
"category": "カテゴリ(見積、技術、クレーム、その他)",
"urgency": "緊急度(高、中、低)",
"summary": "20文字以内の要約"
}
問い合わせ:${inquiry}
`;
const result = callGemini(prompt);
return JSON.parse(result);
}
定期レポートの自動送信
JavaScript (GAS)
function sendWeeklyReport() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('週次データ');
const data = sheet.getDataRange().getValues();
const reportText = generateWeeklyReport(data);
// メール送信
GmailApp.sendEmail(
'manager@example.com',
'週次レポート ' + Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd'),
reportText
);
}
function generateWeeklyReport(data) {
const dataText = formatDataForAI(data);
const prompt = `
以下の週次データからレポートを作成してください。
形式:
1. 今週のサマリー(3行)
2. 主なトピック(箇条書き)
3. 来週の見通し
データ:
${dataText}
`;
return callGemini(prompt);
}
// トリガー設定
function setWeeklyTrigger() {
ScriptApp.newTrigger('sendWeeklyReport')
.timeBased()
.onWeekDay(ScriptApp.WeekDay.FRIDAY)
.atHour(17)
.create();
}
7. 注意点とベストプラクティス
API利用の注意
JavaScript (GAS)
// レート制限対策
function callGeminiWithRetry(prompt, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return callGemini(prompt);
} catch (e) {
if (i === maxRetries - 1) throw e;
Utilities.sleep(2000 * (i + 1)); // 指数バックオフ
}
}
}
// キャッシュの活用
function callGeminiWithCache(prompt) {
const cache = CacheService.getScriptCache();
const cacheKey = Utilities.computeDigest(
Utilities.DigestAlgorithm.MD5,
prompt
).join('');
const cached = cache.get(cacheKey);
if (cached) return cached;
const result = callGemini(prompt);
cache.put(cacheKey, result, 3600);
return result;
}
エラーハンドリング
JavaScript (GAS)
function safeCallGemini(prompt) {
try {
const result = callGemini(prompt);
return { success: true, data: result };
} catch (e) {
Logger.log('API Error: ' + e.message);
return { success: false, error: e.message };
}
}
コスト管理
コスト削減のコツ
- キャッシュを活用
- プロンプトを短くする
- 不要な呼び出しを避ける
- バッチ処理でまとめる
8. まとめ
GAS×AIの活用パターン
活用パターン
- スプレッドシートのデータ処理
- メールの自動分類・返信
- ドキュメントの自動生成
- フォーム回答の分析
- 定期レポートの作成
導入ステップ
1. Gemini APIキーを取得 2. 簡単な関数から試す 3. スプレッドシート連携 4. 自動化トリガーを設定
注意点
注意点
- API制限を考慮
- キャッシュを活用
- エラーハンドリング
- コスト管理
関連記事
