Skip to content

Commit 65055ef

Browse files
committed
added downloads tracking separate from huggingface
1 parent 992d04b commit 65055ef

File tree

7 files changed

+182
-11
lines changed

7 files changed

+182
-11
lines changed

packages/bare-resource-fetcher/src/ResourceFetcher.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ export const BareResourceFetcher: BareResourceFetcherInterface = {
300300

301301
await RNFS.moveFile(extendedInfo.cacheFileUri!, extendedInfo.fileUri!);
302302
this.downloads.delete(source);
303-
ResourceFetcherUtils.triggerHuggingFaceDownloadCounter(extendedInfo.uri!);
304303

305304
const filename = extendedInfo.fileUri!.split('/').pop();
306305
if (filename) {

packages/bare-resource-fetcher/src/ResourceFetcherUtils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export namespace ResourceFetcherUtils {
2626
export const calculateDownloadProgress = CoreUtils.calculateDownloadProgress;
2727
export const triggerHuggingFaceDownloadCounter =
2828
CoreUtils.triggerHuggingFaceDownloadCounter;
29+
export const triggerDownloadEvent = CoreUtils.triggerDownloadEvent;
2930
export const getFilenameFromUri = CoreUtils.getFilenameFromUri;
3031

3132
export function getType(source: ResourceSource): SourceType {

packages/expo-resource-fetcher/src/ResourceFetcher.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,6 @@ export const ExpoResourceFetcher: ExpoResourceFetcherInterface = {
264264
to: resource.extendedInfo.fileUri,
265265
});
266266
this.downloads.delete(source);
267-
ResourceFetcherUtils.triggerHuggingFaceDownloadCounter(
268-
resource.extendedInfo.uri
269-
);
270267

271268
return this.returnOrStartNext(
272269
resource.extendedInfo,
@@ -526,7 +523,6 @@ export const ExpoResourceFetcher: ExpoResourceFetcherInterface = {
526523
to: sourceExtended.fileUri,
527524
});
528525
this.downloads.delete(source);
529-
ResourceFetcherUtils.triggerHuggingFaceDownloadCounter(uri);
530526
return ResourceFetcherUtils.removeFilePrefix(sourceExtended.fileUri);
531527
},
532528

packages/expo-resource-fetcher/src/ResourceFetcherUtils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export namespace ResourceFetcherUtils {
3939
export const calculateDownloadProgress = CoreUtils.calculateDownloadProgress;
4040
export const triggerHuggingFaceDownloadCounter =
4141
CoreUtils.triggerHuggingFaceDownloadCounter;
42+
export const triggerDownloadEvent = CoreUtils.triggerDownloadEvent;
4243
export const getFilenameFromUri = CoreUtils.getFilenameFromUri;
4344

4445
export function getType(source: ResourceSource): SourceType {

packages/react-native-executorch/src/constants/modelUrls.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,3 +976,130 @@ export const FSMN_VAD = {
976976
modelName: 'fsmn-vad',
977977
modelSource: FSMN_VAD_MODEL,
978978
} as const;
979+
980+
/**
981+
* Registry of all available model configurations.
982+
*
983+
* Use this to discover and enumerate all models shipped with the library.
984+
* @example
985+
* ```ts
986+
* import { MODEL_REGISTRY } from 'react-native-executorch';
987+
*
988+
* // Access a specific model
989+
* const llama = MODEL_REGISTRY.LLAMA3_2_1B;
990+
*
991+
* // List all model names
992+
* const names = Object.values(MODEL_REGISTRY).map(m => m.modelName);
993+
*
994+
* // Find models by name substring
995+
* const whisperModels = Object.values(MODEL_REGISTRY)
996+
* .filter(m => m.modelName.includes('whisper'));
997+
* ```
998+
* @category Utils
999+
*/
1000+
export const MODEL_REGISTRY = {
1001+
LLAMA3_2_3B,
1002+
LLAMA3_2_3B_QLORA,
1003+
LLAMA3_2_3B_SPINQUANT,
1004+
LLAMA3_2_1B,
1005+
LLAMA3_2_1B_QLORA,
1006+
LLAMA3_2_1B_SPINQUANT,
1007+
QWEN3_0_6B,
1008+
QWEN3_0_6B_QUANTIZED,
1009+
QWEN3_1_7B,
1010+
QWEN3_1_7B_QUANTIZED,
1011+
QWEN3_4B,
1012+
QWEN3_4B_QUANTIZED,
1013+
HAMMER2_1_0_5B,
1014+
HAMMER2_1_0_5B_QUANTIZED,
1015+
HAMMER2_1_1_5B,
1016+
HAMMER2_1_1_5B_QUANTIZED,
1017+
HAMMER2_1_3B,
1018+
HAMMER2_1_3B_QUANTIZED,
1019+
SMOLLM2_1_135M,
1020+
SMOLLM2_1_135M_QUANTIZED,
1021+
SMOLLM2_1_360M,
1022+
SMOLLM2_1_360M_QUANTIZED,
1023+
SMOLLM2_1_1_7B,
1024+
SMOLLM2_1_1_7B_QUANTIZED,
1025+
QWEN2_5_0_5B,
1026+
QWEN2_5_0_5B_QUANTIZED,
1027+
QWEN2_5_1_5B,
1028+
QWEN2_5_1_5B_QUANTIZED,
1029+
QWEN2_5_3B,
1030+
QWEN2_5_3B_QUANTIZED,
1031+
PHI_4_MINI_4B,
1032+
PHI_4_MINI_4B_QUANTIZED,
1033+
LFM2_5_1_2B_INSTRUCT,
1034+
LFM2_5_1_2B_INSTRUCT_QUANTIZED,
1035+
LFM2_VL_1_6B_QUANTIZED,
1036+
EFFICIENTNET_V2_S,
1037+
EFFICIENTNET_V2_S_QUANTIZED,
1038+
SSDLITE_320_MOBILENET_V3_LARGE,
1039+
RF_DETR_NANO,
1040+
STYLE_TRANSFER_CANDY,
1041+
STYLE_TRANSFER_CANDY_QUANTIZED,
1042+
STYLE_TRANSFER_MOSAIC,
1043+
STYLE_TRANSFER_MOSAIC_QUANTIZED,
1044+
STYLE_TRANSFER_RAIN_PRINCESS,
1045+
STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED,
1046+
STYLE_TRANSFER_UDNIE,
1047+
STYLE_TRANSFER_UDNIE_QUANTIZED,
1048+
WHISPER_TINY_EN,
1049+
WHISPER_TINY_EN_QUANTIZED,
1050+
WHISPER_BASE_EN,
1051+
WHISPER_BASE_EN_QUANTIZED,
1052+
WHISPER_SMALL_EN,
1053+
WHISPER_SMALL_EN_QUANTIZED,
1054+
WHISPER_TINY,
1055+
WHISPER_BASE,
1056+
WHISPER_SMALL,
1057+
DEEPLAB_V3_RESNET50,
1058+
DEEPLAB_V3_RESNET101,
1059+
DEEPLAB_V3_MOBILENET_V3_LARGE,
1060+
LRASPP_MOBILENET_V3_LARGE,
1061+
FCN_RESNET50,
1062+
FCN_RESNET101,
1063+
DEEPLAB_V3_RESNET50_QUANTIZED,
1064+
DEEPLAB_V3_RESNET101_QUANTIZED,
1065+
DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED,
1066+
LRASPP_MOBILENET_V3_LARGE_QUANTIZED,
1067+
FCN_RESNET50_QUANTIZED,
1068+
FCN_RESNET101_QUANTIZED,
1069+
SELFIE_SEGMENTATION,
1070+
YOLO26N_SEG,
1071+
YOLO26S_SEG,
1072+
YOLO26M_SEG,
1073+
YOLO26L_SEG,
1074+
YOLO26X_SEG,
1075+
RF_DETR_NANO_SEG,
1076+
CLIP_VIT_BASE_PATCH32_IMAGE,
1077+
CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED,
1078+
ALL_MINILM_L6_V2,
1079+
ALL_MPNET_BASE_V2,
1080+
MULTI_QA_MINILM_L6_COS_V1,
1081+
MULTI_QA_MPNET_BASE_DOT_V1,
1082+
CLIP_VIT_BASE_PATCH32_TEXT,
1083+
BK_SDM_TINY_VPRED_512,
1084+
BK_SDM_TINY_VPRED_256,
1085+
FSMN_VAD,
1086+
} as const;
1087+
1088+
const urlToModelName = new Map<string, string>();
1089+
for (const config of Object.values(MODEL_REGISTRY)) {
1090+
const modelName = config.modelName;
1091+
for (const [key, value] of Object.entries(config)) {
1092+
if (key !== 'modelName' && typeof value === 'string') {
1093+
urlToModelName.set(value, modelName);
1094+
}
1095+
}
1096+
}
1097+
1098+
/**
1099+
* Looks up the model name for a given source URL.
1100+
* @param url - The source URL to look up.
1101+
* @returns The model name if found, otherwise undefined.
1102+
*/
1103+
export function getModelNameForUrl(url: string): string | undefined {
1104+
return urlToModelName.get(url);
1105+
}

packages/react-native-executorch/src/utils/ResourceFetcher.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export interface ResourceFetcherAdapter {
7575
*/
7676
export class ResourceFetcher {
7777
private static adapter: ResourceFetcherAdapter | null = null;
78+
private static reportedUrls = new Set<string>();
7879

7980
/**
8081
* Sets a custom resource fetcher adapter for resource operations.
@@ -123,16 +124,17 @@ export class ResourceFetcher {
123124
callback: (downloadProgress: number) => void = () => {},
124125
...sources: ResourceSource[]
125126
) {
126-
for (const source of sources) {
127-
if (typeof source === 'string') {
128-
try {
127+
const result = await this.getAdapter().fetch(callback, ...sources);
128+
if (result) {
129+
for (const source of sources) {
130+
if (typeof source === 'string' && !this.reportedUrls.has(source)) {
131+
this.reportedUrls.add(source);
129132
ResourceFetcherUtils.triggerHuggingFaceDownloadCounter(source);
130-
} catch (error) {
131-
throw error;
133+
ResourceFetcherUtils.triggerDownloadEvent(source);
132134
}
133135
}
134136
}
135-
return this.getAdapter().fetch(callback, ...sources);
137+
return result;
136138
}
137139

138140
/**

packages/react-native-executorch/src/utils/ResourceFetcherUtils.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ResourceSource } from '..';
2+
import { getModelNameForUrl } from '../constants/modelUrls';
23

34
/**
45
* Http status codes
@@ -193,6 +194,50 @@ export namespace ResourceFetcherUtils {
193194
}
194195
}
195196

197+
// TODO: Replace with actual endpoint URL
198+
const DOWNLOAD_EVENT_ENDPOINT =
199+
'https://ai.swmansion.com/telemetry/downloads/api/downloads';
200+
201+
function getCountryCode(): string {
202+
try {
203+
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
204+
const regionTag = locale.split('-').pop();
205+
if (regionTag && regionTag.length === 2) {
206+
return regionTag.toUpperCase();
207+
}
208+
} catch {}
209+
return 'UNKNOWN';
210+
}
211+
212+
function getModelNameFromUri(uri: string): string {
213+
const knownName = getModelNameForUrl(uri);
214+
if (knownName) {
215+
return knownName;
216+
}
217+
const pathname = new URL(uri).pathname;
218+
const filename = pathname.split('/').pop() ?? uri;
219+
return filename.replace(/\.[^.]+$/, '');
220+
}
221+
222+
/**
223+
* Sends a download event to the analytics endpoint.
224+
* @param uri - The URI of the downloaded resource.
225+
*/
226+
export function triggerDownloadEvent(uri: string) {
227+
try {
228+
fetch(DOWNLOAD_EVENT_ENDPOINT, {
229+
method: 'POST',
230+
headers: { 'Content-Type': 'application/json' },
231+
body: JSON.stringify({
232+
modelName: getModelNameFromUri(uri),
233+
countryCode: getCountryCode(),
234+
}),
235+
});
236+
} catch (e) {
237+
console.log(e);
238+
}
239+
}
240+
196241
/**
197242
* Generates a safe filename from a URI by removing the protocol and replacing special characters.
198243
* @param uri - The source URI.

0 commit comments

Comments
 (0)