今回はレシピを提案してくれるアレクサスキルを作成しました。
アレクサに欲しい献立のキーワードを指定することで、ChatGPTがレシピを提案し、DALL-Eが生成した画像を提供してくれるというスキルです。

どんな献立が欲しい?

ヘルシーな晩御飯の献立

提案したよ。
↓↓
スマホにメールが送信される
(献立のレシピと画像のURLが記載)
↓↓

↓↓
メールに記載されたURLにアクセスすることで、
料理名で生成された画像が確認できる
↓↓


これで晩御飯に迷わなくていいね。
使ってみる
例えば、以下のようなプロンプトを指定することができます。
- 場面を指定したプロンプト
例:「朝食におすすめの献立」
→「アボカドトースト、スムージーボウル、ゆで卵」 - 気分で指定したプロンプト
例:「ダイエットに最適なヘルシーな献立」
→「蒸し鶏と野菜のサラダ、豆腐とほうれん草の味噌汁、玄米」 - 料理名を指定したプロンプト
例:「台湾チャーハンがメインの献立」
→「台湾チャーハン、青菜の中華炒め、わかめスープ」 - 食材を指定したプロンプト
例:「卵を使った献立」
→「オムライス、ほうれん草の卵とじ、味噌汁」
場面を指定したプロンプト
朝ご飯や夜ご飯など、場面に合わせたプロンプトで献立を提案してもらえます。

朝食におすすめの献立

提案したよ。
↓↓
メール送信
↓↓


気分で指定したプロンプト
その日の気分に合わせた献立を提案してもらうこともできます。

ダイエットに最適なヘルシーな献立

提案したよ。
↓↓
メール送信
↓↓


料理名を指定したプロンプト
料理名を指定して実行することもできます。

台湾チャーハンがメインの献立
このようなプロンプトを入力すると、台湾チャーハンを中心とした献立が提案され、関連する料理の画像も生成されます。

提案したよ。
↓↓
メール送信
↓↓


食材を指定したプロンプト
食材を指定した場合でも、それに応じたレシピを提案してくれます。
例えば、「卵」を指定すると、卵を使った様々な料理のレシピが提供され、それらの料理の画像も合わせて生成されます。

卵を使った献立

提案したよ。
↓↓
メール送信
↓↓


このように、特定の料理や材料を指定することができます。
簡単に多様な献立を提案してもらえるため、とても便利です。
日々の献立に悩んでいる方や、新しい料理に挑戦したい方にぜひおすすめします。
構成と処理の流れ
主な構成要素は、以下のとおりです。
- Alexa
- Lambda
- OpenAIのAPI(gptとDALL-E 3)
- Amazon SNS

- アレクサスキルでLambda処理を呼び出す
- GPT-4oでレシピを提案
- DALL-E 3のレシピの画像を生成
- 生成画像のURLをAmazon SNSで自身のメールアドレスに送信
Alexaのカスタムスキル作成

- カスタムスキルを作成
- カスタムスキルとLambdaの紐付け
カスタムスキルを作成
Alexaのカスタムスキルとは、自身で実装した処理に従ってアレクサが応答するというものです。
Alexa Developer Consoleから、カスタムスキルを作成することができます。

カスタムスキル作成のさらに具体的な作成手順は、以下の記事をご確認ください。
Skill Invocation Nameの設定
作成したカスタムスキルのdeveloper consoleから、「Skill Invocation Name」を選択します。

カスタムスキルを呼び出すためのトリガーワードを設定します。
今回は「レシピ提案して」というトリガーワードでカスタムスキルが起動するようにしてみました。

Intentsの作成
developer consoleからIntentsも作成しておきます。
ユーザーからの応答は、このIntentsに設定内容に応じて処理されます。


questionという名前でAMAZON.Languageというスロットを設定します。

ざっくりというと、日本語を検知したら「この処理が走るよ。」という意味のスロットです。
Lambda関数では、以下の箇所が該当します。
ユーザーからの応答が日本語として、questionに格納されます。
class ChatGPTImageGeneIntentHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
return ask_utils.is_intent_name("ChatGPTImageGeneIntent")(handler_input)
def handle(self, handler_input):
slots = handler_input.request_envelope.request.intent.slots
question = slots["question"].value
prompt = question
詳しくは以下のドキュメントを参照してみてください。
Alexa developer console スロットタイプリファレンス
アレクサスキルとLambdaの紐付け
developer consoleのEndpointで「Default Region」を設定します。
この値は、Lambda関数のARNを入力してください。


‖


これでAlexaカスタムスキルの設定は完了です。
Lambda設定

