docstr: Create Disco Diffusion artworks and save the result into a DocumentArray.
  
  :param text_prompts: Phrase, sentence, or string of words and phrases describing what the image should look like.  The words will be analyzed by the AI and will guide the diffusion process toward the image(s) you describe. These can include commas and weights to adjust the relative importance of each element.  E.g. "A beautiful painting of a singular lighthouse, shining its light across a tumultuous sea of blood by greg rutkowski and thomas kinkade, Trending on artstation."Notice that this prompt loosely follows a structure: [subject], [prepositional details], [setting], [meta modifiers and artist]; this is a good starting point for your experiments. Developing text prompts takes practice and experience, and is not the subject of this guide.  If you are a beginner to writing text prompts, a good place to start is on a simple AI art app like Night Cafe, starry ai or WOMBO prior to using DD, to get a feel for how text gets translated into images by GAN tools.  These other apps use different technologies, but many of the same principles apply.
  :param style: Image style, such as oil paintings, if specified, style will be used to construct prompts.
  :param artist: Artist style, if specified, style will be used to construct prompts.
  :param width_height: Desired final image size, in pixels. You can have a square, wide, or tall image, but each edge length should be set to a multiple of 64px, and a minimum of 512px on the default CLIP model setting.  If you forget to use multiples of 64px in your dimensions, DD will adjust the dimensions of your image to make it so.
  :param batch_size: This variable sets the number of still images you want SD to create for each prompt.
  :param num_inference_steps: The number of inference steps.
  :param guidance_scale: Increase the adherence to the conditional signal which in this case is text as well as overall sample quality.
  :param enable_fp16: Whether to use float16.
  :param use_gpu: whether to use gpu or not.
  :param output_dir: Output directory.
  :return: a DocumentArray object that has `n_batches` Documents
