Guest User

ComfyUI JanusPro

a guest
Jan 28th, 2025
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.07 KB | Source Code | 0 0
  1. import torch
  2. import numpy as np
  3. from PIL import Image
  4.  
  5. class JanusImageGeneration:
  6.     @classmethod
  7.     def INPUT_TYPES(s):
  8.         return {
  9.             "required": {
  10.                 "model": ("JANUS_MODEL",),
  11.                 "processor": ("JANUS_PROCESSOR",),
  12.                 "prompt": ("STRING", {
  13.                     "multiline": True,
  14.                     "default": "A beautiful photo of"
  15.                 }),
  16.                 "seed": ("INT", {
  17.                     "default": 666666666666666,
  18.                     "min": 0,
  19.                     "max": 0xffffffffffffffff
  20.                 }),
  21.                 "batch_size": ("INT", {
  22.                     "default": 1,
  23.                     "min": 1,
  24.                     "max": 16
  25.                 }),
  26.                 "cfg_weight": ("FLOAT", {
  27.                     "default": 5.0,
  28.                     "min": 1.0,
  29.                     "max": 10.0,
  30.                     "step": 0.5
  31.                 }),
  32.                 "temperature": ("FLOAT", {
  33.                     "default": 1.0,
  34.                     "min": 0.1,
  35.                     "max": 2.0,
  36.                     "step": 0.1
  37.                 }),
  38.                 "top_p": ("FLOAT", {
  39.                     "default": 0.95,
  40.                     "min": 0.0,
  41.                     "max": 1.0
  42.                 }),
  43.                 "image_token_num": ("INT", {
  44.                     "default": 576,
  45.                     "min": 0,
  46.                     "max": 10000
  47.                 }),
  48.                 "img_size": ("INT", {
  49.                     "default": 384,
  50.                     "min": 1,
  51.                     "max": 10000
  52.                 }),
  53.                 "patch_size": ("INT", {
  54.                     "default": 16,
  55.                     "min": 0,
  56.                     "max": 10000
  57.                 }),
  58.             },
  59.         }
  60.    
  61.     RETURN_TYPES = ("IMAGE",)
  62.     RETURN_NAMES = ("images",)
  63.     FUNCTION = "generate_images"
  64.     CATEGORY = "Janus-Pro"
  65.  
  66.     def generate_images(self, model, processor, prompt, seed, batch_size=1, temperature=1.0, cfg_weight=5.0, top_p=0.95, img_size=384, image_token_num=576, patch_size=16):
  67.         try:
  68.             from janus.models import MultiModalityCausalLM
  69.         except ImportError:
  70.             raise ImportError("Please install Janus using 'pip install -r requirements.txt'")
  71.  
  72.         # 设置随机种子
  73.         torch.manual_seed(seed)
  74.         torch.cuda.manual_seed(seed)
  75.  
  76.         # 图像参数设置
  77.         parallel_size = batch_size
  78.  
  79.         # 准备对话格式
  80.         conversation = [
  81.             {
  82.                 "role": "<|User|>",
  83.                 "content": prompt,
  84.             },
  85.             {"role": "<|Assistant|>", "content": ""},
  86.         ]
  87.  
  88.         # 准备输入
  89.         sft_format = processor.apply_sft_template_for_multi_turn_prompts(
  90.             conversations=conversation,
  91.             sft_format=processor.sft_format,
  92.             system_prompt="",
  93.         )
  94.         prompt = sft_format + processor.image_start_tag
  95.  
  96.         # 编码输入文本
  97.         input_ids = processor.tokenizer.encode(prompt)
  98.         input_ids = torch.LongTensor(input_ids)
  99.  
  100.         # 准备条件和无条件输入
  101.         tokens = torch.zeros((parallel_size*2, len(input_ids)), dtype=torch.int).cuda()
  102.         for i in range(parallel_size*2):
  103.             tokens[i, :] = input_ids
  104.             if i % 2 != 0:  # 无条件输入
  105.                 tokens[i, 1:-1] = processor.pad_id
  106.  
  107.         # 获取文本嵌入
  108.         inputs_embeds = model.language_model.get_input_embeddings()(tokens)
  109.  
  110.         # 生成图像tokens
  111.         generated_tokens = torch.zeros((parallel_size, image_token_num), dtype=torch.int).cuda()
  112.         outputs = None
  113.  
  114.         # 自回归生成
  115.         for i in range(image_token_num):
  116.             outputs = model.language_model.model(
  117.                 inputs_embeds=inputs_embeds,
  118.                 use_cache=True,
  119.                 past_key_values=outputs.past_key_values if i != 0 else None
  120.             )
  121.             hidden_states = outputs.last_hidden_state
  122.            
  123.             # 获取logits并应用CFG
  124.             logits = model.gen_head(hidden_states[:, -1, :])
  125.             logit_cond = logits[0::2, :]
  126.             logit_uncond = logits[1::2, :]
  127.            
  128.             logits = logit_uncond + cfg_weight * (logit_cond-logit_uncond)
  129.             probs = torch.softmax(logits / temperature, dim=-1)
  130.  
  131.             # 采样下一个token
  132.             next_token = torch.multinomial(probs, num_samples=1)
  133.             generated_tokens[:, i] = next_token.squeeze(dim=-1)
  134.  
  135.             # 准备下一步的输入
  136.             next_token = torch.cat([next_token.unsqueeze(dim=1), next_token.unsqueeze(dim=1)], dim=1).view(-1)
  137.             img_embeds = model.prepare_gen_img_embeds(next_token)
  138.             inputs_embeds = img_embeds.unsqueeze(dim=1)
  139.  
  140.         # 解码生成的tokens为图像
  141.         dec = model.gen_vision_model.decode_code(
  142.             generated_tokens.to(dtype=torch.int),
  143.             shape=[parallel_size, 8, img_size//patch_size, img_size//patch_size]
  144.         )
  145.        
  146.         # 转换为numpy进行处理
  147.         dec = dec.to(torch.float32).cpu().numpy()
  148.        
  149.         # 确保是BCHW格式
  150.         if dec.shape[1] != 3:
  151.             dec = np.repeat(dec, 3, axis=1)
  152.        
  153.         # 从[-1,1]转换到[0,1]
  154.         dec = (dec + 1) / 2
  155.        
  156.         # 确保值范围在[0,1]之间
  157.         dec = np.clip(dec, 0, 1)
  158.        
  159.         # 转换为ComfyUI需要的格式 [B,C,H,W] -> [B,H,W,C]
  160.         dec = np.transpose(dec, (0, 2, 3, 1))
  161.        
  162.         # 转换为tensor
  163.         images = torch.from_numpy(dec).float()
  164.        
  165.         # 打印详细的形状信息
  166.         # print(f"Initial dec shape: {dec.shape}")
  167.         # print(f"Final tensor: shape={images.shape}, dtype={images.dtype}, range=[{images.min():.3f}, {images.max():.3f}]")
  168.        
  169.         # 确保格式正确
  170.         assert images.ndim == 4 and images.shape[-1] == 3, f"Unexpected shape: {images.shape}"
  171.        
  172.         return (images,)
  173.  
  174.     @classmethod
  175.     def IS_CHANGED(cls, seed, **kwargs):
  176.         return seed
Tags: ComfyUI
Advertisement
Add Comment
Please, Sign In to add comment