import random import gradio as gr import numpy as np import spaces import torch from diffusers import AutoPipelineForText2Image, AutoencoderKL from compel import Compel, ReturnedEmbeddingsType import re def tokenize_line(text, tokenizer): tokens = tokenizer.tokenize(text) return tokens def parse_prompt_attention(text): res = [] pattern = re.compile(r"\(([^)]+):([\d\.]+)\)") matches = pattern.findall(text) for match in matches: res.append((match[0], float(match[1]))) return res def prompt_attention_to_invoke_prompt(attention_list): prompt = "" for item in attention_list: prompt += f"({item[0]}:{item[1]}) " return prompt.strip() def merge_embeds(prompts, compel): embeds = [] pooled_embeds = [] for prompt in prompts: conditioning, pooled = compel(prompt) embeds.append(conditioning) pooled_embeds.append(pooled) # 合并嵌入,这里使用平均值,可以根据需要调整 merged_embed = torch.mean(torch.stack(embeds), dim=0) merged_pooled = torch.mean(torch.stack(pooled_embeds), dim=0) return merged_embed, merged_pooled def get_embed_new(prompt, pipeline, compel, only_convert_string=False, compel_process_sd=False): if compel_process_sd: return merge_embeds(tokenize_line(prompt, pipeline.tokenizer), compel) else: # fix bug weights conversion excessive emphasis prompt = prompt.replace("((", "(").replace("))", ")") # Convert to Compel attention = parse_prompt_attention(prompt) global_attention_chunks = [] for att in attention: for chunk in att[0].split(','): temp_prompt_chunks = tokenize_line(chunk, pipeline.tokenizer) for small_chunk in temp_prompt_chunks: temp_dict = { "weight": round(att[1], 2), "length": len(pipeline.tokenizer.tokenize(f'{small_chunk},')), "prompt": f'{small_chunk},' } global_attention_chunks.append(temp_dict) max_tokens = pipeline.tokenizer.model_max_length - 2 global_prompt_chunks = [] current_list = [] current_length = 0 for item in global_attention_chunks: if current_length + item['length'] > max_tokens: global_prompt_chunks.append(current_list) current_list = [[item['prompt'], item['weight']]] current_length = item['length'] else: if not current_list: current_list.append([item['prompt'], item['weight']]) else: if item['weight'] != current_list[-1][1]: current_list.append([item['prompt'], item['weight']]) else: current_list[-1][0] += f" {item['prompt']}" current_length += item['length'] if current_list: global_prompt_chunks.append(current_list) if only_convert_string: return ' '.join([prompt_attention_to_invoke_prompt(i) for i in global_prompt_chunks]) return merge_embeds([prompt_attention_to_invoke_prompt(i) for i in global_prompt_chunks], compel) if not torch.cuda.is_available(): DESCRIPTION += "\n

你现在运行在CPU上 但是此项目只支持GPU.

" MAX_SEED = np.iinfo(np.int32).max MAX_IMAGE_SIZE = 4096 if torch.cuda.is_available(): vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16) pipe = AutoPipelineForText2Image.from_pretrained( "anon4ik/noobaiXLNAIXL_epsilonPred05Version_diffusers", vae=vae, torch_dtype=torch.float16, use_safetensors=True, add_watermarker=False ) pipe.to("cuda") def randomize_seed_fn(seed: int, randomize_seed: bool) -> int: if randomize_seed: seed = random.randint(0, MAX_SEED) return seed @spaces.GPU def infer( prompt: str, negative_prompt: str = "lowres, {bad}, error, fewer, extra, missing, worst quality, jpeg artifacts, bad quality, watermark, unfinished, displeasing, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract]", use_negative_prompt: bool = True, seed: int = 7, width: int = 1024, height: int = 1536, guidance_scale: float = 3, num_inference_steps: int = 30, randomize_seed: bool = True, use_resolution_binning: bool = True, progress=gr.Progress(track_tqdm=True), ): seed = int(randomize_seed_fn(seed, randomize_seed)) generator = torch.Generator().manual_seed(seed) # 初始化 Compel 实例 compel_instance = Compel( tokenizer=[pipe.tokenizer, pipe.tokenizer_2], text_encoder=[pipe.text_encoder, pipe.text_encoder_2], returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED, requires_pooled=[False, True] ) # 使用 get_embed_new 获取嵌入 conditioning, pooled = get_embed_new(prompt, pipe, compel_instance) # 处理反向提示(negative_prompt) if use_negative_prompt and negative_prompt: negative_conditioning, negative_pooled = get_embed_new(negative_prompt, pipe, compel_instance) else: negative_conditioning = None negative_pooled = None image = pipe( prompt_embeds=conditioning, pooled_prompt_embeds=pooled, negative_prompt_embeds=negative_conditioning, negative_pooled_prompt_embeds=negative_pooled, width=width, height=height, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, generator=generator, use_resolution_binning=use_resolution_binning, ).images[0] image.save("output_image.png") return image, seed examples = [ "nahida (genshin impact)", "klee (genshin impact)", ] css = ''' .gradio-container{max-width: 560px !important} h1{text-align:center} footer { visibility: hidden } ''' with gr.Blocks(css=css) as demo: gr.Markdown("""# 梦羽的模型生成器 ### 快速生成NoobAIXL v0.5的模型图片 V1.0模型在另一个项目上""") with gr.Group(): with gr.Row(): prompt = gr.Text( label="关键词", show_label=False, max_lines=1, placeholder="输入你要的图片关键词", container=False, ) run_button = gr.Button("生成", scale=0, variant="primary") result = gr.Image(label="Result", show_label=False, format="png") with gr.Accordion("高级选项", open=False): with gr.Row(): use_negative_prompt = gr.Checkbox(label="使用反向词条", value=True) negative_prompt = gr.Text( label="反向词条", max_lines=5, lines=4, placeholder="输入你要排除的图片关键词", value="lowres, {bad}, error, fewer, extra, missing, worst quality, jpeg artifacts, bad quality, watermark, unfinished, displeasing, chromatic aberration, signature, extra digits, artistic error, username, scan, [abstract]", visible=True, ) seed = gr.Slider( label="种子", minimum=0, maximum=MAX_SEED, step=1, value=0, ) randomize_seed = gr.Checkbox(label="随机种子", value=True) with gr.Row(visible=True): width = gr.Slider( label="宽度", minimum=512, maximum=MAX_IMAGE_SIZE, step=64, value=1024, ) height = gr.Slider( label="高度", minimum=512, maximum=MAX_IMAGE_SIZE, step=64, value=1536, ) with gr.Row(): guidance_scale = gr.Slider( label="Guidance Scale", minimum=0.1, maximum=10, step=0.1, value=7.0, ) num_inference_steps = gr.Slider( label="生成步数", minimum=1, maximum=50, step=1, value=28, ) gr.Examples( examples=examples, inputs=prompt, outputs=[result, seed], fn=infer ) use_negative_prompt.change( fn=lambda x: gr.update(visible=x), inputs=use_negative_prompt, outputs=negative_prompt, ) gr.on( triggers=[prompt.submit, run_button.click], fn=infer, inputs=[ prompt, negative_prompt, use_negative_prompt, seed, width, height, guidance_scale, num_inference_steps, randomize_seed, ], outputs=[result, seed], ) if __name__ == "__main__": demo.launch()