• 作者:老汪软件技巧
  • 发表时间:2024-11-09 07:01
  • 浏览量:

大家好,我是electrolux,这篇文章带大家看看前端怎么直接离线调用huggingface的模型

代码在这里: /electroluxc…

路由是: /transformer

在开始文章之前。首先咱们来聊一下huggingface吧

image-20241107153902726.png

简单的来说huggingface 可以理解为对于AI开发者的GitHub,提供了模型,数据集等ai的物料。并且提供了一个名为 transformers 的库,这个库结合了多种模型,使得用户可以快速地学习和使用这些模型

然后回归咱们的文章,咱们这篇文章也会用到 transformerjs, 通过这个库,我们可以调用huggingface里面的模型。对比transformer其他服务端的package,主要少了视频的输出能力和表格任务。具体可以参考

这篇文章会用 transformerjs 用 30行代码左右带你实现一个ai翻译助手,下面是成品,接着预告一下,下一篇文章我会用langchan+transformerjs实现一个带rag(目标检索增强)的llm助手,有兴趣的可以follow一下。话不多说,直接开始

image-20241107150010915.png

1.1 选择模型和下载模型

说实话,这一步可能就是咱们这个教程最难的地方了,由于众所皆知的原因,咱们不能直接连接huggingface,所以这一步我们可以选择他的镜像站点

/

现在是第二步,我们要清楚前端不是每一个模型都能够直接调用的,只有是onnx的格式才能够进行调用,因此 我们可以在hf中搜两个作者。 onnx-community 和 Xenova 。这两者的模型可以直接在前端调用。里面加起来的模型大概有1000来个,大家可以根据需求自己选择

地址如下

好,现在我们到第三步了,怎么把模型下载到我们本地。在前端项目中,public文件夹一般是可访问的。我们可以考虑将大模型下载到这里。这里我们采用的是nllb模型,一个ai翻译的简单模型,由于文件较大,这里提供三个方法下载。然后在咱们的源码示例中,也不会携带模型的。大家自己选择方法下载即可

git submodule add https://hf-mirror.com/Xenova/nllb-200-distilled-600M public/nllb-200-distilled-600M
# 后续可能需要 git lfs pull

1.2 指定环境变量

这一步是离线调用的关键,默认transformer 是 会加载 huggingface网站 的线上模型,我们可以通过改变环境变量来让前端去加载自己本地的模型

import { env } from '@xenova/transformers';
env.useCustomCache = false
env.useFSCache = false
// 会加载public下的模型
env.localModelPath = "/"

1.3 调用模型输出

前端离线包和cdn的区别_前端离线缓存技术_

transformer核心是一个 pipeline 方法,然后 可以参照对应模型文件的readme来查看使用示例。

核心代码如下

import { pipeline } from '@xenova/transformers';
let dataGet = async () => {
    const translator = await pipeline('translation', 'nllb-200-distilled-600M');
    let input = '你好,今天天气怎么样'
    const output = await translator(input, {
        src_lang: 'zho_Hans', // Chinese
        tgt_lang: 'eng_Latn', // English
    });
    console.log({
        output, input
    });
}
dataGet();

这是加载模型和自定义环境的完整代码,26行就实现了,aw。确实简单。然后在控制台中输出

import React from 'react'
import { useEffect } from 'react'
import { pipeline, env } from '@xenova/transformers';
env.useCustomCache = false
env.useFSCache = false
env.localModelPath = "/model"
export default function index() {
    let dataGet = async () => {
        const translator = await pipeline('translation', 'nllb-200-distilled-600M');
        let input = '你好,今天天气怎么样'
        const output = await translator(input, {
            src_lang: 'zho_Hans', // Chinese
            tgt_lang: 'eng_Latn', // English
        });
        console.log({
            output, input
        });
    }
    useEffect(() => {
        dataGet();
    })
    return (
        <div>transformerdiv>
    )
}
​

1.4 代码简单加个ui

