Skip to content

Commit ae65915

Browse files
authored
Merge pull request #88 from animalnots/dev
v1.17.0
2 parents 4f8bc5c + 55e3dfd commit ae65915

File tree

13 files changed

+1364
-658
lines changed

13 files changed

+1364
-658
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "better-chatgpt",
33
"private": true,
4-
"version": "1.16.0",
4+
"version": "1.17.0",
55
"type": "module",
66
"homepage": "./",
77
"main": "electron/index.cjs",

public/locales/en/model.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,30 @@
3131
"low": "low",
3232
"high": "high",
3333
"auto": "auto"
34+
},
35+
"customModels": {
36+
"title": "Custom Models",
37+
"addModel": "Add Model",
38+
"modelId": "Model ID (e.g. gpt4)",
39+
"modelName": "Model Name",
40+
"modality": "Model Type",
41+
"textOnly": "Text Only",
42+
"textAndImage": "Text + Image",
43+
"yourCustomModels": "Your Custom Models",
44+
"noModels": "No custom models added yet",
45+
"remove": "Remove",
46+
"advancedSettings": "Advanced Settings",
47+
"showAdvanced": "Show Advanced Settings",
48+
"hideAdvanced": "Hide Advanced Settings",
49+
"contextLength": "Context Length (max tokens)",
50+
"maxCompletionTokens": "Max Completion Tokens",
51+
"pricing": "Pricing (USD)",
52+
"promptPrice": "Prompt Price (per token)",
53+
"completionPrice": "Completion Price (per token)",
54+
"imagePrice": "Image Price (per image)",
55+
"requestPrice": "Request Base Price",
56+
"customLabel": "(custom)",
57+
"streamSupported": "Stream Support",
58+
"streamSupportedDescription": "Enable streaming for real-time response generation"
3459
}
3560
}

public/models.json

Lines changed: 884 additions & 644 deletions
Large diffs are not rendered by default.

src/components/Chat/ChatContent/ChatTitle.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { _defaultChatConfig } from '@constants/chat';
88

99
const ChatTitle = React.memo(() => {
1010
const { t } = useTranslation('model');
11+
const customModels = useStore((state) => state.customModels);
1112
const chat = useStore(
1213
(state) =>
1314
state.chats &&
@@ -38,6 +39,15 @@ const ChatTitle = React.memo(() => {
3839
setChats(updatedChats);
3940
};
4041

42+
const getModelDisplayName = (modelId: string) => {
43+
const isCustom = customModels.some(m => m.id === modelId);
44+
if (isCustom) {
45+
const customModel = customModels.find(m => m.id === modelId);
46+
return `${customModel?.name} ${t('customModels.customLabel', { ns: 'model' })}`;
47+
}
48+
return modelId;
49+
};
50+
4151
// for migrating from old ChatInterface to new ChatInterface (with config)
4252
useEffect(() => {
4353
const chats = useStore.getState().chats;
@@ -57,7 +67,7 @@ const ChatTitle = React.memo(() => {
5767
}}
5868
>
5969
<div className='text-center p-1 rounded-md bg-gray-300/20 dark:bg-gray-900/10 hover:bg-gray-300/50 dark:hover:bg-gray-900/50'>
60-
{t('model')}: {chat.config.model}
70+
{t('model')}: {getModelDisplayName(chat.config.model)}
6171
</div>
6272
<div className='text-center p-1 rounded-md bg-gray-300/20 dark:bg-gray-900/10 hover:bg-gray-300/50 dark:hover:bg-gray-900/50'>
6373
{t('token.label')}: {chat.config.max_tokens}

src/components/ConfigMenu/ConfigMenu.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ConfigInterface, ImageDetail } from '@type/chat';
55
import Select from 'react-select';
66
import { modelOptions, modelMaxToken } from '@constants/modelLoader';
77
import { ModelOptions } from '@utils/modelReader';
8+
import useStore from '@store/store';
89

910
const ConfigMenu = ({
1011
setIsModalOpen,
@@ -94,12 +95,26 @@ export const ModelSelector = ({
9495
_setModel: React.Dispatch<React.SetStateAction<ModelOptions>>;
9596
_label: string;
9697
}) => {
97-
const { t } = useTranslation('model');
98+
const { t } = useTranslation(['main', 'model']);
99+
const [localModelOptions, setLocalModelOptions] = useState<string[]>(modelOptions);
100+
const customModels = useStore((state) => state.customModels);
101+
102+
// Update model options when custom models change
103+
useEffect(() => {
104+
const customModelIds = customModels.map(model => model.id);
105+
const defaultModelIds = modelOptions.filter(id => !customModelIds.includes(id));
106+
setLocalModelOptions([...customModelIds, ...defaultModelIds]);
107+
}, [customModels]);
108+
109+
const modelOptionsFormatted = localModelOptions.map((model) => {
110+
const isCustom = customModels.some(m => m.id === model);
111+
const customModel = customModels.find(m => m.id === model);
112+
return {
113+
value: model,
114+
label: isCustom ? `${customModel?.name} ${t('customModels.customLabel', { ns: 'model' })}` : model,
115+
};
116+
});
98117

99-
const modelOptionsFormatted = modelOptions.map((model) => ({
100-
value: model,
101-
label: model,
102-
}));
103118
const customStyles = {
104119
control: (provided: any) => ({
105120
...provided,
@@ -138,7 +153,12 @@ export const ModelSelector = ({
138153
{_label}
139154
</label>
140155
<Select
141-
value={{ value: _model, label: _model }}
156+
value={{
157+
value: _model,
158+
label: customModels.some(m => m.id === _model)
159+
? `${customModels.find(m => m.id === _model)?.name} ${t('customModels.customLabel', { ns: 'model' })}`
160+
: _model,
161+
}}
142162
onChange={(selectedOption) =>
143163
_setModel(selectedOption?.value as ModelOptions)
144164
}

0 commit comments

Comments
 (0)