Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/pals #205

Merged
merged 19 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
559cd17
feat: add Pals screen and related components
Mukhammadali Feb 10, 2025
7b0b979
chore: set seed default to -1
a-ghorbani Feb 11, 2025
470e653
chore: upgrade llama.rn to 0.5.3-1
a-ghorbani Feb 11, 2025
efc225b
feat: update generatingPrompt for assistant
a-ghorbani Feb 11, 2025
d60b3fe
chore(pals): add experimental to Pals page
a-ghorbani Feb 11, 2025
39f8a0a
chore: make safeParseJSON more robust
a-ghorbani Feb 11, 2025
4e6abf7
fix(pals): use stop words from model settings
a-ghorbani Feb 12, 2025
3cb86ca
chore: move Pals position on sidebar
a-ghorbani Feb 12, 2025
271c2b7
chore(pal): add helper text to systemp prompt and prompt generating m…
a-ghorbani Feb 12, 2025
188e2d2
feat(pals): add stop button for generating systemp prompt
a-ghorbani Feb 12, 2025
bf9419d
chore(pals): make the selected color indicator more prominent
a-ghorbani Feb 12, 2025
9ef5049
fix(pals): respect custom (pals) system prompt even when model templa…
a-ghorbani Feb 14, 2025
5e33e5f
chore: fix unit tests, update sidebar, fix pals bugs
Mukhammadali Feb 19, 2025
c1b7f86
fix: store model object inside pal and add model download functionali…
Mukhammadali Feb 19, 2025
d19abfe
fix: fix sidebar sponsor button issue on smaller screen
Mukhammadali Feb 19, 2025
01138af
fix: unit test random value not supported issue
Mukhammadali Feb 19, 2025
13b1f17
feat: display alert icon on pal card if the default model is not avai…
a-ghorbani Feb 19, 2025
02d3d8b
fix: memory usage tooltip visibility in tests
a-ghorbani Feb 19, 2025
4d4c100
fix: enable stop while generating systemp prompt
a-ghorbani Feb 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,14 @@ import {KeyboardProvider} from 'react-native-keyboard-controller';
import {useTheme} from './src/hooks';
import {Theme} from './src/utils/types';

import {
SidebarContent,
ModelsHeaderRight,
ChatHeader,
HeaderLeft,
} from './src/components';
import {SidebarContent, ModelsHeaderRight, HeaderLeft} from './src/components';
import {
ChatScreen,
ModelsScreen,
SettingsScreen,
BenchmarkScreen,
} from './src/screens';
import {PalsScreen} from './src/screens/PalsScreen';

const Drawer = createDrawerNavigator();

