@hazeljs/ml 0.2.0-alpha.1
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/LICENSE +192 -0
- package/README.md +300 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +15 -0
- package/dist/decorators/model.decorator.d.ts +26 -0
- package/dist/decorators/model.decorator.d.ts.map +1 -0
- package/dist/decorators/model.decorator.js +48 -0
- package/dist/decorators/model.decorator.test.d.ts +2 -0
- package/dist/decorators/model.decorator.test.d.ts.map +1 -0
- package/dist/decorators/model.decorator.test.js +128 -0
- package/dist/decorators/predict.decorator.d.ts +20 -0
- package/dist/decorators/predict.decorator.d.ts.map +1 -0
- package/dist/decorators/predict.decorator.js +40 -0
- package/dist/decorators/train.decorator.d.ts +21 -0
- package/dist/decorators/train.decorator.d.ts.map +1 -0
- package/dist/decorators/train.decorator.js +41 -0
- package/dist/evaluation/metrics.service.d.ts +54 -0
- package/dist/evaluation/metrics.service.d.ts.map +1 -0
- package/dist/evaluation/metrics.service.js +163 -0
- package/dist/evaluation/metrics.service.test.d.ts +2 -0
- package/dist/evaluation/metrics.service.test.d.ts.map +1 -0
- package/dist/evaluation/metrics.service.test.js +253 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/inference/batch.service.d.ts +16 -0
- package/dist/inference/batch.service.d.ts.map +1 -0
- package/dist/inference/batch.service.js +52 -0
- package/dist/inference/batch.service.test.d.ts +2 -0
- package/dist/inference/batch.service.test.d.ts.map +1 -0
- package/dist/inference/batch.service.test.js +86 -0
- package/dist/inference/predictor.service.d.ts +13 -0
- package/dist/inference/predictor.service.d.ts.map +1 -0
- package/dist/inference/predictor.service.js +65 -0
- package/dist/inference/predictor.service.test.d.ts +2 -0
- package/dist/inference/predictor.service.test.d.ts.map +1 -0
- package/dist/inference/predictor.service.test.js +115 -0
- package/dist/ml-model.base.d.ts +20 -0
- package/dist/ml-model.base.d.ts.map +1 -0
- package/dist/ml-model.base.js +33 -0
- package/dist/ml-model.base.test.d.ts +2 -0
- package/dist/ml-model.base.test.d.ts.map +1 -0
- package/dist/ml-model.base.test.js +57 -0
- package/dist/ml.module.d.ts +27 -0
- package/dist/ml.module.d.ts.map +1 -0
- package/dist/ml.module.js +126 -0
- package/dist/ml.module.test.d.ts +2 -0
- package/dist/ml.module.test.d.ts.map +1 -0
- package/dist/ml.module.test.js +60 -0
- package/dist/ml.types.d.ts +30 -0
- package/dist/ml.types.d.ts.map +1 -0
- package/dist/ml.types.js +5 -0
- package/dist/registry/model.registry.d.ts +21 -0
- package/dist/registry/model.registry.d.ts.map +1 -0
- package/dist/registry/model.registry.js +64 -0
- package/dist/registry/model.registry.test.d.ts +2 -0
- package/dist/registry/model.registry.test.d.ts.map +1 -0
- package/dist/registry/model.registry.test.js +93 -0
- package/dist/training/pipeline.service.d.ts +25 -0
- package/dist/training/pipeline.service.d.ts.map +1 -0
- package/dist/training/pipeline.service.js +65 -0
- package/dist/training/pipeline.service.test.d.ts +2 -0
- package/dist/training/pipeline.service.test.d.ts.map +1 -0
- package/dist/training/pipeline.service.test.js +52 -0
- package/dist/training/trainer.service.d.ts +13 -0
- package/dist/training/trainer.service.d.ts.map +1 -0
- package/dist/training/trainer.service.js +69 -0
- package/dist/training/trainer.service.test.d.ts +2 -0
- package/dist/training/trainer.service.test.d.ts.map +1 -0
- package/dist/training/trainer.service.test.js +99 -0
- package/package.json +52 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const model_registry_1 = require("../registry/model.registry");
|
|
13
|
+
const predictor_service_1 = require("./predictor.service");
|
|
14
|
+
const decorators_1 = require("../decorators");
|
|
15
|
+
describe('PredictorService', () => {
|
|
16
|
+
let registry;
|
|
17
|
+
let predictor;
|
|
18
|
+
let TestModel = class TestModel {
|
|
19
|
+
async train() {
|
|
20
|
+
return { accuracy: 0.9 };
|
|
21
|
+
}
|
|
22
|
+
async predict(input) {
|
|
23
|
+
return { sentiment: 'positive', score: 0.92, input };
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, decorators_1.Train)(),
|
|
28
|
+
__metadata("design:type", Function),
|
|
29
|
+
__metadata("design:paramtypes", []),
|
|
30
|
+
__metadata("design:returntype", Promise)
|
|
31
|
+
], TestModel.prototype, "train", null);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, decorators_1.Predict)(),
|
|
34
|
+
__metadata("design:type", Function),
|
|
35
|
+
__metadata("design:paramtypes", [Object]),
|
|
36
|
+
__metadata("design:returntype", Promise)
|
|
37
|
+
], TestModel.prototype, "predict", null);
|
|
38
|
+
TestModel = __decorate([
|
|
39
|
+
(0, decorators_1.Model)({ name: 'test-model', version: '1.0.0', framework: 'tensorflow' })
|
|
40
|
+
], TestModel);
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
registry = new model_registry_1.ModelRegistry();
|
|
43
|
+
predictor = new predictor_service_1.PredictorService(registry);
|
|
44
|
+
registry.register({
|
|
45
|
+
metadata: { name: 'test-model', version: '1.0.0', framework: 'tensorflow' },
|
|
46
|
+
instance: new TestModel(),
|
|
47
|
+
trainMethod: 'train',
|
|
48
|
+
predictMethod: 'predict',
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
it('predicts and returns result', async () => {
|
|
52
|
+
const result = await predictor.predict('test-model', 'hello');
|
|
53
|
+
expect(result).toEqual({ sentiment: 'positive', score: 0.92, input: 'hello' });
|
|
54
|
+
});
|
|
55
|
+
it('predicts with specific version', async () => {
|
|
56
|
+
const result = await predictor.predict('test-model', 'hi', '1.0.0');
|
|
57
|
+
expect(result.sentiment).toBe('positive');
|
|
58
|
+
});
|
|
59
|
+
it('throws when model not found', async () => {
|
|
60
|
+
await expect(predictor.predict('unknown', {})).rejects.toThrow('Model not found: unknown');
|
|
61
|
+
});
|
|
62
|
+
it('throws when model has no prediction method', async () => {
|
|
63
|
+
let NoPredictModel = class NoPredictModel {
|
|
64
|
+
train() { }
|
|
65
|
+
};
|
|
66
|
+
__decorate([
|
|
67
|
+
(0, decorators_1.Train)(),
|
|
68
|
+
__metadata("design:type", Function),
|
|
69
|
+
__metadata("design:paramtypes", []),
|
|
70
|
+
__metadata("design:returntype", void 0)
|
|
71
|
+
], NoPredictModel.prototype, "train", null);
|
|
72
|
+
NoPredictModel = __decorate([
|
|
73
|
+
(0, decorators_1.Model)({ name: 'no-predict', version: '1.0.0', framework: 'tensorflow' })
|
|
74
|
+
], NoPredictModel);
|
|
75
|
+
registry.register({
|
|
76
|
+
metadata: { name: 'no-predict', version: '1.0.0', framework: 'tensorflow' },
|
|
77
|
+
instance: new NoPredictModel(),
|
|
78
|
+
trainMethod: 'train',
|
|
79
|
+
});
|
|
80
|
+
await expect(predictor.predict('no-predict', {})).rejects.toThrow('no-predict has no prediction method');
|
|
81
|
+
});
|
|
82
|
+
it('discoverPredictMethod finds @Predict decorated method', () => {
|
|
83
|
+
const instance = new TestModel();
|
|
84
|
+
expect(predictor.discoverPredictMethod(instance)).toBe('predict');
|
|
85
|
+
});
|
|
86
|
+
it('throws when predict method is not a function', async () => {
|
|
87
|
+
const fakeInstance = {
|
|
88
|
+
predict: 'not-a-function',
|
|
89
|
+
};
|
|
90
|
+
registry.register({
|
|
91
|
+
metadata: { name: 'broken-model', version: '1.0.0', framework: 'custom' },
|
|
92
|
+
instance: fakeInstance,
|
|
93
|
+
trainMethod: undefined,
|
|
94
|
+
predictMethod: 'predict',
|
|
95
|
+
});
|
|
96
|
+
await expect(predictor.predict('broken-model', {})).rejects.toThrow('Prediction method predict not found on model');
|
|
97
|
+
});
|
|
98
|
+
it('discoverPredictMethod returns undefined when no @Predict method', () => {
|
|
99
|
+
let NoPredictClass = class NoPredictClass {
|
|
100
|
+
train() { }
|
|
101
|
+
someMethod() { }
|
|
102
|
+
};
|
|
103
|
+
__decorate([
|
|
104
|
+
(0, decorators_1.Train)(),
|
|
105
|
+
__metadata("design:type", Function),
|
|
106
|
+
__metadata("design:paramtypes", []),
|
|
107
|
+
__metadata("design:returntype", void 0)
|
|
108
|
+
], NoPredictClass.prototype, "train", null);
|
|
109
|
+
NoPredictClass = __decorate([
|
|
110
|
+
(0, decorators_1.Model)({ name: 'no-predict-method', version: '1.0.0', framework: 'custom' })
|
|
111
|
+
], NoPredictClass);
|
|
112
|
+
const instance = new NoPredictClass();
|
|
113
|
+
expect(predictor.discoverPredictMethod(instance)).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ModelRegistry } from './registry/model.registry';
|
|
2
|
+
import { TrainerService } from './training/trainer.service';
|
|
3
|
+
import { PredictorService } from './inference/predictor.service';
|
|
4
|
+
/**
|
|
5
|
+
* Registers an ML model instance with the registry.
|
|
6
|
+
* Call this from your model's constructor when injecting ModelRegistry.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* @Model({ name: 'sentiment', version: '1.0.0', framework: 'tensorflow' })
|
|
11
|
+
* @Injectable()
|
|
12
|
+
* class SentimentModel extends MLModelBase {
|
|
13
|
+
* constructor(registry: ModelRegistry, trainer: TrainerService, predictor: PredictorService) {
|
|
14
|
+
* super(registry, trainer, predictor);
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function registerMLModel(instance: object, registry: ModelRegistry, trainerService: TrainerService, predictorService: PredictorService): void;
|
|
20
|
+
//# sourceMappingURL=ml-model.base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ml-model.base.d.ts","sourceRoot":"","sources":["../src/ml-model.base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,aAAa,EACvB,cAAc,EAAE,cAAc,EAC9B,gBAAgB,EAAE,gBAAgB,GACjC,IAAI,CAcN"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerMLModel = registerMLModel;
|
|
4
|
+
const decorators_1 = require("./decorators");
|
|
5
|
+
/**
|
|
6
|
+
* Registers an ML model instance with the registry.
|
|
7
|
+
* Call this from your model's constructor when injecting ModelRegistry.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* @Model({ name: 'sentiment', version: '1.0.0', framework: 'tensorflow' })
|
|
12
|
+
* @Injectable()
|
|
13
|
+
* class SentimentModel extends MLModelBase {
|
|
14
|
+
* constructor(registry: ModelRegistry, trainer: TrainerService, predictor: PredictorService) {
|
|
15
|
+
* super(registry, trainer, predictor);
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function registerMLModel(instance, registry, trainerService, predictorService) {
|
|
21
|
+
const metadata = (0, decorators_1.getModelMetadata)(instance.constructor);
|
|
22
|
+
if (!metadata)
|
|
23
|
+
return;
|
|
24
|
+
const trainMethod = trainerService.discoverTrainMethod(instance);
|
|
25
|
+
const predictMethod = predictorService.discoverPredictMethod(instance);
|
|
26
|
+
const registered = {
|
|
27
|
+
metadata,
|
|
28
|
+
instance,
|
|
29
|
+
trainMethod,
|
|
30
|
+
predictMethod,
|
|
31
|
+
};
|
|
32
|
+
registry.register(registered);
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ml-model.base.test.d.ts","sourceRoot":"","sources":["../src/ml-model.base.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const ml_model_base_1 = require("./ml-model.base");
|
|
13
|
+
const model_registry_1 = require("./registry/model.registry");
|
|
14
|
+
const trainer_service_1 = require("./training/trainer.service");
|
|
15
|
+
const predictor_service_1 = require("./inference/predictor.service");
|
|
16
|
+
const decorators_1 = require("./decorators");
|
|
17
|
+
let RegisterTestModel = class RegisterTestModel {
|
|
18
|
+
train() { }
|
|
19
|
+
predict() { }
|
|
20
|
+
};
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, decorators_1.Train)(),
|
|
23
|
+
__metadata("design:type", Function),
|
|
24
|
+
__metadata("design:paramtypes", []),
|
|
25
|
+
__metadata("design:returntype", void 0)
|
|
26
|
+
], RegisterTestModel.prototype, "train", null);
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, decorators_1.Predict)(),
|
|
29
|
+
__metadata("design:type", Function),
|
|
30
|
+
__metadata("design:paramtypes", []),
|
|
31
|
+
__metadata("design:returntype", void 0)
|
|
32
|
+
], RegisterTestModel.prototype, "predict", null);
|
|
33
|
+
RegisterTestModel = __decorate([
|
|
34
|
+
(0, decorators_1.Model)({ name: 'register-test', version: '1.0.0', framework: 'tensorflow' })
|
|
35
|
+
], RegisterTestModel);
|
|
36
|
+
describe('registerMLModel', () => {
|
|
37
|
+
it('registers model with registry', () => {
|
|
38
|
+
const registry = new model_registry_1.ModelRegistry();
|
|
39
|
+
const trainer = new trainer_service_1.TrainerService(registry);
|
|
40
|
+
const predictor = new predictor_service_1.PredictorService(registry);
|
|
41
|
+
const instance = new RegisterTestModel();
|
|
42
|
+
(0, ml_model_base_1.registerMLModel)(instance, registry, trainer, predictor);
|
|
43
|
+
const registered = registry.get('register-test', '1.0.0');
|
|
44
|
+
expect(registered).toBeDefined();
|
|
45
|
+
expect(registered?.trainMethod).toBe('train');
|
|
46
|
+
expect(registered?.predictMethod).toBe('predict');
|
|
47
|
+
});
|
|
48
|
+
it('does nothing for class without @Model', () => {
|
|
49
|
+
const registry = new model_registry_1.ModelRegistry();
|
|
50
|
+
const trainer = new trainer_service_1.TrainerService(registry);
|
|
51
|
+
const predictor = new predictor_service_1.PredictorService(registry);
|
|
52
|
+
class PlainClass {
|
|
53
|
+
}
|
|
54
|
+
(0, ml_model_base_1.registerMLModel)(new PlainClass(), registry, trainer, predictor);
|
|
55
|
+
expect(registry.list()).toHaveLength(0);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Type } from '@hazeljs/core';
|
|
2
|
+
export declare const ML_MODELS: unique symbol;
|
|
3
|
+
export interface MLModuleOptions {
|
|
4
|
+
models?: Type<unknown>[];
|
|
5
|
+
}
|
|
6
|
+
export declare class MLModule {
|
|
7
|
+
private static options;
|
|
8
|
+
/**
|
|
9
|
+
* Configure MLModule with models to register
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* imports: [
|
|
14
|
+
* MLModule.forRoot({
|
|
15
|
+
* models: [SentimentModel],
|
|
16
|
+
* }),
|
|
17
|
+
* ]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
static forRoot(options?: MLModuleOptions): {
|
|
21
|
+
module: typeof MLModule;
|
|
22
|
+
providers: unknown[];
|
|
23
|
+
exports: unknown[];
|
|
24
|
+
};
|
|
25
|
+
static getOptions(): MLModuleOptions;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=ml.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ml.module.d.ts","sourceRoot":"","sources":["../src/ml.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAUtF,eAAO,MAAM,SAAS,eAA4B,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;CAC1B;AAkCD,qBAkBa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAuB;IAE7C;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,eAAoB,GAAG;QAC7C,MAAM,EAAE,OAAO,QAAQ,CAAC;QACxB,SAAS,EAAE,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,EAAE,CAAC;KACpB;IA8BD,MAAM,CAAC,UAAU,IAAI,eAAe;CAGrC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var MLModule_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.MLModule = exports.ML_MODELS = void 0;
|
|
17
|
+
const core_1 = require("@hazeljs/core");
|
|
18
|
+
const model_registry_1 = require("./registry/model.registry");
|
|
19
|
+
const trainer_service_1 = require("./training/trainer.service");
|
|
20
|
+
const pipeline_service_1 = require("./training/pipeline.service");
|
|
21
|
+
const predictor_service_1 = require("./inference/predictor.service");
|
|
22
|
+
const batch_service_1 = require("./inference/batch.service");
|
|
23
|
+
const metrics_service_1 = require("./evaluation/metrics.service");
|
|
24
|
+
const decorators_1 = require("./decorators");
|
|
25
|
+
exports.ML_MODELS = Symbol('hazel:ml:models');
|
|
26
|
+
/**
|
|
27
|
+
* Bootstrap that registers models with the registry when instantiated.
|
|
28
|
+
* Added as a provider when using MLModule.forRoot({ models: [...] }).
|
|
29
|
+
*/
|
|
30
|
+
let MLModelBootstrap = class MLModelBootstrap {
|
|
31
|
+
constructor(modelRegistry, trainerService, predictorService, modelTypes) {
|
|
32
|
+
this.modelRegistry = modelRegistry;
|
|
33
|
+
this.trainerService = trainerService;
|
|
34
|
+
this.predictorService = predictorService;
|
|
35
|
+
this.modelTypes = modelTypes;
|
|
36
|
+
const container = core_1.Container.getInstance();
|
|
37
|
+
for (const ModelClass of this.modelTypes) {
|
|
38
|
+
const metadata = (0, decorators_1.getModelMetadata)(ModelClass);
|
|
39
|
+
if (!metadata)
|
|
40
|
+
continue;
|
|
41
|
+
const instance = container.resolve(ModelClass);
|
|
42
|
+
const trainMethod = this.trainerService.discoverTrainMethod(instance);
|
|
43
|
+
const predictMethod = this.predictorService.discoverPredictMethod(instance);
|
|
44
|
+
const registered = {
|
|
45
|
+
metadata,
|
|
46
|
+
instance,
|
|
47
|
+
trainMethod,
|
|
48
|
+
predictMethod,
|
|
49
|
+
};
|
|
50
|
+
this.modelRegistry.register(registered);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
MLModelBootstrap = __decorate([
|
|
55
|
+
(0, core_1.Injectable)(),
|
|
56
|
+
__param(3, (0, core_1.Inject)(exports.ML_MODELS)),
|
|
57
|
+
__metadata("design:paramtypes", [model_registry_1.ModelRegistry,
|
|
58
|
+
trainer_service_1.TrainerService,
|
|
59
|
+
predictor_service_1.PredictorService, Array])
|
|
60
|
+
], MLModelBootstrap);
|
|
61
|
+
let MLModule = MLModule_1 = class MLModule {
|
|
62
|
+
/**
|
|
63
|
+
* Configure MLModule with models to register
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* imports: [
|
|
68
|
+
* MLModule.forRoot({
|
|
69
|
+
* models: [SentimentModel],
|
|
70
|
+
* }),
|
|
71
|
+
* ]
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
static forRoot(options = {}) {
|
|
75
|
+
MLModule_1.options = options;
|
|
76
|
+
const models = options.models || [];
|
|
77
|
+
const providers = [
|
|
78
|
+
model_registry_1.ModelRegistry,
|
|
79
|
+
trainer_service_1.TrainerService,
|
|
80
|
+
pipeline_service_1.PipelineService,
|
|
81
|
+
predictor_service_1.PredictorService,
|
|
82
|
+
batch_service_1.BatchService,
|
|
83
|
+
metrics_service_1.MetricsService,
|
|
84
|
+
...models,
|
|
85
|
+
{ provide: exports.ML_MODELS, useValue: models },
|
|
86
|
+
MLModelBootstrap,
|
|
87
|
+
];
|
|
88
|
+
return {
|
|
89
|
+
module: MLModule_1,
|
|
90
|
+
providers,
|
|
91
|
+
exports: [
|
|
92
|
+
model_registry_1.ModelRegistry,
|
|
93
|
+
trainer_service_1.TrainerService,
|
|
94
|
+
pipeline_service_1.PipelineService,
|
|
95
|
+
predictor_service_1.PredictorService,
|
|
96
|
+
batch_service_1.BatchService,
|
|
97
|
+
metrics_service_1.MetricsService,
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
static getOptions() {
|
|
102
|
+
return MLModule_1.options;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
exports.MLModule = MLModule;
|
|
106
|
+
MLModule.options = {};
|
|
107
|
+
exports.MLModule = MLModule = MLModule_1 = __decorate([
|
|
108
|
+
(0, core_1.HazelModule)({
|
|
109
|
+
providers: [
|
|
110
|
+
model_registry_1.ModelRegistry,
|
|
111
|
+
trainer_service_1.TrainerService,
|
|
112
|
+
pipeline_service_1.PipelineService,
|
|
113
|
+
predictor_service_1.PredictorService,
|
|
114
|
+
batch_service_1.BatchService,
|
|
115
|
+
metrics_service_1.MetricsService,
|
|
116
|
+
],
|
|
117
|
+
exports: [
|
|
118
|
+
model_registry_1.ModelRegistry,
|
|
119
|
+
trainer_service_1.TrainerService,
|
|
120
|
+
pipeline_service_1.PipelineService,
|
|
121
|
+
predictor_service_1.PredictorService,
|
|
122
|
+
batch_service_1.BatchService,
|
|
123
|
+
metrics_service_1.MetricsService,
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
], MLModule);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ml.module.test.d.ts","sourceRoot":"","sources":["../src/ml.module.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const ml_module_1 = require("./ml.module");
|
|
13
|
+
const decorators_1 = require("./decorators");
|
|
14
|
+
let TestModel = class TestModel {
|
|
15
|
+
train() { }
|
|
16
|
+
predict() { }
|
|
17
|
+
};
|
|
18
|
+
__decorate([
|
|
19
|
+
(0, decorators_1.Train)(),
|
|
20
|
+
__metadata("design:type", Function),
|
|
21
|
+
__metadata("design:paramtypes", []),
|
|
22
|
+
__metadata("design:returntype", void 0)
|
|
23
|
+
], TestModel.prototype, "train", null);
|
|
24
|
+
__decorate([
|
|
25
|
+
(0, decorators_1.Predict)(),
|
|
26
|
+
__metadata("design:type", Function),
|
|
27
|
+
__metadata("design:paramtypes", []),
|
|
28
|
+
__metadata("design:returntype", void 0)
|
|
29
|
+
], TestModel.prototype, "predict", null);
|
|
30
|
+
TestModel = __decorate([
|
|
31
|
+
(0, decorators_1.Model)({ name: 'test', version: '1.0.0', framework: 'tensorflow' })
|
|
32
|
+
], TestModel);
|
|
33
|
+
describe('MLModule', () => {
|
|
34
|
+
describe('forRoot', () => {
|
|
35
|
+
it('returns dynamic module structure', () => {
|
|
36
|
+
const result = ml_module_1.MLModule.forRoot();
|
|
37
|
+
expect(result).toHaveProperty('module', ml_module_1.MLModule);
|
|
38
|
+
expect(result).toHaveProperty('providers');
|
|
39
|
+
expect(result).toHaveProperty('exports');
|
|
40
|
+
expect(Array.isArray(result.providers)).toBe(true);
|
|
41
|
+
expect(result.providers.length).toBeGreaterThan(0);
|
|
42
|
+
});
|
|
43
|
+
it('includes models in providers when specified', () => {
|
|
44
|
+
const result = ml_module_1.MLModule.forRoot({ models: [TestModel] });
|
|
45
|
+
expect(result.providers).toContain(TestModel);
|
|
46
|
+
});
|
|
47
|
+
it('includes ML_MODELS and MLModelBootstrap when models provided', () => {
|
|
48
|
+
const result = ml_module_1.MLModule.forRoot({ models: [TestModel] });
|
|
49
|
+
const mlModels = result.providers.find((p) => p && typeof p === 'object' && 'provide' in p);
|
|
50
|
+
expect(mlModels).toBeDefined();
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('getOptions', () => {
|
|
54
|
+
it('returns last forRoot options', () => {
|
|
55
|
+
ml_module_1.MLModule.forRoot({ models: [TestModel] });
|
|
56
|
+
const opts = ml_module_1.MLModule.getOptions();
|
|
57
|
+
expect(opts.models).toContain(TestModel);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hazeljs/ml - Type definitions for ML models and operations
|
|
3
|
+
*/
|
|
4
|
+
export type MLFramework = 'tensorflow' | 'onnx' | 'custom';
|
|
5
|
+
export interface ModelMetadata {
|
|
6
|
+
name: string;
|
|
7
|
+
version: string;
|
|
8
|
+
framework: MLFramework;
|
|
9
|
+
description?: string;
|
|
10
|
+
tags?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface TrainingData {
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface TrainingResult {
|
|
16
|
+
accuracy?: number;
|
|
17
|
+
loss?: number;
|
|
18
|
+
metrics?: Record<string, number>;
|
|
19
|
+
modelPath?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface PredictionResult<T = unknown> {
|
|
22
|
+
[key: string]: T;
|
|
23
|
+
}
|
|
24
|
+
export interface ModelVersion {
|
|
25
|
+
version: string;
|
|
26
|
+
createdAt: Date;
|
|
27
|
+
path?: string;
|
|
28
|
+
metrics?: Record<string, number>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=ml.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ml.types.d.ts","sourceRoot":"","sources":["../src/ml.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
|
package/dist/ml.types.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ModelMetadata, ModelVersion } from '../ml.types';
|
|
2
|
+
export interface RegisteredModel {
|
|
3
|
+
metadata: ModelMetadata;
|
|
4
|
+
instance: object;
|
|
5
|
+
trainMethod?: string;
|
|
6
|
+
predictMethod?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Model Registry - Handles model versioning and storage
|
|
10
|
+
* Integrates with TensorFlow.js, ONNX Runtime for model persistence
|
|
11
|
+
*/
|
|
12
|
+
export declare class ModelRegistry {
|
|
13
|
+
private models;
|
|
14
|
+
private versions;
|
|
15
|
+
register(model: RegisteredModel): void;
|
|
16
|
+
get(name: string, version?: string): RegisteredModel | undefined;
|
|
17
|
+
list(): ModelMetadata[];
|
|
18
|
+
getVersions(name: string): ModelVersion[];
|
|
19
|
+
unregister(name: string, version: string): boolean;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=model.registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.registry.d.ts","sourceRoot":"","sources":["../../src/registry/model.registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG1D,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,qBACa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,CAAC,QAAQ,CAA0C;IAE1D,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IActC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAUhE,IAAI,IAAI,aAAa,EAAE;IAIvB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE;IAIzC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;CAUnD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ModelRegistry = void 0;
|
|
13
|
+
const core_1 = require("@hazeljs/core");
|
|
14
|
+
const core_2 = __importDefault(require("@hazeljs/core"));
|
|
15
|
+
/**
|
|
16
|
+
* Model Registry - Handles model versioning and storage
|
|
17
|
+
* Integrates with TensorFlow.js, ONNX Runtime for model persistence
|
|
18
|
+
*/
|
|
19
|
+
let ModelRegistry = class ModelRegistry {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.models = new Map();
|
|
22
|
+
this.versions = new Map();
|
|
23
|
+
}
|
|
24
|
+
register(model) {
|
|
25
|
+
const key = `${model.metadata.name}@${model.metadata.version}`;
|
|
26
|
+
this.models.set(key, model);
|
|
27
|
+
const versions = this.versions.get(model.metadata.name) || [];
|
|
28
|
+
versions.push({
|
|
29
|
+
version: model.metadata.version,
|
|
30
|
+
createdAt: new Date(),
|
|
31
|
+
});
|
|
32
|
+
this.versions.set(model.metadata.name, versions);
|
|
33
|
+
core_2.default.debug(`Registered model: ${key}`);
|
|
34
|
+
}
|
|
35
|
+
get(name, version) {
|
|
36
|
+
if (version) {
|
|
37
|
+
return this.models.get(`${name}@${version}`);
|
|
38
|
+
}
|
|
39
|
+
// Return latest version
|
|
40
|
+
const versions = this.versions.get(name) || [];
|
|
41
|
+
const latest = versions[versions.length - 1];
|
|
42
|
+
return latest ? this.models.get(`${name}@${latest.version}`) : undefined;
|
|
43
|
+
}
|
|
44
|
+
list() {
|
|
45
|
+
return Array.from(this.models.values()).map((m) => m.metadata);
|
|
46
|
+
}
|
|
47
|
+
getVersions(name) {
|
|
48
|
+
return this.versions.get(name) || [];
|
|
49
|
+
}
|
|
50
|
+
unregister(name, version) {
|
|
51
|
+
const key = `${name}@${version}`;
|
|
52
|
+
const deleted = this.models.delete(key);
|
|
53
|
+
if (deleted) {
|
|
54
|
+
const versions = this.versions.get(name) || [];
|
|
55
|
+
const filtered = versions.filter((v) => v.version !== version);
|
|
56
|
+
this.versions.set(name, filtered);
|
|
57
|
+
}
|
|
58
|
+
return deleted;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
exports.ModelRegistry = ModelRegistry;
|
|
62
|
+
exports.ModelRegistry = ModelRegistry = __decorate([
|
|
63
|
+
(0, core_1.Service)()
|
|
64
|
+
], ModelRegistry);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.registry.test.d.ts","sourceRoot":"","sources":["../../src/registry/model.registry.test.ts"],"names":[],"mappings":""}
|