简单装饰一下

image-20241107150010915.png

css文件

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
​
.bg-black{
  background-color: #000;
}
​
.bg-blue-1{
  background-color: #e6f2ff;
}
​
.bg-blue-3{
  background-color: #007bff;
}
.bg-white{
  background-color: #fff;
}
​
.bg-black-1{
  background: #585a5d
}
​
.color-white-1{
  color: #c3c3c3
}
​
​
.color-blue-1{
  color: #a6d2ff;
}
.color-blue-3{
  color: #007bff;
}
.color-white{
  color: #fff;
}
​
.chat-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  
 
}
.chat-move{
  position: relative;
  top: -100px;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.messages-container {
  width: 80%;
  max-height: 60%;
  overflow-y: auto;
  padding: 20px;
  border-radius: 15px;
  box-shadow: 0 4px 8px rgba(0, 0, 255, 0.2);
}
​
.message {
  padding: 12px;
  border-radius: 10px;
  margin-bottom: 15px;
  word-break: break-word;
}
​
.user {
  border: 1px solid #c2e0ff;
  align-self: flex-end;
}
​
.bot {
  border: 1px solid #c2e0ff;
  display: flex;
  flex-direction: row-reverse;
  align-self: flex-start;
}
​
.input-area {
  display: flex;
  gap: 10px;
  width: 80%;
  margin-top: 20px;
}
​
input {
  flex-grow: 1;
  border: 1px solid #007bff;
  border-radius: 10px;
}
input:focus {
  outline: none;
  border: 1px solid #007bff;
}
​
button {
  padding: 10px 20px;
  border: none;
  border-radius: 10px;
  cursor: pointer;
}

tsx文件示例,路由在 /Transformer

import React from 'react'
import { useState} from 'react'import { pipeline, env } from '@xenova/transformers';
env.useCustomCache = false
env.useFSCache = false
env.localModelPath = "/"
export default function index() {
​
  const dataGet = async (inputValueTemp) => {
    
    setAnswer("加载中");
    const translator = await pipeline('translation', 'nllb-200-distilled-600M');
    const output = await (translator as any)(inputValueTemp, {
      src_lang: 'zho_Hans', // Chinese
      tgt_lang: 'eng_Latn', // English
    }) ;
    setAnswer(output[0].translation_text);
  }
  const [quesion, setQuestion] = useState('提问区');
  const [answer, setAnswer] = useState('回答区');
  const [inputValue, setInputValue] = useState('');
​
  const handleSendMessage = () => {
    if (inputValue.trim() !== '') {
      setQuestion(inputValue)
      setInputValue('');
      dataGet(inputValue)
    }
  };
​
  return (
    <div className="chat-container bg-black-1">
      <div className="chat-move">
        <div className="title">
          <h1 className='color-white-1'>AI翻译助手h1>
        div>
        <div className="messages-container bg-white">
          <div
            className="message user"
          >
            {quesion}
          div>
          <div
            className="message bot"
          >
            {answer}
          div>
        div>
        <div className="input-area">
          <input
            type="text"
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
          />
          <button className='bg-blue-3 color-white' onClick={handleSendMessage}>发送button>
        div>
      div>
    div>
  );
}
​

1.5 感叹一下

transformerjs确实是个好框架,可惜的是transformerjs并不支持训练,虽然也没几个会在客户端进行训练哈哈。

并且现在如果要web端加载几个g的模型对性能是个大挑战

因此这个玩意工程化之路道阻且长, 但是我相信也不会有多久的,

目前唯一感觉可以使用的场景是在手机端,可以模仿王者荣耀资源包的形式引入模型,让用户自主选择。

顺便一提,最近看 到一个 MobileLLM(Optimizing Sub-billion Parameter Language Models for On-Device Use Cases),算是近期优化的比较好的一个开源模型,是为了移动端性能考虑的量化模型,但是文件堪堪也有800M,虽然也挺大的,但是在动则3,4G的模型中算还可以