CoolFace
Datasetpublic

diffusers/community-pipelines-mirror

Community Pipeline Examples For more information about community pipelines, please have a look at this issue. Community pipeline examples consist pipelines that have been added by the community. Please have a look at the following tables to get an overview of all community examples. Click on the Code Example to get a copy-and-paste ready code example that you can try out. If a community pipeline doesn't work as expected, please open an issue and ping the author on it. Please… See the full description on the dataset page: https://huggingface.co/datasets/diffusers/community-pipelines-mirror.

sourceHugging Faceupdated 1mo agoView on Hugging Face
9likes21kdownloads
lpw_stable_diffusion_onnx.py1147 linesDownload Raw Back to v0.19.3
1import inspect2import re3from typing import Callable, List, Optional, Union4 5import numpy as np6import PIL7import torch8from packaging import version9from transformers import CLIPImageProcessor, CLIPTokenizer10 11import diffusers12from diffusers import OnnxRuntimeModel, OnnxStableDiffusionPipeline, SchedulerMixin13from diffusers.pipelines.stable_diffusion import StableDiffusionPipelineOutput14from diffusers.utils import logging15 16 17try:18    from diffusers.pipelines.onnx_utils import ORT_TO_NP_TYPE19except ImportError:20    ORT_TO_NP_TYPE = {21        "tensor(bool)": np.bool_,22        "tensor(int8)": np.int8,23        "tensor(uint8)": np.uint8,24        "tensor(int16)": np.int16,25        "tensor(uint16)": np.uint16,26        "tensor(int32)": np.int32,27        "tensor(uint32)": np.uint32,28        "tensor(int64)": np.int64,29        "tensor(uint64)": np.uint64,30        "tensor(float16)": np.float16,31        "tensor(float)": np.float32,32        "tensor(double)": np.float64,33    }34 35try:36    from diffusers.utils import PIL_INTERPOLATION37except ImportError:38    if version.parse(version.parse(PIL.__version__).base_version) >= version.parse("9.1.0"):39        PIL_INTERPOLATION = {40            "linear": PIL.Image.Resampling.BILINEAR,41            "bilinear": PIL.Image.Resampling.BILINEAR,42            "bicubic": PIL.Image.Resampling.BICUBIC,43            "lanczos": PIL.Image.Resampling.LANCZOS,44            "nearest": PIL.Image.Resampling.NEAREST,45        }46    else:47        PIL_INTERPOLATION = {48            "linear": PIL.Image.LINEAR,49            "bilinear": PIL.Image.BILINEAR,50            "bicubic": PIL.Image.BICUBIC,51            "lanczos": PIL.Image.LANCZOS,52            "nearest": PIL.Image.NEAREST,53        }54# ------------------------------------------------------------------------------55 56logger = logging.get_logger(__name__)  # pylint: disable=invalid-name57 58re_attention = re.compile(59    r"""60\\\(|61\\\)|62\\\[|63\\]|64\\\\|65\\|66\(|67\[|68:([+-]?[.\d]+)\)|69\)|70]|71[^\\()\[\]:]+|72:73""",74    re.X,75)76 77 78def parse_prompt_attention(text):79    """80    Parses a string with attention tokens and returns a list of pairs: text and its associated weight.81    Accepted tokens are:82      (abc) - increases attention to abc by a multiplier of 1.183      (abc:3.12) - increases attention to abc by a multiplier of 3.1284      [abc] - decreases attention to abc by a multiplier of 1.185      \( - literal character '('86      \[ - literal character '['87      \) - literal character ')'88      \] - literal character ']'89      \\ - literal character '\'90      anything else - just text91    >>> parse_prompt_attention('normal text')92    [['normal text', 1.0]]93    >>> parse_prompt_attention('an (important) word')94    [['an ', 1.0], ['important', 1.1], [' word', 1.0]]95    >>> parse_prompt_attention('(unbalanced')96    [['unbalanced', 1.1]]97    >>> parse_prompt_attention('\(literal\]')98    [['(literal]', 1.0]]99    >>> parse_prompt_attention('(unnecessary)(parens)')100    [['unnecessaryparens', 1.1]]101    >>> parse_prompt_attention('a (((house:1.3)) [on] a (hill:0.5), sun, (((sky))).')102    [['a ', 1.0],103     ['house', 1.5730000000000004],104     [' ', 1.1],105     ['on', 1.0],106     [' a ', 1.1],107     ['hill', 0.55],108     [', sun, ', 1.1],109     ['sky', 1.4641000000000006],110     ['.', 1.1]]111    """112 113    res = []114    round_brackets = []115    square_brackets = []116 117    round_bracket_multiplier = 1.1118    square_bracket_multiplier = 1 / 1.1119 120    def multiply_range(start_position, multiplier):121        for p in range(start_position, len(res)):122            res[p][1] *= multiplier123 124    for m in re_attention.finditer(text):125        text = m.group(0)126        weight = m.group(1)127 128        if text.startswith("\\"):129            res.append([text[1:], 1.0])130        elif text == "(":131            round_brackets.append(len(res))132        elif text == "[":133            square_brackets.append(len(res))134        elif weight is not None and len(round_brackets) > 0:135            multiply_range(round_brackets.pop(), float(weight))136        elif text == ")" and len(round_brackets) > 0:137            multiply_range(round_brackets.pop(), round_bracket_multiplier)138        elif text == "]" and len(square_brackets) > 0:139            multiply_range(square_brackets.pop(), square_bracket_multiplier)140        else:141            res.append([text, 1.0])142 143    for pos in round_brackets:144        multiply_range(pos, round_bracket_multiplier)145 146    for pos in square_brackets:147        multiply_range(pos, square_bracket_multiplier)148 149    if len(res) == 0:150        res = [["", 1.0]]151 152    # merge runs of identical weights153    i = 0154    while i + 1 < len(res):155        if res[i][1] == res[i + 1][1]:156            res[i][0] += res[i + 1][0]157            res.pop(i + 1)158        else:159            i += 1160 161    return res162 163 164def get_prompts_with_weights(pipe, prompt: List[str], max_length: int):165    r"""166    Tokenize a list of prompts and return its tokens with weights of each token.167 168    No padding, starting or ending token is included.169    """170    tokens = []171    weights = []172    truncated = False173    for text in prompt:174        texts_and_weights = parse_prompt_attention(text)175        text_token = []176        text_weight = []177        for word, weight in texts_and_weights:178            # tokenize and discard the starting and the ending token179            token = pipe.tokenizer(word, return_tensors="np").input_ids[0, 1:-1]180            text_token += list(token)181            # copy the weight by length of token182            text_weight += [weight] * len(token)183            # stop if the text is too long (longer than truncation limit)184            if len(text_token) > max_length:185                truncated = True186                break187        # truncate188        if len(text_token) > max_length:189            truncated = True190            text_token = text_token[:max_length]191            text_weight = text_weight[:max_length]192        tokens.append(text_token)193        weights.append(text_weight)194    if truncated:195        logger.warning("Prompt was truncated. Try to shorten the prompt or increase max_embeddings_multiples")196    return tokens, weights197 198 199def pad_tokens_and_weights(tokens, weights, max_length, bos, eos, pad, no_boseos_middle=True, chunk_length=77):200    r"""201    Pad the tokens (with starting and ending tokens) and weights (with 1.0) to max_length.202    """203    max_embeddings_multiples = (max_length - 2) // (chunk_length - 2)204    weights_length = max_length if no_boseos_middle else max_embeddings_multiples * chunk_length205    for i in range(len(tokens)):206        tokens[i] = [bos] + tokens[i] + [pad] * (max_length - 1 - len(tokens[i]) - 1) + [eos]207        if no_boseos_middle:208            weights[i] = [1.0] + weights[i] + [1.0] * (max_length - 1 - len(weights[i]))209        else:210            w = []211            if len(weights[i]) == 0:212                w = [1.0] * weights_length213            else:214                for j in range(max_embeddings_multiples):215                    w.append(1.0)  # weight for starting token in this chunk216                    w += weights[i][j * (chunk_length - 2) : min(len(weights[i]), (j + 1) * (chunk_length - 2))]217                    w.append(1.0)  # weight for ending token in this chunk218                w += [1.0] * (weights_length - len(w))219            weights[i] = w[:]220 221    return tokens, weights222 223 224def get_unweighted_text_embeddings(225    pipe,226    text_input: np.array,227    chunk_length: int,228    no_boseos_middle: Optional[bool] = True,229):230    """231    When the length of tokens is a multiple of the capacity of the text encoder,232    it should be split into chunks and sent to the text encoder individually.233    """234    max_embeddings_multiples = (text_input.shape[1] - 2) // (chunk_length - 2)235    if max_embeddings_multiples > 1:236        text_embeddings = []237        for i in range(max_embeddings_multiples):238            # extract the i-th chunk239            text_input_chunk = text_input[:, i * (chunk_length - 2) : (i + 1) * (chunk_length - 2) + 2].copy()240 241            # cover the head and the tail by the starting and the ending tokens242            text_input_chunk[:, 0] = text_input[0, 0]243            text_input_chunk[:, -1] = text_input[0, -1]244 245            text_embedding = pipe.text_encoder(input_ids=text_input_chunk)[0]246 247            if no_boseos_middle:248                if i == 0:249                    # discard the ending token250                    text_embedding = text_embedding[:, :-1]251                elif i == max_embeddings_multiples - 1:252                    # discard the starting token253                    text_embedding = text_embedding[:, 1:]254                else:255                    # discard both starting and ending tokens256                    text_embedding = text_embedding[:, 1:-1]257 258            text_embeddings.append(text_embedding)259        text_embeddings = np.concatenate(text_embeddings, axis=1)260    else:261        text_embeddings = pipe.text_encoder(input_ids=text_input)[0]262    return text_embeddings263 264 265def get_weighted_text_embeddings(266    pipe,267    prompt: Union[str, List[str]],268    uncond_prompt: Optional[Union[str, List[str]]] = None,269    max_embeddings_multiples: Optional[int] = 4,270    no_boseos_middle: Optional[bool] = False,271    skip_parsing: Optional[bool] = False,272    skip_weighting: Optional[bool] = False,273    **kwargs,274):275    r"""276    Prompts can be assigned with local weights using brackets. For example,277    prompt 'A (very beautiful) masterpiece' highlights the words 'very beautiful',278    and the embedding tokens corresponding to the words get multiplied by a constant, 1.1.279 280    Also, to regularize of the embedding, the weighted embedding would be scaled to preserve the original mean.281 282    Args:283        pipe (`OnnxStableDiffusionPipeline`):284            Pipe to provide access to the tokenizer and the text encoder.285        prompt (`str` or `List[str]`):286            The prompt or prompts to guide the image generation.287        uncond_prompt (`str` or `List[str]`):288            The unconditional prompt or prompts for guide the image generation. If unconditional prompt289            is provided, the embeddings of prompt and uncond_prompt are concatenated.290        max_embeddings_multiples (`int`, *optional*, defaults to `1`):291            The max multiple length of prompt embeddings compared to the max output length of text encoder.292        no_boseos_middle (`bool`, *optional*, defaults to `False`):293            If the length of text token is multiples of the capacity of text encoder, whether reserve the starting and294            ending token in each of the chunk in the middle.295        skip_parsing (`bool`, *optional*, defaults to `False`):296            Skip the parsing of brackets.297        skip_weighting (`bool`, *optional*, defaults to `False`):298            Skip the weighting. When the parsing is skipped, it is forced True.299    """300    max_length = (pipe.tokenizer.model_max_length - 2) * max_embeddings_multiples + 2301    if isinstance(prompt, str):302        prompt = [prompt]303 304    if not skip_parsing:305        prompt_tokens, prompt_weights = get_prompts_with_weights(pipe, prompt, max_length - 2)306        if uncond_prompt is not None:307            if isinstance(uncond_prompt, str):308                uncond_prompt = [uncond_prompt]309            uncond_tokens, uncond_weights = get_prompts_with_weights(pipe, uncond_prompt, max_length - 2)310    else:311        prompt_tokens = [312            token[1:-1]313            for token in pipe.tokenizer(prompt, max_length=max_length, truncation=True, return_tensors="np").input_ids314        ]315        prompt_weights = [[1.0] * len(token) for token in prompt_tokens]316        if uncond_prompt is not None:317            if isinstance(uncond_prompt, str):318                uncond_prompt = [uncond_prompt]319            uncond_tokens = [320                token[1:-1]321                for token in pipe.tokenizer(322                    uncond_prompt,323                    max_length=max_length,324                    truncation=True,325                    return_tensors="np",326                ).input_ids327            ]328            uncond_weights = [[1.0] * len(token) for token in uncond_tokens]329 330    # round up the longest length of tokens to a multiple of (model_max_length - 2)331    max_length = max([len(token) for token in prompt_tokens])332    if uncond_prompt is not None:333        max_length = max(max_length, max([len(token) for token in uncond_tokens]))334 335    max_embeddings_multiples = min(336        max_embeddings_multiples,337        (max_length - 1) // (pipe.tokenizer.model_max_length - 2) + 1,338    )339    max_embeddings_multiples = max(1, max_embeddings_multiples)340    max_length = (pipe.tokenizer.model_max_length - 2) * max_embeddings_multiples + 2341 342    # pad the length of tokens and weights343    bos = pipe.tokenizer.bos_token_id344    eos = pipe.tokenizer.eos_token_id345    pad = getattr(pipe.tokenizer, "pad_token_id", eos)346    prompt_tokens, prompt_weights = pad_tokens_and_weights(347        prompt_tokens,348        prompt_weights,349        max_length,350        bos,351        eos,352        pad,353        no_boseos_middle=no_boseos_middle,354        chunk_length=pipe.tokenizer.model_max_length,355    )356    prompt_tokens = np.array(prompt_tokens, dtype=np.int32)357    if uncond_prompt is not None:358        uncond_tokens, uncond_weights = pad_tokens_and_weights(359            uncond_tokens,360            uncond_weights,361            max_length,362            bos,363            eos,364            pad,365            no_boseos_middle=no_boseos_middle,366            chunk_length=pipe.tokenizer.model_max_length,367        )368        uncond_tokens = np.array(uncond_tokens, dtype=np.int32)369 370    # get the embeddings371    text_embeddings = get_unweighted_text_embeddings(372        pipe,373        prompt_tokens,374        pipe.tokenizer.model_max_length,375        no_boseos_middle=no_boseos_middle,376    )377    prompt_weights = np.array(prompt_weights, dtype=text_embeddings.dtype)378    if uncond_prompt is not None:379        uncond_embeddings = get_unweighted_text_embeddings(380            pipe,381            uncond_tokens,382            pipe.tokenizer.model_max_length,383            no_boseos_middle=no_boseos_middle,384        )385        uncond_weights = np.array(uncond_weights, dtype=uncond_embeddings.dtype)386 387    # assign weights to the prompts and normalize in the sense of mean388    # TODO: should we normalize by chunk or in a whole (current implementation)?389    if (not skip_parsing) and (not skip_weighting):390        previous_mean = text_embeddings.mean(axis=(-2, -1))391        text_embeddings *= prompt_weights[:, :, None]392        text_embeddings *= (previous_mean / text_embeddings.mean(axis=(-2, -1)))[:, None, None]393        if uncond_prompt is not None:394            previous_mean = uncond_embeddings.mean(axis=(-2, -1))395            uncond_embeddings *= uncond_weights[:, :, None]396            uncond_embeddings *= (previous_mean / uncond_embeddings.mean(axis=(-2, -1)))[:, None, None]397 398    # For classifier free guidance, we need to do two forward passes.399    # Here we concatenate the unconditional and text embeddings into a single batch400    # to avoid doing two forward passes401    if uncond_prompt is not None:402        return text_embeddings, uncond_embeddings403 404    return text_embeddings405 406 407def preprocess_image(image):408    w, h = image.size409    w, h = (x - x % 32 for x in (w, h))  # resize to integer multiple of 32410    image = image.resize((w, h), resample=PIL_INTERPOLATION["lanczos"])411    image = np.array(image).astype(np.float32) / 255.0412    image = image[None].transpose(0, 3, 1, 2)413    return 2.0 * image - 1.0414 415 416def preprocess_mask(mask, scale_factor=8):417    mask = mask.convert("L")418    w, h = mask.size419    w, h = (x - x % 32 for x in (w, h))  # resize to integer multiple of 32420    mask = mask.resize((w // scale_factor, h // scale_factor), resample=PIL_INTERPOLATION["nearest"])421    mask = np.array(mask).astype(np.float32) / 255.0422    mask = np.tile(mask, (4, 1, 1))423    mask = mask[None].transpose(0, 1, 2, 3)  # what does this step do?424    mask = 1 - mask  # repaint white, keep black425    return mask426 427 428class OnnxStableDiffusionLongPromptWeightingPipeline(OnnxStableDiffusionPipeline):429    r"""430    Pipeline for text-to-image generation using Stable Diffusion without tokens length limit, and support parsing431    weighting in prompt.432 433    This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods the434    library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)435    """436    if version.parse(version.parse(diffusers.__version__).base_version) >= version.parse("0.9.0"):437 438        def __init__(439            self,440            vae_encoder: OnnxRuntimeModel,441            vae_decoder: OnnxRuntimeModel,442            text_encoder: OnnxRuntimeModel,443            tokenizer: CLIPTokenizer,444            unet: OnnxRuntimeModel,445            scheduler: SchedulerMixin,446            safety_checker: OnnxRuntimeModel,447            feature_extractor: CLIPImageProcessor,448            requires_safety_checker: bool = True,449        ):450            super().__init__(451                vae_encoder=vae_encoder,452                vae_decoder=vae_decoder,453                text_encoder=text_encoder,454                tokenizer=tokenizer,455                unet=unet,456                scheduler=scheduler,457                safety_checker=safety_checker,458                feature_extractor=feature_extractor,459                requires_safety_checker=requires_safety_checker,460            )461            self.__init__additional__()462 463    else:464 465        def __init__(466            self,467            vae_encoder: OnnxRuntimeModel,468            vae_decoder: OnnxRuntimeModel,469            text_encoder: OnnxRuntimeModel,470            tokenizer: CLIPTokenizer,471            unet: OnnxRuntimeModel,472            scheduler: SchedulerMixin,473            safety_checker: OnnxRuntimeModel,474            feature_extractor: CLIPImageProcessor,475        ):476            super().__init__(477                vae_encoder=vae_encoder,478                vae_decoder=vae_decoder,479                text_encoder=text_encoder,480                tokenizer=tokenizer,481                unet=unet,482                scheduler=scheduler,483                safety_checker=safety_checker,484                feature_extractor=feature_extractor,485            )486            self.__init__additional__()487 488    def __init__additional__(self):489        self.unet.config.in_channels = 4490        self.vae_scale_factor = 8491 492    def _encode_prompt(493        self,494        prompt,495        num_images_per_prompt,496        do_classifier_free_guidance,497        negative_prompt,498        max_embeddings_multiples,499    ):500        r"""501        Encodes the prompt into text encoder hidden states.502 503        Args:504            prompt (`str` or `list(int)`):505                prompt to be encoded506            num_images_per_prompt (`int`):507                number of images that should be generated per prompt508            do_classifier_free_guidance (`bool`):509                whether to use classifier free guidance or not510            negative_prompt (`str` or `List[str]`):511                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored512                if `guidance_scale` is less than `1`).513            max_embeddings_multiples (`int`, *optional*, defaults to `3`):514                The max multiple length of prompt embeddings compared to the max output length of text encoder.515        """516        batch_size = len(prompt) if isinstance(prompt, list) else 1517 518        if negative_prompt is None:519            negative_prompt = [""] * batch_size520        elif isinstance(negative_prompt, str):521            negative_prompt = [negative_prompt] * batch_size522        if batch_size != len(negative_prompt):523            raise ValueError(524                f"`negative_prompt`: {negative_prompt} has batch size {len(negative_prompt)}, but `prompt`:"525                f" {prompt} has batch size {batch_size}. Please make sure that passed `negative_prompt` matches"526                " the batch size of `prompt`."527            )528 529        text_embeddings, uncond_embeddings = get_weighted_text_embeddings(530            pipe=self,531            prompt=prompt,532            uncond_prompt=negative_prompt if do_classifier_free_guidance else None,533            max_embeddings_multiples=max_embeddings_multiples,534        )535 536        text_embeddings = text_embeddings.repeat(num_images_per_prompt, 0)537        if do_classifier_free_guidance:538            uncond_embeddings = uncond_embeddings.repeat(num_images_per_prompt, 0)539            text_embeddings = np.concatenate([uncond_embeddings, text_embeddings])540 541        return text_embeddings542 543    def check_inputs(self, prompt, height, width, strength, callback_steps):544        if not isinstance(prompt, str) and not isinstance(prompt, list):545            raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")546 547        if strength < 0 or strength > 1:548            raise ValueError(f"The value of strength should in [0.0, 1.0] but is {strength}")549 550        if height % 8 != 0 or width % 8 != 0:551            raise ValueError(f"`height` and `width` have to be divisible by 8 but are {height} and {width}.")552 553        if (callback_steps is None) or (554            callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps <= 0)555        ):556            raise ValueError(557                f"`callback_steps` has to be a positive integer but is {callback_steps} of type"558                f" {type(callback_steps)}."559            )560 561    def get_timesteps(self, num_inference_steps, strength, is_text2img):562        if is_text2img:563            return self.scheduler.timesteps, num_inference_steps564        else:565            # get the original timestep using init_timestep566            offset = self.scheduler.config.get("steps_offset", 0)567            init_timestep = int(num_inference_steps * strength) + offset568            init_timestep = min(init_timestep, num_inference_steps)569 570            t_start = max(num_inference_steps - init_timestep + offset, 0)571            timesteps = self.scheduler.timesteps[t_start:]572            return timesteps, num_inference_steps - t_start573 574    def run_safety_checker(self, image):575        if self.safety_checker is not None:576            safety_checker_input = self.feature_extractor(577                self.numpy_to_pil(image), return_tensors="np"578            ).pixel_values.astype(image.dtype)579            # There will throw an error if use safety_checker directly and batchsize>1580            images, has_nsfw_concept = [], []581            for i in range(image.shape[0]):582                image_i, has_nsfw_concept_i = self.safety_checker(583                    clip_input=safety_checker_input[i : i + 1], images=image[i : i + 1]584                )585                images.append(image_i)586                has_nsfw_concept.append(has_nsfw_concept_i[0])587            image = np.concatenate(images)588        else:589            has_nsfw_concept = None590        return image, has_nsfw_concept591 592    def decode_latents(self, latents):593        latents = 1 / 0.18215 * latents594        # image = self.vae_decoder(latent_sample=latents)[0]595        # it seems likes there is a strange result for using half-precision vae decoder if batchsize>1596        image = np.concatenate(597            [self.vae_decoder(latent_sample=latents[i : i + 1])[0] for i in range(latents.shape[0])]598        )599        image = np.clip(image / 2 + 0.5, 0, 1)600        image = image.transpose((0, 2, 3, 1))601        return image602 603    def prepare_extra_step_kwargs(self, generator, eta):604        # prepare extra kwargs for the scheduler step, since not all schedulers have the same signature605        # eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.606        # eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502607        # and should be between [0, 1]608 609        accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys())610        extra_step_kwargs = {}611        if accepts_eta:612            extra_step_kwargs["eta"] = eta613 614        # check if the scheduler accepts generator615        accepts_generator = "generator" in set(inspect.signature(self.scheduler.step).parameters.keys())616        if accepts_generator:617            extra_step_kwargs["generator"] = generator618        return extra_step_kwargs619 620    def prepare_latents(self, image, timestep, batch_size, height, width, dtype, generator, latents=None):621        if image is None:622            shape = (623                batch_size,624                self.unet.config.in_channels,625                height // self.vae_scale_factor,626                width // self.vae_scale_factor,627            )628 629            if latents is None:630                latents = torch.randn(shape, generator=generator, device="cpu").numpy().astype(dtype)631            else:632                if latents.shape != shape:633                    raise ValueError(f"Unexpected latents shape, got {latents.shape}, expected {shape}")634 635            # scale the initial noise by the standard deviation required by the scheduler636            latents = (torch.from_numpy(latents) * self.scheduler.init_noise_sigma).numpy()637            return latents, None, None638        else:639            init_latents = self.vae_encoder(sample=image)[0]640            init_latents = 0.18215 * init_latents641            init_latents = np.concatenate([init_latents] * batch_size, axis=0)642            init_latents_orig = init_latents643            shape = init_latents.shape644 645            # add noise to latents using the timesteps646            noise = torch.randn(shape, generator=generator, device="cpu").numpy().astype(dtype)647            latents = self.scheduler.add_noise(648                torch.from_numpy(init_latents), torch.from_numpy(noise), timestep649            ).numpy()650            return latents, init_latents_orig, noise651 652    @torch.no_grad()653    def __call__(654        self,655        prompt: Union[str, List[str]],656        negative_prompt: Optional[Union[str, List[str]]] = None,657        image: Union[np.ndarray, PIL.Image.Image] = None,658        mask_image: Union[np.ndarray, PIL.Image.Image] = None,659        height: int = 512,660        width: int = 512,661        num_inference_steps: int = 50,662        guidance_scale: float = 7.5,663        strength: float = 0.8,664        num_images_per_prompt: Optional[int] = 1,665        eta: float = 0.0,666        generator: Optional[torch.Generator] = None,667        latents: Optional[np.ndarray] = None,668        max_embeddings_multiples: Optional[int] = 3,669        output_type: Optional[str] = "pil",670        return_dict: bool = True,671        callback: Optional[Callable[[int, int, np.ndarray], None]] = None,672        is_cancelled_callback: Optional[Callable[[], bool]] = None,673        callback_steps: int = 1,674        **kwargs,675    ):676        r"""677        Function invoked when calling the pipeline for generation.678 679        Args:680            prompt (`str` or `List[str]`):681                The prompt or prompts to guide the image generation.682            negative_prompt (`str` or `List[str]`, *optional*):683                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored684                if `guidance_scale` is less than `1`).685            image (`np.ndarray` or `PIL.Image.Image`):686                `Image`, or tensor representing an image batch, that will be used as the starting point for the687                process.688            mask_image (`np.ndarray` or `PIL.Image.Image`):689                `Image`, or tensor representing an image batch, to mask `image`. White pixels in the mask will be690                replaced by noise and therefore repainted, while black pixels will be preserved. If `mask_image` is a691                PIL image, it will be converted to a single channel (luminance) before use. If it's a tensor, it should692                contain one color channel (L) instead of 3, so the expected shape would be `(B, H, W, 1)`.693            height (`int`, *optional*, defaults to 512):694                The height in pixels of the generated image.695            width (`int`, *optional*, defaults to 512):696                The width in pixels of the generated image.697            num_inference_steps (`int`, *optional*, defaults to 50):698                The number of denoising steps. More denoising steps usually lead to a higher quality image at the699                expense of slower inference.700            guidance_scale (`float`, *optional*, defaults to 7.5):701                Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598).702                `guidance_scale` is defined as `w` of equation 2. of [Imagen703                Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale >704                1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,705                usually at the expense of lower image quality.706            strength (`float`, *optional*, defaults to 0.8):707                Conceptually, indicates how much to transform the reference `image`. Must be between 0 and 1.708                `image` will be used as a starting point, adding more noise to it the larger the `strength`. The709                number of denoising steps depends on the amount of noise initially added. When `strength` is 1, added710                noise will be maximum and the denoising process will run for the full number of iterations specified in711                `num_inference_steps`. A value of 1, therefore, essentially ignores `image`.712            num_images_per_prompt (`int`, *optional*, defaults to 1):713                The number of images to generate per prompt.714            eta (`float`, *optional*, defaults to 0.0):715                Corresponds to parameter eta (η) in the DDIM paper: https://arxiv.org/abs/2010.02502. Only applies to716                [`schedulers.DDIMScheduler`], will be ignored for others.717            generator (`torch.Generator`, *optional*):718                A [torch generator](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make generation719                deterministic.720            latents (`np.ndarray`, *optional*):721                Pre-generated noisy latents, sampled from a Gaussian distribution, to be used as inputs for image722                generation. Can be used to tweak the same generation with different prompts. If not provided, a latents723                tensor will ge generated by sampling using the supplied random `generator`.724            max_embeddings_multiples (`int`, *optional*, defaults to `3`):725                The max multiple length of prompt embeddings compared to the max output length of text encoder.726            output_type (`str`, *optional*, defaults to `"pil"`):727                The output format of the generate image. Choose between728                [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`.729            return_dict (`bool`, *optional*, defaults to `True`):730                Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a731                plain tuple.732            callback (`Callable`, *optional*):733                A function that will be called every `callback_steps` steps during inference. The function will be734                called with the following arguments: `callback(step: int, timestep: int, latents: np.ndarray)`.735            is_cancelled_callback (`Callable`, *optional*):736                A function that will be called every `callback_steps` steps during inference. If the function returns737                `True`, the inference will be cancelled.738            callback_steps (`int`, *optional*, defaults to 1):739                The frequency at which the `callback` function will be called. If not specified, the callback will be740                called at every step.741 742        Returns:743            `None` if cancelled by `is_cancelled_callback`,744            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:745            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple.746            When returning a tuple, the first element is a list with the generated images, and the second element is a747            list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"748            (nsfw) content, according to the `safety_checker`.749        """750        # 0. Default height and width to unet751        height = height or self.unet.config.sample_size * self.vae_scale_factor752        width = width or self.unet.config.sample_size * self.vae_scale_factor753 754        # 1. Check inputs. Raise error if not correct755        self.check_inputs(prompt, height, width, strength, callback_steps)756 757        # 2. Define call parameters758        batch_size = 1 if isinstance(prompt, str) else len(prompt)759        # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)760        # of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`761        # corresponds to doing no classifier free guidance.762        do_classifier_free_guidance = guidance_scale > 1.0763 764        # 3. Encode input prompt765        text_embeddings = self._encode_prompt(766            prompt,767            num_images_per_prompt,768            do_classifier_free_guidance,769            negative_prompt,770            max_embeddings_multiples,771        )772        dtype = text_embeddings.dtype773 774        # 4. Preprocess image and mask775        if isinstance(image, PIL.Image.Image):776            image = preprocess_image(image)777        if image is not None:778            image = image.astype(dtype)779        if isinstance(mask_image, PIL.Image.Image):780            mask_image = preprocess_mask(mask_image, self.vae_scale_factor)781        if mask_image is not None:782            mask = mask_image.astype(dtype)783            mask = np.concatenate([mask] * batch_size * num_images_per_prompt)784        else:785            mask = None786 787        # 5. set timesteps788        self.scheduler.set_timesteps(num_inference_steps)789        timestep_dtype = next(790            (input.type for input in self.unet.model.get_inputs() if input.name == "timestep"), "tensor(float)"791        )792        timestep_dtype = ORT_TO_NP_TYPE[timestep_dtype]793        timesteps, num_inference_steps = self.get_timesteps(num_inference_steps, strength, image is None)794        latent_timestep = timesteps[:1].repeat(batch_size * num_images_per_prompt)795 796        # 6. Prepare latent variables797        latents, init_latents_orig, noise = self.prepare_latents(798            image,799            latent_timestep,800            batch_size * num_images_per_prompt,801            height,802            width,803            dtype,804            generator,805            latents,806        )807 808        # 7. Prepare extra step kwargs. TODO: Logic should ideally just be moved out of the pipeline809        extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)810 811        # 8. Denoising loop812        for i, t in enumerate(self.progress_bar(timesteps)):813            # expand the latents if we are doing classifier free guidance814            latent_model_input = np.concatenate([latents] * 2) if do_classifier_free_guidance else latents815            latent_model_input = self.scheduler.scale_model_input(torch.from_numpy(latent_model_input), t)816            latent_model_input = latent_model_input.numpy()817 818            # predict the noise residual819            noise_pred = self.unet(820                sample=latent_model_input,821                timestep=np.array([t], dtype=timestep_dtype),822                encoder_hidden_states=text_embeddings,823            )824            noise_pred = noise_pred[0]825 826            # perform guidance827            if do_classifier_free_guidance:828                noise_pred_uncond, noise_pred_text = np.split(noise_pred, 2)829                noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)830 831            # compute the previous noisy sample x_t -> x_t-1832            scheduler_output = self.scheduler.step(833                torch.from_numpy(noise_pred), t, torch.from_numpy(latents), **extra_step_kwargs834            )835            latents = scheduler_output.prev_sample.numpy()836 837            if mask is not None:838                # masking839                init_latents_proper = self.scheduler.add_noise(840                    torch.from_numpy(init_latents_orig),841                    torch.from_numpy(noise),842                    t,843                ).numpy()844                latents = (init_latents_proper * mask) + (latents * (1 - mask))845 846            # call the callback, if provided847            if i % callback_steps == 0:848                if callback is not None:849                    callback(i, t, latents)850                if is_cancelled_callback is not None and is_cancelled_callback():851                    return None852 853        # 9. Post-processing854        image = self.decode_latents(latents)855 856        # 10. Run safety checker857        image, has_nsfw_concept = self.run_safety_checker(image)858 859        # 11. Convert to PIL860        if output_type == "pil":861            image = self.numpy_to_pil(image)862 863        if not return_dict:864            return image, has_nsfw_concept865 866        return StableDiffusionPipelineOutput(images=image, nsfw_content_detected=has_nsfw_concept)867 868    def text2img(869        self,870        prompt: Union[str, List[str]],871        negative_prompt: Optional[Union[str, List[str]]] = None,872        height: int = 512,873        width: int = 512,874        num_inference_steps: int = 50,875        guidance_scale: float = 7.5,876        num_images_per_prompt: Optional[int] = 1,877        eta: float = 0.0,878        generator: Optional[torch.Generator] = None,879        latents: Optional[np.ndarray] = None,880        max_embeddings_multiples: Optional[int] = 3,881        output_type: Optional[str] = "pil",882        return_dict: bool = True,883        callback: Optional[Callable[[int, int, np.ndarray], None]] = None,884        callback_steps: int = 1,885        **kwargs,886    ):887        r"""888        Function for text-to-image generation.889        Args:890            prompt (`str` or `List[str]`):891                The prompt or prompts to guide the image generation.892            negative_prompt (`str` or `List[str]`, *optional*):893                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored894                if `guidance_scale` is less than `1`).895            height (`int`, *optional*, defaults to 512):896                The height in pixels of the generated image.897            width (`int`, *optional*, defaults to 512):898                The width in pixels of the generated image.899            num_inference_steps (`int`, *optional*, defaults to 50):900                The number of denoising steps. More denoising steps usually lead to a higher quality image at the901                expense of slower inference.902            guidance_scale (`float`, *optional*, defaults to 7.5):903                Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598).904                `guidance_scale` is defined as `w` of equation 2. of [Imagen905                Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale >906                1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,907                usually at the expense of lower image quality.908            num_images_per_prompt (`int`, *optional*, defaults to 1):909                The number of images to generate per prompt.910            eta (`float`, *optional*, defaults to 0.0):911                Corresponds to parameter eta (η) in the DDIM paper: https://arxiv.org/abs/2010.02502. Only applies to912                [`schedulers.DDIMScheduler`], will be ignored for others.913            generator (`torch.Generator`, *optional*):914                A [torch generator](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make generation915                deterministic.916            latents (`np.ndarray`, *optional*):917                Pre-generated noisy latents, sampled from a Gaussian distribution, to be used as inputs for image918                generation. Can be used to tweak the same generation with different prompts. If not provided, a latents919                tensor will ge generated by sampling using the supplied random `generator`.920            max_embeddings_multiples (`int`, *optional*, defaults to `3`):921                The max multiple length of prompt embeddings compared to the max output length of text encoder.922            output_type (`str`, *optional*, defaults to `"pil"`):923                The output format of the generate image. Choose between924                [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`.925            return_dict (`bool`, *optional*, defaults to `True`):926                Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a927                plain tuple.928            callback (`Callable`, *optional*):929                A function that will be called every `callback_steps` steps during inference. The function will be930                called with the following arguments: `callback(step: int, timestep: int, latents: np.ndarray)`.931            callback_steps (`int`, *optional*, defaults to 1):932                The frequency at which the `callback` function will be called. If not specified, the callback will be933                called at every step.934        Returns:935            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:936            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple.937            When returning a tuple, the first element is a list with the generated images, and the second element is a938            list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"939            (nsfw) content, according to the `safety_checker`.940        """941        return self.__call__(942            prompt=prompt,943            negative_prompt=negative_prompt,944            height=height,945            width=width,946            num_inference_steps=num_inference_steps,947            guidance_scale=guidance_scale,948            num_images_per_prompt=num_images_per_prompt,949            eta=eta,950            generator=generator,951            latents=latents,952            max_embeddings_multiples=max_embeddings_multiples,953            output_type=output_type,954            return_dict=return_dict,955            callback=callback,956            callback_steps=callback_steps,957            **kwargs,958        )959 960    def img2img(961        self,962        image: Union[np.ndarray, PIL.Image.Image],963        prompt: Union[str, List[str]],964        negative_prompt: Optional[Union[str, List[str]]] = None,965        strength: float = 0.8,966        num_inference_steps: Optional[int] = 50,967        guidance_scale: Optional[float] = 7.5,968        num_images_per_prompt: Optional[int] = 1,969        eta: Optional[float] = 0.0,970        generator: Optional[torch.Generator] = None,971        max_embeddings_multiples: Optional[int] = 3,972        output_type: Optional[str] = "pil",973        return_dict: bool = True,974        callback: Optional[Callable[[int, int, np.ndarray], None]] = None,975        callback_steps: int = 1,976        **kwargs,977    ):978        r"""979        Function for image-to-image generation.980        Args:981            image (`np.ndarray` or `PIL.Image.Image`):982                `Image`, or ndarray representing an image batch, that will be used as the starting point for the983                process.984            prompt (`str` or `List[str]`):985                The prompt or prompts to guide the image generation.986            negative_prompt (`str` or `List[str]`, *optional*):987                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored988                if `guidance_scale` is less than `1`).989            strength (`float`, *optional*, defaults to 0.8):990                Conceptually, indicates how much to transform the reference `image`. Must be between 0 and 1.991                `image` will be used as a starting point, adding more noise to it the larger the `strength`. The992                number of denoising steps depends on the amount of noise initially added. When `strength` is 1, added993                noise will be maximum and the denoising process will run for the full number of iterations specified in994                `num_inference_steps`. A value of 1, therefore, essentially ignores `image`.995            num_inference_steps (`int`, *optional*, defaults to 50):996                The number of denoising steps. More denoising steps usually lead to a higher quality image at the997                expense of slower inference. This parameter will be modulated by `strength`.998            guidance_scale (`float`, *optional*, defaults to 7.5):999                Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598).1000                `guidance_scale` is defined as `w` of equation 2. of [Imagen1001                Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale >1002                1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,1003                usually at the expense of lower image quality.1004            num_images_per_prompt (`int`, *optional*, defaults to 1):1005                The number of images to generate per prompt.1006            eta (`float`, *optional*, defaults to 0.0):1007                Corresponds to parameter eta (η) in the DDIM paper: https://arxiv.org/abs/2010.02502. Only applies to1008                [`schedulers.DDIMScheduler`], will be ignored for others.1009            generator (`torch.Generator`, *optional*):1010                A [torch generator](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make generation1011                deterministic.1012            max_embeddings_multiples (`int`, *optional*, defaults to `3`):1013                The max multiple length of prompt embeddings compared to the max output length of text encoder.1014            output_type (`str`, *optional*, defaults to `"pil"`):1015                The output format of the generate image. Choose between1016                [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`.1017            return_dict (`bool`, *optional*, defaults to `True`):1018                Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a1019                plain tuple.1020            callback (`Callable`, *optional*):1021                A function that will be called every `callback_steps` steps during inference. The function will be1022                called with the following arguments: `callback(step: int, timestep: int, latents: np.ndarray)`.1023            callback_steps (`int`, *optional*, defaults to 1):1024                The frequency at which the `callback` function will be called. If not specified, the callback will be1025                called at every step.1026        Returns:1027            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:1028            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple.1029            When returning a tuple, the first element is a list with the generated images, and the second element is a1030            list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"1031            (nsfw) content, according to the `safety_checker`.1032        """1033        return self.__call__(1034            prompt=prompt,1035            negative_prompt=negative_prompt,1036            image=image,1037            num_inference_steps=num_inference_steps,1038            guidance_scale=guidance_scale,1039            strength=strength,1040            num_images_per_prompt=num_images_per_prompt,1041            eta=eta,1042            generator=generator,1043            max_embeddings_multiples=max_embeddings_multiples,1044            output_type=output_type,1045            return_dict=return_dict,1046            callback=callback,1047            callback_steps=callback_steps,1048            **kwargs,1049        )1050 1051    def inpaint(1052        self,1053        image: Union[np.ndarray, PIL.Image.Image],1054        mask_image: Union[np.ndarray, PIL.Image.Image],1055        prompt: Union[str, List[str]],1056        negative_prompt: Optional[Union[str, List[str]]] = None,1057        strength: float = 0.8,1058        num_inference_steps: Optional[int] = 50,1059        guidance_scale: Optional[float] = 7.5,1060        num_images_per_prompt: Optional[int] = 1,1061        eta: Optional[float] = 0.0,1062        generator: Optional[torch.Generator] = None,1063        max_embeddings_multiples: Optional[int] = 3,1064        output_type: Optional[str] = "pil",1065        return_dict: bool = True,1066        callback: Optional[Callable[[int, int, np.ndarray], None]] = None,1067        callback_steps: int = 1,1068        **kwargs,1069    ):1070        r"""1071        Function for inpaint.1072        Args:1073            image (`np.ndarray` or `PIL.Image.Image`):1074                `Image`, or tensor representing an image batch, that will be used as the starting point for the1075                process. This is the image whose masked region will be inpainted.1076            mask_image (`np.ndarray` or `PIL.Image.Image`):1077                `Image`, or tensor representing an image batch, to mask `image`. White pixels in the mask will be1078                replaced by noise and therefore repainted, while black pixels will be preserved. If `mask_image` is a1079                PIL image, it will be converted to a single channel (luminance) before use. If it's a tensor, it should1080                contain one color channel (L) instead of 3, so the expected shape would be `(B, H, W, 1)`.1081            prompt (`str` or `List[str]`):1082                The prompt or prompts to guide the image generation.1083            negative_prompt (`str` or `List[str]`, *optional*):1084                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored1085                if `guidance_scale` is less than `1`).1086            strength (`float`, *optional*, defaults to 0.8):1087                Conceptually, indicates how much to inpaint the masked area. Must be between 0 and 1. When `strength`1088                is 1, the denoising process will be run on the masked area for the full number of iterations specified1089                in `num_inference_steps`. `image` will be used as a reference for the masked area, adding more1090                noise to that region the larger the `strength`. If `strength` is 0, no inpainting will occur.1091            num_inference_steps (`int`, *optional*, defaults to 50):1092                The reference number of denoising steps. More denoising steps usually lead to a higher quality image at1093                the expense of slower inference. This parameter will be modulated by `strength`, as explained above.1094            guidance_scale (`float`, *optional*, defaults to 7.5):1095                Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598).1096                `guidance_scale` is defined as `w` of equation 2. of [Imagen1097                Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale >1098                1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,1099                usually at the expense of lower image quality.1100            num_images_per_prompt (`int`, *optional*, defaults to 1):1101                The number of images to generate per prompt.1102            eta (`float`, *optional*, defaults to 0.0):1103                Corresponds to parameter eta (η) in the DDIM paper: https://arxiv.org/abs/2010.02502. Only applies to1104                [`schedulers.DDIMScheduler`], will be ignored for others.1105            generator (`torch.Generator`, *optional*):1106                A [torch generator](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make generation1107                deterministic.1108            max_embeddings_multiples (`int`, *optional*, defaults to `3`):1109                The max multiple length of prompt embeddings compared to the max output length of text encoder.1110            output_type (`str`, *optional*, defaults to `"pil"`):1111                The output format of the generate image. Choose between1112                [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`.1113            return_dict (`bool`, *optional*, defaults to `True`):1114                Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a1115                plain tuple.1116            callback (`Callable`, *optional*):1117                A function that will be called every `callback_steps` steps during inference. The function will be1118                called with the following arguments: `callback(step: int, timestep: int, latents: np.ndarray)`.1119            callback_steps (`int`, *optional*, defaults to 1):1120                The frequency at which the `callback` function will be called. If not specified, the callback will be1121                called at every step.1122        Returns:1123            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:1124            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple.1125            When returning a tuple, the first element is a list with the generated images, and the second element is a1126            list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"1127            (nsfw) content, according to the `safety_checker`.1128        """1129        return self.__call__(1130            prompt=prompt,1131            negative_prompt=negative_prompt,1132            image=image,1133            mask_image=mask_image,1134            num_inference_steps=num_inference_steps,1135            guidance_scale=guidance_scale,1136            strength=strength,1137            num_images_per_prompt=num_images_per_prompt,1138            eta=eta,1139            generator=generator,1140            max_embeddings_multiples=max_embeddings_multiples,1141            output_type=output_type,1142            return_dict=return_dict,1143            callback=callback,1144            callback_steps=callback_steps,1145            **kwargs,1146        )1147