| name | astrbot-remote-comfyui |
| description | 将 AstrBot 连接到远程 ComfyUI 服务器 — SSH 隧道、systemd 自启、插件选型、工作流配置 |
AstrBot → 远程 ComfyUI 集成
适用场景
AstrBot 装在 WSL/本地,ComfyUI 在远程服务器(无公网 IP,通过 FRP/SSH 访问)。
方案
1. SSH 隧道(核心)
ssh -p <port> -o BatchMode=yes -o ConnectTimeout=5 user@host "echo OK"
ssh -p <port> -N -L 8188:127.0.0.1:8188 user@host
2. systemd 服务
参照 AstrBot 已有服务的格式:
[Unit]
Description=SSH Tunnel to ComfyUI Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=po
ExecStart=/usr/bin/ssh -p <port> -N -L 8188:127.0.0.1:8188 \
-o ServerAliveInterval=30 -o ExitOnForwardFailure=yes user@host
ExecStop=/usr/bin/pkill -f "ssh.*<port>.*8188"
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now comfyui-tunnel
前提:SSH 密钥无密码(BatchMode=yes 验证)
3. AstrBot 插件配置
server_ip = 127.0.0.1:8188(指向本地转发端口)
4. 插件选型对比
| 插件 | LLM 触发 | 工作流方式 | 评价 |
|---|
| cjxzdzh/astrbot_plugin_comfyui | LLM Tool 调用 | 文件名约定 工作流名+文本N+图片M+视频K.json + Simple String 节点 | 架构干净,但需改 ComfyUI 节点 |
| lumingya/astrbot_plugin_comfyui_pro | 正则提取 <draw> 标签 | 填 Input/Output 节点 ID | 社区最火,兼容性好 |
| tjc/astrbot_plugin_ComfyUI_promax | 指令前缀 | 预置 SD 工作流 | 功能最全但最重 |
5. 坑
- cg-use-everywhere v7 移除了 Simple String:需要 pin 到 v6。
git checkout f2a0c34...(最后一个有 Simple String 的提交)
- promax 插件只读
models/checkpoints/,不认 diffusion_models/:Flux 等新架构模型需要自定义 workflow,插件内置工作流用不了
- SSH 隧道需要
ServerAliveInterval:否则长时间不用会断开
- AstrBot 需要重载插件两次 + 刷新浏览器(插件缓存机制)
6. 运维
- 检查隧道状态:
systemctl status comfyui-tunnel
- 检查 ComfyUI 可达:
curl http://127.0.0.1:8188/system_stats
7. 三个集成路径(plugin vs skill vs 直调)
AstrBot 调 ComfyUI 有三条互不重叠的路径,先问用户走哪条:
| 路径 | 落地形式 | 谁执行 curl | LLM 介入方式 | 何时选 |
|---|
| A. AstrBot 插件(plugin marketplace) | data/plugins/astrbot_plugin_*/main.py 注册 LLM tool | 插件 Python | tool 装饰器 + schema(强制) | 用户要现成的、生图成产品功能、跨工作流统一 |
B. AstrBot skill(data/skills/<slug>/) | SKILL.md 文档 + 可选 _meta.json + 可选 Python | LLM 自己照文档 curl | 纯文档型无需 schema | 用户要"LLM 学会去调",schema 写起来累,工作流少(1-3 个) |
| C. 直调:AstrBot 不参与 | 用户手动 curl /prompt + 取图 | 人 | 不适用 | 调试用、接口验证 |
B 是最少配置的路线:用户已经在 data/skills/comfyui-anima-t2i/ 维护了一个本地 skill(_meta.json + SKILL.md),LLM 读 SKILL.md 直接 curl,不写 Python、不注册 tool、不写 schema。LTM tool 的 LLM "skill 模式" 由 AstrBot v4 的 simple_subplugin / skill loader 启用,前提是 skill 目录存在合法 SKILL.md。
_meta.json schema(AstrBot 识别 skill 的强依赖):
{"ownerId": "local", "slug": "comfyui-anima-t2i", "version": "1.0.0", "publishedAt": 1751972400000}
四字段缺一不可:缺 slug → 加载失败;缺 version → WebUI 标红;缺 publishedAt → 当成本地暂存(不显示在市场)。
决策树 — 用户说"加 ComfyUI 能力"或"给 AstrBot 接 ComfyUI":
- 先查
data/skills/ 看有没有现成 skill(ls data/skills/comfy*)
- 有 → 直接复用,不要绕去 plugin marketplace
- 没 → 若工作流固定 1-3 个,写 skill(B 路径)比装插件快 10 倍
- 工作流多、要产品化功能 → A 路径,挑
cjxzdzh/astrbot_plugin_comfyui(架构最干净)或 WalkerZJH/astrbot_plugin_easy_comfyui(最简单)
易错:
- 用户说"找一下 skill"时不主动跳到 plugin marketplace——"skill"在 AstrBot 生态里特指
data/skills/ 下的东西,跟 AstrBot Plugin Marketplace(plugins.astrbot.app)是两回事
- 跟"Hermes skill 市场"(
~/.hermes/skills/、skills.sh)也完全不同——Hermes skill 是给 Hermes Agent 自己用的;AstrBot skill 是给 AstrBot 的 LLM 用的。混淆就闹笑话
7.1 复杂 + 演化型工具表面:选 self-evolving skill,绕过插件
触发条件(同时满足):
- 工具 API/model 频繁变(ComfyUI 加新模型架构、SVN 增新云 API...)
- 用户嫌"每次有新东西都得重写插件"或"这插件太死板了"
- 工作流数量有限(1-N 个,每个用户能维护 json 文件),不需要产品级功能
走法 — 让 skill 自我演化(not 框架,是约定):
- 一个主
SKILL.md(< 200 行),教 LLM 怎么调用这个工具的通用范式(不绑死任何具体工作流/模型)
- 旁边三个数据目录(不在 skill 内,在 AstrBot 数据根):
data/<slug>_workflows/<name>/ # 用户维护:workflow_api.json + README.md
data/<slug>_eval/<workflow>.md # 回归 prompt 集,每个工作流 3-5 条
data/<slug>_journal/YYYY-MM-DD-N.md # LLM 每次跑完追加:prompt + 选择 + 结果 + 学到的
- 演化触发写入 SKILL.md:journal ≥ 5 条 / 同类失败 ≥ 2 次 / 用户显式吐槽
- 演化流程:LLM 自反思 → 提 patch(add/delete/replace 三种,少于 SKILL.md 20%)→ 在 eval 上回归 → 涨分落地,不涨拒绝
- 受 SkillOpt 启发,但不装 SkillOpt 框架:没有 trainer、没有 schema、没有 optimizer backend 抽象——LLM 自己就是 optimizer
为什么不是 plugin:
- plugin 写完就冻结;新模型要 fork、重写、发布
- plugin 的
@llm_tool 装饰器每个 tool 写一次 schema,工具多起来成本爆炸
- plugin 路径把 LLM 决策权偷走(每条 tool 是固定签名),skill 路径让 LLM 自己挑工作流、自己决定参数
详细 recipe:references/skill-self-evolve-pattern.md(ComfyUI 是第一个案例,模式可迁移到任何"AI 调外部工具"的场景——AstrBot 学 Git CLI、ffmpeg pipeline、SQL、任意外部 SaaS API)
写 SKILL.md 时的 5 个坑(jq 不在 PATH、SaveImage 节点别硬编码、polling history 500 兜底、object_info 常空、POST /prompt 的 number 队列位): references/comfyui-skill-md-pitfalls.md,端到端第一次跑通时撞到,下次写同类 SKILL.md 先看。
反例:用户说"我要一个能让我朋友也装的生图插件、跨 QQ 群都用"——这种要走 A 路径 plugin + 发布到 marketplace,self-evolve skill 是私人的,不能给别人用
8. 故障排查:图生成成功但效果不对 / "不接提示词"
用户报错"插件不接提示词"时,90% 的排查时间应花在"到底是哪一截挂了"。三个怀疑对象,按从服务端 → 客户端顺序排除:
A. ComfyUI 服务端(先排除)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8188/
ssh -i ~/.ssh/id_ed25519 -p <port> user@host \
"sudo -n journalctl -u comfyui -n 100 --no-pager"
关键诊断接口:/history/{prompt_id} — 返回完整 prompt JSON(包括用户输入的 text 节点值),不像 /history 列表那样被 truncation。
PID=$(curl -s "http://127.0.0.1:8188/history?max_items=1" | \
python3 -c "import sys,json; print(list(json.load(sys.stdin).keys())[0])")
curl -s "http://127.0.0.1:8188/history/$PID" | \
python3 -c "import sys,json; d=json.load(sys.stdin); pj=d[list(d.keys())[0]]['prompt'][2]; print(json.dumps(pj, indent=2, ensure_ascii=False))"
看到 node 11 (CLIPTextEncode) 的 inputs.text 字段是用户实际输入的中文(或翻译后的英文),就证明 promax 端正确传过去了。这步把"提示词没到 ComfyUI"的可能性直接排除。
B. AstrBot 端:plugin 配置位置(v4)
AstrBot v4 的 plugin 配置文件不在 data/plugins/<plugin>/config.json,在:
/home/po/astrbot/data/config/astrbot_plugin_<plugin>_config.json
常见 promax 配置坑:
| 配置项 | 默认 | 坑 |
|---|
enable_translation | false | 关闭时中文 prompt 直接喂给 Qwen3 0.6B,会出图但内容不达预期(Anima 等日漫风格必须用英文 Danbooru 标签) |
enable_fake_forward | true | 配 fake_forward_qq="" 时转发失效,图可能没发到群 |
enable_auto_recall | false | 配 true 的话图发出去 N 秒后撤回,用户没看到 |
daily_download_limit | 1 | 用户一天超限后任务静默丢弃 |
group_whitelist | [] | 空数组 = 全部拒绝,插件不会响应 |
修法:先用 enable_translation: true 让 promax 调 LLM 翻中文 → Danbooru 标签;或让用户直接发英文 Danbooru 标签(Anima 出图质量最高)。
C. 客户端:日志死路
AstrBot v4 默认 log_file_enable: false。systemd 拉起时 stdout 进 socket / journalctl,data/astrbot.log 不会更新——里面是几个月前的尸体日志。
journalctl --user -u astrbot -f
D. 提示词注入路径(promax workflow 模式)
读懂 _inject_user_params / build_workflow(workflow_engine.py:1202-1243):
- 节点参数按
node_id:param_name 格式(如 11:text)查表
- 用户消息中没有
xxx:yyy 模式的部分 → 走 LLM 翻译 → 注入到 text 节点
- 所以
anima 抽烟的白毛猫娘 → 翻译成 Danbooru → 注入 node 11 的 text 字段
参考:references/comfyui-diagnostics.md 收录了完整的"问题在 ComfyUI 还是 AstrBot"诊断 recipe 和具体错误样例。references/skill-vs-plugin-discovery.md 收录三条集成路径的识别口诀、AstrBot skill 合规最小公约数、以及从废插件迁 skill 的最小步骤。