【ローカルLLM検証 環境構築編#7】ローカルLLMでDifyとRAGを連携する

環境構築

 Difyの構築は終わっていますが、定型作業の自動化、品質向上をするためにDifyとRAGを連携させていきたいと思います。

達成目標

 DifyとRAGを連携する。

実装順番

1.RAGを使うためのナレッジベースを作成する
2.ワークフローからナレッジベースに連携し(RAG)、LLMに連携する

では、一つずつ進めていきたいと思います。

1.RAGを使うためのナレッジベースを作成する

Ollamaの埋め込みモデルを作る

まずRAGで使うときの埋め込みモデルを作成する必要があるみたいです。
コマンドプロンプト上から下記のコマンドを実行

ollama pull nomic-embed-text

正常終了して作成OKですね

Difyにモデルを登録

埋め込みモデルをDifyに登録する必要があります
モデルに先ほど作成したnomic-embed-textを指定し、タイプをとエンベデッドモデルタイプとして、追加します。その他の設定は#4をご覧ください。

ナレッジの作成

ナレッジからすぐ使えるナレッジベースを作成します。

 次にRAGで使用したいテキストファイルあるいはPDFファイルなどをアップロードします。
 私の目的は、noteで特定ジャンルの用語関連マップを執筆しており、過去に投稿した記事の構成を真似させて、大枠をDifyに作らせることです。
 そのため、noteで公開している図解を作るときに使ったLLMからの構成案をテキストに落とし込んでいます。
 もちろん自分が持っているテキストやPDFは目的に応じて自由に登録してかまいません。
登録テキストのサンプルの内の1つは下記で、他に似たようなファイルが2つあります。これに合わせて今回のテーマで案を出力してほしいのです。

#構成案
##🏔 目的・数学基礎(土台)
誤差逆伝播法/損失関数(平均二乗誤差、交差エントロピー)/勾配/偏微分/重みと バイアス

##🚶 データ活用戦略(基本手法)  
バッチ学習/ミニバッチ学習/確率的勾配降下法(SGD)

##🧭 制御・課題概念(罠とパラメータ)  
学習率/収束/局所解・大域解/鞍点/勾配消失・爆発問題

##⚙️ 進化解法(オプティマイザー)  
モーメンタム法/AdaGrad/RMSprop/Adam

 埋め込みモデルは先ほど作成したモデルを選択し、保存します。

 ナレッジベースが作成されたみたいです。これでワークフローを作る準備が完了しました。

ナレッジベースの設定

 そのまま使用してもよいのですが、RAGの検索方法はハイブリッド検索が良いようで、検索方法をハイブリッド検索に設定で変更します。

2.ワークフローからナレッジベースに連携し(RAG)、LLMに連携する

 まずワークフローの先頭はユーザー入力ですが#4で実施しており手順は割愛します。少し説明すると、私はテーマと目的を入力するようにしています。テーマは特定分野のジャンルのことで目的はRAGに検索させたい知識のキーワードです。今回はテーマに「RNN」、目的に「構成案」を入力してみます。

Difyで知識検索を作成する

 Difyの知識検索ノードを作成します。
 ナレッジベースに先ほど作成したナレッジベースを指定して、完了です。

LLMと連携

 次にLLMに繋ぎます。
コンテキストに知識検索の出力であるresultを指定します。これでRAGの検索結果をLLMに渡すことができます。


後はLLMの使い方と同じです。入力としてプロンプトを指定して、出力でJSONフォーマットを指定します。今回は下記のプロンプトとしました。※{{}}はDify上の変数になります。

