Skip to content

Commit

Permalink
change(ml): Drop the feature to publish from an AutoML Model (#1974)
Browse files Browse the repository at this point in the history
* Deprecating the feature to publish from an AutoML Model

* Empty-Commit to trigger CI

---------

Co-authored-by: Lahiru Maramba <[email protected]>
pavelgj and lahirumaramba authored Nov 30, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent e7c4258 commit ffae70c
Showing 8 changed files with 5 additions and 201 deletions.
4 changes: 0 additions & 4 deletions etc/firebase-admin.api.md
Original file line number Diff line number Diff line change
@@ -320,10 +320,6 @@ export function machineLearning(app?: App): machineLearning.MachineLearning;

// @public (undocumented)
export namespace machineLearning {
// Warning: (ae-forgotten-export) The symbol "AutoMLTfliteModelOptions" needs to be exported by the entry point default-namespace.d.ts
//
// @deprecated
export type AutoMLTfliteModelOptions = AutoMLTfliteModelOptions;
// Warning: (ae-forgotten-export) The symbol "GcsTfliteModelOptions" needs to be exported by the entry point default-namespace.d.ts
export type GcsTfliteModelOptions = GcsTfliteModelOptions;
// Warning: (ae-forgotten-export) The symbol "ListModelsOptions" needs to be exported by the entry point default-namespace.d.ts
12 changes: 1 addition & 11 deletions etc/firebase-admin.machine-learning.api.md
Original file line number Diff line number Diff line change
@@ -8,14 +8,6 @@

import { Agent } from 'http';

// @public @deprecated (undocumented)
export interface AutoMLTfliteModelOptions extends ModelOptionsBase {
// (undocumented)
tfliteModel: {
automlModel: string;
};
}

// @public (undocumented)
export interface GcsTfliteModelOptions extends ModelOptionsBase {
// (undocumented)
@@ -74,7 +66,7 @@ export class Model {
}

// @public (undocumented)
export type ModelOptions = ModelOptionsBase | GcsTfliteModelOptions | AutoMLTfliteModelOptions;
export type ModelOptions = ModelOptionsBase | GcsTfliteModelOptions;

// @public
export interface ModelOptionsBase {
@@ -86,8 +78,6 @@ export interface ModelOptionsBase {

// @public
export interface TFLiteModel {
// @deprecated
readonly automlModel?: string;
readonly gcsTfliteUri?: string;
readonly sizeBytes: number;
}
1 change: 0 additions & 1 deletion src/machine-learning/index.ts
Original file line number Diff line number Diff line change
@@ -31,7 +31,6 @@ export {
TFLiteModel,
} from './machine-learning';
export {
AutoMLTfliteModelOptions,
GcsTfliteModelOptions,
ListModelsOptions,
ModelOptions,
12 changes: 1 addition & 11 deletions src/machine-learning/machine-learning-api-client.ts
Original file line number Diff line number Diff line change
@@ -38,16 +38,7 @@ export interface GcsTfliteModelOptions extends ModelOptionsBase {
};
}

/**
* @deprecated AutoMLTfliteModelOptions will be removed in the next major version.
*/
export interface AutoMLTfliteModelOptions extends ModelOptionsBase {
tfliteModel: {
automlModel: string;
};
}

export type ModelOptions = ModelOptionsBase | GcsTfliteModelOptions | AutoMLTfliteModelOptions;
export type ModelOptions = ModelOptionsBase | GcsTfliteModelOptions;

/**
* Interface representing options for listing Models.
@@ -108,7 +99,6 @@ export interface ModelContent {
};
readonly tfliteModel?: {
readonly gcsTfliteUri?: string;
readonly automlModel?: string;

readonly sizeBytes: number;
};
8 changes: 0 additions & 8 deletions src/machine-learning/machine-learning-namespace.ts
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ import {
TFLiteModel as TTFLiteModel,
} from './machine-learning';
import {
AutoMLTfliteModelOptions as TAutoMLTfliteModelOptions,
GcsTfliteModelOptions as TGcsTfliteModelOptions,
ListModelsOptions as TListModelsOptions,
ModelOptions as TModelOptions,
@@ -80,13 +79,6 @@ export namespace machineLearning {
*/
export type TFLiteModel = TTFLiteModel;

/**
* Type alias to {@link firebase-admin.machine-learning#AutoMLTfliteModelOptions}.
*
* @deprecated AutoMLTfliteModelOptions will be removed in the next major version.
*/
export type AutoMLTfliteModelOptions = TAutoMLTfliteModelOptions;

/**
* Type alias to {@link firebase-admin.machine-learning#GcsTfliteModelOptions}.
*/
16 changes: 2 additions & 14 deletions src/machine-learning/machine-learning.ts
Original file line number Diff line number Diff line change
@@ -40,23 +40,13 @@ export interface ListModelsResult {

/**
* A TensorFlow Lite Model output object
*
* One of either the `gcsTfliteUri` or `automlModel` properties will be
* defined.
*/
export interface TFLiteModel {
/** The size of the model. */
readonly sizeBytes: number;

/** The URI from which the model was originally provided to Firebase. */
readonly gcsTfliteUri?: string;
/**
* The AutoML model reference from which the model was originally provided
* to Firebase.
*
* @deprecated AutoML model support will be removed in the next major version.
*/
readonly automlModel?: string;
}

/**
@@ -400,11 +390,9 @@ export class Model {
}
const tmpModel = deepCopy(model);

// If tflite Model is specified, it must have a source consisting of
// oneof {gcsTfliteUri, automlModel}
// If tflite Model is specified, it must have a source of {gcsTfliteUri}
if (model.tfliteModel &&
!validator.isNonEmptyString(model.tfliteModel.gcsTfliteUri) &&
!validator.isNonEmptyString(model.tfliteModel.automlModel)) {
!validator.isNonEmptyString(model.tfliteModel.gcsTfliteUri)) {
// If we have some other source, ignore the whole tfliteModel.
delete (tmpModel as any).tfliteModel;
}
89 changes: 1 addition & 88 deletions test/integration/machine-learning.spec.ts
Original file line number Diff line number Diff line change
@@ -17,11 +17,10 @@

import path = require('path');
import * as chai from 'chai';
import { projectId } from './setup';
import { Bucket } from '@google-cloud/storage';
import { getStorage } from '../../lib/storage/index';
import {
AutoMLTfliteModelOptions, GcsTfliteModelOptions, Model, ModelOptions, getMachineLearning,
GcsTfliteModelOptions, Model, ModelOptions, getMachineLearning,
} from '../../lib/machine-learning/index';

const expect = chai.expect;
@@ -104,31 +103,6 @@ describe('admin.machineLearning', () => {
});
});

it('creates a new Model with valid AutoML TFLite ModelFormat', function () {
// AutoML models require verification. This takes between 20 and 60 seconds
this.timeout(60000); // Allow up to 60 seconds for this test.
return getAutoMLModelReference()
.then((automlRef: string) => {
if (!automlRef) {
this.skip();
return;
}
const modelOptions: ModelOptions = {
displayName: 'node-integ-test-create-automl',
tags: ['tagAutoml'],
tfliteModel: { automlModel: automlRef }
};
return getMachineLearning().createModel(modelOptions)
.then((model) => {
return model.waitForUnlocked(55000)
.then(() => {
scheduleForDelete(model);
verifyModel(model, modelOptions);
});
});
});
});

it('creates a new Model with invalid ModelFormat', () => {
// Upload a file to default gcs bucket
const modelOptions: ModelOptions = {
@@ -233,33 +207,6 @@ describe('admin.machineLearning', () => {
});
});

it('updates the automl model', function () {
// AutoML models require verification. This takes between 20 and 60 seconds
this.timeout(60000); // Allow up to 60 seconds for this test.
return createTemporaryModel({
displayName: 'node-integ-test-update-automl'
}).then((model) => {

return getAutoMLModelReference()
.then((automlRef: string) => {
if (!automlRef) {
this.skip();
return;
}
const modelOptions: ModelOptions = {
tfliteModel: { automlModel: automlRef },
};
return getMachineLearning().updateModel(model.modelId, modelOptions)
.then((updatedModel) => {
return updatedModel.waitForUnlocked(55000)
.then(() => {
verifyModel(updatedModel, modelOptions);
});
});
});
});
});

it('can update more than 1 field', () => {
const DISPLAY_NAME = 'node-integ-test-update-3b';
const TAGS = ['node-integ-tag-1', 'node-integ-tag-2'];
@@ -540,8 +487,6 @@ function verifyModel(model: Model, expectedOptions: ModelOptions): void {
}
if ((expectedOptions as GcsTfliteModelOptions).tfliteModel?.gcsTfliteUri !== undefined) {
verifyGcsTfliteModel(model, (expectedOptions as GcsTfliteModelOptions));
} else if ((expectedOptions as AutoMLTfliteModelOptions).tfliteModel?.automlModel !== undefined) {
verifyAutomlTfliteModel(model, (expectedOptions as AutoMLTfliteModelOptions));
} else {
expect(model.validationError).to.equal('No model file has been uploaded.');
}
@@ -558,35 +503,3 @@ function verifyGcsTfliteModel(model: Model, expectedOptions: GcsTfliteModelOptio
expect(model.validationError).to.be.undefined;
}
}

function verifyAutomlTfliteModel(model: Model, expectedOptions: AutoMLTfliteModelOptions): void {
const expectedAutomlReference = expectedOptions.tfliteModel.automlModel;
expect(model.tfliteModel!.automlModel).to.equal(expectedAutomlReference);
expect(model.validationError).to.be.undefined;
expect(model.tfliteModel!.sizeBytes).to.not.be.undefined;
expect(model.modelHash).to.not.be.undefined;
}

function getAutoMLModelReference(): Promise<string> {
let automl;
try {
const { AutoMlClient } = require('@google-cloud/automl').v1;
automl = new AutoMlClient();
}
catch (error) {
// Returning an empty string will result in skipping the test.
return Promise.resolve('');
}

const parent = automl.locationPath(projectId, 'us-central1');
return automl.listModels({ parent, filter:'displayName=admin_sdk_integ_test1' })
.then(([models]: [any]) => {
let modelRef = '';
for (const model of models) {
modelRef = model.name;
}
return modelRef;
})
// Skip the test if anything goes wrong with listing the models.
.catch(() => '');
}
64 changes: 0 additions & 64 deletions test/unit/machine-learning/machine-learning-api-client.spec.ts
Original file line number Diff line number Diff line change
@@ -64,20 +64,6 @@ describe('MachineLearningApiClient', () => {
sizeBytes: 2220022,
},
};
const MODEL_RESPONSE_AUTOML = {
name: 'projects/test-project/models/3456789',
createTime: '2020-07-15T18:12:25.123987Z',
updateTime: '2020-07-15T19:15:32.965435Z',
etag: 'etag345',
modelHash: 'modelHash345',
displayName: 'model_automl',
tags: ['tag_automl'],
state: { published: true },
tfliteModel: {
automlModel: 'projects/65432/models/ICN123',
sizeBytes: 3330033,
},
};

const PROJECT_ID = 'test-project';
const PROJECT_NUMBER = '1234567';
@@ -105,10 +91,6 @@ describe('MachineLearningApiClient', () => {
},
done: false,
};
const OPERATION_AUTOML_RESPONSE = {
done: true,
response: MODEL_RESPONSE_AUTOML,
};
const LOCKED_MODEL_RESPONSE = {
name: 'projects/test-project/models/1234567',
createTime: '2020-02-07T23:45:23.288047Z',
@@ -179,12 +161,6 @@ describe('MachineLearningApiClient', () => {
gcsTfliteUri: 'gcsUri1',
},
};
const AUTOML_OPTIONS: ModelOptions = {
displayName: 'name3',
tfliteModel: {
automlModel: 'automlModel',
},
};

const invalidContent: any[] = [null, undefined, {}, { tags: [] }];
invalidContent.forEach((content) => {
@@ -236,19 +212,6 @@ describe('MachineLearningApiClient', () => {
});
});

it('should accept AutoML options', () => {
const stub = sinon
.stub(HttpClient.prototype, 'send')
.resolves(utils.responseFrom(OPERATION_AUTOML_RESPONSE));
stubs.push(stub);
return apiClient.createModel(AUTOML_OPTIONS)
.then((resp) => {
expect(resp.done).to.be.true;
expect(resp.name).to.be.undefined;
expect(resp.response).to.deep.equal(MODEL_RESPONSE_AUTOML);
});
});

it('should resolve with error when the operation fails', () => {
const stub = sinon
.stub(HttpClient.prototype, 'send')
@@ -302,20 +265,12 @@ describe('MachineLearningApiClient', () => {
gcsTfliteUri: 'gcsUri1',
},
};
const AUTOML_OPTIONS: ModelOptions = {
displayName: 'name3',
tfliteModel: {
automlModel: 'automlModel',
},
};

const NAME_ONLY_MASK_LIST = ['displayName'];
const GCS_MASK_LIST = ['displayName', 'tfliteModel.gcsTfliteUri'];
const AUTOML_MASK_LIST = ['displayName', 'tfliteModel.automlModel'];

const NAME_ONLY_UPDATE_MASK_STRING = 'updateMask=displayName';
const GCS_UPDATE_MASK_STRING = 'updateMask=displayName,tfliteModel.gcsTfliteUri';
const AUTOML_UPDATE_MASK_STRING = 'updateMask=displayName,tfliteModel.automlModel';

const invalidOptions: any[] = [null, undefined];
invalidOptions.forEach((option) => {
@@ -385,25 +340,6 @@ describe('MachineLearningApiClient', () => {
});
});

it('should resolve with the updated AutoML resource on success', () => {
const stub = sinon
.stub(HttpClient.prototype, 'send')
.resolves(utils.responseFrom(OPERATION_SUCCESS_RESPONSE));
stubs.push(stub);
return apiClient.updateModel(MODEL_ID, AUTOML_OPTIONS, AUTOML_MASK_LIST)
.then((resp) => {
expect(resp.done).to.be.true;
expect(resp.name).to.be.undefined;
expect(resp.response).to.deep.equal(MODEL_RESPONSE);
expect(stub).to.have.been.calledOnce.and.calledWith({
method: 'PATCH',
headers: EXPECTED_HEADERS,
url: `${BASE_URL}/projects/test-project/models/${MODEL_ID}?${AUTOML_UPDATE_MASK_STRING}`,
data: AUTOML_OPTIONS,
});
});
});

it('should resolve with error when the operation fails', () => {
const stub = sinon
.stub(HttpClient.prototype, 'send')

0 comments on commit ffae70c

Please sign in to comment.