Problem
Model families in src/models.ts spread their default variant into the family object so it doubles as a usable config:
EFFICIENTNET_V2_S: {
...EFFICIENTNET_V2_S_XNNPACK_INT8,
XNNPACK_INT8: EFFICIENTNET_V2_S_XNNPACK_INT8,
XNNPACK_FP32: EFFICIENTNET_V2_S_XNNPACK_FP32,
COREML_FP16: EFFICIENTNET_V2_S_COREML_FP16,
},
download() walks any nested structure of plain objects and collects every string leaf matching /^https?:\/\//, then fetches all of them. So passing a family object rather than a variant downloads every variant in that family, not just the default the spread advertises.
The convenience default therefore costs a multiple of what a caller would expect, and it pulls artifacts for backends the device cannot even run.
Impact
models.ocr.PADDLE.PPOCRV6_SMALL, measured at the v0.10.0 tag:
| file |
size |
pp_ocrv6_xnnpack_int8.pte |
23.9 MB |
pp_ocrv6_coreml_int8.pte |
8.3 MB |
pp_ocrv6_vulkan_fp16.pte |
26.2 MB |
| total fetched |
58.3 MB |
Against 23.9 MB for the XNNPACK variant alone: 2.4x the bytes, and an Android device downloads the CoreML artifact while an iOS device downloads the Vulkan one.
This is not specific to OCR. 62 families across the registry use the spread, so the same applies to classification, style transfer, segmentation and the rest, in proportion to how many variants each ships.
Why this is worth fixing
The failure is silent. Nothing errors, nothing warns, the app just spends several times the bandwidth and storage it should on a first run, on metered connections and low-end devices included. The API shape actively invites it: PPOCRV6_SMALL looks like the simplest thing to pass, and it is the most expensive.
Possible directions
- Have
download() only follow a config's own model fields rather than recursing into nested variant objects. Most targeted, but changes documented download() behaviour, which is deliberately generic.
- Skip URLs for backends the running platform cannot use, which caps the waste without changing the registry.
- Drop the spreads and require callers to name a variant. Cleanest semantics, but a breaking change to the registry shape.
Option 2 is the smallest fix that removes the cross-platform nonsense; option 1 or 3 is needed to fix the multiple-variant case properly.
Context
Surfaced while reviewing #1322: #1322 (comment)
Problem
Model families in
src/models.tsspread their default variant into the family object so it doubles as a usable config:download()walks any nested structure of plain objects and collects every string leaf matching/^https?:\/\//, then fetches all of them. So passing a family object rather than a variant downloads every variant in that family, not just the default the spread advertises.The convenience default therefore costs a multiple of what a caller would expect, and it pulls artifacts for backends the device cannot even run.
Impact
models.ocr.PADDLE.PPOCRV6_SMALL, measured at thev0.10.0tag:pp_ocrv6_xnnpack_int8.ptepp_ocrv6_coreml_int8.ptepp_ocrv6_vulkan_fp16.pteAgainst 23.9 MB for the XNNPACK variant alone: 2.4x the bytes, and an Android device downloads the CoreML artifact while an iOS device downloads the Vulkan one.
This is not specific to OCR. 62 families across the registry use the spread, so the same applies to classification, style transfer, segmentation and the rest, in proportion to how many variants each ships.
Why this is worth fixing
The failure is silent. Nothing errors, nothing warns, the app just spends several times the bandwidth and storage it should on a first run, on metered connections and low-end devices included. The API shape actively invites it:
PPOCRV6_SMALLlooks like the simplest thing to pass, and it is the most expensive.Possible directions
download()only follow a config's own model fields rather than recursing into nested variant objects. Most targeted, but changes documenteddownload()behaviour, which is deliberately generic.Option 2 is the smallest fix that removes the cross-platform nonsense; option 1 or 3 is needed to fix the multiple-variant case properly.
Context
Surfaced while reviewing #1322: #1322 (comment)