Maison > interface Web > js tutoriel > Running Deepseek Janus-Pro-in the Browser: Un guide étape par étape

Running Deepseek Janus-Pro-in the Browser: Un guide étape par étape

Mary-Kate Olsen
Libérer: 2025-01-28 10:32:09
original
686 Les gens l'ont consulté

Running DeepSeek Janus-Pro-in the Browser: A Step-by-Step Guide

L'exécution d'un modèle grand langage (LLM) directement dans le navigateur apporte de nouvelles possibilités à l'application AI client qui protège la confidentialité. Dans cet article de blog, nous explorerons comment utiliser WebGPU et Hugging Face's Transformers.js Library in the Browser pour exécuter complètement un texte puissant pour la génération d'images Modèle

Deepseek Janus-Pro-1b .

Pourquoi choisir un raisonnement basé sur un navigateur?

confidentialité

: Les données ne quitteront jamais l'appareil de l'utilisateur.
  1. Avantages coûts : Aucune infrastructure de serveur n'est requise.
  2. Accessabilité
  3. : Il peut s'exécuter sur n'importe quel appareil avec un navigateur moderne et webgpu.
  4. Parce que transformateurs.js
  5. et webgpu accélèrent l'optimisation, les actes dédiés à la conception de tâches multimodales telles que l'entretien de génération de texte à l'image avec raisonnement.
  6. Outils et bibliothèques clés

Transformers.js : version javascript de la bibliothèque Transformers de la face étreinte, optimisée pour l'exécution du navigateur.

webgpu

: API moderne pour GPU accéléré dans le navigateur, il remplace Webgl par les performances de charge de travail ML améliorées. ONNX Runtime

: L'exécution du modèle est implémentée par un diagramme de calcul optimisé.
  1. Exercice de code de démonstration
  2. L'exemple suivant montre comment charger et exécuter Deepseek Janus-Pro-1b dans le travailleur Web pour un raisonnement non bloquant. Le code complet se trouve dans le référentiel GitHub.
  3. Exécutez la démonstration
  4. Voir la démonstration en temps réel ici:
  5. Deepseek Janus-Pro-1b Browser Demonstration
.

Les principales caractéristiques de la démonstration :

La progression du temps réel du chargement et du raisonnement du modèle est mise à jour.
import {
  AutoProcessor,
  MultiModalityCausalLM,
  BaseStreamer,
  TextStreamer,
  InterruptableStoppingCriteria,
} from "@huggingface/transformers";

// 定义常量
const IMAGE_GENERATION_COMMAND_PREFIX = "/imagine ";
const MAX_NEW_TEXT_TOKENS = 1024;

/**
 * 用于执行 WebGPU 功能检测的辅助函数
 */
let fp16_supported = false;
async function check() {
  try {
    const adapter = await navigator.gpu.requestAdapter();
    if (!adapter) {
      throw new Error("WebGPU 不受支持(未找到适配器)");
    }
    fp16_supported = adapter.features.has("shader-f16");
    self.postMessage({
      status: "success",
      data: fp16_supported,
    });
  } catch (e) {
    self.postMessage({
      status: "error",
      data: e.toString(),
    });
  }
}

/**
 * 此类使用单例模式来启用管道延迟加载
 */
class ImageGenerationPipeline {
  static model_id = "onnx-community/Janus-Pro-1B-ONNX";

  static async getInstance(progress_callback = null) {
    this.processor ??= AutoProcessor.from_pretrained(this.model_id, {
      progress_callback,
    });

    this.model ??= MultiModalityCausalLM.from_pretrained(this.model_id, {
      dtype: fp16_supported
        ? {
            prepare_inputs_embeds: "q4",
            language_model: "q4f16",
            lm_head: "fp16",
            gen_head: "fp16",
            gen_img_embeds: "fp16",
            image_decode: "fp32",
          }
        : {
            prepare_inputs_embeds: "fp32",
            language_model: "q4",
            lm_head: "fp32",
            lm_head: "fp32",
            gen_head: "fp32",
            gen_img_embeds: "fp32",
            image_decode: "fp32",
          },
      device: {
        prepare_inputs_embeds: "wasm", // TODO 当错误修复后使用“webgpu”
        language_model: "webgpu",
        lm_head: "webgpu",
        gen_head: "webgpu",
        gen_img_embeds: "webgpu",
        image_decode: "webgpu",
      },
      progress_callback,
    });

    return Promise.all([this.processor, this.model]);
  }
}

class ProgressStreamer extends BaseStreamer {
  constructor(total, on_progress) {
    super();
    this.total = total;
    this.on_progress = on_progress;

    this.count = null;
    this.start_time = null;
  }

  put(value) {
    if (this.count === null) {
      // 忽略第一批标记(提示)
      this.count = 0;
      this.start_time = performance.now();
      return;
    }

    const progress = ++this.count / this.total;

    this.on_progress({
      count: this.count,
      total: this.total,
      progress,
      time: performance.now() - this.start_time,
    });
  }

