File size: 3,997 Bytes
ef22617
 
 
 
 
 
 
 
9453220
2d433d5
791629f
30a90be
 
 
 
6246bb9
 
2ab051d
 
9002fdc
 
 
ef22617
 
57c2e56
 
ef22617
 
 
 
 
 
 
 
 
 
 
 
 
b785e1d
 
 
 
ef22617
c4b02b2
 
 
 
ef22617
 
 
096584a
ef22617
 
 
 
 
b785e1d
 
ef22617
 
3ffc848
b785e1d
3ffc848
ef22617
 
 
 
 
 
75cc68d
 
ef22617
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
096584a
 
ef22617
 
57c2e56
 
ef22617
 
6c2bdb4
 
 
 
 
ef22617
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { client } from "@gradio/client"

import { generateSeed } from "../utils/generateSeed.mts"
import { getValidNumber } from "./getValidNumber.mts"

// we don't use replicas yet, because it ain't easy to get their hostname
const instances: string[] = [
  `${process.env.VC_SDXL_SPACE_API_URL_1 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_2 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_3 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_4 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_5 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_6 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_7 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_8 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_9 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_10 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_11 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_12 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_13 || ""}`,
  `${process.env.VC_SDXL_SPACE_API_URL_14 || ""}`,

].filter(instance => instance?.length > 0)

const secretToken = `${process.env.VC_MICROSERVICE_SECRET_TOKEN || ""}`

export async function generateImageSDXLAsBase64(options: {
  positivePrompt: string;
  negativePrompt?: string;
  seed?: number;
  width?: number;
  height?: number;
  nbSteps?: number;
}) {

  const positivePrompt = options?.positivePrompt || ""
  if (!positivePrompt) {
    throw new Error("missing prompt")
  }

  // the negative prompt CAN be missing, since we use a trick
  // where we make the interface mandatory in the TS doc,
  // but browsers might send something partial
  const negativePrompt = options?.negativePrompt || ""
  
  // we treat 0 as meaning "random seed"
  const seed = (options?.seed ? options.seed : 0) || generateSeed()

  const width = getValidNumber(options?.width, 256, 1024, 512)
  const height = getValidNumber(options?.height, 256, 1024, 512)
  const nbSteps = getValidNumber(options?.nbSteps, 5, 100, 20)
  console.log("SEED:", seed)

  const instance = instances.shift()
  instances.push(instance)

  const positive = [

    // oh well.. is it too late to move this to the bottom?
    "beautiful",
    "intricate details",
    positivePrompt,

    "award winning",
    "high resolution"
  ].filter(word => word)
  .join(", ")

  const negative =  [
    negativePrompt,
    "watermark",
    "copyright",
    "blurry",
    // "artificial",
    // "cropped",
    "low quality",
    "ugly"
  ].filter(word => word)
  .join(", ")

  const api = await client(instance, {
    hf_token: `${process.env.VC_HF_API_TOKEN}` as any
  })

  
  const rawResponse = (await api.predict("/run", [		
    positive, // string  in 'Prompt' Textbox component		
    negative, // string  in 'Negative prompt' Textbox component		
    positive, // string  in 'Prompt 2' Textbox component		
    negative, // string  in 'Negative prompt 2' Textbox component		
    true, // boolean  in 'Use negative prompt' Checkbox component		
    false, // boolean  in 'Use prompt 2' Checkbox component		
    false, // boolean  in 'Use negative prompt 2' Checkbox component		
    seed, // number (numeric value between 0 and 2147483647) in 'Seed' Slider component		
    width, // number (numeric value between 256 and 1024) in 'Width' Slider component		
    height, // number (numeric value between 256 and 1024) in 'Height' Slider component		
    8, // number (numeric value between 1 and 20) in 'Guidance scale for base' Slider component		
    8, // number (numeric value between 1 and 20) in 'Guidance scale for refiner' Slider component		
    nbSteps, // number (numeric value between 10 and 100) in 'Number of inference steps for base' Slider component		
    nbSteps, // number (numeric value between 10 and 100) in 'Number of inference steps for refiner' Slider component		
    true, // boolean  in 'Apply refiner' Checkbox component,
    secretToken
  ])) as any
    
  const result = rawResponse?.data?.[0] as string
  if (!result?.length) {
    throw new Error(`the returned image was empty`)
  }
  return result
}