docstr_tok: ["Create","Disco","Diffusion","artworks","and","save","the","result","into","a","DocumentArray",".",":","param","text_prompts",":","Phrase",",","sentence",",","or","string","of","words","and","phrases","describing","what","the","image","should","look","like",".","The","words","will","be","analyzed","by","the","AI","and","will","guide","the","diffusion","process","toward","the","image","(","s",")","you","describe",".","These","can","include","commas","and","weights","to","adjust","the","relative","importance","of","each","element",".","E.g",".","``","A","beautiful","painting","of","a","singular","lighthouse",",","shining","its","light","across","a","tumultuous","sea","of","blood","by","greg","rutkowski","and","thomas","kinkade",",","Trending","on","artstation",".","``","Notice","that","this","prompt","loosely","follows","a","structure",":","[","subject","]",",","[","prepositional","details","]",",","[","setting","]",",","[","meta","modifiers","and","artist","]",";","this","is","a","good","starting","point","for","your","experiments",".","Developing","text","prompts","takes","practice","and","experience",",","and","is","not","the","subject","of","this","guide",".","If","you","are","a","beginner","to","writing","text","prompts",",","a","good","place","to","start","is","on","a","simple","AI","art","app","like","Night","Cafe",",","starry","ai","or","WOMBO","prior","to","using","DD",",","to","get","a","feel","for","how","text","gets","translated","into","images","by","GAN","tools",".","These","other","apps","use","different","technologies",",","but","many","of","the","same","principles","apply",".",":","param","style",":","Image","style",",","such","as","oil","paintings",",","if","specified",",","style","will","be","used","to","construct","prompts",".",":","param","artist",":","Artist","style",",","if","specified",",","style","will","be","used","to","construct","prompts",".",":","param","width_height",":","Desired","final","image","size",",","in","pixels",".","You","can","have","a","square",",","wide",",","or","tall","image",",","but","each","edge","length","should","be","set","to","a","multiple","of","64px",",","and","a","minimum","of","512px","on","the","default","CLIP","model","setting",".","If","you","forget","to","use","multiples","of","64px","in","your","dimensions",",","DD","will","adjust","the","dimensions","of","your","image","to","make","it","so",".",":","param","batch_size",":","This","variable","sets","the","number","of","still","images","you","want","SD","to","create","for","each","prompt",".",":","param","num_inference_steps",":","The","number","of","inference","steps",".",":","param","guidance_scale",":","Increase","the","adherence","to","the","conditional","signal","which","in","this","case","is","text","as","well","as","overall","sample","quality",".",":","param","enable_fp16",":","Whether","to","use","float16",".",":","param","use_gpu",":","whether","to","use","gpu","or","not",".",":","param","output_dir",":","Output","directory",".",":","return",":","a","DocumentArray","object","that","has","`","n_batches","`","Documents"]
code: def generate_image(
      self,
      text_prompts,
      style: Optional[str] = None,
      artist: Optional[str] = None,
      width_height: Optional[List[int]] = [512, 512],
      batch_size: Optional[int] = 1,
      num_inference_steps=50,
      guidance_scale=7.5,
      enable_fp16=False,
      seed=None,
      display_rate=5,
      use_gpu=True,
      output_dir: Optional[str] = "stable_diffusion_out",
  ):
      """
      Create Disco Diffusion artworks and save the result into a DocumentArray.
  
      :param text_prompts: Phrase, sentence, or string of words and phrases describing what the image should look like.  The words will be analyzed by the AI and will guide the diffusion process toward the image(s) you describe. These can include commas and weights to adjust the relative importance of each element.  E.g. "A beautiful painting of a singular lighthouse, shining its light across a tumultuous sea of blood by greg rutkowski and thomas kinkade, Trending on artstation."Notice that this prompt loosely follows a structure: [subject], [prepositional details], [setting], [meta modifiers and artist]; this is a good starting point for your experiments. Developing text prompts takes practice and experience, and is not the subject of this guide.  If you are a beginner to writing text prompts, a good place to start is on a simple AI art app like Night Cafe, starry ai or WOMBO prior to using DD, to get a feel for how text gets translated into images by GAN tools.  These other apps use different technologies, but many of the same principles apply.
      :param style: Image style, such as oil paintings, if specified, style will be used to construct prompts.
      :param artist: Artist style, if specified, style will be used to construct prompts.
      :param width_height: Desired final image size, in pixels. You can have a square, wide, or tall image, but each edge length should be set to a multiple of 64px, and a minimum of 512px on the default CLIP model setting.  If you forget to use multiples of 64px in your dimensions, DD will adjust the dimensions of your image to make it so.
      :param batch_size: This variable sets the number of still images you want SD to create for each prompt.
      :param num_inference_steps: The number of inference steps.
      :param guidance_scale: Increase the adherence to the conditional signal which in this case is text as well as overall sample quality.
      :param enable_fp16: Whether to use float16.
      :param use_gpu: whether to use gpu or not.
      :param output_dir: Output directory.
      :return: a DocumentArray object that has `n_batches` Documents
      """
      if seed:
          np.random.seed(seed)
          random.seed(seed)
          paddle.seed(seed)
  
      if use_gpu:
          try:
              _places = os.environ.get("CUDA_VISIBLE_DEVICES", None)
              if _places:
                  paddle.device.set_device("gpu:{}".format(0))
          except:
              raise RuntimeError(
                  "Environment Variable CUDA_VISIBLE_DEVICES is not set correctly. If you wanna use gpu, please set CUDA_VISIBLE_DEVICES as cuda_device_id."
              )
      else:
          paddle.device.set_device("cpu")
      paddle.disable_static()
  
      if not os.path.exists(output_dir):
          os.makedirs(output_dir, exist_ok=True)
  
      if isinstance(text_prompts, str):
          text_prompts = text_prompts.rstrip(",.，。")
          if style is not None:
              text_prompts += ",{}".format(style)
          if artist is not None:
              text_prompts += ",{},trending on artstation".format(
                  artist
              )
          text_prompts = [text_prompts]
      elif isinstance(text_prompts, list):
          for i, prompt in enumerate(
              text_prompts
          ):  # different from dd here, dd can have multiple prompts for one image with weight.
              text_prompts[i] = prompt.rstrip(",.，。")
              if style is not None:
                  text_prompts[i] += ",{}".format(style)
              if artist is not None:
                  text_prompts[
                      i
                  ] += ",{},trending on artstation".format(artist)
  
      width, height = width_height
      da_batches = DocumentArray()
  
      for prompt in text_prompts:
          d = Document(tags={"prompt": prompt})
          da_batches.append(d)
          for i in range(batch_size):
              d.chunks.append(
                  Document(tags={"prompt": prompt, "image idx": i})
              )
          d.chunks.append(
              Document(tags={"prompt": prompt, "image idx": "merged"})
          )
          with paddle.amp.auto_cast(enable=enable_fp16, level="O2"):
              prompts = [prompt] * batch_size
              text_input = tokenize(prompts)
              text_embeddings = self.text_encoder(text_input)
              uncond_input = tokenize([""] * batch_size)
              uncond_embeddings = self.text_encoder(uncond_input)
              text_embeddings = paddle.concat(
                  [uncond_embeddings, text_embeddings]
              )
  
              latents = paddle.randn(
                  (
                      batch_size,
                      self.unet.in_channels,
                      height // 8,
                      width // 8,
                  ),
              )
              if isinstance(self.scheduler, LMSDiscreteScheduler):
                  latents = latents * self.scheduler.sigmas[0]
  
              self.scheduler.set_timesteps(num_inference_steps)
              for i, t in tqdm(enumerate(self.scheduler.timesteps)):
                  # expand the latents if we are doing classifier-free guidance to avoid doing two forward passes.
                  latent_model_input = paddle.concat([latents] * 2)
  
                  if isinstance(self.scheduler, LMSDiscreteScheduler):
                      sigma = self.scheduler.sigmas[i]
                      latent_model_input = latent_model_input / (
                          (sigma**2 + 1) ** 0.5
                      )
  
                  # predict the noise residual
                  noise_pred = self.unet(
                      latent_model_input,
                      t,
                      encoder_hidden_states=text_embeddings,
                  )["sample"]
  
                  # perform guidance
                  noise_pred_uncond, noise_pred_text = noise_pred.chunk(
                      2
                  )
                  noise_pred = noise_pred_uncond + guidance_scale * (
                      noise_pred_text - noise_pred_uncond
                  )
  
                  # compute the previous noisy sample x_t -> x_t-1
                  if isinstance(self.scheduler, LMSDiscreteScheduler):
                      latents = self.scheduler.step(
                          noise_pred, i, latents
                      )["prev_sample"]
                  else:
                      latents = self.scheduler.step(
                          noise_pred, t, latents
                      )["prev_sample"]
                  if i % display_rate == 0:
                      # vae decode
                      images = self.vae.decode(1 / 0.18215 * latents)
                      images = (images / 2 + 0.5).clip(0, 1)
                      merge_image = (
                          images.cpu()
                          .transpose([2, 0, 3, 1])
                          .flatten(1, 2)
                          .numpy()
                      )
                      merge_image = (
                          (merge_image * 255).round().astype(np.uint8)
                      )
                      merge_image = Image.fromarray(merge_image)
                      merge_image.save(
                          os.path.join(
                              output_dir, f"{prompt}-progress.png"
                          )
                      )
                      c = Document(tags={"step": i, "prompt": prompt})
                      c.load_pil_image_to_datauri(merge_image)
                      d.chunks[-1].chunks.append(c)
                      display.clear_output(wait=True)
                      display.display(merge_image)
                      images = (
                          images.cpu().transpose([0, 2, 3, 1]).numpy()
                      )
                      images = (images * 255).round().astype(np.uint8)
                      for j in range(images.shape[0]):
                          image = Image.fromarray(images[j])
                          c = Document(
                              tags={"step": i, "prompt": prompt}
                          )
                          c.load_pil_image_to_datauri(image)
                          d.chunks[j].chunks.append(c)
  
              # vae decode
              images = self.vae.decode(1 / 0.18215 * latents)
              images = (images / 2 + 0.5).clip(0, 1)
              merge_image = (
                  images.cpu()
                  .transpose([2, 0, 3, 1])
                  .flatten(1, 2)
                  .numpy()
              )
              merge_image = (merge_image * 255).round().astype(np.uint8)
              merge_image = Image.fromarray(merge_image)
              merge_image.save(
                  os.path.join(output_dir, f"{prompt}-merge.png")
              )
              display.clear_output(wait=True)
              display.display(merge_image)
              d.load_pil_image_to_datauri(merge_image)
              d.chunks[-1].load_pil_image_to_datauri(merge_image)
              images = images.cpu().transpose([0, 2, 3, 1]).numpy()
              images = (images * 255).round().astype(np.uint8)
              for j in range(images.shape[0]):
                  image = Image.fromarray(images[j])
                  image.save(
                      os.path.join(
                          output_dir, f"{prompt}-image-{j}.png"
                      )
                  )
                  d.chunks[j].load_pil_image_to_datauri(image)
      return da_batches
  
imports: import argparse
  import ast
  import os
  import random
  import sys
  from functools import partial
  from typing import List
  from typing import Optional
  import numpy
  import paddle
  from docarray import Document
  from docarray import DocumentArray
  from IPython import display
  from PIL import Image
  from stable_diffusion.clip.clip.utils import build_model
  from stable_diffusion.clip.clip.utils import tokenize
  from stable_diffusion.diffusers import AutoencoderKL
  from stable_diffusion.diffusers import DDIMScheduler
  from stable_diffusion.diffusers import LMSDiscreteScheduler
  from stable_diffusion.diffusers import PNDMScheduler
  from stable_diffusion.diffusers import UNet2DConditionModel
  from tqdm.auto import tqdm
  import paddlehub
  from paddlehub.module.module import moduleinfo
  from paddlehub.module.module import runnable
  from paddlehub.module.module import serving
label_desc: Use image node_id 2 for calling the StableDiffusion obj's underlying member method code with example usage: obj.generate_image(text_prompts, style, artist, width_height, batch_size, num_inference_steps, guidance_scale, enable_fp16, seed, display_rate, use_gpu, output_dir) and returns: da_batches