180 lines
6.1 KiB
Python
180 lines
6.1 KiB
Python
"""导入产品推荐 Workflow 到 Dify/BaoDan。
|
||
|
||
使用方式:
|
||
python scripts/import_workflow.py [--base-url URL] [--token TOKEN]
|
||
|
||
参数:
|
||
--base-url Dify API 地址(默认 http://localhost:5001)
|
||
--token Dify Console API Token(登录后从浏览器 Cookie 或 API 管理页面获取)
|
||
|
||
导入完成后,还需要在 Dify 后台:
|
||
1. 打开导入的"产品推荐方案生成" Workflow
|
||
2. 绑定知识库(节点3:知识库检索 → 选择已创建的知识库)
|
||
3. 确认 LLM 模型配置(节点4:方案生成 → 选择 DeepSeek)
|
||
4. 点击"发布"
|
||
5. 在"访问 API"页面创建 API Key,填入 .env 的 BAODAN_WORKFLOW_API_KEY
|
||
"""
|
||
import argparse
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
import requests
|
||
|
||
|
||
def find_existing_app(base_url: str, token: str) -> str | None:
|
||
"""查找已存在的同名 Workflow 应用。"""
|
||
headers = {
|
||
"Authorization": f"Bearer {token}",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
page = 1
|
||
while True:
|
||
resp = requests.get(
|
||
f"{base_url}/console/api/apps",
|
||
params={"page": page, "limit": 100},
|
||
headers=headers,
|
||
timeout=30
|
||
)
|
||
if resp.status_code != 200:
|
||
break
|
||
|
||
data = resp.json()
|
||
apps = data.get("data", [])
|
||
if not apps:
|
||
break
|
||
|
||
for app in apps:
|
||
if app.get("name") == "产品推荐方案生成" and app.get("mode") == "workflow":
|
||
return app.get("id")
|
||
|
||
if len(apps) < 100:
|
||
break
|
||
page += 1
|
||
|
||
return None
|
||
|
||
|
||
def import_workflow(base_url: str, token: str, yaml_path: str) -> dict:
|
||
"""通过 Dify Console API 导入 Workflow DSL(如果不存在则复用)。"""
|
||
headers = {
|
||
"Authorization": f"Bearer {token}",
|
||
"Content-Type": "application/json",
|
||
}
|
||
|
||
# 先检查是否已存在同名应用
|
||
existing_app_id = find_existing_app(base_url, token)
|
||
if existing_app_id:
|
||
print(f"♻️ 复用已存在的应用,App ID: {existing_app_id}")
|
||
return {"app_id": existing_app_id, "status": "reused"}
|
||
|
||
url = f"{base_url}/console/api/apps/imports"
|
||
|
||
with open(yaml_path, "r", encoding="utf-8") as f:
|
||
yaml_content = f.read()
|
||
|
||
payload = {
|
||
"mode": "yaml-content",
|
||
"yaml_content": yaml_content,
|
||
"name": "产品推荐方案生成",
|
||
"description": "根据客户信息和知识库检索结果,生成基础/均衡/全面三套保险推荐方案",
|
||
"icon_type": "emoji",
|
||
"icon": "\U0001F3E6",
|
||
"icon_background": "#E4FBCC",
|
||
}
|
||
|
||
print(f"正在导入 Workflow 到 {base_url} ...")
|
||
resp = requests.post(url, json=payload, headers=headers, timeout=30)
|
||
result = resp.json()
|
||
|
||
if resp.status_code == 200:
|
||
print(f"✓ 导入成功!")
|
||
print(f" App ID: {result.get('app_id', 'N/A')}")
|
||
print(f" App Mode: {result.get('app_mode', 'N/A')}")
|
||
print(f" Status: {result.get('status', 'N/A')}")
|
||
return result
|
||
elif resp.status_code == 202:
|
||
# 版本不匹配,需要确认
|
||
import_id = result.get("id")
|
||
print(f"⚠ 需要确认导入(版本不匹配)")
|
||
print(f" Import ID: {import_id}")
|
||
print(f" 当前版本: {result.get('current_dsl_version')}")
|
||
print(f" 导入版本: {result.get('imported_dsl_version')}")
|
||
|
||
confirm_url = f"{base_url}/console/api/apps/imports/{import_id}/confirm"
|
||
confirm_resp = requests.post(confirm_url, headers=headers, timeout=30)
|
||
confirm_result = confirm_resp.json()
|
||
|
||
if confirm_resp.status_code == 200:
|
||
print(f"✓ 确认导入成功!")
|
||
print(f" App ID: {confirm_result.get('app_id', 'N/A')}")
|
||
return confirm_result
|
||
else:
|
||
print(f"✗ 确认失败: {confirm_result}")
|
||
return confirm_result
|
||
else:
|
||
print(f"✗ 导入失败 (HTTP {resp.status_code})")
|
||
print(f" 错误: {result.get('message', result)}")
|
||
return result
|
||
|
||
|
||
def get_console_token_interactive(base_url: str) -> str:
|
||
"""交互式获取 Console Token。"""
|
||
print()
|
||
print("=" * 60)
|
||
print(" 获取 Dify Console Token 的方法:")
|
||
print("=" * 60)
|
||
print()
|
||
print(" 方法1:浏览器登录 Dify 后台 → F12 → Application → Cookies")
|
||
print(" → 复制 dify_session 或 access_token 的值")
|
||
print()
|
||
print(" 方法2:使用 API 密钥管理页面生成的 Personal Access Token")
|
||
print()
|
||
token = input(" 请输入 Token: ").strip()
|
||
return token
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="导入产品推荐 Workflow 到 Dify/BaoDan")
|
||
parser.add_argument("--base-url", default="http://localhost:5001", help="Dify API 地址")
|
||
parser.add_argument("--token", default="", help="Console API Token")
|
||
parser.add_argument("--yaml", default="deploy/workflow_recommend.yml", help="DSL YAML 文件路径")
|
||
args = parser.parse_args()
|
||
|
||
# 确认 YAML 文件存在
|
||
yaml_path = Path(args.yaml)
|
||
if not yaml_path.exists():
|
||
print(f"✗ 找不到 YAML 文件: {yaml_path}")
|
||
sys.exit(1)
|
||
|
||
# 获取 Token
|
||
token = args.token
|
||
if not token:
|
||
token = get_console_token_interactive(args.base_url)
|
||
if not token:
|
||
print("✗ 未提供 Token,退出")
|
||
sys.exit(1)
|
||
|
||
# 导入
|
||
result = import_workflow(args.base_url, token, str(yaml_path))
|
||
|
||
if result.get("app_id"):
|
||
print()
|
||
print("=" * 60)
|
||
print(" 后续步骤:")
|
||
print("=" * 60)
|
||
print()
|
||
print(f" 1. 打开 Dify 后台 → 找到「产品推荐方案生成」应用")
|
||
print(f" 2. 进入 Workflow 编辑器 → 点击「知识库检索」节点")
|
||
print(f" → 替换 dataset_ids 为实际知识库 ID")
|
||
print(f" 3. 点击「方案生成」节点 → 确认模型为 deepseek-chat")
|
||
print(f" 4. 点击右上角「发布」按钮")
|
||
print(f" 5. 进入「访问 API」页面 → 创建 API Key")
|
||
print(f" 6. 将 API Key 填入 .env 的 BAODAN_WORKFLOW_API_KEY")
|
||
print()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|