  end() {
    /* 什么也不做 */
  }
}

const stopping_criteria = new InterruptableStoppingCriteria();

async function generate(messages) {
  // 对于此演示,我们只响应最后一条消息
  const message = messages.at(-1);

  // 告诉主线程我们已开始
  self.postMessage({ status: "start" });

  // 加载管道
  const [processor, model] = await ImageGenerationPipeline.getInstance();

  // 确定用户是否要生成图像或文本
  if (message.content.startsWith(IMAGE_GENERATION_COMMAND_PREFIX)) {
    const text = message.content.replace(IMAGE_GENERATION_COMMAND_PREFIX, "");

    const conversation = [
      {
        role: "", // 使用标题大小写
        content: text,
      },
    ];
    const inputs = await processor(conversation, {
      chat_template: "text_to_image",
    });

    const callback_function = (output) => {
      self.postMessage({
        status: "image-update",
        ...output,
      });
    };

    const num_image_tokens = processor.num_image_tokens;
    const streamer = new ProgressStreamer(num_image_tokens, callback_function);

    const outputs = await model.generate_images({
      ...inputs,
      min_new_tokens: num_image_tokens,
      max_new_tokens: num_image_tokens,
      do_sample: true,
      streamer,
    });

    const blob = await outputs[0].toBlob();

    // 将输出发送回主线程
    self.postMessage({
      status: "image-update",
      blob,
    });
  } else {
    const inputs = await processor(
      message.image
        ? [
            {
              role: "",
              content: "<image_placeholder>\n" + message.content,
              images: [message.image],
            },
          ]
        : [
            {
              role: "",
              content:
                "您是一位乐于助人的助手。以简洁的方式回答用户的问题。",
            },
            {
              role: "",
              content: message.content,
            },
          ],
    );

    let startTime;
    let numTokens = 0;
    let tps;
    const token_callback_function = () => {
      startTime ??= performance.now();

      if (numTokens++ > 0) {
        tps = (numTokens / (performance.now() - startTime)) * 1000;
      }
    };
    const callback_function = (output) => {
      self.postMessage({
        status: "text-update",
        output,
        tps,
        numTokens,
      });
    };

    const streamer = new TextStreamer(processor.tokenizer, {
      skip_prompt: true,
      skip_special_tokens: true,
      callback_function,
      token_callback_function,
    });

    // 生成响应
    const outputs = await model.generate({
      ...inputs,
      max_new_tokens: MAX_NEW_TEXT_TOKENS,
      do_sample: false,
      streamer,
      stopping_criteria,
    });
  }

  // 告诉主线程我们已完成
  self.postMessage({
    status: "complete",
  });
}

async function load() {
  self.postMessage({
    status: "loading",
    data: "正在加载模型...",
  });

  // 加载管道并将其保存以备将来使用。
  const [processor, model] = await ImageGenerationPipeline.getInstance((x) => {
    // 我们还向管道添加进度回调,以便我们可以
    // 跟踪模型加载。
    self.postMessage(x);
  });

  self.postMessage({ status: "ready" });
}

// 侦听来自主线程的消息
self.addEventListener("message", async (e) => {
  const { type, data } = e.data;

  switch (type) {
    case "check":
      check();
      break;

    case "load":
      load();
      break;

    case "generate":
      stopping_criteria.reset();
      generate(data);
      break;

    case "interrupt":
      stopping_criteria.interrupt();
      break;

    case "reset":
      stopping_criteria.reset();
      break;
  }
});
Copier après la connexion

webgpu est accéléré (Chrome obligatoire 113 ou bord 113). Exécution complète du client - Les données ne seront pas envoyées au serveur externe.

Défi et optimisation

Quantification du modèle : Quantification du modèle à 8 chiffres pour réduire sa taille et augmenter la vitesse de chargement.

    Gestion de la mémoire
  • :: Le travailleur Web peut empêcher l'interface utilisateur de geler pendant le raisonnement.
  • Compatibilité du navigateur
  • :: WebGPU est toujours au stade de test, mais il est essentiel pour les performances.
Conclusion

Running Deepseek Janus-Pro-1b dans le navigateur montre le potentiel de l'IA du client. Avec des outils tels que Transformers.js et WebGPUS, les modèles complexes peuvent désormais s'exécuter efficacement dans l'environnement limité, tout en protégeant la confidentialité des utilisateurs.

    Suivi -Up étapes
  1. :
    • Essayez différentes invites et configurations de modèle.
    • Explorer le modèle de tarif fin pour la mission pour des champs spécifiques.
    • Surveiller l'adoption de WebGPU pour assurer une compatibilité plus large.

    Pour les développeurs, cela marque la transformation passionnante des applications AI de la descente et de l'utilisateur. Dans la recherche sur l'exemple de code et démarrer la construction! ?

    Cette sortie révocée maintient la signification d'origine lors de l'utilisation des structures differeng et de phrases.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal