ToDoリスト導入編📝(LLMアプリケーションを活用したプロトタイプ)
ToDoリストとLLMを組み合わせたプロトタイプを作っていきたい
背景
- 多忙で新生活の準備が進んでいない。
- パートナーがイライラしている。
- ToDoリストを作って課題を見える化しよう。
ただ、買うものは列挙できても何を買うかがなかなか決まらない。。。
↓
AIが何を買えば良いか提案してくれるToDoリストがあれば便利!
ToDoリストは以下のサイトを参照してAppSheetで作成。
G列にLLMからのアドバイスを出力させるイメージ。
Difyを呼び出すためのGASは以下の記事を参照して作成。
GAS初めて触る。
function sendChildrenQuestion() {
// スプレッドシートのIDは、スプレッドシートのURLに含まれています。
// 例えば、URLが https://docs.google.com/spreadsheets/d/abcd1234efgh5678ijkl90mnopqrstuv の場合、
// abcd1234efgh5678ijkl90mnopqrstuv がスプレッドシートのIDです
var spreadsheetId = 'MY SPREADSHEET ID'; // TODO スプレッドシートのIDを書き換え
var sheetName = 'シート1';
var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
var sheet = spreadsheet.getSheetByName(sheetName);
// B列のデータをすべて取得
var data = sheet.getRange('B:B').getValues();
// 最後の行を特定(空のセルは除外)
var lastRow = data.filter(String).length;
// 最後の行の質問を取得
var question = sheet.getRange('B' + lastRow).getValue();
var url = 'https://api.dify.ai/v1/workflows/run'; // リクエストを送るURL
// リクエストのヘッダー情報
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {MY Dify API}' // TODO DifyワークフローのAPIキーで書き換え
};
// リクエストのボディデータ
var payload = {
'inputs': {'Input':question}, // TODO Difyのワークフローの開始で設定した変数名
'response_mode': 'blocking',
'user': 'user123'
};
// オプションの設定
var options = {
'method': 'post',
'headers': headers,
'payload': JSON.stringify(payload),
'muteHttpExceptions': true // これをtrueにすると、エラーが発生しても例外がスローされません
};
// HTTP POSTリクエストの送信
try {
var response = UrlFetchApp.fetch(url, options);
// Logger.log(response.getContentText()); // レスポンスの内容をログに出力
var jsonResponse = response.getContentText()
// JSONをオブジェクトに変換
var responseObject = JSON.parse(jsonResponse);
// 必要なデータを取得
var taskId = responseObject.task_id;
var workflowRunId = responseObject.workflow_run_id;
var data = responseObject.data;
var status = data.status;
var outputs = data.outputs;
var answer = outputs.text;
// ログに出力
Logger.log('Task ID: ' + taskId);
Logger.log('Workflow Run ID: ' + workflowRunId);
Logger.log('Status: ' + status);
Logger.log('Outputs Text: ' + answer);
// G列に返却された値を書き込み
sheet.getRange('G' + lastRow).setValue(answer);
} catch (e) {
Logger.log('Error: ' + e.message); // エラーメッセージをログに出力
}
}
Difyのワークフローは授業資料を参照して作成。
授業ではLLMはGPTを使ったが、今回はGeminiを使ってみる。
Difyのプロンプト
## 命令
あなたは「引っ越しのプロ」です。
ユーザーは"{{#1721071307658.Input#}}"の購入を検討しています。
以下の条件を参考に、具体的にどのような物を購入すればよいか結果だけをシンプルに200文字以内でアドバイスしてください。
## 条件
・20代夫婦
・1LDK
・北欧好き
・ミニマリスト
・節約志向
AppSheetに新規の項目を追加してもLLMから回答が出力されない。。。
AppSheetのモニターを見るとエラーが出ているみたい
エラーメッセージ
Error encountered in step with name [New step]: The tasks argument included a null value. (Parameter 'tasks')
Qiitaとteratailとstack overflowとstack overflow 日本語版の4サイトで上記エラーについて質問を投げた。
stack overflow 日本語版に回答がついた。
"マルチポスト"とやらを注意されただけだった。
以下の文言を質問文に追記した。
※本件は他サイトでマルチポストしております。(teratail、Qiita、stack overflow)
他のサイトで回答やヒントなどの情報が得られた場合、自己回答で情報共有させていただきます。
回答はなかったけど、変数名にシングルクォーテーションが不要なだけだった。
QAサイトの方は明日、自己回答でクローズさせる。
- 'inputs': {'Input':question}, // TODO Difyのワークフローの開始で設定した変数名
+ 'inputs': {Input:question}, // TODO Difyのワークフローの開始で設定した変数名
更新通知をLINE Notifyに送るようにGASを修正した。というかClaude 3.5 Sonnetに修正してもらった。
## 命令
あなたはプロのWebエンジニアです。
以下のGoogle Apps Scriptのコードに最後にG列に追加した内容をLINE notifyに通知する実装を加えたい。追加内容を教えて。
ただし、不要な修正はしないでください。
また、誤った情報が含まれている場合、罰金100万ドルを請求します。
```Google Apps Script
function sendChildrenQuestion() {
// スプレッドシートのIDは、スプレッドシートのURLに含まれています。
// 例えば、URLが https://docs.google.com/spreadsheets/d/abcd1234efgh5678ijkl90mnopqrstuv の場合、
// abcd1234efgh5678ijkl90mnopqrstuv がスプレッドシートのIDです
var spreadsheetId = '1ikJ1P-UwAYD2pmoVZ4BzYcvUMswz1TAPqOBTryN00Lg'; // TODO スプレッドシートのIDを書き換え
var sheetName = 'シート1';
var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
var sheet = spreadsheet.getSheetByName(sheetName);
// B列のデータをすべて取得
var data = sheet.getRange('B:B').getValues();
// 最後の行を特定(空のセルは除外)
var lastRow = data.filter(String).length;
// 最後の行の質問を取得
var question = sheet.getRange('B' + lastRow).getValue();
var url = 'https://api.dify.ai/v1/workflows/run'; // リクエストを送るURL
// リクエストのヘッダー情報
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer app-YMvobLPFQYDvJmFNY2U7axKH' // TODO DifyワークフローのAPIキーで書き換え
};
// リクエストのボディデータ
var payload = {
'inputs': {Input:question}, // TODO Difyのワークフローの開始で設定した変数名
'response_mode': 'blocking',
'user': 'user123'
};
// オプションの設定
var options = {
'method': 'post',
'headers': headers,
'payload': JSON.stringify(payload),
'muteHttpExceptions': true // これをtrueにすると、エラーが発生しても例外がスローされません
};
// HTTP POSTリクエストの送信
try {
var response = UrlFetchApp.fetch(url, options);
// Logger.log(response.getContentText()); // レスポンスの内容をログに出力
var jsonResponse = response.getContentText()
// JSONをオブジェクトに変換
var responseObject = JSON.parse(jsonResponse);
// 必要なデータを取得
var taskId = responseObject.task_id;
var workflowRunId = responseObject.workflow_run_id;
var data = responseObject.data;
var status = data.status;
var outputs = data.outputs;
var answer = outputs.text;
// ログに出力
Logger.log('Task ID: ' + taskId);
Logger.log('Workflow Run ID: ' + workflowRunId);
Logger.log('Status: ' + status);
Logger.log('Outputs Text: ' + answer);
// G列に返却された値を書き込み
sheet.getRange('G' + lastRow).setValue(answer);
} catch (e) {
Logger.log('Error: ' + e.message); // エラーメッセージをログに出力
}
}
function sendChildrenQuestion() {
// スプレッドシートのIDは、スプレッドシートのURLに含まれています。
// 例えば、URLが https://docs.google.com/spreadsheets/d/abcd1234efgh5678ijkl90mnopqrstuv の場合、
// abcd1234efgh5678ijkl90mnopqrstuv がスプレッドシートのIDです
var spreadsheetId = 'YOUR_SPREADSHEET_ID'; // TODO スプレッドシートのIDを書き換え
var sheetName = 'シート1';
var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
var sheet = spreadsheet.getSheetByName(sheetName);
// B列のデータをすべて取得
var data = sheet.getRange('B:B').getValues();
// 最後の行を特定(空のセルは除外)
var lastRow = data.filter(String).length;
// 最後の行の質問を取得
var question = sheet.getRange('B' + lastRow).getValue();
var url = 'https://api.dify.ai/v1/workflows/run'; // リクエストを送るURL
// リクエストのヘッダー情報
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer {YOUR_DIFY_API_KEY}' // TODO DifyワークフローのAPIキーで書き換え
};
// リクエストのボディデータ
var payload = {
'inputs': {Input:question}, // TODO Difyのワークフローの開始で設定した変数名
'response_mode': 'blocking',
'user': 'user123'
};
// オプションの設定
var options = {
'method': 'post',
'headers': headers,
'payload': JSON.stringify(payload),
'muteHttpExceptions': true // これをtrueにすると、エラーが発生しても例外がスローされません
};
// HTTP POSTリクエストの送信
try {
var response = UrlFetchApp.fetch(url, options);
// Logger.log(response.getContentText()); // レスポンスの内容をログに出力
var jsonResponse = response.getContentText()
// JSONをオブジェクトに変換
var responseObject = JSON.parse(jsonResponse);
// 必要なデータを取得
var taskId = responseObject.task_id;
var workflowRunId = responseObject.workflow_run_id;
var data = responseObject.data;
var status = data.status;
var outputs = data.outputs;
var answer = outputs.text;
// ログに出力
Logger.log('Task ID: ' + taskId);
Logger.log('Workflow Run ID: ' + workflowRunId);
Logger.log('Status: ' + status);
Logger.log('Outputs Text: ' + answer);
// G列に返却された値を書き込み
sheet.getRange('G' + lastRow).setValue(answer);
} catch (e) {
Logger.log('Error: ' + e.message); // エラーメッセージをログに出力
}
// LINE Notify用の処理を追加
var lineNotifyToken = 'YOUR_LINE_NOTIFY_TOKEN'; // TODO: LINE Notifyのトークンを設定してください
var lineNotifyUrl = 'https://notify-api.line.me/api/notify';
// B列(質問)とG列(回答)の最新の内容を取得
var latestQuestion = sheet.getRange('B' + lastRow).getValue();
var latestAnswer = sheet.getRange('G' + lastRow).getValue();
// LINE Notifyに送信するメッセージを作成
var message = '\n【' + latestQuestion + '】 が追加されました!' + '\n\n【AI提案】\n' + latestAnswer + '\nhttps://www.appsheet.com/newshortcut/fd7b2962-439e-4648-a638-d6846a068992';
var lineNotifyOptions = {
'method': 'post',
'headers': {
'Authorization': 'Bearer ' + lineNotifyToken,
'Content-Type': 'application/x-www-form-urlencoded'
},
'payload': 'message=' + encodeURIComponent(message)
};
// LINE Notifyに通知を送信
try {
var lineResponse = UrlFetchApp.fetch(lineNotifyUrl, lineNotifyOptions);
Logger.log('LINE Notify Response: ' + lineResponse.getContentText());
} catch (error) {
Logger.log('LINE Notify Error: ' + error.message);
}
}
一瞬しかLINE使ってないけど、またLINE DCのLT出れたらいいな。
宿題提出しようとしたら出題意図から外れていることに気づいた
今回は LLMアプリケーション担う部分のプロトタイプ(※チャットアプリケーションのようなアウトプットを想定しています) だった。
時間ないけど急いで記事の方向性を修正する。
とりあえず、RAGになるようにワークフローを修正。
DALL-E 3のモジュールも発見したので、AppSheet(ToDoリスト)の各項目のサムネイルで使えないか検討していきたい。
LLMのTempretureとTop_pとTop_kについて調べてみた。
TempretureとTop_pは一般的にはどちらを変更して制御するみたい。
デフォルトではTempretureが0.7でTop_pはオフになっていた。
Tempretureを小さくすると回答のバリエーションが少なくなり、大きくすると精度が悪い回答をするようになった。
デフォルトの0.7がちょうどいいのかも。