ElcamyTECH
Articles
Dify

【Difyで作るシリーズ 10】スライドを自動作成する

Tech生成AIDifyDify2025/10/02

はじめに

Dify というサービスを聞いたことがあるけれど、「何ができるかわからない」、「どう使うのかわからない」などの理由で使ったことがない方は多いのではないでしょうか。

そのような方のために、「Dify で何ができるのか?」や Dify を使った活用事例を紹介する記事をシリーズ化していきます。

今回は第10回目で、Gamma APIを使用して、スライドを自動作成するワークフローを作成する方法について紹介します。

メモ

Gamma とは Gammaは、AIを活用してプレゼンテーション資料やドキュメント、Webページなどを自動で生成するクラウドサービスです。従来、資料作成はスライド一枚一枚のデザインやレイアウトを手作業で行う必要がありましたが、Gammaは簡単なテキストでの指示(プロンプト)を与えるだけで、構成の考案から文章の生成、デザインの適用までを自動で行います。

https://gamma.app/ja 主な特徴

  • 簡単な操作: 「AIについて」といったテーマを入力するだけで、AIが最適な構成のアウトラインを提案し、それに沿った内容のスライドを自動で作成します。
  • 高品質なデザイン: 豊富なテンプレートが用意されており、専門的なデザインスキルがなくても、誰でも洗練された見た目の資料を作成できます。
  • 時間の大幅な短縮: アイデア出しから清書までのプロセスをAIがサポートするため、資料作成にかかる時間を劇的に削減します。
注意

今回使用する Gamma API はベータ版であり、以下のような制限があります。

  • レートリミット: 一日あたり最大50回までコンテンツを生成することができます。
  • **破壊的変更のリスク: APIの仕様が大幅に変更され、現在APIを利用しているプログラムが動作しなくなるような「破壊的変更」**が、事前の十分な告知なく行われる可能性があります。
メモ

この記事の対象者

  • Dify という言葉を聞いたことがあるが、何ができるのかがわからない方
  • Dify を業務に取り入れたいと検討している方
メモ

事前準備

  • Dify へのサインアップ
  • OpenAI APIまたはGemini APIのAPIキーの取得
    • Gemini APIの場合
      1. ここにアクセスし、「APIキーを作成」を選択します。
      2. 「新しいプロジェクトでAPIキーを作成」を押します。
      3. APIキーをコピーします。
        • OpenAI APIの場合
        • サインアップした後、こちらからAPIキーを作成し、保存します。
        • APIキーのセットアップ

環境

  • Dify v1.8.0
  • Gamma Proプランに加入している

概要

AIにどのようなスライドを作ってほしいか指示を出す(プロンプトを入力する)ことで、資料を自動生成します。指示の出し方には、簡単なテーマだけを伝える方法と、各ページの内容を細かく指定する方法の2通りがあります。 1. テーマを伝えるだけのシンプル作成 作りたいプレゼンテーションのテーマを短い文章で入力するだけで、AIがそのテーマに沿った構成や内容のスライド一式を自動で生成します。最も手軽な方法です。

入力例
AIを活用した生産性向上術

2. Markdown記法で各ページを細かく指定 各ページの内容をより具体的にコントロールしたい場合は、Markdownに似た記法で指示を出します。 「#」の後ろに各ページのタイトルを、「-」の後ろにそのページに含めたい箇条書きの要素を記述することで、スライドの構成と内容を正確に指定できます。

入力例
# 最後のフロンティア:深海探査
- 海の20%未満しか探索されていない
- 水深1,000メートルを超える領域はいまだに大部分が謎
- 人類は海の最深部よりも宇宙に行った人の方が多い

# 技術的ブレークスルー
- 極限の水圧に耐えられる高度な潜水艇
- 高解像度カメラとサンプリング装置を備えた遠隔操作探査機(ROV)
- 長期的なマッピング任務を行う自律型無人潜水機
- リアルタイムでデータ伝送を可能にする深海通信ネットワーク

