具材を入力するだけでレシピ完成!「AI献立くん」
この度、「AI献立くん」をリリースしました!
AI献立くん : https://lin.ee/sRdqjeO
具材を何個か入力するだけで、自動で何個か献立を考えてくれます。
今回のリリースでは、下記の3種類のレシピを考えてくれます。
- すぐに作れるもの
- 簡単に作れるもの
- 美味しく作れるもの
同時にYouTubeでもリリース動画を出しています。
作り方
今回はLINEの公式アカウントをGoogle Apps Script (GAS) でスプレッドシートをデータベースに実装しています。AI部分はChatGPTのAIである「gpt-3.5-turbo」を使用しています。
詳しいGASでAI搭載のLINE公式アカウントの作り方に関しては、Udemy講座をご確認ください。
Udemy講座 : https://www.udemy.com/course/chatgpt-line-function-calling-ai/
今回リリースしているプログラム部分に関しては、下記に公開しておきます。
スプレッドシートは「制約」「ログ」「ユーザー」の3種類を用意しています。
コード.gs
function doPost(e) {
// メッセージ受信
const data = JSON.parse(e.postData.contents).events[0]
// ユーザーID取得
const lineUserId = data.source.userId
// リプレイトークン取得
const replyToken = data.replyToken
// 送信されたメッセージ取得
const postMessage = data.message.text
// データのタイプを取得
const dataType = data.type
// フォロー時はユーザーデータを登録
if (dataType == "follow")
addUser(userId)
// 個別のスプレッドシート情報取得
// const SHEET_ID = findSheetId(lineUserId);
// テキスト以外だった時(スタンプや写真など)
if (postMessage === undefined)
return sendMessage(replyToken, "献立を作るAIなので、お手元にある具材を伝えてね!\n例:ソーセージ、ポテト、人参");
// データ生成&LINEに送信
const replyText = chatGPT(postMessage);
sendMessage(replyToken, replyText);
debugLog(lineUserId, postMessage, replyText);
}
// 返答するメッセージを生成
function chatGPT(prompt) {
// prompt = "こんにちは"
let constraints;
try {
constraints = SHEET.getRange(1, 1).getValue()
} catch (e) {
console.log("制約なし");
}
const requestOptions = {
"method": "post",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer "+ OPENAI_APIKEY
},
"payload": JSON.stringify({
"model": CHAT_GPT_VER,
"messages": [
{"role": "system", "content": constraints},
{"role": "user", "content": prompt}
]
})
}
const response = UrlFetchApp.fetch(CHAT_GPT_URL, requestOptions);
const responseText = response.getContentText();
const json = JSON.parse(responseText);
const text = json['choices'][0]['message']['content'].trim();
console.log(text);
const search_prompt = prompt.replace(/ /g, 'と').replace(/ /g, 'と').replace(/\n/g, 'と');
const return_text = `${text}\n\nhttps://cookpad.com/search/${search_prompt}`
return (return_text);
}
// LINEに返答するデータ生成
function sendMessage(replyToken, replyText) {
const postData = {
"replyToken" : replyToken,
"messages" : [
{
"type" : "text",
"text" : replyText
}
]
};
return postMessage(postData);
}
// LINEに返答
function postMessage(postData) {
const headers = {
"Content-Type" : "application/json; charset=UTF-8",
"Authorization" : "Bearer " + LINE_ACCESS_TOKEN
};
const options = {
"method" : "POST",
"headers" : headers,
"payload" : JSON.stringify(postData)
};
return UrlFetchApp.fetch(LINE_REPLY_URL, options);
}
ろ
ログ.gs
function debugLog(userId, text, replyText) {
if ('' == text) return; // テキストではない時はログなし
const UserData = findUser(userId); // ユーザーシートにデータがあるか確認
typeof UserData === "undefined" ? addUser(userId) : userUseChat(userId); // ユーザーシートにデータがなければユーザー追加、あれば投稿数だけ追加
const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss'); // 現在の日付を取得
SHEET_LOG.appendRow([userId, UserData, text, replyText, date]); // ログシートに情報追加
// 日付順に並び替え
const numColumn_LOG = SHEET_LOG.getLastColumn(); // 最後列の列番号を取得
const numRow_LOG = SHEET_LOG.getLastRow()-1; // 最後行の行番号を取得
const dataRange_LOG = SHEET_LOG.getRange(2, 1, numRow_LOG, numColumn_LOG);
dataRange_LOG.sort([{column: 5, ascending: false}]); // 日付順に並び替え
}
// メンバーとしてユーザー登録されているか検索
function findUser(uid) {
return getUserData().reduce(function(uuid, row) { return uuid || (row.key === uid && row.value); }, false) || undefined;
}
// ユーザー情報取得
function getUserData() {
const data = SHEET_USER.getDataRange().getValues();
return data.map(function(row) { return {key: row[0], value: row[1]}; });
}
// ユーザー追加
function addUser(userId) {
const userName = getUserDisplayName(userId)
const userIMG = getUserDisplayIMG(userId)
const SHEET_ID = sheetCopy(userName)
const DATE = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss'); // 現在の日付を取得
SHEET_USER.appendRow([userId, userName, userIMG, 0, SHEET_ID, DATE, DATE])
}
// シートをコピー
function sheetCopy(userName) {
// そのスプレッドシートのコピーを作成
const SS_COPY = SS.copy(`[${userName}] ${SS.getName()}`)
// そのスプレッドシートのIDを取得
const SHEET_ID = SS_COPY.getId()
// コピーしたシートのユーザー情報部分は削除
const SHEET_LOG = SS_COPY.getSheetByName('ログ')
SHEET_LOG.deleteColumns(1,2)
const SHEET_USER = SS_COPY.getSheetByName('ユーザー')
SS_COPY.deleteSheet(SHEET_USER)
// シートのログデータは全て削除
const numColumn = SHEET_LOG.getLastColumn() // 最後列の列番号を取得
const numRow = SHEET_LOG.getLastRow()-1 // 最後行の行番号を取得
if (numRow != 0) {
SHEET_LOG.getRange(2, 1, numRow, numColumn).clear()
}
return SHEET_ID
}
// ユーザーのプロフィール名取得
function getUserDisplayName(userId) {
const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + LINE_ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).displayName;
}
// ユーザーのプロフィール画像取得
///////////////////////////////
function getUserDisplayIMG(userId) {
const url = 'https://api.line.me/v2/bot/profile/' + userId;
const userProfile = UrlFetchApp.fetch(url,{
'headers': {
'Authorization' : 'Bearer ' + LINE_ACCESS_TOKEN,
},
})
return JSON.parse(userProfile).pictureUrl;
}
// ユーザーの投稿数をプラス1
function userUseChat(userId) {
// 送信したユーザー先のユーザーを検索
const textFinder = SHEET_USER.createTextFinder(userId);
const ranges = textFinder.findAll();
// ユーザーが存在しない場合エラー
if(!ranges[0]) SHEET_USER.appendRow([userId, "???", '', 1]);;
// ステータスを出勤中から離席中に変更
const statusFinder = SHEET_USER.createTextFinder('投稿数');
const statusRanges = statusFinder.findAll();
const row = ranges[0].getRow();
const column = statusRanges[0].getColumn();
// 投稿数追加
let number = SHEET_USER.getRange(row, column).getValue();
SHEET_USER.getRange(row, column).setValue(++number);
}
config.gs
// API設定部分
const OPENAI_APIKEY = "sk-*******************************************";
const LINE_ACCESS_TOKEN = "**************************************************************************************************************************************************************************=";
// 使用API
const LINE_REPLY_URL = 'https://api.line.me/v2/bot/message/reply';
const CHAT_GPT_URL = "https://api.openai.com/v1/chat/completions";
const CHAT_GPT_VER = "gpt-3.5-turbo";
// スプレッドシートの情報
const SS = SpreadsheetApp.getActiveSpreadsheet();
const SHEET = SS.getSheetByName('制約');
const SHEET_LOG = SS.getSheetByName('ログ');
const SHEET_USER = SS.getSheetByName('ユーザー');さ
さいごに
今後、毎月何かしら新しいサービスをリリースしていこうと思っています。今回は1時間くらいで作れたので、毎日新しいサービスを作ろうと思えば作れるんじゃないかとも思いますが、長く続けていくことのほうが大事だと思っているので、毎月に設定しています。
暖かく見守っていただけると嬉しいです。サービス開発で億り人になるぞっ!
Udemy講座もよろしくお願いします!
Udemy講座 : https://www.udemy.com/course/chatgpt-line-function-calling-ai/








【メタバース入門】Unity × Cluster ワールド作ろう
【1,000円 OFF優待!】
プログラミングで作るLINEチャットボット|初心者向け個別レッスン
【1,000円 OFF優待!】





