
1. はじめに:生成AIが変えるEC体験
ECサイトにおいて、商品説明文は「購買意欲を高める最後の一押し」にもなる重要な要素です。しかし、その作成は出店者にとって大きな負担となっています。
とくにCake.jpのようなスイーツ専門モールでは、商品の魅力を伝えることは非常に重要であり、より効果的にアピールする方法を模索している店舗さまも少なくありません。
そんな課題を解決するために、今回私たちは生成AI(Dify API)を活用して、商品説明文の自動生成機能を開発・導入しました。
本記事では、その実装背景から技術構成、プロンプト設計、そして今後の展望までを余すことなくご紹介します。
2. プロジェクト背景:手間と表現力の壁を越えるために
Cake.jpでは、出店者が自ら商品情報を入力する「店舗向け管理画面」を提供しています。
しかし、その中でとくに負担になっていたのが「商品説明文の入力」。
- 商品自体は素晴らしいのに、うまく言語化できない…
- 毎回説明文を考えるのが面倒…
- 他商品との差別化がうまくできない…
- 普段の業務に追われ、時間がなくて書けない...
こうした課題を感じていたため、「少ない労力で最大限に商品の魅力を伝える仕組み」の必要性が明確でした。
3. なぜDifyを選んだのか?
もともと社内では他業務でもDifyを利用しており、以下の理由から導入はスムーズでした
- ドキュメントが充実しており、学習コストが低い
- ホスティング不要ですぐに試せる
- Flowベースで簡単にプロンプト設計できる
- 他のLangChain系などと比べ、とにかく導入が早い!
PoC的に試すには最適な選択肢でした。
1時間で Dify APIを使ったプロトタイプを作成
バックエンド側での技術検証のために、まずはDifyのAPIを叩くプロトタイプを作成しました。
これはVS Code と Copilot を使い、1時間足らずで動くところまで作成できました。

スクリーンショットの右側カラムのUI部分について、実装者は一切コードを書いていません。
js部分もすべてAIエージェントに丸投げです。
実際のプロンプト
次のcontrollerを作ってください。CakePHP1.3 PHP8.3です。
必要であれば、フロントのctpやjsもお願いします。
DifyのAPIを使ったテキスト生成機能です。
ジャンルやシーンといった情報をPHPから渡し、テキストを生成します。
フロントはjsでcontrollerのエンドポイントをAjaxでたたきます。
ページには下記のフォームが必要です。
- ジャンル(genre)
- シーン(scene)
- キーワード(keyword)
- トーン(tone)
コントローラーの名前はDifyに依存しないでください。別のAPIに変わる可能性もあります。
Difyのエンドポイント
@https://api.dify.ai/v1/chat-messages
このあと何度か修正指示を出してはいます。
4. 実装:CakePHP での生成AIの現場活用
プロトタイプにより実際のシステムでも使えるイメージがついたので、本番用に組み込むこととなりました。
🔌 全体構成の概要
Cake.jpはCakePHPフレームワークを中心に構築されており、店舗さま向け管理画面にて、商品情報を登録・編集できるUIを提供しています。
生成AIによる商品説明文生成機能は、以下のような構成で実現しています。

APIにはCurlでこんな感じでリクエストしています。
...
// リクエストデータ
$postData = [
'inputs' => [
'genre' => $params->genre, // 👈ジャンル(カテゴリ)
'scene' => $params->scene, // 👈シーン
'keyword' => $params->keyword, // 👈キーワード
'tone' => $params->tone // 👈トーン
],
'query' => $prompt,
'response_mode' => 'blocking',
'user' => $params->user, // 👈店舗さまを識別するID
];
$httpRequest = $this->httpClient;
try {
$httpRequest->init($this->config->apiUrl);
$httpRequest->setOption(CURLOPT_POST, true);
$httpRequest->setOption(CURLOPT_POSTFIELDS, json_encode($postData));
$httpRequest->setOption(CURLOPT_RETURNTRANSFER, true);
$httpRequest->setOption(CURLOPT_TIMEOUT, $this->config->timeout);
$httpRequest->setOption(CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->config->apiKey,
'Content-Type: application/json',
]);
$response = $httpRequest->execute();
$httpCode = $httpRequest->responseCode();
$curlError = $httpRequest->errorString();
...
userというパラメータに店舗さまの識別情報を渡すことで、店舗ごとにどのくらいご利用いただいているかをDifyのコンソールで見られるようにしています。

Dify側のフロー
Dify側のアプリのフローはいたって単純です。

