Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change(ml): Drop the feature to publish from an AutoML Model #1974

Merged
merged 2 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions etc/firebase-admin.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 1 addition & 11 deletions etc/firebase-admin.machine-learning.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -74,7 +66,7 @@ export class Model {
}

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

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

// @public
export interface TFLiteModel {
// @deprecated
readonly automlModel?: string;
readonly gcsTfliteUri?: string;
readonly sizeBytes: number;
}
Expand Down
1 change: 0 additions & 1 deletion src/machine-learning/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export {
TFLiteModel,
} from './machine-learning';
export {
AutoMLTfliteModelOptions,
GcsTfliteModelOptions,
ListModelsOptions,
ModelOptions,
Expand Down
12 changes: 1 addition & 11 deletions src/machine-learning/machine-learning-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -108,7 +99,6 @@ export interface ModelContent {
};
readonly tfliteModel?: {
readonly gcsTfliteUri?: string;
readonly automlModel?: string;

readonly sizeBytes: number;
};
Expand Down
8 changes: 0 additions & 8 deletions src/machine-learning/machine-learning-namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
TFLiteModel as TTFLiteModel,
} from './machine-learning';
import {
AutoMLTfliteModelOptions as TAutoMLTfliteModelOptions,
GcsTfliteModelOptions as TGcsTfliteModelOptions,
ListModelsOptions as TListModelsOptions,
ModelOptions as TModelOptions,
Expand Down Expand Up @@ -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}.
*/
Expand Down
16 changes: 2 additions & 14 deletions src/machine-learning/machine-learning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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;
}
Expand Down
89 changes: 1 addition & 88 deletions test/integration/machine-learning.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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'];
Expand Down Expand Up @@ -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.');
}
Expand All @@ -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
Expand Up @@ -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';
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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')
Expand Down