レシピ動画サービス「クラシル」におけるAWS Bedrock活用事例
こんにちは。バックエンドエンジニアの松嶋です。
昨今、AIの進化のスピードが凄まじく、この波についていけているのか不安に感じている今日この頃です。
普段はバックエンド開発とSREを兼務していますが、個人的にはDevinを頻繁に活用しています。これにより、トイルのような面倒で反復的な運用タスクを任せられるようになり、大きな恩恵を受けていると実感しています。
ところで弊社では、昨年からAWS Bedrockを本格的に導入・運用しているのですが、今年のAWS Summit 2025で 「AWS で生成 AI アプリケーションを構築する時に役立つサービスと組み立て方を学ぼう」 というセッションの活用事例として取り上げていただきました!(やったね)
この記事では、上記のセッションで紹介された内容に加えて、弊社がAWS Bedrockをどのように活用し、プロダクトの改善につなげているのかについて詳しく紹介します。
AWS Bedrockを導入するに至った背景
弊社では、「クラシル」というレシピ動画サービスを運営しており、サービスローンチから10年目に突入しました。クラシルは弊社の中で最も歴史が長く、最も有名なプロダクトです。
当初は栄養管理士監修の公式レシピ動画で「きちんとおいしく作れる」体験をユーザーに届けてきましたが、2022年のブランドリニューアルをきっかけに、レシピ投稿機能を開放し、一般ユーザーもレシピを投稿できるようになりました。
コンテンツ数の増加によりユーザーの多様な食の好みや要望に応えられるようになった反面、「品質管理」と「データ構造」という2つの大きな課題が浮き彫りになりました。
これまでは社内の厳密なレシピチェックフローを経てコンテンツが公開されていたため、一定以上の品質が保たれていました。しかし、料理をする上で情報が不十分なものやレシピとはいえないものが投稿されることも少なからず発生しており、従来より品質管理が困難になっていました。
また、レシピ投稿機能はフォーマットの制約がなく、ユーザーが各々のスタイルで投稿できるようになっていたため、公式レシピのように構造化されずテキストデータとして保存されていました。その結果、レシピの特徴を把握しづらいという課題も生じました。
これらの課題は主に公式レシピとUGCレシピの差によるものですが、実は公式レシピ自体にも構造化が不十分なデータが存在し、本来ユーザーにとって有益な情報をプロダクトに反映しきれていないという課題も以前から抱えています。
これらの課題を解決するため、昨年からAWS Bedrock(Anthropic社のClaude Sonnetモデル)を用いて私たちが保有するレシピコンテンツを分析し、非構造化データを構造化していく仕組みづくりを開始しました。
また、他のLLMではなく、AWS Bedrock(Anthropic社のClaude Sonnetモデル)を採用したのは、以下の3点が主な理由です。(※2024年3月時点での比較検証結果に基づいています。)[1]
- コスト・精度・パフォーマンスの観点で比較検証した結果、私たちの要件を最も満たしていたこと
- Bedrockを介してinvoke model APIを実行できるため、AWSのIAMによる細かな権限管理が可能であること
- マルチリージョンでリクエストを分散して可用性を担保でき、AWS SDKに組み込まれている自動リトライ機構を利用することで、自前での実装や外部ライブラリの導入が不要となり、可用性を維持しながら素早く開発できること
AWS Bedrock活用事例
1. ユーザー投稿レシピのレシピ判定処理・レシピの構造化
はじめに、AWS Summitでも取り上げていただいた事例について紹介します。UGCレシピの判定およびデータ構造化の仕組みは、2段階のプロセスで構成されています。
まず、ユーザーがクラシルアプリからレシピを投稿すると、データベースへの登録と同時に、その投稿が弊社のレシピの基準を満たしているかを判定する非同期処理が呼び出されます。レシピと判定された場合、その投稿にレシピフラグが付与されます。なお、クラシルの非同期処理は、Rails上でActive Job + SQS + shoryukenを使用して実装しています。
次に、レシピと判定されたコンテンツは、定期的に実行されるバッチ処理によって構造化データに変換されます。以下は、生成された構造化データの一例です。
{
"first_comments": ["病みつきになるおつまみ麻薬卵!", "とろ〜り半熟卵を薬味たっぷり醤油ベースの甘辛タレに漬け込むだけ♪", "ごはんがめっちゃ進みます😋🍚🥢"],
"servings": "卵6個分",
"cooking_time": nil,
"ingredients":
[{"name": "卵", "quantity": "6個"},
{"name": "長ねぎの白い部分", "quantity": "12cm"},
{"name": "長ねぎの青い部分", "quantity": "6cm"},
{"name": "にんにくチューブ", "quantity": "1cm"},
{"name": "白いりごま", "quantity": "大さじ1.5"},
{"name": "醤油", "quantity": "100ml"},
{"name": "水", "quantity": "100ml"},
{"name": "三温糖", "quantity": "大さじ3"},
{"name": "鷹の爪", "quantity": "2本(※お好みで1本 or 1/2本でも)"}],
"steps":
["① 半熟ゆで卵を作る♪ 沸騰したお湯に卵をそっと入れて6分20秒茹でる。冷水にとり、殻をむく。(水の中でむくと綺麗にむけます)",
"② 長ねぎをみじん切りにする。卵が6個入る大きさの容器に、長ねぎ、白いりごま、にんにくチューブ、醤油、水、三温糖を入れてかき混ぜる。砂糖をよく溶かす。",
"③ 種を除いた鷹の爪をキッチンバサミで輪切りにして加える。加える量はお好みの辛さで♪",
"④ ゆで卵を加えて、卵がひたひたになるくらいがベスト。少し顔が出るならばラップを被せておく。容器に蓋をして、冷蔵庫で一晩漬ける。",
"あったかごはんにのせていただきます♪ タレも一緒にかけながら😋"],
"other_comments": ["半熟卵の茹で時間は6分20秒〜30秒が個人的にベストなとろとろ加減になる具合でした✨ 殻もむきやすく扱いやすい柔らかさです♪", "お砂糖はよくかき混ぜて溶かしてください🥄"],
"hashtags": ["#おつまみレシピ", "#麻薬卵", "#ごはんのお供", "#簡単れしぴ"]
}
生成された構造化データを用いて、レシピページのUIをアップデートした結果がこちらです。
このようにレシピデータを構造化することは、UI/UXの改善に繋がるだけでなく、検索エンジンのクローラーがページコンテンツを正確に理解する手助けにもなります。
また、生成された構造化データは、Google検索用の構造化データとしても活用できるため、ページ内部に埋め込むことでリッチリザルトに表示されやすくなり、ユーザー流入の増加が期待できます。[2]
さらに、レシピフラグを付与したことによって、レシピではないページを検索エンジンのインデックス対象から除外できるようになりました。
実際に、これらの改善により1コンテンツあたりの自然流入効率が290%向上し、ユーザーの滞在時間も有意に増加するという結果が得られました。
2. 公式レシピのユーザーの質問の活用
クラシルの公式レシピには、ユーザーからの質問が数多く投稿されています。これらの質問への回答は、弊社の管理栄養士による裏付けがなされており、材料の代用・省略方法や調理のコツ・ポイントなどが記載されています。これらはレシピを選択したり調理したりする際に非常に有益な情報となっています。
しかし、これらの情報はページ下部に折りたたまれており、ページを訪れたユーザーの目に留まりにくい場所に配置されているため、せっかくの有益な情報を効果的に提供できていないのではないかと私たちは考えました。
この課題を解決するために、膨大なユーザーの質問データを分析し、レシピ選択や調理過程でのユーザーの意思決定をサポートする重要な質問を集約し、それらの質問を関連する材料や調理工程に紐づけるバッチ処理を実装しました。
レシピ情報、ユーザーの質問と管理栄養士の回答をプロンプトに入力して解析することで、以下のような構造化データを生成できます。
[
{
"id": 1,
"question": "上白糖は他の種類の砂糖で代用できますか?",
"answer": "上白糖の代わりにグラニュー糖や三温糖、きび砂糖などご家庭にある砂糖を使用してお作りいただけます。",
"category": "代用",
"ingredient_id": 12,
"step_id": nil,
"reason": "この質問は砂糖(材料ID 12)の代用に関するものです。"
}
{
"id": 2,
"question": "レモン汁は省いても作れますか?",
"answer": "レモン汁は省いてもお作りいただけます。加えることでさわやかな酸味が加わり一層おいしく仕上がりますので、ご用意のある際はぜひ加えてお作りください。",
"category": "省略",
"ingredient_id": 222,
"step_id": nil,
"reason": "この質問はレモン汁(材料ID 222)の省略に関するものです。"
},
{
"id": 3,
"question": "表面が割れてしまいます",
"answer": "表面が割れてしまった原因として、「生地を勢いよく混ぜ合わせたことにより空気が入ってしまった」「生地の急激な温度変化」などが考えられます。生地を混ぜる際は空気が入り込まないようにゆっくりと混ぜ合わせることがポイントです。また、使用する食材は常温に戻しておき、焼いている最中は必要以上にオーブンを開け閉めしないようお気をつけください。焼き立ては表面に割れ目が入ることがありますが、粗熱が取れると表面が落ち着いてきます。",
"category": "コツ・ポイント",
"ingredient_id": nil,
"step_id": 123,
"reason": "この質問は焼成過程(手順ID 123)に関連するコツやポイントを説明しています。"
}
]
上記のように、材料と手順によくある質問を紐づけることで、ユーザーはレシピ選択時に代用・省略可能な食材を確認したり、調理中に各手順のコツやポイントを参照しながら料理を進められるようになりました。これにより、ユーザーがより安心して料理を楽しめるUIを実現することができました。
テキストの文言は管理サイト上で編集したり、公開・非公開を切り替えたりできるため、柔軟な運用が可能です。
また、この機能をリリースしてからユーザー行動への影響を分析したところ、想定以上の効果があり、レシピページ内でクリック率Top3に入るなど、高いエンゲージメントを示す機能として定着しました。
3. たべれぽのAI要約機能
最後に、たべれぽの要約機能について紹介したいと思います。クラシルの公式レシピ・UGCレシピには、「たべれぽ」と呼ばれるレシピを作ったユーザーのレビューを投稿できる機能があります。特に公式レシピには約10年分のたべれぽが蓄積されており、人気レシピには約2500件もの投稿があります。
これらのたべれぽには、ユーザーのアレンジ方法や、失敗したポイント、美味しく作るコツなど、他のユーザーにとって参考になる情報が多く含まれています。しかし、レシピを選択したり調理したりする際に、1つ1つレビューを確認することは現実的ではありません。そこで、手軽に要点や調理のコツを把握できる仕組みが必要だと考えました。
この課題を解決するため、私たちのガイドラインに沿って料理のポイントが伝わる要約を生成する仕組みを実装しました。ユーザーにとって参考になる高品質な要約を生成するため、解析対象とするたべれぽにはいくつかの条件を設けています。まず、レシピあたりの投稿数と文字数が一定以上であること、その上で「参考になった」のリアクション数が多い上位100件を解析対象としました。
たべれぽのAI要約機能をリリースした結果、レシピを作る上でのポイントや魅力が伝わりやすくなり、レシピページにおけるユーザーの滞在時間に有意な増加が見られました。
さらに、レシピ動画の再生率も増加傾向にあり、要約によるネガティブな影響はほとんど見られませんでした。むしろ、完成後の料理のイメージがより具体的に伝わるようになったことで、レシピ選びの後押しになっていると考えています。
まとめ
今回は、AWS Bedrockの活用事例から代表的な3つを紹介しました。紹介した事例以外にも、レシピのジャンルやカテゴリの自動付与によるレシピ制作の運用負荷削減など、弊社ではさまざまな場面でAWS Bedrockを活用しています。
いずれも複雑なエージェント処理ではなく、シンプルな推論タスクの組み合わせではありますが、社内に蓄積された非構造データを構造化し、ユーザー体験やプロダクト改善につなげていくための基盤を整えるという意味で、非常に有効なアプローチだと感じています。
これからもクラシルが大切にしている「きちんとおいしく作れる」体験をユーザーに提供し続けるために、AIを効果的に活用しながら、プロダクトの改善に取り組んでいきます。
-
現在は、Claude Sonnet3とClaude Sonnet3.5を併用しています。 ↩︎
-
https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data?hl=ja ↩︎
Discussion