catch-img

Difyの使い方(メモリ―機能と会話変数とは)

2024年8月17日更新:2024年8月にDifyのバージョン0.7.0がローンチされ、新機能「Conversation Variables(会話変数)」と「Variable Assigner(変数アサイン)」が追加されましたので、この2機能の解説を後半に追記しました。

目次[非表示]

  1. LLMのメモリー機能
    1. チャットフローのみ有効
    2. メモリ機能は会話を記憶するかどうか
    3. メモリ機能オフの会話
    4. メモリ機能をオンにした会話
    5. ウインドウサイズは会話記憶の数
    6. ウインドウサイズ1の会話
  2. Conversation VariablesとVariable Assigner
    1. Appendが可能なのは、array[object]のみ
    2. 会話変数の中身
    3. こんなケースで使える?
      1. 1.音声メインやマルチモーダル全盛期になったときに強い?
      2. 2.プレスリリースの作成ヒアリングにも使える
      3. 3.会計系、特に確定申告アプリは大活躍しそう

ノーコードLLM構築ツール「Dify」のつまずきポイントを、備忘録を兼ねて解説していきます。

LLMのメモリー機能

迷うことが多い機能の一つが「メモリ―」機能です。

まずオフィシャルの説明です。

高度な機能
記憶:記憶をオンにすると、問題分類器の各入力に対話履歴が含まれ、LLM が文脈を理解しやすくなり、対話の理解能力が向上します。


記憶ウィンドウ:記憶ウィンドウが閉じている場合、システムはモデルのコンテキストウィンドウに基づいて対話履歴の伝達数を動的にフィルタリングします。開いている場合、ユーザーは対話履歴の伝達数を正確に制御できます(対数)。

よく分かりません。Perplexityに聞いてみます。

質問:Difyのメモリー機能とは?


回答:Difyのメモリー機能とは、チャットフロー内で複数回の対話の履歴メッセージを保存および伝達するために使用される機能です。この機能は、LLM(Large Language Model)や問題分類などのノードで有効にすることができます。メモリー機能を使用することで、チャットボットはユーザーとの対話履歴を記憶し、より適切な回答を提供することができます。メモリー機能は、チャットフローの開始ノードに内蔵されている変数sys.query、sys.files、sys.conversation_id、sys.user_idを使用して、対話履歴を保存および伝達します。さらに、メモリー機能は、チャットフローの終了ノードでプロセス終了時にのみ選択できる終了ノードとは異なり、プロセスの中間ステップでも出力をサポートする回答ノードで使用することができます。メモリー機能の利点は、チャットボットがユーザーとの対話履歴を記憶し、より適切な回答を提供することができることです。これにより、ユーザー体験が向上し、チャットボットの有用性が高まります。ただし、メモリー機能は、ワークフローにはメモリ関連の設定がなく、有効にできません。

記憶機能のようです。釈然としませんので調べて解説します。

チャットフローのみ有効

メモリー機能はChatflowのみ有効になる記憶保持機能のようです。ワークフローでは機能が出てきません。

メモリ機能を反映させた機能一覧はこちら。Dify機能一覧

実際に機能を見ていきます。

ChatflowのLLMを開くと、メモリ―機能が現れます。

Difyのメモリー機能

オンオフ可能な「メモリ」と数値選択も可能な「ウインドウサイズ」が現れます。

USERには、sys.query(チャット上でのユーザーの新期質問)が自動入力されます。

メモリ機能は会話を記憶するかどうか

この「メモリ」機能はチャットフロー上の会話において、ユーザーとの会話を記録するかどうかの機能のようです。

以下のプロンプトで実際にオン・オフを比較してみます。

Difyメモリー機能

Dify

※メモリをオフにするとsys.queryは消えるので、改めてUSERに設定して実行します。

メモリ機能オフの会話

Difyメモリー機能

直前の会話も記憶していません。

メモリ機能をオンにした会話

Difyメモリー機能

メモリをオンにすると、好物と季節をしっかりと回答しています。

このときのログを見てみます。

