e761074fb9
CI / docker (push) Successful in 3m46s
Merge model_id/alias in the image provider UI, and ensure ComfyUI never receives seed -1 after cloneMap type coercion. Co-authored-by: Cursor <cursoragent@cursor.com>
98 lines
2.1 KiB
Go
98 lines
2.1 KiB
Go
package prediction
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
)
|
|
|
|
func BuildPrompt(workflowJSON string, binding InputBinding, input map[string]any) (map[string]any, error) {
|
|
var workflow map[string]any
|
|
if err := json.Unmarshal([]byte(workflowJSON), &workflow); err != nil {
|
|
return nil, fmt.Errorf("invalid workflow: %w", err)
|
|
}
|
|
prompt := deepCopyMap(workflow)
|
|
for name, target := range binding {
|
|
if target == nil || target.Node == "" || target.Field == "" {
|
|
continue
|
|
}
|
|
val, ok := input[name]
|
|
if !ok {
|
|
continue
|
|
}
|
|
if name == "seed" {
|
|
val = resolveSeed(val)
|
|
}
|
|
node, ok := prompt[target.Node].(map[string]any)
|
|
if !ok {
|
|
return nil, fmt.Errorf("node %s not found", target.Node)
|
|
}
|
|
inputs, ok := node["inputs"].(map[string]any)
|
|
if !ok {
|
|
return nil, fmt.Errorf("node %s inputs missing", target.Node)
|
|
}
|
|
inputs[target.Field] = val
|
|
}
|
|
sanitizeSamplerSeeds(prompt)
|
|
return prompt, nil
|
|
}
|
|
|
|
// resolveSeed maps seed < 0 (random) to a non-negative value ComfyUI accepts.
|
|
func resolveSeed(val any) any {
|
|
n, ok := seedAsInt64(val)
|
|
if !ok || n >= 0 {
|
|
return val
|
|
}
|
|
r, err := rand.Int(rand.Reader, big.NewInt(1<<31-1))
|
|
if err != nil {
|
|
return int(0)
|
|
}
|
|
return int(r.Int64())
|
|
}
|
|
|
|
func seedAsInt64(v any) (int64, bool) {
|
|
switch n := v.(type) {
|
|
case int:
|
|
return int64(n), true
|
|
case int64:
|
|
return n, true
|
|
case float64:
|
|
return int64(n), true
|
|
case json.Number:
|
|
i, err := n.Int64()
|
|
return i, err == nil
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
func sanitizeSamplerSeeds(prompt map[string]any) {
|
|
seedFields := []string{"seed", "noise_seed"}
|
|
for _, raw := range prompt {
|
|
node, ok := raw.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if class, _ := node["class_type"].(string); class != "KSampler" {
|
|
continue
|
|
}
|
|
inputs, ok := node["inputs"].(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
for _, field := range seedFields {
|
|
if v, ok := inputs[field]; ok {
|
|
inputs[field] = resolveSeed(v)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func deepCopyMap(src map[string]any) map[string]any {
|
|
b, _ := json.Marshal(src)
|
|
var dst map[string]any
|
|
_ = json.Unmarshal(b, &dst)
|
|
return dst
|
|
}
|