- 送信されてきた
inputs内のパラメータをstringの変数として受け取り、
- LLMブロック(ノード)にてプロンプトに埋め込みリクエスト
- 生成されたものをJson文字列で返す
🧾 Structured outputs(構造化出力)の活用
今回の説明文の生成では、構造化出力(Structured outputs) 機能を活用しています。
Structured Outputs とは、その名の通り「構造化された出力」です。
簡単に言うと、LLMが返す結果を必ずjsonフォーマットで返す ようにできるということです。
LLMは、その仕組み上、出力が完了するまで何が返ってくるか予測できないという特性があります。そのため、従来は決まった形式での結果を確実に受け取ることが困難でした。
たとえば、
「必ずjson形式で回答してください。それ以外の回答はしなくてよいです」
といったプロンプトで、強目に出力形式をお願いしたり、JSONモードを使ったりして、jsonのフォーマットで返ってくることを願うしかありませんでした。
しかし、OpenAIが開発したこのStructured outputsの仕組みを使えば、指定したJSON Schemaに完全準拠した形で返してくれます。
(Claude や Gemini など他社のLLMでも同様のJsonスキーマ準拠のアウトプットの仕組みや概念はあるようです)
参考)https://platform.openai.com/docs/guides/structured-outputs?api-mode=responses

☝️Difyでは構造化出力の機能のON/OFFスイッチがある
Dify APIのレスポンス自体は元々JSONで返ってくるのですが、LLMが生成したテキスト結果は、textというプロパティに文字列で埋め込まれます。
この部分をJSON文字列にするために、構造化出力機能を使っています。
モデルによって違う、構造化出力を【 使える / 使えない】
構造化出力は、すべてのモデルで使えるわけではありません。
- gpt-4o / gpt-4o-mini は構造化出力に正式対応
- gpt-3.5-turbo などは未対応(Dify側でプロンプトにてjson出力指示を加えるフォールバックがあるそう)
Cake.jpでは、将来的には商品説明文だけでなく、タイトルやその他複数の要素を一括生成するニーズがあるため、構造化出力は重要な技術基盤になります。
🤖 gpt-4o-mini のモデルを採用した理由
私たちは「魅力的で高精度な出力をレスポンス早く」を求めて、開発初期は gpt-4o を用いてプロトタイプを作成していました。
しかし、商用運用を見据えると実行コストが懸念事項となってきました。
💰 モデルごとのDifyでのクレジットコスト
| モデル名 |
1リクエストあたりのクレジット |
| gpt-3.5-turbo |
1クレジット |
| gpt-4o-mini |
1クレジット |
| gpt-4.1-mini |
1クレジット |
| o3-mini / o4-mini |
5クレジット |
| gpt-4.1 |
5クレジット |
| gpt-4o |
10クレジット |
| gpt-4 |
20クレジット |
gpt-4o-mini は gpt-4o のわずか1/10のコストなので、十分に使える品質さえ得られれば採用したいと思い、検証することにしました。
Dify プロプランの上限
現在契約中のプロプランでは、1ヶ月あたり5000メッセージクレジットが上限となります。
つまり、10クレジット消費するgpt-4oでは、1ヶ月に500メッセージしか送れません。
さらに、開発検証で既に多くのクレジットを消費してしまい、当月の残りは1000メッセージクレジットとなっていました笑
もちろん、オーバーした場合はLLMの外部APIキーを設定していれば上限を超えることは可能です。
しかし、このアプリ以外でもDifyを利用しているため、一旦5000メッセージクレジットの範囲内で収めることを目標としました。
結果的に 「そこそこ良い品質が、レスポンスよく、かつ安価で得られる」 と判断し、本番環境でも1クレジット消費の gpt-4o-mini を採用しました。
🧠 今後の構想:LLMを役割分担させる
現在は1つのLLMブロックのみですが、さらに出力の精度や品質を上げるために、LLMブロックを2つ繋げる構成も検討中です。
- 初稿作成用 LLMブロック
- 評価・修正・校正用 LLMブロック
どちらのブロックも1クレジットコストのLLMですが、役割を変えて2つ、ないしは複数を繋げることでより良い出力を得られることが予想されます。
【10クレジットの高レベルLLM1回】より、【1クレジットの下位レベルLLM x 2】 の方が高品質になる可能性もあるからです。
これはAIエージェントのデザインパターン「Agentic Design Patterns」でも語られる Reflection(自己改善) の実装にも通じる発想ですね。
参考)「Agentic Design Patterns」
https://zenn.dev/loglass/articles/b9ee37737deb85
5. ウィザード式モーダルUIと生成AIならではのUX
UIはモーダル形式のウィザードで構成し、以下の情報を店舗さまに順々に選択してもらうことにしました。
- 商品ジャンル カテゴリ(例:チーズケーキ、クッキー)
- 利用シーン(例:誕生日、クリスマス、ギフト)
- 商品に関わるキーワード(例:手作り、無添加、さくさく)
- 文章のトーン(例:高級感、カジュアル、お祝い感)

