diff --git a/.eslintrc.js b/.eslintrc.js index 35d2da64cc..b09ff37d23 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -63,7 +63,11 @@ module.exports = { customWordListFile: path.resolve(__dirname, '.cspell-wordlist.txt'), }, ], - 'camelcase': 'error', + // `properties: 'never'` lets the lowercase snake_case keys in `models` + // (e.g. `models.text_to_speech.kokoro_small`, mirroring the underlying + // `.pte` filenames) pass while still requiring camelCase for variable + // and function declarations. + 'camelcase': ['error', { properties: 'never' }], 'jsdoc/require-jsdoc': 'off', 'jsdoc/require-param': ['error', { checkDestructured: false }], 'jsdoc/check-param-names': ['error', { checkDestructured: false }], diff --git a/apps/bare-rn/App.tsx b/apps/bare-rn/App.tsx index b7e28658dc..cb6af0aa33 100644 --- a/apps/bare-rn/App.tsx +++ b/apps/bare-rn/App.tsx @@ -13,11 +13,7 @@ import { TouchableWithoutFeedback, View, } from 'react-native'; -import { - initExecutorch, - useLLM, - LLAMA3_2_1B_SPINQUANT, -} from 'react-native-executorch'; +import { models, initExecutorch, useLLM } from 'react-native-executorch'; import { BareResourceFetcher } from 'react-native-executorch-bare-resource-fetcher'; import { setConfig } from '@kesha-antonov/react-native-background-downloader'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; @@ -144,7 +140,9 @@ function App() { const textInputRef = useRef(null); const scrollViewRef = useRef(null); - const llm = useLLM({ model: LLAMA3_2_1B_SPINQUANT }); + const llm = useLLM({ + model: models.llm.lfm2_5_1_2b_instruct(), + }); // Alternatively, to use a custom local model, uncomment below: // const llm = useLLM({ model: { // modelSource: require('./assets/ai-models/smolLm2/smolLm2_135M/smolLm2_135M_bf16.pte'), diff --git a/apps/computer-vision/app/classification/index.tsx b/apps/computer-vision/app/classification/index.tsx index d45e0ddbf8..55a42f7422 100644 --- a/apps/computer-vision/app/classification/index.tsx +++ b/apps/computer-vision/app/classification/index.tsx @@ -1,16 +1,22 @@ import Spinner from '../../components/Spinner'; import { getImage } from '../../utils'; import { + models, useClassification, - EFFICIENTNET_V2_S, - EFFICIENTNET_V2_S_QUANTIZED, ClassificationModelSources, } from 'react-native-executorch'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; +const classification = models.classification; const MODELS: ModelOption[] = [ - { label: 'EfficientNet V2 S Quantized', value: EFFICIENTNET_V2_S_QUANTIZED }, - { label: 'EfficientNet V2 S', value: EFFICIENTNET_V2_S }, + { + label: 'EfficientNet V2 S Quantized', + value: classification.efficientnet_v2_s(), + }, + { + label: 'EfficientNet V2 S', + value: classification.efficientnet_v2_s({ quant: false }), + }, ]; import { View, StyleSheet, Image, Text, ScrollView } from 'react-native'; import { BottomBar } from '../../components/BottomBar'; @@ -22,7 +28,7 @@ import ErrorBanner from '../../components/ErrorBanner'; export default function ClassificationScreen() { const [selectedModel, setSelectedModel] = - useState(EFFICIENTNET_V2_S_QUANTIZED); + useState(classification.efficientnet_v2_s()); const [results, setResults] = useState<{ label: string; score: number }[]>( [] ); diff --git a/apps/computer-vision/app/instance_segmentation/index.tsx b/apps/computer-vision/app/instance_segmentation/index.tsx index f669c383d5..72a4c64506 100644 --- a/apps/computer-vision/app/instance_segmentation/index.tsx +++ b/apps/computer-vision/app/instance_segmentation/index.tsx @@ -3,16 +3,9 @@ import { BottomBar } from '../../components/BottomBar'; import { getImage } from '../../utils'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; import { + models, useInstanceSegmentation, - YOLO26N_SEG, - YOLO26S_SEG, - YOLO26M_SEG, - YOLO26L_SEG, - YOLO26X_SEG, - RF_DETR_NANO_SEG, InstanceSegmentationModelSources, - FASTSAM_S, - FASTSAM_X, } from 'react-native-executorch'; import { View, @@ -29,21 +22,28 @@ import ImageWithMasks, { DisplayInstance, } from '../../components/ImageWithMasks'; import { StatsBar } from '../../components/StatsBar'; +const instanceSegmentation = models.instance_segmentation; +const objectDetection = models.object_detection; const MODELS: ModelOption[] = [ - { label: 'Yolo26N', value: YOLO26N_SEG }, - { label: 'Yolo26S', value: YOLO26S_SEG }, - { label: 'Yolo26M', value: YOLO26M_SEG }, - { label: 'Yolo26L', value: YOLO26L_SEG }, - { label: 'Yolo26X', value: YOLO26X_SEG }, - { label: 'RF-DeTR Nano', value: RF_DETR_NANO_SEG }, - { label: 'FastSAM-S', value: FASTSAM_S }, - { label: 'FastSAM-X', value: FASTSAM_X }, + { label: 'Yolo26N', value: instanceSegmentation.yolo26n_seg() }, + { label: 'Yolo26S', value: instanceSegmentation.yolo26s_seg() }, + { label: 'Yolo26M', value: instanceSegmentation.yolo26m_seg() }, + { label: 'Yolo26L', value: instanceSegmentation.yolo26l_seg() }, + { label: 'Yolo26X', value: instanceSegmentation.yolo26x_seg() }, + { + label: 'RF-DeTR Nano', + value: instanceSegmentation.rf_detr_nano_seg(), + }, + { label: 'FastSAM-S', value: objectDetection.fastsam_s() }, + { label: 'FastSAM-X', value: objectDetection.fastsam_x() }, ]; export default function InstanceSegmentationScreen() { const [selectedModel, setSelectedModel] = - useState(YOLO26N_SEG); + useState( + instanceSegmentation.yolo26n_seg() + ); const [inferenceTime, setInferenceTime] = useState(null); const { setGlobalGenerating } = useContext(GeneratingContext); diff --git a/apps/computer-vision/app/object_detection/index.tsx b/apps/computer-vision/app/object_detection/index.tsx index ea4a9fc7b7..1ed3c136ba 100644 --- a/apps/computer-vision/app/object_detection/index.tsx +++ b/apps/computer-vision/app/object_detection/index.tsx @@ -3,15 +3,9 @@ import { BottomBar } from '../../components/BottomBar'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; import { getImage } from '../../utils'; import { + models, Detection, useObjectDetection, - RF_DETR_NANO, - SSDLITE_320_MOBILENET_V3_LARGE, - YOLO26N, - YOLO26S, - YOLO26M, - YOLO26L, - YOLO26X, ObjectDetectionModelSources, } from 'react-native-executorch'; import { View, StyleSheet, Image, Text } from 'react-native'; @@ -20,15 +14,22 @@ import React, { useContext, useEffect, useState } from 'react'; import { GeneratingContext } from '../../context'; import ScreenWrapper from '../../ScreenWrapper'; import { StatsBar } from '../../components/StatsBar'; +const objectDetection = models.object_detection; const MODELS: ModelOption[] = [ - { label: 'RF-DeTR Nano', value: RF_DETR_NANO }, - { label: 'SSDLite MobileNet', value: SSDLITE_320_MOBILENET_V3_LARGE }, - { label: 'YOLO26N', value: YOLO26N }, - { label: 'YOLO26S', value: YOLO26S }, - { label: 'YOLO26M', value: YOLO26M }, - { label: 'YOLO26L', value: YOLO26L }, - { label: 'YOLO26X', value: YOLO26X }, + { + label: 'RF-DeTR Nano', + value: objectDetection.rf_detr_nano(), + }, + { + label: 'SSDLite MobileNet', + value: objectDetection.ssdlite_320_mobilenet_v3_large(), + }, + { label: 'YOLO26N', value: objectDetection.yolo26n() }, + { label: 'YOLO26S', value: objectDetection.yolo26s() }, + { label: 'YOLO26M', value: objectDetection.yolo26m() }, + { label: 'YOLO26L', value: objectDetection.yolo26l() }, + { label: 'YOLO26X', value: objectDetection.yolo26x() }, ]; import ErrorBanner from '../../components/ErrorBanner'; @@ -41,7 +42,7 @@ export default function ObjectDetectionScreen() { height: number; }>(); const [selectedModel, setSelectedModel] = - useState(RF_DETR_NANO); + useState(objectDetection.rf_detr_nano()); const [inferenceTime, setInferenceTime] = useState(null); const model = useObjectDetection({ model: selectedModel }); diff --git a/apps/computer-vision/app/ocr/index.tsx b/apps/computer-vision/app/ocr/index.tsx index de4abcd400..b81b57326c 100644 --- a/apps/computer-vision/app/ocr/index.tsx +++ b/apps/computer-vision/app/ocr/index.tsx @@ -2,17 +2,7 @@ import Spinner from '../../components/Spinner'; import { BottomBar } from '../../components/BottomBar'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; import { getImage } from '../../utils'; -import { - useOCR, - OCR_ENGLISH, - OCR_GERMAN, - OCR_FRENCH, - OCR_SPANISH, - OCR_ITALIAN, - OCR_JAPANESE, - OCR_KOREAN, - OCRProps, -} from 'react-native-executorch'; +import { models, useOCR, OCRProps } from 'react-native-executorch'; import { View, StyleSheet, Image, Text, ScrollView } from 'react-native'; import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes'; import React, { useContext, useEffect, useState } from 'react'; @@ -22,14 +12,16 @@ import { StatsBar } from '../../components/StatsBar'; type OCRModelSources = OCRProps['model']; +const ocr = models.ocr.craft; + const MODELS: ModelOption[] = [ - { label: 'English', value: OCR_ENGLISH }, - { label: 'German', value: OCR_GERMAN }, - { label: 'French', value: OCR_FRENCH }, - { label: 'Spanish', value: OCR_SPANISH }, - { label: 'Italian', value: OCR_ITALIAN }, - { label: 'Japanese', value: OCR_JAPANESE }, - { label: 'Korean', value: OCR_KOREAN }, + { label: 'English', value: ocr({ language: 'en' }) }, + { label: 'German', value: ocr({ language: 'de' }) }, + { label: 'French', value: ocr({ language: 'fr' }) }, + { label: 'Spanish', value: ocr({ language: 'es' }) }, + { label: 'Italian', value: ocr({ language: 'it' }) }, + { label: 'Japanese', value: ocr({ language: 'ja' }) }, + { label: 'Korean', value: ocr({ language: 'ko' }) }, ]; import ErrorBanner from '../../components/ErrorBanner'; @@ -41,8 +33,9 @@ export default function OCRScreen() { width: number; height: number; }>(); - const [selectedModel, setSelectedModel] = - useState(OCR_ENGLISH); + const [selectedModel, setSelectedModel] = useState( + ocr({ language: 'en' }) + ); const [inferenceTime, setInferenceTime] = useState(null); const model = useOCR({ diff --git a/apps/computer-vision/app/ocr_vertical/index.tsx b/apps/computer-vision/app/ocr_vertical/index.tsx index 8754ee8b5f..f1a015eb01 100644 --- a/apps/computer-vision/app/ocr_vertical/index.tsx +++ b/apps/computer-vision/app/ocr_vertical/index.tsx @@ -1,7 +1,7 @@ import Spinner from '../../components/Spinner'; import { BottomBar } from '../../components/BottomBar'; import { getImage } from '../../utils'; -import { useVerticalOCR, OCR_ENGLISH } from 'react-native-executorch'; +import { models, useVerticalOCR } from 'react-native-executorch'; import { View, StyleSheet, Image, Text, ScrollView } from 'react-native'; import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes'; import React, { useContext, useEffect, useState } from 'react'; @@ -22,7 +22,7 @@ export default function VerticalOCRScreen() { const [error, setError] = useState(null); const model = useVerticalOCR({ - model: OCR_ENGLISH, + model: models.ocr.craft({ language: 'en' }), independentCharacters: true, }); diff --git a/apps/computer-vision/app/pose_estimation/index.tsx b/apps/computer-vision/app/pose_estimation/index.tsx index 3a07816e7e..4546b628fa 100644 --- a/apps/computer-vision/app/pose_estimation/index.tsx +++ b/apps/computer-vision/app/pose_estimation/index.tsx @@ -2,11 +2,11 @@ import Spinner from '../../components/Spinner'; import { BottomBar } from '../../components/BottomBar'; import { getImage } from '../../utils'; import { + models, usePoseEstimation, PoseDetections, RnExecutorchError, RnExecutorchErrorCode, - YOLO26N_POSE, } from 'react-native-executorch'; import { View, StyleSheet, Image, Text } from 'react-native'; import React, { useContext, useEffect, useState } from 'react'; @@ -31,7 +31,7 @@ export default function PoseEstimationScreen() { const [inferenceTime, setInferenceTime] = useState(null); const [layout, setLayout] = useState({ width: 0, height: 0 }); - const model = usePoseEstimation({ model: YOLO26N_POSE }); + const model = usePoseEstimation({ model: models.pose_estimation.yolo26n() }); const { setGlobalGenerating } = useContext(GeneratingContext); useEffect(() => { diff --git a/apps/computer-vision/app/segment_anything/index.tsx b/apps/computer-vision/app/segment_anything/index.tsx index 037a988327..b4101309c0 100644 --- a/apps/computer-vision/app/segment_anything/index.tsx +++ b/apps/computer-vision/app/segment_anything/index.tsx @@ -21,13 +21,10 @@ import { AlphaType, } from '@shopify/react-native-skia'; import { + models, useInstanceSegmentation, useImageEmbeddings, useTextEmbeddings, - FASTSAM_S, - FASTSAM_X, - CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED, - CLIP_VIT_BASE_PATCH32_TEXT, InstanceSegmentationModelSources, SegmentedInstance, FastSAMLabel, @@ -48,19 +45,20 @@ import ImageWithMasks, { } from '../../components/ImageWithMasks'; import { getImage } from '../../utils'; import ColorPalette from '../../colors'; +const objectDetection = models.object_detection; type PromptMode = 'point' | 'box' | 'text'; const MODELS: ModelOption[] = [ - { label: 'FastSAM-S', value: FASTSAM_S }, - { label: 'FastSAM-X', value: FASTSAM_X }, + { label: 'FastSAM-S', value: objectDetection.fastsam_s() }, + { label: 'FastSAM-X', value: objectDetection.fastsam_x() }, ]; export default function SegmentAnythingScreen() { const { setGlobalGenerating } = useContext(GeneratingContext); const [selectedModel, setSelectedModel] = - useState(FASTSAM_S); + useState(objectDetection.fastsam_s()); const [mode, setMode] = useState('point'); const [inferenceTime, setInferenceTime] = useState(null); @@ -78,9 +76,11 @@ export default function SegmentAnythingScreen() { useInstanceSegmentation({ model: selectedModel }); const clipImage = useImageEmbeddings({ - model: CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED, + model: models.image_embedding.clip_vit_base_patch32_image(), + }); + const clipText = useTextEmbeddings({ + model: models.text_embedding.clip_vit_base_patch32_text(), }); - const clipText = useTextEmbeddings({ model: CLIP_VIT_BASE_PATCH32_TEXT }); const skiaSource = useImage(imageUri || null); const [textPrompt, setTextPrompt] = useState(''); diff --git a/apps/computer-vision/app/semantic_segmentation/index.tsx b/apps/computer-vision/app/semantic_segmentation/index.tsx index ba998bca2a..f77c8de9c8 100644 --- a/apps/computer-vision/app/semantic_segmentation/index.tsx +++ b/apps/computer-vision/app/semantic_segmentation/index.tsx @@ -3,13 +3,7 @@ import { BottomBar } from '../../components/BottomBar'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; import { getImage } from '../../utils'; import { - DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED, - DEEPLAB_V3_RESNET50_QUANTIZED, - DEEPLAB_V3_RESNET101_QUANTIZED, - LRASPP_MOBILENET_V3_LARGE_QUANTIZED, - FCN_RESNET50_QUANTIZED, - FCN_RESNET101_QUANTIZED, - SELFIE_SEGMENTATION, + models, useSemanticSegmentation, SemanticSegmentationModelSources, } from 'react-native-executorch'; @@ -27,6 +21,7 @@ import { GeneratingContext } from '../../context'; import ScreenWrapper from '../../ScreenWrapper'; import { StatsBar } from '../../components/StatsBar'; import ErrorBanner from '../../components/ErrorBanner'; +const semanticSegmentation = models.semantic_segmentation; const numberToColor: number[][] = [ [255, 87, 51], // 0 Red @@ -55,21 +50,39 @@ const numberToColor: number[][] = [ const MODELS: ModelOption[] = [ { label: 'DeepLab MobileNet', - value: DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED, + value: semanticSegmentation.deeplab_v3_mobilenet_v3_large(), + }, + { + label: 'DeepLab ResNet50', + value: semanticSegmentation.deeplab_v3_resnet50(), + }, + { + label: 'DeepLab ResNet101', + value: semanticSegmentation.deeplab_v3_resnet101(), + }, + { + label: 'LRASPP MobileNet', + value: semanticSegmentation.lraspp_mobilenet_v3_large(), + }, + { + label: 'FCN ResNet50', + value: semanticSegmentation.fcn_resnet50(), + }, + { + label: 'FCN ResNet101', + value: semanticSegmentation.fcn_resnet101(), + }, + { + label: 'Selfie Segmentation', + value: semanticSegmentation.selfie_segmentation(), }, - { label: 'DeepLab ResNet50', value: DEEPLAB_V3_RESNET50_QUANTIZED }, - { label: 'DeepLab ResNet101', value: DEEPLAB_V3_RESNET101_QUANTIZED }, - { label: 'LRASPP MobileNet', value: LRASPP_MOBILENET_V3_LARGE_QUANTIZED }, - { label: 'FCN ResNet50', value: FCN_RESNET50_QUANTIZED }, - { label: 'FCN ResNet101', value: FCN_RESNET101_QUANTIZED }, - { label: 'Selfie Segmentation', value: SELFIE_SEGMENTATION }, ]; export default function SemanticSegmentationScreen() { const { setGlobalGenerating } = useContext(GeneratingContext); const [selectedModel, setSelectedModel] = useState( - DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED + semanticSegmentation.deeplab_v3_mobilenet_v3_large() ); const { diff --git a/apps/computer-vision/app/style_transfer/index.tsx b/apps/computer-vision/app/style_transfer/index.tsx index 8770087067..d8eda655f7 100644 --- a/apps/computer-vision/app/style_transfer/index.tsx +++ b/apps/computer-vision/app/style_transfer/index.tsx @@ -3,11 +3,8 @@ import { BottomBar } from '../../components/BottomBar'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; import { getImage } from '../../utils'; import { + models, useStyleTransfer, - STYLE_TRANSFER_CANDY_QUANTIZED, - STYLE_TRANSFER_MOSAIC_QUANTIZED, - STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED, - STYLE_TRANSFER_UDNIE_QUANTIZED, StyleTransferModelName, ResourceSource, } from 'react-native-executorch'; @@ -18,6 +15,7 @@ import React, { useContext, useEffect, useState } from 'react'; import { GeneratingContext } from '../../context'; import ScreenWrapper from '../../ScreenWrapper'; import { StatsBar } from '../../components/StatsBar'; +const styleTransfer = models.style_transfer; type StyleTransferModelSources = { modelName: StyleTransferModelName; @@ -25,16 +23,19 @@ type StyleTransferModelSources = { }; const MODELS: ModelOption[] = [ - { label: 'Candy', value: STYLE_TRANSFER_CANDY_QUANTIZED }, - { label: 'Mosaic', value: STYLE_TRANSFER_MOSAIC_QUANTIZED }, - { label: 'Rain Princess', value: STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED }, - { label: 'Udnie', value: STYLE_TRANSFER_UDNIE_QUANTIZED }, + { label: 'Candy', value: styleTransfer.candy() }, + { label: 'Mosaic', value: styleTransfer.mosaic() }, + { + label: 'Rain Princess', + value: styleTransfer.rain_princess(), + }, + { label: 'Udnie', value: styleTransfer.udnie() }, ]; import ErrorBanner from '../../components/ErrorBanner'; export default function StyleTransferScreen() { const [selectedModel, setSelectedModel] = useState( - STYLE_TRANSFER_CANDY_QUANTIZED + styleTransfer.candy() ); const model = useStyleTransfer({ model: selectedModel }); diff --git a/apps/computer-vision/app/text_to_image/index.tsx b/apps/computer-vision/app/text_to_image/index.tsx index 6af71227e9..47fce1e8b6 100644 --- a/apps/computer-vision/app/text_to_image/index.tsx +++ b/apps/computer-vision/app/text_to_image/index.tsx @@ -14,9 +14,8 @@ import React, { useContext, useEffect, useState } from 'react'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Spinner from '../../components/Spinner'; import { + models, useTextToImage, - BK_SDM_TINY_VPRED_256, - BK_SDM_TINY_VPRED_512, TextToImageProps, } from 'react-native-executorch'; import { ModelPicker, ModelOption } from '../../components/ModelPicker'; @@ -26,12 +25,19 @@ import ProgressBar from '../../components/ProgressBar'; import { Ionicons } from '@expo/vector-icons'; import { StatsBar } from '../../components/StatsBar'; import ErrorBanner from '../../components/ErrorBanner'; +const imageGeneration = models.image_generation; type TextToImageModelSources = TextToImageProps['model']; const MODELS: ModelOption[] = [ - { label: 'BK-SDM 256', value: BK_SDM_TINY_VPRED_256 }, - { label: 'BK-SDM 512', value: BK_SDM_TINY_VPRED_512 }, + { + label: 'BK-SDM 256', + value: imageGeneration.bk_sdm_tiny_vpred_256(), + }, + { + label: 'BK-SDM 512', + value: imageGeneration.bk_sdm_tiny_vpred_512(), + }, ]; export default function TextToImageScreen() { @@ -42,7 +48,7 @@ export default function TextToImageScreen() { const [input, setInput] = useState(''); const [selectedModel, setSelectedModel] = useState( - BK_SDM_TINY_VPRED_256 + imageGeneration.bk_sdm_tiny_vpred_256() ); const [generationTime, setGenerationTime] = useState(null); diff --git a/apps/computer-vision/components/vision_camera/tasks/ClassificationTask.tsx b/apps/computer-vision/components/vision_camera/tasks/ClassificationTask.tsx index ef0046a297..e5b2f3ad3f 100644 --- a/apps/computer-vision/components/vision_camera/tasks/ClassificationTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/ClassificationTask.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; -import { EFFICIENTNET_V2_S, useClassification } from 'react-native-executorch'; +import { models, useClassification } from 'react-native-executorch'; import { FRAME_TARGET_RESOLUTION, TaskProps } from './types'; type Props = Omit< @@ -19,7 +19,9 @@ export default function ClassificationTask({ onFpsChange, onErrorChange, }: Props) { - const model = useClassification({ model: EFFICIENTNET_V2_S }); + const model = useClassification({ + model: models.classification.efficientnet_v2_s(), + }); const [classResult, setClassResult] = useState({ label: '', score: 0 }); const lastFrameTimeRef = useRef(Date.now()); diff --git a/apps/computer-vision/components/vision_camera/tasks/InstanceSegmentationTask.tsx b/apps/computer-vision/components/vision_camera/tasks/InstanceSegmentationTask.tsx index 52251f6e3e..478cb25732 100644 --- a/apps/computer-vision/components/vision_camera/tasks/InstanceSegmentationTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/InstanceSegmentationTask.tsx @@ -3,11 +3,8 @@ import { StyleSheet, Text, View } from 'react-native'; import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; import { + models, SegmentedInstance, - YOLO26N_SEG, - RF_DETR_NANO_SEG, - FASTSAM_S, - FASTSAM_X, useInstanceSegmentation, CocoLabel, CocoLabelYolo, @@ -20,6 +17,8 @@ import { buildDisplayInstances, DisplayInstance, } from '../../../components/ImageWithMasks'; +const instanceSegmentation = models.instance_segmentation; +const objectDetection = models.object_detection; type InstSegModelId = | 'instanceSegmentationYolo26n' @@ -42,19 +41,19 @@ export default function InstanceSegmentationTask({ onErrorChange, }: Props) { const yolo26n = useInstanceSegmentation({ - model: YOLO26N_SEG, + model: instanceSegmentation.yolo26n_seg(), preventLoad: activeModel !== 'instanceSegmentationYolo26n', }); const rfdetr = useInstanceSegmentation({ - model: RF_DETR_NANO_SEG, + model: instanceSegmentation.rf_detr_nano_seg(), preventLoad: activeModel !== 'instanceSegmentationRfdetr', }); const fastsamS = useInstanceSegmentation({ - model: FASTSAM_S, + model: objectDetection.fastsam_s(), preventLoad: activeModel !== 'instanceSegmentationFastsamS', }); const fastsamX = useInstanceSegmentation({ - model: FASTSAM_X, + model: objectDetection.fastsam_x(), preventLoad: activeModel !== 'instanceSegmentationFastsamX', }); diff --git a/apps/computer-vision/components/vision_camera/tasks/OCRTask.tsx b/apps/computer-vision/components/vision_camera/tasks/OCRTask.tsx index 3dfa874b43..54e73161a1 100644 --- a/apps/computer-vision/components/vision_camera/tasks/OCRTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/OCRTask.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { StyleSheet, View } from 'react-native'; import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; -import { OCR_ENGLISH, OCRDetection, useOCR } from 'react-native-executorch'; +import { models, OCRDetection, useOCR } from 'react-native-executorch'; import Svg, { Polygon, Text as SvgText } from 'react-native-svg'; import { FRAME_TARGET_RESOLUTION, TaskProps } from './types'; @@ -19,7 +19,7 @@ export default function OCRTask({ onFpsChange, onErrorChange, }: Props) { - const model = useOCR({ model: OCR_ENGLISH }); + const model = useOCR({ model: models.ocr.craft({ language: 'en' }) }); const [detections, setDetections] = useState([]); const [imageSize, setImageSize] = useState({ width: 1, height: 1 }); const lastFrameTimeRef = useRef(Date.now()); diff --git a/apps/computer-vision/components/vision_camera/tasks/ObjectDetectionTask.tsx b/apps/computer-vision/components/vision_camera/tasks/ObjectDetectionTask.tsx index 992a8eaad0..e05de26105 100644 --- a/apps/computer-vision/components/vision_camera/tasks/ObjectDetectionTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/ObjectDetectionTask.tsx @@ -3,16 +3,15 @@ import { StyleSheet, View } from 'react-native'; import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; import { + models, Detection, - RF_DETR_NANO, - SSDLITE_320_MOBILENET_V3_LARGE, - YOLO26N, useObjectDetection, CocoLabel, CocoLabelYolo, } from 'react-native-executorch'; import BoundingBoxes from '../../BoundingBoxes'; import { FRAME_TARGET_RESOLUTION, TaskProps } from './types'; +const objectDetection = models.object_detection; type ObjModelId = | 'objectDetectionSsdlite' @@ -34,15 +33,15 @@ export default function ObjectDetectionTask({ onErrorChange, }: Props) { const ssdlite = useObjectDetection({ - model: SSDLITE_320_MOBILENET_V3_LARGE, + model: objectDetection.ssdlite_320_mobilenet_v3_large(), preventLoad: activeModel !== 'objectDetectionSsdlite', }); const rfdetr = useObjectDetection({ - model: RF_DETR_NANO, + model: objectDetection.rf_detr_nano(), preventLoad: activeModel !== 'objectDetectionRfdetr', }); const yolo26n = useObjectDetection({ - model: YOLO26N, + model: objectDetection.yolo26n(), preventLoad: activeModel !== 'objectDetectionYolo26n', }); diff --git a/apps/computer-vision/components/vision_camera/tasks/PoseEstimationTask.tsx b/apps/computer-vision/components/vision_camera/tasks/PoseEstimationTask.tsx index 476435643d..a357881da0 100644 --- a/apps/computer-vision/components/vision_camera/tasks/PoseEstimationTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/PoseEstimationTask.tsx @@ -4,9 +4,9 @@ import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; import Svg, { Circle, Line } from 'react-native-svg'; import { + models, usePoseEstimation, PoseDetections, - YOLO26N_POSE, } from 'react-native-executorch'; import { TaskProps } from './types'; import { COCO_SKELETON_CONNECTIONS } from '../../utils/cocoSkeleton'; @@ -29,7 +29,7 @@ export default function PoseEstimationTask({ onErrorChange, }: Props) { const poseModel = usePoseEstimation({ - model: YOLO26N_POSE, + model: models.pose_estimation.yolo26n(), preventLoad: activeModel !== 'poseEstimationYolo26n', }); diff --git a/apps/computer-vision/components/vision_camera/tasks/SegmentationTask.tsx b/apps/computer-vision/components/vision_camera/tasks/SegmentationTask.tsx index b06f2ff9d1..b88e457b23 100644 --- a/apps/computer-vision/components/vision_camera/tasks/SegmentationTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/SegmentationTask.tsx @@ -2,16 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { StyleSheet, View } from 'react-native'; import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; -import { - DEEPLAB_V3_RESNET50_QUANTIZED, - DEEPLAB_V3_RESNET101_QUANTIZED, - DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED, - FCN_RESNET50_QUANTIZED, - FCN_RESNET101_QUANTIZED, - LRASPP_MOBILENET_V3_LARGE_QUANTIZED, - SELFIE_SEGMENTATION, - useSemanticSegmentation, -} from 'react-native-executorch'; +import { models, useSemanticSegmentation } from 'react-native-executorch'; import { AlphaType, Canvas, @@ -22,6 +13,7 @@ import { } from '@shopify/react-native-skia'; import { CLASS_COLORS } from '../../utils/colors'; import { FRAME_TARGET_RESOLUTION, TaskProps } from './types'; +const semanticSegmentation = models.semantic_segmentation; type SegModelId = | 'segmentationDeeplabResnet50' @@ -47,31 +39,31 @@ export default function SegmentationTask({ onErrorChange, }: Props) { const segDeeplabResnet50 = useSemanticSegmentation({ - model: DEEPLAB_V3_RESNET50_QUANTIZED, + model: semanticSegmentation.deeplab_v3_resnet50(), preventLoad: activeModel !== 'segmentationDeeplabResnet50', }); const segDeeplabResnet101 = useSemanticSegmentation({ - model: DEEPLAB_V3_RESNET101_QUANTIZED, + model: semanticSegmentation.deeplab_v3_resnet101(), preventLoad: activeModel !== 'segmentationDeeplabResnet101', }); const segDeeplabMobilenet = useSemanticSegmentation({ - model: DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED, + model: semanticSegmentation.deeplab_v3_mobilenet_v3_large(), preventLoad: activeModel !== 'segmentationDeeplabMobilenet', }); const segLraspp = useSemanticSegmentation({ - model: LRASPP_MOBILENET_V3_LARGE_QUANTIZED, + model: semanticSegmentation.lraspp_mobilenet_v3_large(), preventLoad: activeModel !== 'segmentationLraspp', }); const segFcnResnet50 = useSemanticSegmentation({ - model: FCN_RESNET50_QUANTIZED, + model: semanticSegmentation.fcn_resnet50(), preventLoad: activeModel !== 'segmentationFcnResnet50', }); const segFcnResnet101 = useSemanticSegmentation({ - model: FCN_RESNET101_QUANTIZED, + model: semanticSegmentation.fcn_resnet101(), preventLoad: activeModel !== 'segmentationFcnResnet101', }); const segSelfie = useSemanticSegmentation({ - model: SELFIE_SEGMENTATION, + model: semanticSegmentation.selfie_segmentation(), preventLoad: activeModel !== 'segmentationSelfie', }); diff --git a/apps/computer-vision/components/vision_camera/tasks/StyleTransferTask.tsx b/apps/computer-vision/components/vision_camera/tasks/StyleTransferTask.tsx index 6361970bfc..d5f8578272 100644 --- a/apps/computer-vision/components/vision_camera/tasks/StyleTransferTask.tsx +++ b/apps/computer-vision/components/vision_camera/tasks/StyleTransferTask.tsx @@ -2,11 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { StyleSheet, View } from 'react-native'; import { Frame, useFrameOutput } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; -import { - STYLE_TRANSFER_CANDY, - STYLE_TRANSFER_MOSAIC, - useStyleTransfer, -} from 'react-native-executorch'; +import { models, useStyleTransfer } from 'react-native-executorch'; import { AlphaType, Canvas, @@ -16,6 +12,7 @@ import { SkImage, } from '@shopify/react-native-skia'; import { FRAME_TARGET_RESOLUTION, TaskProps } from './types'; +const styleTransfer = models.style_transfer; type StyleModelId = 'styleTransferCandy' | 'styleTransferMosaic'; @@ -34,11 +31,11 @@ export default function StyleTransferTask({ onErrorChange, }: Props) { const candy = useStyleTransfer({ - model: STYLE_TRANSFER_CANDY, + model: styleTransfer.candy(), preventLoad: activeModel !== 'styleTransferCandy', }); const mosaic = useStyleTransfer({ - model: STYLE_TRANSFER_MOSAIC, + model: styleTransfer.mosaic(), preventLoad: activeModel !== 'styleTransferMosaic', }); diff --git a/apps/llm/app/llm/index.tsx b/apps/llm/app/llm/index.tsx index 901b74de43..ed7d4a99c1 100644 --- a/apps/llm/app/llm/index.tsx +++ b/apps/llm/app/llm/index.tsx @@ -11,7 +11,7 @@ import { View, } from 'react-native'; import SendIcon from '../../assets/icons/send_icon.svg'; -import { useLLM, LLAMA3_2_1B_SPINQUANT } from 'react-native-executorch'; +import { models, useLLM } from 'react-native-executorch'; import { ModelPicker } from '../../components/ModelPicker'; import { LLM_MODELS, LLMModelSources } from '../../components/llmModels'; import PauseIcon from '../../assets/icons/pause_icon.svg'; @@ -43,7 +43,7 @@ function LLMScreen() { const [isTextInputFocused, setIsTextInputFocused] = useState(false); const [userInput, setUserInput] = useState(''); const [selectedModel, setSelectedModel] = useState( - LLAMA3_2_1B_SPINQUANT + models.llm.lfm2_5_1_2b_instruct() ); const textInputRef = useRef(null); const { setGlobalGenerating } = useContext(GeneratingContext); diff --git a/apps/llm/app/llm_structured_output/index.tsx b/apps/llm/app/llm_structured_output/index.tsx index aea47b8136..8150da4d6c 100644 --- a/apps/llm/app/llm_structured_output/index.tsx +++ b/apps/llm/app/llm_structured_output/index.tsx @@ -24,10 +24,10 @@ import { useLLMStats } from '../../hooks/useLLMStats'; import { StatsBar } from '../../components/StatsBar'; import ErrorBanner from '../../components/ErrorBanner'; import { + models, useLLM, fixAndValidateStructuredOutput, getStructuredOutputPrompt, - QWEN3_1_7B_QUANTIZED, } from 'react-native-executorch'; import { ModelPicker } from '../../components/ModelPicker'; import { LLM_MODELS, LLMModelSources } from '../../components/llmModels'; @@ -83,8 +83,9 @@ export default function LLMScreenWrapper() { function LLMScreen() { const [isTextInputFocused, setIsTextInputFocused] = useState(false); const [userInput, setUserInput] = useState(''); - const [selectedModel, setSelectedModel] = - useState(QWEN3_1_7B_QUANTIZED); + const [selectedModel, setSelectedModel] = useState( + models.llm.qwen3_1_7b() + ); const textInputRef = useRef(null); const { setGlobalGenerating } = useContext(GeneratingContext); diff --git a/apps/llm/app/llm_tool_calling/index.tsx b/apps/llm/app/llm_tool_calling/index.tsx index 2ef688ed69..f059d59793 100644 --- a/apps/llm/app/llm_tool_calling/index.tsx +++ b/apps/llm/app/llm_tool_calling/index.tsx @@ -17,11 +17,7 @@ import SWMIcon from '../../assets/icons/swm_icon.svg'; import SendIcon from '../../assets/icons/send_icon.svg'; import Spinner from '../../components/Spinner'; import ErrorBanner from '../../components/ErrorBanner'; -import { - useLLM, - DEFAULT_SYSTEM_PROMPT, - HAMMER2_1_1_5B_QUANTIZED, -} from 'react-native-executorch'; +import { models, useLLM, DEFAULT_SYSTEM_PROMPT } from 'react-native-executorch'; import { ModelPicker } from '../../components/ModelPicker'; import { LLM_MODELS, LLMModelSources } from '../../components/llmModels'; import PauseIcon from '../../assets/icons/pause_icon.svg'; @@ -55,7 +51,7 @@ function LLMToolCallingScreen() { const [hasCalendarPermission, setHasCalendarPermission] = useState(true); const [hasBrightnessPermission, setHasBrightnessPermission] = useState(true); const [selectedModel, setSelectedModel] = useState( - HAMMER2_1_1_5B_QUANTIZED + models.llm.hammer2_1_1_5b() ); const textInputRef = useRef(null); const { setGlobalGenerating } = useContext(GeneratingContext); diff --git a/apps/llm/app/multimodal_llm/index.tsx b/apps/llm/app/multimodal_llm/index.tsx index b7d6859ede..0de5004849 100644 --- a/apps/llm/app/multimodal_llm/index.tsx +++ b/apps/llm/app/multimodal_llm/index.tsx @@ -14,7 +14,7 @@ import { import { launchImageLibrary } from 'react-native-image-picker'; import { useIsFocused } from '@react-navigation/native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import { useLLM, LFM2_5_VL_1_6B_QUANTIZED } from 'react-native-executorch'; +import { models, useLLM } from 'react-native-executorch'; import SendIcon from '../../assets/icons/send_icon.svg'; import PauseIcon from '../../assets/icons/pause_icon.svg'; import ColorPalette from '../../colors'; @@ -50,7 +50,7 @@ function MultimodalLLMScreen() { const [error, setError] = useState(null); const vlm = useLLM({ - model: LFM2_5_VL_1_6B_QUANTIZED, + model: models.llm.lfm2_5_vl_1_6b(), }); const tokenCount = vlm.isReady ? vlm.getGeneratedTokenCount() : 0; const { stats, onMessageSend } = useLLMStats( diff --git a/apps/llm/app/privacy_filter/index.tsx b/apps/llm/app/privacy_filter/index.tsx index e6541dfe52..6f3e132bc1 100644 --- a/apps/llm/app/privacy_filter/index.tsx +++ b/apps/llm/app/privacy_filter/index.tsx @@ -10,12 +10,13 @@ import { import { useIsFocused } from '@react-navigation/native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { + models, PiiEntity, - PRIVACY_FILTER_NEMOTRON, - PRIVACY_FILTER_OPENAI, PrivacyFilterModelSources, usePrivacyFilter, } from 'react-native-executorch'; + +const privacyFilter = models.privacy_filter; import ColorPalette from '../../colors'; import { ModelOption, ModelPicker } from '../../components/ModelPicker'; import { @@ -46,16 +47,19 @@ Workstation MAC 3C:22:FB:8E:01:9A, IPv4 10.0.42.118, device IMEI 359888061234560 /* cspell:enable */ const MODEL_OPTIONS: ModelOption[] = [ - { label: 'OpenAI Privacy Filter (8 entities)', value: PRIVACY_FILTER_OPENAI }, + { + label: 'OpenAI Privacy Filter (8 entities)', + value: privacyFilter.openai(), + }, { label: 'OpenMed Nemotron (55 entities)', - value: PRIVACY_FILTER_NEMOTRON, + value: privacyFilter.nemotron(), }, ]; // Pick the right sample to display/run based on the active model. function sampleFor(model: PrivacyFilterModelSources): string { - return model.modelName === PRIVACY_FILTER_NEMOTRON.modelName + return model.modelName === privacyFilter.nemotron().modelName ? NEMOTRON_SAMPLE : OPENAI_SAMPLE; } @@ -98,7 +102,7 @@ function PrivacyFilterScreen() { const [runError, setRunError] = useState(null); const [inferenceMs, setInferenceMs] = useState(null); const [selectedModel, setSelectedModel] = useState( - PRIVACY_FILTER_OPENAI + privacyFilter.openai() ); const filter = usePrivacyFilter({ model: selectedModel }); diff --git a/apps/llm/app/voice_chat/index.tsx b/apps/llm/app/voice_chat/index.tsx index 23ab70bff4..5bffeceb31 100644 --- a/apps/llm/app/voice_chat/index.tsx +++ b/apps/llm/app/voice_chat/index.tsx @@ -13,15 +13,9 @@ import SWMIcon from '../../assets/icons/swm_icon.svg'; import Spinner from '../../components/Spinner'; import ErrorBanner from '../../components/ErrorBanner'; import { + models, useSpeechToText, useLLM, - QWEN3_0_6B_QUANTIZED, - QWEN3_1_7B_QUANTIZED, - LLAMA3_2_1B_SPINQUANT, - WHISPER_TINY_EN, - WHISPER_TINY_EN_QUANTIZED, - WHISPER_BASE_EN, - WHISPER_SMALL_EN, LLMProps, SpeechToTextProps, } from 'react-native-executorch'; @@ -41,16 +35,24 @@ type LLMModelSources = LLMProps['model']; type STTModelSources = SpeechToTextProps['model']; const LLM_MODELS: ModelOption[] = [ - { label: 'Qwen3 0.6B', value: QWEN3_0_6B_QUANTIZED }, - { label: 'Qwen3 1.7B', value: QWEN3_1_7B_QUANTIZED }, - { label: 'Llama 1B', value: LLAMA3_2_1B_SPINQUANT }, + { label: 'Qwen3 0.6B', value: models.llm.qwen3_0_6b() }, + { label: 'Qwen3 1.7B', value: models.llm.qwen3_1_7b() }, + { label: 'Llama 1B', value: models.llm.llama3_2_1b() }, ]; const STT_MODELS: ModelOption[] = [ - { label: 'Whisper Tiny', value: WHISPER_TINY_EN }, - { label: 'Whisper Tiny Q', value: WHISPER_TINY_EN_QUANTIZED }, - { label: 'Whisper Base', value: WHISPER_BASE_EN }, - { label: 'Whisper Small', value: WHISPER_SMALL_EN }, + { + label: 'Whisper Tiny', + value: models.speech_to_text.whisper_tiny_en(), + }, + { + label: 'Whisper Base', + value: models.speech_to_text.whisper_base_en(), + }, + { + label: 'Whisper Small', + value: models.speech_to_text.whisper_small_en(), + }, ]; export default function VoiceChatScreenWrapper() { @@ -63,10 +65,12 @@ function VoiceChatScreen() { const { bottom } = useSafeAreaInsets(); const [isRecording, setIsRecording] = useState(false); const [liveTranscription, setLiveTranscription] = useState(''); - const [selectedLLM, setSelectedLLM] = - useState(QWEN3_0_6B_QUANTIZED); - const [selectedSTT, setSelectedSTT] = - useState(WHISPER_TINY_EN); + const [selectedLLM, setSelectedLLM] = useState( + models.llm.qwen3_0_6b() + ); + const [selectedSTT, setSelectedSTT] = useState( + models.speech_to_text.whisper_tiny_en() + ); const [error, setError] = useState(null); const [recorder] = useState(() => new AudioRecorder()); diff --git a/apps/llm/components/llmModels.ts b/apps/llm/components/llmModels.ts index 593db478b3..1d80d7a395 100644 --- a/apps/llm/components/llmModels.ts +++ b/apps/llm/components/llmModels.ts @@ -1,101 +1,146 @@ import { - LLAMA3_2_1B, + models, LLAMA3_2_1B_QLORA, - LLAMA3_2_1B_SPINQUANT, - LLAMA3_2_3B, LLAMA3_2_3B_QLORA, - LLAMA3_2_3B_SPINQUANT, - QWEN3_0_6B, - QWEN3_0_6B_QUANTIZED, - QWEN3_1_7B, - QWEN3_1_7B_QUANTIZED, - QWEN3_4B, - QWEN3_4B_QUANTIZED, - HAMMER2_1_0_5B, - HAMMER2_1_0_5B_QUANTIZED, - HAMMER2_1_1_5B, - HAMMER2_1_1_5B_QUANTIZED, - HAMMER2_1_3B, - HAMMER2_1_3B_QUANTIZED, - SMOLLM2_1_135M, - SMOLLM2_1_135M_QUANTIZED, - SMOLLM2_1_360M, - SMOLLM2_1_360M_QUANTIZED, - SMOLLM2_1_1_7B, - SMOLLM2_1_1_7B_QUANTIZED, - QWEN2_5_0_5B, - QWEN2_5_0_5B_QUANTIZED, - QWEN2_5_1_5B, - QWEN2_5_1_5B_QUANTIZED, - QWEN2_5_3B, - QWEN2_5_3B_QUANTIZED, - PHI_4_MINI_4B, - PHI_4_MINI_4B_QUANTIZED, - LFM2_5_350M, - LFM2_5_350M_QUANTIZED, - LFM2_5_1_2B_INSTRUCT, - LFM2_5_1_2B_INSTRUCT_QUANTIZED, LLMProps, - QWEN3_5_0_8B_QUANTIZED, - QWEN3_5_2B_QUANTIZED, - BIELIK_V3_0_1_5B_QUANTIZED, - BIELIK_V3_0_1_5B, } from 'react-native-executorch'; import { ModelOption } from './ModelPicker'; +const llm = models.llm; export type LLMModelSources = LLMProps['model']; export const LLM_MODELS: ModelOption[] = [ // Llama 3.2 - { label: 'Llama 3.2 1B', value: LLAMA3_2_1B }, + { + label: 'Llama 3.2 1B', + value: llm.llama3_2_1b({ quant: false }), + }, { label: 'Llama 3.2 1B QLoRA', value: LLAMA3_2_1B_QLORA }, - { label: 'Llama 3.2 1B SpinQuant', value: LLAMA3_2_1B_SPINQUANT }, - { label: 'Llama 3.2 3B', value: LLAMA3_2_3B }, + { label: 'Llama 3.2 1B SpinQuant', value: llm.llama3_2_1b() }, + { + label: 'Llama 3.2 3B', + value: llm.llama3_2_3b({ quant: false }), + }, { label: 'Llama 3.2 3B QLoRA', value: LLAMA3_2_3B_QLORA }, - { label: 'Llama 3.2 3B SpinQuant', value: LLAMA3_2_3B_SPINQUANT }, + { label: 'Llama 3.2 3B SpinQuant', value: llm.llama3_2_3b() }, // Qwen3 - { label: 'Qwen3 0.6B', value: QWEN3_0_6B }, - { label: 'Qwen3 0.6B Quantized', value: QWEN3_0_6B_QUANTIZED }, - { label: 'Qwen3 1.7B', value: QWEN3_1_7B }, - { label: 'Qwen3 1.7B Quantized', value: QWEN3_1_7B_QUANTIZED }, - { label: 'Qwen3 4B', value: QWEN3_4B }, - { label: 'Qwen3 4B Quantized', value: QWEN3_4B_QUANTIZED }, + { + label: 'Qwen3 0.6B', + value: llm.qwen3_0_6b({ quant: false }), + }, + { label: 'Qwen3 0.6B Quantized', value: llm.qwen3_0_6b() }, + { + label: 'Qwen3 1.7B', + value: llm.qwen3_1_7b({ quant: false }), + }, + { label: 'Qwen3 1.7B Quantized', value: llm.qwen3_1_7b() }, + { label: 'Qwen3 4B', value: llm.qwen3_4b({ quant: false }) }, + { label: 'Qwen3 4B Quantized', value: llm.qwen3_4b() }, // Hammer 2.1 - { label: 'Hammer 2.1 0.5B', value: HAMMER2_1_0_5B }, - { label: 'Hammer 2.1 0.5B Quantized', value: HAMMER2_1_0_5B_QUANTIZED }, - { label: 'Hammer 2.1 1.5B', value: HAMMER2_1_1_5B }, - { label: 'Hammer 2.1 1.5B Quantized', value: HAMMER2_1_1_5B_QUANTIZED }, - { label: 'Hammer 2.1 3B', value: HAMMER2_1_3B }, - { label: 'Hammer 2.1 3B Quantized', value: HAMMER2_1_3B_QUANTIZED }, + { + label: 'Hammer 2.1 0.5B', + value: llm.hammer2_1_0_5b({ quant: false }), + }, + { + label: 'Hammer 2.1 0.5B Quantized', + value: llm.hammer2_1_0_5b(), + }, + { + label: 'Hammer 2.1 1.5B', + value: llm.hammer2_1_1_5b({ quant: false }), + }, + { + label: 'Hammer 2.1 1.5B Quantized', + value: llm.hammer2_1_1_5b(), + }, + { + label: 'Hammer 2.1 3B', + value: llm.hammer2_1_3b({ quant: false }), + }, + { + label: 'Hammer 2.1 3B Quantized', + value: llm.hammer2_1_3b(), + }, // SmolLM2 - { label: 'SmolLM2 135M', value: SMOLLM2_1_135M }, - { label: 'SmolLM2 135M Quantized', value: SMOLLM2_1_135M_QUANTIZED }, - { label: 'SmolLM2 360M', value: SMOLLM2_1_360M }, - { label: 'SmolLM2 360M Quantized', value: SMOLLM2_1_360M_QUANTIZED }, - { label: 'SmolLM2 1.7B', value: SMOLLM2_1_1_7B }, - { label: 'SmolLM2 1.7B Quantized', value: SMOLLM2_1_1_7B_QUANTIZED }, + { + label: 'SmolLM2 135M', + value: llm.smollm2_1_135m({ quant: false }), + }, + { + label: 'SmolLM2 135M Quantized', + value: llm.smollm2_1_135m(), + }, + { + label: 'SmolLM2 360M', + value: llm.smollm2_1_360m({ quant: false }), + }, + { + label: 'SmolLM2 360M Quantized', + value: llm.smollm2_1_360m(), + }, + { + label: 'SmolLM2 1.7B', + value: llm.smollm2_1_1_7b({ quant: false }), + }, + { + label: 'SmolLM2 1.7B Quantized', + value: llm.smollm2_1_1_7b(), + }, // Qwen2.5 - { label: 'Qwen2.5 0.5B', value: QWEN2_5_0_5B }, - { label: 'Qwen2.5 0.5B Quantized', value: QWEN2_5_0_5B_QUANTIZED }, - { label: 'Qwen2.5 1.5B', value: QWEN2_5_1_5B }, - { label: 'Qwen2.5 1.5B Quantized', value: QWEN2_5_1_5B_QUANTIZED }, - { label: 'Qwen2.5 3B', value: QWEN2_5_3B }, - { label: 'Qwen2.5 3B Quantized', value: QWEN2_5_3B_QUANTIZED }, + { + label: 'Qwen2.5 0.5B', + value: llm.qwen2_5_0_5b({ quant: false }), + }, + { + label: 'Qwen2.5 0.5B Quantized', + value: llm.qwen2_5_0_5b(), + }, + { + label: 'Qwen2.5 1.5B', + value: llm.qwen2_5_1_5b({ quant: false }), + }, + { + label: 'Qwen2.5 1.5B Quantized', + value: llm.qwen2_5_1_5b(), + }, + { + label: 'Qwen2.5 3B', + value: llm.qwen2_5_3b({ quant: false }), + }, + { label: 'Qwen2.5 3B Quantized', value: llm.qwen2_5_3b() }, // Qwen3.5 - { label: 'Qwen3.5 0.8B Quantized', value: QWEN3_5_0_8B_QUANTIZED }, - { label: 'Qwen3.5 2B Quantized', value: QWEN3_5_2B_QUANTIZED }, + { label: 'Qwen3.5 0.8B Quantized', value: llm.qwen3_5_0_8b() }, + { label: 'Qwen3.5 2B Quantized', value: llm.qwen3_5_2b() }, // Phi-4 - { label: 'Phi-4 Mini 4B', value: PHI_4_MINI_4B }, - { label: 'Phi-4 Mini 4B Quantized', value: PHI_4_MINI_4B_QUANTIZED }, + { + label: 'Phi-4 Mini 4B', + value: llm.phi_4_mini_4b({ quant: false }), + }, + { + label: 'Phi-4 Mini 4B Quantized', + value: llm.phi_4_mini_4b(), + }, // LFM2.5 - { label: 'LFM2.5 350M', value: LFM2_5_350M }, - { label: 'LFM2.5 350M Quantized', value: LFM2_5_350M_QUANTIZED }, - { label: 'LFM2.5 1.2B Instruct', value: LFM2_5_1_2B_INSTRUCT }, + { + label: 'LFM2.5 350M', + value: llm.lfm2_5_350m({ quant: false }), + }, + { label: 'LFM2.5 350M Quantized', value: llm.lfm2_5_350m() }, + { + label: 'LFM2.5 1.2B Instruct', + value: llm.lfm2_5_1_2b_instruct({ quant: false }), + }, { label: 'LFM2.5 1.2B Instruct Quantized', - value: LFM2_5_1_2B_INSTRUCT_QUANTIZED, + value: llm.lfm2_5_1_2b_instruct(), }, // Bielik v3.0 - { label: 'Bielik v3.0 1.5B', value: BIELIK_V3_0_1_5B }, - { label: 'Bielik v3.0 1.5B Quantized', value: BIELIK_V3_0_1_5B_QUANTIZED }, + { + label: 'Bielik v3.0 1.5B', + value: llm.bielik_v3_0_1_5b({ quant: false }), + }, + { + label: 'Bielik v3.0 1.5B Quantized', + value: llm.bielik_v3_0_1_5b(), + }, ]; diff --git a/apps/speech/screens/Quiz.tsx b/apps/speech/screens/Quiz.tsx index ae7cf69998..ffd574d96d 100644 --- a/apps/speech/screens/Quiz.tsx +++ b/apps/speech/screens/Quiz.tsx @@ -17,10 +17,7 @@ import Animated, { runOnJS, } from 'react-native-reanimated'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; -import { - KOKORO_AMERICAN_ENGLISH_MALE_SANTA, - useTextToSpeech, -} from 'react-native-executorch'; +import { models, useTextToSpeech } from 'react-native-executorch'; import { AudioManager, AudioContext, @@ -59,7 +56,7 @@ const createAudioBufferFromVector = ( export const Quiz = ({ onBack }: { onBack: () => void }) => { // --- Hooks & State --- - const model = useTextToSpeech(KOKORO_AMERICAN_ENGLISH_MALE_SANTA); + const model = useTextToSpeech(models.text_to_speech.kokoro.en_us.santa()); const [shuffledQuestions] = useState(() => shuffleArray(QUESTIONS)); const [currentIndex, setCurrentIndex] = useState(0); diff --git a/apps/speech/screens/SpeechToTextScreen.tsx b/apps/speech/screens/SpeechToTextScreen.tsx index dfd39c15b4..0c8a5a58f8 100644 --- a/apps/speech/screens/SpeechToTextScreen.tsx +++ b/apps/speech/screens/SpeechToTextScreen.tsx @@ -12,23 +12,29 @@ import { } from 'react-native'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; import { + models, useSpeechToText, - WHISPER_TINY_EN, - WHISPER_TINY_EN_QUANTIZED, - WHISPER_BASE_EN, - WHISPER_SMALL_EN, TranscriptionResult, SpeechToTextProps, } from 'react-native-executorch'; import { ModelPicker, ModelOption } from '../components/ModelPicker'; +const speechToText = models.speech_to_text; type STTModelSources = SpeechToTextProps['model']; const MODELS: ModelOption[] = [ - { label: 'Whisper Tiny', value: WHISPER_TINY_EN }, - { label: 'Whisper Tiny Q', value: WHISPER_TINY_EN_QUANTIZED }, - { label: 'Whisper Base', value: WHISPER_BASE_EN }, - { label: 'Whisper Small', value: WHISPER_SMALL_EN }, + { + label: 'Whisper Tiny', + value: speechToText.whisper_tiny_en(), + }, + { + label: 'Whisper Base', + value: speechToText.whisper_base_en(), + }, + { + label: 'Whisper Small', + value: speechToText.whisper_small_en(), + }, ]; import FontAwesome from '@expo/vector-icons/FontAwesome'; import { @@ -46,8 +52,9 @@ import ErrorBanner from '../components/ErrorBanner'; const isSimulator = DeviceInfo.isEmulatorSync(); export const SpeechToTextScreen = ({ onBack }: { onBack: () => void }) => { - const [selectedModel, setSelectedModel] = - useState(WHISPER_TINY_EN); + const [selectedModel, setSelectedModel] = useState( + speechToText.whisper_tiny_en() + ); const model = useSpeechToText({ model: selectedModel, @@ -109,14 +116,13 @@ export const SpeechToTextScreen = ({ onBack }: { onBack: () => void }) => { return; } - const uri = await getAudioFile(audioURL); // Reset previous states setTranscription(null); setLiveResult(null); - const audioContext = new AudioContext({ sampleRate: 16000 }); - try { + const uri = await getAudioFile(audioURL); + const audioContext = new AudioContext({ sampleRate: 16000 }); const decodedAudioData = await audioContext.decodeAudioData(uri); const audioBuffer = decodedAudioData.getChannelData(0); const start = Date.now(); @@ -326,6 +332,7 @@ export const SpeechToTextScreen = ({ onBack }: { onBack: () => void }) => { { const [displayText, setDisplayText] = useState(''); const [isTtsStreaming, setIsTtsStreaming] = useState(false); - const llm = useLLM({ model: LLAMA3_2_1B_QLORA }); - const tts = useTextToSpeech(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART); + const llm = useLLM({ model: models.llm.llama3_2_1b() }); + const tts = useTextToSpeech(models.text_to_speech.kokoro.en_us.heart()); const processedLengthRef = useRef(0); const audioContextRef = useRef(null); diff --git a/apps/speech/screens/TextToSpeechScreen.tsx b/apps/speech/screens/TextToSpeechScreen.tsx index c9756b6aa6..198c40faf8 100644 --- a/apps/speech/screens/TextToSpeechScreen.tsx +++ b/apps/speech/screens/TextToSpeechScreen.tsx @@ -10,52 +10,35 @@ import { } from 'react-native'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; import { + models, useTextToSpeech, TextToSpeechModelConfig, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, - KOKORO_AMERICAN_ENGLISH_FEMALE_RIVER, - KOKORO_AMERICAN_ENGLISH_FEMALE_SARAH, - KOKORO_AMERICAN_ENGLISH_MALE_ADAM, - KOKORO_AMERICAN_ENGLISH_MALE_MICHAEL, - KOKORO_AMERICAN_ENGLISH_MALE_SANTA, - KOKORO_BRITISH_ENGLISH_FEMALE_EMMA, - KOKORO_BRITISH_ENGLISH_MALE_DANIEL, - KOKORO_FRENCH_FEMALE_SIWIS, - KOKORO_SPANISH_FEMALE_DORA, - KOKORO_SPANISH_MALE_ALEX, - KOKORO_ITALIAN_FEMALE_SARA, - KOKORO_ITALIAN_MALE_NICOLA, - KOKORO_PORTUGUESE_FEMALE_DORA, - KOKORO_PORTUGUESE_MALE_SANTA, - KOKORO_GERMAN_FEMALE_ANNA, - KOKORO_POLISH_MALE_MATEUSZ, - KOKORO_HINDI_FEMALE_ALPHA, - KOKORO_HINDI_MALE_OMEGA, - KOKORO_HINDI_MALE_PSI, } from 'react-native-executorch'; import { ModelPicker, ModelOption } from '../components/ModelPicker'; +const tts = models.text_to_speech.kokoro; + const VOICES: ModelOption[] = [ - { label: '🇺🇸 AF Heart', value: KOKORO_AMERICAN_ENGLISH_FEMALE_HEART }, - { label: '🇺🇸 AF River', value: KOKORO_AMERICAN_ENGLISH_FEMALE_RIVER }, - { label: '🇺🇸 AF Sarah', value: KOKORO_AMERICAN_ENGLISH_FEMALE_SARAH }, - { label: '🇺🇸 AM Adam', value: KOKORO_AMERICAN_ENGLISH_MALE_ADAM }, - { label: '🇺🇸 AM Michael', value: KOKORO_AMERICAN_ENGLISH_MALE_MICHAEL }, - { label: '🇺🇸 AM Santa', value: KOKORO_AMERICAN_ENGLISH_MALE_SANTA }, - { label: '🇬🇧 BF Emma', value: KOKORO_BRITISH_ENGLISH_FEMALE_EMMA }, - { label: '🇬🇧 BM Daniel', value: KOKORO_BRITISH_ENGLISH_MALE_DANIEL }, - { label: '🇫🇷 FF Siwis', value: KOKORO_FRENCH_FEMALE_SIWIS }, - { label: '🇪🇸 EF Dora', value: KOKORO_SPANISH_FEMALE_DORA }, - { label: '🇪🇸 EM Alex', value: KOKORO_SPANISH_MALE_ALEX }, - { label: '🇮🇹 IF Sara', value: KOKORO_ITALIAN_FEMALE_SARA }, - { label: '🇮🇹 IM Nicola', value: KOKORO_ITALIAN_MALE_NICOLA }, - { label: '🇵🇹 PF Dora', value: KOKORO_PORTUGUESE_FEMALE_DORA }, - { label: '🇵🇹 PM Santa', value: KOKORO_PORTUGUESE_MALE_SANTA }, - { label: '🇩🇪 DF Anna', value: KOKORO_GERMAN_FEMALE_ANNA }, - { label: '🇵🇱 PM Mateusz', value: KOKORO_POLISH_MALE_MATEUSZ }, - { label: '🇮🇳 HF Alpha', value: KOKORO_HINDI_FEMALE_ALPHA }, - { label: '🇮🇳 HM Omega', value: KOKORO_HINDI_MALE_OMEGA }, - { label: '🇮🇳 HM Psi', value: KOKORO_HINDI_MALE_PSI }, + { label: '🇺🇸 AF Heart', value: tts.en_us.heart() }, + { label: '🇺🇸 AF River', value: tts.en_us.river() }, + { label: '🇺🇸 AF Sarah', value: tts.en_us.sarah() }, + { label: '🇺🇸 AM Adam', value: tts.en_us.adam() }, + { label: '🇺🇸 AM Michael', value: tts.en_us.michael() }, + { label: '🇺🇸 AM Santa', value: tts.en_us.santa() }, + { label: '🇬🇧 BF Emma', value: tts.en_gb.emma() }, + { label: '🇬🇧 BM Daniel', value: tts.en_gb.daniel() }, + { label: '🇫🇷 FF Siwis', value: tts.fr.siwis() }, + { label: '🇪🇸 EF Dora', value: tts.es.dora() }, + { label: '🇪🇸 EM Alex', value: tts.es.alex() }, + { label: '🇮🇹 IF Sara', value: tts.it.sara() }, + { label: '🇮🇹 IM Nicola', value: tts.it.nicola() }, + { label: '🇵🇹 PF Dora', value: tts.pt.dora() }, + { label: '🇵🇹 PM Santa', value: tts.pt.santa() }, + { label: '🇩🇪 DF Anna', value: tts.de.anna() }, + { label: '🇵🇱 PM Mateusz', value: tts.pl.mateusz() }, + { label: '🇮🇳 HF Alpha', value: tts.hi.alpha() }, + { label: '🇮🇳 HM Omega', value: tts.hi.omega() }, + { label: '🇮🇳 HM Psi', value: tts.hi.psi() }, ]; import FontAwesome from '@expo/vector-icons/FontAwesome'; @@ -95,7 +78,7 @@ const createAudioBufferFromVector = ( export const TextToSpeechScreen = ({ onBack }: { onBack: () => void }) => { const [selectedSpeaker, setSelectedSpeaker] = - useState(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART); + useState(tts.en_us.heart()); const model = useTextToSpeech(selectedSpeaker); @@ -236,6 +219,7 @@ export const TextToSpeechScreen = ({ onBack }: { onBack: () => void }) => { Enter text to synthesize (CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED); + useState( + models.image_embedding.clip_vit_base_patch32_image() + ); - const textModel = useTextEmbeddings({ model: CLIP_VIT_BASE_PATCH32_TEXT }); + const textModel = useTextEmbeddings({ + model: models.text_embedding.clip_vit_base_patch32_text(), + }); const imageModel = useImageEmbeddings({ model: selectedImageModel }); const [imageUri, setImageUri] = useState(null); @@ -249,6 +259,7 @@ function ClipEmbeddingsScreen() { (ALL_MINILM_L6_V2); + const [selectedModel, setSelectedModel] = useState( + textEmbedding.all_minilm_l6_v2() + ); const model = useTextEmbeddings({ model: selectedModel }); const [error, setError] = useState(null); @@ -189,6 +190,7 @@ function TextEmbeddingsScreen() { Try Your Sentence - + + ```bash npm install react-native-executorch + # For Expo projects, you need to install expo resource fetcher + npm install react-native-executorch-expo-resource-fetcher + npm install expo-file-system expo-asset + # For bare React Native projects, you need to install bare resource fetcher + npm install react-native-executorch-bare-resource-fetcher + npm install @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader ``` - + ```bash - pnpm add react-native-executorch + pnpm install react-native-executorch + # For Expo projects, you need to install expo resource fetcher + pnpm install react-native-executorch-expo-resource-fetcher + pnpm install expo-file-system expo-asset + # For bare React Native projects, you need to install bare resource fetcher + pnpm install react-native-executorch-bare-resource-fetcher + pnpm install @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader ``` - + ```bash yarn add react-native-executorch - ``` - - - - -### 2. Install a resource fetcher - -Pick the adapter that matches your project. We recommend the Expo adapter when your app uses Expo; use the bare adapter for projects without Expo. - -#### Expo projects - - - - - ```bash - npm install react-native-executorch-expo-resource-fetcher expo-file-system expo-asset - ``` - - - - - ```bash - pnpm add react-native-executorch-expo-resource-fetcher expo-file-system expo-asset - ``` - - - - - ```bash - yarn add react-native-executorch-expo-resource-fetcher expo-file-system expo-asset - ``` - - - - -#### Bare React Native projects - - - - - ```bash - npm install react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader - ``` - - - - - ```bash - pnpm add react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader - ``` - - - - - ```bash - yarn add react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader + # For Expo projects, you need to install expo resource fetcher + yarn add react-native-executorch-expo-resource-fetcher + yarn add expo-file-system expo-asset + # For bare React Native projects, you need to install bare resource fetcher + yarn add react-native-executorch-bare-resource-fetcher + yarn add @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader ``` @@ -160,29 +120,9 @@ Because we are using ExecuTorch under the hood, you won't be able to build iOS a Running the app with the library: - - - - ```bash - npm run -- -d - ``` - - - - - ```bash - pnpm -d - ``` - - - - - ```bash - yarn -d - ``` - - - +```bash +yarn -d +``` ## Supporting new models in React Native ExecuTorch diff --git a/docs/docs/01-fundamentals/02-loading-models.md b/docs/docs/01-fundamentals/02-loading-models.md index 28df1d8d6d..ffadd5dc08 100644 --- a/docs/docs/01-fundamentals/02-loading-models.md +++ b/docs/docs/01-fundamentals/02-loading-models.md @@ -2,9 +2,6 @@ title: Loading Models --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - There are three different methods available for loading model files, depending on their size and location. ## Prerequisites @@ -13,29 +10,10 @@ In our library, you can use two different resource fetching mechanisms. One is i To use the Expo adapter, please add these libraries: - - - - ```bash - npm install react-native-executorch-expo-resource-fetcher expo-file-system expo-asset - ``` - - - - - ```bash - pnpm add react-native-executorch-expo-resource-fetcher expo-file-system expo-asset - ``` - - - - - ```bash - yarn add react-native-executorch-expo-resource-fetcher expo-file-system expo-asset - ``` - - - +```bash +yarn add react-native-executorch-expo-resource-fetcher +yarn add expo-file-system expo-asset +``` and then add the following code in your React Native app: @@ -50,29 +28,10 @@ initExecutorch({ If you cannot use Expo in your project, proceed with the following steps: - - - - ```bash - npm install react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader - ``` - - - - - ```bash - pnpm add react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader - ``` - - - - - ```bash - yarn add react-native-executorch-bare-resource-fetcher @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader - ``` - - - +```bash +yarn add react-native-executorch-bare-resource-fetcher +yarn add @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader +``` and @@ -128,7 +87,6 @@ Our library offers out-of-the-box support for multiple models. To make things ea The following code snippet demonstrates how to load model and tokenizer files using `useLLM` hook: ```typescript -import { useLLM, LFM2_5_1_2B_INSTRUCT } from 'react-native-executorch'; - -const llm = useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +import { models, useLLM } from 'react-native-executorch'; +const llm = useLLM({ model: models.llm.lfm2_5_1_2b_instruct() }); ``` diff --git a/docs/docs/03-hooks/01-natural-language-processing/useLLM.md b/docs/docs/03-hooks/01-natural-language-processing/useLLM.md index 7e6e4b17c2..7b1cb25158 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/useLLM.md +++ b/docs/docs/03-hooks/01-natural-language-processing/useLLM.md @@ -44,9 +44,8 @@ Lower-end devices might not be able to fit LLMs into memory. We recommend using In order to load a model into the app, you need to run the following code: ```typescript -import { useLLM, LFM2_5_1_2B_INSTRUCT } from 'react-native-executorch'; - -const llm = useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +import { models, useLLM } from 'react-native-executorch'; +const llm = useLLM({ model: models.llm.lfm2_5_1_2b_instruct() }); ```
@@ -92,7 +91,7 @@ You can use functions returned from this hooks in two manners: To perform chat completion you can use the [`generate`](../../06-api-reference/interfaces/LLMType.md#generate) function. The [`response`](../../06-api-reference/interfaces/LLMType.md#response) value is updated with each token as it's generated, and the function returns a promise that resolves to the complete response when generation finishes. ```tsx -const llm = useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +const llm = useLLM({ model: models.llm.lfm2_5_1_2b_instruct() }); const handleGenerate = async () => { const chat: Message[] = [ @@ -152,7 +151,7 @@ const TOOL_DEFINITIONS: LLMTool[] = [ }, ]; -const llm = useLLM({ model: HAMMER2_1_1_5B }); +const llm = useLLM({ model: models.llm.hammer2_1_1_5b() }); const handleGenerate = () => { const chat: Message[] = [ @@ -226,13 +225,12 @@ Model presets expose an optional [`generationConfig`](../../06-api-reference/int ```tsx import { useEffect } from 'react'; import { + models, MessageCountContextStrategy, DEFAULT_SYSTEM_PROMPT, ToolCall, useLLM, - LFM2_5_1_2B_INSTRUCT, } from 'react-native-executorch'; - const TOOL_DEFINITIONS: LLMTool[] = [ { name: 'get_weather', @@ -266,7 +264,7 @@ const executeTool: (call: ToolCall) => Promise = async ( } }; -const llm = useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +const llm = useLLM({ model: models.llm.lfm2_5_1_2b_instruct() }); const { configure } = llm; useEffect(() => { @@ -303,7 +301,7 @@ useEffect(() => { In order to send a message to the model, one can use the following code: ```tsx -const llm = useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +const llm = useLLM({ model: models.llm.lfm2_5_1_2b_instruct() }); const send = () => { const message = 'Hi, who are you?'; @@ -348,7 +346,7 @@ const TOOL_DEFINITIONS: LLMTool[] = [ }, ]; -const llm = useLLM({ model: HAMMER2_1_1_5B }); +const llm = useLLM({ model: models.llm.hammer2_1_1_5b() }); useEffect(() => { llm.configure({ @@ -426,7 +424,7 @@ const responseSchemaWithZod = z.object({ currency: z.optional(z.string().meta({ description: 'Currency of offer.' })), }); -const llm = useLLM({ model: QWEN3_4B_QUANTIZED }); +const llm = useLLM({ model: models.llm.qwen3_4b() }); useEffect(() => { const formattingInstructions = getStructuredOutputPrompt(responseSchema); @@ -501,9 +499,8 @@ Some models support multimodal input — text and images together. To use them, ### Loading a VLM ```tsx -import { useLLM, LFM2_5_VL_1_6B_QUANTIZED } from 'react-native-executorch'; - -const llm = useLLM({ model: LFM2_5_VL_1_6B_QUANTIZED }); +import { models, useLLM } from 'react-native-executorch'; +const llm = useLLM({ model: models.llm.lfm2_5_vl_1_6b() }); ``` The `capabilities` field is already set on the model constant. You can also construct the model object explicitly: @@ -524,7 +521,7 @@ Passing `capabilities` unlocks the typed `media` argument on `sendMessage`. ### Sending a message with an image ```tsx -const llm = useLLM({ model: LFM2_5_VL_1_6B_QUANTIZED }); +const llm = useLLM({ model: models.llm.lfm2_5_vl_1_6b() }); const send = () => { llm.sendMessage('What is in this image?', { @@ -547,7 +544,7 @@ The `imagePath` should be a local file path on the device. You can also use `generate` directly by setting `mediaPath` on user messages: ```tsx -const llm = useLLM({ model: LFM2_5_VL_1_6B_QUANTIZED }); +const llm = useLLM({ model: models.llm.lfm2_5_vl_1_6b() }); const handleGenerate = async () => { const chat: Message[] = [ @@ -565,14 +562,14 @@ const handleGenerate = async () => { ## Available models -| Model Family | Sizes | Quantized | Capabilities | -| ------------------------------------------------------------------------------------------------------------------ | :-----------------: | :-------: | :----------: | -| [Hammer 2.1](https://huggingface.co/software-mansion/react-native-executorch-hammer-2.1) | 0.5B, 1.5B, 3B | ✅ | - | -| [Qwen 2.5](https://huggingface.co/software-mansion/react-native-executorch-qwen-2.5) | 0.5B, 1.5B, 3B | ✅ | - | -| [Qwen 3](https://huggingface.co/software-mansion/react-native-executorch-qwen-3) | 0.6B, 1.7B, 4B | ✅ | - | -| [Phi 4 Mini](https://huggingface.co/software-mansion/react-native-executorch-phi-4-mini) | 4B | ✅ | - | -| [SmolLM 2](https://huggingface.co/software-mansion/react-native-executorch-smolLm-2) | 135M, 360M, 1.7B | ✅ | - | -| [LLaMA 3.2](https://huggingface.co/software-mansion/react-native-executorch-llama-3.2) | 1B, 3B | ✅ | - | -| [LFM2.5](https://huggingface.co/software-mansion/react-native-executorch-lfm-2.5) | 350M, 1.2B, 1.6B-VL | ✅ | - | -| [LFM2.5-VL-450M](https://huggingface.co/software-mansion/react-native-executorch-lfm-2.5/tree/main/lfm2.5-VL-450M) | 450M | ✅ | vision | -| [LFM2.5-VL-1.6B](https://huggingface.co/software-mansion/react-native-executorch-lfm-2.5/tree/main/lfm2.5-VL-1.6B) | 1.6B | ✅ | vision | +| Model Family | Sizes | Quantized | Capabilities | +| ------------------------------------------------------------------------------------------ | :--------------------------: | :-------: | :----------: | +| [Hammer 2.1](https://huggingface.co/software-mansion/react-native-executorch-hammer-2.1) | 0.5B, 1.5B, 3B | ✅ | - | +| [Qwen 2.5](https://huggingface.co/software-mansion/react-native-executorch-qwen-2.5) | 0.5B, 1.5B, 3B | ✅ | - | +| [Qwen 3](https://huggingface.co/software-mansion/react-native-executorch-qwen-3) | 0.6B, 1.7B, 4B | ✅ | - | +| [Qwen 3.5](https://huggingface.co/software-mansion/react-native-executorch-qwen-3.5) | 0.8B, 2B | ✅ | - | +| [Phi 4 Mini](https://huggingface.co/software-mansion/react-native-executorch-phi-4-mini) | 4B | ✅ | - | +| [SmolLM 2](https://huggingface.co/software-mansion/react-native-executorch-smolLm-2) | 135M, 360M, 1.7B | ✅ | - | +| [LLaMA 3.2](https://huggingface.co/software-mansion/react-native-executorch-llama-3.2) | 1B, 3B | ✅ | - | +| [Bielik v3.0](https://huggingface.co/software-mansion/react-native-executorch-bielik-v3.0) | 1.5B | ✅ | - | +| [LFM2.5](https://huggingface.co/software-mansion/react-native-executorch-lfm-2.5) | 350M, 450M-VL, 1.2B, 1.6B-VL | ✅ | vision | diff --git a/docs/docs/03-hooks/01-natural-language-processing/usePrivacyFilter.md b/docs/docs/03-hooks/01-natural-language-processing/usePrivacyFilter.md index c0155dfbbf..97495f510b 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/usePrivacyFilter.md +++ b/docs/docs/03-hooks/01-natural-language-processing/usePrivacyFilter.md @@ -32,12 +32,8 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { - usePrivacyFilter, - PRIVACY_FILTER_OPENAI, -} from 'react-native-executorch'; - -const model = usePrivacyFilter({ model: PRIVACY_FILTER_OPENAI }); +import { models, usePrivacyFilter } from 'react-native-executorch'; +const model = usePrivacyFilter({ model: models.privacy_filter.openai() }); try { const entities = await model.generate( @@ -89,14 +85,9 @@ Both built-in models ship with neutral, validity-only Viterbi decoding by defaul ```tsx import React, { useState } from 'react'; import { Button, Text, View, TextInput, ScrollView } from 'react-native'; -import { - usePrivacyFilter, - PRIVACY_FILTER_OPENAI, - PiiEntity, -} from 'react-native-executorch'; - +import { models, usePrivacyFilter, PiiEntity } from 'react-native-executorch'; export default function App() { - const model = usePrivacyFilter({ model: PRIVACY_FILTER_OPENAI }); + const model = usePrivacyFilter({ model: models.privacy_filter.openai() }); const [text, setText] = useState( 'My name is Sarah Chen and you can reach me at sarah.chen@example.com.' ); diff --git a/docs/docs/03-hooks/01-natural-language-processing/useSpeechToText.md b/docs/docs/03-hooks/01-natural-language-processing/useSpeechToText.md index 089b844eb0..39d0566af5 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/useSpeechToText.md +++ b/docs/docs/03-hooks/01-natural-language-processing/useSpeechToText.md @@ -33,12 +33,12 @@ It is recommended to use models provided by us, which are available at our [Hugg You can obtain waveform from audio in any way most suitable to you, however in the snippet below we utilize [`react-native-audio-api`](https://docs.swmansion.com/react-native-audio-api/) library to process a `.mp3` file. ```typescript -import { useSpeechToText, WHISPER_TINY_EN } from 'react-native-executorch'; +import { models, useSpeechToText } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; import * as FileSystem from 'expo-file-system'; const model = useSpeechToText({ - model: WHISPER_TINY_EN, + model: models.speech_to_text.whisper_tiny_en(), }); const { uri } = await FileSystem.downloadAsync( @@ -92,10 +92,9 @@ Before running the model's [`transcribe`](../../06-api-reference/interfaces/Spee If you want to transcribe speech in languages other than English, use the multilingual version of Whisper. To generate the output in your desired language, pass the [`language`](../../06-api-reference/interfaces/DecodingOptions.md#language) option to the [`transcribe`](../../06-api-reference/interfaces/SpeechToTextType.md#transcribe) method. ```typescript -import { useSpeechToText, WHISPER_TINY } from 'react-native-executorch'; - +import { models, useSpeechToText } from 'react-native-executorch'; const model = useSpeechToText({ - model: WHISPER_TINY, + model: models.speech_to_text.whisper_tiny(), }); const transcription = await model.transcribe(spanishAudio, { language: 'es' }); @@ -143,8 +142,8 @@ const transcription = await model.transcribe(audioBuffer, { verbose: true }); import React, { useState } from 'react'; import { Button, Text, View } from 'react-native'; import { + models, useSpeechToText, - WHISPER_TINY_EN, TranscriptionResult, } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; @@ -152,7 +151,7 @@ import * as FileSystem from 'expo-file-system'; function App() { const model = useSpeechToText({ - model: WHISPER_TINY_EN, + model: models.speech_to_text.whisper_tiny_en(), }); const [transcription, setTranscription] = useState(null); @@ -220,12 +219,12 @@ function App() { ```tsx import React, { useEffect, useState, useRef } from 'react'; import { Text, Button, View, SafeAreaView } from 'react-native'; -import { useSpeechToText, WHISPER_TINY_EN } from 'react-native-executorch'; +import { models, useSpeechToText } from 'react-native-executorch'; import { AudioManager, AudioRecorder } from 'react-native-audio-api'; export default function App() { const model = useSpeechToText({ - model: WHISPER_TINY_EN, + model: models.speech_to_text.whisper_tiny_en(), }); const [transcribedText, setTranscribedText] = useState(''); diff --git a/docs/docs/03-hooks/01-natural-language-processing/useTextEmbeddings.md b/docs/docs/03-hooks/01-natural-language-processing/useTextEmbeddings.md index 09240d1e75..b9ba8c41b9 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/useTextEmbeddings.md +++ b/docs/docs/03-hooks/01-natural-language-processing/useTextEmbeddings.md @@ -29,9 +29,10 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { useTextEmbeddings, ALL_MINILM_L6_V2 } from 'react-native-executorch'; - -const model = useTextEmbeddings({ model: ALL_MINILM_L6_V2 }); +import { models, useTextEmbeddings } from 'react-native-executorch'; +const model = useTextEmbeddings({ + model: models.text_embedding.all_minilm_l6_v2(), +}); try { const embedding = await model.forward('Hello World!'); @@ -64,8 +65,7 @@ To run the model, you can use the [`forward`](../../06-api-reference/interfaces/ ## Example ```typescript -import { useTextEmbeddings, ALL_MINILM_L6_V2 } from 'react-native-executorch'; - +import { models, useTextEmbeddings } from 'react-native-executorch'; const dotProduct = (a: number[], b: number[]) => a.reduce((sum, val, i) => sum + val * b[i], 0); @@ -77,7 +77,9 @@ const cosineSimilarity = (a: number[], b: number[]) => { }; function App() { - const model = useTextEmbeddings({ model: ALL_MINILM_L6_V2 }); + const model = useTextEmbeddings({ + model: models.text_embedding.all_minilm_l6_v2(), + }); // ... diff --git a/docs/docs/03-hooks/01-natural-language-processing/useTextToSpeech.md b/docs/docs/03-hooks/01-natural-language-processing/useTextToSpeech.md index e7b14defd0..fe0dd3b2ee 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/useTextToSpeech.md +++ b/docs/docs/03-hooks/01-natural-language-processing/useTextToSpeech.md @@ -33,13 +33,10 @@ It is recommended to use models provided by us, which are available at our [Hugg You can play the generated waveform in any way most suitable to you; however, in the snippet below we utilize the react-native-audio-api library to play synthesized speech. ```typescript -import { - useTextToSpeech, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; +import { models, useTextToSpeech } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; -const model = useTextToSpeech(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART); +const model = useTextToSpeech(models.text_to_speech.kokoro.en_us.heart()); const audioContext = new AudioContext({ sampleRate: 24000 }); @@ -114,14 +111,11 @@ Since `forward` and `stream` process the input, they might take a significant am ```tsx import React from 'react'; import { Button, View } from 'react-native'; -import { - useTextToSpeech, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; +import { models, useTextToSpeech } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; export default function App() { - const tts = useTextToSpeech(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART); + const tts = useTextToSpeech(models.text_to_speech.kokoro.en_us.heart()); const generateAudio = async () => { const audioData = await tts.forward({ @@ -152,14 +146,11 @@ export default function App() { ```tsx import React, { useRef } from 'react'; import { Button, View } from 'react-native'; -import { - useTextToSpeech, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; +import { models, useTextToSpeech } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; export default function App() { - const tts = useTextToSpeech(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART); + const tts = useTextToSpeech(models.text_to_speech.kokoro.en_us.heart()); const contextRef = useRef(new AudioContext({ sampleRate: 24000 })); @@ -199,13 +190,9 @@ If you already have a phoneme string obtained from an external source (e.g. the ```tsx import React from 'react'; import { Button, View } from 'react-native'; -import { - useTextToSpeech, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; - +import { models, useTextToSpeech } from 'react-native-executorch'; export default function App() { - const tts = useTextToSpeech(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART); + const tts = useTextToSpeech(models.text_to_speech.kokoro.en_us.heart()); const synthesizePhonemes = async () => { // Example phonemes for "Hello" diff --git a/docs/docs/03-hooks/01-natural-language-processing/useTokenizer.md b/docs/docs/03-hooks/01-natural-language-processing/useTokenizer.md index aef466ade4..ba3516638e 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/useTokenizer.md +++ b/docs/docs/03-hooks/01-natural-language-processing/useTokenizer.md @@ -29,9 +29,11 @@ We are using [Hugging Face Tokenizers](https://huggingface.co/docs/tokenizers/in ## High Level Overview ```typescript -import { useTokenizer, ALL_MINILM_L6_V2 } from 'react-native-executorch'; +import { models, useTokenizer } from 'react-native-executorch'; -const tokenizer = useTokenizer({ tokenizer: ALL_MINILM_L6_V2 }); +const tokenizer = useTokenizer({ + tokenizer: models.text_embedding.all_minilm_l6_v2(), +}); const text = 'Hello, world!'; @@ -52,7 +54,7 @@ try { `useTokenizer` takes [`TokenizerProps`](../../06-api-reference/interfaces/TokenizerProps.md) that consists of: -- `tokenizer` of type [`TokenizerProps`](../../06-api-reference/interfaces/TokenizerProps.md) containing [`tokenizerSource`](../../06-api-reference/interfaces/TokenizerProps.md#tokenizersource). +- `tokenizer` — an object containing [`tokenizerSource`](../../06-api-reference/interfaces/TokenizerProps.md#tokenizersource). - An optional flag [`preventLoad`](../../06-api-reference/interfaces/TokenizerProps.md#preventload) which prevents auto-loading of the model. You need more details? Check the following resources: @@ -67,10 +69,12 @@ You need more details? Check the following resources: ## Example ```typescript -import { useTokenizer, ALL_MINILM_L6_V2 } from 'react-native-executorch'; +import { models, useTokenizer } from 'react-native-executorch'; function App() { - const tokenizer = useTokenizer({ tokenizer: ALL_MINILM_L6_V2 }); + const tokenizer = useTokenizer({ + tokenizer: models.text_embedding.all_minilm_l6_v2(), + }); // ... diff --git a/docs/docs/03-hooks/01-natural-language-processing/useVAD.md b/docs/docs/03-hooks/01-natural-language-processing/useVAD.md index 81207dec07..01cf8cd4e3 100644 --- a/docs/docs/03-hooks/01-natural-language-processing/useVAD.md +++ b/docs/docs/03-hooks/01-natural-language-processing/useVAD.md @@ -18,12 +18,12 @@ It is recommended to use models provided by us, which are available at our [Hugg You can obtain waveform from audio in any way most suitable to you, however in the snippet below we utilize [`react-native-audio-api`](https://docs.swmansion.com/react-native-audio-api/) library to process a `.mp3` file. ```typescript -import { useVAD, FSMN_VAD } from 'react-native-executorch'; +import { models, useVAD } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; import * as FileSystem from 'expo-file-system'; const model = useVAD({ - model: FSMN_VAD, + model: models.vad.fsmn_vad(), }); const { uri } = await FileSystem.downloadAsync( @@ -76,13 +76,13 @@ Timestamps in returned speech segments, correspond to indices of input array (wa ```tsx import React from 'react'; import { Button, Text, SafeAreaView } from 'react-native'; -import { useVAD, FSMN_VAD } from 'react-native-executorch'; +import { models, useVAD } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; import * as FileSystem from 'expo-file-system'; export default function App() { const model = useVAD({ - model: FSMN_VAD, + model: models.vad.fsmn_vad(), }); const audioURL = 'https://some-audio-url.com/file.mp3'; diff --git a/docs/docs/03-hooks/02-computer-vision/useClassification.md b/docs/docs/03-hooks/02-computer-vision/useClassification.md index 53ec0901bd..7db709dd9a 100644 --- a/docs/docs/03-hooks/02-computer-vision/useClassification.md +++ b/docs/docs/03-hooks/02-computer-vision/useClassification.md @@ -20,9 +20,10 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { useClassification, EFFICIENTNET_V2_S } from 'react-native-executorch'; - -const model = useClassification({ model: EFFICIENTNET_V2_S }); +import { models, useClassification } from 'react-native-executorch'; +const model = useClassification({ + model: models.classification.efficientnet_v2_s(), +}); const imageUri = 'file::///Users/.../cute_puppy.png'; @@ -75,10 +76,11 @@ See the full guide: [VisionCamera Integration](./visioncamera-integration.md). ## Example ```typescript -import { useClassification, EFFICIENTNET_V2_S } from 'react-native-executorch'; - +import { models, useClassification } from 'react-native-executorch'; function App() { - const model = useClassification({ model: EFFICIENTNET_V2_S }); + const model = useClassification({ + model: models.classification.efficientnet_v2_s(), + }); // ... const imageUri = 'file:///Users/.../cute_puppy.png'; diff --git a/docs/docs/03-hooks/02-computer-vision/useImageEmbeddings.md b/docs/docs/03-hooks/02-computer-vision/useImageEmbeddings.md index df2442c6bd..13947a96f2 100644 --- a/docs/docs/03-hooks/02-computer-vision/useImageEmbeddings.md +++ b/docs/docs/03-hooks/02-computer-vision/useImageEmbeddings.md @@ -30,12 +30,10 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { - useImageEmbeddings, - CLIP_VIT_BASE_PATCH32_IMAGE, -} from 'react-native-executorch'; - -const model = useImageEmbeddings({ model: CLIP_VIT_BASE_PATCH32_IMAGE }); +import { models, useImageEmbeddings } from 'react-native-executorch'; +const model = useImageEmbeddings({ + model: models.image_embedding.clip_vit_base_patch32_image(), +}); try { const imageEmbedding = await model.forward('https://url-to-image.jpg'); diff --git a/docs/docs/03-hooks/02-computer-vision/useInstanceSegmentation.md b/docs/docs/03-hooks/02-computer-vision/useInstanceSegmentation.md index 129316cfee..d1728a3cf8 100644 --- a/docs/docs/03-hooks/02-computer-vision/useInstanceSegmentation.md +++ b/docs/docs/03-hooks/02-computer-vision/useInstanceSegmentation.md @@ -15,10 +15,9 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { useInstanceSegmentation, YOLO26N_SEG } from 'react-native-executorch'; - +import { models, useInstanceSegmentation } from 'react-native-executorch'; const model = useInstanceSegmentation({ - model: YOLO26N_SEG, + model: models.instance_segmentation.yolo26n_seg(), }); const imageUri = 'file:///Users/.../photo.jpg'; @@ -81,11 +80,10 @@ To run the model, use the [`forward`](../../06-api-reference/interfaces/Instance ## Example ```typescript -import { useInstanceSegmentation, YOLO26N_SEG } from 'react-native-executorch'; - +import { models, useInstanceSegmentation } from 'react-native-executorch'; function App() { const model = useInstanceSegmentation({ - model: YOLO26N_SEG, + model: models.instance_segmentation.yolo26n_seg(), }); const handleSegment = async () => { @@ -150,14 +148,15 @@ Instance segmentation models return a list of segmented instances. After `forwar ```typescript import { + models, useInstanceSegmentation, selectByPoint, selectByBox, selectByText, - FASTSAM_X, } from 'react-native-executorch'; - -const model = useInstanceSegmentation({ model: FASTSAM_X }); +const model = useInstanceSegmentation({ + model: models.object_detection.fastsam_x(), +}); try { const instances = await model.forward(imageUri); @@ -179,12 +178,6 @@ try { } ``` -For detailed API Reference for `selectByPoint`, `selectByBox`, and `selectByText` see their respective documentation pages: - -- [`selectByPoint` API Reference](../../06-api-reference/functions/selectByPoint.md) -- [`selectByBox` API Reference](../../06-api-reference/functions/selectByBox.md) -- [`selectByText` API Reference](../../06-api-reference/functions/selectByText.md) - :::tip Use FastSAM-S for faster performance on simple images with non-overlapping instances and FastSAM-X for better accuracy on complex scenes with many diff --git a/docs/docs/03-hooks/02-computer-vision/useOCR.md b/docs/docs/03-hooks/02-computer-vision/useOCR.md index 8f015e77a5..eaf9798fe5 100644 --- a/docs/docs/03-hooks/02-computer-vision/useOCR.md +++ b/docs/docs/03-hooks/02-computer-vision/useOCR.md @@ -16,10 +16,9 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```tsx -import { useOCR, OCR_ENGLISH } from 'react-native-executorch'; - +import { models, useOCR } from 'react-native-executorch'; function App() { - const model = useOCR({ model: OCR_ENGLISH }); + const model = useOCR({ model: models.ocr.craft({ language: 'en' }) }); // ... for (const ocrDetection of await model.forward('https://url-to-image.jpg')) { @@ -81,10 +80,9 @@ The `text` property contains the text recognized within detected text region. Th ## Example ```tsx -import { useOCR, OCR_ENGLISH } from 'react-native-executorch'; - +import { models, useOCR } from 'react-native-executorch'; function App() { - const model = useOCR({ model: OCR_ENGLISH }); + const model = useOCR({ model: models.ocr.craft({ language: 'en' }) }); const runModel = async () => { const ocrDetections = await model.forward('https://url-to-image.jpg'); diff --git a/docs/docs/03-hooks/02-computer-vision/useObjectDetection.md b/docs/docs/03-hooks/02-computer-vision/useObjectDetection.md index b5e0dfaf5e..317c00c3b7 100644 --- a/docs/docs/03-hooks/02-computer-vision/useObjectDetection.md +++ b/docs/docs/03-hooks/02-computer-vision/useObjectDetection.md @@ -16,13 +16,9 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { - useObjectDetection, - SSDLITE_320_MOBILENET_V3_LARGE, -} from 'react-native-executorch'; - +import { models, useObjectDetection } from 'react-native-executorch'; const model = useObjectDetection({ - model: SSDLITE_320_MOBILENET_V3_LARGE, + model: models.object_detection.ssdlite_320_mobilenet_v3_large(), }); const imageUri = 'file:///Users/.../photo.jpg'; @@ -84,11 +80,10 @@ To run the model, use the [`forward`](../../06-api-reference/interfaces/ObjectDe ## Example ```typescript -import { useObjectDetection, YOLO26N } from 'react-native-executorch'; - +import { models, useObjectDetection } from 'react-native-executorch'; function App() { const model = useObjectDetection({ - model: YOLO26N, + model: models.object_detection.yolo26n(), }); const handleDetect = async () => { diff --git a/docs/docs/03-hooks/02-computer-vision/usePoseEstimation.md b/docs/docs/03-hooks/02-computer-vision/usePoseEstimation.md index e31b928074..465a0ab6a6 100644 --- a/docs/docs/03-hooks/02-computer-vision/usePoseEstimation.md +++ b/docs/docs/03-hooks/02-computer-vision/usePoseEstimation.md @@ -16,10 +16,9 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```typescript -import { usePoseEstimation, YOLO26N_POSE } from 'react-native-executorch'; - +import { models, usePoseEstimation } from 'react-native-executorch'; const model = usePoseEstimation({ - model: YOLO26N_POSE, + model: models.pose_estimation.yolo26n(), }); const imageUri = 'file:///Users/.../photo.jpg'; @@ -94,11 +93,10 @@ The keypoint names available on each person are determined by the model's keypoi ## Example ```typescript -import { usePoseEstimation, YOLO26N_POSE } from 'react-native-executorch'; - +import { models, usePoseEstimation } from 'react-native-executorch'; function App() { const model = usePoseEstimation({ - model: YOLO26N_POSE, + model: models.pose_estimation.yolo26n(), }); const handleDetect = async () => { diff --git a/docs/docs/03-hooks/02-computer-vision/useSemanticSegmentation.md b/docs/docs/03-hooks/02-computer-vision/useSemanticSegmentation.md index dfc95317db..dd059cc4b6 100644 --- a/docs/docs/03-hooks/02-computer-vision/useSemanticSegmentation.md +++ b/docs/docs/03-hooks/02-computer-vision/useSemanticSegmentation.md @@ -16,13 +16,9 @@ It is recommended to use models provided by us which are available at our [Huggi ## High Level Overview ```typescript -import { - useSemanticSegmentation, - DEEPLAB_V3_RESNET50, -} from 'react-native-executorch'; - +import { models, useSemanticSegmentation } from 'react-native-executorch'; const model = useSemanticSegmentation({ - model: DEEPLAB_V3_RESNET50, + model: models.semantic_segmentation.deeplab_v3_resnet50(), }); const imageUri = 'file::///Users/.../cute_cat.png'; @@ -85,14 +81,13 @@ The return type is fully typed — TypeScript narrows it based on the labels you ```typescript import { + models, useSemanticSegmentation, - DEEPLAB_V3_RESNET50, DeeplabLabel, } from 'react-native-executorch'; - function App() { const model = useSemanticSegmentation({ - model: DEEPLAB_V3_RESNET50, + model: models.semantic_segmentation.deeplab_v3_resnet50(), }); const handleSegment = async () => { diff --git a/docs/docs/03-hooks/02-computer-vision/useStyleTransfer.md b/docs/docs/03-hooks/02-computer-vision/useStyleTransfer.md index 800a1cdc4f..f76693fdc4 100644 --- a/docs/docs/03-hooks/02-computer-vision/useStyleTransfer.md +++ b/docs/docs/03-hooks/02-computer-vision/useStyleTransfer.md @@ -16,12 +16,8 @@ It is recommended to use models provided by us which are available at our [Huggi ## High Level Overview ```typescript -import { - useStyleTransfer, - STYLE_TRANSFER_CANDY, -} from 'react-native-executorch'; - -const model = useStyleTransfer({ model: STYLE_TRANSFER_CANDY }); +import { models, useStyleTransfer } from 'react-native-executorch'; +const model = useStyleTransfer({ model: models.style_transfer.candy() }); const imageUri = 'file:///Users/.../cute_cat.png'; @@ -68,13 +64,9 @@ When `outputType` is `'url'`, the generated image is stored in your application' ## Example ```typescript -import { - useStyleTransfer, - STYLE_TRANSFER_CANDY, -} from 'react-native-executorch'; - +import { models, useStyleTransfer } from 'react-native-executorch'; function App() { - const model = useStyleTransfer({ model: STYLE_TRANSFER_CANDY }); + const model = useStyleTransfer({ model: models.style_transfer.candy() }); // Returns a file URI — easy to pass to const runWithUrl = async (imageUri: string) => { diff --git a/docs/docs/03-hooks/02-computer-vision/useTextToImage.md b/docs/docs/03-hooks/02-computer-vision/useTextToImage.md index 1968c46088..3ca063bf60 100644 --- a/docs/docs/03-hooks/02-computer-vision/useTextToImage.md +++ b/docs/docs/03-hooks/02-computer-vision/useTextToImage.md @@ -18,9 +18,10 @@ It is recommended to use models provided by us which are available at our [Huggi ## High Level Overview ```typescript -import { useTextToImage, BK_SDM_TINY_VPRED_256 } from 'react-native-executorch'; - -const model = useTextToImage({ model: BK_SDM_TINY_VPRED_256 }); +import { models, useTextToImage } from 'react-native-executorch'; +const model = useTextToImage({ + model: models.image_generation.bk_sdm_tiny_vpred_256(), +}); const input = 'a castle'; @@ -62,10 +63,11 @@ Larger imageSize values require significantly more memory to run the model. ## Example ```tsx -import { useTextToImage, BK_SDM_TINY_VPRED_256 } from 'react-native-executorch'; - +import { models, useTextToImage } from 'react-native-executorch'; function App() { - const model = useTextToImage({ model: BK_SDM_TINY_VPRED_256 }); + const model = useTextToImage({ + model: models.image_generation.bk_sdm_tiny_vpred_256(), + }); //... const input = 'a medieval castle by the sea shore'; diff --git a/docs/docs/03-hooks/02-computer-vision/useVerticalOCR.md b/docs/docs/03-hooks/02-computer-vision/useVerticalOCR.md index ff27b55e17..82c983d900 100644 --- a/docs/docs/03-hooks/02-computer-vision/useVerticalOCR.md +++ b/docs/docs/03-hooks/02-computer-vision/useVerticalOCR.md @@ -20,11 +20,10 @@ It is recommended to use models provided by us, which are available at our [Hugg ## High Level Overview ```tsx -import { useVerticalOCR, OCR_ENGLISH } from 'react-native-executorch'; - +import { models, useVerticalOCR } from 'react-native-executorch'; function App() { const model = useVerticalOCR({ - model: OCR_ENGLISH, + model: models.ocr.craft({ language: 'en' }), independentCharacters: true, }); @@ -89,11 +88,10 @@ The `text` property contains the text recognized within detected text region. Th ## Example ```tsx -import { useVerticalOCR, OCR_ENGLISH } from 'react-native-executorch'; - +import { models, useVerticalOCR } from 'react-native-executorch'; function App() { const model = useVerticalOCR({ - model: OCR_ENGLISH, + model: models.ocr.craft({ language: 'en' }), independentCharacters: true, }); diff --git a/docs/docs/03-hooks/02-computer-vision/visioncamera-integration.md b/docs/docs/03-hooks/02-computer-vision/visioncamera-integration.md index b96b7f5274..b421047552 100644 --- a/docs/docs/03-hooks/02-computer-vision/visioncamera-integration.md +++ b/docs/docs/03-hooks/02-computer-vision/visioncamera-integration.md @@ -78,17 +78,14 @@ import { useFrameOutput, } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; -import { - Detection, - useObjectDetection, - SSDLITE_320_MOBILENET_V3_LARGE, -} from 'react-native-executorch'; - +import { models, Detection, useObjectDetection } from 'react-native-executorch'; export default function App() { const { hasPermission, requestPermission } = useCameraPermission(); const devices = useCameraDevices(); const device = devices.find((d) => d.position === 'back'); - const model = useObjectDetection({ model: SSDLITE_320_MOBILENET_V3_LARGE }); + const model = useObjectDetection({ + model: models.object_detection.ssdlite_320_mobilenet_v3_large(), + }); const [detections, setDetections] = useState([]); const detRof = model.runOnFrame; @@ -211,11 +208,7 @@ import { useFrameOutput, } from 'react-native-vision-camera'; import { scheduleOnRN } from 'react-native-worklets'; -import { - ClassificationModule, - EFFICIENTNET_V2_S, -} from 'react-native-executorch'; - +import { models, ClassificationModule } from 'react-native-executorch'; export default function App() { const { hasPermission, requestPermission } = useCameraPermission(); const device = useCameraDevice('back'); @@ -227,7 +220,9 @@ export default function App() { }, [hasPermission, requestPermission]); useEffect(() => { - ClassificationModule.fromModelName(EFFICIENTNET_V2_S).then((module) => { + ClassificationModule.fromModelName( + models.classification.efficientnet_v2_s() + ).then((module) => { // () => module.runOnFrame is required — passing module.runOnFrame directly // would cause React to call it as a state initializer function setRunOnFrame(() => module.runOnFrame); diff --git a/docs/docs/03-hooks/03-executorch-bindings/useExecutorchModule.md b/docs/docs/03-hooks/03-executorch-bindings/useExecutorchModule.md index f51733307b..7429b4b60e 100644 --- a/docs/docs/03-hooks/03-executorch-bindings/useExecutorchModule.md +++ b/docs/docs/03-hooks/03-executorch-bindings/useExecutorchModule.md @@ -18,7 +18,6 @@ You can initialize the ExecuTorch module in your JavaScript application using th ```typescript import { useExecutorchModule } from 'react-native-executorch'; - const executorchModule = useExecutorchModule({ modelSource: require('../assets/models/model.pte'), }); @@ -64,14 +63,13 @@ First, import the necessary functions from the `react-native-executorch` package ```typescript import { + models, useExecutorchModule, - STYLE_TRANSFER_CANDY, ScalarType, } from 'react-native-executorch'; - // Initialize the executorch module with the predefined style transfer model. const executorchModule = useExecutorchModule({ - modelSource: STYLE_TRANSFER_CANDY, + modelSource: models.style_transfer.candy(), }); ``` diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/LLMModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/LLMModule.md index c1cf24a9fc..967625160c 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/LLMModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/LLMModule.md @@ -13,11 +13,10 @@ TypeScript API implementation of the [useLLM](../../03-hooks/01-natural-language ## High Level Overview ```typescript -import { LLMModule, LFM2_5_1_2B_INSTRUCT } from 'react-native-executorch'; - +import { models, LLMModule } from 'react-native-executorch'; // Creating an instance and loading the model const llm = await LLMModule.fromModelName( - LFM2_5_1_2B_INSTRUCT, + models.llm.lfm2_5_1_2b_instruct(), (progress) => console.log(progress), (token) => console.log(token), (messages) => console.log(messages) @@ -44,7 +43,7 @@ Use the static [`fromModelName`](../../06-api-reference/classes/LLMModule.md#fro ```typescript const llm = await LLMModule.fromModelName( - LFM2_5_1_2B_INSTRUCT, // model config constant + models.llm.lfm2_5_1_2b_instruct(), // model config constant onDownloadProgress, // optional, progress 0–1 tokenCallback, // optional, called on every token messageHistoryCallback // optional, called when generation finishes @@ -122,10 +121,9 @@ Model presets expose an optional `generationConfig` that `LLMModule.fromModelNam Some models support multimodal input — text and images together. To use them, pass `capabilities` in the model object when calling [`fromModelName`](../../06-api-reference/classes/LLMModule.md#frommodelname): ```typescript -import { LLMModule, LFM2_5_VL_1_6B_QUANTIZED } from 'react-native-executorch'; - +import { models, LLMModule } from 'react-native-executorch'; const llm = await LLMModule.fromModelName( - LFM2_5_VL_1_6B_QUANTIZED, + models.llm.lfm2_5_vl_1_6b(), undefined, (token) => console.log(token) ); @@ -171,7 +169,6 @@ Use [`fromCustomModel`](../../06-api-reference/classes/LLMModule.md#fromcustommo ```typescript import { LLMModule } from 'react-native-executorch'; - const llm = await LLMModule.fromCustomModel( 'https://example.com/model.pte', 'https://example.com/tokenizer.json', diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/PrivacyFilterModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/PrivacyFilterModule.md index a862bce3bb..2df0f7dff0 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/PrivacyFilterModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/PrivacyFilterModule.md @@ -12,13 +12,9 @@ TypeScript API implementation of the [usePrivacyFilter](../../03-hooks/01-natura ## High Level Overview ```typescript -import { - PrivacyFilterModule, - PRIVACY_FILTER_OPENAI, -} from 'react-native-executorch'; - +import { models, PrivacyFilterModule } from 'react-native-executorch'; const model = await PrivacyFilterModule.fromModelName( - PRIVACY_FILTER_OPENAI, + models.privacy_filter.openai(), (progress) => console.log(progress) ); diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/SpeechToTextModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/SpeechToTextModule.md index d4d8897e7c..de5d763db9 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/SpeechToTextModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/SpeechToTextModule.md @@ -12,10 +12,9 @@ TypeScript API implementation of the [useSpeechToText](../../03-hooks/01-natural ## High Level Overview ```typescript -import { SpeechToTextModule, WHISPER_TINY_EN } from 'react-native-executorch'; - +import { models, SpeechToTextModule } from 'react-native-executorch'; const model = await SpeechToTextModule.fromModelName( - WHISPER_TINY_EN, + models.speech_to_text.whisper_tiny_en(), (progress) => { console.log(progress); } @@ -65,10 +64,9 @@ To run the model, you can use the [`transcribe`](../../06-api-reference/classes/ If you aim to obtain a transcription in other languages than English, use the multilingual version of whisper. To obtain the output text in your desired language, pass the [`DecodingOptions`](../../06-api-reference/interfaces/DecodingOptions.md) object with the [`language`](../../06-api-reference/interfaces/DecodingOptions.md#language) field set to your desired language code. ```typescript -import { SpeechToTextModule, WHISPER_TINY } from 'react-native-executorch'; - +import { models, SpeechToTextModule } from 'react-native-executorch'; const model = await SpeechToTextModule.fromModelName( - WHISPER_TINY, + models.speech_to_text.whisper_tiny(), (progress) => { console.log(progress); } @@ -118,14 +116,14 @@ const transcription = await model.transcribe(audioBuffer, { verbose: true }); ### Transcription ```tsx -import { SpeechToTextModule, WHISPER_TINY_EN } from 'react-native-executorch'; +import { models, SpeechToTextModule } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; import * as FileSystem from 'expo-file-system'; const transcribeAudio = async () => { // Initialize with the model config const model = await SpeechToTextModule.fromModelName( - WHISPER_TINY_EN, + models.speech_to_text.whisper_tiny_en(), (progress) => { console.log(progress); } @@ -164,12 +162,12 @@ const transcribeAudio = async () => { ### Streaming Transcription ```tsx -import { SpeechToTextModule, WHISPER_TINY_EN } from 'react-native-executorch'; +import { models, SpeechToTextModule } from 'react-native-executorch'; import { AudioManager, AudioRecorder } from 'react-native-audio-api'; // Load the model const model = await SpeechToTextModule.fromModelName( - WHISPER_TINY_EN, + models.speech_to_text.whisper_tiny_en(), (progress) => { console.log(progress); } diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/TextEmbeddingsModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/TextEmbeddingsModule.md index 054299290b..aa563c213d 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/TextEmbeddingsModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/TextEmbeddingsModule.md @@ -12,14 +12,11 @@ TypeScript API implementation of the [useTextEmbeddings](../../03-hooks/01-natur ## High Level Overview ```typescript -import { - TextEmbeddingsModule, - ALL_MINILM_L6_V2, -} from 'react-native-executorch'; - +import { models, TextEmbeddingsModule } from 'react-native-executorch'; // Creating an instance and loading the model -const textEmbeddingsModule = - await TextEmbeddingsModule.fromModelName(ALL_MINILM_L6_V2); +const textEmbeddingsModule = await TextEmbeddingsModule.fromModelName( + models.text_embedding.all_minilm_l6_v2() +); // Running the model const embedding = await textEmbeddingsModule.forward('Hello World!'); diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/TextToSpeechModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/TextToSpeechModule.md index 2834b421f8..daf5cb735b 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/TextToSpeechModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/TextToSpeechModule.md @@ -13,13 +13,9 @@ TypeScript API implementation of the [useTextToSpeech](../../03-hooks/01-natural ## High Level Overview ```typescript -import { - TextToSpeechModule, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; - +import { models, TextToSpeechModule } from 'react-native-executorch'; const model = await TextToSpeechModule.fromModelName( - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, + models.text_to_speech.kokoro.en_us.heart(), (progress) => console.log(progress) ); @@ -68,14 +64,11 @@ Since `forward` processes the entire input at once, it might take a significant ### Speech Synthesis ```typescript -import { - TextToSpeechModule, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; +import { models, TextToSpeechModule } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; const tts = await TextToSpeechModule.fromModelName( - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART + models.text_to_speech.kokoro.en_us.heart() ); const audioContext = new AudioContext({ sampleRate: 24000 }); @@ -98,14 +91,11 @@ try { ### Streaming Synthesis ```typescript -import { - TextToSpeechModule, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; +import { models, TextToSpeechModule } from 'react-native-executorch'; import { AudioContext } from 'react-native-audio-api'; const tts = await TextToSpeechModule.fromModelName( - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART + models.text_to_speech.kokoro.en_us.heart() ); const audioContext = new AudioContext({ sampleRate: 24000 }); @@ -136,13 +126,9 @@ try { If you already have a phoneme string (e.g., from an external library), you can use `forward` or `stream` with the `phonemize: false` flag to synthesize audio directly, skipping the internal phonemizer stage. ```typescript -import { - TextToSpeechModule, - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, -} from 'react-native-executorch'; - +import { models, TextToSpeechModule } from 'react-native-executorch'; const tts = await TextToSpeechModule.fromModelName( - KOKORO_AMERICAN_ENGLISH_FEMALE_HEART + models.text_to_speech.kokoro.en_us.heart() ); // Example phonemes for "ExecuTorch" diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/TokenizerModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/TokenizerModule.md index dffdfba867..f85178fe09 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/TokenizerModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/TokenizerModule.md @@ -11,13 +11,12 @@ TypeScript API implementation of the [useTokenizer](../../03-hooks/01-natural-la ## High Level Overview ```typescript -import { TokenizerModule, ALL_MINILM_L6_V2 } from 'react-native-executorch'; - +import { models, TokenizerModule } from 'react-native-executorch'; // Creating an instance const tokenizerModule = new TokenizerModule(); // Load the tokenizer -await tokenizerModule.load(ALL_MINILM_L6_V2); +await tokenizerModule.load(models.text_embedding.all_minilm_l6_v2()); console.log('Tokenizer loaded'); // Get tokenizers vocabulary size diff --git a/docs/docs/04-typescript-api/01-natural-language-processing/VADModule.md b/docs/docs/04-typescript-api/01-natural-language-processing/VADModule.md index d32a7c3920..e9dd56710e 100644 --- a/docs/docs/04-typescript-api/01-natural-language-processing/VADModule.md +++ b/docs/docs/04-typescript-api/01-natural-language-processing/VADModule.md @@ -12,9 +12,8 @@ TypeScript API implementation of the [useVAD](../../03-hooks/01-natural-language ## High Level Overview ```typescript -import { VADModule, FSMN_VAD } from 'react-native-executorch'; - -const model = await VADModule.fromModelName(FSMN_VAD, (progress) => +import { models, VADModule } from 'react-native-executorch'; +const model = await VADModule.fromModelName(models.vad.fsmn_vad(), (progress) => console.log(progress) ); diff --git a/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md b/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md index 256e918123..8f7802686c 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md @@ -12,16 +12,13 @@ TypeScript API implementation of the [useClassification](../../03-hooks/02-compu ## High Level Overview ```typescript -import { - ClassificationModule, - EFFICIENTNET_V2_S, -} from 'react-native-executorch'; - +import { models, ClassificationModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating and loading the module -const classificationModule = - await ClassificationModule.fromModelName(EFFICIENTNET_V2_S); +const classificationModule = await ClassificationModule.fromModelName( + models.classification.efficientnet_v2_s() +); // Running the model const classesWithProbabilities = await classificationModule.forward(imageUri); @@ -49,7 +46,6 @@ Use [`fromCustomModel`](../../06-api-reference/classes/ClassificationModule.md#f ```typescript import { ClassificationModule } from 'react-native-executorch'; - const MyLabels = { CAT: 0, DOG: 1, BIRD: 2 } as const; const classifier = await ClassificationModule.fromCustomModel( diff --git a/docs/docs/04-typescript-api/02-computer-vision/ImageEmbeddingsModule.md b/docs/docs/04-typescript-api/02-computer-vision/ImageEmbeddingsModule.md index 47eceef00a..132245a3f5 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/ImageEmbeddingsModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/ImageEmbeddingsModule.md @@ -12,14 +12,10 @@ TypeScript API implementation of the [useImageEmbeddings](../../03-hooks/02-comp ## High Level Overview ```typescript -import { - ImageEmbeddingsModule, - CLIP_VIT_BASE_PATCH32_IMAGE, -} from 'react-native-executorch'; - +import { models, ImageEmbeddingsModule } from 'react-native-executorch'; // Creating and loading the module const imageEmbeddingsModule = await ImageEmbeddingsModule.fromModelName( - CLIP_VIT_BASE_PATCH32_IMAGE + models.image_embedding.clip_vit_base_patch32_image() ); // Running the model diff --git a/docs/docs/04-typescript-api/02-computer-vision/InstanceSegmentationModule.md b/docs/docs/04-typescript-api/02-computer-vision/InstanceSegmentationModule.md index 6363de61f5..1403cfb21e 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/InstanceSegmentationModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/InstanceSegmentationModule.md @@ -11,16 +11,13 @@ TypeScript API implementation of the [useInstanceSegmentation](../../03-hooks/02 ## High Level Overview ```typescript -import { - InstanceSegmentationModule, - YOLO26N_SEG, -} from 'react-native-executorch'; - +import { models, InstanceSegmentationModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating an instance from a built-in model -const segmentation = - await InstanceSegmentationModule.fromModelName(YOLO26N_SEG); +const segmentation = await InstanceSegmentationModule.fromModelName( + models.instance_segmentation.yolo26n_seg() +); // Running the model const instances = await segmentation.forward(imageUri); @@ -44,13 +41,10 @@ Use [`fromModelName`](../../06-api-reference/classes/InstanceSegmentationModule. - `onDownloadProgress` (optional) - Callback to track download progress, receiving a value between 0 and 1. ```typescript -import { - InstanceSegmentationModule, - YOLO26N_SEG, -} from 'react-native-executorch'; - -const segmentation = - await InstanceSegmentationModule.fromModelName(YOLO26N_SEG); +import { models, InstanceSegmentationModule } from 'react-native-executorch'; +const segmentation = await InstanceSegmentationModule.fromModelName( + models.instance_segmentation.yolo26n_seg() +); ``` ### From a custom config diff --git a/docs/docs/04-typescript-api/02-computer-vision/OCRModule.md b/docs/docs/04-typescript-api/02-computer-vision/OCRModule.md index 1391982173..a1fac72f5c 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/OCRModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/OCRModule.md @@ -12,11 +12,13 @@ TypeScript API implementation of the [useOCR](../../03-hooks/02-computer-vision/ ## High Level Overview ```typescript -import { OCRModule, OCR_ENGLISH } from 'react-native-executorch'; +import { models, OCRModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating an instance and loading the model -const ocrModule = await OCRModule.fromModelName(OCR_ENGLISH); +const ocrModule = await OCRModule.fromModelName( + models.ocr.craft({ language: 'en' }) +); // Running the model const detections = await ocrModule.forward(imageUri); diff --git a/docs/docs/04-typescript-api/02-computer-vision/ObjectDetectionModule.md b/docs/docs/04-typescript-api/02-computer-vision/ObjectDetectionModule.md index 0d004e6752..4b1e19982f 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/ObjectDetectionModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/ObjectDetectionModule.md @@ -12,16 +12,12 @@ TypeScript API implementation of the [useObjectDetection](../../03-hooks/02-comp ## High Level Overview ```typescript -import { - ObjectDetectionModule, - SSDLITE_320_MOBILENET_V3_LARGE, -} from 'react-native-executorch'; - +import { models, ObjectDetectionModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating an instance and loading the model const objectDetectionModule = await ObjectDetectionModule.fromModelName( - SSDLITE_320_MOBILENET_V3_LARGE + models.object_detection.ssdlite_320_mobilenet_v3_large() ); // Running the model @@ -69,7 +65,6 @@ Use [`fromCustomModel`](../../06-api-reference/classes/ObjectDetectionModule.md# ```typescript import { ObjectDetectionModule } from 'react-native-executorch'; - const MyLabels = { BACKGROUND: 0, CAT: 1, DOG: 2 } as const; const detector = await ObjectDetectionModule.fromCustomModel( diff --git a/docs/docs/04-typescript-api/02-computer-vision/PoseEstimationModule.md b/docs/docs/04-typescript-api/02-computer-vision/PoseEstimationModule.md index bc32211b19..f8c2c7a173 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/PoseEstimationModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/PoseEstimationModule.md @@ -12,13 +12,13 @@ TypeScript API implementation of the [usePoseEstimation](../../03-hooks/02-compu ## High Level Overview ```typescript -import { PoseEstimationModule, YOLO26N_POSE } from 'react-native-executorch'; - +import { models, PoseEstimationModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating an instance and loading the model -const poseEstimationModule = - await PoseEstimationModule.fromModelName(YOLO26N_POSE); +const poseEstimationModule = await PoseEstimationModule.fromModelName( + models.pose_estimation.yolo26n() +); // Running the model const detections = await poseEstimationModule.forward(imageUri); @@ -72,7 +72,6 @@ Use [`fromCustomModel`](../../06-api-reference/classes/PoseEstimationModule.md#f ```typescript import { PoseEstimationModule } from 'react-native-executorch'; - const HandKeypoints = { WRIST: 0, THUMB_TIP: 1, diff --git a/docs/docs/04-typescript-api/02-computer-vision/SemanticSegmentationModule.md b/docs/docs/04-typescript-api/02-computer-vision/SemanticSegmentationModule.md index b248f2876e..fffe2a7ba1 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/SemanticSegmentationModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/SemanticSegmentationModule.md @@ -12,16 +12,13 @@ TypeScript API implementation of the [useSemanticSegmentation](../../03-hooks/02 ## High Level Overview ```typescript -import { - SemanticSegmentationModule, - DEEPLAB_V3_RESNET50, -} from 'react-native-executorch'; - +import { models, SemanticSegmentationModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating an instance from a built-in model -const segmentation = - await SemanticSegmentationModule.fromModelName(DEEPLAB_V3_RESNET50); +const segmentation = await SemanticSegmentationModule.fromModelName( + models.semantic_segmentation.deeplab_v3_resnet50() +); // Running the model const result = await segmentation.forward(imageUri); @@ -42,7 +39,7 @@ Use [`fromModelName`](../../06-api-reference/classes/SemanticSegmentationModule. ```typescript const segmentation = await SemanticSegmentationModule.fromModelName( - DEEPLAB_V3_RESNET50, + models.semantic_segmentation.deeplab_v3_resnet50(), (progress) => console.log(`Download: ${Math.round(progress * 100)}%`) ); ``` diff --git a/docs/docs/04-typescript-api/02-computer-vision/StyleTransferModule.md b/docs/docs/04-typescript-api/02-computer-vision/StyleTransferModule.md index 4c57716001..966cdff58b 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/StyleTransferModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/StyleTransferModule.md @@ -12,16 +12,13 @@ TypeScript API implementation of the [useStyleTransfer](../../03-hooks/02-comput ## High Level Overview ```typescript -import { - StyleTransferModule, - STYLE_TRANSFER_CANDY, -} from 'react-native-executorch'; - +import { models, StyleTransferModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating and loading the module -const styleTransferModule = - await StyleTransferModule.fromModelName(STYLE_TRANSFER_CANDY); +const styleTransferModule = await StyleTransferModule.fromModelName( + models.style_transfer.candy() +); // Running the model const generatedImageUrl = await styleTransferModule.forward(imageUri); diff --git a/docs/docs/04-typescript-api/02-computer-vision/TextToImageModule.md b/docs/docs/04-typescript-api/02-computer-vision/TextToImageModule.md index d6ade747bd..cf73eee019 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/TextToImageModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/TextToImageModule.md @@ -12,16 +12,12 @@ TypeScript API implementation of the [useTextToImage](../../03-hooks/02-computer ## High Level Overview ```typescript -import { - TextToImageModule, - BK_SDM_TINY_VPRED_256, -} from 'react-native-executorch'; - +import { models, TextToImageModule } from 'react-native-executorch'; const input = 'a castle'; // Creating an instance and loading the model const textToImageModule = await TextToImageModule.fromModelName( - BK_SDM_TINY_VPRED_256 + models.image_generation.bk_sdm_tiny_vpred_256() ); // Running the model diff --git a/docs/docs/04-typescript-api/02-computer-vision/VerticalOCRModule.md b/docs/docs/04-typescript-api/02-computer-vision/VerticalOCRModule.md index cc1cdba51d..59eaacfbb8 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/VerticalOCRModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/VerticalOCRModule.md @@ -12,12 +12,13 @@ TypeScript API implementation of the [useVerticalOCR](../../03-hooks/02-computer ## High Level Overview ```typescript -import { VerticalOCRModule, OCR_ENGLISH } from 'react-native-executorch'; - +import { models, VerticalOCRModule } from 'react-native-executorch'; const imageUri = 'path/to/image.png'; // Creating an instance and loading the model -const verticalOCRModule = await VerticalOCRModule.fromModelName(OCR_ENGLISH); +const verticalOCRModule = await VerticalOCRModule.fromModelName( + models.ocr.craft({ language: 'en' }) +); // Running the model const detections = await verticalOCRModule.forward(imageUri); diff --git a/docs/docs/04-typescript-api/03-executorch-bindings/ExecutorchModule.md b/docs/docs/04-typescript-api/03-executorch-bindings/ExecutorchModule.md index 099379b333..252f7fa74a 100644 --- a/docs/docs/04-typescript-api/03-executorch-bindings/ExecutorchModule.md +++ b/docs/docs/04-typescript-api/03-executorch-bindings/ExecutorchModule.md @@ -15,12 +15,7 @@ For React applications, consider using the [`useExecutorchModule`](../../03-hook ## High Level Overview ```typescript -import { - ExecutorchModule, - STYLE_TRANSFER_CANDY, - ScalarType, -} from 'react-native-executorch'; - +import { models, ExecutorchModule, ScalarType } from 'react-native-executorch'; // Creating the input array const inputTensor = { dataPtr: new Float32Array(1 * 3 * 640 * 640), @@ -32,7 +27,7 @@ const inputTensor = { const model = new ExecutorchModule(); // Loading the model -await model.load(STYLE_TRANSFER_CANDY); +await model.load(models.style_transfer.candy()); // Running the forward method const output = await model.forward([inputTensor]); @@ -61,17 +56,12 @@ This example demonstrates the integration and usage of the ExecuTorch bindings w First, import the necessary functions from the `react-native-executorch` package and initialize the ExecuTorch module with the specified style transfer model. ```typescript -import { - ExecutorchModule, - STYLE_TRANSFER_CANDY, - ScalarType, -} from 'react-native-executorch'; - +import { models, ExecutorchModule, ScalarType } from 'react-native-executorch'; // Initialize the executorch module const executorchModule = new ExecutorchModule(); // Load the model with optional download progress callback -await executorchModule.load(STYLE_TRANSFER_CANDY, (progress) => { +await executorchModule.load(models.style_transfer.candy(), (progress) => { console.log(`Download progress: ${progress}%`); }); ``` diff --git a/docs/docs/05-utilities/04-error-handling.md b/docs/docs/05-utilities/04-error-handling.md index bf13b71668..3e1b9d9fe6 100644 --- a/docs/docs/05-utilities/04-error-handling.md +++ b/docs/docs/05-utilities/04-error-handling.md @@ -10,14 +10,13 @@ This example uses the `LLMModule`, and then tries to change its `generationConfi ```typescript import { + models, LLMModule, - LFM2_5_1_2B_INSTRUCT, RnExecutorchError, RnExecutorchErrorCode, } from 'react-native-executorch'; - const llm = await LLMModule.fromModelName( - LFM2_5_1_2B_INSTRUCT, + models.llm.lfm2_5_1_2b_instruct(), (progress) => console.log(progress), (token) => console.log(token), (messages) => console.log(messages) @@ -68,9 +67,7 @@ llm.delete(); ## Reference -All errors in React Native ExecuTorch inherit from `RnExecutorchError` and include a `code` property. The code is typed as `RnExecutorchErrorCode | number`: in practice you'll almost always see a member of the enum, but the codes are generated from a shared config into both the C++ and TS sources, and if those generated files drift the raw numeric value flows through unchanged. When switching on `err.code`, always include a `default` branch. - -Below is a comprehensive list of all possible errors, organized by category. +All errors in React Native ExecuTorch inherit from `RnExecutorchError` and include a `code` property from the `RnExecutorchErrorCode` enum. Below is a comprehensive list of all possible errors, organized by category. ### Module State Errors @@ -85,15 +82,15 @@ These errors occur when trying to perform operations on a model in an invalid st These errors occur when invalid configuration or input is provided. -| Error Code | Description | When It Occurs | How to Handle | -| ---------------------- | ------------------------------------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| `InvalidConfig` | Configuration parameters are invalid | Setting parameters outside valid ranges (e.g., `topp` outside [0, 1]) | Check parameter constraints and provide valid values | -| `InvalidUserInput` | Input provided to API is invalid | Passing empty arrays, null values, or malformed data to methods | Validate input before calling methods | -| `InvalidModelSource` | Model source type is invalid | Providing wrong type for model source (e.g., object when string expected) | Ensure model source matches expected type | -| `LanguageNotSupported` | Language not supported by model | Passing unsupported language to multilingual OCR or Speech-to-Text models | Use a supported language or different model | -| `PlatformNotSupported` | Current platform is not supported | Using features (e.g., camera frame processing) on an unsupported platform or OS version | Ensure you're running on a supported platform/OS version | -| `WrongDimensions` | Input tensor dimensions don't match | Providing input with incorrect shape for the model | Check model's expected input dimensions | -| `UnexpectedNumInputs` | Wrong number of inputs provided | Passing more or fewer inputs than model expects | Verify the expected model I/O contract in docs or source code | +| Error Code | Description | When It Occurs | How to Handle | +| ---------------------- | ------------------------------------ | --------------------------------------------------------------------------------------- | -------------------------------------------------------- | +| `InvalidConfig` | Configuration parameters are invalid | Setting parameters outside valid ranges (e.g., `topp` outside [0, 1]) | Check parameter constraints and provide valid values | +| `InvalidUserInput` | Input provided to API is invalid | Passing empty arrays, null values, or malformed data to methods | Validate input before calling methods | +| `InvalidModelSource` | Model source type is invalid | Providing wrong type for model source (e.g., object when string expected) | Ensure model source matches expected type | +| `LanguageNotSupported` | Language not supported by model | Passing unsupported language to multilingual OCR or Speech-to-Text models | Use a supported language or different model | +| `PlatformNotSupported` | Current platform is not supported | Using features (e.g., camera frame processing) on an unsupported platform or OS version | Ensure you're running on a supported platform/OS version | +| `WrongDimensions` | Input tensor dimensions don't match | Providing input with incorrect shape for the model | Check model's expected input dimensions | +| `UnexpectedNumInputs` | Wrong number of inputs provided | Passing more or fewer inputs than model expects | Match the number of inputs to model metadata | ### File Operations Errors @@ -135,12 +132,12 @@ These errors are specific to streaming transcription operations. These errors come from the ExecuTorch runtime during model execution. -| Error Code | Description | When It Occurs | How to Handle | -| -------------------- | -------------------------------- | ---------------------------------------------- | ----------------------------------------------------------- | -| `InvalidModelOutput` | Model output size unexpected | Model produces output of wrong size | Verify model's expected I/O contract in docs or source code | -| `ThreadPoolError` | Threadpool operation failed | Internal threading issue | Restart the model or app | -| `TokenizerError` | Tokenizer or tokenization failed | Tokenizer initialization or processing error | Check tokenizer files and model compatibility | -| `UnknownError` | Unexpected error occurred | 3rd-party library error or unhandled exception | Check logs for details, report if reproducible | +| Error Code | Description | When It Occurs | How to Handle | +| -------------------- | -------------------------------- | ---------------------------------------------- | ---------------------------------------------- | +| `InvalidModelOutput` | Model output size unexpected | Model produces output of wrong size | Verify model is compatible with the library | +| `ThreadPoolError` | Threadpool operation failed | Internal threading issue | Restart the model or app | +| `TokenizerError` | Tokenizer or tokenization failed | Tokenizer initialization or processing error | Check tokenizer files and model compatibility | +| `UnknownError` | Unexpected error occurred | 3rd-party library error or unhandled exception | Check logs for details, report if reproducible | ### ExecuTorch Runtime Errors diff --git a/docs/docs/05-utilities/model-registry.md b/docs/docs/05-utilities/model-registry.md index 02a74bbb13..83b9b80fd5 100644 --- a/docs/docs/05-utilities/model-registry.md +++ b/docs/docs/05-utilities/model-registry.md @@ -2,36 +2,142 @@ title: Model Registry --- -The [Model Registry](/react-native-executorch/docs/next/api-reference/variables/MODEL_REGISTRY) is a collection of all pre-configured model definitions shipped with React Native ExecuTorch. Each entry contains the model's name and all source URLs needed to download and run it, so you don't have to manage URLs manually. +The Model Registry is a typed, grouped index of every model shipped with React Native ExecuTorch. It removes the need to memorize per-model constant names: pick a capability group, pick a model, and optionally opt out of quantization or override the backend. -## Usage +```typescript +import { models } from 'react-native-executorch'; + +// Default (quantized when available, platform-default backend). +const llm = useLLM({ model: models.llm.llama3_2_3b() }); + +// Non-quantized variant. +const llmBase = useLLM({ model: models.llm.llama3_2_3b({ quant: false }) }); +``` + +Each leaf is a **function**. Call it (optionally with `{ quant, backend }`) to get the resolved model config. Accessors are not readable as values — this avoids a class of React state pitfalls (`useState` lazy-init, `useMemo`/`useCallback` deps), and pickers can fall back to plain `===` reference equality on the returned config. + +## Shape + +`models` is grouped by capability. Each leaf is a callable accessor. + +| Group | Examples | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `llm` | `llama3_2_3b`, `qwen3_4b`, `smollm2_1_1_7b`, `phi_4_mini_4b`, `bielik_v3_0_1_5b`, `lfm2_5_1_2b_instruct`, `lfm2_5_vl_1_6b`, `lfm2_5_vl_450m`, … | +| `classification` | `efficientnet_v2_s` | +| `privacy_filter` | `openai`, `nemotron` | +| `object_detection` | `ssdlite_320_mobilenet_v3_large`, `yolo26n` … `yolo26x`, `rf_detr_nano`, `fastsam_s`, `fastsam_x` | +| `pose_estimation` | `yolo26n` | +| `semantic_segmentation` | `deeplab_v3_resnet50`, `lraspp_mobilenet_v3_large`, `fcn_resnet101`, `selfie_segmentation`, … | +| `instance_segmentation` | `yolo26n_seg` … `yolo26x_seg`, `rf_detr_nano_seg` | +| `style_transfer` | `candy`, `mosaic`, `rain_princess`, `udnie` | +| `speech_to_text` | `whisper_tiny_en`, `whisper_base`, `whisper_small_en`, … | +| `text_to_speech` | nested by model family + language: `kokoro.en_us.{heart, river, sarah, adam, …}`, `kokoro.en_gb.{emma, daniel}`, `kokoro.fr.siwis`, `kokoro.es.{dora, alex}`, `kokoro.it.{sara, nicola}`, `kokoro.pt.{dora, santa}`, `kokoro.hi.{alpha, omega, psi}`, `kokoro.pl.mateusz`, `kokoro.de.anna` | +| `text_embedding` | `all_minilm_l6_v2`, `all_mpnet_base_v2`, `clip_vit_base_patch32_text`, … | +| `image_embedding` | `clip_vit_base_patch32_image` | +| `image_generation` | `bk_sdm_tiny_vpred_256`, `bk_sdm_tiny_vpred_512` | +| `vad` | `fsmn_vad` | +| `ocr` | nested by detector: `craft({ language: 'en' })` — see [§OCR](#ocr) below | + +## Options ```typescript -import { MODEL_REGISTRY, LFM2_5_1_2B_INSTRUCT } from 'react-native-executorch'; +type ModelOpts = { + quant?: boolean; // Pick the non-quantized variant when false. Defaults to the quantized variant when one is published. + backend?: B; // Explicit backend; the set of allowed values is per-model. +}; ``` -### Accessing a model directly +- `quant` defaults to the quantized variant for models that publish one (e.g. `llama3_2_3b` → SpinQuant, `efficientnet_v2_s` → int8). Pass `{ quant: false }` to get the full-precision variant. For models with a single variant, `quant` is accepted but has no effect. +- `backend` selects an explicit backend. The accessor's call signature is typed to exactly the backends the model ships with, so requesting one the model doesn't publish is a compile-time error (e.g. `models.llm.llama3_2_3b({ backend: 'coreml' })` does not type-check — Llama 3.2 is xnnpack-only). When `backend` is omitted, the platform-default applies: CoreML on iOS and XNNPACK on Android whenever the model ships that backend. Models that ship only one backend (e.g. xnnpack-only LLMs) use that one on both platforms. + +## Usage patterns -Every model config is exported as a standalone constant: +### Default model ```typescript -import { LFM2_5_1_2B_INSTRUCT } from 'react-native-executorch'; +import { models } from 'react-native-executorch'; -const llm = useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +const llm = useLLM({ model: models.llm.llama3_2_3b() }); +const classifier = useClassification({ + model: models.classification.efficientnet_v2_s(), +}); +const stt = useSpeechToText({ + model: models.speech_to_text.whisper_tiny_en(), +}); ``` -### Listing all models +### Non-quantized variant -Use `MODEL_REGISTRY` to discover and enumerate all available models: +```typescript +const llm = useLLM({ model: models.llm.qwen3_4b({ quant: false }) }); +const classifier = useClassification({ + model: models.classification.efficientnet_v2_s({ quant: false }), +}); +``` + +### Explicit backend ```typescript -import { MODEL_REGISTRY } from 'react-native-executorch'; +// Force XNNPACK on iOS (overrides the CoreML default). +const detector = useObjectDetection({ + model: models.object_detection.rf_detr_nano({ backend: 'xnnpack' }), +}); + +// Combine `quant` and `backend`. +const styled = useStyleTransfer({ + model: models.style_transfer.candy({ backend: 'coreml', quant: false }), +}); +``` -// Get all model names -const names = Object.values(MODEL_REGISTRY.ALL_MODELS).map((m) => m.modelName); +### Text-to-speech -// Find models by name -const whisperModels = Object.values(MODEL_REGISTRY.ALL_MODELS).filter((m) => - m.modelName.includes('whisper') -); +`text_to_speech` is grouped by model family then by language code (`kokoro.en_us`, `kokoro.en_gb`, `kokoro.fr`, `kokoro.es`, `kokoro.it`, `kokoro.pt`, `kokoro.hi`, `kokoro.pl`, `kokoro.de`). Each leaf returns a complete Kokoro preset bundling the model, voice, and phonemizer — pass the whole result to `useTextToSpeech`. The `kokoro` level reserves room for a future TTS family without forcing a breaking rename. + +```typescript +import { models, useTextToSpeech } from 'react-native-executorch'; + +const tts = useTextToSpeech(models.text_to_speech.kokoro.en_us.heart()); +// Other languages: +// models.text_to_speech.kokoro.en_gb.emma() +// models.text_to_speech.kokoro.fr.siwis() +// models.text_to_speech.kokoro.pl.mateusz() ``` + +### OCR + +OCR is nested by detector family and parameterized by language. `craft` is the current pipeline (CRAFT detector + per-alphabet CRNN recognizer); future detectors land as siblings so the call site stays stable. + +```typescript +const ocr = useOcr({ + model: models.ocr.craft({ language: 'en' }), +}); +``` + +The `language` parameter is type-narrowed to supported tokens (`'en'`, `'es'`, `'ja'`, `'ko'`, …). See the OCR docs for the full list. + +### Direct imports still work + +Every model is also exported as a top-level constant. Either style is supported: + +```typescript +import { LFM2_5_1_2B_INSTRUCT, models } from 'react-native-executorch'; + +useLLM({ model: LFM2_5_1_2B_INSTRUCT }); +useLLM({ model: models.llm.lfm2_5_1_2b_instruct() }); +``` + +## Migration from the previous registry + +Earlier releases exposed `MODEL_REGISTRY` as an uppercase, dual-value/function shape. That has been replaced with a function-only, lowercase `models` export. + +```typescript +// Before +useLLM(MODEL_REGISTRY.LLM.LLAMA3_2_3B); +useLLM(MODEL_REGISTRY.LLM.LLAMA3_2_3B({ quant: false })); + +// After +useLLM({ model: models.llm.llama3_2_3b() }); +useLLM({ model: models.llm.llama3_2_3b({ quant: false }) }); +``` + +Individual constant imports (`LLAMA3_2_3B`, `WHISPER_TINY_EN`, …) are unchanged. diff --git a/docs/docs/08-resource-fetcher/02-custom-adapter.md b/docs/docs/08-resource-fetcher/02-custom-adapter.md index 36d25a888d..22773b3f47 100644 --- a/docs/docs/08-resource-fetcher/02-custom-adapter.md +++ b/docs/docs/08-resource-fetcher/02-custom-adapter.md @@ -13,7 +13,6 @@ import { ResourceFetcherAdapter, ResourceSource, } from 'react-native-executorch'; - interface ResourceFetcherAdapter { fetch( callback: (downloadProgress: number) => void, diff --git a/docs/versioned_docs/version-0.8.x/05-utilities/model-registry.md b/docs/versioned_docs/version-0.8.x/05-utilities/model-registry.md index 3b4241c986..7c15dc1205 100644 --- a/docs/versioned_docs/version-0.8.x/05-utilities/model-registry.md +++ b/docs/versioned_docs/version-0.8.x/05-utilities/model-registry.md @@ -2,7 +2,7 @@ title: Model Registry --- -The [Model Registry](/react-native-executorch/docs/next/api-reference/variables/MODEL_REGISTRY) is a collection of all pre-configured model definitions shipped with React Native ExecuTorch. Each entry contains the model's name and all source URLs needed to download and run it, so you don't have to manage URLs manually. +The [Model Registry](../api-reference/variables/MODEL_REGISTRY) is a collection of all pre-configured model definitions shipped with React Native ExecuTorch. Each entry contains the model's name and all source URLs needed to download and run it, so you don't have to manage URLs manually. ## Usage diff --git a/packages/react-native-executorch/src/constants/modelRegistry.ts b/packages/react-native-executorch/src/constants/modelRegistry.ts new file mode 100644 index 0000000000..34ed574224 --- /dev/null +++ b/packages/react-native-executorch/src/constants/modelRegistry.ts @@ -0,0 +1,571 @@ +import { Platform } from 'react-native'; +import * as M from './modelUrls'; +import * as OCR from './ocr/models'; +import { symbols } from './ocr/symbols'; +import { + KOKORO_AMERICAN_ENGLISH_FEMALE_HEART, + KOKORO_AMERICAN_ENGLISH_FEMALE_RIVER, + KOKORO_AMERICAN_ENGLISH_FEMALE_SARAH, + KOKORO_AMERICAN_ENGLISH_MALE_ADAM, + KOKORO_AMERICAN_ENGLISH_MALE_MICHAEL, + KOKORO_AMERICAN_ENGLISH_MALE_SANTA, + KOKORO_BRITISH_ENGLISH_FEMALE_EMMA, + KOKORO_BRITISH_ENGLISH_MALE_DANIEL, + KOKORO_FRENCH_FEMALE_SIWIS, + KOKORO_SPANISH_FEMALE_DORA, + KOKORO_SPANISH_MALE_ALEX, + KOKORO_ITALIAN_FEMALE_SARA, + KOKORO_ITALIAN_MALE_NICOLA, + KOKORO_PORTUGUESE_FEMALE_DORA, + KOKORO_PORTUGUESE_MALE_SANTA, + KOKORO_HINDI_FEMALE_ALPHA, + KOKORO_HINDI_MALE_OMEGA, + KOKORO_HINDI_MALE_PSI, + KOKORO_POLISH_MALE_MATEUSZ, + KOKORO_GERMAN_FEMALE_ANNA, +} from './tts/voices'; +import { TextToSpeechModelConfig } from '../types/tts'; + +/** + * Backend options accepted by `models` accessors. + * + * The set of backends a particular model can be loaded with is encoded in + * its accessor's call signature — e.g. `models.llm.llama3_2_3b` only accepts + * `'xnnpack'`, while `models.object_detection.rf_detr_nano` accepts + * `'xnnpack' | 'coreml'`. Passing a backend a model doesn't ship is a + * compile-time error. + * @category Utils + */ +export type Backend = 'xnnpack' | 'coreml' | 'vulkan' | 'qnn'; + +/** + * Options for a `models` accessor call. + * @typeParam B - Subset of {@link Backend} that the accessor actually supports. + * @category Utils + */ +export type ModelOpts = { + /** Pick the non-quantized variant when `false`. Defaults to the quantized variant when one is published. */ + quant?: boolean; + /** Explicit backend; defaults to the platform-preferred backend for the model. */ + backend?: B; +}; + +// Accessors are functions; calling with no opts returns the platform default. +type Accessor = ( + opts?: ModelOpts +) => C; + +type BackendCell = { + base?: { modelName: string }; + quant?: { modelName: string }; +}; +type AnyVariantMap = Partial>; +type PlatformDefaults = { + ios?: B; + android?: B; + /** Fallback when no platform-specific default is set. */ + default?: B; +}; + +type CellConfig = T extends { base?: infer D; quant?: infer Q } + ? NonNullable | NonNullable + : never; +type ConfigOf = Extract< + { [K in keyof V]: CellConfig }[keyof V], + { modelName: string } +>; +type BackendsOf = Extract; + +const BACKEND_ORDER: Backend[] = ['xnnpack', 'coreml', 'vulkan', 'qnn']; + +function firstBackend(variants: AnyVariantMap): Backend { + for (const b of BACKEND_ORDER) { + if (variants[b]) return b; + } + throw new Error('Model variant map is empty.'); +} + +function resolveBackend( + variants: AnyVariantMap, + platformDefaults: PlatformDefaults | undefined, + requested: Backend | undefined +): Backend { + if (requested) return requested; + if (platformDefaults) { + if (Platform.OS === 'ios' && platformDefaults.ios) + return platformDefaults.ios; + if (Platform.OS === 'android' && platformDefaults.android) { + return platformDefaults.android; + } + if (platformDefaults.default) return platformDefaults.default; + } + // Implicit platform default: prefer CoreML on iOS, XNNPACK on Android + // whenever the model ships that backend. Models can override via + // `platformDefaults`. + if (Platform.OS === 'ios' && variants.coreml) return 'coreml'; + if (Platform.OS === 'android' && variants.xnnpack) return 'xnnpack'; + return firstBackend(variants); +} + +function resolveCell(cell: BackendCell, quant: boolean): { modelName: string } { + // Fall back to the other slot when the requested precision is missing, + // so single-precision backends still work either way. + const primary = quant ? cell.quant : cell.base; + const fallback = quant ? cell.base : cell.quant; + const result = primary ?? fallback; + if (!result) { + throw new Error('Model variant cell has no config.'); + } + return result; +} + +function resolveVariant( + variants: AnyVariantMap, + platformDefaults: PlatformDefaults | undefined, + opts: ModelOpts +): { modelName: string } { + const backend = resolveBackend(variants, platformDefaults, opts.backend); + const cell = variants[backend]; + if (!cell) { + throw new Error(`Backend '${backend}' is not available for this model.`); + } + return resolveCell(cell, opts.quant !== false); +} + +// Build an Accessor from a per-backend variant map and an optional +// platform-default policy. The resulting accessor's `backend` parameter is +// typed to exactly the keys present in `variants`. +function variant( + variants: V, + platformDefaults?: PlatformDefaults> +): Accessor, BackendsOf> { + type C = ConfigOf; + type B = BackendsOf; + return (opts: ModelOpts = {}) => + resolveVariant(variants, platformDefaults, opts) as C; +} + +// Single-config accessor (xnnpack-only, no quantized variant). +function base(c: C) { + return variant({ xnnpack: { base: c } }); +} + +// xnnpack-only accessor with a `base` / `quant` pair. +function pair( + baseC: D, + quantC: Q +) { + return variant({ xnnpack: { base: baseC, quant: quantC } }); +} + +// TTS presets bundle model + voice + phonemizer in a single config; they +// don't share the `{ modelName: string }` shape of the rest of the registry, +// and have no quant/backend axis. Expose them as a plain `() => Config` +// accessor so the call style stays consistent (`models.text_to_speech.en_us.heart()`). +function tts(c: C): () => C { + return () => c; +} + +// ───────────────────────────────────────────────────────────────────────────── +// Per-backend variant maps for models that ship more than one backend. +// ───────────────────────────────────────────────────────────────────────────── + +const EFFICIENTNET_V2_S_VARIANTS = { + xnnpack: { + base: { + modelName: 'efficientnet-v2-s' as const, + modelSource: M.EFFICIENTNET_V2_S_XNNPACK_FP32_MODEL, + }, + quant: { + modelName: 'efficientnet-v2-s-quantized' as const, + modelSource: M.EFFICIENTNET_V2_S_XNNPACK_INT8_MODEL, + }, + }, + coreml: { + base: { + modelName: 'efficientnet-v2-s' as const, + modelSource: M.EFFICIENTNET_V2_S_COREML_FP32_MODEL, + }, + quant: { + modelName: 'efficientnet-v2-s-quantized' as const, + modelSource: M.EFFICIENTNET_V2_S_COREML_FP16_MODEL, + }, + }, +}; + +const SSDLITE_320_MOBILENET_V3_LARGE_VARIANTS = { + xnnpack: { + base: { + modelName: 'ssdlite-320-mobilenet-v3-large' as const, + modelSource: M.SSDLITE_320_MOBILENET_V3_LARGE_XNNPACK_FP32_MODEL, + }, + }, + coreml: { + base: { + modelName: 'ssdlite-320-mobilenet-v3-large' as const, + modelSource: M.SSDLITE_320_MOBILENET_V3_LARGE_COREML_FP16_MODEL, + }, + }, +}; + +const RF_DETR_NANO_VARIANTS = { + xnnpack: { + base: { + modelName: 'rf-detr-nano' as const, + modelSource: M.RF_DETR_NANO_XNNPACK_FP32_MODEL, + }, + }, + coreml: { + base: { + modelName: 'rf-detr-nano' as const, + modelSource: M.RF_DETR_NANO_COREML_INT8_MODEL, + }, + }, +}; + +const RF_DETR_NANO_SEG_VARIANTS = { + xnnpack: { + base: { + modelName: 'rfdetr-nano-seg' as const, + modelSource: M.RF_DETR_NANO_SEG_XNNPACK_FP32_MODEL, + }, + }, + coreml: { + base: { + modelName: 'rfdetr-nano-seg' as const, + modelSource: M.RF_DETR_NANO_SEG_COREML_INT8_MODEL, + }, + }, +}; + +const FASTSAM_S_VARIANTS = { + xnnpack: { + base: { + modelName: 'fastsam-s' as const, + modelSource: M.FASTSAM_S_XNNPACK_FP32_MODEL, + }, + }, + coreml: { + base: { + modelName: 'fastsam-s' as const, + modelSource: M.FASTSAM_S_COREML_FP16_MODEL, + }, + }, +}; + +const FASTSAM_X_VARIANTS = { + xnnpack: { + base: { + modelName: 'fastsam-x' as const, + modelSource: M.FASTSAM_X_XNNPACK_FP32_MODEL, + }, + }, + coreml: { + base: { + modelName: 'fastsam-x' as const, + modelSource: M.FASTSAM_X_COREML_FP16_MODEL, + }, + }, +}; + +function styleTransferVariants< + const Display extends string, + const Slug extends string, +>(display: Display, slug: Slug) { + const urls = M.styleTransferUrls(display, slug); + return { + xnnpack: { + base: { + modelName: `style-transfer-${display}`, + modelSource: urls.xnnpackBase, + } as { + modelName: `style-transfer-${Display}`; + modelSource: string; + }, + quant: { + modelName: `style-transfer-${display}-quantized`, + modelSource: urls.xnnpackQuant, + } as { + modelName: `style-transfer-${Display}-quantized`; + modelSource: string; + }, + }, + coreml: { + base: { + modelName: `style-transfer-${display}`, + modelSource: urls.coremlBase, + } as { + modelName: `style-transfer-${Display}`; + modelSource: string; + }, + quant: { + modelName: `style-transfer-${display}-quantized`, + modelSource: urls.coremlQuant, + } as { + modelName: `style-transfer-${Display}-quantized`; + modelSource: string; + }, + }, + }; +} + +const STYLE_TRANSFER_CANDY_VARIANTS = styleTransferVariants('candy', 'candy'); +const STYLE_TRANSFER_MOSAIC_VARIANTS = styleTransferVariants( + 'mosaic', + 'mosaic' +); +const STYLE_TRANSFER_RAIN_PRINCESS_VARIANTS = styleTransferVariants( + 'rain-princess', + 'rain_princess' +); +const STYLE_TRANSFER_UDNIE_VARIANTS = styleTransferVariants('udnie', 'udnie'); + +const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_VARIANTS = { + xnnpack: { + base: { + modelName: 'distiluse-base-multilingual-cased-v2-8da4w' as const, + modelSource: M.DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W_MODEL, + tokenizerSource: M.DISTILUSE_BASE_MULTILINGUAL_CASED_V2_TOKENIZER, + }, + }, + coreml: { + base: { + modelName: 'distiluse-base-multilingual-cased-v2-coreml' as const, + modelSource: M.DISTILUSE_BASE_MULTILINGUAL_CASED_V2_COREML_MODEL, + tokenizerSource: M.DISTILUSE_BASE_MULTILINGUAL_CASED_V2_TOKENIZER, + }, + }, +}; + +// ───────────────────────────────────────────────────────────────────────────── +// OCR — language-parameterized accessor. +// +// The OCR pipeline ships one CRAFT detector + per-alphabet CRNN recognizers, +// already paired up in `OCR_` objects keyed by ISO language token +// (the `.language` field on each export). Build a runtime map from those +// exports so the user only needs to pass `{ language: 'en' }`. +// ───────────────────────────────────────────────────────────────────────────── + +type OcrConfig = typeof OCR.OCR_ABAZA; +type SupportedLanguage = keyof typeof symbols; + +const OCR_BY_LANGUAGE: Partial> = (() => { + const map: Partial> = {}; + for (const value of Object.values(OCR) as OcrConfig[]) { + if (value && typeof value === 'object' && 'language' in value) { + map[value.language as SupportedLanguage] = value; + } + } + return map; +})(); + +function craft({ language }: { language: SupportedLanguage }): OcrConfig { + const cfg = OCR_BY_LANGUAGE[language]; + if (!cfg) { + throw new Error( + `OCR is not published for language '${language}'. ` + + `Supported: ${Object.keys(OCR_BY_LANGUAGE).sort().join(', ')}` + ); + } + return cfg; +} + +/** + * Typed model registry grouped by capability. Each entry is a function-only + * accessor: call it (optionally with `{ quant, backend }`) to get the resolved + * config. The `backend` parameter is typed to exactly the backends a given + * model ships with — asking for a backend a model doesn't publish is a + * compile-time error. + * @example + * ```ts + * import { models } from 'react-native-executorch'; + * + * // Platform default (CoreML on iOS, XNNPACK on Android for multi-backend models). + * useObjectDetection({ model: models.object_detection.rf_detr_nano() }); + * + * // Explicit backend. + * useObjectDetection({ + * model: models.object_detection.rf_detr_nano({ backend: 'xnnpack' }), + * }); + * + * // Non-quantized variant. + * useLLM({ model: models.llm.llama3_2_3b({ quant: false }) }); + * + * // OCR — language-parameterized. + * useOcr({ model: models.ocr({ language: 'en' }) }); + * ``` + * @category Utils + */ +export const models = { + llm: { + llama3_2_1b: pair(M.LLAMA3_2_1B, M.LLAMA3_2_1B_SPINQUANT), + llama3_2_3b: pair(M.LLAMA3_2_3B, M.LLAMA3_2_3B_SPINQUANT), + qwen3_0_6b: pair(M.QWEN3_0_6B, M.QWEN3_0_6B_QUANTIZED), + qwen3_1_7b: pair(M.QWEN3_1_7B, M.QWEN3_1_7B_QUANTIZED), + qwen3_4b: pair(M.QWEN3_4B, M.QWEN3_4B_QUANTIZED), + qwen3_5_0_8b: base(M.QWEN3_5_0_8B_QUANTIZED), + qwen3_5_2b: base(M.QWEN3_5_2B_QUANTIZED), + qwen2_5_0_5b: pair(M.QWEN2_5_0_5B, M.QWEN2_5_0_5B_QUANTIZED), + qwen2_5_1_5b: pair(M.QWEN2_5_1_5B, M.QWEN2_5_1_5B_QUANTIZED), + qwen2_5_3b: pair(M.QWEN2_5_3B, M.QWEN2_5_3B_QUANTIZED), + hammer2_1_0_5b: pair(M.HAMMER2_1_0_5B, M.HAMMER2_1_0_5B_QUANTIZED), + hammer2_1_1_5b: pair(M.HAMMER2_1_1_5B, M.HAMMER2_1_1_5B_QUANTIZED), + hammer2_1_3b: pair(M.HAMMER2_1_3B, M.HAMMER2_1_3B_QUANTIZED), + smollm2_1_135m: pair(M.SMOLLM2_1_135M, M.SMOLLM2_1_135M_QUANTIZED), + smollm2_1_360m: pair(M.SMOLLM2_1_360M, M.SMOLLM2_1_360M_QUANTIZED), + smollm2_1_1_7b: pair(M.SMOLLM2_1_1_7B, M.SMOLLM2_1_1_7B_QUANTIZED), + phi_4_mini_4b: pair(M.PHI_4_MINI_4B, M.PHI_4_MINI_4B_QUANTIZED), + lfm2_5_350m: pair(M.LFM2_5_350M, M.LFM2_5_350M_QUANTIZED), + lfm2_5_1_2b_instruct: pair( + M.LFM2_5_1_2B_INSTRUCT, + M.LFM2_5_1_2B_INSTRUCT_QUANTIZED + ), + bielik_v3_0_1_5b: pair(M.BIELIK_V3_0_1_5B, M.BIELIK_V3_0_1_5B_QUANTIZED), + // Multimodal LLMs — same hook/module as plain LLMs, listed here so users + // pick a model by capability ("LLM") rather than by modality. + lfm2_5_vl_1_6b: base(M.LFM2_5_VL_1_6B_QUANTIZED), + lfm2_5_vl_450m: base(M.LFM2_5_VL_450M_QUANTIZED), + }, + classification: { + efficientnet_v2_s: variant(EFFICIENTNET_V2_S_VARIANTS), + }, + privacy_filter: { + openai: base(M.PRIVACY_FILTER_OPENAI), + nemotron: base(M.PRIVACY_FILTER_NEMOTRON), + }, + object_detection: { + ssdlite_320_mobilenet_v3_large: variant( + SSDLITE_320_MOBILENET_V3_LARGE_VARIANTS + ), + rf_detr_nano: variant(RF_DETR_NANO_VARIANTS), + yolo26n: base(M.YOLO26N), + yolo26s: base(M.YOLO26S), + yolo26m: base(M.YOLO26M), + yolo26l: base(M.YOLO26L), + yolo26x: base(M.YOLO26X), + fastsam_s: variant(FASTSAM_S_VARIANTS), + fastsam_x: variant(FASTSAM_X_VARIANTS), + }, + pose_estimation: { + yolo26n: base(M.YOLO26N_POSE), + }, + semantic_segmentation: { + deeplab_v3_resnet50: pair( + M.DEEPLAB_V3_RESNET50, + M.DEEPLAB_V3_RESNET50_QUANTIZED + ), + deeplab_v3_resnet101: pair( + M.DEEPLAB_V3_RESNET101, + M.DEEPLAB_V3_RESNET101_QUANTIZED + ), + deeplab_v3_mobilenet_v3_large: pair( + M.DEEPLAB_V3_MOBILENET_V3_LARGE, + M.DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED + ), + lraspp_mobilenet_v3_large: pair( + M.LRASPP_MOBILENET_V3_LARGE, + M.LRASPP_MOBILENET_V3_LARGE_QUANTIZED + ), + fcn_resnet50: pair(M.FCN_RESNET50, M.FCN_RESNET50_QUANTIZED), + fcn_resnet101: pair(M.FCN_RESNET101, M.FCN_RESNET101_QUANTIZED), + selfie_segmentation: base(M.SELFIE_SEGMENTATION), + }, + instance_segmentation: { + yolo26n_seg: base(M.YOLO26N_SEG), + yolo26s_seg: base(M.YOLO26S_SEG), + yolo26m_seg: base(M.YOLO26M_SEG), + yolo26l_seg: base(M.YOLO26L_SEG), + yolo26x_seg: base(M.YOLO26X_SEG), + rf_detr_nano_seg: variant(RF_DETR_NANO_SEG_VARIANTS), + }, + style_transfer: { + candy: variant(STYLE_TRANSFER_CANDY_VARIANTS), + mosaic: variant(STYLE_TRANSFER_MOSAIC_VARIANTS), + rain_princess: variant(STYLE_TRANSFER_RAIN_PRINCESS_VARIANTS), + udnie: variant(STYLE_TRANSFER_UDNIE_VARIANTS), + }, + speech_to_text: { + whisper_tiny_en: base(M.WHISPER_TINY_EN), + whisper_base_en: base(M.WHISPER_BASE_EN), + whisper_small_en: base(M.WHISPER_SMALL_EN), + whisper_tiny: base(M.WHISPER_TINY), + whisper_base: base(M.WHISPER_BASE), + whisper_small: base(M.WHISPER_SMALL), + }, + // Kokoro presets bundle model + voice + phonemizer per language. They go + // through `useTextToSpeech` directly — pick one and pass it as the `model`. + // Nested under the model family (`kokoro`) so a future TTS family can be + // added without breaking call sites. + text_to_speech: { + kokoro: { + en_us: { + heart: tts(KOKORO_AMERICAN_ENGLISH_FEMALE_HEART), + river: tts(KOKORO_AMERICAN_ENGLISH_FEMALE_RIVER), + sarah: tts(KOKORO_AMERICAN_ENGLISH_FEMALE_SARAH), + adam: tts(KOKORO_AMERICAN_ENGLISH_MALE_ADAM), + michael: tts(KOKORO_AMERICAN_ENGLISH_MALE_MICHAEL), + santa: tts(KOKORO_AMERICAN_ENGLISH_MALE_SANTA), + }, + en_gb: { + emma: tts(KOKORO_BRITISH_ENGLISH_FEMALE_EMMA), + daniel: tts(KOKORO_BRITISH_ENGLISH_MALE_DANIEL), + }, + fr: { + siwis: tts(KOKORO_FRENCH_FEMALE_SIWIS), + }, + es: { + dora: tts(KOKORO_SPANISH_FEMALE_DORA), + alex: tts(KOKORO_SPANISH_MALE_ALEX), + }, + it: { + sara: tts(KOKORO_ITALIAN_FEMALE_SARA), + nicola: tts(KOKORO_ITALIAN_MALE_NICOLA), + }, + pt: { + dora: tts(KOKORO_PORTUGUESE_FEMALE_DORA), + santa: tts(KOKORO_PORTUGUESE_MALE_SANTA), + }, + hi: { + alpha: tts(KOKORO_HINDI_FEMALE_ALPHA), + omega: tts(KOKORO_HINDI_MALE_OMEGA), + psi: tts(KOKORO_HINDI_MALE_PSI), + }, + pl: { + mateusz: tts(KOKORO_POLISH_MALE_MATEUSZ), + }, + de: { + anna: tts(KOKORO_GERMAN_FEMALE_ANNA), + }, + }, + }, + text_embedding: { + all_minilm_l6_v2: base(M.ALL_MINILM_L6_V2), + all_mpnet_base_v2: base(M.ALL_MPNET_BASE_V2), + multi_qa_minilm_l6_cos_v1: base(M.MULTI_QA_MINILM_L6_COS_V1), + multi_qa_mpnet_base_dot_v1: base(M.MULTI_QA_MPNET_BASE_DOT_V1), + distiluse_base_multilingual_cased_v2: variant( + DISTILUSE_BASE_MULTILINGUAL_CASED_V2_VARIANTS + ), + paraphrase_multilingual_minilm_l12_v2: base( + M.PARAPHRASE_MULTILINGUAL_MINILM_L12_V2_QUANTIZED + ), + clip_vit_base_patch32_text: base(M.CLIP_VIT_BASE_PATCH32_TEXT), + }, + image_embedding: { + clip_vit_base_patch32_image: pair( + M.CLIP_VIT_BASE_PATCH32_IMAGE, + M.CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED + ), + }, + image_generation: { + bk_sdm_tiny_vpred_512: base(M.BK_SDM_TINY_VPRED_512), + bk_sdm_tiny_vpred_256: base(M.BK_SDM_TINY_VPRED_256), + }, + vad: { + fsmn_vad: base(M.FSMN_VAD), + }, + // Nested under the detector model (`craft`) so a future OCR pipeline + // (e.g. an end-to-end TrOCR) can land as a sibling without breaking + // existing call sites. + ocr: { craft }, +} as const; diff --git a/packages/react-native-executorch/src/constants/modelUrls.ts b/packages/react-native-executorch/src/constants/modelUrls.ts index 159396add8..99d75f4626 100644 --- a/packages/react-native-executorch/src/constants/modelUrls.ts +++ b/packages/react-native-executorch/src/constants/modelUrls.ts @@ -3,19 +3,19 @@ import { PRIVACY_FILTER_NEMOTRON_LABELS, PRIVACY_FILTER_OPENAI_LABELS, } from './privacyFilterLabels'; -import { URL_PREFIX, PREVIOUS_VERSION_TAG, VERSION_TAG } from './versions'; +import { URL_PREFIX, VERSION_TAG, PREVIOUS_VERSION_TAG } from './versions'; // LLMs // LLAMA 3.2 -const LLAMA3_2_3B_MODEL = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/llama-3.2-3B/original/llama3_2_3B_bf16.pte`; +const LLAMA3_2_3B_MODEL = `${URL_PREFIX}-llama-3.2/${VERSION_TAG}/3b/xnnpack/llama_3_2_3b_xnnpack_bf16.pte`; const LLAMA3_2_3B_QLORA_MODEL = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/llama-3.2-3B/QLoRA/llama3_2-3B_qat_lora.pte`; -const LLAMA3_2_3B_SPINQUANT_MODEL = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/llama-3.2-3B/spinquant/llama3_2_3B_spinquant.pte`; -const LLAMA3_2_1B_MODEL = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/llama-3.2-1B/original/llama3_2_bf16.pte`; +const LLAMA3_2_3B_SPINQUANT_MODEL = `${URL_PREFIX}-llama-3.2/${VERSION_TAG}/3b/xnnpack/llama_3_2_3b_xnnpack_spinquant.pte`; +const LLAMA3_2_1B_MODEL = `${URL_PREFIX}-llama-3.2/${VERSION_TAG}/1b/xnnpack/llama_3_2_1b_xnnpack_bf16.pte`; const LLAMA3_2_1B_QLORA_MODEL = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/llama-3.2-1B/QLoRA/llama3_2_qat_lora.pte`; -const LLAMA3_2_1B_SPINQUANT_MODEL = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/llama-3.2-1B/spinquant/llama3_2_spinquant.pte`; -const LLAMA3_2_TOKENIZER = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const LLAMA3_2_TOKENIZER_CONFIG = `${URL_PREFIX}-llama-3.2/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const LLAMA3_2_1B_SPINQUANT_MODEL = `${URL_PREFIX}-llama-3.2/${VERSION_TAG}/1b/xnnpack/llama_3_2_1b_xnnpack_spinquant.pte`; +const LLAMA3_2_TOKENIZER = `${URL_PREFIX}-llama-3.2/${VERSION_TAG}/tokenizer.json`; +const LLAMA3_2_TOKENIZER_CONFIG = `${URL_PREFIX}-llama-3.2/${VERSION_TAG}/tokenizer_config.json`; /** * @category Models - LLM @@ -28,6 +28,10 @@ export const LLAMA3_2_3B = { } as const; /** + * @deprecated Use `LLAMA3_2_3B_SPINQUANT` instead — SpinQuant is the + * canonical quantized Llama 3.2 3B variant going forward. This alias + * still resolves the v0.8.0 file for back-compat and will be removed in + * a future major release. * @category Models - LLM */ export const LLAMA3_2_3B_QLORA = { @@ -58,6 +62,10 @@ export const LLAMA3_2_1B = { } as const; /** + * @deprecated Use `LLAMA3_2_1B_SPINQUANT` instead — SpinQuant is the + * canonical quantized Llama 3.2 1B variant going forward. This alias + * still resolves the v0.8.0 file for back-compat and will be removed in + * a future major release. * @category Models - LLM */ export const LLAMA3_2_1B_QLORA = { @@ -78,14 +86,14 @@ export const LLAMA3_2_1B_SPINQUANT = { } as const; // QWEN 3 -const QWEN3_0_6B_MODEL = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/qwen-3-0.6B/original/qwen3_0_6b_bf16.pte`; -const QWEN3_0_6B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/qwen-3-0.6B/quantized/qwen3_0_6b_8da4w.pte`; -const QWEN3_1_7B_MODEL = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/qwen-3-1.7B/original/qwen3_1_7b_bf16.pte`; -const QWEN3_1_7B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/qwen-3-1.7B/quantized/qwen3_1_7b_8da4w.pte`; -const QWEN3_4B_MODEL = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/qwen-3-4B/original/qwen3_4b_bf16.pte`; -const QWEN3_4B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/qwen-3-4B/quantized/qwen3_4b_8da4w.pte`; -const QWEN3_TOKENIZER = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const QWEN3_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-3/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const QWEN3_0_6B_MODEL = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/0_6b/xnnpack/qwen_3_0_6b_xnnpack_bf16.pte`; +const QWEN3_0_6B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/0_6b/xnnpack/qwen_3_0_6b_xnnpack_8da4w.pte`; +const QWEN3_1_7B_MODEL = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/1_7b/xnnpack/qwen_3_1_7b_xnnpack_bf16.pte`; +const QWEN3_1_7B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/1_7b/xnnpack/qwen_3_1_7b_xnnpack_8da4w.pte`; +const QWEN3_4B_MODEL = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/4b/xnnpack/qwen_3_4b_xnnpack_bf16.pte`; +const QWEN3_4B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/4b/xnnpack/qwen_3_4b_xnnpack_8da4w.pte`; +const QWEN3_TOKENIZER = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/tokenizer.json`; +const QWEN3_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-3/${VERSION_TAG}/tokenizer_config.json`; // Qwen3's published generation_config.json recommends temperature=0.6 and // top_p=0.95. We propagate those to every Qwen3 preset so model quality is @@ -162,14 +170,14 @@ export const QWEN3_4B_QUANTIZED = { } as const; // HAMMER 2.1 -const HAMMER2_1_0_5B_MODEL = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/hammer-2.1-0.5B/original/hammer2_1_0_5B_bf16.pte`; -const HAMMER2_1_0_5B_QUANTIZED_MODEL = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/hammer-2.1-0.5B/quantized/hammer2_1_0_5B_8da4w.pte`; -const HAMMER2_1_1_5B_MODEL = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/hammer-2.1-1.5B/original/hammer2_1_1_5B_bf16.pte`; -const HAMMER2_1_1_5B_QUANTIZED_MODEL = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/hammer-2.1-1.5B/quantized/hammer2_1_1_5B_8da4w.pte`; -const HAMMER2_1_3B_MODEL = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/hammer-2.1-3B/original/hammer2_1_3B_bf16.pte`; -const HAMMER2_1_3B_QUANTIZED_MODEL = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/hammer-2.1-3B/quantized/hammer2_1_3B_8da4w.pte`; -const HAMMER2_1_TOKENIZER = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const HAMMER2_1_TOKENIZER_CONFIG = `${URL_PREFIX}-hammer-2.1/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const HAMMER2_1_0_5B_MODEL = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/0_5b/xnnpack/hammer_2_1_0_5b_xnnpack_bf16.pte`; +const HAMMER2_1_0_5B_QUANTIZED_MODEL = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/0_5b/xnnpack/hammer_2_1_0_5b_xnnpack_8da4w.pte`; +const HAMMER2_1_1_5B_MODEL = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/1_5b/xnnpack/hammer_2_1_1_5b_xnnpack_bf16.pte`; +const HAMMER2_1_1_5B_QUANTIZED_MODEL = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/1_5b/xnnpack/hammer_2_1_1_5b_xnnpack_8da4w.pte`; +const HAMMER2_1_3B_MODEL = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/3b/xnnpack/hammer_2_1_3b_xnnpack_bf16.pte`; +const HAMMER2_1_3B_QUANTIZED_MODEL = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/3b/xnnpack/hammer_2_1_3b_xnnpack_8da4w.pte`; +const HAMMER2_1_TOKENIZER = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/tokenizer.json`; +const HAMMER2_1_TOKENIZER_CONFIG = `${URL_PREFIX}-hammer-2.1/${VERSION_TAG}/tokenizer_config.json`; /** * @category Models - LLM @@ -232,14 +240,14 @@ export const HAMMER2_1_3B_QUANTIZED = { } as const; // SMOLLM2 -const SMOLLM2_1_135M_MODEL = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/smolLm-2-135M/original/smolLm2_135M_bf16.pte`; -const SMOLLM2_1_135M_QUANTIZED_MODEL = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/smolLm-2-135M/quantized/smolLm2_135M_8da4w.pte`; -const SMOLLM2_1_360M_MODEL = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/smolLm-2-360M/original/smolLm2_360M_bf16.pte`; -const SMOLLM2_1_360M_QUANTIZED_MODEL = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/smolLm-2-360M/quantized/smolLm2_360M_8da4w.pte`; -const SMOLLM2_1_1_7B_MODEL = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/smolLm-2-1.7B/original/smolLm2_1_7B_bf16.pte`; -const SMOLLM2_1_1_7B_QUANTIZED_MODEL = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/smolLm-2-1.7B/quantized/smolLm2_1_7B_8da4w.pte`; -const SMOLLM2_1_TOKENIZER = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const SMOLLM2_1_TOKENIZER_CONFIG = `${URL_PREFIX}-smolLm-2/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const SMOLLM2_1_135M_MODEL = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/135m/xnnpack/smollm2_135m_xnnpack_bf16.pte`; +const SMOLLM2_1_135M_QUANTIZED_MODEL = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/135m/xnnpack/smollm2_135m_xnnpack_8da4w.pte`; +const SMOLLM2_1_360M_MODEL = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/360m/xnnpack/smollm2_360m_xnnpack_bf16.pte`; +const SMOLLM2_1_360M_QUANTIZED_MODEL = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/360m/xnnpack/smollm2_360m_xnnpack_8da4w.pte`; +const SMOLLM2_1_1_7B_MODEL = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/1_7b/xnnpack/smollm2_1_7b_xnnpack_bf16.pte`; +const SMOLLM2_1_1_7B_QUANTIZED_MODEL = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/1_7b/xnnpack/smollm2_1_7b_xnnpack_8da4w.pte`; +const SMOLLM2_1_TOKENIZER = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/tokenizer.json`; +const SMOLLM2_1_TOKENIZER_CONFIG = `${URL_PREFIX}-smolLm-2/${VERSION_TAG}/tokenizer_config.json`; /** * @category Models - LLM @@ -302,14 +310,14 @@ export const SMOLLM2_1_1_7B_QUANTIZED = { } as const; // QWEN 2.5 -const QWEN2_5_0_5B_MODEL = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/qwen-2.5-0.5B/original/qwen2_5_0_5b_bf16.pte`; -const QWEN2_5_0_5B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/qwen-2.5-0.5B/quantized/qwen2_5_0_5b_8da4w.pte`; -const QWEN2_5_1_5B_MODEL = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/qwen-2.5-1.5B/original/qwen2_5_1_5b_bf16.pte`; -const QWEN2_5_1_5B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/qwen-2.5-1.5B/quantized/qwen2_5_1_5b_8da4w.pte`; -const QWEN2_5_3B_MODEL = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/qwen-2.5-3B/original/qwen2_5_3b_bf16.pte`; -const QWEN2_5_3B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/qwen-2.5-3B/quantized/qwen2_5_3b_8da4w.pte`; -const QWEN2_5_TOKENIZER = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const QWEN2_5_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-2.5/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const QWEN2_5_0_5B_MODEL = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/0_5b/xnnpack/qwen_2_5_0_5b_xnnpack_bf16.pte`; +const QWEN2_5_0_5B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/0_5b/xnnpack/qwen_2_5_0_5b_xnnpack_8da4w.pte`; +const QWEN2_5_1_5B_MODEL = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/1_5b/xnnpack/qwen_2_5_1_5b_xnnpack_bf16.pte`; +const QWEN2_5_1_5B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/1_5b/xnnpack/qwen_2_5_1_5b_xnnpack_8da4w.pte`; +const QWEN2_5_3B_MODEL = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/3b/xnnpack/qwen_2_5_3b_xnnpack_bf16.pte`; +const QWEN2_5_3B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/3b/xnnpack/qwen_2_5_3b_xnnpack_8da4w.pte`; +const QWEN2_5_TOKENIZER = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/tokenizer.json`; +const QWEN2_5_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-2.5/${VERSION_TAG}/tokenizer_config.json`; /** * @category Models - LLM @@ -372,9 +380,9 @@ export const QWEN2_5_3B_QUANTIZED = { } as const; // QWEN3.5-0.8B -const QWEN3_5_0_8B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/Qwen3.5-0.8B/qwen3_5_0_8b_xnnpack_8da4w.pte`; -const QWEN3_5_0_8B_TOKENIZER = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/Qwen3.5-0.8B/tokenizer.json`; -const QWEN3_5_0_8B_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/Qwen3.5-0.8B/tokenizer_config.json`; +const QWEN3_5_0_8B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/0_8b/xnnpack/qwen_3_5_0_8b_xnnpack_8da4w.pte`; +const QWEN3_5_0_8B_TOKENIZER = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/0_8b/tokenizer.json`; +const QWEN3_5_0_8B_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/0_8b/tokenizer_config.json`; /** * @category Models - LLM @@ -387,9 +395,9 @@ export const QWEN3_5_0_8B_QUANTIZED = { } as const; // QWEN3.5-2B -const QWEN3_5_2B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/Qwen3.5-2B/qwen3_5_2b_xnnpack_8da4w.pte`; -const QWEN3_5_2B_TOKENIZER = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/Qwen3.5-2B/tokenizer.json`; -const QWEN3_5_2B_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/Qwen3.5-2B/tokenizer_config.json`; +const QWEN3_5_2B_QUANTIZED_MODEL = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/2b/xnnpack/qwen_3_5_2b_xnnpack_8da4w.pte`; +const QWEN3_5_2B_TOKENIZER = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/2b/tokenizer.json`; +const QWEN3_5_2B_TOKENIZER_CONFIG = `${URL_PREFIX}-qwen-3.5/${VERSION_TAG}/2b/tokenizer_config.json`; /** * @category Models - LLM @@ -402,10 +410,10 @@ export const QWEN3_5_2B_QUANTIZED = { } as const; // PHI 4 -const PHI_4_MINI_4B_MODEL = `${URL_PREFIX}-phi-4-mini/${PREVIOUS_VERSION_TAG}/original/phi-4-mini_bf16.pte`; -const PHI_4_MINI_4B_QUANTIZED_MODEL = `${URL_PREFIX}-phi-4-mini/${PREVIOUS_VERSION_TAG}/quantized/phi-4-mini_8da4w.pte`; -const PHI_4_MINI_TOKENIZER = `${URL_PREFIX}-phi-4-mini/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const PHI_4_MINI_TOKENIZER_CONFIG = `${URL_PREFIX}-phi-4-mini/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const PHI_4_MINI_4B_MODEL = `${URL_PREFIX}-phi-4-mini/${VERSION_TAG}/xnnpack/phi_4_mini_xnnpack_bf16.pte`; +const PHI_4_MINI_4B_QUANTIZED_MODEL = `${URL_PREFIX}-phi-4-mini/${VERSION_TAG}/xnnpack/phi_4_mini_xnnpack_8da4w.pte`; +const PHI_4_MINI_TOKENIZER = `${URL_PREFIX}-phi-4-mini/${VERSION_TAG}/tokenizer.json`; +const PHI_4_MINI_TOKENIZER_CONFIG = `${URL_PREFIX}-phi-4-mini/${VERSION_TAG}/tokenizer_config.json`; /** * @category Models - LLM @@ -428,10 +436,10 @@ export const PHI_4_MINI_4B_QUANTIZED = { } as const; // LFM2.5-1.2B-Instruct -const LFM2_5_1_2B_INSTRUCT_MODEL = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-1.2B-instruct/original/lfm2_5_1_2b_fp16.pte`; -const LFM2_5_1_2B_INSTRUCT_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-1.2B-instruct/quantized/lfm2_5_1_2b_8da4w.pte`; -const LFM2_5_1_2B_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-1.2B-instruct/tokenizer.json`; -const LFM2_5_1_2B_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-1.2B-instruct/tokenizer_config.json`; +const LFM2_5_1_2B_INSTRUCT_MODEL = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/1_2b/xnnpack/lfm_2_5_1_2b_xnnpack_fp16.pte`; +const LFM2_5_1_2B_INSTRUCT_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/1_2b/xnnpack/lfm_2_5_1_2b_xnnpack_8da4w.pte`; +const LFM2_5_1_2B_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/1_2b/tokenizer.json`; +const LFM2_5_1_2B_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/1_2b/tokenizer_config.json`; /** * @category Models - LLM @@ -454,10 +462,10 @@ export const LFM2_5_1_2B_INSTRUCT_QUANTIZED = { } as const; // LFM2.5-350M -const LFM2_5_350M_MODEL = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-350M/xnnpack/lfm2_5_350m_xnnpack_fp16.pte`; -const LFM2_5_350M_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-350M/xnnpack/lfm2_5_350m_xnnpack_8w4da.pte`; -const LFM2_5_350M_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-350M/tokenizer.json`; -const LFM2_5_350M_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-350M/tokenizer_config.json`; +const LFM2_5_350M_MODEL = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/350m/xnnpack/lfm_2_5_350m_xnnpack_fp16.pte`; +const LFM2_5_350M_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/350m/xnnpack/lfm_2_5_350m_xnnpack_8da4w.pte`; +const LFM2_5_350M_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/350m/tokenizer.json`; +const LFM2_5_350M_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/350m/tokenizer_config.json`; /** * @category Models - LLM @@ -480,10 +488,10 @@ export const LFM2_5_350M_QUANTIZED = { } as const; // Bielik-v3.0 -const BIELIK_V3_0_1_5B_MODEL = `${URL_PREFIX}-bielik-v3.0/${PREVIOUS_VERSION_TAG}/bielik-v3.0-1.5B/original/bielik_1_5b_v3_0_instruct_xnnpack_fp16.pte`; -const BIELIK_V3_0_1_5B_QUANTIZED_MODEL = `${URL_PREFIX}-bielik-v3.0/${PREVIOUS_VERSION_TAG}/bielik-v3.0-1.5B/quantized/bielik_1_5b_v3_0_instruct_xnnpack_8da4w.pte`; -const BIELIK_V3_0_TOKENIZER = `${URL_PREFIX}-bielik-v3.0/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const BIELIK_V3_0_TOKENIZER_CONFIG = `${URL_PREFIX}-bielik-v3.0/${PREVIOUS_VERSION_TAG}/tokenizer_config.json`; +const BIELIK_V3_0_1_5B_MODEL = `${URL_PREFIX}-bielik-v3.0/${VERSION_TAG}/xnnpack/bielik_v3_0_1_5b_xnnpack_fp16.pte`; +const BIELIK_V3_0_1_5B_QUANTIZED_MODEL = `${URL_PREFIX}-bielik-v3.0/${VERSION_TAG}/xnnpack/bielik_v3_0_1_5b_xnnpack_8da4w.pte`; +const BIELIK_V3_0_TOKENIZER = `${URL_PREFIX}-bielik-v3.0/${VERSION_TAG}/tokenizer.json`; +const BIELIK_V3_0_TOKENIZER_CONFIG = `${URL_PREFIX}-bielik-v3.0/${VERSION_TAG}/tokenizer_config.json`; /** * @category Models - LLM @@ -506,14 +514,14 @@ export const BIELIK_V3_0_1_5B_QUANTIZED = { } as const; // LFM2.5-VL-1.6B -const LFM2_VL_1_6B_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-VL-1.6B/quantized/lfm2_5_vl_1_6b_8da4w_xnnpack.pte`; -const LFM2_VL_1_6B_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-VL-1.6B/tokenizer.json`; -const LFM2_VL_1_6B_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-VL-1.6B/tokenizer_config.json`; +const LFM2_VL_1_6B_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/vl_1_6b/xnnpack/lfm_2_5_vl_1_6b_xnnpack_8da4w.pte`; +const LFM2_VL_1_6B_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/vl_1_6b/tokenizer.json`; +const LFM2_VL_1_6B_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/vl_1_6b/tokenizer_config.json`; // LFM2.5-VL-450M -const LFM2_VL_450M_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-VL-450M/lfm2_5_vl_450m_8da4w_xnnpack.pte`; -const LFM2_VL_450M_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-VL-450M/tokenizer.json`; -const LFM2_VL_450M_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${PREVIOUS_VERSION_TAG}/lfm2.5-VL-450M/tokenizer_config.json`; +const LFM2_VL_450M_QUANTIZED_MODEL = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/vl_450m/xnnpack/lfm_2_5_vl_450m_xnnpack_8da4w.pte`; +const LFM2_VL_450M_TOKENIZER = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/vl_450m/tokenizer.json`; +const LFM2_VL_450M_TOKENIZER_CONFIG = `${URL_PREFIX}-lfm-2.5/${VERSION_TAG}/vl_450m/tokenizer_config.json`; /** * @category Models - VLM @@ -565,14 +573,18 @@ export const LFM2_VL_1_6B_QUANTIZED = LFM2_5_VL_1_6B_QUANTIZED; export const LFM2_VL_450M_QUANTIZED = LFM2_5_VL_450M_QUANTIZED; // Classification +export const EFFICIENTNET_V2_S_XNNPACK_FP32_MODEL = `${URL_PREFIX}-efficientnet-v2-s/${VERSION_TAG}/xnnpack/efficientnet_v2_s_xnnpack_fp32.pte`; +export const EFFICIENTNET_V2_S_XNNPACK_INT8_MODEL = `${URL_PREFIX}-efficientnet-v2-s/${VERSION_TAG}/xnnpack/efficientnet_v2_s_xnnpack_int8.pte`; +export const EFFICIENTNET_V2_S_COREML_FP32_MODEL = `${URL_PREFIX}-efficientnet-v2-s/${VERSION_TAG}/coreml/efficientnet_v2_s_coreml_fp32.pte`; +export const EFFICIENTNET_V2_S_COREML_FP16_MODEL = `${URL_PREFIX}-efficientnet-v2-s/${VERSION_TAG}/coreml/efficientnet_v2_s_coreml_fp16.pte`; const EFFICIENTNET_V2_S_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-efficientnet-v2-s/${PREVIOUS_VERSION_TAG}/coreml/efficientnet_v2_s_coreml_fp32.pte` - : `${URL_PREFIX}-efficientnet-v2-s/${PREVIOUS_VERSION_TAG}/xnnpack/efficientnet_v2_s_xnnpack_fp32.pte`; + ? EFFICIENTNET_V2_S_COREML_FP32_MODEL + : EFFICIENTNET_V2_S_XNNPACK_FP32_MODEL; const EFFICIENTNET_V2_S_QUANTIZED_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-efficientnet-v2-s/${PREVIOUS_VERSION_TAG}/coreml/efficientnet_v2_s_coreml_fp16.pte` - : `${URL_PREFIX}-efficientnet-v2-s/${PREVIOUS_VERSION_TAG}/xnnpack/efficientnet_v2_s_xnnpack_int8.pte`; + ? EFFICIENTNET_V2_S_COREML_FP16_MODEL + : EFFICIENTNET_V2_S_XNNPACK_INT8_MODEL; /** * @category Models - Classification @@ -591,14 +603,18 @@ export const EFFICIENTNET_V2_S_QUANTIZED = { } as const; // Object detection +export const SSDLITE_320_MOBILENET_V3_LARGE_XNNPACK_FP32_MODEL = `${URL_PREFIX}-ssdlite320-mobilenet-v3-large/${VERSION_TAG}/xnnpack/ssdlite320_mobilenet_v3_large_xnnpack_fp32.pte`; +export const SSDLITE_320_MOBILENET_V3_LARGE_COREML_FP16_MODEL = `${URL_PREFIX}-ssdlite320-mobilenet-v3-large/${VERSION_TAG}/coreml/ssdlite320_mobilenet_v3_large_coreml_fp16.pte`; +export const RF_DETR_NANO_XNNPACK_FP32_MODEL = `${URL_PREFIX}-rfdetr-nano-detector/${VERSION_TAG}/xnnpack/rfdetr_nano_xnnpack_fp32.pte`; +export const RF_DETR_NANO_COREML_INT8_MODEL = `${URL_PREFIX}-rfdetr-nano-detector/${VERSION_TAG}/coreml/rfdetr_nano_coreml_int8.pte`; const SSDLITE_320_MOBILENET_V3_LARGE_MODEL = Platform.OS === 'ios' - ? `${URL_PREFIX}-ssdlite320-mobilenet-v3-large/${PREVIOUS_VERSION_TAG}/coreml/ssdlite320_mobilenet_v3_large_coreml_fp16.pte` - : `${URL_PREFIX}-ssdlite320-mobilenet-v3-large/${PREVIOUS_VERSION_TAG}/xnnpack/ssdlite320_mobilenet_v3_large_xnnpack_fp32.pte`; + ? SSDLITE_320_MOBILENET_V3_LARGE_COREML_FP16_MODEL + : SSDLITE_320_MOBILENET_V3_LARGE_XNNPACK_FP32_MODEL; const RF_DETR_NANO_MODEL = Platform.OS === 'ios' - ? `${URL_PREFIX}-rfdetr-nano-detector/${PREVIOUS_VERSION_TAG}/coreml/rfdetr_n_det_coreml_int8.pte` - : `${URL_PREFIX}-rfdetr-nano-detector/${PREVIOUS_VERSION_TAG}/rfdetr_detector.pte`; + ? RF_DETR_NANO_COREML_INT8_MODEL + : RF_DETR_NANO_XNNPACK_FP32_MODEL; /** * @category Models - Object Detection @@ -617,11 +633,11 @@ export const RF_DETR_NANO = { } as const; // YOLO26 Object Detection -const YOLO26N_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${PREVIOUS_VERSION_TAG}/yolo26n/xnnpack/yolo26n.pte`; -const YOLO26S_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${PREVIOUS_VERSION_TAG}/yolo26s/xnnpack/yolo26s.pte`; -const YOLO26M_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${PREVIOUS_VERSION_TAG}/yolo26m/xnnpack/yolo26m.pte`; -const YOLO26L_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${PREVIOUS_VERSION_TAG}/yolo26l/xnnpack/yolo26l.pte`; -const YOLO26X_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${PREVIOUS_VERSION_TAG}/yolo26x/xnnpack/yolo26x.pte`; +const YOLO26N_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${VERSION_TAG}/n/xnnpack/yolo26_n_xnnpack_fp32.pte`; +const YOLO26S_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${VERSION_TAG}/s/xnnpack/yolo26_s_xnnpack_fp32.pte`; +const YOLO26M_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${VERSION_TAG}/m/xnnpack/yolo26_m_xnnpack_fp32.pte`; +const YOLO26L_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${VERSION_TAG}/l/xnnpack/yolo26_l_xnnpack_fp32.pte`; +const YOLO26X_DETECTION_MODEL = `${URL_PREFIX}-yolo26/${VERSION_TAG}/x/xnnpack/yolo26_x_xnnpack_fp32.pte`; /** * @category Models - Object Detection @@ -664,7 +680,7 @@ export const YOLO26X = { } as const; // YOLO26 Pose Estimation -const YOLO26N_POSE_MODEL = `${URL_PREFIX}-yolo26-pose/${VERSION_TAG}/yolo26n/xnnpack/yolo26n-pose_xnnpack.pte`; +const YOLO26N_POSE_MODEL = `${URL_PREFIX}-yolo26-pose/${VERSION_TAG}/xnnpack/yolo26_pose_n_xnnpack_fp32.pte`; /** * @category Models - Pose Estimation @@ -675,38 +691,63 @@ export const YOLO26N_POSE = { } as const; // Style transfer +/** + * Builds the four `(backend, precision)` URLs for a single style-transfer style. + * @param display - HF repo suffix (e.g. `rain-princess`). + * @param slug - .pte filename token (e.g. `rain_princess`). Differs from + * `display` for styles whose names contain spaces. + * @returns Per-(backend, precision) URLs for the requested style. + */ +export function styleTransferUrls< + const Display extends string, + const Slug extends string, +>(display: Display, slug: Slug) { + return { + xnnpackBase: `${URL_PREFIX}-style-transfer-${display}/${VERSION_TAG}/xnnpack/style_transfer_${slug}_xnnpack_fp32.pte`, + xnnpackQuant: `${URL_PREFIX}-style-transfer-${display}/${VERSION_TAG}/xnnpack/style_transfer_${slug}_xnnpack_int8.pte`, + coremlBase: `${URL_PREFIX}-style-transfer-${display}/${VERSION_TAG}/coreml/style_transfer_${slug}_coreml_fp32.pte`, + coremlQuant: `${URL_PREFIX}-style-transfer-${display}/${VERSION_TAG}/coreml/style_transfer_${slug}_coreml_fp16.pte`, + }; +} +const STYLE_TRANSFER_CANDY_URLS = styleTransferUrls('candy', 'candy'); +const STYLE_TRANSFER_MOSAIC_URLS = styleTransferUrls('mosaic', 'mosaic'); +const STYLE_TRANSFER_RAIN_PRINCESS_URLS = styleTransferUrls( + 'rain-princess', + 'rain_princess' +); +const STYLE_TRANSFER_UDNIE_URLS = styleTransferUrls('udnie', 'udnie'); const STYLE_TRANSFER_CANDY_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-candy/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_candy_coreml_fp32.pte` - : `${URL_PREFIX}-style-transfer-candy/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_candy_xnnpack_fp32.pte`; + ? STYLE_TRANSFER_CANDY_URLS.coremlBase + : STYLE_TRANSFER_CANDY_URLS.xnnpackBase; const STYLE_TRANSFER_CANDY_QUANTIZED_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-candy/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_candy_coreml_fp16.pte` - : `${URL_PREFIX}-style-transfer-candy/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_candy_xnnpack_int8.pte`; + ? STYLE_TRANSFER_CANDY_URLS.coremlQuant + : STYLE_TRANSFER_CANDY_URLS.xnnpackQuant; const STYLE_TRANSFER_MOSAIC_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-mosaic/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_mosaic_coreml_fp32.pte` - : `${URL_PREFIX}-style-transfer-mosaic/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_mosaic_xnnpack_fp32.pte`; + ? STYLE_TRANSFER_MOSAIC_URLS.coremlBase + : STYLE_TRANSFER_MOSAIC_URLS.xnnpackBase; const STYLE_TRANSFER_MOSAIC_QUANTIZED_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-mosaic/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_mosaic_coreml_fp16.pte` - : `${URL_PREFIX}-style-transfer-mosaic/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_mosaic_xnnpack_int8.pte`; + ? STYLE_TRANSFER_MOSAIC_URLS.coremlQuant + : STYLE_TRANSFER_MOSAIC_URLS.xnnpackQuant; const STYLE_TRANSFER_RAIN_PRINCESS_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-rain-princess/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_rain_princess_coreml_fp32.pte` - : `${URL_PREFIX}-style-transfer-rain-princess/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_rain_princess_xnnpack_fp32.pte`; + ? STYLE_TRANSFER_RAIN_PRINCESS_URLS.coremlBase + : STYLE_TRANSFER_RAIN_PRINCESS_URLS.xnnpackBase; const STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-rain-princess/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_rain_princess_coreml_fp16.pte` - : `${URL_PREFIX}-style-transfer-rain-princess/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_rain_princess_xnnpack_int8.pte`; + ? STYLE_TRANSFER_RAIN_PRINCESS_URLS.coremlQuant + : STYLE_TRANSFER_RAIN_PRINCESS_URLS.xnnpackQuant; const STYLE_TRANSFER_UDNIE_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-udnie/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_udnie_coreml_fp32.pte` - : `${URL_PREFIX}-style-transfer-udnie/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_udnie_xnnpack_fp32.pte`; + ? STYLE_TRANSFER_UDNIE_URLS.coremlBase + : STYLE_TRANSFER_UDNIE_URLS.xnnpackBase; const STYLE_TRANSFER_UDNIE_QUANTIZED_MODEL = Platform.OS === `ios` - ? `${URL_PREFIX}-style-transfer-udnie/${PREVIOUS_VERSION_TAG}/coreml/style_transfer_udnie_coreml_fp16.pte` - : `${URL_PREFIX}-style-transfer-udnie/${PREVIOUS_VERSION_TAG}/xnnpack/style_transfer_udnie_xnnpack_int8.pte`; + ? STYLE_TRANSFER_UDNIE_URLS.coremlQuant + : STYLE_TRANSFER_UDNIE_URLS.xnnpackQuant; /** * @category Models - Style Transfer @@ -773,32 +814,32 @@ export const STYLE_TRANSFER_UDNIE_QUANTIZED = { } as const; // S2T -const WHISPER_TINY_EN_TOKENIZER = `${URL_PREFIX}-whisper-tiny.en/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_TINY_EN_MODEL = `${URL_PREFIX}-whisper-tiny.en/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_tiny_en_xnnpack.pte`; +const WHISPER_TINY_EN_TOKENIZER = `${URL_PREFIX}-whisper-tiny.en/${VERSION_TAG}/tokenizer.json`; +const WHISPER_TINY_EN_MODEL = `${URL_PREFIX}-whisper-tiny.en/${VERSION_TAG}/xnnpack/whisper_tiny_en_xnnpack_fp32.pte`; -const WHISPER_TINY_EN_QUANTIZED_TOKENIZER = `${URL_PREFIX}-whisper-tiny-quantized.en/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_TINY_EN_QUANTIZED_MODEL = `${URL_PREFIX}-whisper-tiny-quantized.en/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_tiny_en_quantized_xnnpack.pte`; +const WHISPER_TINY_EN_QUANTIZED_TOKENIZER = `${URL_PREFIX}-whisper-tiny.en/${VERSION_TAG}/tokenizer.json`; +const WHISPER_TINY_EN_QUANTIZED_MODEL = `${URL_PREFIX}-whisper-tiny.en/${VERSION_TAG}/xnnpack/whisper_tiny_en_xnnpack_int8.pte`; -const WHISPER_BASE_EN_TOKENIZER = `${URL_PREFIX}-whisper-base.en/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_BASE_EN_MODEL = `${URL_PREFIX}-whisper-base.en/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_base_en_xnnpack.pte`; +const WHISPER_BASE_EN_TOKENIZER = `${URL_PREFIX}-whisper-base.en/${VERSION_TAG}/tokenizer.json`; +const WHISPER_BASE_EN_MODEL = `${URL_PREFIX}-whisper-base.en/${VERSION_TAG}/xnnpack/whisper_base_en_xnnpack_fp32.pte`; -const WHISPER_BASE_EN_QUANTIZED_TOKENIZER = `${URL_PREFIX}-whisper-base-quantized.en/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_BASE_EN_QUANTIZED_MODEL = `${URL_PREFIX}-whisper-base-quantized.en/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_base_en_quantized_xnnpack.pte`; +const WHISPER_BASE_EN_QUANTIZED_TOKENIZER = `${URL_PREFIX}-whisper-base.en/${VERSION_TAG}/tokenizer.json`; +const WHISPER_BASE_EN_QUANTIZED_MODEL = `${URL_PREFIX}-whisper-base.en/${VERSION_TAG}/xnnpack/whisper_base_en_xnnpack_int8.pte`; -const WHISPER_SMALL_EN_TOKENIZER = `${URL_PREFIX}-whisper-small.en/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_SMALL_EN_MODEL = `${URL_PREFIX}-whisper-small.en/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_small_en_xnnpack.pte`; +const WHISPER_SMALL_EN_TOKENIZER = `${URL_PREFIX}-whisper-small.en/${VERSION_TAG}/tokenizer.json`; +const WHISPER_SMALL_EN_MODEL = `${URL_PREFIX}-whisper-small.en/${VERSION_TAG}/xnnpack/whisper_small_en_xnnpack_fp32.pte`; -const WHISPER_SMALL_EN_QUANTIZED_TOKENIZER = `${URL_PREFIX}-whisper-small-quantized.en/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_SMALL_EN_QUANTIZED_MODEL = `${URL_PREFIX}-whisper-small-quantized.en/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_small_en_quantized_xnnpack.pte`; +const WHISPER_SMALL_EN_QUANTIZED_TOKENIZER = `${URL_PREFIX}-whisper-small.en/${VERSION_TAG}/tokenizer.json`; +const WHISPER_SMALL_EN_QUANTIZED_MODEL = `${URL_PREFIX}-whisper-small.en/${VERSION_TAG}/xnnpack/whisper_small_en_xnnpack_int8.pte`; -const WHISPER_TINY_TOKENIZER = `${URL_PREFIX}-whisper-tiny/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_TINY_MODEL = `${URL_PREFIX}-whisper-tiny/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_tiny_xnnpack.pte`; +const WHISPER_TINY_TOKENIZER = `${URL_PREFIX}-whisper-tiny/${VERSION_TAG}/tokenizer.json`; +const WHISPER_TINY_MODEL = `${URL_PREFIX}-whisper-tiny/${VERSION_TAG}/xnnpack/whisper_tiny_xnnpack_fp32.pte`; -const WHISPER_BASE_TOKENIZER = `${URL_PREFIX}-whisper-base/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_BASE_MODEL = `${URL_PREFIX}-whisper-base/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_base_xnnpack.pte`; +const WHISPER_BASE_TOKENIZER = `${URL_PREFIX}-whisper-base/${VERSION_TAG}/tokenizer.json`; +const WHISPER_BASE_MODEL = `${URL_PREFIX}-whisper-base/${VERSION_TAG}/xnnpack/whisper_base_xnnpack_fp32.pte`; -const WHISPER_SMALL_TOKENIZER = `${URL_PREFIX}-whisper-small/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const WHISPER_SMALL_MODEL = `${URL_PREFIX}-whisper-small/${PREVIOUS_VERSION_TAG}/xnnpack/whisper_small_xnnpack.pte`; +const WHISPER_SMALL_TOKENIZER = `${URL_PREFIX}-whisper-small/${VERSION_TAG}/tokenizer.json`; +const WHISPER_SMALL_MODEL = `${URL_PREFIX}-whisper-small/${VERSION_TAG}/xnnpack/whisper_small_xnnpack_fp32.pte`; /** * @category Models - Speech To Text @@ -891,18 +932,18 @@ export const WHISPER_SMALL = { } as const; // Semantic Segmentation -const DEEPLAB_V3_RESNET50_MODEL = `${URL_PREFIX}-deeplab-v3/${PREVIOUS_VERSION_TAG}/deeplab-v3-resnet50/xnnpack/deeplabv3_resnet50_xnnpack_fp32.pte`; -const DEEPLAB_V3_RESNET101_MODEL = `${URL_PREFIX}-deeplab-v3/${PREVIOUS_VERSION_TAG}/deeplab-v3-resnet101/xnnpack/deeplabv3_resnet101_xnnpack_fp32.pte`; -const DEEPLAB_V3_MOBILENET_V3_LARGE_MODEL = `${URL_PREFIX}-deeplab-v3/${PREVIOUS_VERSION_TAG}/deeplab-v3-mobilenet-v3-large/xnnpack/deeplabv3_mobilenet_v3_large_xnnpack_fp32.pte`; -const LRASPP_MOBILENET_V3_LARGE_MODEL = `${URL_PREFIX}-lraspp/${PREVIOUS_VERSION_TAG}/xnnpack/lraspp_mobilenet_v3_large_xnnpack_fp32.pte`; -const FCN_RESNET50_MODEL = `${URL_PREFIX}-fcn/${PREVIOUS_VERSION_TAG}/fcn-resnet50/xnnpack/fcn_resnet50_xnnpack_fp32.pte`; -const FCN_RESNET101_MODEL = `${URL_PREFIX}-fcn/${PREVIOUS_VERSION_TAG}/fcn-resnet101/xnnpack/fcn_resnet101_xnnpack_fp32.pte`; -const DEEPLAB_V3_RESNET50_QUANTIZED_MODEL = `${URL_PREFIX}-deeplab-v3/${PREVIOUS_VERSION_TAG}/deeplab-v3-resnet50/xnnpack/deeplabv3_resnet50_xnnpack_int8.pte`; -const DEEPLAB_V3_RESNET101_QUANTIZED_MODEL = `${URL_PREFIX}-deeplab-v3/${PREVIOUS_VERSION_TAG}/deeplab-v3-resnet101/xnnpack/deeplabv3_resnet101_xnnpack_int8.pte`; -const DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED_MODEL = `${URL_PREFIX}-deeplab-v3/${PREVIOUS_VERSION_TAG}/deeplab-v3-mobilenet-v3-large/xnnpack/deeplabv3_mobilenet_v3_large_xnnpack_int8.pte`; -const LRASPP_MOBILENET_V3_LARGE_QUANTIZED_MODEL = `${URL_PREFIX}-lraspp/${PREVIOUS_VERSION_TAG}/xnnpack/lraspp_mobilenet_v3_large_xnnpack_int8.pte`; -const FCN_RESNET50_QUANTIZED_MODEL = `${URL_PREFIX}-fcn/${PREVIOUS_VERSION_TAG}/fcn-resnet50/xnnpack/fcn_resnet50_xnnpack_int8.pte`; -const FCN_RESNET101_QUANTIZED_MODEL = `${URL_PREFIX}-fcn/${PREVIOUS_VERSION_TAG}/fcn-resnet101/xnnpack/fcn_resnet101_xnnpack_int8.pte`; +const DEEPLAB_V3_RESNET50_MODEL = `${URL_PREFIX}-deeplab-v3/${VERSION_TAG}/xnnpack/deeplab_v3_resnet50_xnnpack_fp32.pte`; +const DEEPLAB_V3_RESNET101_MODEL = `${URL_PREFIX}-deeplab-v3/${VERSION_TAG}/xnnpack/deeplab_v3_resnet101_xnnpack_fp32.pte`; +const DEEPLAB_V3_MOBILENET_V3_LARGE_MODEL = `${URL_PREFIX}-deeplab-v3/${VERSION_TAG}/xnnpack/deeplab_v3_mobilenet_v3_large_xnnpack_fp32.pte`; +const LRASPP_MOBILENET_V3_LARGE_MODEL = `${URL_PREFIX}-lraspp/${VERSION_TAG}/xnnpack/lraspp_mobilenet_v3_large_xnnpack_fp32.pte`; +const FCN_RESNET50_MODEL = `${URL_PREFIX}-fcn/${VERSION_TAG}/xnnpack/fcn_resnet50_xnnpack_fp32.pte`; +const FCN_RESNET101_MODEL = `${URL_PREFIX}-fcn/${VERSION_TAG}/xnnpack/fcn_resnet101_xnnpack_fp32.pte`; +const DEEPLAB_V3_RESNET50_QUANTIZED_MODEL = `${URL_PREFIX}-deeplab-v3/${VERSION_TAG}/xnnpack/deeplab_v3_resnet50_xnnpack_int8.pte`; +const DEEPLAB_V3_RESNET101_QUANTIZED_MODEL = `${URL_PREFIX}-deeplab-v3/${VERSION_TAG}/xnnpack/deeplab_v3_resnet101_xnnpack_int8.pte`; +const DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED_MODEL = `${URL_PREFIX}-deeplab-v3/${VERSION_TAG}/xnnpack/deeplab_v3_mobilenet_v3_large_xnnpack_int8.pte`; +const LRASPP_MOBILENET_V3_LARGE_QUANTIZED_MODEL = `${URL_PREFIX}-lraspp/${VERSION_TAG}/xnnpack/lraspp_mobilenet_v3_large_xnnpack_int8.pte`; +const FCN_RESNET50_QUANTIZED_MODEL = `${URL_PREFIX}-fcn/${VERSION_TAG}/xnnpack/fcn_resnet50_xnnpack_int8.pte`; +const FCN_RESNET101_QUANTIZED_MODEL = `${URL_PREFIX}-fcn/${VERSION_TAG}/xnnpack/fcn_resnet101_xnnpack_int8.pte`; /** * @category Models - Semantic Segmentation @@ -1000,7 +1041,7 @@ export const FCN_RESNET101_QUANTIZED = { modelSource: FCN_RESNET101_QUANTIZED_MODEL, } as const; -const SELFIE_SEGMENTATION_MODEL = `${URL_PREFIX}-selfie-segmentation/${PREVIOUS_VERSION_TAG}/xnnpack/selfie-segmentation.pte`; +const SELFIE_SEGMENTATION_MODEL = `${URL_PREFIX}-selfie-segmentation/${VERSION_TAG}/xnnpack/selfie_segmentation_xnnpack_fp32.pte`; /** * @category Models - Semantic Segmentation @@ -1011,14 +1052,18 @@ export const SELFIE_SEGMENTATION = { } as const; // FastSAM Instance Segmentation +export const FASTSAM_S_XNNPACK_FP32_MODEL = `${URL_PREFIX}-fast-sam/${VERSION_TAG}/s/xnnpack/fast_sam_s_xnnpack_fp32.pte`; +export const FASTSAM_S_COREML_FP16_MODEL = `${URL_PREFIX}-fast-sam/${VERSION_TAG}/s/coreml/fast_sam_s_coreml_fp16.pte`; +export const FASTSAM_X_XNNPACK_FP32_MODEL = `${URL_PREFIX}-fast-sam/${VERSION_TAG}/x/xnnpack/fast_sam_x_xnnpack_fp32.pte`; +export const FASTSAM_X_COREML_FP16_MODEL = `${URL_PREFIX}-fast-sam/${VERSION_TAG}/x/coreml/fast_sam_x_coreml_fp16.pte`; const FASTSAM_S_SEG_MODEL = Platform.OS === 'ios' - ? `${URL_PREFIX}-fast-sam/${VERSION_TAG}/fastsam-s/coreml/fastsam_s_coreml_fp16.pte` - : `${URL_PREFIX}-fast-sam/${VERSION_TAG}/fastsam-s/xnnpack/fastsam_s_xnnpack_fp32.pte`; + ? FASTSAM_S_COREML_FP16_MODEL + : FASTSAM_S_XNNPACK_FP32_MODEL; const FASTSAM_X_SEG_MODEL = Platform.OS === 'ios' - ? `${URL_PREFIX}-fast-sam/${VERSION_TAG}/fastsam-x/coreml/fastsam_x_coreml_fp16.pte` - : `${URL_PREFIX}-fast-sam/${VERSION_TAG}/fastsam-x/xnnpack/fastsam_x_xnnpack_fp32.pte`; + ? FASTSAM_X_COREML_FP16_MODEL + : FASTSAM_X_XNNPACK_FP32_MODEL; /** * @category Models - Instance Segmentation @@ -1039,15 +1084,17 @@ export const FASTSAM_X = { /** * @category Models - Instance Segmentation */ -const YOLO26N_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${PREVIOUS_VERSION_TAG}/yolo26n-seg/xnnpack/yolo26n-seg.pte`; -const YOLO26S_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${PREVIOUS_VERSION_TAG}/yolo26s-seg/xnnpack/yolo26s-seg.pte`; -const YOLO26M_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${PREVIOUS_VERSION_TAG}/yolo26m-seg/xnnpack/yolo26m-seg.pte`; -const YOLO26L_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${PREVIOUS_VERSION_TAG}/yolo26l-seg/xnnpack/yolo26l-seg.pte`; -const YOLO26X_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${PREVIOUS_VERSION_TAG}/yolo26x-seg/xnnpack/yolo26x-seg.pte`; +const YOLO26N_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${VERSION_TAG}/n/xnnpack/yolo26_seg_n_xnnpack_fp32.pte`; +const YOLO26S_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${VERSION_TAG}/s/xnnpack/yolo26_seg_s_xnnpack_fp32.pte`; +const YOLO26M_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${VERSION_TAG}/m/xnnpack/yolo26_seg_m_xnnpack_fp32.pte`; +const YOLO26L_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${VERSION_TAG}/l/xnnpack/yolo26_seg_l_xnnpack_fp32.pte`; +const YOLO26X_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${VERSION_TAG}/x/xnnpack/yolo26_seg_x_xnnpack_fp32.pte`; +export const RF_DETR_NANO_SEG_XNNPACK_FP32_MODEL = `${URL_PREFIX}-rfdetr-nano-segmentation/${VERSION_TAG}/xnnpack/rfdetr_nano_xnnpack_fp32.pte`; +export const RF_DETR_NANO_SEG_COREML_INT8_MODEL = `${URL_PREFIX}-rfdetr-nano-segmentation/${VERSION_TAG}/coreml/rfdetr_nano_coreml_int8.pte`; const RF_DETR_NANO_SEG_MODEL = Platform.OS === 'ios' - ? `${URL_PREFIX}-rfdetr-nano-segmentation/${PREVIOUS_VERSION_TAG}/coreml/rfdetr_n_seg_coreml_int8.pte` - : `${URL_PREFIX}-rfdetr-nano-segmentation/${PREVIOUS_VERSION_TAG}/rfdetr_segmentation.pte`; + ? RF_DETR_NANO_SEG_COREML_INT8_MODEL + : RF_DETR_NANO_SEG_XNNPACK_FP32_MODEL; /** * @category Models - Instance Segmentation */ @@ -1097,8 +1144,8 @@ export const RF_DETR_NANO_SEG = { } as const; // Image Embeddings -const CLIP_VIT_BASE_PATCH32_IMAGE_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${PREVIOUS_VERSION_TAG}/xnnpack/clip_vit_base_patch32_vision_xnnpack_fp32.pte`; -const CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${PREVIOUS_VERSION_TAG}/xnnpack/clip_vit_base_patch32_vision_xnnpack_int8.pte`; +const CLIP_VIT_BASE_PATCH32_IMAGE_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${VERSION_TAG}/xnnpack/clip_vit_base_patch32_image_xnnpack_fp32.pte`; +const CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${VERSION_TAG}/xnnpack/clip_vit_base_patch32_image_xnnpack_int8.pte`; /** * @category Models - Image Embeddings @@ -1117,21 +1164,21 @@ export const CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED = { } as const; // Text Embeddings -const ALL_MINILM_L6_V2_MODEL = `${URL_PREFIX}-all-MiniLM-L6-v2/${PREVIOUS_VERSION_TAG}/all-MiniLM-L6-v2_xnnpack.pte`; -const ALL_MINILM_L6_V2_TOKENIZER = `${URL_PREFIX}-all-MiniLM-L6-v2/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const ALL_MPNET_BASE_V2_MODEL = `${URL_PREFIX}-all-mpnet-base-v2/${PREVIOUS_VERSION_TAG}/all-mpnet-base-v2_xnnpack.pte`; -const ALL_MPNET_BASE_V2_TOKENIZER = `${URL_PREFIX}-all-mpnet-base-v2/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const MULTI_QA_MINILM_L6_COS_V1_MODEL = `${URL_PREFIX}-multi-qa-MiniLM-L6-cos-v1/${PREVIOUS_VERSION_TAG}/multi-qa-MiniLM-L6-cos-v1_xnnpack.pte`; -const MULTI_QA_MINILM_L6_COS_V1_TOKENIZER = `${URL_PREFIX}-multi-qa-MiniLM-L6-cos-v1/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const MULTI_QA_MPNET_BASE_DOT_V1_MODEL = `${URL_PREFIX}-multi-qa-mpnet-base-dot-v1/${PREVIOUS_VERSION_TAG}/multi-qa-mpnet-base-dot-v1_xnnpack.pte`; -const MULTI_QA_MPNET_BASE_DOT_V1_TOKENIZER = `${URL_PREFIX}-multi-qa-mpnet-base-dot-v1/${PREVIOUS_VERSION_TAG}/tokenizer.json`; -const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W_MODEL = `${URL_PREFIX}-distiluse-base-multilingual-cased-v2/${VERSION_TAG}/xnnpack/distiluse-base-multilingual-cased-v2_xnnpack_8da4w.pte`; -const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_COREML_MODEL = `${URL_PREFIX}-distiluse-base-multilingual-cased-v2/${VERSION_TAG}/coreml/distiluse-base-multilingual-cased-v2_coreml_fp32.pte`; -const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_TOKENIZER = `${URL_PREFIX}-distiluse-base-multilingual-cased-v2/${VERSION_TAG}/tokenizer.json`; -const PARAPHRASE_MULTILINGUAL_MINILM_L12_V2_QUANTIZED_MODEL = `${URL_PREFIX}-paraphrase-multilingual-MiniLM-L12-v2/${VERSION_TAG}/xnnpack/paraphrase-multilingual-MiniLM-L12-v2_xnnpack_8da4w.pte`; +const ALL_MINILM_L6_V2_MODEL = `${URL_PREFIX}-all-MiniLM-L6-v2/${VERSION_TAG}/xnnpack/all_minilm_l6_v2_xnnpack_fp32.pte`; +const ALL_MINILM_L6_V2_TOKENIZER = `${URL_PREFIX}-all-MiniLM-L6-v2/${VERSION_TAG}/tokenizer.json`; +const ALL_MPNET_BASE_V2_MODEL = `${URL_PREFIX}-all-mpnet-base-v2/${VERSION_TAG}/xnnpack/all_mpnet_base_v2_xnnpack_fp32.pte`; +const ALL_MPNET_BASE_V2_TOKENIZER = `${URL_PREFIX}-all-mpnet-base-v2/${VERSION_TAG}/tokenizer.json`; +const MULTI_QA_MINILM_L6_COS_V1_MODEL = `${URL_PREFIX}-multi-qa-MiniLM-L6-cos-v1/${VERSION_TAG}/xnnpack/multi_qa_minilm_l6_cos_v1_xnnpack_fp32.pte`; +const MULTI_QA_MINILM_L6_COS_V1_TOKENIZER = `${URL_PREFIX}-multi-qa-MiniLM-L6-cos-v1/${VERSION_TAG}/tokenizer.json`; +const MULTI_QA_MPNET_BASE_DOT_V1_MODEL = `${URL_PREFIX}-multi-qa-mpnet-base-dot-v1/${VERSION_TAG}/xnnpack/multi_qa_mpnet_base_dot_v1_xnnpack_fp32.pte`; +const MULTI_QA_MPNET_BASE_DOT_V1_TOKENIZER = `${URL_PREFIX}-multi-qa-mpnet-base-dot-v1/${VERSION_TAG}/tokenizer.json`; +export const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W_MODEL = `${URL_PREFIX}-distiluse-base-multilingual-cased-v2/${VERSION_TAG}/xnnpack/distiluse_base_multilingual_cased_v2_xnnpack_8da4w.pte`; +export const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_COREML_MODEL = `${URL_PREFIX}-distiluse-base-multilingual-cased-v2/${VERSION_TAG}/coreml/distiluse_base_multilingual_cased_v2_coreml_fp32.pte`; +export const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_TOKENIZER = `${URL_PREFIX}-distiluse-base-multilingual-cased-v2/${VERSION_TAG}/tokenizer.json`; +const PARAPHRASE_MULTILINGUAL_MINILM_L12_V2_QUANTIZED_MODEL = `${URL_PREFIX}-paraphrase-multilingual-MiniLM-L12-v2/${VERSION_TAG}/xnnpack/paraphrase_multilingual_minilm_l12_v2_xnnpack_8da4w.pte`; const PARAPHRASE_MULTILINGUAL_MINILM_L12_V2_TOKENIZER = `${URL_PREFIX}-paraphrase-multilingual-MiniLM-L12-v2/${VERSION_TAG}/tokenizer.json`; -const CLIP_VIT_BASE_PATCH32_TEXT_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${PREVIOUS_VERSION_TAG}/xnnpack/clip_vit_base_patch32_text_xnnpack_fp32.pte`; -const CLIP_VIT_BASE_PATCH32_TEXT_TOKENIZER = `${URL_PREFIX}-clip-vit-base-patch32/${PREVIOUS_VERSION_TAG}/tokenizer.json`; +const CLIP_VIT_BASE_PATCH32_TEXT_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${VERSION_TAG}/xnnpack/clip_vit_base_patch32_text_xnnpack_fp32.pte`; +const CLIP_VIT_BASE_PATCH32_TEXT_TOKENIZER = `${URL_PREFIX}-clip-vit-base-patch32/${VERSION_TAG}/tokenizer.json`; /** * @category Models - Text Embeddings @@ -1171,6 +1218,8 @@ export const MULTI_QA_MPNET_BASE_DOT_V1 = { /** * @category Models - Text Embeddings + * @deprecated Use `MODEL_REGISTRY.TEXT_EMBEDDING.DISTILUSE_BASE_MULTILINGUAL_CASED_V2` + * (defaults to xnnpack on Android) or pass `{ backend: 'xnnpack' }`. */ export const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W = { modelName: 'distiluse-base-multilingual-cased-v2-8da4w', @@ -1180,6 +1229,7 @@ export const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W = { /** * @category Models - Text Embeddings + * @deprecated Use `MODEL_REGISTRY.TEXT_EMBEDDING.DISTILUSE_BASE_MULTILINGUAL_CASED_V2({ backend: 'coreml' })`. */ export const DISTILUSE_BASE_MULTILINGUAL_CASED_V2_COREML = { modelName: 'distiluse-base-multilingual-cased-v2-coreml', @@ -1220,7 +1270,7 @@ export const CLIP_VIT_BASE_PATCH32_TEXT = { */ export const PRIVACY_FILTER_OPENAI = { modelName: 'privacy-filter-openai', - modelSource: `${URL_PREFIX}-privacy-filter-openai/${VERSION_TAG}/xnnpack/privacy-filter_xnnpack_8da4w.pte`, + modelSource: `${URL_PREFIX}-privacy-filter-openai/${VERSION_TAG}/xnnpack/privacy_filter_openai_xnnpack_8da4w.pte`, tokenizerSource: `${URL_PREFIX}-privacy-filter-openai/${VERSION_TAG}/tokenizer.json`, labelNames: PRIVACY_FILTER_OPENAI_LABELS, } as const; @@ -1233,7 +1283,7 @@ export const PRIVACY_FILTER_OPENAI = { */ export const PRIVACY_FILTER_NEMOTRON = { modelName: 'privacy-filter-nemotron', - modelSource: `${URL_PREFIX}-privacy-filter-nemotron/${VERSION_TAG}/xnnpack/privacy-filter-nemotron_xnnpack_8da4w.pte`, + modelSource: `${URL_PREFIX}-privacy-filter-nemotron/${VERSION_TAG}/xnnpack/privacy_filter_nemotron_xnnpack_8da4w.pte`, tokenizerSource: `${URL_PREFIX}-privacy-filter-nemotron/${VERSION_TAG}/tokenizer.json`, labelNames: PRIVACY_FILTER_NEMOTRON_LABELS, } as const; @@ -1245,11 +1295,11 @@ export const PRIVACY_FILTER_NEMOTRON = { */ export const BK_SDM_TINY_VPRED_512 = { modelName: 'bk-sdm-tiny-vpred-512', - schedulerSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/scheduler/scheduler_config.json`, - tokenizerSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/tokenizer/tokenizer.json`, - encoderSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/text_encoder/model.pte`, - unetSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/unet/model.pte`, - decoderSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/vae/model.pte`, + schedulerSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/scheduler/scheduler_config.json`, + tokenizerSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/tokenizer/tokenizer.json`, + encoderSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/xnnpack/bk_sdm_tiny_text_encoder_xnnpack_fp32.pte`, + unetSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/xnnpack/bk_sdm_tiny_unet_xnnpack_fp32.pte`, + decoderSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/xnnpack/bk_sdm_tiny_vae_xnnpack_fp32.pte`, } as const; /** @@ -1257,15 +1307,15 @@ export const BK_SDM_TINY_VPRED_512 = { */ export const BK_SDM_TINY_VPRED_256 = { modelName: 'bk-sdm-tiny-vpred-256', - schedulerSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/scheduler/scheduler_config.json`, - tokenizerSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/tokenizer/tokenizer.json`, - encoderSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/text_encoder/model.pte`, - unetSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/unet/model.256.pte`, - decoderSource: `${URL_PREFIX}-bk-sdm-tiny/${PREVIOUS_VERSION_TAG}/vae/model.256.pte`, + schedulerSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/scheduler/scheduler_config.json`, + tokenizerSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/tokenizer/tokenizer.json`, + encoderSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/xnnpack/bk_sdm_tiny_text_encoder_xnnpack_fp32.pte`, + unetSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/xnnpack/bk_sdm_tiny_unet_256_xnnpack_fp32.pte`, + decoderSource: `${URL_PREFIX}-bk-sdm-tiny/${VERSION_TAG}/xnnpack/bk_sdm_tiny_vae_256_xnnpack_fp32.pte`, } as const; // Voice Activity Detection -const FSMN_VAD_MODEL = `${URL_PREFIX}-fsmn-vad/${PREVIOUS_VERSION_TAG}/xnnpack/fsmn-vad_xnnpack.pte`; +const FSMN_VAD_MODEL = `${URL_PREFIX}-fsmn-vad/${VERSION_TAG}/xnnpack/fsmn_vad_xnnpack_fp32.pte`; /** * @category Models - Voice Activity Detection @@ -1275,131 +1325,112 @@ export const FSMN_VAD = { modelSource: FSMN_VAD_MODEL, } as const; -/** - * Registry of all available model configurations. - * - * Use this to discover and enumerate all models shipped with the library. - * @example - * ```ts - * import { MODEL_REGISTRY } from 'react-native-executorch'; - * - * // List all model names - * const names = Object.values(MODEL_REGISTRY).map(m => m.modelName); - * - * // Find models by name substring - * const whisperModels = Object.values(MODEL_REGISTRY) - * .filter(m => m.modelName.includes('whisper')); - * ``` - * @category Utils - */ -export const MODEL_REGISTRY = { - ALL_MODELS: { - LLAMA3_2_3B, - LLAMA3_2_3B_QLORA, - LLAMA3_2_3B_SPINQUANT, - LLAMA3_2_1B, - LLAMA3_2_1B_QLORA, - LLAMA3_2_1B_SPINQUANT, - QWEN3_0_6B, - QWEN3_0_6B_QUANTIZED, - QWEN3_1_7B, - QWEN3_1_7B_QUANTIZED, - QWEN3_4B, - QWEN3_4B_QUANTIZED, - QWEN3_5_0_8B_QUANTIZED, - QWEN3_5_2B_QUANTIZED, - HAMMER2_1_0_5B, - HAMMER2_1_0_5B_QUANTIZED, - HAMMER2_1_1_5B, - HAMMER2_1_1_5B_QUANTIZED, - HAMMER2_1_3B, - HAMMER2_1_3B_QUANTIZED, - SMOLLM2_1_135M, - SMOLLM2_1_135M_QUANTIZED, - SMOLLM2_1_360M, - SMOLLM2_1_360M_QUANTIZED, - SMOLLM2_1_1_7B, - SMOLLM2_1_1_7B_QUANTIZED, - QWEN2_5_0_5B, - QWEN2_5_0_5B_QUANTIZED, - QWEN2_5_1_5B, - QWEN2_5_1_5B_QUANTIZED, - QWEN2_5_3B, - QWEN2_5_3B_QUANTIZED, - PHI_4_MINI_4B, - PHI_4_MINI_4B_QUANTIZED, - LFM2_5_350M, - LFM2_5_350M_QUANTIZED, - LFM2_5_1_2B_INSTRUCT, - LFM2_5_1_2B_INSTRUCT_QUANTIZED, - LFM2_5_VL_1_6B_QUANTIZED, - LFM2_5_VL_450M_QUANTIZED, - LFM2_VL_1_6B_QUANTIZED, - LFM2_VL_450M_QUANTIZED, - BIELIK_V3_0_1_5B, - BIELIK_V3_0_1_5B_QUANTIZED, - EFFICIENTNET_V2_S, - EFFICIENTNET_V2_S_QUANTIZED, - SSDLITE_320_MOBILENET_V3_LARGE, - RF_DETR_NANO, - STYLE_TRANSFER_CANDY, - STYLE_TRANSFER_CANDY_QUANTIZED, - STYLE_TRANSFER_MOSAIC, - STYLE_TRANSFER_MOSAIC_QUANTIZED, - STYLE_TRANSFER_RAIN_PRINCESS, - STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED, - STYLE_TRANSFER_UDNIE, - STYLE_TRANSFER_UDNIE_QUANTIZED, - WHISPER_TINY_EN, - WHISPER_TINY_EN_QUANTIZED, - WHISPER_BASE_EN, - WHISPER_BASE_EN_QUANTIZED, - WHISPER_SMALL_EN, - WHISPER_SMALL_EN_QUANTIZED, - WHISPER_TINY, - WHISPER_BASE, - WHISPER_SMALL, - DEEPLAB_V3_RESNET50, - DEEPLAB_V3_RESNET101, - DEEPLAB_V3_MOBILENET_V3_LARGE, - LRASPP_MOBILENET_V3_LARGE, - FCN_RESNET50, - FCN_RESNET101, - DEEPLAB_V3_RESNET50_QUANTIZED, - DEEPLAB_V3_RESNET101_QUANTIZED, - DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED, - LRASPP_MOBILENET_V3_LARGE_QUANTIZED, - FCN_RESNET50_QUANTIZED, - FCN_RESNET101_QUANTIZED, - SELFIE_SEGMENTATION, - YOLO26N_SEG, - YOLO26S_SEG, - YOLO26M_SEG, - YOLO26L_SEG, - YOLO26X_SEG, - RF_DETR_NANO_SEG, - FASTSAM_S, - FASTSAM_X, - CLIP_VIT_BASE_PATCH32_IMAGE, - CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED, - ALL_MINILM_L6_V2, - ALL_MPNET_BASE_V2, - MULTI_QA_MINILM_L6_COS_V1, - MULTI_QA_MPNET_BASE_DOT_V1, - DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W, - DISTILUSE_BASE_MULTILINGUAL_CASED_V2_COREML, - PARAPHRASE_MULTILINGUAL_MINILM_L12_V2_QUANTIZED, - CLIP_VIT_BASE_PATCH32_TEXT, - BK_SDM_TINY_VPRED_512, - BK_SDM_TINY_VPRED_256, - FSMN_VAD, - PRIVACY_FILTER_OPENAI, - PRIVACY_FILTER_NEMOTRON, - }, -} as const; +// Internal — populates the urlToModelName lookup below. Not exported: the +// typed grouping lives in `./modelRegistry` as MODEL_REGISTRY. +const _ALL_MODELS = [ + LLAMA3_2_3B, + LLAMA3_2_3B_QLORA, + LLAMA3_2_3B_SPINQUANT, + LLAMA3_2_1B, + LLAMA3_2_1B_QLORA, + LLAMA3_2_1B_SPINQUANT, + QWEN3_0_6B, + QWEN3_0_6B_QUANTIZED, + QWEN3_1_7B, + QWEN3_1_7B_QUANTIZED, + QWEN3_4B, + QWEN3_4B_QUANTIZED, + QWEN3_5_0_8B_QUANTIZED, + QWEN3_5_2B_QUANTIZED, + HAMMER2_1_0_5B, + HAMMER2_1_0_5B_QUANTIZED, + HAMMER2_1_1_5B, + HAMMER2_1_1_5B_QUANTIZED, + HAMMER2_1_3B, + HAMMER2_1_3B_QUANTIZED, + SMOLLM2_1_135M, + SMOLLM2_1_135M_QUANTIZED, + SMOLLM2_1_360M, + SMOLLM2_1_360M_QUANTIZED, + SMOLLM2_1_1_7B, + SMOLLM2_1_1_7B_QUANTIZED, + QWEN2_5_0_5B, + QWEN2_5_0_5B_QUANTIZED, + QWEN2_5_1_5B, + QWEN2_5_1_5B_QUANTIZED, + QWEN2_5_3B, + QWEN2_5_3B_QUANTIZED, + PHI_4_MINI_4B, + PHI_4_MINI_4B_QUANTIZED, + LFM2_5_350M, + LFM2_5_350M_QUANTIZED, + LFM2_5_1_2B_INSTRUCT, + LFM2_5_1_2B_INSTRUCT_QUANTIZED, + LFM2_5_VL_1_6B_QUANTIZED, + LFM2_5_VL_450M_QUANTIZED, + BIELIK_V3_0_1_5B, + BIELIK_V3_0_1_5B_QUANTIZED, + EFFICIENTNET_V2_S, + EFFICIENTNET_V2_S_QUANTIZED, + SSDLITE_320_MOBILENET_V3_LARGE, + RF_DETR_NANO, + STYLE_TRANSFER_CANDY, + STYLE_TRANSFER_CANDY_QUANTIZED, + STYLE_TRANSFER_MOSAIC, + STYLE_TRANSFER_MOSAIC_QUANTIZED, + STYLE_TRANSFER_RAIN_PRINCESS, + STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED, + STYLE_TRANSFER_UDNIE, + STYLE_TRANSFER_UDNIE_QUANTIZED, + WHISPER_TINY_EN, + WHISPER_TINY_EN_QUANTIZED, + WHISPER_BASE_EN, + WHISPER_BASE_EN_QUANTIZED, + WHISPER_SMALL_EN, + WHISPER_SMALL_EN_QUANTIZED, + WHISPER_TINY, + WHISPER_BASE, + WHISPER_SMALL, + DEEPLAB_V3_RESNET50, + DEEPLAB_V3_RESNET101, + DEEPLAB_V3_MOBILENET_V3_LARGE, + LRASPP_MOBILENET_V3_LARGE, + FCN_RESNET50, + FCN_RESNET101, + DEEPLAB_V3_RESNET50_QUANTIZED, + DEEPLAB_V3_RESNET101_QUANTIZED, + DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED, + LRASPP_MOBILENET_V3_LARGE_QUANTIZED, + FCN_RESNET50_QUANTIZED, + FCN_RESNET101_QUANTIZED, + SELFIE_SEGMENTATION, + YOLO26N_SEG, + YOLO26S_SEG, + YOLO26M_SEG, + YOLO26L_SEG, + YOLO26X_SEG, + RF_DETR_NANO_SEG, + FASTSAM_S, + FASTSAM_X, + CLIP_VIT_BASE_PATCH32_IMAGE, + CLIP_VIT_BASE_PATCH32_IMAGE_QUANTIZED, + ALL_MINILM_L6_V2, + ALL_MPNET_BASE_V2, + MULTI_QA_MINILM_L6_COS_V1, + MULTI_QA_MPNET_BASE_DOT_V1, + DISTILUSE_BASE_MULTILINGUAL_CASED_V2_8DA4W, + DISTILUSE_BASE_MULTILINGUAL_CASED_V2_COREML, + PARAPHRASE_MULTILINGUAL_MINILM_L12_V2_QUANTIZED, + CLIP_VIT_BASE_PATCH32_TEXT, + BK_SDM_TINY_VPRED_512, + BK_SDM_TINY_VPRED_256, + FSMN_VAD, + PRIVACY_FILTER_OPENAI, + PRIVACY_FILTER_NEMOTRON, +]; const urlToModelName = new Map(); -for (const config of Object.values(MODEL_REGISTRY.ALL_MODELS)) { +for (const config of _ALL_MODELS) { const modelName = config.modelName; for (const [key, value] of Object.entries(config)) { if (key !== 'modelName' && typeof value === 'string') { diff --git a/packages/react-native-executorch/src/constants/ocr/models.ts b/packages/react-native-executorch/src/constants/ocr/models.ts index 990156a8bd..b906f6f12b 100644 --- a/packages/react-native-executorch/src/constants/ocr/models.ts +++ b/packages/react-native-executorch/src/constants/ocr/models.ts @@ -1,11 +1,11 @@ import { alphabets, symbols } from './symbols'; -import { URL_PREFIX, PREVIOUS_VERSION_TAG } from '../versions'; +import { URL_PREFIX, VERSION_TAG } from '../versions'; -const DETECTOR_CRAFT_MODEL = `${URL_PREFIX}-detector-craft/${PREVIOUS_VERSION_TAG}/xnnpack_quantized/xnnpack_craft_quantized.pte`; +const DETECTOR_CRAFT_MODEL = `${URL_PREFIX}-detector-craft/${VERSION_TAG}/xnnpack/craft_xnnpack_int8.pte`; const createHFRecognizerDownloadUrl = (alphabet: keyof typeof alphabets) => - `${URL_PREFIX}-recognizer-crnn.en/${PREVIOUS_VERSION_TAG}/xnnpack/${alphabet}/xnnpack_crnn_${alphabet}.pte`; + `${URL_PREFIX}-recognizer-crnn.en/${VERSION_TAG}/${alphabet}/xnnpack/crnn_${alphabet}_xnnpack_fp32.pte`; const RECOGNIZER_ENGLISH_CRNN = createHFRecognizerDownloadUrl('english'); const RECOGNIZER_LATIN_CRNN = createHFRecognizerDownloadUrl('latin'); diff --git a/packages/react-native-executorch/src/constants/ocr/symbols.ts b/packages/react-native-executorch/src/constants/ocr/symbols.ts index e122958c6b..0947b2e8b7 100644 --- a/packages/react-native-executorch/src/constants/ocr/symbols.ts +++ b/packages/react-native-executorch/src/constants/ocr/symbols.ts @@ -8,7 +8,6 @@ export const alphabets = { ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ªÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿĀāĂ㥹ĆćČčĎďĐđĒēĖėĘęĚěĞğĨĩĪīĮįİıĶķĹĺĻļĽľŁłŃńŅņŇňŒœŔŕŘřŚśŞşŠšŤťŨũŪūŮůŲųŸŹźŻżŽžƏƠơƯưȘșȚțə̇ḌḍḶḷṀṁṂṃṄṅṆṇṬṭẠạẢảẤấẦầẨẩẪẫẬậẮắẰằẲẳẴẵẶặẸẹẺẻẼẽẾếỀềỂểỄễỆệỈỉỊịỌọỎỏỐốỒồỔổỖỗỘộỚớỜờỞởỠỡỢợỤụỦủỨứỪừỬửỮữỰựỲỳỴỵỶỷỸỹ€', japanese: ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~‥…※♪、。々〈〉《》「」『』【】〔〕あぃいうぇえおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろわをんァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロワヱヲンヴヶ・ー一丁七万丈三上下不与丑世丘丙丞両並中串丸丹主乃久之乗乙九也乱乳乾亀了予争事二互五井亘亜亡交亥亨享京亭亮人仁今介仏仕他付仙代令以仮仰仲件任企伊伍伎伏休会伝伯伴伶伸似伽位低住佐佑体何余作佳使例侍侑供依価便係俊俗保信俣修俵倉個倍倒倖候借値倫倭倶偉偏健側偵偽傍傑備債傷働像僧儀優允元兄充先光克免兎児党入全八公六共兵其具典兼内円再写冠冨冬冴冶冷凍凡処凪出刀刃分切刈刑列初判別利制刷券刺刻則削前剛剣剤剥副割創劇力功加助労効勅勇勉動勘務勝勢勤勧勲包化北匠匡区医十千升午半卒卓協南単博占卯印危即卵卸厚原厨厳去参又叉及友双反収取受叡口古句只叫召可台史右叶号司各合吉同名后吏吐向君吟否吸吹吾呂呉告呑周味呼命和咲哀品哉員哲唄唐唯唱商問啓善喜喬喰営嗣嘉噌器四回因団囲図固国國園土圧在圭地坂均坊坐坪垂型垢垣埋城埜域執基埼堀堂堅堤堰報場堺塔塗塚塩塵境墓増墨墳壁壇壊士壬壮声壱売壷変夏夕外多夜夢大天太夫央失夷奇奈奉奏契奥奨女奴好如妃妙妹妻姉始姓委姥姫姿威娘婆婚婦嫌嬉子孔字存孝孟季孤学孫宅宇守安完宏宗官宙定宜宝実客宣室宥宮宰害家容宿寂寄寅密富寒寛寝察寧審寸寺対寿封専射将尊尋導小少尚尭就尺尻尼尽尾尿局居屈屋展属層屯山岐岡岩岬岱岳岸峠峡峨峯峰島峻崇崎崩嵐嵩嵯嶋嶺巌川州巡巣工左巧巨差己巳巴巻巾市布帆希帝師席帯帰帳常帽幅幌幕幡幣干平年幸幹幽幾庁広庄床序底店府度座庫庭庵康庸廃廉廣延建廻弁式弐弓引弘弟弥弦弱張強弾当形彦彩彪彫彬彰影役彼往征径待律後徒従得御復微徳徹心必忌忍志応忠快念怒怜思急性恋恐恒恩恭息恵悌悟悠患悦悪悲情惇惑惟惣想意愚愛感慈態慎慣慧慶憂憲憶懐懸戎成我戒戦戯戸戻房所扇手才打払扶承技投抗折抜抱押担拓拝拡拳拾持指挙振捕捨捷掃排掘掛採探接推掻提揖揚換揮援揺損摂摘摩摺撃撫播撮操擦擬支改攻放政故敏救敗教敢散敦敬数整敵敷文斉斎斐斑斗料斜斤断斯新方於施旅旋族旗日旦旧旨早旬旭旺昂昆昇昌明易星映春昭是昼時晃晋晩普景晴晶智暁暖暗暢暦暮暴曇曙曜曲曳更書曹曽曾替最月有朋服朔朗望朝期木未末本札朱朴杉李杏材村杖杜束条来杭東杵松板析枕林枚果枝枯架柄柊柏柑染柔柚柱柳柴査柿栃栄栖栗校株核根格桂桃案桐桑桜桝桧桶梁梅梓梢梨梯械梶棄棒棚棟森椋植椎検椿楊楓楠楢業楯極楼楽榊榎榛構槌様槙槻樋標模権横樫樹樺樽橋橘機檀櫛欠次欣欧欲欽歌歓止正此武歩歯歳歴死殊残殖段殺殻殿毅母毎毒比毛氏民気水氷永汀汁求汐汗汚江池汰汲決沈沓沖沙沢河油治沼泉泊法波泣泥注泰洋洗洞津洪洲活派流浄浅浜浦浩浪浮浴海消涌涙液涼淀淑淡深淳淵混添清済渉渋渓渕渚減渡渥温測港湊湖湧湯湾湿満源準溜溝溶滅滋滑滝漁漆漏演漢漬潔潜潟潤潮潰澄澤激濃濱瀧瀬灘火灯灰災炉炎炭点為烈烏無焦然焼煙照煮熊熟熱燃燈燕燦燭爆爪父爽爾片版牛牟牧物特犬犯状狂狐狗狩独狭狼猛猪猫献猿獄獅獣玄率玉王玖玲珍珠現球理琉琢琳琴瑚瑛瑞瑠瑳璃環瓜瓦瓶甘甚生産用甫田由甲申男町画界畑畔留畜畝畠略番異畳疾病症痛療発登白百的皆皇皮皿盆益盗盛盟監盤目盲直相省眉看県眞真眠眼着督睦瞬瞳矢知矩短石砂研砲破硫硬碑碧碩確磁磐磨磯礁示礼社祇祈祉祐祖祝神祢祥票祭禁禄禅禎福禰秀私秋科秘秦秩称移稀程税稔稗稚種稲穂積穏穴究空突窓窪立竜章童竪端競竹笑笛笠符第笹筆等筋筑筒答策箇箕算管箱箸節範築篠篤篭簡簾籍米粉粒粕粗粟粥精糖糞糠糸系紀約紅紋納純紗紘紙級素紡索紫細紳紹紺終組経結絡絢給統絵絶絹継続綜維綱網綾綿緋総緑緒線締編緩練縁縄縦縫縮績繁織繰罪置羅羊美群義羽翁習翔翠翼耀老考者耐耕耳耶聖聞聡聴職肇肉肌肝股肥肩育肺背胞胡胤胸能脂脇脈脚脱脳腐腕腫腰腸腹膜膳臣臥臨自臭至致臼興舌舎舘舛舜舞舟航般船艦良色艶芋芙芝芥芦花芳芸芹芽苅苑苔苗若苦苫英茂茄茅茉茜茨茶草荒荘荷荻莉菅菊菌菓菖菜華菱萌萩萱落葉葛葦葵蒔蒲蒸蒼蓋蓑蓬蓮蔦蔭蔵蕗薄薩薫薬薮藁藍藤藻蘇蘭虎虚虫虹虻蚊蛇蛍蛭蜂蜜蝦蝶融螺蟹蟻血衆行術街衛衝衡衣表袋袖被裁裂装裏裕補裟裸製複西要覆覇見規視覚覧親観角解触言計訓託記訪設許訳訴診証評詞詠試詩詰話誉誌認誓誘語誠誤説読課調談請諏論諭諸謙講謝謹識警議譲護讃谷豆豊豚象豪貝貞負財貢貧貨販貫責貯貴買貸費賀賃資賞賢質赤赦走起超越足跡路跳踏身車軌軍軒軟転軸軽載輔輝輪輸辛辞辰農辺辻込迎近返迦迫述迷追退送逃逆透途通速造逢連週進逸遅遊運過道達違遠遣遥適選遺遼避邑那邦邪郁郎郡部郭郵郷都配酒酔酢酸醍醐采釈里重野量金釘釜針釣鈴鉄鉛鉢鉱鉾銀銃銅銘銭鋭鋼錦録鍋鍛鍬鍵鎌鎖鎮鏡鐘鑑長門閉開閑間関閣闇闘阪防阿陀附降限院陣除陰陳陵陶陸険陽隅隆隈隊階随隔際障隠隣隼雀雁雄雅集雑雛離難雨雪雲零雷電震霊霜霞霧露青靖静非面革鞍鞠韓音響頂頃項順須預頓領頭頼題額顔顕願類風飛食飯飲飼飽飾餅養館首香馨馬駄駅駆駐駒駿騎験骨高髪鬼魁魂魅魔魚鮎鮫鮮鯉鯨鳥鳩鳳鳴鴨鴻鵜鶏鶴鷲鷹鷺鹿麓麗麦麻麿黄黒黙鼓鼠鼻齢龍*', - /* eslint-disable camelcase */ zh_sim: ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~。〈〉《》「」『』一丁七万丈三上下不与丐丑专且丕世丘丙业丛东丝丞丢两严丧个丫中丰串临丸丹为主丽举乃久么义之乌乍乎乏乐乒乓乔乖乘乙乜九乞也习乡书乩买乱乳乾了予争事二亍于亏云互亓五井亘亚些亟亡亢交亥亦产亨亩享京亭亮亲亳亵人亿什仁仂仃仄仅仆仇仉今介仍从仑仓仔仕他仗付仙仞仟仡代令以仨仪仫们仰仲仳仵件价任份仿企伉伊伍伎伏伐休众优伙会伛伞伟传伢伤伦伧伪伫伯估伴伶伸伺似伽佃但位低住佐佑体何佗佘余佚佛作佝佞佟你佣佤佥佩佬佯佰佳佴佶佻佼佾使侃侄侈侉例侍侏侑侔侗供依侠侣侥侦侧侨侩侪侬侮侯侵便促俄俅俊俎俏俐俑俗俘俚俜保俞俟信俣俦俨俩俪俭修俯俱俳俸俺俾倌倍倏倒倔倘候倚倜借倡倥倦倨倩倪倬倭债值倾偃假偈偌偎偏偕做停健偬偶偷偻偾偿傀傅傈傍傣傥傧储傩催傲傻像僖僚僦僧僬僭僮僳僵僻儆儇儋儒儡儿兀允元兄充兆先光克免兑兔兕兖党兜兢入全八公六兮兰共关兴兵其具典兹养兼兽冀冁内冈冉册再冒冕冗写军农冠冢冤冥冬冯冰冱冲决况冶冷冻冼冽净凄准凇凉凋凌减凑凛凝几凡凤凫凭凯凰凳凶凸凹出击凼函凿刀刁刃分切刈刊刍刎刑划刖列刘则刚创初删判刨利别刭刮到刳制刷券刹刺刻刽刿剀剁剂剃削剌前剐剑剔剖剜剞剡剥剧剩剪副割剽剿劁劂劈劐劓力劝办功加务劢劣动助努劫劬劭励劲劳劾势勃勇勉勋勐勒勖勘募勤勰勺勾勿匀包匆匈匍匏匐匕化北匙匝匠匡匣匦匪匮匹区医匾匿十千卅升午卉半华协卑卒卓单卖南博卜卞卟占卡卢卣卤卦卧卫卮卯印危即却卵卷卸卺卿厂厄厅历厉压厌厍厕厘厚厝原厢厣厥厦厨厩厮去县叁参又叉及友双反发叔取受变叙叛叟叠口古句另叨叩只叫召叭叮可台叱史右叵叶号司叹叻叼叽吁吃各吆合吉吊同名后吏吐向吒吓吕吗君吝吞吟吠吡吣否吧吨吩含听吭吮启吱吲吴吵吸吹吻吼吾呀呃呆呈告呋呐呓呔呕呖呗员呙呛呜呢呤呦周呱呲味呵呶呷呸呻呼命咀咂咄咆咋和咎咏咐咒咔咕咖咙咚咛咝咣咤咦咧咨咩咪咫咬咭咯咱咳咴咸咻咽咿哀品哂哄哆哇哈哉哌响哎哏哐哑哓哔哕哗哙哚哝哞哟哥哦哧哨哩哪哭哮哲哳哺哼哽哿唁唆唇唉唏唐唑唔唛唠唢唣唤唧唪唬售唯唱唳唷唼唾唿啁啃啄商啉啊啐啕啖啜啡啤啥啦啧啪啬啭啮啵啶啷啸啻啼啾喀喁喂喃善喇喈喉喊喋喏喑喔喘喙喜喝喟喧喱喳喵喷喹喻喽喾嗄嗅嗉嗌嗍嗑嗒嗓嗔嗖嗜嗝嗟嗡嗣嗤嗥嗦嗨嗪嗫嗬嗯嗲嗳嗵嗷嗽嗾嘀嘁嘈嘉嘌嘎嘏嘘嘛嘞嘟嘣嘤嘧嘬嘭嘱嘲嘴嘶嘹嘻嘿噌噍噎噔噗噙噜噢噤器噩噪噫噬噱噶噻噼嚅嚆嚎嚏嚓嚣嚯嚷嚼囊囔囚四囝回囟因囡团囤囫园困囱围囵囹固国图囿圃圄圆圈圉圊圜土圣在圩圪圬圭圮圯地圳圹场圻圾址坂均坊坌坍坎坏坐坑块坚坛坜坝坞坟坠坡坤坦坨坩坪坫坭坯坳坷坻坼垂垃垄垅垆型垌垒垓垛垠垡垢垣垤垦垧垩垫垭垮垲垸埂埃埋城埏埒埔埕埘埙埚埝域埠埤埭埯埴埸培基埽堂堆堇堋堍堑堕堙堞堠堡堤堪堰堵塄塌塍塑塔塘塞塥填塬塾墀墁境墅墉墒墓墙增墟墨墩墼壁壅壑壕壤士壬壮声壳壶壹处备复夏夔夕外夙多夜够夤夥大天太夫夭央夯失头夷夸夹夺夼奁奂奄奇奈奉奋奎奏契奔奕奖套奘奚奠奢奥女奴奶奸她好妁如妃妄妆妇妈妊妍妒妓妖妗妙妞妣妤妥妨妩妪妫妮妯妲妹妻妾姆姊始姐姑姒姓委姗姘姚姜姝姣姥姨姬姹姻姿威娃娄娅娆娇娈娉娌娑娓娘娜娟娠娣娥娩娱娲娴娶娼婀婆婉婊婕婚婢婧婪婴婵婶婷婺婿媒媚媛媪媲媳媵媸媾嫁嫂嫉嫌嫒嫔嫖嫘嫜嫠嫡嫣嫦嫩嫫嫱嬉嬖嬗嬴嬷孀子孑孓孔孕字存孙孚孛孜孝孟孢季孤孥学孩孪孬孰孱孳孵孺孽宁它宄宅宇守安宋完宏宓宕宗官宙定宛宜宝实宠审客宣室宥宦宪宫宰害宴宵家宸容宽宾宿寂寄寅密寇富寐寒寓寝寞察寡寤寥寨寮寰寸对寺寻导寿封射将尉尊小少尔尕尖尘尚尜尝尤尥尧尬就尴尸尹尺尻尼尽尾尿局屁层居屈屉届屋屎屏屐屑展屙属屠屡屣履屦屯山屹屺屿岁岂岈岌岍岐岑岔岖岗岘岙岚岛岢岣岩岫岬岭岱岳岵岷岸岿峁峄峋峒峙峡峤峥峦峨峪峭峰峻崂崃崆崇崎崔崖崛崞崤崦崧崩崭崮崴崽嵇嵊嵋嵌嵘嵛嵝嵩嵫嵬嵯嵴嶂嶙嶝嶷巅巍川州巡巢工左巧巨巩巫差巯己已巳巴巷巽巾币市布帅帆师希帏帐帑帔帕帖帘帙帚帛帜帝带帧席帮帱帷常帻帼帽幂幄幅幌幔幕幛幞幡幢干平年并幸幺幻幼幽广庀庄庆庇床庋序庐庑库应底庖店庙庚府庞废庠庥度座庭庳庵庶康庸庹庾廉廊廒廓廖廛廨廪延廷建廿开弁异弃弄弈弊弋式弑弓引弗弘弛弟张弥弦弧弩弭弯弱弹强弼彀归当录彖彗彘彝形彤彦彩彪彬彭彰影彳彷役彻彼往征徂径待徇很徉徊律後徐徒徕得徘徙徜御徨循徭微徵德徼徽心必忆忉忌忍忏忐忑忒忖志忘忙忝忠忡忤忧忪快忭忮忱念忸忻忽忾忿怀态怂怃怄怅怆怊怍怎怏怒怔怕怖怙怛怜思怠怡急怦性怨怩怪怫怯怵总怼怿恁恂恃恋恍恐恒恕恙恚恝恢恣恤恧恨恩恪恫恬恭息恰恳恶恸恹恺恻恼恽恿悃悄悉悌悍悒悔悖悚悛悝悟悠患悦您悫悬悭悯悱悲悴悸悻悼情惆惊惋惑惕惘惚惜惝惟惠惦惧惨惩惫惬惭惮惯惰想惴惶惹惺愀愁愆愈愉愍愎意愕愚感愠愣愤愦愧愫愿慈慊慌慎慑慕慝慢慧慨慰慵慷憋憎憔憝憧憨憩憬憷憾懂懈懊懋懑懒懦懵懿戆戈戊戋戌戍戎戏成我戒戕或戗战戚戛戟戡戢戥截戬戮戳戴户戽戾房所扁扃扇扈扉手扌才扎扑扒打扔托扛扣扦执扩扪扫扬扭扮扯扰扳扶批扼找承技抄抉把抑抒抓投抖抗折抚抛抟抠抡抢护报抨披抬抱抵抹抻押抽抿拂拄担拆拇拈拉拊拌拍拎拐拒拓拔拖拗拘拙拚招拜拟拢拣拥拦拧拨择括拭拮拯拱拳拴拶拷拼拽拾拿持挂指挈按挎挑挖挚挛挝挞挟挠挡挢挣挤挥挨挪挫振挲挹挺挽捂捃捅捆捉捋捌捍捎捏捐捕捞损捡换捣捧捩捭据捱捶捷捺捻掀掂掇授掉掊掌掎掏掐排掖掘掠探掣接控推掩措掬掭掮掰掳掴掷掸掺掼掾揄揆揉揍揎描提插揖揞揠握揣揩揪揭援揶揸揽揿搀搁搂搅搋搌搏搐搓搔搛搜搞搠搡搦搪搬搭搴携搽摁摄摅摆摇摈摊摒摔摘摞摧摩摭摸摹摺撂撄撅撇撑撒撕撖撙撞撤撩撬播撮撰撵撷撸撺撼擀擂擅操擎擐擒擘擞擢擤擦攀攉攒攘攥攫攮支收攸改攻放政故效敉敌敏救敕敖教敛敝敞敢散敦敫敬数敲整敷文斋斌斐斑斓斗料斛斜斟斡斤斥斧斩斫断斯新方於施旁旃旄旅旆旋旌旎族旒旖旗无既日旦旧旨早旬旭旮旯旰旱时旷旺昀昂昃昆昊昌明昏易昔昕昙昝星映春昧昨昭是昱昴昵昶昼显晁晃晋晌晏晒晓晔晕晖晗晚晟晡晤晦晨普景晰晴晶晷智晾暂暄暇暌暑暖暗暝暧暨暮暴暹暾曙曛曜曝曦曩曰曲曳更曷曹曼曾替最月有朊朋服朐朔朕朗望朝期朦木未末本札术朱朴朵机朽杀杂权杆杈杉杌李杏材村杓杖杜杞束杠条来杨杪杭杯杰杲杳杵杷杼松板极构枇枉枋析枕林枘枚果枝枞枢枣枥枧枨枪枫枭枯枰枳枵架枷枸柁柃柄柏某柑柒染柔柘柙柚柜柝柞柠柢查柩柬柯柰柱柳柴柽柿栀栅标栈栉栊栋栌栎栏树栓栖栗栝校栩株栲栳样核根格栽栾桀桁桂桃桄桅框案桉桊桌桎桐桑桓桔桕桠桡桢档桤桥桦桧桨桩桫桴桶桷梁梃梅梆梏梓梗梢梦梧梨梭梯械梳梵检棂棉棋棍棒棕棘棚棠棣森棰棱棵棹棺棼椁椅椋植椎椐椒椟椠椤椭椰椴椹椽椿楂楔楗楚楝楞楠楣楦楫楮楷楸楹楼榀概榄榆榇榈榉榍榔榕榛榜榧榨榫榭榱榴榷榻槁槊槌槎槐槔槛槟槠槭槲槽槿樊樗樘樟模樨横樯樱樵樽樾橄橇橐橘橙橛橡橥橱橹橼檀檄檎檐檑檗檠檩檫檬欠次欢欣欤欧欲欷欺款歃歆歇歉歌歙止正此步武歧歪歹死歼殁殂殃殄殆殇殉殊残殍殒殓殖殚殛殡殪殳殴段殷殿毁毂毅毋母每毒毓比毕毖毗毙毛毡毪毫毯毳毵毹毽氅氆氇氍氏氐民氓气氕氖氘氙氚氛氟氡氢氤氦氧氨氩氪氮氯氰氲水永氽汀汁求汆汇汉汊汐汔汕汗汛汜汝汞江池污汤汨汩汪汰汲汴汶汹汽汾沁沂沃沅沆沈沉沌沏沐沓沔沙沛沟没沣沤沥沦沧沩沪沫沭沮沱河沸油治沼沽沾沿泄泅泉泊泌泐泓泔法泖泗泛泞泠泡波泣泥注泪泫泮泯泰泱泳泵泷泸泺泻泼泽泾洁洄洇洋洌洎洒洗洙洚洛洞津洧洪洫洮洱洲洳洵洹活洼洽派流浃浅浆浇浈浊测浍济浏浑浒浓浔浙浚浜浞浠浣浦浩浪浮浯浴海浸浼涂涅消涉涌涎涑涓涔涕涛涝涞涟涠涡涣涤润涧涨涩涪涫涮涯液涵涸涿淀淄淅淆淇淋淌淑淖淘淙淝淞淠淡淤淦淫淬淮深淳混淹添淼清渊渌渍渎渐渑渔渖渗渚渝渠渡渣渤渥温渫渭港渲渴游渺湃湄湍湎湔湖湘湛湟湫湮湾湿溃溅溆溉溏源溘溜溟溢溥溧溪溯溱溲溴溶溷溺溻溽滁滂滇滋滏滑滓滔滕滗滚滞滟滠满滢滤滥滦滨滩滴滹漂漆漉漏漓演漕漠漤漩漪漫漭漯漱漳漶漾潆潇潋潍潘潜潞潢潦潭潮潲潴潸潺潼澄澈澉澌澍澎澜澡澧澳澶澹激濂濉濑濒濞濠濡濮濯瀑瀚瀛瀣瀵瀹灌灏灞火灭灯灰灵灶灸灼灾灿炀炅炉炊炎炒炔炕炖炙炜炝炫炬炭炮炯炱炳炷炸点炻炼炽烀烁烂烃烈烊烘烙烛烟烤烦烧烨烩烫烬热烯烷烹烽焉焊焐焓焕焖焘焙焚焦焯焰焱然煅煊煌煎煜煞煤煦照煨煮煲煳煸煺煽熄熊熏熔熘熙熟熠熨熬熵熹燃燎燔燕燠燥燧燮燹爆爝爨爪爬爰爱爵父爷爸爹爻爽爿片版牌牍牒牖牙牛牝牟牡牢牦牧物牮牯牲牵特牺牾犀犁犄犊犋犍犏犒犟犬犯犰犴状犷犸犹狁狂狃狄狈狍狎狐狒狗狙狞狠狡狨狩独狭狮狯狰狱狲狳狴狷狸狺狻狼猁猃猊猎猕猖猗猛猜猝猞猡猢猥猩猪猫猬献猱猴猷猸猹猾猿獍獐獒獗獠獬獭獯獾玄率玉王玎玑玖玛玢玩玫玮环现玲玳玷玺玻珀珂珈珉珊珍珏珐珑珙珞珠珥珧珩班珲球琅理琉琏琐琚琛琢琥琦琨琪琬琮琰琳琴琵琶琼瑁瑕瑗瑙瑚瑛瑜瑞瑟瑭瑰瑶瑾璀璁璃璇璋璎璐璜璞璧璨璩瓒瓜瓞瓠瓢瓣瓤瓦瓮瓯瓴瓶瓷瓿甄甏甑甓甘甙甚甜生甥用甩甫甬甭田由甲申电男甸町画甾畀畅畈畋界畎畏畔留畚畛畜略畦番畲畴畸畹畿疃疆疋疏疑疔疖疗疙疚疝疟疠疡疣疤疥疫疬疮疯疰疱疲疳疴疵疸疹疼疽疾痂痃痄病症痈痉痊痍痒痔痕痘痛痞痢痣痤痦痧痨痪痫痰痱痴痹痼痿瘀瘁瘃瘅瘊瘌瘐瘗瘘瘙瘛瘟瘠瘢瘤瘥瘦瘩瘪瘫瘭瘰瘳瘴瘵瘸瘼瘾瘿癀癃癌癍癔癖癜癞癣癫癯癸登白百皂的皆皇皈皋皎皑皓皖皙皤皮皱皲皴皿盂盅盆盈益盍盎盏盐监盒盔盖盗盘盛盟盥目盯盱盲直相盹盼盾省眄眇眈眉看眍眙眚真眠眢眦眨眩眭眯眵眶眷眸眺眼着睁睃睇睐睑睚睛睡睢督睥睦睨睫睬睹睽睾睿瞀瞄瞅瞌瞍瞎瞑瞒瞟瞠瞢瞥瞧瞩瞪瞬瞰瞳瞵瞻瞽瞿矍矗矛矜矢矣知矧矩矫矬短矮石矶矸矽矾矿砀码砂砉砌砍砑砒研砖砗砘砚砜砝砟砣砥砧砭砰破砷砸砹砺砻砼砾础硅硇硌硎硐硒硕硖硗硝硪硫硬硭确硷硼碇碉碌碍碎碑碓碗碘碚碛碜碟碡碣碥碧碰碱碲碳碴碹碾磁磅磉磊磋磐磔磕磙磨磬磲磴磷磺礁礅礓礞礤礴示礻礼社祀祁祆祈祉祓祖祗祚祛祜祝神祟祠祢祥祧票祭祯祷祸祺禀禁禄禅禊福禚禧禳禹禺离禽禾秀私秃秆秉秋种科秒秕秘租秣秤秦秧秩秫秭积称秸移秽稀稂稆程稍税稔稗稚稞稠稣稳稷稻稼稽稿穆穑穗穰穴究穷穸穹空穿窀突窃窄窈窍窑窒窕窖窗窘窜窝窟窠窥窦窨窬窭窳窿立竖站竞竟章竣童竦竭端竹竺竽竿笃笄笆笈笊笋笏笑笔笕笙笛笞笠笤笥符笨笪笫第笮笱笳笸笺笼笾筅筇等筋筌筏筐筑筒答策筘筚筛筝筠筢筮筱筲筵筷筹筻签简箅箍箐箔箕算箜管箢箦箧箨箩箪箫箬箭箱箴箸篁篆篇篌篑篓篙篚篝篡篥篦篪篮篱篷篼篾簇簋簌簏簖簟簦簧簪簸簿籀籁籍米籴类籼籽粉粑粒粕粗粘粜粝粞粟粤粥粪粮粱粲粳粹粼粽精糁糅糇糈糊糌糍糕糖糗糙糜糟糠糨糯系紊素索紧紫累絮絷綦綮縻繁繇纂纛纠纡红纣纤纥约级纨纩纪纫纬纭纯纰纱纲纳纵纶纷纸纹纺纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绗绘给绚绛络绝绞统绠绡绢绣绥绦继绨绩绪绫续绮绯绰绲绳维绵绶绷绸绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缌缎缏缑缒缓缔缕编缗缘缙缚缛缜缝缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵缶缸缺罂罄罅罐网罔罕罗罘罚罟罡罢罨罩罪置罱署罴罹罾羁羊羌美羔羚羝羞羟羡群羧羯羰羲羸羹羼羽羿翁翅翊翌翎翔翕翘翟翠翡翥翦翩翮翰翱翳翻翼耀老考耄者耆耋而耍耐耒耔耕耖耗耘耙耜耠耢耥耦耧耨耩耪耱耳耵耶耷耸耻耽耿聂聃聆聊聋职聍聒联聘聚聩聪聱聿肃肄肆肇肉肋肌肓肖肘肚肛肝肟肠股肢肤肥肩肪肫肭肮肯肱育肴肷肺肼肽肾肿胀胁胂胃胄胆背胍胎胖胗胙胚胛胜胝胞胡胤胥胧胨胩胪胫胬胭胯胰胱胲胳胴胶胸胺胼能脂脆脉脊脍脎脏脐脑脒脓脔脖脘脚脞脬脯脱脲脶脸脾腆腈腊腋腌腐腑腓腔腕腙腚腠腥腧腩腭腮腰腱腴腹腺腻腼腽腾腿膀膂膈膊膏膑膘膛膜膝膦膨膪膳膺膻臀臁臂臃臆臊臌臣臧自臬臭至致臻臼臾舀舁舂舄舅舆舌舍舐舒舔舛舜舞舟舡舢舣舨航舫般舰舱舳舴舵舶舷舸船舻舾艄艇艋艘艚艟艨艮良艰色艳艴艺艽艾艿节芄芈芊芋芍芎芏芑芒芗芘芙芜芝芟芡芥芦芨芩芪芫芬芭芮芯芰花芳芴芷芸芹芽芾苁苄苇苈苊苋苌苍苎苏苑苒苓苔苕苗苘苛苜苞苟苠苡苣苤若苦苫苯英苴苷苹苻茁茂范茄茅茆茈茉茌茎茏茑茔茕茗茚茛茜茧茨茫茬茭茯茱茳茴茵茶茸茹茼荀荃荆荇草荏荐荑荒荔荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭药荷荸荻荼荽莅莆莉莎莒莓莘莛莜莞莠莨莩莪莫莰莱莲莳莴莶获莸莹莺莼莽菀菁菅菇菊菌菏菔菖菘菜菝菟菠菡菥菩菪菰菱菲菹菽萁萃萄萋萌萍萎萏萑萘萜萝萤营萦萧萨萱萸萼落葆葑著葚葛葜葡董葩葫葬葭葱葳葵葶葸葺蒂蒇蒈蒉蒋蒌蒎蒗蒙蒜蒡蒯蒲蒴蒸蒹蒺蒽蒿蓁蓄蓉蓊蓍蓐蓑蓓蓖蓝蓟蓠蓣蓥蓦蓬蓰蓼蓿蔌蔑蔓蔗蔚蔟蔡蔫蔬蔷蔸蔹蔺蔻蔼蔽蕃蕈蕉蕊蕖蕙蕞蕤蕨蕲蕴蕹蕺蕻蕾薄薅薇薏薛薜薤薨薪薮薯薰薷薹藁藉藏藐藓藕藜藤藩藻藿蘅蘑蘖蘧蘩蘸蘼虎虏虐虑虔虚虞虢虫虬虮虱虹虺虻虼虽虾虿蚀蚁蚂蚊蚋蚌蚍蚓蚕蚜蚝蚣蚤蚧蚨蚩蚬蚯蚰蚱蚴蚶蚺蛀蛄蛆蛇蛉蛊蛋蛎蛏蛐蛑蛔蛘蛙蛛蛞蛟蛤蛩蛭蛮蛰蛱蛲蛳蛴蛸蛹蛾蜀蜂蜃蜇蜈蜉蜊蜍蜒蜓蜕蜗蜘蜚蜜蜞蜡蜢蜣蜥蜩蜮蜱蜴蜷蜻蜾蜿蝇蝈蝉蝌蝎蝓蝗蝙蝠蝣蝤蝥蝮蝰蝴蝶蝻蝼蝽蝾螂螃螅螈螋融螗螟螨螫螬螭螯螳螵螺螽蟀蟆蟊蟋蟑蟒蟛蟠蟥蟪蟮蟹蟾蠃蠊蠓蠕蠖蠡蠢蠲蠹蠼血衄衅行衍衔街衙衡衢衣补表衩衫衬衮衰衲衷衽衾衿袁袂袄袅袈袋袍袒袖袜袢袤被袭袱袼裁裂装裆裉裎裒裔裕裘裙裟裢裣裤裥裨裰裱裳裴裸裹裼裾褂褊褐褒褓褙褚褛褡褥褪褫褰褴褶襁襄襞襟襦襻西要覃覆见观规觅视觇览觉觊觋觌觎觏觐觑角觖觚觜觞解觥触觫觯觳言訇訾詈詹誉誊誓謇警譬计订讣认讥讦讧讨让讪讫训议讯记讲讳讴讵讶讷许讹论讼讽设访诀证诂诃评诅识诈诉诊诋诌词诎诏译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诫诬语诮误诰诱诲诳说诵请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谙谚谛谜谝谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豁豆豇豉豌豕豚象豢豪豫豳豸豹豺貂貅貉貊貌貔貘贝贞负贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赓赔赖赘赙赚赛赜赝赞赠赡赢赣赤赦赧赫赭走赳赴赵赶起趁趄超越趋趑趔趟趣趱足趴趵趸趺趼趾趿跃跄跆跋跌跎跏跑跖跗跚跛距跞跟跣跤跨跪跬路跳践跷跸跹跺跻跽踅踉踊踌踏踔踝踞踟踢踣踩踪踬踮踯踱踵踹踺踽蹀蹁蹂蹄蹇蹈蹉蹊蹋蹑蹒蹙蹦蹩蹬蹭蹯蹰蹲蹴蹶蹼蹿躁躅躇躏躐躔躜躞身躬躯躲躺车轧轨轩轫转轭轮软轰轱轲轳轴轵轶轷轸轺轻轼载轾轿辁辂较辄辅辆辇辈辉辊辋辍辎辏辐辑输辔辕辖辗辘辙辚辛辜辞辟辣辨辩辫辰辱边辽达迁迂迄迅过迈迎运近迓返迕还这进远违连迟迢迤迥迦迨迩迪迫迭迮述迷迸迹追退送适逃逄逅逆选逊逋逍透逐逑递途逖逗通逛逝逞速造逡逢逦逭逮逯逵逶逸逻逼逾遁遂遄遇遍遏遐遑遒道遗遘遛遢遣遥遨遭遮遴遵遽避邀邂邃邈邋邑邓邕邗邙邛邝邡邢那邦邪邬邮邯邰邱邳邴邵邶邸邹邺邻邾郁郄郅郇郊郎郏郐郑郓郗郛郜郝郡郢郦郧部郫郭郯郴郸都郾鄂鄄鄙鄞鄢鄣鄯鄱鄹酃酆酉酊酋酌配酎酏酐酒酗酚酝酞酡酢酣酤酥酩酪酬酮酯酰酱酲酴酵酶酷酸酹酽酾酿醅醇醉醋醌醍醐醑醒醚醛醢醪醭醮醯醴醵醺采釉释里重野量金釜鉴銎銮鋈錾鍪鎏鏊鏖鐾鑫钆钇针钉钊钋钌钍钎钏钐钒钓钔钕钗钙钚钛钜钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钷钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铌铍铎铐铑铒铕铗铘铙铛铜铝铞铟铠铡铢铣铤铥铧铨铩铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锎锏锐锑锒锓锔锕锖锗锘错锚锛锝锞锟锡锢锣锤锥锦锨锩锪锫锬锭键锯锰锱锲锴锵锶锷锸锹锺锻锾锿镀镁镂镄镅镆镇镉镊镌镍镎镏镐镑镒镓镔镖镗镘镛镜镝镞镡镢镣镤镥镦镧镨镩镪镫镬镭镯镰镱镲镳镶长门闩闪闫闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾阀阁阂阃阄阅阆阈阉阊阋阌阍阎阏阐阑阒阔阕阖阗阙阚阜队阡阢阪阮阱防阳阴阵阶阻阼阽阿陀陂附际陆陇陈陉陋陌降限陔陕陛陟陡院除陧陨险陪陬陲陴陵陶陷隅隆隈隋隍随隐隔隗隘隙障隧隰隳隶隼隽难雀雁雄雅集雇雉雌雍雎雏雒雕雠雨雩雪雯雳零雷雹雾需霁霄霆震霈霉霍霎霏霓霖霜霞霪霭霰露霸霹霾青靓靖静靛非靠靡面靥革靳靴靶靼鞅鞋鞍鞑鞒鞘鞠鞣鞫鞭鞯鞲鞴韦韧韩韪韫韬韭音韵韶页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颌颍颏颐频颓颔颖颗题颚颛颜额颞颟颠颡颢颤颥颦颧风飑飒飓飕飘飙飚飞食飧飨餍餐餮饔饕饥饧饨饩饪饫饬饭饮饯饰饱饲饴饵饶饷饺饼饽饿馀馁馄馅馆馇馈馊馋馍馏馐馑馒馓馔馕首馗馘香馥馨马驭驮驯驰驱驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骄骅骆骇骈骊骋验骏骐骑骒骓骖骗骘骚骛骜骝骞骟骠骡骢骣骤骥骧骨骰骶骷骸骺骼髀髁髂髅髋髌髑髓高髡髦髫髭髯髹髻鬃鬈鬏鬓鬟鬣鬯鬲鬻鬼魁魂魃魄魅魇魈魉魍魏魑魔鱼鱿鲁鲂鲅鲆鲇鲈鲋鲍鲎鲐鲑鲔鲚鲛鲜鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲫鲭鲮鲰鲱鲲鲳鲴鲵鲷鲸鲺鲻鲼鲽鳃鳄鳅鳆鳇鳊鳌鳍鳎鳏鳐鳓鳔鳕鳖鳗鳘鳙鳜鳝鳞鳟鳢鸟鸠鸡鸢鸣鸥鸦鸨鸩鸪鸫鸬鸭鸯鸱鸲鸳鸵鸶鸷鸸鸹鸺鸽鸾鸿鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹎鹏鹑鹕鹗鹘鹚鹛鹜鹞鹣鹤鹦鹧鹨鹩鹪鹫鹬鹭鹰鹱鹳鹿麂麇麈麋麒麓麝麟麦麸麻麽麾黄黉黍黎黏黑黔默黛黜黝黟黠黢黥黧黩黯黹黻黼黾鼋鼍鼎鼐鼓鼗鼙鼠鼢鼬鼯鼷鼹鼻鼾齐齑齿龀龃龄龅龆龇龈龉龊龋龌龙龚龛龟龠', korean: diff --git a/packages/react-native-executorch/src/constants/versions.ts b/packages/react-native-executorch/src/constants/versions.ts index 9ce8a726d8..c272d992fe 100644 --- a/packages/react-native-executorch/src/constants/versions.ts +++ b/packages/react-native-executorch/src/constants/versions.ts @@ -2,5 +2,7 @@ export const LIB_VERSION = '0.9.0'; export const URL_PREFIX = 'https://huggingface.co/software-mansion/react-native-executorch'; +// Used by @deprecated constants that still resolve v0.8.0 files (e.g. the +// Llama QLoRA aliases superseded by SpinQuant). export const PREVIOUS_VERSION_TAG = 'resolve/v0.8.0'; export const VERSION_TAG = `resolve/v${LIB_VERSION}`; diff --git a/packages/react-native-executorch/src/controllers/LLMController.ts b/packages/react-native-executorch/src/controllers/LLMController.ts index 5eb8edaed0..dab1cc70ff 100644 --- a/packages/react-native-executorch/src/controllers/LLMController.ts +++ b/packages/react-native-executorch/src/controllers/LLMController.ts @@ -113,7 +113,10 @@ export class LLMController { const modelPath = modelResult?.[0]; if (!tokenizerPath || !tokenizerConfigPath || !modelPath) { - throw new RnExecutorchError(RnExecutorchErrorCode.DownloadInterrupted); + throw new RnExecutorchError( + RnExecutorchErrorCode.DownloadInterrupted, + 'The download has been interrupted. As a result, not every file was downloaded. Please retry the download.' + ); } this.tokenizerConfig = JSON.parse( @@ -257,7 +260,7 @@ export class LLMController { if (this._isGenerating) { throw new RnExecutorchError( RnExecutorchErrorCode.ModelGenerating, - 'You cannot delete the model now. You need to interrupt it first.' + 'You cannot delete the model now. You need ot interrupt it first.' ); } @@ -271,10 +274,16 @@ export class LLMController { public async forward(input: string, imagePaths?: string[]): Promise { if (!this._isReady) { - throw new RnExecutorchError(RnExecutorchErrorCode.ModuleNotLoaded); + throw new RnExecutorchError( + RnExecutorchErrorCode.ModuleNotLoaded, + 'The model is currently not loaded. Please load the model before calling forward().' + ); } if (this._isGenerating) { - throw new RnExecutorchError(RnExecutorchErrorCode.ModelGenerating); + throw new RnExecutorchError( + RnExecutorchErrorCode.ModelGenerating, + 'The model is currently generating. Please wait until previous model run is complete.' + ); } try { this.isGeneratingCallback(true); @@ -360,7 +369,6 @@ export class LLMController { messages, this.tokenizerConfig, tools, - // eslint-disable-next-line camelcase { tools_in_user_message: false, add_generation_prompt: true } ); @@ -389,7 +397,6 @@ export class LLMController { messages, this.tokenizerConfig, this.toolsConfig?.tools, - // eslint-disable-next-line camelcase { tools_in_user_message: false, add_generation_prompt: true } ); const textTokens = this.nativeModule.countTextTokens(rendered); diff --git a/packages/react-native-executorch/src/index.ts b/packages/react-native-executorch/src/index.ts index a33e9bdce0..556d35de02 100644 --- a/packages/react-native-executorch/src/index.ts +++ b/packages/react-native-executorch/src/index.ts @@ -239,6 +239,7 @@ export * from './types/poseEstimation'; export * from './constants/commonVision'; export * from './constants/classification'; export * from './constants/modelUrls'; +export * from './constants/modelRegistry'; export * from './constants/ocr/models'; export * from './constants/tts/models'; export * from './constants/tts/voices';