# 生態学的発見
- 太陽光なしで繁栄する独自の生態系
- 化学合成を利用する熱水噴出孔の群集
- 生物発光や耐圧性など驚異的な適応を持つ生物
- 毎年数千もの新種が発見されている

完成イメージ

メモ

イメージ

  1. 「topic」スライド作成に必要な情報を入力します。

  2. 右側にスライドのリンクが表示されます。

  3. リンク先のサイトに遷移すると、自動生成されたスライドが表示されます。

    image

    image

今回作成するワークフローの全体図です。

image

作成手順

ここからは、ワークフロー構築の手順について説明します。

手順

  1. ワークフローの新規作成
  2. ワークフロー作成画面上での作業
  3. ワークフローの動作確認

1. ワークフローの新規作成

  1. 最初の画面の「最初から作成」を選択します。

    image

  2. 「ワークフロー」を選択し、「アプリのアイコンと名前」を入力してから「作成する」を選択します。

    image

2. ワークフロー作成画面上での作業

  1. Gamma API を呼び出すための APIキーを「環境変数」に設定します(キーの漏洩防止と安全な管理のため)。
  2. 画面右上にある「ENV」ボタンを押す
  3. +環境変数の追加」ボタンを押す
  4. 環境変数を以下のように設定する
項目
項目
タイプString
変数名gamma_api
Gamma APIキー 取得する方法はこちら

以下の画像のようになっていればOKです。

image

  1. 「開始」ノードを選択した後、「+」ボタンを押し、下記の表のように4つの項目を追加します。
項目
項目
フィールドタイプ段落
変数名user_input
ラベル名topic
最大長1000

image

  1. 入力のタイプを分類するために「IF/ELSE」ノードを作成し、以下の表のように設定します。 これによって、「#」で始まるテキストを各ページを細かく指定したテキストとして判定します。
項目入力
項目入力
IF(で始まる)開始/user_input#

以下の画像のようになっていればOKです。

image 以降、「IF」の分岐での作業を行います。

  1. 「IF/ELSE」ノードの「+」ボタンを押し、「コード実行」ノードを作成します。

    image 入力変数を以下のように設定します。

ラベル名パラメータ
ラベル名パラメータ
input_text開始/user_input

また、「コード」部分は以下のように設定します。Markdown記法で記述されたインプットをGamma APIのプロンプト(inputTextフィールド)の書式に合うように変換しています。

python
import json
 
def convert_markdown(input_text: str) -> str:
    lines = input_text.strip().splitlines()
    sections = []
    buffer = []
 
    for line in lines:
        if line.startswith("#"):
            if buffer:
                sections.append("\n".join(buffer))
                buffer = []
            buffer.append(line)
        elif line.strip().startswith("- "):
            buffer.append(line.replace("- ", "* ", 1))
        else:
            buffer.append(line)
 
    if buffer:
        sections.append("\n".join(buffer))
 
    # セクションごとに \n---\n で結合(実体は“本当の改行”)
    return "\n---\n".join(sections)
 
 
def main(input_text: str):
    # 1) 生の改行を含む文字列
    raw = convert_markdown(input_text)
 
    # 2) HTTP JSON ボディに安全な「エスケープ済み」文字列(\n など)
    escaped_for_json = json.dumps(raw, ensure_ascii=False)[1:-1]
 
    return {
        "result": escaped_for_json  # HTTPリクエストの Body に使う
    }

以下の画像のようになっていればOKです。(わかりやすいようにノード名を「コンテンツ作成(Long_ver)」としています。)

image

  1. 「コンテンツ作成(Long_ver)」ノードの「+」ボタンを押し、「HTTPリクエスト」ノードを作成します。 Gamma APIを使ってスライドの作成をリクエストします。

    image APIの設定で「認証なし」を選択し、以下のように値を設定します。

