Hinweis: Dieser Artikel verwendet Dify v0.7.2.
Dieser Chat-Flow zeigt, wie man einen Chatbot für die ambulante Beratung erstellt, der Patientendaten per Web- oder Sprachdialog erfassen kann. Einfach ausgedrückt bedeutet dies, dass der Patient eine Empfehlung für eine Abteilung auf der Grundlage von Patientendaten (Alter, Geschlecht und Symptome) erhält.
I. Workflow-Denken
1 Screenshot Workflow
Screenshot des gesamten Arbeitsablaufs der ambulanten Orientierung, siehe unten:
2. pseudo-Flowchart zum Arbeitsablauf
Der Zweck des Arbeitsablaufs für die ambulante Beratung besteht darin, einem Patienten auf der Grundlage seiner Angaben zu Alter, Geschlecht und Symptomen eine Abteilung zu empfehlen. Da der Patient in der ersten Dialogrunde alle oder einen Teil der Informationen auf einmal eingeben kann, wird der Knoten "Parameter Extractor" verwendet, um das Geschlecht, das Symptom und das Alter aus der ersten Eingabe des Patienten zu extrahieren. Die Dialogvariable is_first_message wird durch den Knoten "Variable Assignment" auf 0 gesetzt.
3. die Probleme 1
In den folgenden Dialogrunden wird jeweils nur eine Art von Feldinformationen ermittelt, obwohl der Patient mehrere Felder angeben kann, wobei die Reihenfolge der Feldidentifizierung Alter, Geschlecht und Symptome ist.
4. die Probleme 2
Wenn eine Abteilung bereits aufgrund von Patienteninformationen empfohlen wurde, wird bei erneuter Eingabe von Informationen die letzte Abteilung empfohlen. Da das Feld "Abteilung" nicht leer ist, wird das Verfahren der direkten Antwort angewendet.
II. Variablen der Sitzung
Die Sitzungsvariable wird verwendet, um Kontextinformationen zu speichern, die vom LLM benötigt werden, wie z. B. Benutzereinstellungen, Dialogverlauf usw. Sie ist schreibgeschützt. Sitzungsvariablen sind auf Mehrrunden-Dialogszenarien ausgerichtet, daher sind Sitzungsvariablen nur für Anwendungen vom Typ Chatflow (Chat Assistant -> Workflow Orchestration) verfügbar.
1.SitzungsvariableDatentyp
(1) Zeichenfolge
(2) Anzahl
(3) Gegenstand
(4) Array[string] Array von Zeichenketten
(5) Array[number] Array mit Zahlen
(6) Array[object] Array von Objekten
2.SitzungsvariableCharakterisierung
(1) Sitzungsvariablen können in den meisten Knoten global referenziert werden;
(2) Das Schreiben von Sitzungsvariablen erfordert die Verwendung derVariablenzuweisungKnotenpunkte;
(3) Sitzungsvariablen sind schreibgeschützt.
3. die in diesem Workflow definierten Sitzungsvariablen
Die fünf für diesen Arbeitsablauf definierten Sitzungsvariablen sind, ob es sich um die erste Gesprächsrunde handelt, Alter, Geschlecht, Symptome und Abteilung.
III. Arbeitsablaufbezogene Schnittstellen
1. die Schnittstelle zum Workflow erhalten
(1) Ort des Quellcodes
- Ort des Quellcodes: dedify-0.7.2\api\controllers\console\app\workflow.py
- Ort des Quellcodes: dedify-0.7.2\api\services\workflow_service.py
(2) Abrufen von Workflow-Vorgängen
http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/draft. wobei draft, wie draft, die Fehlersuche auf der Workflow-Seite anzeigt.
(3) Beschaffung von Workflow-Implementierungen
Der Workflow speichert einen Datensatz in der Datentabelle workflows. Die Version ist nun ein Entwurf und jedes Mal, wenn ein Workflow veröffentlicht wird, wird ein Datensatz in diese Tabelle eingefügt. Wie unten gezeigt:
(4) Datenstruktur des Arbeitsablaufs
Die von der Schnittstelle zurückgegebene Workflow-Datenstruktur ist unten dargestellt:
class Workflow(db.Model).
__tablenname__ = 'workflows'
__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)
version: 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)
_umgebungsvariablen: Mapped[str] = db.Column('umgebungsvariablen', db.Text, nullable=False, server_default='{}')
_conversation_variables: Mapped[str] = db.Column('conversation_variables', db.Text, nullable=False, server_default='{}')
2. aktualisierte Workflow-Schnittstellen
(1) Ort des Quellcodes
- Quellort: dedify-0.7.2\web\app\components\workflow\hooks\use-nodes-sync-draft.ts
- Ort des Quellcodes: dedify-0.7.2\web\service\workflow.ts
(2) Aktualisierung der Arbeitsabläufe
http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/draft.
(3) Aktualisierung des Front-End-Codes des Workflows
Aufgrund des React Flow-Frameworks, das im Front-End des Dify-Workflows verwendet wird, wird vermutet, dass POST-Operationen wie Hinzufügen, Löschen und Ändern ausgeführt werden können, wenn sich der Workflow ändert. Anhand der Protokolle in der Konsole des Back-Ends wurde festgestellt, dass der Aufruf derworkflows/entwurf?_token=
::
passieren (eine Rechnung oder Inspektion etc.)workflows/entwurf?_token=
Beim Durchsuchen des Front-End-Codes wurde nur eine Stelle gefunden, an der es verwendet wird, und das muss hier sein.
Da der POST-Vorgang durchgeführt wird, muss es einen Payload-Parameter geben, und der Workflow-Parameter befindet sich in dieser Datei.
Wenn die AbhängigkeitgetPostParams
Wenn eine Änderung eintritt, wird sie asynchron ausgeführt.syncWorkflowDraft(postParams)
.
(zeigt kausalen Zusammenhang an)syncWorkflowDraft(postParams)
Der eigentliche Aufruf ist POST. wie unten dargestellt:
(4) Zusammenfassung der Workflow-Funktionen
rechtsdify-0.7.2\web\service\workflow.ts
Die Funktionen lassen sich wie folgt zusammenfassen:
Seriennummer | Funktionsname | Funktion Funktion | Parameter und Erläuterungen |
---|---|---|---|
1 | fetchWorkflowDraft |
Holen Sie sich den Entwurf des Arbeitsablaufs. | url URL: String, die URL der Anfrage. |
2 | syncWorkflowDraft |
Workflow-Entwürfe synchronisieren. | url URL: String, die URL der Anfrage.Parameter : Objekt, die Parameter der Anfrage, die die Grafik , undMerkmale , undumwelt_variablen im Gesang antworten konversations_variablen . |
3 | fetchNodesDefaultConfigs |
Abrufen der Standardkonfiguration des Knotens. | url URL: String, die URL der Anfrage. |
4 | fetchWorkflowRunHistory |
Historie der Workflow-Läufe abrufen. | url URL: String, die URL der Anfrage. |
5 | fetcChatRunHistory |
Chat-Verlauf abrufen. | url URL: String, die URL der Anfrage. |
6 | singleNodeRun |
Führen Sie einen einzelnen Knoten aus. | appId : String, ID der Anwendung.nodeId ID: String, die ID des Knotens.Parameter Parameter der Anfrage: Objekt, Parameter der Anfrage. |
7 | getIterationSingleNodeRunUrl |
Ruft die URL des Iterationslaufs für einen einzelnen Knoten ab. | isChatFlow Boolescher Wert, der angibt, ob es sich um einen Chat-Stream handelt oder nicht.appId : String, ID der Anwendung.nodeId ID: String, die ID des Knotens. |
8 | publishWorkflow |
Buchen Sie einen Arbeitsablauf. | url URL: String, die URL der Anfrage. |
9 | fetchPublishedWorkflow |
Veröffentlichen Sie Workflows. | url URL: String, die URL der Anfrage. |
10 | stopWorkflowRun |
Beenden Sie die Ausführung des Workflows. | url URL: String, die URL der Anfrage. |
11 | fetchNodeDefault |
Abrufen der Standardkonfiguration des Knotens. | appId : String, ID der Anwendung.blockType Aufzählungswert: Aufzählungswert, Typ des Knotens.Abfrage : Objekt, optional, Abfrageparameter. |
12 | updateWorkflowDraftFromDSL |
Aktualisierung der Workflow-Entwürfe von DSL. | appId : String, ID der Anwendung.Daten : String, DSL-Daten. |
13 | fetchCurrentValueOfConversationVariable |
Ruft den aktuellen Wert der Sitzungsvariablen ab. | url URL: String, die URL der Anfrage.Parameter : Objekt, die Parameter der Anfrage, die die conversation_id . |
3. die Implementierung von Arbeitsabläufen
Hinweis auf dieProzessimplementierung von Chatflow-Operationen zum Erstellen, Aktualisieren, Ausführen und LöschenDer Abschnitt "Chatflow-Implementierung" in [6].
4. die Veröffentlichung von Arbeitsabläufen
(1) Ort des Quellcodes
- Ort des Quellcodes: dedify-0.7.2\api\controllers\console\app\workflow.py
- Ort des Quellcodes: dedify-0.7.2\api\services\workflow_service.py
- Quellort: dedify-0.7.2\api\events\event_handlers\update_app_dataset_join_when_app_published_workflow_updated.py
(2) Schnittstelle zur Veröffentlichung von Workflows
Dieser wird ausgeführt, wenn Sie auf Workflow veröffentlichen klicken.http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/publish
Schnittstelle.
Sie besteht hauptsächlich aus der Erstellung eines neuen Workflows und der Auslösung des App-Workflow-Ereignisses. Wie unten gezeigt:
(3) Erstellen eines neuen Workflow-Datensatzes
Dies besteht hauptsächlich darin, einen neuen Workflow-Datensatz zu erstellen, bei dem der Inhalt des Versionsfeldes 2024-09-07 09:11:25.894535 lautet, was darauf hinweist, dass der Workflow veröffentlicht wurde und nicht im Entwurfsstadium ist (der Workflow wurde noch nicht veröffentlicht und wird noch im Workflow Canvas getestet). Wie unten gezeigt:
(4) app_published_workflow_was_updated Ereignisimplementierung
@app_published_workflow_was_updated.connect
def handle(absender, **kwargs):
app = Absender
published_workflow = kwargs.get("published_workflow")
published_workflow = cast(Workflow, published_workflow)
dataset_ids = get_dataset_ids_from_workflow(published_workflow) # Abrufen der Datensatz-ID aus dem Workflow
app_dataset_joins = db.session.query(AppDatasetJoin).filter(AppDatasetJoin.app_id == app.id).all() # Abrufen von Anwendungsdatensatzzuordnungen
removed_dataset_ids = [] # Zum Speichern entfernter Datensatz-IDs verwenden
if not app_dataset_joins: # Wenn es keine app-Datensatz-Verknüpfungen gibt
added_dataset_ids = dataset_ids # Hinzufügen von Dataset-IDs
else: # Wenn es einen Anwendungsdatensatz-Zusammenschluss gibt
old_dataset_ids = set() # zum Speichern alter Datensatz-IDs
for app_dataset_join in app_dataset_joins: # Iterieren über app-Datensatz-Zuordnungen
old_dataset_ids.add(app_dataset_join.dataset_id) # Hinzufügen von Dataset-IDs
added_dataset_ids = dataset_ids - old_dataset_ids # Hinzufügen von Datensatz-IDs
removed_dataset_ids = old_dataset_ids - dataset_ids # Entfernen von Datensatz-IDs
if removed_dataset_ids: # wenn es eine entfernte Datensatz-ID gibt
for dataset_id in removed_dataset_ids: # Iterieren über entfernte Datensatz-IDs
db.session.query(AppDatasetJoin).filter(
AppDatasetJoin.app_id == app.id, AppDatasetJoin.dataset_id == dataset_id
).delete() # Löschen der Anwendungsdatensatz-Zuordnung
if added_dataset_ids: # Wenn hinzugefügte Dataset-IDs vorhanden sind
for dataset_id in added_dataset_ids: # Iterieren über die IDs der hinzugefügten Datensätze
app_dataset_join = AppDatasetJoin(app_id=app.id, dataset_id=dataset_id) # Erstellen der Anwendungsdatensatzzuordnung
db.session.add(app_dataset_join) # Hinzufügen einer Anwendungsdatensatzzuordnung
db.session.commit() # Festschreiben der Transaktion
Die Funktion dieses Codes ist es, die app_published_workflow_was_updated
Signal zur Aktualisierung der Assoziationsbeziehung zwischen einer Anwendung und einem Datensatz, wenn der veröffentlichte Workflow für diese Anwendung aktualisiert wird. Die einzelnen Schritte sind wie folgt:
- Abrufen des Anwendungsobjekts, das das Signal sendet
app
und aktualisierte Workflow-Objekteveröffentlichter_workflow
. - Aufforderungen
get_dataset_ids_from_workflow
Funktion, die die Datensatz-ID-Sammlung aus dem aktualisierten Arbeitsablauf extrahiertdatensatz_ids
. - Abfrage der Datenbank, um alle Daten der aktuellen Anwendung zu erhalten
AppDatasetJoin
Aufzeichnungen. - Berechnen Sie die hinzuzufügenden und zu löschenden Dataset-IDs:
- Wenn es keine aktuellen
AppDatasetJoin
Datensätze, dann müssen alle extrahierten Datensatz-IDs hinzugefügt werden. - Andernfalls berechnen Sie die hinzuzufügenden und zu löschenden Dataset-IDs.
- Wenn es keine aktuellen
- Wegfall der Notwendigkeit des Entfernens
AppDatasetJoin
Aufzeichnungen. - Neu hinzufügen
AppDatasetJoin
Aufzeichnungen. - Senden Sie eine Datenbanktransaktion.
(5) Die Rolle der Tabelle AppDatasetJoin
Die Tabelle AppDatasetJoin dient der Aufrechterhaltung einer Many-to-many-Beziehung zwischen einer Anwendung (App) und einem Datensatz (Dataset). Jeder Datensatz stellt die Verbindung zwischen einer Anwendung und einem Datensatz dar. Die spezifischen Felder sind wie folgt:
- id: Primärschlüssel zur eindeutigen Identifizierung eines Datensatzes.
- app_id: Der eindeutige Bezeichner der Anwendung.
- dataset_id: Eindeutiger Bezeichner des Datensatzes.
- created_at: Der Zeitstempel der Erstellung des Datensatzes.
- Mit dieser Tabelle ist es möglich, abzufragen, welche Datensätze mit einer bestimmten Anwendung verbunden sind oder mit welchen Anwendungen ein bestimmter Datensatz verbunden ist.
(6) Implementierung von get_dataset_ids_from_workflow()
def get_dataset_ids_from_workflow(published_workflow: Workflow) -> set: # Holt Datensatz-IDs aus dem Workflow
dataset_ids = set() # Dient zum Speichern von Datensatz-IDs
graph = published_workflow.graph_dict # Abrufen des Workflow-Graphen
if not graph: # Wenn kein Graph vorhanden ist
return dataset_ids # return empty set
nodes = graph.get("nodes", []) # holt die Knoten aus dem Graphen
# holt alle Wissensabfrageknoten # holt alle Wissensabfrageknoten
knowledge_retrieval_nodes = [
node for node in nodes if node.get("data", {}).get("type") == NodeType.KNOWLEDGE_RETRIEVAL.value
# Alle Wissensabfrageknoten holen
if not knowledge_retrieval_nodes: # Wenn keine Wissensabfrageknoten vorhanden sind
return dataset_ids # Gibt die leere Menge zurück.
for node in knowledge_retrieval_nodes: # Iteration über Wissensabfrageknoten
try: node_data = Knowledge_retrieval_nodes.
node_data = KnowledgeRetrievalNodeData(**node.get("data", {})) # Abrufen von Knotendaten
dataset_ids.update(node_data.dataset_ids) # Datensatz-IDs aktualisieren
except Exception as e: # Wenn es eine Ausnahme gibt
weiter
return dataset_ids
Die Hauptfunktion der Funktion get_dataset_ids_from_workflow besteht darin, die relevanten Datensatz-IDs aller Knowledge-Retrieval-Knoten aus einem gegebenen Workflow-Objekt zu extrahieren. Die Schritte sind wie folgt:
- Initialisierung einer leeren dataset_ids-Sammlung zur Speicherung von Datensatz-IDs.
- Abrufen der Graphstruktur des Workflow-Graphen.
- Gibt die leere dataset_ids-Sammlung zurück, wenn die Graphstruktur leer ist.
- Ermittelt alle Knoten im Graphen.
- Filtert alle Knoten des Typs KNOWLEDGE_RETRIEVAL knowledge_retrieval_nodes.
- Iterieren Sie über diese Wissensabrufknoten, extrahieren Sie ihre Datensatz-IDs und aktualisieren Sie sie in der Sammlung dataset_ids.
- Gibt eine Sammlung aller extrahierten Datensatz-IDs zurück.
5. andere Schnittstellen zum Workflow
Auf diesen Teil der Schnittstelle wird nicht näher eingegangen, da die API für die Workflow-Orchestrierung in Konversationsanwendungen bereits sehr genau beschrieben wurde.
Seriennummer | Interface-Name | Schnittstellenverbindung | Erklärte Schnittstellenfunktionen |
---|---|---|---|
1 | Eine Dialognachricht senden | POST /chat-messages | Erstellen Sie Sitzungsnachrichten, die Benutzereingaben senden oder Fragen stellen. |
2 | Hochladen von Dateien | POST /files/upload | Hochladen von Dateien (derzeit werden nur Bilder unterstützt) zur Verwendung beim Senden von Nachrichten. |
3 | aufhören zu antworten | POST /chat-messages/:task_id/stop | Beenden Sie das Streaming von Antworten (nur der Streaming-Modus wird unterstützt). |
4 | Nachrichten-Feedback (Likes) | POST /messages/:message_id/feedbacks | Nutzerfeedback und Likes auf Nachrichten zur Optimierung der Ausgabe. |
5 | Erhalten Sie eine Liste mit Fragenvorschlägen für die nächste Runde | GET /nachrichten/{nachricht_id}/vorgeschlagen | Lassen Sie sich eine Liste mit Fragenvorschlägen für die nächste Runde geben. |
6 | Sitzungsverlaufsmeldungen abrufen | GET /Nachrichten | Ruft den Verlauf der Nachrichtenprotokolle der Sitzung ab. |
7 | Sitzungsliste abrufen | GET /Gespräche | Ruft eine Liste der Sitzungen des aktuellen Benutzers ab. |
8 | Löschung einer Sitzung | DELETE /Unterhaltungen/:conversation_id | Löscht die angegebene Sitzung. |
9 | Sitzungsumbenennung | POST /Unterhaltungen/:conversation_id/name | Benennen Sie die Sitzung um. |
10 | Sprache-zu-Text | POST /audio-to-text | Konvertieren Sie Sprachdateien in Text. |
11 | Text-to-Speech | POST /text-to-audio | Text in Sprache umwandeln. |
12 | Abrufen von Informationen zur Anwendungskonfiguration | GET /Parameter | Abrufen von Konfigurationsinformationen für die Anwendung, z. B. Funktionsschalter, Eingabeparameter usw. |
13 | Abrufen von Anwendungs-Meta-Informationen | GET /meta | Holen Sie sich die Metainformationen der Anwendung, um das Werkzeugsymbol zu erhalten. |
bibliographie
[1] Sitzungsvariablen: https://docs.dify.ai/v/zh-hans/guides/workflow/variables
[2] Zuordnung der Variablen: https://docs.dify.ai/v/zh-hans/guides/workflow/node/variable-assignment
[3] Variable Aggregation: https://docs.dify.ai/v/zh-hans/guides/workflow/node/variable-assigner
[4] Reagieren Sie Flow Chinese Website: https://reactflow-cn.js.org/
[5] React Flow englische Website: https://reactflow.dev/
[6] Prozessimplementierung der Chatflow-Vorgänge Erstellen, Aktualisieren, Ausführen und Löschen: https://z0yrmerhgi8.feishu.cn/wiki/FFzxwdF4PijlhjkLUoecOv6Vn8a