我对 Huggingface 上的 Transformers.js 库还很陌生。该库使用 onnx 运行时在浏览器上运行模型。我正在关注本教程link
重新创建的步骤:
在 VSCode 中
npx create-next-app@latest
为应用程序命名
<any-name-you-prefer>
创建应用程序时选择的配置选项如下:
√ What is your project named? ... next
√ Would you like to use TypeScript? ... No / Yes
√ Would you like to use ESLint? ... No / Yes
√ Would you like to use Tailwind CSS? ... No / Yes
√ Would you like to use `src/` directory? ... No / Yes
√ Would you like to use App Router? (recommended) ... No / Yes
√ Would you like to customize the default import alias? ... No / Yes
安装transformersjs
npm i @xenova/transformers
用此替换 next.config.mjs 的内容
/** @type {import('next').NextConfig} */
const nextConfig = {
// (Optional) Export as a static site
// See https://nextjs.org/docs/pages/building-your-application/deploying/static-exports#configuration
output: 'export', // Feel free to modify/remove this option
// Override the default webpack configuration
webpack: (config) => {
// See https://webpack.js.org/configuration/resolve/#resolvealias
config.resolve.alias = {
...config.resolve.alias,
"sharp$": false,
"onnxruntime-node$": false,
}
return config;
},
}
export default nextConfig
创建一个文件
src/app/worker.js
,代码如下:
import { pipeline, env } from "@xenova/transformers";
// Skip local model check
env.allowLocalModels = false;
// Use the Singleton pattern to enable lazy construction of the pipeline.
class PipelineSingleton {
static task = 'text-classification';
static model = 'Xenova/distilbert-base-uncased-finetuned-sst-2-english';
static instance = null;
static async getInstance(progress_callback = null) {
if (this.instance === null) {
this.instance = pipeline(this.task, this.model, { progress_callback });
}
return this.instance;
}
}
// Listen for messages from the main thread
self.addEventListener('message', async (event) => {
// Retrieve the classification pipeline. When called for the first time,
// this will load the pipeline and save it for future use.
let classifier = await PipelineSingleton.getInstance(x => {
// We also add a progress callback to the pipeline so that we can
// track model loading.
self.postMessage(x);
});
// Actually perform the classification
let output = await classifier(event.data.text);
// Send the output back to the main thread
self.postMessage({
status: 'complete',
output: output,
});
});
将
/src/app/page.js
的内容替换为以下代码:
'use client'
import { useState, useEffect, useRef, useCallback } from 'react'
export default function Home() {
// Keep track of the classification result and the model loading status.
const [result, setResult] = useState(null);
const [ready, setReady] = useState(null);
// Create a reference to the worker object.
const worker = useRef(null);
// We use the `useEffect` hook to set up the worker as soon as the `App` component is mounted.
useEffect(() => {
if (!worker.current) {
// Create the worker if it does not yet exist.
worker.current = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module'
});
}
// Create a callback function for messages from the worker thread.
const onMessageReceived = (e) => {
switch (e.data.status) {
case 'initiate':
setReady(false);
break;
case 'ready':
setReady(true);
break;
case 'complete':
setResult(e.data.output[0])
break;
}
};
// Attach the callback function as an event listener.
worker.current.addEventListener('message', onMessageReceived);
// Define a cleanup function for when the component is unmounted.
return () => worker.current.removeEventListener('message', onMessageReceived);
});
const classify = useCallback((text) => {
if (worker.current) {
worker.current.postMessage({ text });
}
}, []);
<main className="flex min-h-screen flex-col items-center justify-center p-12">
<h1 className="text-5xl font-bold mb-2 text-center">Transformers.js</h1>
<h2 className="text-2xl mb-4 text-center">Next.js template</h2>
<input
className="w-full max-w-xs p-2 border border-gray-300 rounded mb-4"
type="text"
placeholder="Enter text here"
onInput={e => {
classify(e.target.value);
}}
/>
{ready !== null && (
<pre className="bg-gray-100 p-2 rounded">
{(!ready || !result) ? 'Loading...' : JSON.stringify(result, null, 2)}
</pre>
)}
</main>
}
使用
npm run dev
运行应用程序
然后当你刷新 localhost:3000 时,你会在 chrome 的控制台上看到以下错误
完整的堆栈跟踪
Uncaught ReferenceError: window is not defined
at 9693 (ort-web.min.js:5035:333)
at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
at 1173 (ort-web.min.js:5086:28)
at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
at 9482 (ort-web.min.js:4752:49)
at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
at 2100 (ort-web.min.js:4744:29)
at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
at 1446 (ort-web.min.js:3450:34)
at __nested_webpack_require_1009257__ (ort-web.min.js:15255:43)
9693 @ ort-web.min.js:5035
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
1173 @ ort-web.min.js:5086
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
9482 @ ort-web.min.js:4752
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
2100 @ ort-web.min.js:4744
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
1446 @ ort-web.min.js:3450
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
9162 @ ort-web.min.js:13374
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
8316 @ ort-web.min.js:6520
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
6416 @ ort-web.min.js:10163
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
5038 @ ort-web.min.js:5503
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
7091 @ ort-web.min.js:5466
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
6919 @ ort-web.min.js:13253
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
7714 @ ort-web.min.js:5212
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
6018 @ ort-web.min.js:5261
__nested_webpack_require_1009257__ @ ort-web.min.js:15255
eval @ ort-web.min.js:15281
eval @ ort-web.min.js:15283
eval @ ort-web.min.js:8
eval @ ort-web.min.js:10
(app-pages-browser)/./node_modules/onnxruntime-web/dist/ort-web.min.js @ _app-pages-browser_src_app_worker_js.js:275
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ onnx.js:9
(app-pages-browser)/./node_modules/@xenova/transformers/src/backends/onnx.js @ _app-pages-browser_src_app_worker_js.js:308
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ env.js:8
(app-pages-browser)/./node_modules/@xenova/transformers/src/env.js @ _app-pages-browser_src_app_worker_js.js:330
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ hub.js:10
(app-pages-browser)/./node_modules/@xenova/transformers/src/utils/hub.js @ _app-pages-browser_src_app_worker_js.js:440
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ tokenizers.js:48
(app-pages-browser)/./node_modules/@xenova/transformers/src/tokenizers.js @ _app-pages-browser_src_app_worker_js.js:374
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ pipelines.js:29
(app-pages-browser)/./node_modules/@xenova/transformers/src/pipelines.js @ _app-pages-browser_src_app_worker_js.js:352
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ transformers.js:450
(app-pages-browser)/./node_modules/@xenova/transformers/src/transformers.js @ _app-pages-browser_src_app_worker_js.js:385
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
fn @ _app-pages-browser_src_app_worker_js.js:712
eval @ worker.js:2
(app-pages-browser)/./src/app/worker.js @ _app-pages-browser_src_app_worker_js.js:286
options.factory @ _app-pages-browser_src_app_worker_js.js:1057
__webpack_require__ @ _app-pages-browser_src_app_worker_js.js:503
(anonymous) @ _app-pages-browser_src_app_worker_js.js:1655
(anonymous) @ _app-pages-browser_src_app_worker_js.js:1658
Show 36 more frames
Show less
成功了🥳
使用新的应用程序文件夹时,我根本无法让工作人员在 NextJS 中工作。我总是遇到像你这样的错误。但是有一个工作示例存储库,其中包含旧页面文件夹和一个工作人员。
我的建议:使用
创建一个新项目npx create-next-app --example with-web-worker your-project-name
并将其用作您的新项目基础,或者将您需要的所有内容复制到您的存储库中。
希望这有帮助。