項目
項目
認証タイプAPIキー
API認証タイプカスタム
ヘッダーX-API-KEY
APIキーgamma_api(環境変数)

image また、「HTTPリクエスト」の設定を以下の表のように設定します。

項目
項目
メソッドPOST
URLhttps://public-api.gamma.app/v0.2/generations
キー(ヘッダー)Content-Type
値(ヘッダー)application/json

image また、「ボディ」には「raw」を選択し、以下のコードを記述します。(「input_text」には「コンテンツ作成/result」を入れます。)

{
  "inputText": "{**ここに「コンテンツ作成/result」を入れる**}",
  "textMode": "generate",
  "format": "presentation",
  "cardSplit": "inputTextBreaks",
  "textOptions": {
    "amount": "medium",
    "language": "ja"
  },
  "imageOptions": {
    "source": "aiGenerated"
  },
  "cardOptions": {
    "dimensions": "16x9"
  },
  "sharingOptions": {
    "externalAccess": "edit"
  }
}

今回は、デフォルトの設定にしていますが、Gamma APIではこのbodyを用いて様々なパラメータが調整できます。

(参考)Gamma APIで調整できる項目
パラメータデータ型必須/任意デフォルト値許容値/フォーマット説明
パラメータデータ型必須/任意デフォルト値許容値/フォーマット説明
inputTextString必須-1~750,000文字コンテンツ生成の基盤となるテキスト。\n---\nでカード分割を制御可能。
textModeEnum任意generategenerate, condense, preserveinputTextの処理方法を定義。preserveはテキストをそのまま維持する。
formatEnum任意presentationpresentation, document, social生成される成果物の種類(プレゼン、ドキュメント等)を決定
themeNameString任意ワークスペースのデフォルト標準またはカスタムテーマ名ビジュアルテーマ(色、フォント)を指定
numCardsInteger任意10Proプラン: 1~50, Ultraプラン: 1~75cardSplitがautoの場合に生成されるカード数
cardSplitEnum任意autoauto, inputTextBreaksコンテンツのカード分割方法inputTextBreaksはinputText内の\n---\nを使用
additionalInstructionsString任意-1~500文字コンテンツやレイアウトに関する追加の指示
exportAsEnum任意-pdf, pptx生成物と同時にPDFまたはPPTXファイルも出力
textOptions.amountEnum任意mediumbrief, medium, detailed, extensiveカードあたりのテキスト量に影響
textOptions.toneString任意-1~500文字テキストのトーンや雰囲気を定義
textOptions.audienceString任意-1~500文字想定される読者層を記述
textOptions.languageString任意en言語コード出力言語を指定
imageOptions.sourceEnum任意aiGeneratedaiGenerated, unsplash, noImages, etc.画像のソースを指定。商用利用可能なオプションも存在
imageOptions.modelString任意-AI画像生成モデル名sourceがaiGeneratedの場合に使用するモデル
imageOptions.styleString任意-1~500文字sourceがaiGeneratedの場合の画像スタイル
cardOptions.dimensionsEnum任意-fluid, 16x9, 4x3 (プレゼン用)カードのアスペクト比を決定。formatに依存
sharingOptions.workspaceAccessEnum任意ワークスペース設定noAccess, view, comment, edit, fullAccessワークスペースメンバーのアクセス権限
sharingOptions.externalAccessEnum任意ワークスペース設定noAccess, view, comment, edit外部ユーザーのアクセス権限

