Skip to content

Commit 5e10f9a

Browse files
committed
feat!: typed models accessor + v0.9.0 model layout
1 parent d3182ce commit 5e10f9a

85 files changed

Lines changed: 1745 additions & 1231 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintrc.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ module.exports = {
6363
customWordListFile: path.resolve(__dirname, '.cspell-wordlist.txt'),
6464
},
6565
],
66-
'camelcase': 'error',
66+
// `properties: 'never'` lets the lowercase snake_case keys in `models`
67+
// (e.g. `models.text_to_speech.kokoro_small`, mirroring the underlying
68+
// `.pte` filenames) pass while still requiring camelCase for variable
69+
// and function declarations.
70+
'camelcase': ['error', { properties: 'never' }],
6771
'jsdoc/require-jsdoc': 'off',
6872
'jsdoc/require-param': ['error', { checkDestructured: false }],
6973
'jsdoc/check-param-names': ['error', { checkDestructured: false }],

apps/bare-rn/App.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ import {
1313
TouchableWithoutFeedback,
1414
View,
1515
} from 'react-native';
16-
import {
17-
initExecutorch,
18-
useLLM,
19-
LLAMA3_2_1B_SPINQUANT,
20-
} from 'react-native-executorch';
16+
import { models, initExecutorch, useLLM } from 'react-native-executorch';
2117
import { BareResourceFetcher } from 'react-native-executorch-bare-resource-fetcher';
2218
import { setConfig } from '@kesha-antonov/react-native-background-downloader';
2319
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
@@ -144,7 +140,9 @@ function App() {
144140
const textInputRef = useRef<TextInput>(null);
145141
const scrollViewRef = useRef<ScrollView>(null);
146142

147-
const llm = useLLM({ model: LLAMA3_2_1B_SPINQUANT });
143+
const llm = useLLM({
144+
model: models.llm.lfm2_5_1_2b_instruct(),
145+
});
148146
// Alternatively, to use a custom local model, uncomment below:
149147
// const llm = useLLM({ model: {
150148
// modelSource: require('./assets/ai-models/smolLm2/smolLm2_135M/smolLm2_135M_bf16.pte'),

apps/computer-vision/app/classification/index.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
import Spinner from '../../components/Spinner';
22
import { getImage } from '../../utils';
33
import {
4+
models,
45
useClassification,
5-
EFFICIENTNET_V2_S,
6-
EFFICIENTNET_V2_S_QUANTIZED,
76
ClassificationModelSources,
87
} from 'react-native-executorch';
98
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
9+
const classification = models.classification;
1010

1111
const MODELS: ModelOption<ClassificationModelSources>[] = [
12-
{ label: 'EfficientNet V2 S Quantized', value: EFFICIENTNET_V2_S_QUANTIZED },
13-
{ label: 'EfficientNet V2 S', value: EFFICIENTNET_V2_S },
12+
{
13+
label: 'EfficientNet V2 S Quantized',
14+
value: classification.efficientnet_v2_s(),
15+
},
16+
{
17+
label: 'EfficientNet V2 S',
18+
value: classification.efficientnet_v2_s({ quant: false }),
19+
},
1420
];
1521
import { View, StyleSheet, Image, Text, ScrollView } from 'react-native';
1622
import { BottomBar } from '../../components/BottomBar';
@@ -22,7 +28,7 @@ import ErrorBanner from '../../components/ErrorBanner';
2228

2329
export default function ClassificationScreen() {
2430
const [selectedModel, setSelectedModel] =
25-
useState<ClassificationModelSources>(EFFICIENTNET_V2_S_QUANTIZED);
31+
useState<ClassificationModelSources>(classification.efficientnet_v2_s());
2632
const [results, setResults] = useState<{ label: string; score: number }[]>(
2733
[]
2834
);

apps/computer-vision/app/instance_segmentation/index.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,9 @@ import { BottomBar } from '../../components/BottomBar';
33
import { getImage } from '../../utils';
44
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
55
import {
6+
models,
67
useInstanceSegmentation,
7-
YOLO26N_SEG,
8-
YOLO26S_SEG,
9-
YOLO26M_SEG,
10-
YOLO26L_SEG,
11-
YOLO26X_SEG,
12-
RF_DETR_NANO_SEG,
138
InstanceSegmentationModelSources,
14-
FASTSAM_S,
15-
FASTSAM_X,
169
} from 'react-native-executorch';
1710
import {
1811
View,
@@ -29,21 +22,28 @@ import ImageWithMasks, {
2922
DisplayInstance,
3023
} from '../../components/ImageWithMasks';
3124
import { StatsBar } from '../../components/StatsBar';
25+
const instanceSegmentation = models.instance_segmentation;
26+
const objectDetection = models.object_detection;
3227

3328
const MODELS: ModelOption<InstanceSegmentationModelSources>[] = [
34-
{ label: 'Yolo26N', value: YOLO26N_SEG },
35-
{ label: 'Yolo26S', value: YOLO26S_SEG },
36-
{ label: 'Yolo26M', value: YOLO26M_SEG },
37-
{ label: 'Yolo26L', value: YOLO26L_SEG },
38-
{ label: 'Yolo26X', value: YOLO26X_SEG },
39-
{ label: 'RF-DeTR Nano', value: RF_DETR_NANO_SEG },
40-
{ label: 'FastSAM-S', value: FASTSAM_S },
41-
{ label: 'FastSAM-X', value: FASTSAM_X },
29+
{ label: 'Yolo26N', value: instanceSegmentation.yolo26n_seg() },
30+
{ label: 'Yolo26S', value: instanceSegmentation.yolo26s_seg() },
31+
{ label: 'Yolo26M', value: instanceSegmentation.yolo26m_seg() },
32+
{ label: 'Yolo26L', value: instanceSegmentation.yolo26l_seg() },
33+
{ label: 'Yolo26X', value: instanceSegmentation.yolo26x_seg() },
34+
{
35+
label: 'RF-DeTR Nano',
36+
value: instanceSegmentation.rf_detr_nano_seg(),
37+
},
38+
{ label: 'FastSAM-S', value: objectDetection.fastsam_s() },
39+
{ label: 'FastSAM-X', value: objectDetection.fastsam_x() },
4240
];
4341

4442
export default function InstanceSegmentationScreen() {
4543
const [selectedModel, setSelectedModel] =
46-
useState<InstanceSegmentationModelSources>(YOLO26N_SEG);
44+
useState<InstanceSegmentationModelSources>(
45+
instanceSegmentation.yolo26n_seg()
46+
);
4747
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
4848

4949
const { setGlobalGenerating } = useContext(GeneratingContext);

apps/computer-vision/app/object_detection/index.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,9 @@ import { BottomBar } from '../../components/BottomBar';
33
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
44
import { getImage } from '../../utils';
55
import {
6+
models,
67
Detection,
78
useObjectDetection,
8-
RF_DETR_NANO,
9-
SSDLITE_320_MOBILENET_V3_LARGE,
10-
YOLO26N,
11-
YOLO26S,
12-
YOLO26M,
13-
YOLO26L,
14-
YOLO26X,
159
ObjectDetectionModelSources,
1610
} from 'react-native-executorch';
1711
import { View, StyleSheet, Image, Text } from 'react-native';
@@ -20,15 +14,22 @@ import React, { useContext, useEffect, useState } from 'react';
2014
import { GeneratingContext } from '../../context';
2115
import ScreenWrapper from '../../ScreenWrapper';
2216
import { StatsBar } from '../../components/StatsBar';
17+
const objectDetection = models.object_detection;
2318

2419
const MODELS: ModelOption<ObjectDetectionModelSources>[] = [
25-
{ label: 'RF-DeTR Nano', value: RF_DETR_NANO },
26-
{ label: 'SSDLite MobileNet', value: SSDLITE_320_MOBILENET_V3_LARGE },
27-
{ label: 'YOLO26N', value: YOLO26N },
28-
{ label: 'YOLO26S', value: YOLO26S },
29-
{ label: 'YOLO26M', value: YOLO26M },
30-
{ label: 'YOLO26L', value: YOLO26L },
31-
{ label: 'YOLO26X', value: YOLO26X },
20+
{
21+
label: 'RF-DeTR Nano',
22+
value: objectDetection.rf_detr_nano(),
23+
},
24+
{
25+
label: 'SSDLite MobileNet',
26+
value: objectDetection.ssdlite_320_mobilenet_v3_large(),
27+
},
28+
{ label: 'YOLO26N', value: objectDetection.yolo26n() },
29+
{ label: 'YOLO26S', value: objectDetection.yolo26s() },
30+
{ label: 'YOLO26M', value: objectDetection.yolo26m() },
31+
{ label: 'YOLO26L', value: objectDetection.yolo26l() },
32+
{ label: 'YOLO26X', value: objectDetection.yolo26x() },
3233
];
3334
import ErrorBanner from '../../components/ErrorBanner';
3435

@@ -41,7 +42,7 @@ export default function ObjectDetectionScreen() {
4142
height: number;
4243
}>();
4344
const [selectedModel, setSelectedModel] =
44-
useState<ObjectDetectionModelSources>(RF_DETR_NANO);
45+
useState<ObjectDetectionModelSources>(objectDetection.rf_detr_nano());
4546
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
4647

4748
const model = useObjectDetection({ model: selectedModel });

apps/computer-vision/app/ocr/index.tsx

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,7 @@ import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
33
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
44
import { getImage } from '../../utils';
5-
import {
6-
useOCR,
7-
OCR_ENGLISH,
8-
OCR_GERMAN,
9-
OCR_FRENCH,
10-
OCR_SPANISH,
11-
OCR_ITALIAN,
12-
OCR_JAPANESE,
13-
OCR_KOREAN,
14-
OCRProps,
15-
} from 'react-native-executorch';
5+
import { models, useOCR, OCRProps } from 'react-native-executorch';
166
import { View, StyleSheet, Image, Text, ScrollView } from 'react-native';
177
import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes';
188
import React, { useContext, useEffect, useState } from 'react';
@@ -22,14 +12,16 @@ import { StatsBar } from '../../components/StatsBar';
2212

2313
type OCRModelSources = OCRProps['model'];
2414

15+
const ocr = models.ocr.craft;
16+
2517
const MODELS: ModelOption<OCRModelSources>[] = [
26-
{ label: 'English', value: OCR_ENGLISH },
27-
{ label: 'German', value: OCR_GERMAN },
28-
{ label: 'French', value: OCR_FRENCH },
29-
{ label: 'Spanish', value: OCR_SPANISH },
30-
{ label: 'Italian', value: OCR_ITALIAN },
31-
{ label: 'Japanese', value: OCR_JAPANESE },
32-
{ label: 'Korean', value: OCR_KOREAN },
18+
{ label: 'English', value: ocr({ language: 'en' }) },
19+
{ label: 'German', value: ocr({ language: 'de' }) },
20+
{ label: 'French', value: ocr({ language: 'fr' }) },
21+
{ label: 'Spanish', value: ocr({ language: 'es' }) },
22+
{ label: 'Italian', value: ocr({ language: 'it' }) },
23+
{ label: 'Japanese', value: ocr({ language: 'ja' }) },
24+
{ label: 'Korean', value: ocr({ language: 'ko' }) },
3325
];
3426
import ErrorBanner from '../../components/ErrorBanner';
3527

@@ -41,8 +33,9 @@ export default function OCRScreen() {
4133
width: number;
4234
height: number;
4335
}>();
44-
const [selectedModel, setSelectedModel] =
45-
useState<OCRModelSources>(OCR_ENGLISH);
36+
const [selectedModel, setSelectedModel] = useState<OCRModelSources>(
37+
ocr({ language: 'en' })
38+
);
4639
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
4740

4841
const model = useOCR({

apps/computer-vision/app/ocr_vertical/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
33
import { getImage } from '../../utils';
4-
import { useVerticalOCR, OCR_ENGLISH } from 'react-native-executorch';
4+
import { models, useVerticalOCR } from 'react-native-executorch';
55
import { View, StyleSheet, Image, Text, ScrollView } from 'react-native';
66
import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes';
77
import React, { useContext, useEffect, useState } from 'react';
@@ -22,7 +22,7 @@ export default function VerticalOCRScreen() {
2222
const [error, setError] = useState<string | null>(null);
2323

2424
const model = useVerticalOCR({
25-
model: OCR_ENGLISH,
25+
model: models.ocr.craft({ language: 'en' }),
2626
independentCharacters: true,
2727
});
2828

apps/computer-vision/app/pose_estimation/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
33
import { getImage } from '../../utils';
44
import {
5+
models,
56
usePoseEstimation,
67
PoseDetections,
78
RnExecutorchError,
89
RnExecutorchErrorCode,
9-
YOLO26N_POSE,
1010
} from 'react-native-executorch';
1111
import { View, StyleSheet, Image, Text } from 'react-native';
1212
import React, { useContext, useEffect, useState } from 'react';
@@ -31,7 +31,7 @@ export default function PoseEstimationScreen() {
3131
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
3232
const [layout, setLayout] = useState({ width: 0, height: 0 });
3333

34-
const model = usePoseEstimation({ model: YOLO26N_POSE });
34+
const model = usePoseEstimation({ model: models.pose_estimation.yolo26n() });
3535
const { setGlobalGenerating } = useContext(GeneratingContext);
3636

3737
useEffect(() => {

apps/computer-vision/app/segment_anything/index.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,10 @@ import {
2121
AlphaType,
2222
} from '@shopify/react-native-skia';
2323
import {
24+
models,
2425
useInstanceSegmentation,
2526
useImageEmbeddings,
2627
useTextEmbeddings,
27-
FASTSAM_S,
28-
FASTSAM_X,
29-
CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED,
30-
CLIP_VIT_BASE_PATCH32_TEXT,
3128
InstanceSegmentationModelSources,
3229
SegmentedInstance,
3330
FastSAMLabel,
@@ -48,19 +45,20 @@ import ImageWithMasks, {
4845
} from '../../components/ImageWithMasks';
4946
import { getImage } from '../../utils';
5047
import ColorPalette from '../../colors';
48+
const objectDetection = models.object_detection;
5149

5250
type PromptMode = 'point' | 'box' | 'text';
5351

5452
const MODELS: ModelOption<InstanceSegmentationModelSources>[] = [
55-
{ label: 'FastSAM-S', value: FASTSAM_S },
56-
{ label: 'FastSAM-X', value: FASTSAM_X },
53+
{ label: 'FastSAM-S', value: objectDetection.fastsam_s() },
54+
{ label: 'FastSAM-X', value: objectDetection.fastsam_x() },
5755
];
5856

5957
export default function SegmentAnythingScreen() {
6058
const { setGlobalGenerating } = useContext(GeneratingContext);
6159

6260
const [selectedModel, setSelectedModel] =
63-
useState<InstanceSegmentationModelSources>(FASTSAM_S);
61+
useState<InstanceSegmentationModelSources>(objectDetection.fastsam_s());
6462
const [mode, setMode] = useState<PromptMode>('point');
6563
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
6664

@@ -78,9 +76,11 @@ export default function SegmentAnythingScreen() {
7876
useInstanceSegmentation({ model: selectedModel });
7977

8078
const clipImage = useImageEmbeddings({
81-
model: CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED,
79+
model: models.image_embedding.clip_vit_base_patch32_image(),
80+
});
81+
const clipText = useTextEmbeddings({
82+
model: models.text_embedding.clip_vit_base_patch32_text(),
8283
});
83-
const clipText = useTextEmbeddings({ model: CLIP_VIT_BASE_PATCH32_TEXT });
8484
const skiaSource = useImage(imageUri || null);
8585

8686
const [textPrompt, setTextPrompt] = useState('');

0 commit comments

Comments
 (0)