Expand All @@ -42,8 +38,8 @@ const App = observer(() => {
<SafeAreaProvider>
<KeyboardProvider statusBarTranslucent navigationBarTranslucent>
<PaperProvider theme={theme}>
<BottomSheetModalProvider>
<NavigationContainer>
<NavigationContainer>
<BottomSheetModalProvider>
<Drawer.Navigator
useLegacyImplementation={false}
screenOptions={{
Expand All @@ -62,7 +58,7 @@ const App = observer(() => {
name="Chat"
component={gestureHandlerRootHOC(ChatScreen)}
options={{
header: () => <ChatHeader />,
headerShown: false,
}}
/>
<Drawer.Screen
Expand All @@ -74,8 +70,8 @@ const App = observer(() => {
}}
/>
<Drawer.Screen
name="Settings"
component={gestureHandlerRootHOC(SettingsScreen)}
name="Pals (experimental)"
component={gestureHandlerRootHOC(PalsScreen)}
options={{
headerStyle: styles.headerWithoutDivider,
}}
Expand All @@ -87,9 +83,16 @@ const App = observer(() => {
headerStyle: styles.headerWithoutDivider,
}}
/>
<Drawer.Screen
name="Settings"
component={gestureHandlerRootHOC(SettingsScreen)}
options={{
headerStyle: styles.headerWithoutDivider,
}}
/>
</Drawer.Navigator>
</NavigationContainer>
</BottomSheetModalProvider>
</BottomSheetModalProvider>
</NavigationContainer>
</PaperProvider>
</KeyboardProvider>
</SafeAreaProvider>
Expand Down
50 changes: 50 additions & 0 deletions __mocks__/stores/palStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {makeAutoObservable} from 'mobx';
import {v4 as uuidv4} from 'uuid';
import {
AssistantFormData,
RoleplayFormData,
} from '../../src/components/PalsSheets/types';
import {Pal} from '../../src/store/PalStore';

class MockPalStore {
pals: Pal[] = [];

constructor() {
makeAutoObservable(this);
}

addPal = jest.fn((data: AssistantFormData | RoleplayFormData) => {
const newPal = {
id: uuidv4(),
...data,
} as Pal;
this.pals.push(newPal);
});

updatePal = jest.fn(
(id: string, data: Partial<AssistantFormData | RoleplayFormData>) => {
const palIndex = this.pals.findIndex(p => p.id === id);
if (palIndex !== -1) {
const currentPal = this.pals[palIndex];
this.pals[palIndex] = {
...currentPal,
...data,
palType: currentPal.palType,
} as Pal;
}
},
);

deletePal = jest.fn((id: string) => {
const palIndex = this.pals.findIndex(p => p.id === id);
if (palIndex !== -1) {
this.pals.splice(palIndex, 1);
}
});

getPals = jest.fn(() => {
return this.pals;
});
}

export const mockPalStore = new MockPalStore();
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ PODS:
- hermes-engine (0.76.3):
- hermes-engine/Pre-built (= 0.76.3)
- hermes-engine/Pre-built (0.76.3)
- llama-rn (0.4.8-2):
- llama-rn (0.5.3-1):
- React-Core
- nanopb (3.30910.0):
- nanopb/decode (= 3.30910.0)
Expand Down Expand Up @@ -2264,7 +2264,7 @@ SPEC CHECKSUMS:
GoogleAppMeasurement: ee5c2d2242816773fbf79e5b0563f5355ef1c315
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
hermes-engine: 0555a84ea495e8e3b4bde71b597cd87fbb382888
llama-rn: eb844b9cc4b240409b0411f16836416e567374f8
llama-rn: 3c5bd293da5dc2d1c7d37daa736f13b3f89e7bdf
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
RCT-Folly: 84578c8756030547307e4572ab1947de1685c599
Expand Down
34 changes: 33 additions & 1 deletion jest/fixtures/models.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {CompletionParams} from '@pocketpalai/llama.rn';
import {CompletionParams, NativeLlamaContext} from '@pocketpalai/llama.rn';

import {deviceInfo} from './device-info';

Expand All @@ -10,6 +10,38 @@ import {
ModelOrigin,
} from '../../src/utils/types';

export const mockContextModel: NativeLlamaContext['model'] = {
desc: '',
size: 0,
nEmbd: 0,
nParams: 0,
chatTemplates: {
llamaChat: false,
minja: {
default: false,
defaultCaps: {
tools: false,
toolCalls: false,
toolResponses: false,
systemRole: false,
parallelToolCalls: false,
toolCallId: false,
},
toolUse: false,
toolUseCaps: {
tools: false,
toolCalls: false,
toolResponses: false,
systemRole: false,
parallelToolCalls: false,
toolCallId: false,
},
},
},
isChatTemplateSupported: false,
metadata: {},
};

export const mockDefaultCompletionParams: CompletionParams = {
prompt: '',
n_predict: 400,
Expand Down
2 changes: 2 additions & 0 deletions jest/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {mockHFStore} from '../__mocks__/stores/hfStore';
import {mockModelStore} from '../__mocks__/stores/modelStore';
import {mockChatSessionStore} from '../__mocks__/stores/chatSessionStore';
import {benchmarkStore as mockBenchmarkStore} from '../__mocks__/stores/benchmarkStore';
import {mockPalStore} from '../__mocks__/stores/palStore';

jest.mock('@react-native-clipboard/clipboard', () => mockClipboard);

Expand All @@ -68,6 +69,7 @@ jest.mock('../src/store', () => {
chatSessionStore: mockChatSessionStore,
hfStore: mockHFStore,
benchmarkStore: mockBenchmarkStore,
palStore: mockPalStore,
};
});

Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"@dr.pogodin/react-native-fs": "^2.30.3",
"@flyerhq/react-native-link-preview": "^1.6.0",
"@gorhom/bottom-sheet": "^5.0.6",
"@pocketpalai/llama.rn": "^0.4.8-2",
"@hookform/resolvers": "^3.10.0",
"@pocketpalai/llama.rn": "^0.5.3-1",
"@react-native-async-storage/async-storage": "^2.1.0",
"@react-native-clipboard/clipboard": "^1.15.0",
"@react-native-community/blur": "^4.4.1",
Expand All @@ -47,6 +48,7 @@
"mobx-persist-store": "^1.1.5",
"mobx-react": "^9.1.1",
"react": "18.3.1",
"react-hook-form": "^7.54.2",
"react-native": "0.76.3",
"react-native-config": "^1.5.1",
"react-native-device-info": "^13.1.0",
Expand All @@ -68,7 +70,9 @@
"react-native-screens": "^4.4.0",
"react-native-svg": "^15.11.1",
"react-native-vector-icons": "^10.1.0",
"uuid": "^10.0.0"
"tinycolor2": "^1.6.0",
"uuid": "^10.0.0",
"zod": "^3.24.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
Expand Down
3 changes: 3 additions & 0 deletions src/assets/icons/alert.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/benchmark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/chat.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/chevron-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/chevron-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/chevron-up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 20 additions & 9 deletions src/assets/icons/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
export {default as AlertIcon} from './alert.svg';
export {default as BenchmarkIcon} from './benchmark.svg';
export {default as ChatIcon} from './chat.svg';
export {default as ChevronDownIcon} from './chevron-down.svg';
export {default as ChevronRightIcon} from './chevron-right.svg';
export {default as ChevronUpIcon} from './chevron-up.svg';
export {default as ClockFastForwardIcon} from './clock-fast-forward.svg';
export {default as CloseIcon} from './close.svg';
export {default as CopyIcon} from './copy.svg';
export {default as DotsVerticalIcon} from './dots-vertical.svg';
export {default as DuplicateIcon} from './duplicate.svg';
export {default as EditBoxIcon} from './edit-box.svg';
export {default as EditIcon} from './edit.svg';
export {default as GridIcon} from './grid.svg';
export {default as CopyIcon} from './copy.svg';
export {default as ShareIcon} from './share.svg';
export {default as SettingsIcon} from './settings.svg';
export {default as ClockFastForwardIcon} from './clock-fast-forward.svg';
export {default as TrashIcon} from './trash.svg';
export {default as EditBoxIcon} from './edit-box.svg';
export {default as DuplicateIcon} from './duplicate.svg';
export {default as MenuIcon} from './menu.svg';
export {default as ModelIcon} from './model.svg';
export {default as PalIcon} from './pal.svg';
export {default as PencilLineIcon} from './pencil-line.svg';
export {default as PlusIcon} from './plus.svg';
export {default as RefreshIcon} from './refresh.svg';
export {default as ReverseLeftIcon} from './reverse-left.svg';
export {default as CloseIcon} from './close.svg';
export {default as MenuIcon} from './menu.svg';
export {default as SendIcon} from './send.svg';
export {default as SettingsIcon} from './settings.svg';
export {default as StopIcon} from './stop.svg';
export {default as ShareIcon} from './share.svg';
export {default as TrashIcon} from './trash.svg';
6 changes: 6 additions & 0 deletions src/assets/icons/model.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/pal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/send.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/stop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/pocketpal-dark-v2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions src/components/ChatEmptyPlaceholder/ChatEmptyPlaceholder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import {Image, View} from 'react-native';
import {Button, Text} from 'react-native-paper';
import {observer} from 'mobx-react';

import {useTheme} from '../../hooks';
import {createStyles} from './styles';
import {modelStore} from '../../store';
import {useNavigation} from '@react-navigation/native';
import {NavigationProp} from '@react-navigation/native';

interface ChatEmptyPlaceholderProps {
onSelectModel: () => void;
bottomComponentHeight: number;
}

export const ChatEmptyPlaceholder = observer(
({onSelectModel, bottomComponentHeight}: ChatEmptyPlaceholderProps) => {
const theme = useTheme();
const navigation = useNavigation<NavigationProp<any>>();
const styles = createStyles({theme});

const hasAvailableModels = modelStore.availableModels.length > 0;
const hasActiveModel = modelStore.activeModelId !== undefined;

const getContent = () => {
if (!hasAvailableModels) {
return {
title: 'No Models Available',
description: 'Download a model to start chatting with PocketPal',
buttonText: 'Download Model',
onPress: () => {
navigation.navigate('Models');
},
};
}

return {
title: 'Activate Model To Get Started',
description:
'Select the model and download it. After downloading, tap Load next to the model and start chatting.',
buttonText: 'Select Model',
onPress: onSelectModel,
};
};

const {title, description, buttonText, onPress} = getContent();

if (hasActiveModel) {
return null;
}
return (
<View
style={[styles.container, {marginBottom: bottomComponentHeight + 100}]}>
<Image
source={require('../../assets/pocketpal-dark-v2.png')}
style={styles.logo}
resizeMode="contain"
/>
<View>
<Text style={styles.title}>{title}</Text>
<Text style={styles.description}>{description}</Text>
</View>
<Button
mode="contained"
onPress={onPress}
style={styles.button}
loading={modelStore.isContextLoading}
disabled={hasActiveModel}>
{modelStore.isContextLoading ? 'Loading...' : buttonText}
</Button>
</View>
);
},
);
1 change: 1 addition & 0 deletions src/components/ChatEmptyPlaceholder/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {ChatEmptyPlaceholder} from './ChatEmptyPlaceholder';
Loading
Loading