image 次に「ELSE」分岐に移動し、作業を行います。

  1. 「IF/ELSE」ノードの「+」ボタンを押し、「LLM」ノードを作成します。 ユーザのプロンプトをもとにスライドのタイトルを生成します。

    image AIモデルには「gpt-4o-mini」を選択し、「コンテキスト」には「開始/user_input」を選択します。 「SYSTEM」に入力するプロンプトは以下です。

    ユーザはスライド資料の作成を依頼しています。
    ユーザのインプット({{#context#}})をもとにスライドのタイトルを作成して、スライドのタイトルのみを出力してください。
    
    必ずタイトルのみを出力してください。
    

以下の画像のようになっていればOKです。(わかりやすいようにノードの名前を「トピック作成(Short_ver)」にしています。)

image

  1. 「トピック作成(Short_ver)」ノードから「HTTPリクエスト」ノードを作成し、「IF」の分岐と同じように設定しますが「raw」の「ボディ」には以下のように記述します。

    {
      "inputText": "**ここに「トピック作成/text」を入れる**",
      "textMode": "generate",
      "format": "presentation",
      "cardSplit": "auto",
      "textOptions": {
        "amount": "medium",
        "language": "ja"
      },
      "imageOptions": {
        "source": "aiGenerated"
      },
      "cardOptions": {
        "dimensions": "16x9"
      },
      "sharingOptions": {
        "externalAccess": "edit"
      }
    }
    

以下の画像のようになっていれば大丈夫です。

image

  1. 変数集約器」ノードを作成し、「IF/ELSE」の分岐を合流させます。

    image IF・ELSEそれぞれの分岐にある「HTTPリクエスト/body」を変数代入し、集約させます。

    image

  2. 「変数集約器」ノードの「+」ボタンを押し、「コード実行」ノードを作成します。

    image 「入力変数」にはラベル名を「body」に、パラメータを「変数集約器/output」に設定します。スライド作成の識別番号である「generationId」を取得するために、コード部分の記述は以下のようにします。

    python
    import json
     
    def main(body):
     body = json.loads(body)
     
     return {
         "generationId": body.get('generationId')
     }

最後に「出力変数」を「generationId」とします。最終的に以下のような画像に設定できていたらOKです。(わかりやすくするためにノード名を「generationId取得」としています。)

image

  1. generationId取得」ノードの「+」ボタンを押し、「ループ」ノードを作成します。

    :::message

    ループ」ノード 終了条件が達成できるまで、または反復上限回数まで特定のワークフローを繰り返します。 スライド作成のHTTPリクエストを送信してから実際にスライドおよびそのリンク(gammaUrl)が作成されるまでには時間がかかります。所要時間はスライドの量に依存するため、定期的にリクエスト(ポーリング処理)するために「ループ」ノードを追加しています。

    :::

    image 「ループ変数」の「+」ボタンを押し、設定を以下の表のようにします。

項目
項目
ラベル名gammaUrl
データ型String
入力モードConstant
URLhttps://gamma.app/

こちらで設定した「URL」は、ループが終了し正常にスライド作成のリンクが生成された後に、gammaUrlで上書きされます。また、万が一上書きされない場合(ループが最大回数に達するなど)に備えて 「gammaワークスペース」のURLにしています。 以下の画像のようになっていればOKです。

image これ以後は、「ループ」ノード内でワークフローを構築していきます。

  1. 「ループ」ノード内にある「+ブロックを追加」ボタンを押し、「HTTPリクエスト」ノードを作成します。 このノードで、Gamma側でのスライド作成の進捗状況を確認し、実際に作成されたスライドのリンク(gammaUrl)を取得します。

    image APIキーの認証については先ほどと同じように設定し、「メソッド」を「GET」にします。また、リクエストするURLを以下のように設定します。(「generation_Id」の部分では、自身の「コード実行」で取得したIdを入力します。「」は不要です。)

    https://public-api.gamma.app/v0.2/generations/「generation_Id取得/generation_Id(この部分を変数に変更)」
    

    image

  2. 「HTTPリクエスト」ノードで取得した情報から、「進捗状況(status)」と「gammaUrl」を抽出します。「HTTPリクエスト」ノードから「コード実行」ノードを作成し、入力変数を以下のように設定します。

ラベル名パラメータ
ラベル名パラメータ
bodyhttpリクエスト(URL取得)/body

また、コードの「ボディ」部分には以下のように記述します。

python
import json
 
def main(body):
    body = json.loads(body)
 
    return {
        "status": body.get('status'),
        "gammaUrl": body.get('gammaUrl', "")
    }

また、出力変数に「gammaUrl」と「status」を設定します。 以下の画像のようになっていればOKです。(ノード名を「GammaURL取得」に変更)

image

  1. スライド作成が完了しているかどうかを確認するために、「GammaURL取得」ノードから「IF/ELSE」ノードを作成し、分岐を以下のように設定します。
分岐名項目条件
分岐名項目条件
CASE 1IF「GammaUrl取得/status」(である)completed(完了)
CASE 2ELIF「GammaUrl取得/status」(である)pending(作成中)

image

  1. 「IF(CASE 1)」の「+」ボタンを押し「変数代入」ノードを作成します。

    image 変数代入の設定を以下の表のように設定します。

代入する変数操作パラメータ
代入する変数操作パラメータ
ループ/GammaUrl上書きGammaURL取得/gammaUrl

image 最後に「ループ完了」ノードを作成してループを終了します。

  1. 「IF/ELSE」ノードに戻り、「ELIF(CASE 2)」の「+」ボタンを押し、「コード実行」ノードを作成します。(ここで「ELSE」の分岐でないことに注意します。)

    image 「入力変数」は何も設定せず、「コード」部分を以下のように記述します。(ノード名を「10秒待機」に変更)

    python
    import time
     
    def main():
     time.sleep(10)
     return {
         "result": ""
     }

    image ここで分岐は終了し、メインループに戻ります。これでループ内のワークフローは完成したので、「ループ」ノードから「終了」ノードを作成し、「ループ/gammaUrl」を出力します。これでワークフローは完成です。

3. ワークフローの動作確認

実際にワークフローが動作しているか確認します。「公開する」を選択し、「更新を公開」した後、「アプリを実行」を選択します。

image 動作確認では、「スライドのページごとの内容」をインプットにした場合を試していますが、Gammaスライドが作成されたサイトのURLが正常に表示されました。

入力例(再掲)
# 最後のフロンティア:深海探査

- 海の20%未満しか探索されていない
- 水深1,000メートルを超える領域はいまだに大部分が謎
- 人類は海の最深部よりも宇宙に行った人の方が多い

# 技術的ブレークスルー

- 極限の水圧に耐えられる高度な潜水艇
- 高解像度カメラとサンプリング装置を備えた遠隔操作探査機(ROV)
- 長期的なマッピング任務を行う自律型無人潜水機
- リアルタイムでデータ伝送を可能にする深海通信ネットワーク

# 生態学的発見

- 太陽光なしで繁栄する独自の生態系
- 化学合成を利用する熱水噴出孔の群集
- 生物発光や耐圧性など驚異的な適応を持つ生物
- 毎年数千もの新種が発見されている

image また出力されたリンクに飛んでみると、正常にスライドが生成されていることが確認できました。

image 「スライドのテーマ」のみをインプットにした場合も、正常にスライドが生成されていることが確認できました。(テスト実行ではタイムアウトが起きてしまい結果が出力されていませんが、ログを参照すると、正常にスライドが生成されていることが確認できます。)

image

image 出力されたリンク先を参照すると正常にスライドが生成されていることが確認できました。

image

応用

今回はGamma APIに対して基本的なリクエストしか飛ばしていませんが、想定される読者の設定や、スライド出力言語の設定など、より場面にあったスライドを作成することができます。

おわりに

今回は、インプットに合わせてスライドを自動作成するワークフローを作成しました。今後もDifyを利用したアプリの作成手順を紹介していきます。ぜひ引き続きご覧ください。

関連記事

Solution

AIエージェント・Dify構築支援

AIエージェント開発・Dify構築・PoC・社内研修まで
ワンストップで支援。まずはお気軽にご相談ください。

Elcamy

Technology Partners

DifyGoogle Cloud Partner