Dify의 독립형 외래 환자 안내 워크플로(채팅 흐름)
참고: 이 글에서는 Dify v0.7.2를 사용합니다.
이 채팅 플로우는 웹 또는 음성 대화를 통해 환자 데이터를 수집할 수 있는 외래 환자 안내용 챗봇을 구축하는 방법을 보여줍니다. 간단히 이해하면 환자 정보(연령, 성별, 증상)를 기반으로 환자에게 진료과를 추천하는 것입니다.
I. 워크플로 사고
1. 워크플로 스크린샷
외래 환자 오리엔테이션의 전체 워크플로 스크린샷은 아래와 같습니다:

2. 워크플로 의사 흐름도
외래 환자 안내 워크플로의 목적은 환자가 입력한 나이, 성별, 증상을 바탕으로 환자에게 진료과를 추천하는 것입니다. 첫 번째 대화에서는 환자가 정보의 전부 또는 일부를 한 번에 입력할 수 있으므로 '매개변수 추출기' 노드를 사용하여 환자의 첫 번째 입력에서 성별, 증상 및 나이를 추출합니다. 대화 변수 is_first_message는 "변수 할당" 노드에서 0으로 설정됩니다.
3. 문제 1
이후 대화를 진행하는 동안에는 한 번에 한 가지 유형의 필드 정보만 식별되지만, 환자가 여러 필드를 제공할 수 있으며 필드 식별 순서는 나이, 성별, 증상입니다.

4. 문제 2
환자 정보를 기반으로 이미 진료과가 추천된 경우 정보를 다시 입력하면 마지막 진료과가 추천됩니다. 부서 필드가 비어 있지 않으므로 직접 응답 프로세스를 따릅니다.

II. 세션 변수
세션 변수는 사용자 기본 설정, 대화 기록 등 LLM에 필요한 상황별 정보를 저장하는 데 사용됩니다. 읽기-쓰기 방식입니다. 세션 변수는 다자간 대화 시나리오를 지향하므로 세션 변수는 Chatflow 유형(Chat Assistant -> 워크플로우 오케스트레이션) 애플리케이션에서만 사용할 수 있습니다.
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\api\controllers\console\app\workflow.py
- 소스 코드 위치: dedify-0.7.2\api\서비시스\워크플로우_service.py
(2) 워크플로 작업 가져오기
http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/draft. 여기서 초안과 같은 초안은 워크플로 페이지에서 디버깅을 나타냅니다.

(3) 워크플로 구현 획득
워크플로는 워크플로 데이터 테이블에 레코드를 저장합니다. 이제 버전은 초안이며 워크플로가 게시될 때마다 해당 테이블에 레코드가 삽입됩니다. 아래 그림과 같습니다:

(4) 워크플로 데이터 구조
인터페이스에서 반환하는 워크플로 데이터 구조는 아래와 같습니다:
class Workflow(db.Model):
__tablename__ = '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)
_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\웹\앱\컴포넌트\워크플로우\후크\사용 노드 동기화 초안.ts
- 소스 코드 위치: dedify-0.7.2\웹\서비스\워크플로우.ts
(2) 워크플로 작업 업데이트
http://localhost:5001/console/api/apps/3c309371-54f6-4bfb-894a-4193b189ffa5/workflows/draft.

(3) 워크플로우 프런트엔드 코드 업데이트
Dify 워크플로우의 프론트엔드에서 사용되는 React Flow 프레임워크로 인해 워크플로우가 변경될 때 추가, 삭제, 변경과 같은 POST 작업이 수행되는 것으로 추측됩니다. 백엔드 콘솔의 로그를 통해, 백엔드 콘솔에서workflows/draft?_token=
::

통과(청구서 또는 검사 등)workflows/draft?_token=
프런트엔드 코드를 검색한 결과 이 코드를 사용할 수 있는 곳은 단 한 곳뿐이었으며, 그 곳은 바로 여기였습니다.

POST 작업이 수행되므로 오른쪽에 페이로드 매개변수가 있어야 하며 워크플로 매개변수는 해당 파일에서 찾을 수 있습니다.

종속성getPostParams
변경이 발생하면 비동기적으로 실행됩니다.syncWorkflowDraft(postParams)
.

