JanusFlow是什么?
JanusFlow是由深度求索(DeepSeek AI)、香港大学、清华大学和北京大学的研究人员提出的创新框架,将图像理解和生成统一在一个模型中。它轻量高效地整合了纠正流与大型语言模型,包括用于理解和生成任务的独立视觉编码器。在训练过程中,这些编码器相互对齐,以提高语义一致性,使系统在图像生成和视觉理解任务中表现出色。

关于JanusFlow的开源信息:
- 开源时间:JanusFlow在2024年11月13日进行了开源。
- 开源协议:JanusFlow的代码仓库遵循MIT License。这意味着JanusFlow的代码可以自由使用,包括商业用途,只要保留原作者的版权声明即可。
- 商用许可:由于JanusFlow遵循的是MIT License,这是一个非常宽松的开源协议,它允许商业使用。因此,JanusFlow可以用于商业用途,只要在使用时包含原作者的版权声明即可。
- DeepSeek Model License:需要注意的是,虽然代码仓库遵循MIT License,但Janus模型的使用还受到DeepSeek Model License的约束。这意味着在使用JanusFlow模型时,除了遵守MIT License的规定外,还可能需要遵守DeepSeek Model License的具体条款。
JanusFlow功能特色
- 多模态理解:JanusFlow能够处理包含文本和图像数据的输入序列,并自回归地预测下一个标记,以理解和回应图像内容。
- 图像生成:给定文本条件,JanusFlow能够使用校正流从高斯噪声开始迭代更新,生成相应的图像。
- 架构与策略:该模型采用了无分类器引导(CFG)来控制生成图像与文本条件之间的对齐,提高图像质量。与传统的使用扩散模型作为外部工具的统一系统相比,JanusFlow提供了更简单、更直接的生成过程,局限性也更少。
- 效率和多功能性:通过消除对独立生成和理解模块的需求,JanusFlow使研究人员和开发者能够利用单一框架处理多种任务,显著降低了复杂性和资源使用。
JanusFlow技术原理
JanusFlow引入了一个极简的架构,将自回归语言模型与校正流相结合,校正流是生成建模中的最新方法。校正流可以直截了当地在大型语言模型框架内进行训练,消除了对复杂架构修改的需求。广泛的实验表明,JanusFlow在各自的领域实现了与专业模型相当或更优越的性能,同时在标准基准测试中显著超越了现有的统一方法。这项工作代表了朝着更高效、更多功能的视觉-语言模型迈出的一步。通过以下几个关键技术原理实现:
1. 极简架构
JanusFlow的核心架构包括两个主要组件:
- 自回归语言模型:用于处理文本生成和理解任务。
- 校正流(Rectified Flow):一种先进的生成建模方法,用于图像生成任务。
2. 解耦理解和生成编码器
JanusFlow采用了两个关键策略来提高模型性能:
- 解耦理解和生成编码器:通过解耦图像理解和生成的编码器,模型可以更好地专注于各自的任务,从而提高整体性能。
- 对齐表示:在统一训练期间对齐理解和生成编码器的表示,确保两者之间的协同作用,提高模型的整体一致性。
3. 校正流的集成
JanusFlow的关键发现之一是校正流可以在大语言模型框架内直接训练,而无需复杂的架构修改。这种集成消除了对独立的大型语言模型(LLM)和生成组件的需求,实现了更为紧密的功能集成,同时降低了架构复杂性。
4. 无分类器引导(CFG)
JanusFlow采用了无分类器引导(CFG)来控制生成图像与文本条件之间的对齐,提高图像质量。这种方法提供了一个更简单、更直接的生成过程,与传统的使用扩散模型作为外部工具的统一系统相比,JanusFlow的局限性更少。
JanusFlow的技术原理体现了其在多模态理解和生成领域的创新性和先进性,通过其独特的架构和策略,JanusFlow为开发能够同时进行图像理解与生成的统一AI模型迈出了重要一步。
JanusFlow实验结果和性能表现
JanusFlow作为一个统一的多模态理解和生成框架,在多个基准测试中展现出了卓越的性能。以下是一些关键的实验结果和性能表现:

