A model whose profiles run engine comfyui is placed on a node's card like any other, and makes pictures there. ComfyUI asks for no key, so the agent starts it behind llmgw comfyui-gate: ComfyUI on the loopback, the gate on the replica's port demanding the replica's key and letting through only what the router asks — queueing, waiting, fetching, cancelling. The gate answers the agent's /health and /v1/models, shows ComfyUI the fetched weights by their own names, and gives each replica its own base directory. ComfyUI runs as the gate's child, so its card memory is the replica's. A node offers the engine when agent.yaml names its ComfyUI (engines.comfyui.dir). The model's comfyui: block names the workflow and, for a source that is a set of files, the checkpoint. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
52 lines
2.0 KiB
Go
52 lines
2.0 KiB
Go
package catalog
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func comfyModel(source string, c *ComfyUI, profiles ...Profile) Model {
|
|
if len(profiles) == 0 {
|
|
profiles = []Profile{{Name: "gpu", Engine: EngineComfyUI, GPUClass: "6000-24g", TP: 1}}
|
|
}
|
|
return Model{Name: "flux", Source: source, ComfyUI: c, Profiles: profiles}
|
|
}
|
|
|
|
func TestAComfyUIModelMakesPicturesFromItsSourcesFile(t *testing.T) {
|
|
cat, err := New([]Model{comfyModel("hf:Comfy-Org/flux1-schnell/flux1-schnell-fp8.safetensors", nil)})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
m, _ := cat.Resolve("flux")
|
|
if !m.MakesImages() || !m.ServesComfyUI() {
|
|
t.Error("a ComfyUI model does not say it makes pictures")
|
|
}
|
|
if w, ckpt := m.ComfyWorkflow(); w != "" || ckpt != "flux1-schnell-fp8.safetensors" {
|
|
t.Errorf("workflow %q, checkpoint %q", w, ckpt)
|
|
}
|
|
}
|
|
|
|
func TestAComfyUIModelIsRefusedWhatItCannotDo(t *testing.T) {
|
|
for name, c := range map[string]struct {
|
|
m Model
|
|
want string
|
|
}{
|
|
"a set without a checkpoint": {comfyModel("https://mirror/flux-dev/v1/", nil), "comfyui.checkpoint"},
|
|
"an unknown workflow": {comfyModel("/w/f.safetensors", &ComfyUI{Workflow: "sdxl"}), "no built-in workflow"},
|
|
"mixed engines": {comfyModel("/w/f.safetensors", nil,
|
|
Profile{Name: "a", Engine: EngineComfyUI, GPUClass: "6000-24g", TP: 1},
|
|
Profile{Name: "b", Engine: "vllm", GPUClass: "6000-24g", TP: 1}), "every profile"},
|
|
"comfyui settings without the engine": {Model{Name: "x", Source: "/w/x", ComfyUI: &ComfyUI{},
|
|
Profiles: []Profile{{Name: "a", Engine: "vllm", GPUClass: "6000-24g", TP: 1}}}, "engine comfyui"},
|
|
"no card": {comfyModel("/w/f.safetensors", nil, Profile{Name: "a", Engine: EngineComfyUI, TP: 1}), "gpu_class"},
|
|
} {
|
|
if _, err := New([]Model{c.m}); err == nil || !strings.Contains(err.Error(), c.want) {
|
|
t.Errorf("%s: %v", name, err)
|
|
}
|
|
}
|
|
ok := comfyModel("https://mirror/flux-dev/v1/", &ComfyUI{Workflow: "flux-dev", Checkpoint: "flux1-dev-fp8.safetensors"})
|
|
if _, err := New([]Model{ok}); err != nil {
|
|
t.Errorf("a set with its checkpoint named was refused: %v", err)
|
|
}
|
|
}
|