Lambda関数では、実際の処理を実装します。
今回はアレクサで読み取った音声を入力として、ChatGPT、VOICEVOXで出力ファイルを作成し、最後にアレクサから応答を返す処理をPythonにて実装します。
- Lambda関数の作成
- Pythonコード作成
- レイヤーの設定(Python3.12ライブラリ)
- OpenAIの環境変数を設定
以下のgithubにソースコードやライブラリのzipファイルを格納しています。
必要に応じて、ご利用下さい。
https://github.com/my-repo-441/chatgpt-recipe-recommender/tree/main
Lambda関数の作成
Lambdaのコンソール画面から、「関数の作成」ボタンを押下します。

以下の値で作成します。
- 関数名:任意
- ランタイム:Python3.12
- アーキテクチャ:x86_64

「関数の作成」ボタンを押下し、Lambda関数を作成します。
以下のように、関数が作成できていることを確認します。

Lambdaレイヤーにライブラリのzipファイルをアップロード
Lambdaのコンソール画面から、レイヤーを選択します。
なお今回使用したレイヤーのzipファイルは以下のgithubに公開しています。
- リンク:https://github.com/my-repo-441/chatgpt-recipe-recommender.git
- コード:
・python.zip(Lambdaのレイヤーに登録するもの)

「レイヤーの作成」を押下し、作成したzipファイルをアップロードしてください。
この時、ランタイムはPython3.12としてください。

OpenAIのAPIキーを環境変数として設定
Lambdaの「設定」から、「環境変数」を選択します。
以下のように、OpenAIのAPIキーを環境変数として追加します。

上記で追加した環境変数は、コードから以下のようにして呼び出すことができます。
import os
from openai import OpenAI
client = OpenAI()
openai_key = os.getenv('OPENAI_API_KEY')
GPTおよびDALL-E3のAPIを使用するためには、OpenAIのAPIキーが必要です。
APIキーを取得されていない方は、まずOpenAIのAPI発行画面からAPIキーを発行しましょう。
Create new secret keyを押下します。

「Create secret key」を押下します。

作成されたキーをコピーしておきます。
画面を閉じてしまうとキーがコピーできなくなるため、注意してください。

Pythonコードの作成
Alexaのカスタムスキル起動時は、lambda_function.pyが呼び出されます。
Lambda関数の画面にて、lambda_function.pyコードを作成します。

今回使用したlambda_function.pyのコードは以下のgithubに公開しています。
- リンク:https://github.com/my-repo-441/chatgpt-recipe-recommender.git
- コード:
・lambda_function.py(Alexaから呼び出されるコード)
レシピを提案する部分の実装は、gpt-4oを用いています。
import os
from openai import OpenAI
client = OpenAI()
openai_key = os.getenv('OPENAI_API_KEY')
messages = [
{
"role": "system",
"content": ("あなたはユーザーの希望を元に、栄養バランスの取れた献立とそのレシピを提案してくれます。"
"例えば、晩御飯の献立の場合、晩御飯に適して献立を考えて提案してくれます"
"必ず次のように最初に料理名:「○○○○、○○○○」という形式で献立の料理名を列挙して。"
"料理名:「白ごはん、チーズインハンバーグ、ポテトサラダ」"
"その後に、それぞれの料理の材料や作り方など必要なレシピを示して。")
},
{
"role": "user",
"content": prompt,
}
]
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
max_tokens=1000
)
answer = response.choices[0].message.content
次に以下のコードにより、chatgptの出力から「料理名」だけを切り取ります。

例えば以下のような出力の場合、「玄米ごはん、鶏むね肉のグリル、ミックスビーンズサラダ」だけを切り取ります。
Recipe:
料理名:「玄米ごはん、鶏むね肉のグリル、ミックスビーンズサラダ」
【玄米ごはん】
材料:玄米1合、水200ml
作り方:
1. 玄米は炊飯器の内釜に入れ、しっかりと洗って水を切ります。
2. 水を加え、ひと混ぜしたら普通に炊飯します。
【鶏むね肉のグリル】
材料:鶏むね肉2枚、オリーブオイル大さじ2、塩適量、こしょう適量、レモン1個
作り方:
1. 鶏むね肉は一口大に切り、塩こしょうで下味をつける。
2. フライパンを温め、オリーブオイルを引き、鶏むね肉を焼く。焼き色がついたら裏返し、全体が白くなるまで焼く。
3. レモンの半分を絞ってジュースを取り、焼き上がった鶏むね肉にかけ、残りのレモンはスライスして添える。
【ミックスビーンズサラダ】
材料:ミックスビーンズ缶1缶、赤玉ねぎ1/4個、パプリカ(赤・黄)各1/2個、オリーブオイル大さじ2、塩適量、こしょう適量
作り方:
1. 赤玉ねぎは薄切り、パプリカは種を取り除き、乱切りにする。ミックスビーンズは水洗いして水気を切る。
2. 全ての材料を混ぜ合わせ、オリーブオイル、塩、こしょうで味を調える。
以上、ヘルシーな晩ごはんの献立です。バランス良く栄養をとるため、玄米ごはんで炭水化物を、鶏むね肉のグリルでたんぱく質を、ミックスビーンズサラダでビタミンや食物繊維を摂取できます。
切り取った文字列をDALL-E3のプロンプトとして渡します。
Prompt:
次の料理名の美味しそうな写真: 玄米ごはん、鶏むね肉のグリル、ミックスビーンズサラダ
# 料理名を切り取る
start = answer.find("「") + 1
end = answer.find("」")
dish_names = answer[start:end]
# Print the extracted dish names
print(f"dish_name={dish_names}")
# Use the extracted text as a prompt for image generation
prompt_img = f"次の料理名の美味しそうな写真: {dish_names}"
response = client.images.generate(
model="dall-e-3",
prompt = prompt_img,
#size="1024x1024",
size="1792x1024",
quality="standard",
n=1,
)
image_url = response.data[0].url
出力としては画像のURLが出力されるので、URLにアクセスすると生成された画像が確認できます。

