Skip to content
This repository was archived by the owner on Aug 28, 2023. It is now read-only.

Commit f73e7f3

Browse files
authored
[82988] Enable GA for huggingface models (#60)
1 parent ad8d55e commit f73e7f3

11 files changed

+172
-29
lines changed

client/src/app/app.component.ts

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export class AppComponent implements OnInit {
4545

4646
private _checkBrowserUserAgent(): void {
4747
const isChromeBrowser = navigator.userAgent.match(/Chrome/);
48+
// todo: save flag to localstorage or user metadata
4849
if (!isChromeBrowser) {
4950
const { title, message } = this._browserInformationMessage;
5051
this.notificationService.add(title, message, NotificationType.DEFAULT);

client/src/app/core/services/common/google-analytics.service.ts

+53-10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { UploadModelSocketDTO } from '@shared/models/dto/upload-socket-message-d
4545
import { DeviceItem } from '@shared/models/device';
4646
import { AccuracyReportType } from '@shared/models/accuracy-analysis/accuracy-report';
4747
import { ITokenizer, TOKENIZER_TYPE_NAME } from '@shared/models/tokenizer/tokenizer';
48+
import { IHuggingfaceModel } from '@shared/models/huggingface/huggingface-model';
4849

4950
import { PrecisionAnalysisService } from '../../../modules/dashboard/components/precision-analysis/precision-analysis.service';
5051
import { ExecutedLayerItem } from '../../../modules/dashboard/components/model-layers-with-graphs/layers-table/layers-table.model';
@@ -86,6 +87,10 @@ export const enum GAActions {
8687
DEVICES = 'Devices',
8788
CANCEL = 'Cancel',
8889
OMZ_DOWNLOAD = 'OMZ Download',
90+
HUGGINGFACE_IMPORT_START = 'Huggingface import start',
91+
HUGGINGFACE_IMPORT = 'Huggingface import',
92+
HUGGINGFACE_LIST = 'Huggingface list',
93+
HUGGINGFACE_MODEL_DETAILS = 'Huggingface model details',
8994
LOCAL_UPLOAD = 'Local Upload',
9095
COMPARE = 'Compare',
9196
CREATE = 'Create',
@@ -171,6 +176,7 @@ export class GoogleAnalyticsService {
171176
originalDatasetType: DatasetTypeToNameMap[dataset.originalType],
172177
modelName: isOMZ ? model.name : 'other',
173178
isOMZ,
179+
modelSource: model.modelSource,
174180
target: TargetMachineTypesNamesMap[machine.targetType],
175181
autogenerated,
176182
OS: machine.operatingSystem,
@@ -301,19 +307,28 @@ export class GoogleAnalyticsService {
301307

302308
public emitUploadModelEvent(modelDescription: UploadModelSocketDTO, model: ModelItem): void {
303309
const modelDomain = modelDomainNames[model.domain];
304-
if (model.modelSource !== ModelSources.OMZ) {
305-
this.emitEvent(GAActions.LOCAL_UPLOAD, Categories.MODEL, { modelDomain });
310+
if (model.modelSource === ModelSources.OMZ) {
311+
this.emitEvent(GAActions.OMZ_DOWNLOAD, Categories.MODEL, {
312+
name: modelDescription.name,
313+
precisions: modelDescription.bodyPrecisions.join(' '),
314+
framework: modelFrameworkNamesMap[model.framework],
315+
modelType: TaskMethodToNameMap[model.accuracyConfiguration.taskMethod],
316+
modelDomain,
317+
downloadTime: GoogleAnalyticsService.getJobExecTime(modelDescription.date),
318+
});
306319
return;
307320
}
308321

309-
this.emitEvent(GAActions.OMZ_DOWNLOAD, Categories.MODEL, {
310-
name: modelDescription.name,
311-
precisions: modelDescription.bodyPrecisions.join(' '),
312-
framework: modelFrameworkNamesMap[model.framework],
313-
modelType: TaskMethodToNameMap[model.accuracyConfiguration.taskMethod],
314-
modelDomain,
315-
downloadTime: GoogleAnalyticsService.getJobExecTime(modelDescription.date),
316-
});
322+
if (model.modelSource === ModelSources.HUGGINGFACE) {
323+
this.emitEvent(GAActions.HUGGINGFACE_IMPORT, Categories.MODEL, {
324+
name: modelDescription.name,
325+
modelDomain,
326+
modelSource: model.modelSource,
327+
});
328+
return;
329+
}
330+
331+
this.emitEvent(GAActions.LOCAL_UPLOAD, Categories.MODEL, { modelDomain });
317332
}
318333

319334
public emitOptimizationEvent(
@@ -497,4 +512,32 @@ export class GoogleAnalyticsService {
497512
[DimensionsEnum.VERSION]: version,
498513
});
499514
}
515+
516+
public emitImportHuggingfaceModelStart(model: IHuggingfaceModel): void {
517+
this.emitEvent(GAActions.HUGGINGFACE_IMPORT_START, Categories.MODEL, {
518+
huggingfaceModelId: model.id,
519+
modelType: model.config?.modelType,
520+
pipelineTag: model.pipelineTag,
521+
});
522+
}
523+
524+
public emitImportHuggingfaceModelFailure(error: string): void {
525+
this.emitEvent(GAActions.HUGGINGFACE_IMPORT, Categories.ERROR, { error });
526+
}
527+
528+
public emitHuggingfaceListLoad(timeToLoad: number): void {
529+
this.emitEvent(GAActions.HUGGINGFACE_LIST, Categories.MODEL, { timeToLoad });
530+
}
531+
532+
public emitHuggingfaceListLoadFailure(error: string): void {
533+
this.emitEvent(GAActions.HUGGINGFACE_LIST, Categories.ERROR, { error });
534+
}
535+
536+
public emitHuggingfaceLoadReadmeSuccess(huggingfaceModelId: string): void {
537+
this.emitEvent(GAActions.HUGGINGFACE_MODEL_DETAILS, Categories.MODEL, { huggingfaceModelId });
538+
}
539+
540+
public emitHuggingfaceLoadReadmeFailure(huggingfaceModelId: string, error: string): void {
541+
this.emitEvent(GAActions.HUGGINGFACE_MODEL_DETAILS, Categories.ERROR, { huggingfaceModelId, error });
542+
}
500543
}

client/src/app/modules/model-manager/components/hugging-face-import-ribbon-content/hugging-face-import-ribbon-content.component.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, OnDestroy } from '@angular/core';
1+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
22

33
import { filter, takeUntil } from 'rxjs/operators';
44
import { Store } from '@ngrx/store';
@@ -33,7 +33,8 @@ export interface IHuggingfaceTagsSets {
3333
})
3434
export class HuggingFaceImportRibbonContentComponent
3535
extends BaseModelZooImportComponent<IHuggingfaceModel, IHuggingfaceModelZooFilter>
36-
implements OnInit, OnDestroy {
36+
implements OnInit, OnDestroy
37+
{
3738
readonly externalResourceNotification =
3839
this._messages.hintMessages.importHuggingFaceTips.externalResourceNotification;
3940
readonly shownSubsetNotification = this._messages.hintMessages.importHuggingFaceTips.shownSubsetNotification;
@@ -95,6 +96,6 @@ export class HuggingFaceImportRibbonContentComponent
9596
}
9697

9798
importModel(): void {
98-
this._store$.dispatch(ModelStoreActions.importHuggingfaceModel({ huggingface_model_id: this.selectedModel.id }));
99+
this._store$.dispatch(ModelStoreActions.importHuggingfaceModel({ huggingfaceModel: this.selectedModel }));
99100
}
100101
}

client/src/app/root-store/huggingface-model-store/huggingface-model-store.actions.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ErrorState } from '@store/state';
77
export const loadModelData = createAction('[Huggingface model] Load model data');
88
export const loadModelDataSuccess = createAction(
99
'[Huggingface model] Load model data success',
10-
props<{ data: IHFModelsData }>()
10+
props<{ data: IHFModelsData; timeToLoad: number }>()
1111
);
1212
export const loadModelDataFailure = createAction(
1313
'[Huggingface model] Load model data failure',
@@ -20,11 +20,11 @@ export const loadModelReadme = createAction(
2020
);
2121
export const loadModelReadmeSuccess = createAction(
2222
'[Huggingface model] Import model readme success',
23-
props<{ readme: string }>()
23+
props<{ readme: string; huggingfaceModelId: string }>()
2424
);
2525
export const loadModelReadmeFailure = createAction(
2626
'[Huggingface model] Import model readme failure',
27-
props<{ error: ErrorState }>()
27+
props<{ error: ErrorState; huggingfaceModelId: string }>()
2828
);
2929

3030
export const reset = createAction('[Huggingface model] reset');

client/src/app/root-store/huggingface-model-store/huggingface-model-store.effects.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@ export class HuggingfaceModelStoreEffects {
1313
loadModels$ = createEffect(() =>
1414
this._actions$.pipe(
1515
ofType(HuggingfaceModelsActions.loadModelData),
16-
switchMap(() =>
17-
this._hfService.getModelsData$().pipe(
18-
map((data) => HuggingfaceModelsActions.loadModelDataSuccess({ data })),
16+
switchMap(() => {
17+
const start = Date.now();
18+
return this._hfService.getModelsData$().pipe(
19+
map((data) =>
20+
HuggingfaceModelsActions.loadModelDataSuccess({
21+
data,
22+
timeToLoad: Number(((Date.now() - start) / 1000).toFixed(2)),
23+
})
24+
),
1925
catchError((error) => of(HuggingfaceModelsActions.loadModelDataFailure({ error }))),
2026
takeUntil(this._actions$.pipe(ofType(HuggingfaceModelsActions.reset)))
21-
)
22-
)
27+
);
28+
})
2329
)
2430
);
2531

@@ -28,8 +34,8 @@ export class HuggingfaceModelStoreEffects {
2834
ofType(HuggingfaceModelsActions.loadModelReadme),
2935
switchMap(({ huggingfaceModelId }) =>
3036
this._hfService.getModelReadme$(huggingfaceModelId).pipe(
31-
map((readme) => HuggingfaceModelsActions.loadModelReadmeSuccess({ readme })),
32-
catchError((error) => of(HuggingfaceModelsActions.loadModelReadmeFailure({ error }))),
37+
map((readme) => HuggingfaceModelsActions.loadModelReadmeSuccess({ readme, huggingfaceModelId })),
38+
catchError((error) => of(HuggingfaceModelsActions.loadModelReadmeFailure({ error, huggingfaceModelId }))),
3339
takeUntil(this._actions$.pipe(ofType(HuggingfaceModelsActions.reset)))
3440
)
3541
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Injectable } from '@angular/core';
2+
3+
import { Actions, createEffect, ofType } from '@ngrx/effects';
4+
import { tap } from 'rxjs/operators';
5+
6+
import { GoogleAnalyticsService } from '@core/services/common/google-analytics.service';
7+
8+
import * as HuggingfaceModelsActions from './huggingface-model-store.actions';
9+
10+
@Injectable()
11+
export class HuggingfaceModelStoreGaEffects {
12+
loadModels$ = createEffect(
13+
() =>
14+
this._actions$.pipe(
15+
ofType(HuggingfaceModelsActions.loadModelDataSuccess),
16+
tap(({ timeToLoad }) => this._ga.emitHuggingfaceListLoad(timeToLoad))
17+
),
18+
{ dispatch: false }
19+
);
20+
21+
loadModelsFailed$ = createEffect(
22+
() =>
23+
this._actions$.pipe(
24+
ofType(HuggingfaceModelsActions.loadModelDataFailure),
25+
tap(({ error }) => this._ga.emitHuggingfaceListLoadFailure(error.toString()))
26+
),
27+
{ dispatch: false }
28+
);
29+
30+
loadReadmeSuccess$ = createEffect(
31+
() =>
32+
this._actions$.pipe(
33+
ofType(HuggingfaceModelsActions.loadModelReadmeSuccess),
34+
tap(({ huggingfaceModelId }) => this._ga.emitHuggingfaceLoadReadmeSuccess(huggingfaceModelId))
35+
),
36+
{ dispatch: false }
37+
);
38+
39+
loadReadmeFailure$ = createEffect(
40+
() =>
41+
this._actions$.pipe(
42+
ofType(HuggingfaceModelsActions.loadModelReadmeFailure),
43+
tap(({ error, huggingfaceModelId }) =>
44+
this._ga.emitHuggingfaceLoadReadmeFailure(huggingfaceModelId, error.toString())
45+
)
46+
),
47+
{ dispatch: false }
48+
);
49+
50+
constructor(private readonly _actions$: Actions, private readonly _ga: GoogleAnalyticsService) {}
51+
}

client/src/app/root-store/huggingface-model-store/huggingface-model-store.module.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { StoreModule } from '@ngrx/store';
55
import { EffectsModule } from '@ngrx/effects';
66

77
import { HuggingfaceModelStoreEffects } from './huggingface-model-store.effects';
8+
import { HuggingfaceModelStoreGaEffects } from './huggingface-model-store.ga.effects';
89
import { reducer } from './huggingface-model-store.reducer';
910

1011
export const FEATURE_KEY = 'huggingfaceModel';
@@ -14,7 +15,7 @@ export const FEATURE_KEY = 'huggingfaceModel';
1415
imports: [
1516
CommonModule,
1617
StoreModule.forFeature(FEATURE_KEY, reducer),
17-
EffectsModule.forFeature([HuggingfaceModelStoreEffects]),
18+
EffectsModule.forFeature([HuggingfaceModelStoreEffects, HuggingfaceModelStoreGaEffects]),
1819
],
1920
})
2021
export class HuggingfaceModelStoreModule {}

client/src/app/root-store/model-store/model-ga.effects.ts

+40-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Categories, GAActions, GoogleAnalyticsService } from '@core/services/co
1010
import { ProjectStatusNames } from '@store/project-store/project.model';
1111
import { selectModelById, selectModelByModelOptimizerJobId } from '@store/model-store/model.selectors';
1212
import { RootStoreState } from '@store';
13-
import { modelFrameworkNamesMap } from '@store/model-store/model.model';
13+
import { modelFrameworkNamesMap, ModelSources } from '@store/model-store/model.model';
1414

1515
import * as ModelStoreActions from './model.actions';
1616

@@ -35,6 +35,45 @@ export class ModelGAEffects {
3535
{ dispatch: false }
3636
);
3737

38+
importHuggingfaceModelStart$ = createEffect(
39+
() =>
40+
this.actions$.pipe(
41+
ofType(ModelStoreActions.importHuggingfaceModel),
42+
tap(({ huggingfaceModel }) => this.gAnalyticsService.emitImportHuggingfaceModelStart(huggingfaceModel))
43+
),
44+
{ dispatch: false }
45+
);
46+
47+
importHuggingfaceModelStartFailure$ = createEffect(
48+
() =>
49+
this.actions$.pipe(
50+
ofType(ModelStoreActions.importHuggingfaceModelFailure),
51+
tap(({ error }) => {
52+
this.gAnalyticsService.emitImportHuggingfaceModelFailure(error.toString());
53+
})
54+
),
55+
{ dispatch: false }
56+
);
57+
58+
importHuggingfaceModelFailure$ = createEffect(
59+
() =>
60+
this.actions$.pipe(
61+
ofType(ModelStoreActions.onUploadModelSocket),
62+
mergeMap(({ data }) => of(data).pipe(withLatestFrom(this.store$.pipe(select(selectModelById, data.id))))),
63+
// for some reason ready status is firing twice, here we catch only message when status actually changes
64+
filter(
65+
([{ status }, model]) =>
66+
status.name === ProjectStatusNames.ERROR &&
67+
model?.status.name === ProjectStatusNames.RUNNING &&
68+
model?.modelSource === ModelSources.HUGGINGFACE
69+
),
70+
tap(([payload]) => {
71+
this.gAnalyticsService.emitImportHuggingfaceModelFailure(payload.status.errorMessage);
72+
})
73+
),
74+
{ dispatch: false }
75+
);
76+
3877
convertModelGA$ = createEffect(
3978
() =>
4079
this.actions$.pipe(

client/src/app/root-store/model-store/model.actions.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ModelDownloaderDTO } from '@shared/models/dto/model-downloader-dto';
77
import { UploadModelSocketDTO } from '@shared/models/dto/upload-socket-message-dto';
88
import { IAccuracyConfiguration } from '@shared/models/accuracy';
99
import { IConfigurePipeline } from '@shared/models/pipelines/configure-pipeline';
10+
import { IHuggingfaceModel } from '@shared/models/huggingface/huggingface-model';
1011

1112
import {
1213
EditModelConvertConfigDTO,
@@ -224,7 +225,7 @@ export const configureModelSuccess = createAction('[Model] Configure Model Succe
224225

225226
export const importHuggingfaceModel = createAction(
226227
'[Model] Import huggingface model',
227-
props<{ huggingface_model_id: string }>()
228+
props<{ huggingfaceModel: IHuggingfaceModel }>()
228229
);
229230

230231
export const importHuggingfaceModelSuccess = createAction(

client/src/app/root-store/model-store/model.effects.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ export class ModelEffects {
290290
importHuggingfaceModel$ = createEffect(() =>
291291
this.actions$.pipe(
292292
ofType(ModelStoreActions.importHuggingfaceModel),
293-
switchMap(({ huggingface_model_id }) =>
294-
this._hfService.importModel$(huggingface_model_id).pipe(
293+
switchMap(({ huggingfaceModel }) =>
294+
this._hfService.importModel$(huggingfaceModel.id).pipe(
295295
map((model: ModelItem) => ModelStoreActions.importHuggingfaceModelSuccess({ model })),
296296
catchError((error) => of(ModelStoreActions.importHuggingfaceModelFailure({ error })))
297297
)

client/tslint.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"no-unused-expression": true,
4747
"no-var-keyword": true,
4848
"object-literal-sort-keys": false,
49-
"one-line": [true, "check-open-brace", "check-catch", "check-else", "check-whitespace"],
49+
"one-line": [true, "check-catch", "check-else", "check-whitespace"],
5050
"prefer-const": true,
5151
"quotemark": [true, "single", "avoid-escape"],
5252
"radix": true,

0 commit comments

Comments
 (0)