{
  "model_mode": "chat",
  "prompts": [
    {
      "role": "user",
      "text": "あなたはチャットボットです。ユーザーの入力に会話形式で返答してください。分からないことは分からないと回答してください、。",
      "files": []
    },
    {
      "role": "user",
      "text": "こんにちは。夏ですね。",
      "files": []
    },
    {
      "role": "assistant",
      "text": "こんにちは!本当に夏ですね。暑い日が続いていますが、何か夏らしいことを楽しんでいますか?",
      "files": []
    },
    {
      "role": "user",
      "text": "いいえ。ところで私の好物はほうじ茶フラペチーノです。",
      "files": []
    },
    {
      "role": "assistant",
      "text": "ほうじ茶フラペチーノ、美味しいですよね!香ばしいほうじ茶の風味が夏にぴったりです。ほかにも好きな飲み物や食べ物はありますか?",
      "files": []
    },
    {
      "role": "user",
      "text": "ありません。しかし暑いですね。",
      "files": []
    },
    {
      "role": "assistant",
      "text": "確かに、暑い日が続いていますね。水分をしっかり取って、体調に気をつけてくださいね。何か涼しくなる方法を見つけましたか?",
      "files": []
    },
    {
      "role": "user",
      "text": "見つけていません。ところで私の好物を知っていますか?",
      "files": []
    },
    {
      "role": "assistant",
      "text": "はい、あなたの好物はほうじ茶フラペチーノですね!とても美味しい選択です。他にも何か気になる食べ物や飲み物があれば教えてください。",
      "files": []
    },
    {
      "role": "user",
      "text": "ところで今の季節はいつですか?",
      "files": []
    }
  ]
}

初回設定からmessagesに追加されていることが分かります。

この流れはOPEN AIのドキュメントを見るとより理解が深まると思います。

openaidoc

https://platform.openai.com/docs/guides/chat-completions/getting-started


ウインドウサイズは会話記憶の数

ウインドウサイズは、userの回答を何個前までプロンプトに入れるかという設定のようです。

ウインドウサイズ1に設定すれば、1つ前のユーザー回答まで保持します。2個以上前の記憶は保持されません。

ウインドウサイズ1の会話

Difyウインドウサイズ

Conversation VariablesとVariable Assigner

この2つもメモリー機能と同様、チャットフローのみで使える機能となります。

これらはChatGPTでいうところの「メモリー機能」と考えると分かりやすいと思います。

  https://help.openai.com/en/articles/8590148-memory-faq https://help.openai.com/en/articles/8590148-memory-faq

LLMメモリー機能は、チャットフローにおける会話履歴(messages)保持の有無やその量を調整する機能でした。

この方式だと、記憶しておかなくても良い会話でも時系列に順番に保存していくことになり、会話が継続されるとデータが増えてしまいます。

またチャット終了時にはリセットされてしまうため、長期・永続的な記憶として使うことができません。

今回の新機能Conversation VariablesとVariable Assignerは、「LLMが記憶するべき要素を自動判断・取得し、記憶項目を変数として自動的に保存しておく機能」と定義するのが良いかもしれません。

テンプレートには、
・Patient Intake Chatbot(性別/年齢/症状からおすすめの診療科を教えてくれる)
・Personalized Memory Assistant(会話から事実や好み、状況などを記憶してくれるアシスタント)

の2つが確認できます。

Patient Intake Chatbotはなかなか複雑ですが、
・LLMで会話からuserの年齢・性別・症状の3つのパラメーターを抽出
・Variable Assignerで3つの変数に入れる
・LLMで診療科を提示

という流れのようです。

仕組みはPersonalized Memory Assistantのほうが分かりやすいです。

流れは以下のようなプロセスです。Difyメモリー「Conversation Variables(会話変数)」と「Variable Assigner(変数アサイン)」

userの発話に以下の3点が現れたら記憶するというフローになりますが、memoriesはどういう意味なのか不明でした。
・the facts(事実)
・preferences(好み)
・memories(思い出?)

これはLLMメモリーライブラリのmem0のプロンプトから使ったと説明が記載されていますが、この3つの区分がMECEなのか、最適なのかは少し疑問です。

  Mem0 - The Memory Layer for Personalized AI A self-improving memory layer for LLM applications. Create personalized AI experiences that saves costs and delights users. https://www.mem0.ai/
  mem0/mem0/configs/prompts.py at main 揃 mem0ai/mem0 The memory layer for Personalized AI. Contribute to mem0ai/mem0 development by creating an account on GitHub. GitHub