(인과 관계 표시)syncWorkflowDraft(postParams)
실제 호출은 아래와 같이 POST:

(4) 워크플로우 기능 요약
오른쪽dify-0.7.2\web\service\workflow.ts
의 기능은 다음과 같이 요약됩니다:
일련 번호 | 함수 이름 | 기능 기능 | 매개변수 및 설명 |
---|---|---|---|
1 | fetchWorkflowDraft | 워크플로 초안을 받아보세요. | url : 문자열, 요청의 URL입니다. |
2 | syncWorkflowDraft | 워크플로 초안을 동기화합니다. | url : 문자열, 요청의 URL입니다.params 객체, 요청의 매개 변수, 요청에 포함된 graph 및features 및environment_variables 노래로 응답 conversation_variables . |
3 | fetchNodesDefaultConfigs | 노드의 기본 구성을 가져옵니다. | url : 문자열, 요청의 URL입니다. |
4 | fetchWorkflowRunHistory | 워크플로 실행 기록을 확인하세요. | url : 문자열, 요청의 URL입니다. |
5 | fetcChatRunHistory | 채팅 실행 기록을 확인하세요. | url : 문자열, 요청의 URL입니다. |
6 | singleNodeRun | 단일 노드를 실행합니다. | appId 문자열, 애플리케이션의 ID입니다.nodeId : 문자열, 노드의 ID입니다.params 객체, 요청의 매개변수입니다. |
7 | getIterationSingleNodeRunUrl | 단일 노드에 대해 실행된 반복의 URL을 가져옵니다. | isChatFlow 채팅 스트림인지 여부를 나타내는 부울 값입니다.appId 문자열, 애플리케이션의 ID입니다.nodeId : 문자열, 노드의 ID입니다. |
8 | publishWorkflow | 워크플로를 게시합니다. | url : 문자열, 요청의 URL입니다. |
9 | fetchPublishedWorkflow | 게시된 워크플로를 확인하세요. | url : 문자열, 요청의 URL입니다. |
10 | stopWorkflowRun | 워크플로 실행을 중지합니다. | url : 문자열, 요청의 URL입니다. |
11 | fetchNodeDefault | 노드의 기본 구성을 가져옵니다. | appId 문자열, 애플리케이션의 ID입니다.blockType : 열거형 값, 노드 유형입니다.query 객체, 선택 사항, 쿼리 매개변수. |
12 | updateWorkflowDraftFromDSL | DSL에서 워크플로 초안을 업데이트합니다. | appId 문자열, 애플리케이션의 ID입니다.data : 문자열, DSL 데이터. |
13 | fetchCurrentValueOfConversationVariable | 세션 변수의 현재 값을 가져옵니다. | url : 문자열, 요청의 URL입니다.params 객체, 요청의 매개 변수, 요청에 포함된 conversation_id . |
3. 워크플로 구현
참조Chatflow 생성, 업데이트, 실행 및 삭제 작업의 프로세스 구현6]의 "채팅 플로우 구현" 섹션을 참조하세요.
4. 워크플로 게시
(1) 소스 코드 위치
- 소스 코드 위치: dedify-0.7.2\api\controllers\console\app\workflow.py
- 소스 코드 위치: dedify-0.7.2\api\서비시스\워크플로우_service.py
- 소스 위치: dedify-0.7.2\api\events\event_handlers\update_app_dataset_join_when_app_published_workflow_updated.py
(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.connect
def handle(sender, **kwargs):
app = sender
published_workflow = kwargs.get("published_workflow")
published_workflow = cast(Workflow, 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
해당 애플리케이션에 대한 게시된 워크플로가 업데이트될 때 애플리케이션과 데이터 집합 간의 연결 관계를 업데이트하도록 신호를 보냅니다. 구체적인 단계는 다음과 같습니다:
- 신호를 전송하는 애플리케이션 객체를 가져옵니다.
app
및 업데이트된 워크플로우 개체published_workflow
. - 호출
get_dataset_ids_from_workflow
함수를 사용하여 업데이트된 워크플로우에서 데이터 세트 ID 컬렉션을 추출합니다.dataset_ids
. - 데이터베이스를 쿼리하여 현재 애플리케이션의 모든 애플리케이션의
AppDatasetJoin
기록. - 추가 및 삭제할 데이터 집합 ID를 계산합니다:
- 전류가 없는 경우
AppDatasetJoin
레코드가 있는 경우 추출된 모든 데이터 세트 ID를 추가해야 합니다. - 그렇지 않으면 추가 및 삭제할 데이터 집합 ID를 계산합니다.
- 전류가 없는 경우
- 제거할 필요성 삭제
AppDatasetJoin
기록. - 새 항목 추가
AppDatasetJoin
기록. - 데이터베이스 트랜잭션을 제출합니다.
(5) 앱데이터셋조인 테이블의 역할
AppDatasetJoin 테이블은 애플리케이션(앱)과 데이터 집합(데이터세트) 간의 다대다 관계를 유지하는 역할을 합니다. 각 레코드는 애플리케이션과 데이터 세트의 연결을 나타냅니다. 구체적인 필드는 다음과 같습니다:
- 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: # 如果没有图
return dataset_ids # 返回空集合
nodes = graph.get("nodes", []) # 获取图中的节点
# fetch all knowledge retrieval 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 = 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 컬렉션을 초기화합니다.
- 워크플로 그래프의 그래프 구조를 가져옵니다.
- 그래프 구조가 비어 있는 경우 빈 데이터셋_아이디 컬렉션을 반환합니다.
- 그래프에 있는 모든 노드를 가져옵니다.
- KNOWLEDGE_RETRIEVAL 지식_검색_노드 유형의 모든 노드를 필터링합니다.
- 이러한 지식 검색 노드를 반복하여 데이터 세트 ID를 추출한 다음 데이터 세트_ids 컬렉션에서 업데이트합니다.
- 추출된 모든 데이터 세트 ID의 컬렉션을 반환합니다.
5. 워크플로 기타 인터페이스
인터페이스의 이 부분은 자세히 설명하지 않겠으며, 워크플로 오케스트레이션 대화형 애플리케이션 API는 매우 명확하게 설명되어 있습니다.
일련 번호 | 인터페이스 이름 | 인터페이스 링크 | 인터페이스 기능 설명 |
---|---|---|---|
1 | 대화 메시지 보내기 | POST /chat-messages | 사용자 입력을 보내거나 질문을 하는 세션 메시지를 만듭니다. |
2 | 파일 업로드 | POST /파일/업로드 | 메시지를 보낼 때 사용할 파일(현재는 이미지만 지원됨)을 업로드합니다. |
3 | 응답 중지 | POST /chat-messages/:task_id/stop | 스트리밍 응답 중지(스트리밍 모드만 지원됨). |
4 | 메시지 피드백(좋아요) | POST /메시지/:메시지_id/feedbacks | 사용자 피드백과 메시지에 대한 좋아요를 통해 결과물을 최적화할 수 있습니다. |
5 | 다음 라운드를 위한 추천 질문 목록 보기 | GET /메시지/{메시지_id}/suggested | 다음 라운드를 위한 추천 질문 목록을 확인하세요. |
6 | 세션 기록 메시지 가져오기 | GET /메시지 | 세션의 메시지 로그 기록을 가져옵니다. |
7 | 세션 목록 가져오기 | GET /대화 | 현재 사용자의 세션 목록을 가져옵니다. |
8 | 세션 삭제하기 | 대화 삭제 /대화/:대화_id | 지정된 세션을 삭제합니다. |
9 | 세션 이름 바꾸기 | POST /대화/:대화_id/이름 | 세션 이름을 바꿉니다. |
10 | 음성-텍스트 변환 | POST /오디오-텍스트 변환 | 음성 파일을 텍스트로 변환하세요. |
11 | 텍스트 음성 변환 | POST /text-to-audio | 텍스트를 음성으로 변환합니다. |
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] React Flow 중국어 웹사이트: https://reactflow-cn.js.org/[5] 리액트 플로우 영문 웹사이트: https://reactflow.dev/[6] Chatflow 생성, 업데이트, 실행 및 삭제 작업의 프로세스 구현: https://z0yrmerhgi8.feishu.cn/wiki/FFzxwdF4PijlhjkLUoecOv6Vn8a© 저작권 정책
기사 저작권 AI 공유 서클 모두 무단 복제하지 마세요.
관련 문서
댓글 없음...