↓↓
URLにアクセス
↓↓

Amazon SNSの設定

DALL-E 3は、生成した画像をURL形式で応答します。
画像のURLを、自身のメールアドレスに送信するように設定します。
- SNSトピックを作成
- 自身のメールをサブスクライブ
SNSトピックを作成
トピックの作成を選択します。
タイプはスタンダードを選択し、名前は任意でOKです。

トピックの作成を押下します。

自身のメールをサブスクライブ
作成したトピックの画面で、サブスクリプションの作成を押下します。



エンドポイントのメールアドレス宛に、以下のように承認の確認メールがきます。Confirm subscriptionを押下することで、SNSからのメールを受け取ることができるようになります。

lambda_function.pyでのソースコード実装部分は以下です。
これでSNSへのメール連携部分の準備は完了です。
# SNSメッセージの組み立てとパブリッシュ
message_to_publish = {
"Recipe": answer,
"Image URL": image_url,
"Prompt": prompt_img
}
# message_json_to_publish = json.dumps(message_to_publish, ensure_ascii=False, indent=4)
# JSON形式のメッセージを文字列に変換してフォーマット
recipe_text = message_to_publish["Recipe"].replace("\\n", "\n")
image_url_text = message_to_publish["Image URL"]
prompt_text = message_to_publish["Prompt"]
message_json_to_publish = f"Recipe:\n{recipe_text}\n\nImage URL:\n{image_url_text}\n\nPrompt:\n{prompt_text}"
# SNSクライアントの作成
sns_client = boto3.client('sns')
# SNSトピックのARN
topic_arn = 'arn:aws:sns:us-east-1:726788541449:OpenAI-Image-Generation'
# SNSトピックにメッセージをパブリッシュ
response = sns_client.publish(
TopicArn=topic_arn,
Message=message_json_to_publish,
Subject='Generated Image URL'
)
Alexaカスタムスキルを実行

上図の処理を実際に動かしてみます。
作成したAlexaカスタムスキルを実行する方法は、以下の3つです。
- Alexa Developer Consoleから実行
- Alexaアプリから実行
- Alexaから実行
Alexa Developer Consoleから実行
カスタムスキル作成するためのAlexa Developer Consoleから実行できます。
この方法は、主にカスタムスキルのテスト目的で使われます。

作成したLambda関数が正常に動作するかを確認するためにも、まずはDeveloper Consoleから実行してみましょう。


Alexaアプリから実行
以下のAlexaアプリを使って、スマートフォン上でスキルを実行できます。



↓↓

Alexaから実行
Alexaから直接カスタムスキルを呼び出すこともできます。

まとめ
ChatGPTとDALL-Eを活用した献立提案のアレクサスキルを作成しました。
このアレクサスキルを使えば、特定の料理名や材料、さらには気分に応じて、簡単に多様な献立を提案してもらうことができます。

DALL-Eの画像生成も視覚的にも楽しめるね。
例えば、「台湾チャーハンがメインの献立」や「卵を使った献立」、「ダイエットに最適なヘルシーな献立」など、様々なプロンプトに応じた具体的なレシピが提案されます。
これにより、毎日の食事の計画がより楽しく、簡単になります。
日々の献立に悩んでいる方、新しい料理に挑戦したい方、またはヘルシーな食事を心がけたい方にとって、このシステムは非常に便利で役立つツールです。ぜひ一度試してみてください。
アレクサ、レシピ提案して