注:この記事はDify v0.7.2を使用しています。
このチャットフローは、Webまたは音声対話で患者データを収集できる外来案内用チャットボットの構築方法を示しています。簡単に理解すると、患者情報(年齢、性別、症状)に基づいて、おすすめの診療科を案内するということです。
I.ワークフロー思考
1.ワークフローのスクリーンショット
外来オリエンテーションの完全なワークフローのスクリーンショットを以下に示す:
2.ワークフロー擬似フローチャート
外来患者ガイダンスワークフローの目的は、患者が入力した年齢、性別、症状に基づいて、患者に診療科を推薦することである。最初の対話では、患者が一度に全部または一部の情報を入力する可能性があるため、"Parameter Extractor "ノードを使用して、患者の最初の入力から性別、症状、年齢を抽出する。対話変数 is_first_message は、「変数割り当て」ノードによって 0 に設定される。
3.問題 1
その後の対話では、一度に認識されるフィールド情報は1種類のみであるが、患者は複数のフィールドを提供することができ、フィールドは年齢、性別、症状の順に認識される。
4.問題 2
患者情報に基づいてすでに診療科が推奨されている場合、再度何らかの情報を入力すると、最後の診療科が推奨されます。診療科フィールドが空でないため、ダイレクトレスポンスプロセスが実行されます。
II.セッション変数
セッション変数は、ユーザー設定や対話履歴など、LLMが必要とするコンテキスト情報を格納するために使用されます。読み書き可能です。セッション変数は複数ラウンドの対話シナリオを指向しているため、セッション変数はチャットフロー型(チャットアシスタント -> ワークフローオーケストレーション)アプリケーションでのみ使用できます。
1.セッション変数データタイプ
(1) ストリング
(2) 数字
(3) 対象物
(4) Array[文字列] 文字列の配列
(5) Array[number] 数値の配列
(6) Array[object] オブジェクトの配列
2.セッション変数性格描写
(1) セッション変数は、ほとんどのノード内でグローバルに参照できます;
(2) セッション変数の書き込みには変数代入ノード
(3) セッション変数は読み書き可能です。
3.このワークフローで定義されたセッション変数
このワークフローのために定義された5つのセッション変数は、初回対話かどうか、年齢、性別、症状、診療科である。
III.ワークフロー関連インターフェース
1.ワークフローへのインターフェイスの取得
(1) ソースコードの場所
- ソースコードの場所: dedify-0.7.2
- ソースコードの場所: dedify-0.7.2
(2) ワークフロー操作の取得
http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/draft。draftは、draftと同じく、ワークフローページでのデバッグを示す。
(3) ワークフロー実装の取得
ワークフローは、ワークフローデータテーブルにレコードを保存する。現在バージョンはドラフトであり、ワークフローがパブリッシュされるたびに、そのテーブルにレコードが挿入される。下図の通りである:
(4) ワークフローのデータ構造
インターフェースによって返されるワークフローのデータ構造を以下に示す:
class Workflow(db.Model).
__tablename__ = 'ワークフロー'.
table_args__ = (
db.PrimaryKeyConstraint('id', name='workflow_pkey')、
db.Index('workflow_version_idx', 'tenant_id', 'app_id', 'version')、
)
id: Mapped[str] = db.Column(StringUUID, server_default=db.text('uuid_generate_v4()'))
tenant_id: Mapped[str] = db.Column(StringUUID, nullable=False)
app_id: Mapped[str] = db.Column(StringUUID, nullable=False)
type: Mapped[str] = db.Column(db.String(255), nullable=False)
バージョン:Mapped[str] = db.Column(db.String(255), nullable=False)
graph: Mapped[str] = db.Column(db.Text)
features: Mapped[str] = db.Column(db.Text)
created_by: Mapped[str] = db.Column(StringUUID, nullable=False)
created_at: Mapped[datetime] = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
updated_by: Mapped[str] = db.Column(StringUUID)
updated_at: Mapped[datetime] = db.Column(db.DateTime)
_environment_variables: Mapped[str] = db.Column('environment_variables', db.Text, nullable=False, server_default='{}')
_conversation_variables: Mapped[str] = db.Column('conversation_variables', db.Text, nullable=False, server_default='{}')
2.ワークフローインターフェイスの更新
(1) ソースコードの場所
- ソースの場所:dedify-0.7.2/webapp/components/workflowhooks/use-nodes-sync-draft.ts
- ソースコードの場所:dedify-0.7.2
(2) ワークフロー操作の更新
http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/draft.
(3) ワークフローのフロントエンド・コードを更新する
DifyワークフローのフロントエンドにはReact Flowフレームワークが使用されているため、ワークフローが変更された際に追加、削除、変更などのPOST操作が行われている可能性が推測される。バックエンドのコンソールのログから、ワークフローが変更されたときにワークフロー/ドラフト?_token=
::
とおすワークフロー/ドラフト?_token=
フロントエンドのコードを探しても、それを使う場所はひとつしか見つからなかった。
POSTオペレーションが実行されるので、Payloadパラメータがあるはずだ。
依存関係getPostParams
変更が発生すると、非同期に実行される。syncWorkflowDraft(postParams)
.
(因果関係を示す)syncWorkflowDraft(postParams)
実際の呼び出しはPOSTである:
(4) ワークフロー機能の概要
右dify-0.7.2 webserviceworkflow.ts
その機能をまとめると以下のようになる:
シリアル番号 | 関数名 | 機能 | パラメータと説明 |
---|---|---|---|
1 | ワークフロードラフトの取得 |
ワークフローの草案を入手する。 | url : 文字列、リクエストのURL。 |
2 | syncWorkflowDraft |
ワークフローのドラフトを同期 | url : 文字列、リクエストのURL。パラメータ を含むリクエストのパラメータ。 グラフ そして特徴 そして環境変数 歌で応える 会話変数 . |
3 | fetchNodesDefaultConfigs |
ノードのデフォルト設定を取得する。 | url : 文字列、リクエストのURL。 |
4 | ワークフロー実行履歴の取得 |
ワークフローの実行履歴を取得します。 | url : 文字列、リクエストのURL。 |
5 | フェット・チャット・ラン・ヒストリー |
チャットの実行履歴を取得します。 | url : 文字列、リクエストのURL。 |
6 | シングルノードラン |
単一ノードを実行する。 | アプリID アプリケーションのID。ノードID ノードのID。パラメータ オブジェクト、リクエストのパラメータ。 |
7 | GetIterationSingleNodeRunUrl |
1つのノードの反復実行のURLを取得します。 | isChatFlow チャットストリームかどうかを示すブール値。アプリID アプリケーションのID。ノードID ノードのID。 |
8 | パブリッシュワークフロー |
ワークフローを投稿する | url : 文字列、リクエストのURL。 |
9 | フェッチパブリッシュワークフロー |
公開されたワークフローを取得する。 | url : 文字列、リクエストのURL。 |
10 | ストップワークフローラン |
ワークフローの実行を停止する。 | url : 文字列、リクエストのURL。 |
11 | フェッチノードデフォルト |
ノードのデフォルト設定を取得する。 | アプリID アプリケーションのID。ブロックタイプ 列挙値、ノードのタイプ。クエリー オブジェクト、オプション、クエリパラメータ。 |
12 | updateワークフロードラフトフロムDSL |
DSLからワークフローのドラフトを更新する。 | アプリID アプリケーションのID。データ 文字列、DSLデータ。 |
13 | 会話変数の現在値の取得 |
セッション変数の現在値を取得します。 | url : 文字列、リクエストのURL。パラメータ を含むリクエストのパラメータ。 会話ID . |
3.ワークフローの実装
への言及Chatflowの作成、更新、実行、削除操作のプロセス実装6]の "Chatflow Implementation "の項を参照。
4.ワークフロー・パブリッシング
(1) ソースコードの場所
- ソースコードの場所: dedify-0.7.2
- ソースコードの場所: dedify-0.7.2
- ソースの場所: dedify-0.7.2
(2) ワークフロー公開インターフェース
ワークフローの公開をクリックすると実行されます。http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/publish
インターフェース
主に、新しいワークフローを作成し、アプリのワークフローイベントをトリガーする。以下に示す:
(3) ワークフロー記録の新規作成
これは主に、バージョンフィールドの内容が 2024-09-07 09:11:25.894535である新しいワークフローレコードを作成することである。以下に示すとおりである:
(4) app_published_workflow_was_updatedイベントの実装
app_published_workflow_was_updated.connect
def handle(sender, **kwargs):
app = sender
公開ワークフロー = kwargs.get("公開ワークフロー")
published_workflow = cast(ワークフロー, published_workflow)
dataset_ids = get_dataset_ids_from_workflow(published_workflow) # ワークフローからデータセットIDを取得する
app_dataset_joins = db.session.query(AppDatasetJoin).filter(AppDatasetJoin.app_id == app.id).all() # アプリケーションデータセットの関連付けを取得する
removed_dataset_ids = [] # 削除されたデータセットIDを格納するために使用する
if not app_dataset_joins: # アプリケーションデータセットの結合がない場合
added_dataset_ids = dataset_ids # データセットIDを追加する
else: # アプリケーションデータセットの結合がある場合
old_dataset_ids = set() # 古いデータセットIDを保存するため
for app_dataset_join in app_dataset_joins: # アプリケーションデータセットの関連付けを繰り返す
old_dataset_ids.add(app_dataset_join.dataset_id) # データセットIDの追加
added_dataset_ids = dataset_ids - old_dataset_ids # データセットIDの追加
removed_dataset_ids = old_dataset_ids - dataset_ids # データセットIDを削除する
if removed_dataset_ids: 削除されたデータセットIDがあれば#
for dataset_id in removed_dataset_ids: # 削除されたデータセットIDを繰り返し調べる
db.session.query(AppDatasetJoin).filter(
AppDatasetJoin.app_id == app.id, AppDatasetJoin.dataset_id == dataset_id
).delete() # アプリケーションデータセットの関連付けを削除する
if added_dataset_ids: # 追加されたデータセットIDがある場合
for dataset_id in added_dataset_ids: # 追加されたデータセットIDを繰り返し処理する
app_dataset_join = AppDatasetJoin(app_id=app.id, dataset_id=dataset_id) # アプリケーションデータセットの関連付けを作成する
db.session.add(app_dataset_join) # アプリケーションデータセット関連付けの追加
db.session.commit() # トランザクションをコミットする
このコードの機能は app_published_workflow_was_updated
アプリケーションの公開ワークフローが更新されたときに、アプリケーションとデータセットの関連関係を更新するためのシグナル。具体的な手順は以下の通り:
- シグナルを送信するアプリケーション・オブジェクトを取得する
アプリ
ワークフローオブジェクトの更新公開ワークフロー
. - 各論
get_dataset_ids_from_workflow
更新されたワークフローからデータセットIDコレクションを抽出する関数データセットID
. - データベースに問い合わせて、現在のアプリケーションの
AppDatasetJoin
記録 - 追加・削除するデータセットIDを計算する:
- もし現在
AppDatasetJoin
レコードがある場合は、抽出されたすべてのデータセットIDを追加する必要がある。 - そうでなければ、追加・削除するデータセットIDを計算する。
- もし現在
- 削除の必要性
AppDatasetJoin
記録 - 新規追加
AppDatasetJoin
記録 - データベーストランザクションを送信します。
(5) AppDatasetJoinテーブルの役割
AppDatasetJoinテーブルは、アプリケーション(App)とデータセット(Dataset)の多対多の関係を維持する役割を果たす。各レコードは、アプリケーションとデータセットの関連を表す。具体的なフィールドは以下のとおり:
- id: レコードを一意に識別する主キー。
- app_id: アプリケーションの一意な識別子。
- dataset_id: データセットの一意識別子.
- created_at: レコード作成のタイムスタンプ。
- このテーブルを使えば、どのデータセットが特定のアプリケーションに関連付けられているか、あるいは特定のデータセットがどのアプリケーションに関連付けられているかを照会することができる。
(6) get_dataset_ids_from_workflow()の実装
def get_dataset_ids_from_workflow(published_workflow: Workflow) -> set: # ワークフローからデータセットIDを取得する。
dataset_ids = set() # データセットIDを格納するために使われる
graph = published_workflow.graph_dict # ワークフローのグラフを取得する
if not graph: # グラフがない場合
dataset_ids を返す # 空のセットを返す
nodes = graph.get("nodes", []) # グラフ内のノードを取得
# すべての知識検索ノードをフェッチする # すべての知識検索ノードをフェッチする
knowledge_retrieval_nodes = [ ]。
node for node in nodes if node.get("data", {}).get("type") == NodeType.KNOWLEDGE_RETRIEVAL.value
] # すべての知識検索ノードを取得する
if not knowledge_retrieval_nodes: # 知識検索ノードがない場合
return dataset_ids # 空集合を返す。
for node in knowledge_retrieval_nodes: # 知識検索ノードを繰り返し処理する
try: node_data = Knowledge_retrieval_nodes.
node_data = KnowledgeRetrievalNodeData(**node.get("data", {})) # ノードデータを取得する
dataset_ids.update(node_data.dataset_ids) # データセットIDの更新
except Exception as e: # 例外が発生した場合
continue
return dataset_ids
get_dataset_ids_from_workflow関数の主な機能は、与えられたワークフローオブジェクトからすべての知識検索ノードの関連データセットIDを抽出することである:
- データセットIDを格納するために、空の dataset_ids コレクションを初期化する。
- ワークフローグラフのグラフ構造を取得する。
- グラフ構造が空の場合、空の dataset_ids コレクションを返す。
- グラフ内のすべてのノードを取得する。
- KNOWLEDGE_RETRIEVAL knowledge_retrieval_nodes 型のすべてのノードをフィルタリングします。
- これらの知識検索ノードを反復処理し、データセットIDを抽出し、dataset_idsコレクションで更新する。
- 抽出されたすべてのデータセットIDのコレクションを返す。
5.ワークフローその他のインターフェース
ワークフロー・オーケストレーションの会話型アプリケーションAPIは非常に明確に説明されている。
シリアル番号 | インターフェース名 | インターフェースリンク | インターフェース機能の説明 |
---|---|---|---|
1 | 対話メッセージを送る | POST /チャットメッセージ | ユーザー入力や質問を送信するセッションメッセージを作成します。 |
2 | ファイルのアップロード | POST /files/upload | メッセージ送信時に使用するファイル(現在は画像のみ対応)のアップロード。 |
3 | 応答を停止する | POST /chat-messages/:task_id/stop | 応答のストリーミングを停止する(ストリーミング・モードのみサポート)。 |
4 | メッセージのフィードバック (いいね) | POST /messages/:message_id/feedbacks | ユーザーからのフィードバックやメッセージへの「いいね!」によって、アウトプットの最適化を促進。 |
5 | 次のラウンドのための質問リストを入手する | GET /メッセージ/{メッセージID}/提案されたメッセージ | 次のラウンドのための質問リストを入手する。 |
6 | セッション履歴メッセージの取得 | メッセージ | セッションのメッセージログの履歴を取得する。 |
7 | セッションリストの取得 | GET /conversations | 現在のユーザーのセッションのリストを取得する。 |
8 | セッションの削除 | DELETE /conversations/:conversation_id | 指定したセッションを削除する。 |
9 | セッション名の変更 | POST /conversations/:conversation_id/name | セッション名を変更する。 |
10 | 音声テキスト | POST /オーディオからテキストへ | 音声ファイルをテキストに変換 |
11 | 音声合成 | POST /テキストからオーディオへ | テキストを音声に変換。 |
12 | アプリケーション構成情報の取得 | GET /parameters | ファンクション・スイッチや入力パラメータなど、アプリケーションの設定情報を取得する。 |
13 | アプリケーションメタ情報の取得 | GET /meta | ツールアイコンを取得するために、アプリケーションのメタ情報を取得する。 |
書誌
[1] セッション変数:https://docs.dify.ai/v/zh-hans/guides/workflow/variables
[2] 変数の割り当て: https://docs.dify.ai/v/zh-hans/guides/workflow/node/variable-assignment
[3] 変数集計:https://docs.dify.ai/v/zh-hans/guides/workflow/node/variable-assigner
[4] 反応 フロー中国語サイト:https://reactflow-cn.js.org/
[5] リアクトフロー英語サイト:https://reactflow.dev/
[6]Chatflowの作成、更新、実行、削除操作のプロセス実装: https://z0yrmerhgi8.feishu.cn/wiki/FFzxwdF4PijlhjkLUoecOv6Vn8a