- 基准测试表现:在多模态理解基准测试中,JanusFlow超越了多个现有的统一多模态模型和一些特定任务的理解模型。具体来说,在MMBench、SeedBench和GQA上的得分分别为74.9、70.5和60.3,这些成绩显示了JanusFlow在多模态理解任务上的优越性能。
- 图像生成质量:在图像生成方面,JanusFlow同样表现出色。它在MJHQ FID-30k的得分为9.51,在GenEval的得分为0.63,这些指标表明JanusFlow在生成高质量图像方面的能力,超越了SDv1.5和SDXL等模型。
- 综合性能:JanusFlow在多个标准基准测试中的表现不仅与专用模型相当,而且在某些情况下甚至超过了它们。这显示了JanusFlow在多任务处理中的高效性和多功能性。
- 参数效率:值得注意的是,JanusFlow仅使用了1.3B参数就实现了这些性能,这在大型模型中是一个相对较小的参数量,显示了其参数效率。
如何使用JanusFlow
JanusFlow的GitHub页面提供了模型的代码和使用说明,用户可以通过该页面获取模型并按照指南进行使用。此外,Hugging Face平台也提供了JanusFlow模型和Demo,用户可以直接在该平台上尝试模型的功能:
- GitHub: https://github.com/deepseek-ai/Janus
- 模型: https://huggingface.co/deepseek-ai/JanusFlow-1.3B
- Demo: https://huggingface.co/spaces/deepseek-ai/JanusFlow-1.3B。
安装 在Python >= 3.8环境下,通过运行以下命令安装必要的依赖项:
pip install -e .
pip install diffusers[torch]
简单的推理示例
多模态理解
import torch
from janus.janusflow.models import MultiModalityCausalLM, VLChatProcessor
from janus.utils.io import load_pil_images
# specify the path to the model
model_path = "deepseek-ai/JanusFlow-1.3B"
vl_chat_processor: VLChatProcessor = VLChatProcessor.from_pretrained(model_path)
tokenizer = vl_chat_processor.tokenizer
vl_gpt = MultiModalityCausalLM.from_pretrained(
model_path, trust_remote_code=True
)
vl_gpt = vl_gpt.to(torch.bfloat16).cuda().eval()
conversation = [
{
"role": "User",
"content": "<image_placeholder>\nConvert the formula into latex code.",
"images": ["images/equation.png"],
},
{"role": "Assistant", "content": ""},
]
# load images and prepare for inputs
pil_images = load_pil_images(conversation)
prepare_inputs = vl_chat_processor(
conversations=conversation, images=pil_images, force_batchify=True
).to(vl_gpt.device)
# # run image encoder to get the image embeddings
inputs_embeds = vl_gpt.prepare_inputs_embeds(**prepare_inputs)
# # run the model to get the response
outputs = vl_gpt.language_model.generate(
inputs_embeds=inputs_embeds,
attention_mask=prepare_inputs.attention_mask,
pad_token_id=tokenizer.eos_token_id,
bos_token_id=tokenizer.bos_token_id,
eos_token_id=tokenizer.eos_token_id,
max_new_tokens=512,
do_sample=False,
use_cache=True,
)
answer = tokenizer.decode(outputs[0].cpu().tolist(), skip_special_tokens=True)
print(f"{prepare_inputs['sft_format'][0]}", answer)
文本到图像生成
import os
import PIL.Image
import torch
import numpy as np
from janus.janusflow.models import MultiModalityCausalLM, VLChatProcessor
import torchvision
# specify the path to the model
model_path = "deepseek-ai/JanusFlow-1.3B"
vl_chat_processor: VLChatProcessor = VLChatProcessor.from_pretrained(model_path)
tokenizer = vl_chat_processor.tokenizer
vl_gpt = MultiModalityCausalLM.from_pretrained(
model_path, trust_remote_code=True
)
vl_gpt = vl_gpt.to(torch.bfloat16).cuda().eval()
from diffusers.models import AutoencoderKL
# remember to use bfloat16 dtype, this vae doesn't work with fp16
vae = AutoencoderKL.from_pretrained("stabilityai/sdxl-vae")
vae = vae.to(torch.bfloat16).cuda().eval()
conversation = [
{
"role": "User",
"content": "A stunning princess from kabul in red, white traditional clothing, blue eyes, brown hair",
},
{"role": "Assistant", "content": ""},
]
sft_format = vl_chat_processor.apply_sft_template_for_multi_turn_prompts(
conversations=conversation,
sft_format=vl_chat_processor.sft_format,
system_prompt="",
)
prompt = sft_format + vl_chat_processor.image_gen_tag
@torch.inference_mode()
def generate(
mmgpt: MultiModalityCausalLM,
vl_chat_processor: VLChatProcessor,
prompt: str,
cfg_weight: float = 5.0,
num_inference_steps: int = 30,
batchsize: int = 5
):
input_ids = vl_chat_processor.tokenizer.encode(prompt)
input_ids = torch.LongTensor(input_ids)
tokens = torch.stack([input_ids] * 2 * batchsize).cuda()
tokens[batchsize:, 1:] = vl_chat_processor.pad_id
inputs_embeds = vl_gpt.language_model.get_input_embeddings()(tokens)
# we remove the last <bog> token and replace it with t_emb later
inputs_embeds = inputs_embeds[:, :-1, :]
# generate with rectified flow ode
# step 1: encode with vision_gen_enc
z = torch.randn((batchsize, 4, 48, 48), dtype=torch.bfloat16).cuda()
dt = 1.0 / num_inference_steps
dt = torch.zeros_like(z).cuda().to(torch.bfloat16) + dt
# step 2: run ode
attention_mask = torch.ones((2*batchsize, inputs_embeds.shape[1]+577)).to(vl_gpt.device)
attention_mask[batchsize:, 1:inputs_embeds.shape[1]] = 0
attention_mask = attention_mask.int()
for step in range(num_inference_steps):
# prepare inputs for the llm
z_input = torch.cat([z, z], dim=0) # for cfg
t = step / num_inference_steps * 1000.
t = torch.tensor([t] * z_input.shape[0]).to(dt)
z_enc = vl_gpt.vision_gen_enc_model(z_input, t)
z_emb, t_emb, hs = z_enc[0], z_enc[1], z_enc[2]
z_emb = z_emb.view(z_emb.shape[0], z_emb.shape[1], -1).permute(0, 2, 1)
z_emb = vl_gpt.vision_gen_enc_aligner(z_emb)
llm_emb = torch.cat([inputs_embeds, t_emb.unsqueeze(1), z_emb], dim=1)
# input to the llm
# we apply attention mask for CFG: 1 for tokens that are not masked, 0 for tokens that are masked.
if step == 0:
outputs = vl_gpt.language_model.model(inputs_embeds=llm_emb,
use_cache=True,
attention_mask=attention_mask,
past_key_values=None)
past_key_values = []
for kv_cache in past_key_values:
k, v = kv_cache[0], kv_cache[1]
past_key_values.append((k[:, :, :inputs_embeds.shape[1], :], v[:, :, :inputs_embeds.shape[1], :]))
past_key_values = tuple(past_key_values)
else:
outputs = vl_gpt.language_model.model(inputs_embeds=llm_emb,
use_cache=True,
attention_mask=attention_mask,
past_key_values=past_key_values)
hidden_states = outputs.last_hidden_state
# transform hidden_states back to v
hidden_states = vl_gpt.vision_gen_dec_aligner(vl_gpt.vision_gen_dec_aligner_norm(hidden_states[:, -576:, :]))
hidden_states = hidden_states.reshape(z_emb.shape[0], 24, 24, 768).permute(0, 3, 1, 2)
v = vl_gpt.vision_gen_dec_model(hidden_states, hs, t_emb)
v_cond, v_uncond = torch.chunk(v, 2)
v = cfg_weight * v_cond - (cfg_weight-1.) * v_uncond
z = z + dt * v
# step 3: decode with vision_gen_dec and sdxl vae
decoded_image = vae.decode(z / vae.config.scaling_factor).sample
os.makedirs('generated_samples', exist_ok=True)
save_path = os.path.join('generated_samples', "img.jpg")
torchvision.utils.save_image(decoded_image.clip_(-1.0, 1.0)*0.5+0.5, save_path)
generate(
vl_gpt,
vl_chat_processor,
prompt,
cfg_weight=2.0,
num_inference_steps=30,
batchsize=5
)
JanusFlow适用场景
JanusFlow适用于需要同时处理图像理解和图像生成的场景,例如:
- 内容创作:根据文本描述生成图像,适用于艺术创作和设计领域。
- 数据增强:在机器学习项目中,用于生成额外的训练数据。
- 自动化设计:在产品设计和建筑规划中,根据描述自动生成设计图。
- 教育和研究:作为教学工具,帮助学生理解图像生成和视觉理解的工作原理。