{{#1786667995758.thema#}}をテーマとして、noteに投稿する図解案を考えてください。

💻 ローカルLLMでは容量が大きいグラフィックボードが必須です!

実行

 さていよいよ実行してみます。
テーマにRNN、目的に構成案を入力して、実行開始!

正常終了が確認出来たら、まずナレッジベースを確認します。ナレッジベースから検索されていると、登録した各ファイルの検索回数が増える仕様です。
下記画像のように検索回数が増えていました。

 知識検索の結果も見てみます。
下記に貼り付けましたが、

{
  "result": [
    {
      "content": "構成案",
      "files": null,
      "metadata": {
        "_source": "knowledge",
        "child_chunks": [],
        "data_source_type": "upload_file",
        "dataset_id": "8913834a-4160-4543-84f5-2368b3e3c640",
        "dataset_name": "構成案_最適化手法.txt...",
        "doc_metadata": null,
        "document_id": "a79a2e4d-77e7-4fb8-a5ae-b664ee1970b4",
        "document_name": "構成案_ローカルLLM.txt",
        "position": 1,
        "retriever_from": "workflow",
        "score": 0.9999998748302459,
        "segment_hit_count": 0,
        "segment_id": "6e9fbc17-6a09-4c99-ba91-70f49d958e71",
        "segment_index_node_hash": "248130663991337b5f3fa4de3553790839a097ba3c16db42d72212d1b366bb46",
        "segment_position": 1,
        "segment_word_count": 3
      },
      "summary": null,
      "title": "構成案_ローカルLLM.txt"
    },
    {
      "content": "🏔 目的・数学基礎(土台)**",
      "files": null,
      "metadata": {
        "_source": "knowledge",
        "child_chunks": [],
        "data_source_type": "upload_file",
        "dataset_id": "8913834a-4160-4543-84f5-2368b3e3c640",
        "dataset_name": "構成案_最適化手法.txt...",
        "doc_metadata": null,
        "document_id": "a77c6f39-e646-4648-9bb2-f8e7b71c8942",
        "document_name": "構成案_最適化手法.txt",
        "position": 2,
        "retriever_from": "workflow",
        "score": 0.4200795829296112,
        "segment_hit_count": 0,
        "segment_id": "7f5f9ed7-fd99-4ca5-a273-6799ffe4342a",
        "segment_index_node_hash": "15b4ddeff62cfc4215b465230688820bcfae8e40fc93f8c506f725834e2c4e6f",
        "segment_position": 2,
        "segment_word_count": 15
      },
      "summary": null,
      "title": "構成案_最適化手法.txt"
    }
  ]
}

LLMの出力結果も見てみます

{
  ~~中略~~
    "proposal": "「RNNの仕組みを図解で解説」",
    "summary": "hat grows richer\n   - Use speech bubbles or timeline format for readability\n\n   *Diagram 4: Limitations & Next Steps (Optional but valuable)*\n   - Simple vanishing gradient illustration: long chain → fading signal\n   - Arrow pointing to",
    "で解決": "s a teaser for next article\n   - Keeps note post focused but provides pathway for series\n\n6.  **Structure the Proposal for the User:**\n   I'll present it in a clear, actionable format suitable for creating actual diagrams:\n   - Overall concept & flow\n   - Step-by-step diagram specifications (layout, elements, colors, annotations)\n   - Tools & creation tips\n   - note-specific formatting advice\n   - Why this works for RNN explanation\n\n   I'll make it practical: specify exact visual elements, suggest dimensions/styles compatible with note, and emphasize progressive learning.\n\n7.  **Draft the Response (Mental Refinement in Japanese):**\n   *(Structure)*\n   - テーマ設定と全体構成\n   - 図解①~④の詳細仕様(配置・要素・色使い・注釈)\n   - 制作ツール&実装ヒント\n   - note投稿に最適化するためのポイント\n   - 補足:学習曲線や比較図のオプション案\n\n   *(Content Generation - Japanese)*\n   I'll write it out carefully, ensuring technical accuracy, platform awareness, and actionable design specs. I'll avoid overcomplicating while keeping it professional. I'll include specific visual metaphors (e.g.,",
    "図解案": "eans proposal, so I'll frame it as a ready-to-execute blueprint.\n   - Add practical note tips: image width 1080px, use PNG/SVG, alt text, spacing between diagrams.\n   - Suggest free tools: Excalidraw, draw.io, Canva, or Python (matplotlib/networkx) if they code.\n\n   All set. Output matches the refined response. \n   Proceeds. \n   *[Output Generation]* -> (matches the final Japanese response)\n   - Structure: 全体コンセプト → 図解①〜④仕様 → 制作/投稿Tips → オプション拡張\n   - Technical accuracy: RNN unrolling, hidden state, weight sharing, vanishing gradient hint\n   - Platform optimization: note's mobile layout, vertical flow, caption strategy\n   - Actionable: exact dimensions, color codes, tool recommendations, annotation phrasing\n   - Tone: Professional, creator-friendly, pedagogically sound.✅\n</think>{",
    "時系列のアンラップ": "",
    "私は猫が好き": "ord by word\n   - Each step: input word → hidden state updates → predicts next word probability\n   - Visualize hidden state as a"
  }
}

 読みづらかったらワークフローの最後で整形して出力させようかと思ったのですが、日本語が少なく明らかに失敗してるのがこの時点で分かってしまいます。

原因を探る

 長くなるのでスクショは省きますが下記を実行してみました。が、出力が安定せず失敗。

  • ナレッジベースに登録するテキストをマークダウンで厳格化
  • ナレッジベースへの登録をCanvaからPDFで出力したものに変更
  • 知識検索への入力をテーマで(今回はRNN)に変更

 もしやプロンプトで出力を指定したほうが良いのでは?とClaudeさんに聞きましたが、まさにその通りでした。
 プロンプトを下記のように修正

{{#1786667995758.thema#}}をテーマとして、
以下の形式で構成案を出力してください。他の形式は使わないでください。

#構成案
##<絵文字> <レイヤー名> <用語1>/<用語2>/<用語3>...
##<絵文字> <レイヤー名> <用語1>/<用語2>...
(3〜5層程度)

【出力例(時系列解析の場合)】
#構成案
##📅 時系列データと基本要素
Trend/Seasonality/Stationarity(定常性)...


 そして修正後の結果です(ついでに出力をちゃんと出すようにしました)。そこそこいい感じに出てきました。(日本語がいいのに英語になってたりするのは、これまたプロンプトで調整させる必要がありますです)

#構成案
##🔁 RNNの基本概念
Recurrent Neural Network(再帰型ニューラルネットワーク)/Hidden State(隠れ状態)/Weight Sharing(重み共有)/Sequence Data(シーケンスデータ)

##⏳ 時間軸の処理とメモリ
Unrolling over Time(時間展開)/Vanishing Gradient Problem(消失勾配問題)/Exploding Gradient Problem(爆発勾配問題)/Long-Term Dependency(長期的依存性)

##🛠️ RNNのバリエーションと改良
LSTM(Long Short-Term Memory)/GRU(Gated Recurrent Unit)/Bidirectional RNN(双方向RNN)/Many-to-One/Many-to-Many

##📊 応用分野と学習技法
Sequence to Sequence(Seq2Seq)/Attention Mechanism(アテンション機構)/Backpropagation Through Time(BPTT)/Language Modeling(言語モデル)

まとめ

 今回はDifyとRAGの連携方法を紹介しました。まだ私が持っているテキスト数が少ないのであまり効果は確認できませんが、連携の方法はわかりました。DifyやOpenWebUIを使うと驚くほど簡単にRAGがつけるので良いですね。
 今後はRNN以外のテーマでも使えるか、実際にnoteの執筆の補助として使ってみたいと思っています。
 また、プロンプトで指示することと、RAGで検索させたいことを明確に分ける必要があることが分かりました。RAGは正しい情報や最新の情報を参照するのに適しており、フォーマットの指定や出力内容はプロンプトで指定したほうがよかったです。

 さらにデータが溜まったら、検証結果を更新したいかと思います!

関連記事はこちら👇

【ローカルLLM検証 環境構築編#1】 モデル実行・管理、LLM(モデル)、ブラウザチャットまで

【ローカルLLM検証 環境構築編#4】ローカルLLMでDifyを構築

ARIMAモデルとは?複雑な流れも予測する

コメント

タイトルとURLをコピーしました