Files
story/docs/dify-workflows.md
T

74 lines
8.3 KiB
Markdown
Raw Normal View History

# 聊天整理与图文回忆录工作流
线上使用自托管 Dify 1.17.1。入口为 <https://82.157.201.114/apps>,使用独立管理员登录。账号密码保存在服务器 `/opt/story-dify/admin-private.json`,不要提交到代码仓库。
## 两个已发布的工作流
- 聊天整理:<https://82.157.201.114/app/984b4de8-9814-4f41-85da-988f43307de9/workflow>。
- 图文回忆录:<https://82.157.201.114/app/fbda0f7e-d24b-4f8c-b932-a7167b992f68/workflow>。
聊天流程:接收任务 → 读取聊天与已有故事 → 分类并逐事件拆分 → 独立审核今天实际事件 → 检查原话证据 → 同一事件比较新增信息 → 返回新增、更新、重复的统计。分类与日常审核分别选择模型,默认均为火山 `deepseek-v4-1-flash-260910`。
回忆录流程:读取该长者全部可用故事 → `doubao-seed-evolving` 一次编写整本 → 核验来源、章节与日期 → 平台先保存并显示正文 → `doubao-seedream-5-0-pro-260628` 逐章配图(并行 3 章)→ 汇总并保存。所有故事必须各出现一次,保持来源日期;插画失败仍保留正文。
选择模型节点,在右侧“设置”的“模型”菜单中选择,提示词在输入变量 `prompt` 中编辑。四个可配置节点如下:
| 工作流 | 节点 | 默认模型 |
| --- | --- | --- |
| 聊天整理 | 分类与故事拆分 | DeepSeek V4.1 Flash |
| 聊天整理 | 审核今天实际事件 | DeepSeek V4.1 Flash |
| 图文回忆录 | 全部故事统一编写整本 | Doubao Seed Evolving |
| 图文回忆录 | 绘制该章情景插画 | Seedream 5.0 Pro |
文本菜单包含 DeepSeek V4.1 Flash、Doubao Seed Evolving、Seed 2.1 Pro、Seed 2.1 Lite。整本写作菜单仅列支持 JSON Schema 的三个 Doubao 模型。插画菜单包含 Seedream 5.0 Pro、5.0 Flash 和 4.0。选择“自定义模型 / 接入点”时,在下面填写火山模型 ID 或 `ep-` 接入点;写作模型须支持 JSON Schema,插画接入点须为图像生成。模型权限和费用沿用当前火山账户,菜单不会切换密钥或服务地址。选错模型或调用失败会明确报错,不会悄悄改回默认模型。
草稿自动保存,先“测试运行”,确认效果后点击右上角“发布”。发布影响后续线上生成任务,已在执行的任务继续使用开始时的工作流版本,同一任务的重复步骤不会因为菜单变化再次调用模型。开始节点的两个输入由平台自动传入。Dify 中手动测试且留空时,使用虚构示例,不写入长者账号。手动测试仍会调用实际火山模型。
画布的“日志”可查看真实任务执行进度、各节点耗时、实际模型 ID 与错误。回忆录正文内记录 `workflow_run_id`,便于对应 Dify 日志。四个模型步骤是原生自定义 API 工具节点,其余步骤保留 HTTP 请求、校验代码及原生迭代节点。
## 数据与授权
Go 后端继续负责登录、账号隔离、授权、来源版本检查、故事合并和数据库保存。真实聊天与整本内容只在私有模型桥接服务的短期内存中传递;Dify 输入和输出只有临时任务编号、执行凭证及统计。上下文任务结束即删除,最长 20 分钟。桥接服务没有数据库凭证,没有公开端口。
火山密钥、两个 Dify 工作流密钥和桥接服务密钥均通过服务器只读秘密文件加载。不要把长者原文或长期密钥粘贴到工作流变量、提示词或导出文件中。
## 配置与维护
API/Worker 配置:
```dotenv
DIFY_ENABLED=true
DIFY_BASE_URL=http://story-dify-nginx/v1
DIFY_BRIDGE_URL=http://model-bridge:8188
DIFY_BRIDGE_SECRET_FILE=/run/secrets/voice-runtime/dify-bridge-secret
DIFY_EXTRACTION_API_KEY_FILE=/run/secrets/voice-runtime/dify-extract-api-key
DIFY_MEMOIR_API_KEY_FILE=/run/secrets/voice-runtime/dify-memoir-api-key
```
默认 `DIFY_ENABLED=false`,使用原有生成器。启用时缺少凭证会在启动时明确失败。
桥接服务源码为 `cmd/workflow-model-bridge`、`internal/workflowbridge`,连接器为 `internal/dify`。模型名称从节点传入,缺省时兼容旧工作流的原模型。Dify 自托管目录为 `/opt/story-dify`,已解析的私密 Compose 配置为 `compose.private.json`。服务配置、数据库密码及所有私密文件均禁止提交。
原生工具提供者名称为“故事平台 · 分步骤模型”,由 `scripts/dify-model-tools.py` 管理。Dify 1.17.1 的 OpenAPI 解析器会忽略 enum 和参数 form,因此安装脚本在原生 `ApiToolBundle` 元数据中配置 SELECT 菜单;API 和运行时使用同一份元数据。不要直接在工具页重新保存 schema,否则菜单参数会被解析回普通文本;变更菜单应更新安装脚本并重新生成元数据。字符串凭证参数使用 `mixed` 变量模板,避免 Dify 编辑器在更换模型时清空字符串的 `variable` 绑定。
API 与 Worker 的 `API_TOOL_DEFAULT_READ_TIMEOUT=660` 必须同时保留,否则原生工具默认 60 秒会中断整本写作。2026-10-07 模型菜单版本的桥接镜像为 `story-workflow-model-bridge:1.1.0-model-menu`,配置、桥接二进制和原工作流备份在 `/opt/story-dify/model-menu-backup-20261007`,回滚时应同时恢复原发布工作流指针和原草稿。
```sh
docker compose -p story-dify -f /opt/story-dify/compose.private.json ps
docker compose -p story-dify -f /opt/story-dify/compose.private.json logs --tail 100 api worker model-bridge
```
平台 API、Worker、gateway 与 Dify nginx、模型桥接服务共用外部网络 `story-workflows`。Dify nginx 的自身 API/Web 上游使用独立别名 `story-dify-api` 和 `story-dify-web`,避免与故事平台服务名冲突。gateway 的 Dify 路由配置有 `/opt/story-dify/gateway-before-dify.conf` 备份。后续重建 gateway 必须保留这个外部网络和 Dify 路由;本次平台发布的冻结 Compose 配置已包含该网络。
Dify 1.17.1 的登录跳转和会话刷新经过 `/auth/refresh`,gateway 必须将该路径精确代理到 `story-dify-nginx`。漏配时,访问 `/apps` 会误进入故事平台家庭登录页。不要代理整个 `/auth/` 前缀,故事平台自身使用 `/auth/callback` 处理 OIDC 回调。2026-10-07 已补齐精确路由,并同步正在挂载的配置、当前发布配置与 `/opt/story-dify/gateway-dify-routes.conf`;修复前备份位于 `/opt/story-dify/gateway-auth-refresh-backup-20261007T003108Z`。修改挂载文件应保留 inode,再执行 `nginx -t` 和 `nginx -s reload`。
Dify 与 sandbox 的执行密钥必须一致;Celery broker URL 必须使用实际 Redis 密码。仅健康探针通过不足以确认工作流可执行。整本模型单次请求允许 480 秒,整体重试最多 600 秒。整本编写节点读超时为 660 秒,Squid 的请求/读超时为 12 分钟、连接存活为 20 分钟,避免默认两分钟代理限制中断长正文。
## 可复现的画布与验证
`python scripts/build-dify-workflows.py --provider-id PROVIDER_UUID` 从应用提示词生成带菜单的 `deploy/dify/workflows/*.yml` 和工具 OpenAPI 定义。先在目标工作空间安装原生提供者,再传入其 UUID;当前工作空间为 `5210ee18-44c1-47f3-a36e-4996e2403d50`。不传 UUID 则生成兼容旧版桥接服务的 HTTP 画布。这些文件是合法 YAML 的 JSON 写法,Dify 0.7.0 DSL 可直接导入,不含长期密钥。可以从 Dify 导出当前已修改的 DSL 作为新版本。部署迁移应使用 `dify-model-tools.py stage APP_ID... --backup-dir PRIVATE_PATH`,保留实际草稿里的提示词;验证后再 `publish`,发生并发修改时哈希校验会拒绝发布。
验证覆盖:Dify 流式执行和中断停止、私有上下文授权和删除、并发步骤避免重复调用、完整故事目录成书、插画欠费保留正文、空故事数组传输,以及数据库中正文先显示、来源变更失效、撤回授权后拒绝读取。实际 Dify 画布另用隔离模型夹具执行两个完整流程,其中回忆录测试包含三个章节的原生并行迭代;测试应用和容器结束后删除。真实火山模型调用另行验证。
回忆录模型的 JSON 格式兼容:根据 schema 补齐缺失的段落数组左括号,并处理引号和换行的转义。修复保持原始段落、故事编号和日期,之后仍执行完整来源校验;被长度截断的模型回复不会被修复后接收。