またサンプルコードではCodeノードでarg1[0]を選択していますが、これの判断基準を実際にどうするのかはわかりませんでした(ここで結構つまずくはず)。

import json

def main(arg1: list) -> str:
    try:
        # 以下でarg1[0]に絞り込んでいるが、実践ではどうするのか不明

        # Assume arg1[0] is the dictionary we need to process
        context = arg1[0] if arg1 else {}
        
        # Construct the memory object
        memory = {"memory": context}
        
        # Convert the object to a JSON string
        json_str = json.dumps(memory, ensure_ascii=False, indent=2)
        
        # Wrap the JSON string in <answer> tags
        result = f"<answer>{json_str}</answer>"
        
        return {
            "result": result
        }
    except Exception as e:
        return {
            "result": f"<answer>Error: {str(e)}</answer>"
        }

ここもベクトルDB検索でリランクして上位n個を使う、といった使い方が今後できるのかもしれません。

Appendが可能なのは、array[object]のみ

WRITE MODEで会話変数の編集効果を、Overwrite(上書き)、Append(追加)、Clear(削除)の3種類から選べます。

Appendは会話変数のタイプをarray[object]にしているときしか選択できません。

会話変数の中身

会話の中からfactsとpreferences、memoriesを取得した結果は、以下のような関数の格納となっています。


{
  "memory": [
    {
      "facts": ["猫を飼っている", "新しいスマホを買った"],
      "preferences": ["ラーメンが好き", "辛いものが苦手"],
      "memories": ["ユーザーは今日機嫌が良い"]
    }
  ]
}

テンプレートではこの内容を最終回答のLLMのシステムプロンプトに入れて回答させています。

You are an expert at answering {{#sys.query#}} based on the provided memories. 

Your task is to provide accurate and concise answers to the questions by leveraging the information given in {{ここに会話変数}} 

Guidelines: 
- Extract relevant information from the memories based on the question. 
- If no relevant information is found, make sure you don't say no information is found. Instead, accept the question and provide a general response. 
- Ensure that the answers are clear, concise, and directly address the question.  
Ensure that the language of the response is consistent with {{#sys.query#}}.


こんなケースで使える?

2種のテンプレートでは、メモリーとの使い分けなど分かりづらい部分もありますが(サンプルコードではメモリー機能も一部オンになっている)、Webでは「チャットボックスにアップロードされたファイル(近々配布予定)」も使えるようになるということで、外部記憶を自在に出し入れできるようになるのだと思います。

自分の大量のパーソナルデータをjson形式でまとめておけば、あらゆるAIに読み取って個人個人に最適化された回答をもらうことができるでしょう。

1.音声メインやマルチモーダル全盛期になったときに強い?

何気ない会話から、重要項目を自動抽出し記憶してておけるため、音声やビデオ入力がメインとなった際にかなり強みを発揮しそうです。

ToDoリストなどに使ったり、冷蔵庫の中身を変数に入れておけばスーパーの買い物でも大変便利そうです。

2.プレスリリースの作成ヒアリングにも使える

以前プレスリリースを自動作成するチャットボット構成を説明しましたが、6W5Hを変数に入れておき、チャットフローで確認しながらヒアリング項目を埋めていき、プレスリリースを作りあげるという流れも可能かもしれません。

  Difyにプレスリリースを自動作成させる方法 ノーコードLLM構築ツールDifyでプレスリリース作成業務を自動化する方法を解説します。 広報・PR支援の株式会社ガーオン

ただ現状では、エージェントにツールを色々と持たせて作ったほうが良い気がします。

エージェントの場合はログがLangSmithなどでしか確認できませんが、会話履歴をそのまま全てmessagesで残しているだけのようです。

3.会計系、特に確定申告アプリは大活躍しそう

入力変数が一定でありルールベースな判断ができる筆頭が、確定申告かもしれません。

MECEですらなく日本語もたどたどしい確定申告サイトは、こうした機能で早く刷新(淘汰)されてほしいものです。

以上、Difyのメモリー機能に関するお悩みの解決の一助となれば幸いです。

関連記事

広報・PRやプレスリリースまわりでお困りのことはございませんか?
多数の企業サポートを行ってきた当社が解決いたします。
お気軽にお問合せください。