From 36f3b2e387ab339ab2246eef019b0f1ad2659e9c Mon Sep 17 00:00:00 2001 From: admin9webs Date: Thu, 27 Aug 2026 15:39:17 +0800 Subject: [PATCH] =?UTF-8?q?Bridge=20=E5=9B=BE=E5=83=8F=E7=94=9F=E6=88=90?= =?UTF-8?q?=E6=8A=80=E8=83=BD:=20gs2-sdxl=20(GS-2=20SDXL)=20+=20gs1-flux?= =?UTF-8?q?=20(GS-1=20FLUX)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 +++++++ gs1-flux/SKILL.md | 85 +++++++++++++++++++++++++ gs1-flux/scripts/flux_txt2img.py | 35 ++++++++++ gs2-sdxl/SKILL.md | 106 +++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+) create mode 100644 README.md create mode 100644 gs1-flux/SKILL.md create mode 100644 gs1-flux/scripts/flux_txt2img.py create mode 100644 gs2-sdxl/SKILL.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..17e8cea --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Bridge VM 图像生成技能 + +给 9Webs 全部 Bridge 虚拟机使用的图像生成技能。 + +## 包含技能 + +- **gs2-sdxl** — GS-2 (192.168.9.116) Forge SDXL base 1.0 双实例 (:7861/:7862),快速出图 +- **gs1-flux** — GS-1 (192.168.9.113) ComfyUI FLUX.1-dev (GGUF Q5_K_S),高质量出图 + +## 安装 + +```bash +mkdir -p ~/.hermes/skills && cd ~/.hermes/skills +git clone http://gitea.9webs.online:3000/admin9webs/bridge-skills.git +# 或仅复制所需技能目录 +cp -r bridge-skills/gs2-sdxl bridge-skills/gs1-flux ~/.hermes/skills/ +``` + +## 使用策略 + +- 快速草图/批量配图 → `gs2-sdxl` (steps 24-30, 约几秒/张) +- 最终成品/复杂构图 → `gs1-flux` (steps 20, 约 100 秒/张) + +> 部署日期: 2026-08-27,已在全部 23 台 Bridge 上安装验证。 diff --git a/gs1-flux/SKILL.md b/gs1-flux/SKILL.md new file mode 100644 index 0000000..c3dfb69 --- /dev/null +++ b/gs1-flux/SKILL.md @@ -0,0 +1,85 @@ +--- +name: gs1-flux +description: 调用 GS-1 (192.168.9.113) ComfyUI FLUX.1-dev 图像生成 — txt2img/img2img/填充。GGUF Q5_K_S 模型,V100 双卡。触发:FLUX 出图、高质量图片、复杂构图、产品图、图生图、局部重绘、inpaint。 +version: 1.0.0 +author: 9Webs +license: internal +platforms: [linux] +triggers: + - FLUX + - flux1 + - 高质量出图 + - ComfyUI + - inpaint + - 局部重绘 + - 图生图 +--- + +# GS-1 FLUX.1-dev 图像生成 (ComfyUI API) + +用 GS-1 的 ComfyUI + FLUX.1-dev (GGUF Q5_K_S) 生成高质量图片。直连 `192.168.9.113:8188` 即可。 + +## 服务拓扑 + +| 项 | 值 | +|----|----| +| 节点 | GS-1 = 192.168.9.113 (2× Tesla V100-SXM2-16GB) | +| ComfyUI | `http://192.168.9.113:8188` (v0.25.0) | +| UNet | `flux1-dev-Q5_K_S.gguf` (GGUF, V100 无 bf16 用 Q5) | +| 填充模型 | `flux1-fill-dev-Q5_K_S.gguf` (inpaint/局部重绘) | +| CLIP | `t5-v1_1-xxl-encoder-Q5_K_M.gguf` + `clip_l.safetensors` (type=flux) | +| VAE | `ae.safetensors` | + +## 调用方式 (ComfyUI REST API) + +1. **POST `/prompt`** 提交 API 格式工作流 (见 workflows/flux_txt2img.json),返回 `prompt_id` +2. **轮询 `GET /history/{prompt_id}`** 直到 `status.completed == true` +3. **取图 `GET /view?filename=&type=output`** 下载 PNG + +### 参考参数 (已实测) + +- **steps 20** (18-28 均可;GGUF 量化,步数低会糊) +- **cfg 1.0** (FLUX 用 cfg≈1 + guidance;标准 KSampler 下 cfg 1.0 即可) +- **1024×1024** (FLUX 原生;V100 16GB 上限约 1024,超高会 OOM) +- **sampler `euler` / scheduler `simple`**, seed 可固定 +- **耗时约 100-120 秒/张** (V100 无 flash-attention;首次调用含模型加载更慢) + +### 脚本 (scripts/flux_txt2img.py) + +```bash +python3 ~/.hermes/skills/gs1-flux/scripts/flux_txt2img.py "prompt here" [--steps 20] [--seed -1] +# 输出: /tmp/flux_out/flux_*.png +``` + +## 健康检查 + +```bash +curl -s http://192.168.9.113:8188/system_stats | head -c 200 # 返回 JSON = 正常 +curl -s http://192.168.9.113:8188/object_info/UnetLoaderGGUF | grep -o 'flux1[^"]*' # 模型在位 +curl -s http://192.168.9.113:8188/queue | python3 -c "import json,sys; d=json.load(sys.stdin); print('running:', len(d['queue_running']), 'pending:', len(d['queue_pending']))" +``` + +## 排障 + +- **提交 400** → 工作流节点错误,读 `node_errors` 详情 (常见: CLIPTextEncodeFlux 需 clip_l/t5xxl/guidance 三个输入) +- **长时间不出图** → 查队列 `queue` 是否堆积;单实例顺序执行,批量任务排队 +- **OOM** → 降到 768×768 或减少 batch +- **换风格/复杂提示** → FLUX 对提示词敏感,直接写详细英文描述;负向提示基本不需要 + +## 服务端排障 + +```bash +sshpass -p 'Tt123456!' ssh admin9webs@192.168.9.113 'systemctl --user status comfyui* --no-pager | head -20' +``` + +## 陷阱 + +1. **Q5_K_S 量化**:图片质量略低于 fp8/bf16,但 V100 无 bf16 只能跑 GGUF;复杂文字/人脸注意检查。 +2. **每次约 2 分钟**:批量任务要轮询串行,不要并发提交同实例。 +3. **图片在 ComfyUI output 目录** (`~/ComfyUI/output/`),推荐客户端用 /view 下载,不依赖服务端目录。 +4. **Flux Fill** (flux1-fill-dev) 用于局部重绘/inpaint,需配合 mask 工作流。 + +## 相关 + +- SDXL 出图用 `gs2-sdxl` 技能 (GS-2 :7861/:7862,快但质量略低) +- 配图策略: 快速草图用 SDXL,最终成品/复杂构图用 FLUX diff --git a/gs1-flux/scripts/flux_txt2img.py b/gs1-flux/scripts/flux_txt2img.py new file mode 100644 index 0000000..4f16485 --- /dev/null +++ b/gs1-flux/scripts/flux_txt2img.py @@ -0,0 +1,35 @@ +import json, urllib.request, urllib.error, time +BASE = 'http://192.168.9.113:8188' +wf = { + "1": {"class_type": "UnetLoaderGGUF", "inputs": {"unet_name": "flux1-dev-Q5_K_S.gguf"}}, + "2": {"class_type": "DualCLIPLoaderGGUF", "inputs": {"clip_name1": "t5-v1_1-xxl-encoder-Q5_K_M.gguf", "clip_name2": "clip_l.safetensors", "type": "flux"}}, + "3": {"class_type": "VAELoader", "inputs": {"vae_name": "ae.safetensors"}}, + "4": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["2", 0], "text": "a red apple on a wooden table, product photo, studio lighting"}}, + "5": {"class_type": "CLIPTextEncode", "inputs": {"clip": ["2", 0], "text": "blurry, low quality"}}, + "6": {"class_type": "EmptyLatentImage", "inputs": {"width": 1024, "height": 1024, "batch_size": 1}}, + "7": {"class_type": "KSampler", "inputs": {"model": ["1", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["6", 0], "seed": 12345, "steps": 20, "cfg": 1.0, "sampler_name": "euler", "scheduler": "simple", "denoise": 1.0}}, + "8": {"class_type": "VAEDecode", "inputs": {"samples": ["7", 0], "vae": ["3", 0]}}, + "9": {"class_type": "SaveImage", "inputs": {"filename_prefix": "flux_test", "images": ["8", 0]}}, +} +req = urllib.request.Request(BASE + '/prompt', data=json.dumps({"prompt": wf}).encode(), headers={'Content-Type': 'application/json'}) +try: + r = json.loads(urllib.request.urlopen(req, timeout=30).read()) + pid = r.get('prompt_id') + print('prompt_id:', pid, '| node_errors:', r.get('node_errors')) + if not pid: raise SystemExit(1) + for i in range(60): + time.sleep(5) + try: + h = json.loads(urllib.request.urlopen(BASE + '/history/' + pid, timeout=10).read()) + except Exception: continue + if pid in h: + st = h[pid].get('status', {}) + if st.get('completed') or st.get('status_str') == 'success': + for nid, o in h[pid].get('outputs', {}).items(): + for img in o.get('images', []): + print('出图:', img.get('filename'), '| 节点', nid) + print('FLUX 生成成功!'); raise SystemExit(0) + elif st.get('status_str') == 'error': + print('FLUX 错误:', json.dumps(st)[:500]); raise SystemExit(1) +except urllib.error.HTTPError as e: + print('HTTP', e.code, e.read().decode()[:600]) diff --git a/gs2-sdxl/SKILL.md b/gs2-sdxl/SKILL.md new file mode 100644 index 0000000..c09ad35 --- /dev/null +++ b/gs2-sdxl/SKILL.md @@ -0,0 +1,106 @@ +--- +name: gs2-sdxl +description: 调用 GS-2 (192.168.9.116) Forge SDXL base 1.0 图像生成 API — txt2img/img2img,双实例 :7861/:7862 轮询。触发:生成图片/产品图/配图/场景图,SDXL 出图,文生图,图生图。 +--- + +# GS-2 SDXL 图像生成 (Forge API) + +用 GS-2 的 SDXL base 1.0 生成图片。本机(任意节点)直连 `192.168.9.116` 即可,无需代理。 + +## 服务拓扑 + +| 项 | 值 | +|----|----| +| 节点 | GS-2 = 192.168.9.116 (2× RTX 3060 Laptop 12GB) | +| 实例1 | `http://192.168.9.116:7861` (GPU0, systemd `forge-sdxl.service`) | +| 实例2 | `http://192.168.9.116:7862` (GPU1, systemd `forge-sdxl-2.service`) | +| 模型 | `sd_xl_base_1.0.safetensors` — **完整 SDXL base,不是 turbo!** + `sdxl_vae.safetensors` | +| API | 标准 A1111/Forge: `/sdapi/v1/txt2img`, `/sdapi/v1/img2img`, `/sdapi/v1/sd-models` | + +双实例轮询:优先 7861,失败/繁忙换 7862。 + +## 推荐参数 (SDXL base 完整版,2026-08-27 实测) + +⚠️ 模型是完整 base(非 turbo),**steps 需要 24-30**,2 步会出糊图。 + +| 参数 | 值 | +|------|----| +| steps | 24-30 (出图约 10-25s@1024²) | +| cfg_scale | 6-7.5 | +| width/height | 768~1024 (SDXL 原生尺寸),默认 1024×1024 或 832×1216 | +| sampler_name | `euler_a` 或 `dpmpp_2m_karras` | +| negative_prompt | `lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, cropped, worst quality, low quality, jpeg artifacts, signature, watermark, username, blurry` | +| 并发 | 单实例同时只处理 1 个请求 (12GB VRAM),批量任务轮询双实例 | + +## 调用方式 (已验证) + +### curl txt2img + +```bash +curl -s -X POST http://192.168.9.116:7861/sdapi/v1/txt2img \ + -H 'Content-Type: application/json' \ + -d '{"prompt":"a cute corgi wearing sunglasses, studio photo","negative_prompt":"lowres, blurry, watermark","steps":24,"cfg_scale":7,"width":1024,"height":1024,"sampler_name":"euler_a","seed":-1}' +``` + +### Python (urllib,无 curl 依赖) + +```python +import json, base64, urllib.request + +def sdxl_txt2img(prompt, negative_prompt="", steps=24, cfg=7.0, + w=1024, h=1024, sampler="euler_a", seed=-1, port=7861): + req = urllib.request.Request( + f"http://192.168.9.116:{port}/sdapi/v1/txt2img", + data=json.dumps({"prompt": prompt, "negative_prompt": negative_prompt, + "steps": steps, "cfg_scale": cfg, "width": w, "height": h, + "sampler_name": sampler, "seed": seed}).encode(), + headers={"Content-Type": "application/json"}) + with urllib.request.urlopen(req, timeout=180) as r: + data = json.loads(r.read()) + return base64.b64decode(data["images"][0]) # PNG bytes + +# 保存 +png = sdxl_txt2img("a red apple on a wooden table, product photo", port=7861) +open("/tmp/apple.png", "wb").write(png) +``` + +### img2img (重绘/换风格/局部重绘) + +```bash +curl -s -X POST http://192.168.9.116:7862/sdapi/v1/img2img \ + -H 'Content-Type: application/json' \ + -d '{"init_images":[""],"prompt":"same product, luxury studio background","denoising_strength":0.6,"steps":24,"cfg_scale":7,"width":1024,"height":1024,"sampler_name":"euler_a"}' +``` + +要点: +- `init_images` 传 **base64 编码的 PNG 字符串**(无 data: 前缀) +- `denoising_strength` 0.5-0.7 重绘风格,0.3 以下基本保留原图,0.8+ 大改 + +## 健康检查 + +```bash +# 模型列表 (返回 JSON 即服务正常) +curl -s http://192.168.9.116:7861/sdapi/v1/sd-models +# 实例间轮询: 7861 → 7862 +``` + +## 服务端排障 (需要时) + +```bash +sshpass -p 'Tt123456!' ssh admin9webs@192.168.9.116 \ + 'export XDG_RUNTIME_DIR=/run/user/$(id -u); systemctl --user status forge-sdxl forge-sdxl-2 --no-pager | head -30' +# 重启: systemctl --user restart forge-sdxl forge-sdxl-2 +``` + +## 陷阱 + +1. **是 base 模型不是 turbo**:steps 必须 24+,2-4 步出糊图/灰图。 +2. **双实例各绑一张卡**:单实例并发第 2 个请求会排队或 OOM,批量任务轮询两个端口。 +3. **12GB VRAM 上限**:1024×1024 稳定;超 1024 或加 ControlNet 可能 OOM,降 768。 +4. **seed=-1 随机**,固定 seed 可复现。 +5. 服务端 outputs 目录在 GS-2 (`~/stable-diffusion-webui-forge/outputs/`),但**推荐客户端解析 base64 直接存本地**,不依赖服务端目录。 + +## 相关 + +- 部署/版本排障细节见本地 `gpustack-cluster` 技能 (GS-2 Forge 双实例 systemd 章节) +- FlairGS (AppServer-105 :7870) 也调这两个实例:FORGE_STEPS=24, CFG=7.5, denoise=0.70 (产品图场景生成)