huggingface / transformers.js

State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server!
https://huggingface.co/docs/transformers.js
Apache License 2.0
12.08k stars 766 forks source link

[Bug] Typescript - Could not find a declaration file for module '@xenova/transformers' #80

Closed warlockdn closed 1 year ago

warlockdn commented 1 year ago

I am trying to look around the functionality and using NextJS with Typescript. I keep getting error

Could not find a declaration file for module '@xenova/transformers'

How to reproduce Create a nextjs project using typescript and install transformers.js

Expected behavior Should work as types are already integrated

image

Environment

chelouche9 commented 1 year ago

will be fixed after #81

xenova commented 1 year ago

@warlockdn Can you test #82 to see if it works in your environment? I'll merge if it works correctly.

warlockdn commented 1 year ago

@warlockdn Can you test #82 to see if it works in your environment? I'll merge if it works correctly.

I did look into this. Somehow its throwing error for the line ./fft

Module '"node_modules/@xenova/transformers/dist/types/fft"' uses 'export =' and cannot be used with 'export *'.ts(2498)

xenova commented 1 year ago

@warlockdn Can you test #82 to see if it works in your environment? I'll merge if it works correctly.

I did look into this. Somehow its throwing error for the line ./fft

Module '"node_modules/@xenova/transformers/dist/types/fft"' uses 'export =' and cannot be used with 'export *'.ts(2498)

Hmm, that's quite strange since that is all done by the typescript compiler (i.e., nothing done by me to do that). I would assume migrating to ES6 syntax would fix it all though. @kungfooman What do you think?

takoyaro commented 1 year ago

I by no means intend to hijack this conversation but ES6 just makes sense in the context of this library and it has come up in a few issues by now, I'm all for it.

xenova commented 1 year ago

Just an update on this. I've spent the day playing around with converting everything to ES6, but there are quite a few issues I've been encountering, especially the way in which non-browser applications would have to mix ES6 and CommonJS imports/exports.

It seems a lot easier to support ES6 from CommonJS than it is to support CommonJS from ES6. I'll try a few more things, but considering webpack can be used to handle the conversions for you, it seems logical to stick with CommonJS for now... (unless anyone can get it working flawlessly on their side)


As for this issue: https://github.com/xenova/transformers.js/issues/80#issuecomment-1504785343, I'll be writing up sample applications over the next few days to make sure everything works as expected.

takoyaro commented 1 year ago

Just an update on this. I've spent the day playing around with converting everything to ES6, but there are quite a few issues I've been encountering, especially the way in which non-browser applications would have to mix ES6 and CommonJS imports/exports.

@xenova would you have an example of this? It's something I'd really like to see happening and I'm not afraid to get my hands dirty

xenova commented 1 year ago

Just an update on this. I've spent the day playing around with converting everything to ES6, but there are quite a few issues I've been encountering, especially the way in which non-browser applications would have to mix ES6 and CommonJS imports/exports.

@xenova would you have an example of this? It's something I'd really like to see happening and I'm not afraid to get my hands dirty

Sure, I can publish the branch I was working on: https://github.com/xenova/transformers.js/tree/es6-rewrite. As you'll see, it's quite incomplete (e.g., building with webpack doesn't work)

SeanDoc77 commented 1 year ago

I am trying to look around the functionality and using NextJS with Typescript. I keep getting error

Could not find a declaration file for module '@xenova/transformers'

How to reproduce Create a nextjs project using typescript and install transformers.js

Expected behavior Should work as types are already integrated

image

Environment

* Transformers.js version: 1.4.2

* Browser (if applicable): NA

* Operating system (if applicable): OSX

Hey, I faced the same issue in my SvelteKit app and managed to work around it by creating a custom TypeScript declaration file. Here's what I did:

  1. Create a new folder named types at the root level of your project.

  2. Inside the types folder, create a new file called transformers.d.ts with the following content:

    declare module '@xenova/transformers';

This tells the TypeScript compiler that you are defining a module named @xenova/transformers.

  1. Update your tsconfig.json file to include the types folder:

Svelte

{
  // ...
  "include": ["src/**/*.ts", "src/**/*.svelte", "types/**/*.d.ts"],
  // ...
}

NextJS (untested)

{
  // ...
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "types/**/*.d.ts"],
  // ...
}
  1. Restart your development server if it's already running.

  2. If you encounter a 'ReferenceError: global is not defined' in the browser, try adding the following code in the main TypeScript file (app.ts or index.ts) of your project:

if (typeof global === "undefined") {
  var global = window;
}

Let me know if this works for you since our environments are different. I've only tested this in the browser with the getting started example so far.

kungfooman commented 1 year ago

@SeanDoc77 About point 5, I hope we use globalThis instead of global soon, as that works in node and browser at the same time and is considered the "new standard":

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis

xenova commented 1 year ago

