lstm example with node.js, load, and http requests

536 views
Skip to first unread message

Jessica Van Brummelen

unread,
Sep 24, 2018, 8:46:06 AM9/24/18
to TensorFlow.js Discussion
Hi everyone,

I'm super new to all of this (tfjs, nodejs, building servers, posting on forums, etc.), so please let me know if I'm doing anything wrong or if you have any comments on my newbie-forum-posting-habits!

I'm currently trying to modify the lstm tfjs example to run as a node.js server. Essentially, I'd like it to load a previously created and trained model, and then accept http requests with seed text and return generated text using the loaded model.

I had it running in the browser so that it would load a pre-trained model from Amazon s3 and output generated text in the console and it worked fine. Now I'm trying to take that code and run it via node on a remote server.

When I send an http request, I get the following error:
"Error: browserHTTPRequest is not supported outside the web browser without a fetch polyfill.
    at new BrowserHTTPRequest (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-core/dist/io/browser_http.js:46:19)
    at Object.browserHTTPRequest (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-core/dist/io/browser_http.js:247:12)
    at Object.<anonymous> (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/models.js:98:50)
    at step (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/models.js:42:23)
    at Object.next (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/models.js:23:53)
    at /work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/models.js:17:71
    at new Promise (<anonymous>)
    at __awaiter (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/models.js:13:12)
    at Object.loadModelInternal (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/models.js:92:12)
    at Object.loadModel (/work/lstm_model_loader/node_modules/@tensorflow/tfjs/node_modules/@tensorflow/tfjs-layers/dist/exports.js:17:21)"

This error is discussed here: https://github.com/tensorflow/tfjs/issues/479

Like it says in the post, I tried adding the following code around my tf.loadModel(modelUrl), but I still get the fetch polyfill error.
const prevIsBrowser = tf.ENV.getFeatures().IS_BROWSER;
tf.ENV.features.IS_BROWSER = true;
const model = await tf.loadModel(modelUrl);
tf.ENV.features.IS_BROWSER = prevIsBrowser;

They also talk about replacing "fetch" with "const fetch = require('node-fetch')" in core and depending on "node-fetch", but I don't know where in core I should put "const fetch = require('node-fetch')". (I tried putting it in my own entry-point file, but that definitely didn't work!)

Could someone explain to me where I might put "const fetch = require('node-fetch')" to get around this error message? Or if you have any other ideas about how I could implement this code with node.js, please let me know!

Thanks!

Shanqing Cai

unread,
Sep 24, 2018, 9:32:57 AM9/24/18
to TensorFlow.js Discussion
The error occurs because tfjs-node currently uses `fetch` to send HTTP requests, but `fetch` is not available in Node.js by default. 

You can add the following line in your Node.js code (there is no need to modify TensorFlow.js source code):

```js
global.fetch = require('node-fetch');
```

or

```js
fetch = require('node-fetch');
```

Don't include the `const` keyword, because the point is to modify the global `fetch` object. Of course you need to depend on the "node-fetch" module, e.g.,
by including it in package.json.

Please try it and let me know if you have any remaining questions.

Best,
Shanqing

Jessica Van Brummelen

unread,
Sep 24, 2018, 11:08:55 AM9/24/18
to TensorFlow.js Discussion
Makes sense, thanks! 

I've actually tried this (to a certain extent), but instead of using "require" I've been using "import" (since the original lstm example was for the browser, so it was using imports) and "node --experimental-modules myEntryPoint.mjs" to get the imports to work...

But with "import fetch from node-fetch" I get the following error:
ExperimentalWarning: The ESM module loader is experimental.
file:///work/lstm_model_loader/node_modules/node-fetch/lib/index.mjs:1
import Stream, { PassThrough } from 'stream';
                 ^^^^^^^^^^^
SyntaxError: The requested module does not provide an export named 'PassThrough'
    at ModuleJob._instantiate (internal/modules/esm/ModuleJob.js:89:21)
    at <anonymous>

Would it be best to change all of my import statements to requires and try without the experimental-modules? (The reason I didn't do this originally was that I wasn't sure if requires work with the lstm example & node.js -- I'm definitely new to this whole thing!)

Thanks.

Loreto Parisi

unread,
Sep 28, 2018, 12:01:36 PM9/28/18
to TensorFlow.js Discussion
How did you solve this issue?
Adding 

global.fetch = require('node-fetch');

will fix the first, but I get an error on the URL format:

TypeError: Only absolute URLs are supported


cause I'm loading local files like

const model_path = 'file://' + __dirname + '/model/model.json';
const model_metadata = __dirname + '/model/metadata.json';


Thanks!

Jessica Van Brummelen

unread,
Sep 28, 2018, 1:33:41 PM9/28/18
to TensorFlow.js Discussion
I changed all of my 'imports' to 'requires', and then loaded the file locally, like this:
const model = await tf.loadModel('file://./models/nietzsche.json');
I also didn't use the global.fetch = require('node-fetch') line... For some reason this time around it worked for me! Feel free to see my code: https://github.com/jessvb/lstm_web_server/blob/master/index.js

Shanqing Cai

unread,
Sep 28, 2018, 1:49:06 PM9/28/18
to Jessica Van Brummelen, TensorFlow.js Discussion
Glad that you made it work. BTW, the `global.fetch = ...` line is needed only if you load from http:// or https://, there is no need to use them if you are loading from file://.

--
You received this message because you are subscribed to the Google Groups "TensorFlow.js Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+uns...@tensorflow.org.
Visit this group at https://groups.google.com/a/tensorflow.org/group/tfjs/.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/tfjs/30e4865a-b9d2-4788-acc1-6db4938031db%40tensorflow.org.


--
---
Shanqing Cai
Software Engineer
Google

Johann St.

unread,
Jan 8, 2019, 5:11:13 PM1/8/19
to TensorFlow.js Discussion, jess.van...@gmail.com
Hey! 

I just found this thread. I get the same problem with tf.loadModel on tensorflow/tf...@0.14.1, tensorflow/tfjs...@0.2.1, no...@8.11.4 macos. I tried both versions of using 

await tf.loadModel(`file://${__dirname}/../models/${this.mepId}`)

- with `global.fetch = require('node-fetch')` 
TypeError: Only absolute URLs are supported

- without `global.fetch = require('node-fetch')`
Error: browserHTTPRequest is not supported outside the web browser without a fetch polyfill
 
¯\_(ツ)_/¯

Shanqing Cai

unread,
Jan 8, 2019, 5:18:39 PM1/8/19
to Johann St., TensorFlow.js Discussion, Jessica Van Brummelen
Can you show the dependencies field of your package.json and how you imported @tensorflow/tfjs, @tensorflow/tfjs-node and/or @tensorflow/tfjs-node-gpu?

Johann St.

unread,
Jan 8, 2019, 6:18:22 PM1/8/19
to TensorFlow.js Discussion, steinbrec...@gmail.com, jess.van...@gmail.com
That gave me already the right pointer Shanqing. I was not loading `require('@tensorflow/tfjs-node')` in the script in question. -> Resolved.
Reply all
Reply to author
Forward
0 new messages