13-3. 例3:審査判定ワークフロー(DSLインポート)

最後に、第12章の手順を使って、生成AIにDSLファイルを書かせてアプリを作ります。題材は「申請内容の形式チェックと判定案の作成」です。申請の文章を受け取り、まず形式チェック(内容が空でないか)を行い、次にAIが必要項目のそろい具合から判定案と理由を作って返します。

判定は あくまで案 です。受付の可否など最終的な判断は、必ず職員が行います。この前提はワークフローの指示文にも書き込みます。

作る流れは次のとおりです。例2より一歩進んで、条件による分岐(IF/ELSE)が入ります。IF/ELSEノードの役割と条件の考え方は第6章6-1、設定項目の詳細は第10章10-3のとおりです。

順番 ノード 何をするか
1 開始(ユーザー入力) 申請の内容(文章)を受け取る
2 IF/ELSE(形式チェック) 申請の内容が空なら不備の経路へ、書かれていれば判定の経路へ分ける
3a テンプレート(不備の経路) 不備を知らせる決まった文章を作る
3b LLM(判定の経路) 必要項目(申請者名・連絡先・事業の内容・金額)のそろい具合を確認し、判定案と理由を書く
4 出力(各経路の末尾) 結果の文章を返す

前提(必要なもの)

手順1:依頼文を用意して生成AIにDSLファイルを書かせる

第12章12-2の依頼文の型(①アプリの種類 ②処理の流れ ③各ノードの設定 ④手動でつなぐものの明示)に沿って、次のように依頼します。

Difyにインポートできる DSLファイル(YAML形式)を作ってください。

- アプリの種類:ワークフロー
- アプリ名:申請内容の形式チェックと判定案
- 処理の流れ:
  1. ユーザー入力ノードで、申請の内容の文章を受け取る
  2. IF/ELSEノードで、申請の内容が空かどうかを判定する
  3. 空の場合:テンプレートノードで「申請の内容が入力されていません。
     内容を記入して再度実行してください。」という文章を作り、
     出力ノードで返す
  4. 空でない場合:LLMノードで判定案を作り、出力ノードで返す
- 各ノードの設定:
  - LLMノードへの指示文は「あなたは申請書類の受付を担当する事務職員です。
    入力された申請の内容に、申請者名・連絡先・事業の内容・金額の
    4項目が書かれているかを確認してください。すべて書かれていれば
    『判定案:受付可』、不足があれば『判定案:要確認』とし、続けて
    理由と不足している項目を箇条書きで書いてください。申請の内容に
    書かれていないことは書かないでください。この判定は案であり、
    最終判断は職員が行います。」とする
  - 応答は日本語とする
- 注意:
  - 使うAIモデルの指定は仮でよい(取り込んだ後にこちらで選び直します)
  - 回答はYAMLのコードブロック1つで、全文を省略せずに出力してください

完了状態:生成AIの回答に、YAMLのコードブロックが1つ含まれている。

手順2:YAMLを保存する

回答のコードブロックからYAMLを取り出し、.ymlファイル(例:shinsa.yml)として保存します。取り出し方・保存のしかたは第12章12-2「回答からYAMLを取り出してファイルに保存する」のとおりです。

完了状態:拡張子が .yml のファイルが手元に保存されている。

掲載DSLファイル(例)

参考として、この依頼で作らせるDSLファイルの例を載せます。生成AIの回答がうまく得られない場合は、次の内容をそのままコピーして .yml ファイルとして保存し、手順3に進んでも構いません。

なお、DSLファイルの中の項目名・ノードの種類名などの書き方は、Difyのバージョンにより異なることがあります。この例が取り込めるかどうかは、お使いの環境での取り込み結果を確認してください。インポートできない場合は、第12章12-2の依頼文の型で生成AIに作り直させてください(エラーの文言とYAML全文を貼って修正を依頼する方法は第12章12-3のとおりです)。

app:
  name: 申請内容の形式チェックと判定案
  mode: workflow
  description: 申請の内容を受け取り、形式チェックのうえでAIが判定案と理由を返すワークフロー。判定は案であり、最終判断は職員が行う。
  icon: app
  icon_background: '#FFFFFF'
kind: app
version: 0.1.5
workflow:
  environment_variables: []
  conversation_variables: []
  features: {}
  graph:
    edges:
      - id: edge-start-check
        source: start-node
        target: check-node
        sourceHandle: source
        targetHandle: target
      - id: edge-check-true-template
        source: check-node
        target: template-error
        sourceHandle: 'true'
        targetHandle: target
      - id: edge-template-end
        source: template-error
        target: end-error
        sourceHandle: source
        targetHandle: target
      - id: edge-check-false-llm
        source: check-node
        target: llm-judge
        sourceHandle: 'false'
        targetHandle: target
      - id: edge-llm-end
        source: llm-judge
        target: end-result
        sourceHandle: source
        targetHandle: target
    nodes:
      - id: start-node
        position:
          x: 50
          y: 250
        data:
          type: start
          title: 開始
          variables:
            - variable: application_text
              label: 申請の内容
              type: paragraph
              required: false
              max_length: 4000
      - id: check-node
        position:
          x: 350
          y: 250
        data:
          type: if-else
          title: 形式チェック
          logical_operator: and
          conditions:
            - id: cond-empty
              variable_selector:
                - start-node
                - application_text
              comparison_operator: empty
              value: ''
      - id: template-error
        position:
          x: 650
          y: 100
        data:
          type: template-transform
          title: 不備の文章
          template: 申請の内容が入力されていません。内容を記入して再度実行してください。
          variables: []
      - id: end-error
        position:
          x: 950
          y: 100
        data:
          type: end
          title: 出力(不備)
          outputs:
            - variable: result
              value_selector:
                - template-error
                - output
      - id: llm-judge
        position:
          x: 650
          y: 400
        data:
          type: llm
          title: 判定案の作成
          model:
            provider: openai
            name: gpt-4o
            mode: chat
            completion_params:
              temperature: 0.2
          prompt_template:
            - role: system
              text: |
                あなたは申請書類の受付を担当する事務職員です。
                入力された申請の内容に、申請者名・連絡先・事業の内容・金額の
                4項目が書かれているかを確認してください。
                すべて書かれていれば「判定案:受付可」、不足があれば
                「判定案:要確認」とし、続けて理由と不足している項目を
                箇条書きで書いてください。
                申請の内容に書かれていないことは書かないでください。
                この判定は案であり、最終判断は職員が行います。
                応答は日本語で書いてください。
            - role: user
              text: '{{#start-node.application_text#}}'
          context:
            enabled: false
            variable_selector: []
      - id: end-result
        position:
          x: 950
          y: 400
        data:
          type: end
          title: 出力(判定案)
          outputs:
            - variable: result
              value_selector:
                - llm-judge
                - text