This should now be fixed in the latest version 2.0.0-alpha.0 (https://www.npmjs.com/package/@xenova/transformers).

The types are now stored in the types folder and should be automatically detected (due to the types parameter in the package.json). Feel free to reopen or open a new issue if you have any further questions.

jedLahrim commented 1 year ago

@xenova i am using typescript and we still get this error: Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/jed/travelApp_backend/node_modules/@xenova/transformers/src/transformers.js from /Users/jed/travelApp_backend/src/routes/map/map.route.ts not supported. while importing import { pipeline } from "@xenova/transformers";

xenova commented 1 year ago

@jedLahrim Since we don't yet support a CommonJS import, you need to either (1) change your project to type: "module", (2) update your node resolution settings, or (3) use the dynamic import syntax (await import('@xenova/transformers'))

e.g.,

let { pipeline, env } = await import('@xenova/transformers');
jedLahrim commented 1 year ago

hhhh you now what i use the await import('@xenova/transformers') like an hour ago and it didnt work now it works im gonna debug it to now why it works now thank you mate

xenova commented 1 year ago

It is most likely transformed to require due to your node resolution settings. You can circumvent this with:

const TransformersApi = Function('return import("@xenova/transformers")')();
const { pipeline } = await TransformersApi;
jedLahrim commented 1 year ago

@xenova when im debuging this function:

async function transcribeAudio() {
  let pipe = await import('@xenova/transformers')
  let transcriber = await pipe.pipeline(
    "automatic-speech-recognition",
    "Xenova/whisper-tiny.en"
  );
  // Load audio data
  let url =
    "https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/jfk.wav";
  let buffer = Buffer.from(await fetch(url).then((x) => x.arrayBuffer()));

  // Read .wav file and convert it to required format
  let wav = new wavefile.WaveFile(buffer);
  wav.toBitDepth("32f"); // Pipeline expects input as a Float32Array
  wav.toSampleRate(16000); // Whisper expects audio with a sampling rate of 16000
  let audioData = wav.getSamples();
  if (Array.isArray(audioData)) {
    // For this demo, if there are multiple channels for the audio file, we just select the first one.
    // In practice, you'd probably want to convert all channels to a single channel (e.g., stereo -> mono).
    audioData = audioData[0];
  }
  let start = performance.now();
  let output = await transcriber(audioData);
  let end = performance.now();
  console.log(`Execution duration: ${(end - start) / 1000} seconds`);
}

it throws me the same error:

Error [ERR_REQUIRE_ESM]: require() of ES Module 
/Users/jed/travelApp_backend/node_modules/@xenova/transformers/src/transformers.js from /Users/jed/travelApp_backend/src/routes/map/map.route.ts not supported.
Instead change the require of transformers.js in /Users/jed/travelApp_backend/src/routes/map/map.route.ts to a dynamic import() which is available in all CommonJS modules.
xenova commented 1 year ago

Yep, looks like it's being transformed behind the scenes. Replace it with

TransformersApi = Function('return import("@xenova/transformers")')();
const { pipeline } = await TransformersApi;

to fix it 👍

jedLahrim commented 1 year ago

yeah it worked but we should improve a better solution to get the types ones in types folder with simple import

xenova commented 1 year ago

Definitely agree. Here's the open feature request for it: https://github.com/xenova/transformers.js/issues/152

jedLahrim commented 1 year ago

@xenova bro a way to load a model for text translation directly from file in my local without waiting compiler until download the model then use the .cache after download first time

async _initXenova() {
let TransformersApi = Function('return import("@xenova/transformers")')();
const { pipeline } = await TransformersApi;
let translator = await pipeline(
"translation",
"Xenova/nllb-200-distilled-600M",
);
return translator;
}
xenova commented 1 year ago

@jedLahrim I'm sorry, I don't quite understand what you mean. Are you saying that the model is cached in .cache? If so, yes, that is by design.

jedLahrim commented 1 year ago

i mean when u call this function

translate(){ // Allocation a pipeline for translation
let translator = await pipeline('translation', 'Xenova/nllb-200-distilled-600M');

// Translate from English to Greek
let result = await translator('I like to walk my dog.', {
src_lang: 'eng_Latn',
tgt_lang: 'ell_Grek'
});
// [ { translation_text: 'Μου αρέσει να περπατάω το σκυλί μου.' } ]

// Translate back to English
let result2 = await translator(result[0].translation_text, {
src_lang: 'ell_Grek',
tgt_lang: 'eng_Latn'
});
// [ { translation_text: 'I like to walk my dog.' } ] }
                                                                                                                                                                                                             for the first time you need to wait some time until the model Xenova/nllb-200-distilled-600M  loaded in my node_modules in @xenova folder i asked you if there is a function or method to load this model Xenova/nllb-200-distilled-600M using the path example ("/path/to/model/Xenova/nllb-200-distilled-600M") in my laptop to get it 
jedLahrim commented 1 year ago

i need to wait some time until the model Xenova/nllb-200-distilled-600M loaded in my node_modules @xenova folder i asked you if there is a function or method to load the Xenova/nllb-200-distilled-600M model uding the path to it example

let translator = await pipeline(
"translation",
"/path/to/model/nllb-200-distilled-600M",
); 
xenova commented 1 year ago

Then yes, you can set the environment variables as follows:

import { pipeline, env } from '@xenova/transformers';

// Disable remote models.
env.allowRemoteModels = false;

// Set local model path.
env.localModelPath = '/path/to/local/models/';

// Create pipeline
let translator = await pipeline('translation', 'Xenova/nllb-200-distilled-600M');

Just remember that your model folder must contain Xenova/nllb-200-distilled-600M/... in it too.

jedLahrim commented 1 year ago
Screenshot 2023-07-19 at 16 50 38

i just read this thank you man

jedLahrim commented 1 year ago

async _initXenova() { let TransformersApi = Function(Constant.XENOVA_IMPORT)(); const { pipeline, env } = await TransformersApi; // Disable remote models. env.allowRemoteModels = false; // Set local model path. env.localModelPath = "/Users/jed/Downloads/Xenova/nllb-200-distilled-600M"; // Create pipeline let translator = await pipeline( "translation", "Xenova/nllb-200-distilled-600M", ); return translator; } `` i get this error **Error:local_files_only=trueorenv.allowRemoteModels=false` and file was not found locally at "/Users/jed/Downloads/Xenova/Xenova/nllb-200-distilled-600M/tokenizer.json".**

xenova commented 1 year ago

That error message should be able to explain what is going wrong. Try removing Xenova/nllb-200-distilled-600M from your localModelPath.

jedLahrim commented 1 year ago

what should i put in my localModelPath

jedLahrim commented 1 year ago
Screenshot 2023-07-19 at 17 39 53
jedLahrim commented 1 year ago
Screenshot 2023-07-19 at 17 41 43

this in node_modules

xenova commented 1 year ago

I can't be 100% certain since I don't know your setup, but either:

env.localModelPath = "/Users/jed/Downloads/";

or

env.localModelPath = "/Users/jed/Downloads/Xenova/";

or

env.localModelPath = "./";

Also, please do not try to spam this issue (which is already closed). If you would like to continue the discussion, feel free to open a new issue.

jedLahrim commented 1 year ago

yah yah hhhh i have not seen what im importing every things is fine now

jedLahrim commented 1 year ago

can we load the model from google drive link ?

xenova commented 1 year ago

Please do not spam this closed issue. If you have questions, please open a new issue.

YoannBuzenet commented 9 months ago

Yep, looks like it's being transformed behind the scenes. Replace it with

TransformersApi = Function('return import("@xenova/transformers")')();
const { pipeline } = await TransformersApi;

to fix it 👍

Hello, Thank your for adressing this issue. However, when using it, I see that : "Cannot find name 'TransformersApi'.

Screenshot from 2024-02-01 14-38-44

What can I do ? Is it because I'm in a NestJS project ?

If using js let { pipeline, env } = await import('@xenova/transformers');, I get this :


0|api  | Instead change the require of transformers.js in /home/yoann/dev/aiBot/api/dist/modules/poc/poc.service.js to a dynamic import() which is available in all CommonJS modules.
0|api  | Error [ERR_REQUIRE_ESM]: require() of ES Module /home/yoann/dev/aiBot/api/node_modules/@xenova/transformers/src/transformers.js from /home/yoann/dev/aiBot/api/dist/modules/poc/poc.service.js not supported.
0|api  | Instead change the require of transformers.js in /home/yoann/dev/aiBot/api/dist/modules/poc/poc.service.js to a dynamic import() which is available in all CommonJS modules.```
xenova commented 9 months ago

Thank your for adressing this issue. However, when using it, I see that : "Cannot find name 'TransformersApi'.

This should be fixable by just defining the variable with const or let. I can't quite remember why I didn't include it in the original comment. Will edit it.

e.g.,

const TransformersApi = Function('return import("@xenova/transformers")')();
const { pipeline } = await TransformersApi;
YoannBuzenet commented 9 months ago

It works thanks. I was wondering if it was some Node magic so I pasted it directly without trying to define it. Thanks :D

pacozaa commented 6 months ago

I got error console.error An error occurred during model execution: "TypeError: A float32 tensor's data must be type of function Float32Array() { [native code] }"

When I try to run this code

const { pipeline } = await TransformersApi
const extractor = await pipeline('feature-extraction', 'Xenova/bert-base-uncased', { revision: 'default' });
const output = await extractor('This is a simple test.')

Posted here because I used to works fine when I import normally.

xenova commented 6 months ago

Are you perhaps running in Jest? Might be a duplicate of https://github.com/xenova/transformers.js/issues/57.

pacozaa commented 6 months ago

Ah yes you are right. Solved.

nanbingxyz commented 2 months ago

Thank your for adressing this issue. However, when using it, I see that : "Cannot find name 'TransformersApi'.

This should be fixable by just defining the variable with const or let. I can't quite remember why I didn't include it in the original comment. Will edit it.

e.g.,

const TransformersApi = Function('return import("@xenova/transformers")')();
const { pipeline } = await TransformersApi;

However, when I attempted this, I encountered another issue: the error info is: TypeError: "Invalid host defined options".