1画面1イシューでユーザーの認知負荷を下げるUX
Cake.jpでは現在、店舗さまがご利用になる管理画面のUX改善のために、UIリニューアルプロジェクトが進行中です。
商品情報を入れてもらう際に1画面1イシューとするウィザード形式のUIを採用しました。
その理由は次のとおりです。
認知負荷を下げる
余計な選択肢を減らし、目の前のタスクだけに集中してもらうためです。
どれを選べば良いか?なにをすべきか?などの迷いを取り除くことができます。
意図の明確化
画面をシンプルにすることで、ユーザーが何のために行なっているかに集中でき、よりよい判断を引き出すことができます。
操作の正確性とスピード
結果として操作ミスが減り、完了までのスピードも上がります。
こうして、モーダル内で次々と段階的に商品に関する情報を選択してもらい、DifyのAPIに送信します。
AIによって生成された説明文が、最後の画面のテキストエリアに表示されます。
ユーザーはその結果を見て自ら編集するのはもちろん、トーン変更や文章の長さ調整を再びAIにリクエストして再生成することもできます。
納得いく文章ができたら「決定」ボタンで、商品登録フォームに上書き反映される仕組みです。
生成AIならではの待ち時間のUX
今回はストリーミングでの受信ではなく、すべての結果が生成されてから画面に反映する仕様にしたので、生成中は何も変化がない待ち時間が発生してしまいました。
(Difyではresponse_mode = 'blocking' というモード)
応答時間はモデルやプロンプトによってかなり差異が出るのですが、今回私たちが設定した環境では10秒〜20秒ほどかかることが分かりました。
AI生成時代のお気軽【思考アニメーション】
体感的にも少し長めに待たされるので、一般的にローディングでよく使われるクルクル回るスピナーのみでは荷が重いと感じました笑
そこで、3点リーダー点滅アニメーション を追加で採用しました。

