Add tf.io.browserDownloads() and tf.io.browserFiles() #1012
Conversation
* tf.io.browserLocalStorage() is the public factory function. * Adjust SaveResult slightly: Remove the required success boolean field. Failures in saving and loading will always be thrown as `Error`s. * Add helper functions: * strinbByteLength: required for calculating the byte length of the JSON model topology and weight specs. * arrayBufferToBase64String * base64StringToArrayBuffer The last two helper functions are required because local storage values cannot by binary arrays or `ArrayBuffer`s.
Wouldn't it make more sense for this to live in tfjs-layers instead of core? |
@ry thanks for the comment. It's true that |
Let's chat about this tomorrow -- overall we think that it may make sense to actually decouple the IOHandler because it's really hard to name these top-level functions that merge load/save. Let's chat about this tomorrow (all of these comments below still apply). Review status: 0 of 3 files reviewed at latest revision, all discussions resolved. src/io/files.ts, line 1 at r1 (raw file):
I think we should call this something like browser_files.ts. I don't want to pack all of the node and browser stuff into a single typescript file. src/io/files.ts, line 32 at r1 (raw file):
WEIGHT src/io/files.ts, line 34 at r1 (raw file):
how about BrowserDownloadTriggerConfig src/io/files.ts, line 42 at r1 (raw file):
Let's remove this config entirely. I think we just want to trigger downloads immediately, and always create temporary anchors. If the user wants to build a UI that lets you click a link, they can add an onclick handler which calls your download trigger method. src/io/files.ts, line 59 at r1 (raw file):
how about BrowserDownloadTrigger src/io/files.ts, line 66 at r1 (raw file):
can this be a string => string object instead of an array, or alternatively have multiple filename arguments? src/io/files.ts, line 67 at r1 (raw file):
window == null src/io/files.ts, line 164 at r1 (raw file):
BrowserFileChooser? Something to disambiguate since this will not be used in node. Also, can you split this file into two files? It's better to have 1:1 classes to files, just like in Java. src/io/files.ts, line 167 at r1 (raw file):
can you just stick a private here? How many files are you expecting to support here? There's a throw in load() for files with non-2 length. Also, are you assuming order of the files? We have standardized filenames for everything, so it would be good to support arbitrary ordering. src/io/files.ts, line 182 at r1 (raw file):
can you type this? I think it may be HTMLEvent src/io/files.ts, line 205 at r1 (raw file):
why is this? if we're using a file chooser you can easily select many files. I think we should support that use case. src/io/files.ts, line 237 at r1 (raw file):
it seems better for this API to have weights / model separated like this:
Comments from Reviewable |
Had conversation offline. Will keep the In order to minimize potential confusion with native files in node.js that we will support in the future. Also, just a heads-up that the complexity of the code in this PR has increased a little as a result of our decision to support uploading multiple (sharded) weight file in the browser. Review status: 0 of 5 files reviewed at latest revision, 12 unresolved discussions, some commit checks failed. src/io/files.ts, line 1 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done renaming this file and the associated test file. src/io/files.ts, line 32 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. src/io/files.ts, line 34 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
This config interface has been removed. src/io/files.ts, line 42 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. src/io/files.ts, line 59 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Changed to src/io/files.ts, line 66 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. Per offline discussion. We will allow client only to specify the file-name prefix. src/io/files.ts, line 67 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. src/io/files.ts, line 164 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
per offline discussion, naming this class 'BrowserFiles', as the files don't have to be user-selected files, they can be Files generated from blobs as well. The two classes and two factory methods will continue to life in src/io/files.ts, line 167 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
As discussed in offline discussion, I use File[] here because we need to support FrozenModel artifacts in the future. FrozenModel involves at least 3 files (GraphDef, weights manifest and weights), which is different from tf.Model, which involves 2 files (model.json and weights). File[] is a clean way to capture both. src/io/files.ts, line 182 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
I think the type is src/io/files.ts, line 205 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done adding support for loading from multiple weight files. As discussed offline, an error will be thrown if there are duplicate file basenames (e.g., dir1/weights.bin, dir2/weights.bin) in the weights manifest for some reason. src/io/files.ts, line 237 at r1 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
See my other response about the difference between FrozenModels and tf.Models. Because of the difference in their file counts, doing it as an array is the cleanest approach. Comments from Reviewable |
Reviewed 1 of 7 files at r2. src/io/browser_files.ts, line 93 at r2 (raw file):
you shouldnt need to cast to HTMLAnchorElement here (magic typescript type lookup for 'a') src/io/browser_files.ts, line 209 at r2 (raw file):
use jsonReader variable src/io/browser_files.ts, line 250 at r2 (raw file):
How about "Creates a browser file download IOHandler" similar below src/io/browser_files.ts, line 259 at r2 (raw file):
update this src/io/browser_files.ts, line 261 at r2 (raw file):
qq - should we migrate the other write_weights.py to write ".bin" extensions for consistency? src/io/browser_files.ts, line 302 at r2 (raw file):
update this src/io/browser_files_test.ts, line 287 at r2 (raw file):
I know you do this in layers, but I prefer we don't do this type of programmatic construction of tests in core. It's much easier to understand / debug if they're static, even if you duplicate code. Comments from Reviewable |
Reviewed 6 of 7 files at r2. src/io/browser_files.ts, line 20 at r2 (raw file):
join the lines above and below this comment into one sentence. src/io/browser_files.ts, line 41 at r2 (raw file):
In node, the check Comments from Reviewable |
Review status: all files reviewed at latest revision, 21 unresolved discussions, all commit checks successful. src/io/browser_files.ts, line 20 at r2 (raw file): Previously, dsmilkov (Daniel Smilkov) wrote…
Done. Also removed reference to native files in node.js. src/io/browser_files.ts, line 41 at r2 (raw file): Previously, dsmilkov (Daniel Smilkov) wrote…
Done. src/io/browser_files.ts, line 93 at r2 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. Thanks! src/io/browser_files.ts, line 209 at r2 (raw file):
This is already using the variable. Maybe I didn't get what you mean? src/io/browser_files.ts, line 250 at r2 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. src/io/browser_files.ts, line 259 at r2 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. src/io/browser_files.ts, line 261 at r2 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Both the python and javascript libraries are agnostic w.r.t. extension names. So I'd say this is not necessary. src/io/browser_files.ts, line 302 at r2 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
Done. src/io/browser_files_test.ts, line 287 at r2 (raw file): Previously, nsthorat (Nikhil Thorat) wrote…
OK. I don't mind removing this kind of parametric tests, as long as you don't mind larger sizes in the test files. Done. Comments from Reviewable |
Review status: 3 of 5 files reviewed at latest revision, 21 unresolved discussions, some commit checks pending. src/io/browser_files.ts, line 209 at r2 (raw file):
Using the variable 'jsonFile'. Comments from Reviewable |
tf.io.browserDownloads()
causes the browser to download a model's artifact as files.tf.Model
(Keras-style model), two files consistent with the tensorflowjs_converter format will be donwnloaded:tf.io.browserFiles()
supports loading model artifacts from files such as user-selected files.Towards tensorflow/tfjs#13
This change is