Skip to content

Commit 1815fd9

Browse files
committed
chore: Add basic statistics to demo apps
1 parent 654f401 commit 1815fd9

File tree

17 files changed

+248
-0
lines changed

17 files changed

+248
-0
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import { BottomBar } from '../../components/BottomBar';
99
import React, { useContext, useEffect, useState } from 'react';
1010
import { GeneratingContext } from '../../context';
1111
import ScreenWrapper from '../../ScreenWrapper';
12+
import { StatsBar } from '../../components/StatsBar';
1213

1314
export default function ClassificationScreen() {
1415
const [results, setResults] = useState<{ label: string; score: number }[]>(
1516
[]
1617
);
1718
const [imageUri, setImageUri] = useState('');
19+
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
1820

1921
const model = useClassification({ model: EFFICIENTNET_V2_S_QUANTIZED });
2022
const { setGlobalGenerating } = useContext(GeneratingContext);
@@ -34,7 +36,9 @@ export default function ClassificationScreen() {
3436
const runForward = async () => {
3537
if (imageUri) {
3638
try {
39+
const start = Date.now();
3740
const output = await model.forward(imageUri);
41+
setInferenceTime(Date.now() - start);
3842
const top10 = Object.entries(output)
3943
.sort(([, a], [, b]) => (b as number) - (a as number))
4044
.slice(0, 10)
@@ -80,6 +84,7 @@ export default function ClassificationScreen() {
8084
</View>
8185
)}
8286
</View>
87+
<StatsBar inferenceTime={inferenceTime} />
8388
<BottomBar
8489
handleCameraPress={handleCameraPress}
8590
runForward={runForward}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import ImageWithBboxes from '../../components/ImageWithBboxes';
1111
import React, { useContext, useEffect, useState } from 'react';
1212
import { GeneratingContext } from '../../context';
1313
import ScreenWrapper from '../../ScreenWrapper';
14+
import { StatsBar } from '../../components/StatsBar';
1415

1516
export default function ObjectDetectionScreen() {
1617
const [imageUri, setImageUri] = useState('');
@@ -19,6 +20,7 @@ export default function ObjectDetectionScreen() {
1920
width: number;
2021
height: number;
2122
}>();
23+
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
2224

2325
const rfDetr = useObjectDetection({ model: RF_DETR_NANO });
2426
const { setGlobalGenerating } = useContext(GeneratingContext);
@@ -42,7 +44,9 @@ export default function ObjectDetectionScreen() {
4244
const runForward = async () => {
4345
if (imageUri) {
4446
try {
47+
const start = Date.now();
4548
const output = await rfDetr.forward(imageUri);
49+
setInferenceTime(Date.now() - start);
4650
setResults(output);
4751
} catch (e) {
4852
console.error(e);
@@ -81,6 +85,10 @@ export default function ObjectDetectionScreen() {
8185
)}
8286
</View>
8387
</View>
88+
<StatsBar
89+
inferenceTime={inferenceTime}
90+
detectionCount={results.length > 0 ? results.length : null}
91+
/>
8492
<BottomBar
8593
handleCameraPress={handleCameraPress}
8694
runForward={runForward}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes';
77
import React, { useContext, useEffect, useState } from 'react';
88
import { GeneratingContext } from '../../context';
99
import ScreenWrapper from '../../ScreenWrapper';
10+
import { StatsBar } from '../../components/StatsBar';
1011

1112
export default function OCRScreen() {
1213
const [imageUri, setImageUri] = useState('');
@@ -15,6 +16,7 @@ export default function OCRScreen() {
1516
width: number;
1617
height: number;
1718
}>();
19+
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
1820

1921
const model = useOCR({
2022
model: OCR_ENGLISH,
@@ -38,7 +40,9 @@ export default function OCRScreen() {
3840

3941
const runForward = async () => {
4042
try {
43+
const start = Date.now();
4144
const output = await model.forward(imageUri);
45+
setInferenceTime(Date.now() - start);
4246
setResults(output);
4347
} catch (e) {
4448
console.error(e);
@@ -89,6 +93,10 @@ export default function OCRScreen() {
8993
</View>
9094
)}
9195
</View>
96+
<StatsBar
97+
inferenceTime={inferenceTime}
98+
detectionCount={results.length > 0 ? results.length : null}
99+
/>
92100
<BottomBar
93101
handleCameraPress={handleCameraPress}
94102
runForward={runForward}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes';
77
import React, { useContext, useEffect, useState } from 'react';
88
import { GeneratingContext } from '../../context';
99
import ScreenWrapper from '../../ScreenWrapper';
10+
import { StatsBar } from '../../components/StatsBar';
1011

1112
export default function VerticalOCRScree() {
1213
const [imageUri, setImageUri] = useState('');
@@ -15,6 +16,7 @@ export default function VerticalOCRScree() {
1516
width: number;
1617
height: number;
1718
}>();
19+
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
1820
const model = useVerticalOCR({
1921
model: OCR_ENGLISH,
2022
independentCharacters: true,
@@ -38,7 +40,9 @@ export default function VerticalOCRScree() {
3840

3941
const runForward = async () => {
4042
try {
43+
const start = Date.now();
4144
const output = await model.forward(imageUri);
45+
setInferenceTime(Date.now() - start);
4246
setResults(output);
4347
} catch (e) {
4448
console.error(e);
@@ -89,6 +93,10 @@ export default function VerticalOCRScree() {
8993
</View>
9094
)}
9195
</View>
96+
<StatsBar
97+
inferenceTime={inferenceTime}
98+
detectionCount={results.length > 0 ? results.length : null}
99+
/>
92100
<BottomBar
93101
handleCameraPress={handleCameraPress}
94102
runForward={runForward}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { View, StyleSheet, Image } from 'react-native';
1717
import React, { useContext, useEffect, useState } from 'react';
1818
import { GeneratingContext } from '../../context';
1919
import ScreenWrapper from '../../ScreenWrapper';
20+
import { StatsBar } from '../../components/StatsBar';
2021

2122
const numberToColor: number[][] = [
2223
[255, 87, 51], // 0 Red
@@ -52,6 +53,7 @@ export default function SemanticSegmentationScreen() {
5253
const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
5354
const [segImage, setSegImage] = useState<SkImage | null>(null);
5455
const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 });
56+
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
5557

5658
useEffect(() => {
5759
setGlobalGenerating(isGenerating);
@@ -71,6 +73,7 @@ export default function SemanticSegmentationScreen() {
7173
const runForward = async () => {
7274
if (!imageUri || imageSize.width === 0 || imageSize.height === 0) return;
7375
try {
76+
const start = Date.now();
7477
const { width, height } = imageSize;
7578
const output = await forward(imageUri, [], true);
7679
const argmax = output.ARGMAX || [];
@@ -99,6 +102,7 @@ export default function SemanticSegmentationScreen() {
99102
width * 4
100103
);
101104
setSegImage(img);
105+
setInferenceTime(Date.now() - start);
102106
} catch (e) {
103107
console.error(e);
104108
}
@@ -150,6 +154,7 @@ export default function SemanticSegmentationScreen() {
150154
</View>
151155
)}
152156
</View>
157+
<StatsBar inferenceTime={inferenceTime} />
153158
<BottomBar
154159
handleCameraPress={handleCameraPress}
155160
runForward={runForward}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { View, StyleSheet, Image } from 'react-native';
99
import React, { useContext, useEffect, useState } from 'react';
1010
import { GeneratingContext } from '../../context';
1111
import ScreenWrapper from '../../ScreenWrapper';
12+
import { StatsBar } from '../../components/StatsBar';
1213

1314
export default function StyleTransferScreen() {
1415
const model = useStyleTransfer({ model: STYLE_TRANSFER_CANDY_QUANTIZED });
@@ -19,6 +20,7 @@ export default function StyleTransferScreen() {
1920

2021
const [imageUri, setImageUri] = useState('');
2122
const [styledUri, setStyledUri] = useState('');
23+
const [inferenceTime, setInferenceTime] = useState<number | null>(null);
2224

2325
const handleCameraPress = async (isCamera: boolean) => {
2426
const image = await getImage(isCamera);
@@ -32,7 +34,9 @@ export default function StyleTransferScreen() {
3234
const runForward = async () => {
3335
if (imageUri) {
3436
try {
37+
const start = Date.now();
3538
const uri = await model.forward(imageUri, 'url');
39+
setInferenceTime(Date.now() - start);
3640
setStyledUri(uri);
3741
} catch (e) {
3842
console.error(e);
@@ -64,6 +68,7 @@ export default function StyleTransferScreen() {
6468
}
6569
/>
6670
</View>
71+
<StatsBar inferenceTime={inferenceTime} />
6772
<BottomBar
6873
handleCameraPress={handleCameraPress}
6974
runForward={runForward}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ import { GeneratingContext } from '../../context';
1313
import ColorPalette from '../../colors';
1414
import ProgressBar from '../../components/ProgressBar';
1515
import { BottomBarWithTextInput } from '../../components/BottomBarWithTextInput';
16+
import { StatsBar } from '../../components/StatsBar';
1617

1718
export default function TextToImageScreen() {
1819
const [inferenceStepIdx, setInferenceStepIdx] = useState<number>(0);
1920
const [imageTitle, setImageTitle] = useState<string | null>(null);
2021
const [image, setImage] = useState<string | null>(null);
2122
const [steps, setSteps] = useState<number>(40);
23+
const [generationTime, setGenerationTime] = useState<number | null>(null);
2224
const [showTextInput, setShowTextInput] = useState(false);
2325
const [keyboardVisible, setKeyboardVisible] = useState(false);
2426

@@ -53,11 +55,13 @@ export default function TextToImageScreen() {
5355
setImageTitle(input);
5456
setSteps(numSteps);
5557
try {
58+
const start = Date.now();
5659
const output = await model.generate(input, imageSize, steps);
5760
if (!output.length) {
5861
setImageTitle(prevImageTitle);
5962
return;
6063
}
64+
setGenerationTime(Date.now() - start);
6165
setImage(output);
6266
} catch (e) {
6367
console.error(e);
@@ -112,6 +116,7 @@ export default function TextToImageScreen() {
112116
</View>
113117
)}
114118

119+
<StatsBar inferenceTime={generationTime} />
115120
<View style={styles.bottomContainer}>
116121
<BottomBarWithTextInput
117122
runModel={runForward}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from 'react';
2+
import { View, Text, StyleSheet } from 'react-native';
3+
4+
interface Props {
5+
inferenceTime: number | null;
6+
detectionCount?: number | null;
7+
}
8+
9+
export function StatsBar({ inferenceTime, detectionCount }: Props) {
10+
if (inferenceTime === null) return null;
11+
12+
return (
13+
<View style={styles.container}>
14+
<Text style={styles.stat}>Inference: {inferenceTime} ms</Text>
15+
{detectionCount != null && (
16+
<>
17+
<Text style={styles.separator}>·</Text>
18+
<Text style={styles.stat}>
19+
{detectionCount} detection{detectionCount !== 1 ? 's' : ''}
20+
</Text>
21+
</>
22+
)}
23+
</View>
24+
);
25+
}
26+
27+
const styles = StyleSheet.create({
28+
container: {
29+
flexDirection: 'row',
30+
justifyContent: 'center',
31+
alignItems: 'center',
32+
gap: 8,
33+
paddingVertical: 6,
34+
},
35+
stat: {
36+
fontSize: 13,
37+
color: '#334155',
38+
fontWeight: '500',
39+
},
40+
separator: {
41+
fontSize: 13,
42+
color: '#94A3B8',
43+
},
44+
});

apps/llm/app/llm/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import Messages from '../../components/Messages';
1818
import { useIsFocused } from '@react-navigation/native';
1919
import { GeneratingContext } from '../../context';
2020
import Spinner from '../../components/Spinner';
21+
import { useLLMStats } from '../../hooks/useLLMStats';
22+
import { StatsBar } from '../../components/StatsBar';
2123

2224
export default function LLMScreenWrapper() {
2325
const isFocused = useIsFocused();
@@ -31,6 +33,7 @@ function LLMScreen() {
3133
const { setGlobalGenerating } = useContext(GeneratingContext);
3234

3335
const llm = useLLM({ model: LLAMA3_2_1B_SPINQUANT });
36+
const { stats, onMessageSend } = useLLMStats(llm.response, llm.isGenerating);
3437

3538
useEffect(() => {
3639
if (llm.error) {
@@ -43,6 +46,7 @@ function LLMScreen() {
4346
}, [llm.isGenerating, setGlobalGenerating]);
4447

4548
const sendMessage = async () => {
49+
onMessageSend();
4650
setUserInput('');
4751
textInputRef.current?.clear();
4852
try {
@@ -86,6 +90,7 @@ function LLMScreen() {
8690
</View>
8791
)}
8892

93+
<StatsBar stats={stats} />
8994
<View style={styles.bottomContainer}>
9095
<TextInput
9196
autoCorrect={false}

apps/llm/app/llm_structured_output/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
} from 'react-native';
1313
import SendIcon from '../../assets/icons/send_icon.svg';
1414
import Spinner from '../../components/Spinner';
15+
import { useLLMStats } from '../../hooks/useLLMStats';
16+
import { StatsBar } from '../../components/StatsBar';
1517
import {
1618
useLLM,
1719
fixAndValidateStructuredOutput,
@@ -74,6 +76,7 @@ function LLMScreen() {
7476
const { setGlobalGenerating } = useContext(GeneratingContext);
7577

7678
const llm = useLLM({ model: QWEN3_1_7B_QUANTIZED }); // try out 4B model if 1.7B struggles with following structured output
79+
const { stats, onMessageSend } = useLLMStats(llm.response, llm.isGenerating);
7780

7881
useEffect(() => {
7982
setGlobalGenerating(llm.isGenerating);
@@ -124,6 +127,7 @@ function LLMScreen() {
124127
}, [llm.error]);
125128

126129
const sendMessage = async () => {
130+
onMessageSend();
127131
setUserInput('');
128132
textInputRef.current?.clear();
129133
try {
@@ -168,6 +172,7 @@ function LLMScreen() {
168172
</View>
169173
)}
170174

175+
<StatsBar stats={stats} />
171176
<View style={styles.bottomContainer}>
172177
<TextInput
173178
autoCorrect={false}

0 commit comments

Comments
 (0)