このファイルには、APIキーなどの秘密の情報や、資料(ナレッジ)の中身は含まれていません(第12章12-1)。AIモデルの指定(この例では仮の指定)は、取り込んだ後に手順4で選び直します。

手順3:インポートする

  1. スタジオの左上の「アプリを作成する」の「DSLファイルをインポート」ボタンを押します(第12章12-3)。
  2. 手順2で保存した .yml ファイル(または掲載例を保存したファイル)を選んで、取り込みを実行します。

完了状態:スタジオのアプリ一覧にアプリが追加され、開くと「開始 → 形式チェック(IF/ELSE)→ 不備の文章(テンプレート)または判定案の作成(LLM)→ 出力」の流れがキャンバスに再現されている。

インポート直後の編集画面。開始・IF/ELSE・テンプレート・LLM・出力のノードが2つの経路に分かれて並んだキャンバス

取り込み時にエラーやバージョンの警告が出た場合の対処は、第12章12-3の表のとおりです。

手順4:モデルを選び直し、内容を確認する

第12章12-4と同じ要領で調整します。

  1. LLMノード(判定案の作成)を開き、お使いの環境で使えるAIモデルを選び直します。DSLに書かれたモデルがお使いの環境に無い場合は、モデル名の横に「非互換」と表示されます。

取り込んだワークフローのLLMノード。DSLに書かれたモデルが使えず「非互換」と表示された状態

  1. 指示文を読み、業務の言葉に合っているか、余計な内容が入っていないかを確認します。必要項目の4つ(申請者名・連絡先・事業の内容・金額)は、自分の業務の必要項目に書き換えて構いません。
  2. IF/ELSEノードの条件(申請の内容が空である)と、2つの出力ノードの変数の割り当てを確認します。

完了状態:モデルがお使いの環境のものになり、指示文・条件・出力の設定が意図どおりになっている。

手順5:テスト実行で確かめる

分岐のあるワークフローなので、両方の経路を試します(第7章7-5)。

  1. テスト実行で、申請の内容を空のまま実行します。不備を知らせる文章が返ることを確認します。

空のまま実行した結果。不備の文章から出力(不備)への経路が緑になり、結果欄に「申請の内容が入力されていません。内容を記入して再度実行してください。」と表示された状態

  1. もう一度テスト実行で、次のような架空の申請文を貼り付けて実行します。
申請者名:庁内テスト用の架空団体
連絡先:000-0000-0000
事業の内容:地域の清掃活動に使う用具の購入
金額:50,000円
  1. 「判定案:受付可」が返ることを確認します。

4項目のそろった申請文で実行した結果。判定案の作成から出力(判定案)への経路が緑になり、結果欄に「判定案:受付可」と表示された状態

  1. さらに、4項目のうち1つ(例:金額)を消した申請文でも実行し、「判定案:要確認」と不足項目が返ることを確認します。

完了状態:3とおりの入力それぞれで、期待した経路の結果が返っている。

完成の確かめ方

次の3つの入力で、期待どおりの結果が返れば完成です。

試す入力 こう返れば完成
申請の内容を空のまま実行 「申請の内容が入力されていません。内容を記入して再度実行してください。」という趣旨の文章が返る
4項目(申請者名・連絡先・事業の内容・金額)がそろった架空の申請文 「判定案:受付可」が返る
4項目のうち1つが欠けた架空の申請文 「判定案:要確認」と、不足している項目が箇条書きで返る

判定案の文面が元の申請文と食い違っていないか(書かれていない事柄を理由にしていないか)も、あわせて確認します。

うまくいかないときの主な確認先

症状 確認先
インポートでエラー・警告が出る 第12章12-3(エラーやバージョン警告が出た場合)。直らなければ、エラーの文言とYAML全文を生成AIに貼って作り直させます
取り込めたが、ノードの構成が意図と違う 手順1の依頼文を見直して依頼し直すか、画面上でノードを直します(第7章7-2〜7-4)
空で実行しても不備の文章が返らない IF/ELSEノードの条件(対象の変数と「空である」の指定)を確認します(第6章6-1・第10章10-3)
判定案の内容がおかしい LLMノードの指示文を画面上で直します(第7章7-4)。書かれていないことを理由にする場合は、指示文の「申請の内容に書かれていないことは書かないでください」が残っているかを確認します
エラーメッセージ別の対処 第14章(トラブルシューティング)