@epfml/discojs-web 3.0.1-p20240902162912.0 → 3.0.1-p20240904094219.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,2 +1 @@
1
1
  export * from "./loaders/index.js";
2
- export * from "./memory/index.js";
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
1
  export * from "./loaders/index.js";
2
- export * from "./memory/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epfml/discojs-web",
3
- "version": "3.0.1-p20240902162912.0",
3
+ "version": "3.0.1-p20240904094219.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1 +0,0 @@
1
- export { IndexedDB } from './memory.js';
@@ -1 +0,0 @@
1
- export { IndexedDB } from './memory.js';
@@ -1,31 +0,0 @@
1
- import * as tf from '@tensorflow/tfjs';
2
- import type { Model, ModelInfo, ModelSource } from '@epfml/discojs';
3
- import { Memory } from '@epfml/discojs';
4
- export declare class IndexedDB extends Memory {
5
- getModelMemoryPath(source: ModelSource): string;
6
- getModelInfo(source: ModelSource): ModelInfo;
7
- getModelMetadata(source: ModelSource): Promise<tf.io.ModelArtifactsInfo | undefined>;
8
- contains(source: ModelSource): Promise<boolean>;
9
- getModel(source: ModelSource): Promise<Model>;
10
- deleteModel(source: ModelSource): Promise<void>;
11
- loadModel(source: ModelSource): Promise<void>;
12
- /**
13
- * Saves the working model to the source.
14
- * @param source the destination
15
- * @param model the model
16
- */
17
- updateWorkingModel(source: ModelSource, model: Model): Promise<void>;
18
- /**
19
- * Creates a saved copy of the working model corresponding to the source.
20
- * @param source the source
21
- */
22
- saveWorkingModel(source: ModelSource): Promise<string>;
23
- saveModel(source: ModelSource, model: Model): Promise<string>;
24
- /**
25
- * Downloads the model corresponding to the source.
26
- * @param source the source
27
- */
28
- downloadModel(source: ModelSource): Promise<void>;
29
- latestDuplicate(source: ModelSource): Promise<number | undefined>;
30
- duplicateSource(source: ModelSource): Promise<ModelInfo>;
31
- }
@@ -1,165 +0,0 @@
1
- /**
2
- * Helper functions used to load and save TFJS models from IndexedDB. The
3
- * working model is the model currently being trained for a task. Saved models
4
- * are models that were explicitly saved to IndexedDB. The two working/ and saved/
5
- * folders are invisible to the user. The user only interacts with the saved/
6
- * folder via the model library. The working/ folder is only used by the backend.
7
- * The working model is loaded from IndexedDB for training (model.fit) only.
8
- */
9
- import { Map } from 'immutable';
10
- import createDebug from "debug";
11
- import * as tf from '@tensorflow/tfjs';
12
- import { Memory, models } from '@epfml/discojs';
13
- const debug = createDebug('discojs-web:memory');
14
- export class IndexedDB extends Memory {
15
- getModelMemoryPath(source) {
16
- if (typeof source === 'string') {
17
- return source;
18
- }
19
- const version = source.version ?? 0;
20
- return `indexeddb://${source.type}/${source.tensorBackend}/${source.taskID}/${source.name}@${version}`;
21
- }
22
- getModelInfo(source) {
23
- if (typeof source !== 'string') {
24
- return source;
25
- }
26
- const [type, tensorBackend, taskID, fullName] = source.split('/').splice(2);
27
- if (type !== 'working' && type !== 'saved') {
28
- throw Error("Unknown memory model type");
29
- }
30
- const [name, versionSuffix] = fullName.split('@');
31
- const version = versionSuffix === undefined ? 0 : Number(versionSuffix);
32
- if (tensorBackend !== 'tfjs' && tensorBackend !== 'gpt') {
33
- throw Error("Unknown tensor backend");
34
- }
35
- return { type, taskID, name, version, tensorBackend };
36
- }
37
- async getModelMetadata(source) {
38
- const models = await tf.io.listModels();
39
- return models[this.getModelMemoryPath(source)];
40
- }
41
- async contains(source) {
42
- return await this.getModelMetadata(source) !== undefined;
43
- }
44
- async getModel(source) {
45
- const layersModel = await tf.loadLayersModel(this.getModelMemoryPath(source));
46
- const tensorBackend = this.getModelInfo(source).tensorBackend;
47
- switch (tensorBackend) {
48
- case 'tfjs':
49
- return new models.TFJS(layersModel);
50
- case 'gpt':
51
- return new models.GPT(undefined, layersModel);
52
- default: {
53
- const _ = tensorBackend;
54
- throw new Error('should never happen');
55
- }
56
- }
57
- }
58
- async deleteModel(source) {
59
- await tf.io.removeModel(this.getModelMemoryPath(source));
60
- }
61
- async loadModel(source) {
62
- const src = this.getModelInfo(source);
63
- if (src.type === 'working') {
64
- // Model is already loaded
65
- return;
66
- }
67
- await tf.io.copyModel(this.getModelMemoryPath(src), this.getModelMemoryPath({ ...src, type: 'working', version: 0 }));
68
- }
69
- /**
70
- * Saves the working model to the source.
71
- * @param source the destination
72
- * @param model the model
73
- */
74
- async updateWorkingModel(source, model) {
75
- const src = this.getModelInfo(source);
76
- if (src.type !== 'working') {
77
- throw new Error('expected working type model');
78
- }
79
- // Enforce version 0 to always keep a single working model at a time
80
- const modelInfo = { ...src, type: 'working', version: 0 };
81
- let includeOptimizer;
82
- if (model instanceof models.TFJS) {
83
- modelInfo['tensorBackend'] = 'tfjs';
84
- includeOptimizer = true;
85
- }
86
- else if (model instanceof models.GPT) {
87
- modelInfo['tensorBackend'] = 'gpt';
88
- includeOptimizer = false; // true raises an error
89
- }
90
- else {
91
- debug('unknown working model type %o', model);
92
- throw new Error(`unknown model type while updating working model`);
93
- }
94
- const indexedDBURL = this.getModelMemoryPath(modelInfo);
95
- await model.extract().save(indexedDBURL, { includeOptimizer });
96
- }
97
- /**
98
- * Creates a saved copy of the working model corresponding to the source.
99
- * @param source the source
100
- */
101
- async saveWorkingModel(source) {
102
- const src = this.getModelInfo(source);
103
- if (src.type !== 'working') {
104
- throw new Error('expected working type model');
105
- }
106
- const dst = this.getModelMemoryPath(await this.duplicateSource({ ...src, type: 'saved' }));
107
- await tf.io.copyModel(this.getModelMemoryPath({ ...src, type: 'working' }), dst);
108
- return dst;
109
- }
110
- async saveModel(source, model) {
111
- const src = this.getModelInfo(source);
112
- if (src.type !== 'saved') {
113
- throw new Error('expected saved type model');
114
- }
115
- const modelInfo = await this.duplicateSource({ ...src, type: 'saved' });
116
- let includeOptimizer;
117
- if (model instanceof models.TFJS) {
118
- modelInfo['tensorBackend'] = 'tfjs';
119
- includeOptimizer = true;
120
- }
121
- else if (model instanceof models.GPT) {
122
- modelInfo['tensorBackend'] = 'gpt';
123
- includeOptimizer = false; // true raises an error
124
- }
125
- else {
126
- debug('unknown saved model type %o', model);
127
- throw new Error('unknown model type while saving model');
128
- }
129
- const indexedDBURL = this.getModelMemoryPath(modelInfo);
130
- await model.extract().save(indexedDBURL, { includeOptimizer });
131
- return indexedDBURL;
132
- }
133
- /**
134
- * Downloads the model corresponding to the source.
135
- * @param source the source
136
- */
137
- async downloadModel(source) {
138
- const src = this.getModelInfo(source);
139
- await tf.io.copyModel(this.getModelMemoryPath(source), `downloads://${src.taskID}_${src.name}`);
140
- }
141
- async latestDuplicate(source) {
142
- if (typeof source !== 'string') {
143
- source = this.getModelMemoryPath({ ...source, version: 0 });
144
- }
145
- // perform a single memory read
146
- const paths = Map(await tf.io.listModels());
147
- if (!paths.has(source)) {
148
- return undefined;
149
- }
150
- const latest = Map(paths).keySeq().toList()
151
- .map((p) => this.getModelInfo(p).version).max();
152
- if (latest === undefined) {
153
- return 0;
154
- }
155
- return latest;
156
- }
157
- async duplicateSource(source) {
158
- const latestDuplicate = await this.latestDuplicate(source);
159
- source = this.getModelInfo(source);
160
- if (latestDuplicate === undefined) {
161
- return source;
162
- }
163
- return { ...source, version: latestDuplicate + 1 };
164
- }
165
- }