@@ -14,11 +14,12 @@ import { Ionicons } from '@expo/vector-icons';
1414import {
1515 useTextEmbeddings ,
1616 useImageEmbeddings ,
17- CLIP_VIT_BASE_PATCH_32_TEXT_ENCODER ,
18- CLIP_VIT_BASE_PATCH_32_IMAGE_ENCODER_MODEL ,
17+ CLIP_VIT_BASE_PATCH32_TEXT ,
18+ CLIP_VIT_BASE_PATCH32_IMAGE ,
1919} from 'react-native-executorch' ;
2020import { launchImageLibrary } from 'react-native-image-picker' ;
2121import { useIsFocused } from '@react-navigation/native' ;
22+ import { dotProduct } from '../../utils/math' ;
2223
2324export default function ClipEmbeddingsScreenWrapper ( ) {
2425 const isFocused = useIsFocused ( ) ;
@@ -27,11 +28,8 @@ export default function ClipEmbeddingsScreenWrapper() {
2728}
2829
2930function ClipEmbeddingsScreen ( ) {
30- const model = useTextEmbeddings ( { ...CLIP_VIT_BASE_PATCH_32_TEXT_ENCODER } ) ;
31-
32- const imageModel = useImageEmbeddings ( {
33- modelSource : CLIP_VIT_BASE_PATCH_32_IMAGE_ENCODER_MODEL ,
34- } ) ;
31+ const textModel = useTextEmbeddings ( CLIP_VIT_BASE_PATCH32_TEXT ) ;
32+ const imageModel = useImageEmbeddings ( CLIP_VIT_BASE_PATCH32_IMAGE ) ;
3533
3634 const [ inputSentence , setInputSentence ] = useState ( '' ) ;
3735 const [ sentencesWithEmbeddings , setSentencesWithEmbeddings ] = useState <
@@ -41,18 +39,10 @@ function ClipEmbeddingsScreen() {
4139 { sentence : string ; similarity : number } [ ]
4240 > ( [ ] ) ;
4341
44- const dotProduct = ( a : Float32Array , b : Float32Array ) => {
45- let sum = 0 ;
46- for ( let i = 0 ; i < a . length ; i ++ ) {
47- sum += a [ i ] * b [ i ] ;
48- }
49- return sum ;
50- } ;
51-
5242 useEffect (
5343 ( ) => {
5444 const computeEmbeddings = async ( ) => {
55- if ( ! model . isReady ) return ;
45+ if ( ! textModel . isReady ) return ;
5646
5747 const sentences = [
5848 'The weather is lovely today.' ,
@@ -64,7 +54,7 @@ function ClipEmbeddingsScreen() {
6454 try {
6555 const embeddings = [ ] ;
6656 for ( const sentence of sentences ) {
67- const embedding = await model . forward ( sentence ) ;
57+ const embedding = await textModel . forward ( sentence ) ;
6858 embeddings . push ( { sentence, embedding } ) ;
6959 }
7060 setSentencesWithEmbeddings ( embeddings ) ;
@@ -76,14 +66,14 @@ function ClipEmbeddingsScreen() {
7666 computeEmbeddings ( ) ;
7767 } ,
7868 // eslint-disable-next-line react-hooks/exhaustive-deps
79- [ model . isReady ]
69+ [ textModel . isReady ]
8070 ) ;
8171
8272 const checkSimilarities = async ( ) => {
83- if ( ! model . isReady || ! inputSentence . trim ( ) ) return ;
73+ if ( ! textModel . isReady || ! inputSentence . trim ( ) ) return ;
8474
8575 try {
86- const inputEmbedding = await model . forward ( inputSentence ) ;
76+ const inputEmbedding = await textModel . forward ( inputSentence ) ;
8777 const matches = sentencesWithEmbeddings . map (
8878 ( { sentence, embedding } ) => ( {
8979 sentence,
@@ -98,10 +88,10 @@ function ClipEmbeddingsScreen() {
9888 } ;
9989
10090 const addToSentences = async ( ) => {
101- if ( ! model . isReady || ! inputSentence . trim ( ) ) return ;
91+ if ( ! textModel . isReady || ! inputSentence . trim ( ) ) return ;
10292
10393 try {
104- const embedding = await model . forward ( inputSentence ) ;
94+ const embedding = await textModel . forward ( inputSentence ) ;
10595 setSentencesWithEmbeddings ( ( prev ) => [
10696 ...prev ,
10797 { sentence : inputSentence , embedding } ,
@@ -115,7 +105,7 @@ function ClipEmbeddingsScreen() {
115105 } ;
116106
117107 const clearList = async ( ) => {
118- if ( ! model . isReady ) return ;
108+ if ( ! textModel . isReady ) return ;
119109 try {
120110 setSentencesWithEmbeddings ( [ ] ) ;
121111 } catch ( error ) {
@@ -149,16 +139,14 @@ function ClipEmbeddingsScreen() {
149139 }
150140 } ;
151141
152- const getModelStatusText = ( ) => {
153- if ( model . error || imageModel . error ) {
154- return `Oops! Error: ${ model . error || imageModel . error } ` ;
142+ const getModelStatusText = ( model : typeof textModel | typeof imageModel ) => {
143+ if ( model . error ) {
144+ return `Oops! Error: ${ model . error } ` ;
155145 }
156- if ( ! model . isReady || ! imageModel . isReady ) {
157- return `Loading model ${ ( ( ( model . downloadProgress + imageModel . downloadProgress ) / 2 ) * 100 ) . toFixed ( 2 ) } %` ;
146+ if ( ! model . isReady ) {
147+ return `Loading model ${ ( model . downloadProgress * 100 ) . toFixed ( 2 ) } %` ;
158148 }
159- return model . isGenerating || imageModel . isGenerating
160- ? 'Generating...'
161- : 'Model is ready' ;
149+ return model . isGenerating ? 'Generating...' : 'Model is ready' ;
162150 } ;
163151
164152 return (
@@ -169,8 +157,12 @@ function ClipEmbeddingsScreen() {
169157 >
170158 < ScrollView contentContainerStyle = { styles . scrollContainer } >
171159 < Text style = { styles . heading } > Text Embeddings Playground</ Text >
172- < Text style = { styles . sectionTitle } > { getModelStatusText ( ) } </ Text >
173-
160+ < Text style = { styles . sectionTitle } >
161+ Text Model: { getModelStatusText ( textModel ) }
162+ </ Text >
163+ < Text style = { styles . sectionTitle } >
164+ Image Model: { getModelStatusText ( imageModel ) }
165+ </ Text >
174166 < View style = { styles . card } >
175167 < Text style = { styles . sectionTitle } > List of Existing Sentences</ Text >
176168 { sentencesWithEmbeddings . map ( ( item , index ) => (
0 commit comments