☝️「AIがテキスト生成中」のあとにつづく ... がひとつひとつ点滅アニメーションします。
これには次のような利点があります。
- デザインする必要がない
- 画像や素材を用意しなくてよい
- 表示エリアも最小限で済む
- なにか思考している雰囲気を出せる
ミニマムで扱いやすいので、多くのAIアプリ系で採用されていますね。
とくに良い点は、いまの時代ではAIにアニメーションの生成を頼むとすぐにjsを実装してくれるところですね笑
タイプライティングの演出で生成感を出す
また、生成された文章をテキストフィールドに表示する際に、タイプライティングしているかのように1文字ずつ出現するアニメーションも実装しました。
ストリーミングモードでは当たり前の動作であったりしますが、今回の仕様ではレスポンスがあった時点で文章の全てがすでに存在しているので、本来は不要なはずの演出です。
しかし、生成AIが文章をひとつひとつ紡ぎ出している雰囲気に見せることで、体感的に結果に対する付加価値を高めることができます。
こちらのアニメーションもまた、AIによって一瞬で実装することができました。
6. プロンプト設計のこだわり
Difyに渡すプロンプトは、単なる「自由文生成」ではなく、明確なルール・制約の元で自然な日本語文章を生成する設計にこだわりました。
- 文章執筆のプロであるロールを与える
- 750〜800文字に収める
- 記号(!・☆など)は使わず、句読点のみ
- トーン別の文体テンプレートを分岐して設定
- アレルゲン情報がある場合は必ず明記
- 文章に自然さと訴求力を持たせること
これにより、生成内容の品質と安定性を確保しています。
プロンプト例
あなたはスイーツ専門EC「cake.jp」に出店する店舗の代わりに、商品ページに掲載される見出し付きの商品説明文を執筆するプロフェッショナルです。
出店者が入力した商品情報と希望するトーンに応じて、商品の魅力を最大限に伝える文章を構成してください。
以下のルールに従い、**750文字以上800文字以内の日本語文章**を作成してください。
※本文のみを出力してください。見出しや注釈、説明文以外の返答は不要です。
---
【出力ルール】
以下の条件をすべて厳守してください:
■商品説明文
- 全体で**750文字以上800文字以内**にしてください
- 範囲外の文字数になった場合は、自動的に修正して再出力してください
- 訴求力があり、読みやすさを意識した構成にしてください
- 誤解を招く表現、過度な誇張、事実と異なる内容は避けてください
- トーンに合わせた文体・語彙を使用し、自然な文章として構成してください
- 記号(!・☆・→など)は使用せず、句読点のみで整えてください
- アレルゲン情報が指定されている場合は、必ず文末または自然な位置に「〇〇を含みます。アレルギーをお持ちの方はご注意ください。」などの注意文を丁寧に記載してください
---
【トーン別ルール】
指定される `トーン` に応じて、以下のような雰囲気・文体で構成してください:
- **丁寧・やさしい**
やわらかく親しみやすい語調。全世代に安心感を与えるトーン。
- **お祝い感を出す**
ポジティブで明るい語彙を中心に、贈り物やイベント用途にふさわしい華やかな印象を与える文体。
- **高級感・上質**
格式ある言葉選びと落ち着いた構成。製法・素材・余韻など「こだわり」を重視する語り口。
- **カジュアル・親しみやすい**
やや口語寄りで軽快な文体。日常に寄り添う表現を使い、ラフすぎない自然な文章に。
- **子ども向け・かわいい**
やさしく楽しい語感。見た目や遊び心を引き出す表現。短めのセンテンスでリズミカルに。
- **明るい雰囲気にする**
パッと気持ちが上がるような色・味・シーン表現を中心に構成。ワクワク感を演出する。
- **職人のこだわりを伝える**
製法・素材・時間へのこだわりや、手仕事の丁寧さに焦点をあて、説得力ある語りに。
---
【出力形式】
*本文のみを出力してください。見出し・注釈は不要です。*
-----
本文の結果の最初に【開発用】とプレフィクスを必ずつけてください
Difyのエンドポイントも本番用と開発用で分けたので、それらをサクッと識別するために、開発用には生成結果にプレフィクスを付け足すようにプロンプトで指示しています。
つづいて、ユーザープロンプト
【入力情報】
- 商品カテゴリ:{{#genre#}}
- シーン:{{#scene#}}
- キーワード{{#keyword#}}
- トーン:{{#tone#}}
【追加のお願いプロンプト】
- {{#sys.query#}}
※本記事用に実際のプロンプトから少し修正しています。
今回はチャットのように対話して生成する想定ではなかったのもあり、システムプロンプトとユーザープロンプトをどう明確に分けるべきかは、あまり検証しきれていないです。
あと当たり前ですが、プロンプトの質によって出力される結果の質も変わりました。
エンジニアが最初にテスト的に書いたプロンプトより、現在のプロンプトの方が明らかに出力される文章の質が良くなったことを実感できました。
「AIの性能は使う人間の能力値によって大きく変わる」とはまさにこのことだなと感じました。
7. 社内の反応と今後の効果に期待
この機能はリリースされたばかりのため、店舗さまからの反応はこれからですが、社内では非常に良い反響がありました。
「おおお!」
「なんかすごいAIっぽい!」
「説明文で悩んでた店舗さん、絶対助かるよね」
など、普段の改善タスクリリースとはひと味違った、生成AIならではの“見えるインパクト“ が ありました。
8. 苦労した点:プロンプトとUXの奥深さ
デモ作成は1時間で完了するほど手軽だった一方で…
安定出力のためのプロンプト調整には非常に時間がかかりました
モデル・トーン・応答速度・料金のバランス取りが難しく、最適解探しは沼です。どこまで追求してもこれが最高だというゴールには辿り着きません笑
これはAIに限った話ではありませんよね。
加えて、「ロード中の演出」など、生成AI特有のUX設計にも苦労
瞬時に結果が返されない、変に期待値が上がる、など生成AI特有のユーザー体験を、既存のサービスに馴染ませるのは、実装そのものより難しい課題だと改めて感じました。
どんな結果が返ってくるかをユーザーに想像できるようにしないと使用してもらえないし、
その想像を超える結果を返せるかということもまた重要であったりします。
9. 今後の展望:商品説明だけにとどまらない可能性
今回は「商品説明文生成」のみの機能でしたが、以下のような領域へも今後展開予定です:
- 商品写真の見せ方支援
- 売上分析 × AIによる改善提案
- SNS用テキスト生成
- レビューやFAQの自動補完
- 広告コピーやバナー文の自動生成
「少ない労力で最大限に伝える」ことができれば、店舗さまにもお客さまにも、また私たちプラットフォーム側にも大きな価値があると確信しています。
10. まとめ
Dify APIを活用することで、既存のEC管理画面に最小限の工数で生成AIの価値を取り込むことができました。
「AIだからできること」ではなく、「AIによって本来やりたかったことが楽に実現できる」——そんな未来がすでに始まっています。
今後もCake.jpでは店舗さまと一緒に、購入していただくお客様に“ハッピー”をお届けすべく、AIも活用してさらに加速していく予定です。