DeepSeek发布了Janus Pro 7B。这是一款免费的多模态AI,它不仅能精准理解图像,还能根据文本生成高质量的视觉图像。

那些单一功能的模型可以退下了,Janus Pro来统一AI的 “视觉” 与 “想象力” 了。接下来咱们详细分析一下,为什么这次发布引起了广泛关注,以及你现在就能上手使用它的方法。

Janus Pro的独特之处

大多数AI模型都只擅长一项任务:要么分析图像,要么生成图像。比如,像LLaVA这样的模型在描述图像方面表现出色,但无法生成图像;而Stable Diffusion能生成艺术作品,却不能回答关于照片的问题。

Janus Pro 7B弥补了这一差距。它是一个经过训练具备以下两种能力的单一模型:

  • 图像分析:描述场景、识别地标、回答与图像相关的问题。
  • 图像生成:将文本提示转化为逼真的照片或艺术作品。

这种 “双重能力” 在开源AI领域十分罕见,这让Janus Pro成为开发者、创作者和企业的多功能工具。

性能究竟如何?

DeepSeek的基准测试显示,Janus Pro的表现优于市面上流行的开源竞品:

  • 在图像理解方面,它超越了LLava-v-1.5模型。
  • 在图像生成方面,它比Stable Diffusion、pixArt、DALL-E表现更出色 。

它是如何工作的?

传统模型通常使用单一的视觉处理方法来完成这两项任务,但由于理解和生成图像需要不同的方法,这可能会导致性能不佳。为了解决这个问题,Janus将视觉处理分为两个不同的路径:

  • 理解路径:该路径专注于通过提取高级语义特征来解释图像,使模型能够理解图像内容。
  • 生成路径:此路径专为创建图像而设计,将视觉数据转换为离散表示,以促进详细的图像合成。

这两条路径都集成到一个统一的Transformer架构中,使Janus能够有效地处理理解和生成任务。

训练数据

  • 用于理解的9000万个样本:包括图像字幕、图表、文档等。
  • 用于高质量图像生成的7200万个合成美学样本:这种真实数据和合成数据的混合,确保了模型输出既准确又具有视觉吸引力。

现在就用Janus Pro

最棒的是,它免费且有多种使用方式:

  • Hugging face:访问DeepSeek的Hugging Face Space。
  • 本地运行

    1. GitHub代码:从DeepSeek的GitHub仓库克隆代码库。
    2. 安装依赖:运行pip install -e.

简单推理示例

多模态理解

import torch
from transformers import AutoModelForCausalLM
from janus.models import MultiModalityCausalLM, VLChatProcessor
from janus.utils.io import load_pil_images

model_path = "deepseek-ai/Janus-Pro-7B"
vl_chat_processor: VLChatProcessor = VLChatProcessor.from_pretrained(model_path)
tokenizer = vl_chat_processor.tokenizer
vl_gpt: MultiModalityCausalLM = AutoModelForCausalLM.from_pretrained(
    model_path, trust_remote_code=True
)
vl_gpt = vl_gpt.to(torch.bfloat16).cuda().eval()

conversation = [
    {"role": "<|User|>", "content": f"<image_placeholder>\n{question}", "images": [image]},
    {"role": "<|Assistant|>", "content": ""}
]
pil_images = load_pil_images(conversation)
prepare_inputs = vl_chat_processor(
    conversations=conversation, images=pil_images, force_batchify=True
).to(vl_gpt.device)
inputs_embeds = vl_gpt.prepare_inputs_embeds(**prepare_inputs)

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 transformers import AutoModelForCausalLM
from janus.models import MultiModalityCausalLM, VLChatProcessor

model_path = "deepseek-ai/Janus-Pro-7B"
vl_chat_processor: VLChatProcessor = VLChatProcessor.from_pretrained(model_path)
tokenizer = vl_chat_processor.tokenizer
vl_gpt: MultiModalityCausalLM = AutoModelForCausalLM.from_pretrained(
    model_path, trust_remote_code=True
)
vl_gpt = vl_gpt.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_start_tag

@torch.inference_mode()
def generate(
    mmgpt: MultiModalityCausalLM,
    vl_chat_processor: VLChatProcessor,
    prompt: str,
    temperature: float = 1,
    parallel_size: int = 16,
    cfg_weight: float = 5,
    image_token_num_per_image: int = 576,
    img_size: int = 384,
    patch_size: int = 16,
):
    input_ids = vl_chat_processor.tokenizer.encode(prompt)
    input_ids = torch.LongTensor(input_ids)
    tokens = torch.zeros((parallel_size*2, len(input_ids)), dtype=torch.int).cuda()
    for i in range(parallel_size*2):
        tokens[i, :] = input_ids
        if i % 2 != 0:
            tokens[i, 1:-1] = vl_chat_processor.pad_id
    inputs_embeds = mmgpt.language_model.get_input_embeddings()(tokens)
    generated_tokens = torch.zeros((parallel_size, image_token_num_per_image), dtype=torch.int).cuda()
    for i in range(image_token_num_per_image):
        outputs = mmgpt.language_model.model(inputs_embeds=inputs_embeds, use_cache=True, past_key_values=outputs.past_key_values if i != 0 else None)
        hidden_states = outputs.last_hidden_state
        logits = mmgpt.gen_head(hidden_states[:, -1, :])
        logit_cond = logits[0::2, :]
        logit_uncond = logits[1::2, :]
        logits = logit_uncond + cfg_weight * (logit_cond-logit_uncond)
        probs = torch.softmax(logits / temperature, dim=-1)
        next_token = torch.multinomial(probs, num_samples=1)
        generated_tokens[:, i] = next_token.squeeze(dim=-1)
        next_token = torch.cat([next_token.unsqueeze(dim=1), next_token.unsqueeze(dim=1)], dim=1).view(-1)
        img_embeds = mmgpt.prepare_gen_img_embeds(next_token)
        inputs_embeds = img_embeds.unsqueeze(dim=1)
    dec = mmgpt.gen_vision_model.decode_code(generated_tokens.to(dtype=torch.int), shape=[parallel_size, 8, img_size//patch_size, img_size//patch_size])
    dec = dec.to(torch.float32).cpu().numpy().transpose(0, 2, 3, 1)
    dec = np.clip((dec + 1) / 2 * 255, 0, 255)
    visual_img = np.zeros((parallel_size, img_size, img_size, 3), dtype=np.uint8)
    visual_img[:, :, :] = dec
    os.makedirs('generated_samples', exist_ok=True)
    for i in range(parallel_size):
        save_path = os.path.join('generated_samples', "img_{}.jpg".format(i))
        PIL.Image.fromarray(visual_img[i]).save(save_path)

generate(
    vl_gpt,
    vl_chat_processor,
    prompt
)

# 推荐阅读
1. 专家混合(MoE)大语言模型:免费的嵌入模型新宠

2. LLM大模型架构专栏|| 从NLP基础谈起

3. AI Agent 架构新变革:构建自己的 Plan-and-Execute Agent

4. 探索 AI 智能体工作流设计模式

5. 探秘 GraphRAG:知识图谱赋能的RAG技术新突破

6. 解锁 RAG 技术:企业数据与大模型的完美融合之道


后续我们会持续带来更多相关技术的深度解析和实践案例,敬请关注公众号 柏企科技圈

本文由mdnice多平台发布


柏企科技圈
15 声望4 粉丝