Skip to content

Commit

Permalink
fix: ollama api response handle strategy, optimize tab button, and ch…
Browse files Browse the repository at this point in the history
…ange model order
  • Loading branch information
zhu-xiaowei committed Jan 24, 2025
1 parent a560722 commit 985bda0
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 121 deletions.
2 changes: 1 addition & 1 deletion react-native/ios/SwiftChat/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string>Support take photos and summarize it</string>
Expand Down
2 changes: 1 addition & 1 deletion react-native/src/api/bedrock-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export const requestAllModels = async (): Promise<AllModel> => {
body: JSON.stringify(bodyObject),
reactNative: { textStreaming: true },
};
const timeoutId = setTimeout(() => controller.abort(), 3000);
const timeoutId = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch(url, options);
clearTimeout(timeoutId);
Expand Down
43 changes: 25 additions & 18 deletions react-native/src/api/ollama-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export const invokeOllamaWithCallBack = async (
model: getTextModel().modelId.split('ollama-')[1],
messages: getOllamaMessages(messages, prompt),
};
console.log(JSON.stringify(bodyObject, null, 2));
const options = {
method: 'POST',
headers: {
Expand Down Expand Up @@ -90,25 +89,33 @@ export const invokeOllamaWithCallBack = async (
const parseStreamData = (chunk: string) => {
let content = '';
let usage: Usage | undefined;

try {
const parsedData: OllamaResponse = JSON.parse(chunk);

if (parsedData.message?.content) {
content = parsedData.message?.content;
const dataChunks = chunk.split('\n');
for (let dataChunk of dataChunks) {
if (!dataChunk.trim()) {
continue;
}
if (dataChunk[0] === '\n') {
dataChunk = dataChunk.slice(1);
}
try {
const parsedData: OllamaResponse = JSON.parse(dataChunk);

if (parsedData.done) {
usage = {
modelName: getTextModel().modelName,
inputTokens: parsedData.prompt_eval_count,
outputTokens: parsedData.eval_count,
totalTokens: parsedData.prompt_eval_count + parsedData.eval_count,
};
if (parsedData.message?.content) {
content += parsedData.message?.content;
}

if (parsedData.done) {
usage = {
modelName: getTextModel().modelName,
inputTokens: parsedData.prompt_eval_count,
outputTokens: parsedData.eval_count,
totalTokens: parsedData.prompt_eval_count + parsedData.eval_count,
};
}
} catch (error) {
console.info('parse error:', error, chunk);
return { error: chunk };
}
} catch (error) {
console.info('parse error:', error, chunk);
return { error: chunk };
}
return { content, usage };
};
Expand Down Expand Up @@ -164,7 +171,7 @@ export const requestAllOllamaModels = async (): Promise<Model[]> => {
signal: controller.signal,
reactNative: { textStreaming: true },
};
const timeoutId = setTimeout(() => controller.abort(), 3000);
const timeoutId = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch(modelsUrl, options);
clearTimeout(timeoutId);
Expand Down
152 changes: 52 additions & 100 deletions react-native/src/settings/SettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {
import { showInfo } from '../chat/util/ToastUtils.ts';
import CustomTextInput from './CustomTextInput.tsx';
import { requestAllOllamaModels } from '../api/ollama-api.ts';
import TabButton from './TabButton';

const initUpgradeInfo: UpgradeInfo = {
needUpgrade: false,
Expand Down Expand Up @@ -167,9 +168,9 @@ function SettingsScreen(): React.JSX.Element {
} else {
response.textModel = [
...response.textModel,
...GPTModels,
...DeepSeekModels,
...ollamaModels,
...DeepSeekModels,
...GPTModels,
];
}
setTextModels(response.textModel);
Expand Down Expand Up @@ -304,28 +305,23 @@ function SettingsScreen(): React.JSX.Element {
);
case 'openai':
return (
<View style={styles.apiKeyContainer}>
<View style={styles.apiKeyInputContainer}>
<CustomTextInput
label="OpenAI API Key"
value={openAIApiKey}
onChangeText={setOpenAIApiKey}
placeholder="Enter OpenAI API Key"
secureTextEntry={true}
/>
</View>
<View
style={[
styles.proxyContainer,
isMac && styles.proxyMacContainer,
]}>
<Text style={styles.proxyLabel}>Proxy</Text>
<>
<CustomTextInput
label="OpenAI API Key"
value={openAIApiKey}
onChangeText={setOpenAIApiKey}
placeholder="Enter OpenAI API Key"
secureTextEntry={true}
/>
<View style={styles.proxySwitchContainer}>
<Text style={styles.proxyLabel}>Use Proxy</Text>
<Switch
style={[isMac ? styles.switch : {}]}
value={openAIProxyEnabled}
onValueChange={toggleOpenAIProxy}
/>
</View>
</View>
</>
);
default:
return null;
Expand All @@ -336,56 +332,26 @@ function SettingsScreen(): React.JSX.Element {
<SafeAreaView style={styles.safeArea}>
<ScrollView style={styles.container}>
<View style={styles.tabContainer}>
<TouchableOpacity
style={[
styles.tab,
selectedTab === 'bedrock' && styles.selectedTab,
]}
onPress={() => setSelectedTab('bedrock')}>
<Text
style={[
styles.tabText,
selectedTab === 'bedrock' && styles.selectedTabText,
]}>
{isMac ? 'Amazon Bedrock' : 'Bedrock'}
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.tab, selectedTab === 'ollama' && styles.selectedTab]}
onPress={() => setSelectedTab('ollama')}>
<Text
style={[
styles.tabText,
selectedTab === 'ollama' && styles.selectedTabText,
]}>
Ollama
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.tab,
selectedTab === 'deepseek' && styles.selectedTab,
]}
onPress={() => setSelectedTab('deepseek')}>
<Text
style={[
styles.tabText,
selectedTab === 'deepseek' && styles.selectedTabText,
]}>
DeepSeek
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.tab, selectedTab === 'openai' && styles.selectedTab]}
onPress={() => setSelectedTab('openai')}>
<Text
style={[
styles.tabText,
selectedTab === 'openai' && styles.selectedTabText,
]}>
OpenAI
</Text>
</TouchableOpacity>
<TabButton
label={isMac ? 'Amazon Bedrock' : 'Bedrock'}
isSelected={selectedTab === 'bedrock'}
onPress={() => setSelectedTab('bedrock')}
/>
<TabButton
label="Ollama"
isSelected={selectedTab === 'ollama'}
onPress={() => setSelectedTab('ollama')}
/>
<TabButton
label="DeepSeek"
isSelected={selectedTab === 'deepseek'}
onPress={() => setSelectedTab('deepseek')}
/>
<TabButton
label="OpenAI"
isSelected={selectedTab === 'openai'}
onPress={() => setSelectedTab('openai')}
/>
</View>

<View style={styles.providerSettingsContainer}>
Expand Down Expand Up @@ -545,6 +511,12 @@ const styles = StyleSheet.create({
marginTop: 10,
marginBottom: 12,
},
proxyLabel: {
fontSize: 14,
fontWeight: '400',
color: 'black',
marginLeft: 2,
},
text: {
fontSize: 14,
fontWeight: '400',
Expand All @@ -566,6 +538,12 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
marginVertical: 10,
},
proxySwitchContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginVertical: 0,
},
itemContainer: {
flexDirection: 'row',
alignItems: 'center',
Expand Down Expand Up @@ -605,12 +583,6 @@ const styles = StyleSheet.create({
proxyMacContainer: {
marginTop: 10,
},
proxyLabel: {
fontSize: 12,
color: 'black',
fontWeight: '500',
marginBottom: 6,
},
tabContainer: {
flexDirection: 'row',
marginBottom: 12,
Expand All @@ -619,34 +591,14 @@ const styles = StyleSheet.create({
backgroundColor: '#f5f5f5',
padding: 6,
},
tab: {
flex: 1,
paddingVertical: 8,
alignItems: 'center',
borderRadius: 6,
},
selectedTab: {
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.2,
shadowRadius: 1.41,
elevation: 2,
},
tabText: {
fontSize: 14,
color: '#666',
fontWeight: '500',
},
selectedTabText: {
color: '#000',
},
providerSettingsContainer: {
marginBottom: 8,
},
switch: {
marginRight: -14,
width: 32,
height: 32,
},
});

export default SettingsScreen;
54 changes: 54 additions & 0 deletions react-native/src/settings/TabButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';

interface TabButtonProps {
label: string;
isSelected: boolean;
onPress: () => void;
}

function TabButton({
label,
isSelected,
onPress,
}: TabButtonProps): React.JSX.Element {
return (
<TouchableOpacity
style={[styles.tab, isSelected && styles.selectedTab]}
onPress={onPress}>
<Text style={[styles.tabText, isSelected && styles.selectedTabText]}>
{label}
</Text>
</TouchableOpacity>
);
}

const styles = StyleSheet.create({
tab: {
flex: 1,
paddingVertical: 8,
alignItems: 'center',
borderRadius: 6,
},
selectedTab: {
backgroundColor: 'white',
shadowColor: 'black',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.2,
shadowRadius: 1.4,
elevation: 2,
},
tabText: {
fontSize: 14,
color: '#666',
fontWeight: '500',
},
selectedTabText: {
color: 'black',
},
});

export default TabButton;
2 changes: 1 addition & 1 deletion react-native/src/storage/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const DefaultTextModel = [
modelName: 'Nova Pro',
modelId: 'us.amazon.nova-pro-v1:0',
},
...GPTModels,
...DeepSeekModels,
...GPTModels,
];

const DefaultImageModel = {
Expand Down

0 comments on commit 985bda0

Please sign in to comment.