webassembly009 transformers.js 网页端侧推理 NLLB翻译模型

打印 上一主题 下一主题

主题 830|帖子 830|积分 2490



应用页面



  • 运行代码:npm i , npm run dev

App.jsx


  1. import { useEffect, useRef, useState } from 'react';
  2. import LanguageSelector from './components/LanguageSelector'; // 语言选择器组件
  3. import Progress from './components/Progress'; // 进度条组件
  4. import './App.css'; // 应用样式
  5. function App() {
  6.   // 状态管理
  7.   const [ready, setReady] = useState(null); // 模型准备状态
  8.   const [disabled, setDisabled] = useState(false); // 翻译按钮是否禁用
  9.   const [progressItems, setProgressItems] = useState([]); // 进度条
  10.   // 输入输出状态管理
  11.   const [input, setInput] = useState('I love walking my dog.'); // 输入文本
  12.   const [sourceLanguage, setSourceLanguage] = useState('eng_Latn'); // 源语言
  13.   const [targetLanguage, setTargetLanguage] = useState('fra_Latn'); // 目标语言
  14.   const [output, setOutput] = useState(''); // 输出文本
  15.   // 创建一个对worker对象的引用
  16.   const worker = useRef(null);
  17.   // 使用`useEffect`钩子在组件挂载时设置worker
  18.   useEffect(() => {
  19.     if (!worker.current) {
  20.       // 如果worker不存在,则创建一个新的Worker实例
  21.       worker.current = new Worker(new URL('./worker.js', import.meta.url), {
  22.         type: 'module' // 指定worker脚本类型为ES模块
  23.       });
  24.     }
  25.     // 给worker添加消息事件监听器
  26.     worker.current.addEventListener('message', onMessageReceived);
  27.    
  28.     // 定义从worker接收消息后的回调处理函数
  29.     const onMessageReceived = (e) => {
  30.       switch (e.data.status) {
  31.         case 'initiate':     // 开始加载模型文件时,更新状态并添加进度项
  32.           setReady(false);
  33.           setProgressItems(prev => [...prev, e.data]);
  34.           break;
  35.         case 'progress':    // 更新模型文件加载进度
  36.           setProgressItems(prev => prev.map(item => item.file === e.data.file ? { ...item, progress: e.data.progress } : item));
  37.           break;
  38.         case 'done':        // 模型文件加载完成,从进度列表中移除该项目
  39.           setProgressItems(prev => prev.filter(item => item.file !== e.data.file));
  40.           break;
  41.         case 'ready':       // 工作线程准备好接受消息
  42.           setReady(true);
  43.           break;
  44.         case 'update':      // 更新输出文本
  45.           setOutput(e.data.output);
  46.           break;
  47.         case 'complete':    // 翻译完成,启用“翻译”按钮
  48.           setDisabled(false);
  49.           break;
  50.       }
  51.     };
  52.     // 返回一个清理函数,在组件卸载时移除事件监听器
  53.     return () => worker.current.removeEventListener('message', onMessageReceived);
  54.   });
  55.   // 翻译函数
  56.   const translate = () => {
  57.     setDisabled(true); // 禁用翻译按钮
  58.     worker.current.postMessage({ // 发送消息给worker开始翻译
  59.       text: input,
  60.       src_lang: sourceLanguage,
  61.       tgt_lang: targetLanguage,
  62.     });
  63.   }
  64.   // 渲染UI
  65.   return (
  66.     <>
  67.       <h1>Transformers.js</h1>
  68.       <h2>ML-powered multilingual translation in React!</h2>
  69.       {/* UI布局,关键在于调用translate函数 */}
  70.       <div className='container'>
  71.         <div className='language-container'>
  72.           <LanguageSelector type={"Source"} defaultLanguage={"eng_Latn"} onChange={x => setSourceLanguage(x.target.value)} />
  73.           <LanguageSelector type={"Target"} defaultLanguage={"fra_Latn"} onChange={x => setTargetLanguage(x.target.value)} />
  74.         </div>
  75.         <div className='textbox-container'>
  76.           <textarea value={input} rows={3} onChange={e => setInput(e.target.value)}></textarea>
  77.           <textarea value={output} rows={3} readOnly></textarea>
  78.         </div>
  79.       </div>
  80.       <button disabled={disabled} onClick={translate}>Translate</button>
  81.       <div className='progress-bars-container'>
  82.         {ready === false && <label>Loading models... (only run once)</label>}
  83.         {progressItems.map(data => (
  84.           <div key={data.file}>
  85.             <Progress text={data.file} percentage={data.progress} />
  86.           </div>
  87.         ))}
  88.       </div>
  89.     </>
  90.   );
  91. }
  92. export default App; // 导出默认组件
复制代码
worker.js



  • 代码定义了一个使用单例模式的MyTranslationPipeline,并通过Web Worker监听主线程的消息来实行翻译任务(Worker线程消息通报):
  1. import { pipeline } from '@xenova/transformers'; // 导入pipeline函数用于加载模型
  2. // 使用单例模式确保仅加载一次翻译管道实例。由于加载管道是一个昂贵的操作,我们不希望每次翻译句子时都重新加载。
  3. class MyTranslationPipeline {
  4.     static task = 'translation'; // 任务类型
  5.     static model = 'Xenova/nllb-200-distilled-600M'; // 模型名称
  6.     static instance = null; // 静态变量:存储单例实例
  7.     /**
  8.      * 获取或创建一个翻译管道的实例。
  9.      * @param progress_callback - 进度回调函数,用于追踪模型加载进度。@returns {Promise<*>} - 返回已加载的翻译管道实例。
  10.      */
  11.     static async getInstance(progress_callback = null) {
  12.         if (this.instance === null) { // 如果尚未创建实例,则加载新的翻译管道并保存
  13.             // 1. pipeline函数transformers.js模型加载:默认情况下,模型将从 Hugging Face Hub 下载并存储在 浏览器缓存 中,有关更多信息,请参见https://hugging-face.cn/docs/transformers.js/custom_usage。
  14.             this.instance = await pipeline(this.task, this.model, { progress_callback });
  15.         }
  16.         return this.instance; // 返回实例
  17.     }
  18. }
  19. // 监听来自主线程的消息事件
  20. self.addEventListener('message', async (event) => {
  21.     // 获取翻译管道实例,首次调用时将加载管道并保存以备将来使用
  22.     let translator = await MyTranslationPipeline.getInstance(x => {
  23.         // 添加进度回调函数,以便跟踪模型加载进度
  24.         self.postMessage(x);
  25.     });
  26.     // 2. transformers.js模型执行实际的翻译操作
  27.     let output = await translator(event.data.text, {
  28.         tgt_lang: event.data.tgt_lang, // 目标语言
  29.         src_lang: event.data.src_lang, // 源语言
  30.         // 允许部分输出,并通过回调函数发送更新
  31.         callback_function: x => {
  32.             self.postMessage({
  33.                 status: 'update', // 状态更新
  34.                 output: translator.tokenizer.decode(x[0].output_token_ids, { skip_special_tokens: true }) // 解码输出文本
  35.             });
  36.         }
  37.     });
  38.     // 将翻译结果发送回主线程
  39.     self.postMessage({
  40.         status: 'complete', // 完成状态
  41.         output: output, // 最终的翻译输出
  42.     });
  43. });
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

祗疼妳一个

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表