mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-10-19 22:08:15 +00:00
feat(settings): add embedding model selector
This commit is contained in:
80
src/components/Settings/Sections/Models/ModelSelect.tsx
Normal file
80
src/components/Settings/Sections/Models/ModelSelect.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import Select from '@/components/ui/Select';
|
||||||
|
import { ConfigModelProvider } from '@/lib/config/types';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
|
const ModelSelect = ({
|
||||||
|
providers,
|
||||||
|
type,
|
||||||
|
}: {
|
||||||
|
providers: ConfigModelProvider[];
|
||||||
|
type: 'chat' | 'embedding';
|
||||||
|
}) => {
|
||||||
|
const [selectedModel, setSelectedModel] = useState<string>(
|
||||||
|
`${providers[0]?.id}/${providers[0].embeddingModels[0]?.key}`,
|
||||||
|
);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleSave = async (newValue: string) => {
|
||||||
|
setLoading(true);
|
||||||
|
setSelectedModel(newValue);
|
||||||
|
try {
|
||||||
|
if (type === 'chat') {
|
||||||
|
localStorage.setItem('chatModelProviderId', newValue.split('/')[0]);
|
||||||
|
localStorage.setItem('chatModelKey', newValue.split('/')[1]);
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(
|
||||||
|
'embeddingModelProviderId',
|
||||||
|
newValue.split('/')[0],
|
||||||
|
);
|
||||||
|
localStorage.setItem('embeddingModelKey', newValue.split('/')[1]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving config:', error);
|
||||||
|
toast.error('Failed to save configuration.');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="rounded-xl border border-light-200 bg-light-primary/80 p-6 transition-colors dark:border-dark-200 dark:bg-dark-primary/80">
|
||||||
|
<div className="space-y-5">
|
||||||
|
<div>
|
||||||
|
<h4 className="text-base text-black dark:text-white">
|
||||||
|
Select {type === 'chat' ? 'Chat Model' : 'Embedding Model'}
|
||||||
|
</h4>
|
||||||
|
<p className="text-xs text-black/50 dark:text-white/50">
|
||||||
|
{type === 'chat'
|
||||||
|
? 'Select the model to use for chat responses'
|
||||||
|
: 'Select the model to use for embeddings'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Select
|
||||||
|
value={selectedModel}
|
||||||
|
onChange={(event) => handleSave(event.target.value)}
|
||||||
|
options={
|
||||||
|
type === 'chat'
|
||||||
|
? providers.flatMap((provider) =>
|
||||||
|
provider.chatModels.map((model) => ({
|
||||||
|
value: `${provider.id}/${model.key}`,
|
||||||
|
label: `${provider.name} - ${model.name}`,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
: providers.flatMap((provider) =>
|
||||||
|
provider.embeddingModels.map((model) => ({
|
||||||
|
value: `${provider.id}/${model.key}`,
|
||||||
|
label: `${provider.name} - ${model.name}`,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="w-full rounded-lg border border-light-200 dark:border-dark-200 bg-light-primary dark:bg-dark-primary px-4 py-3 text-sm text-black/80 dark:text-white/80 placeholder:text-black/40 dark:placeholder:text-white/40 focus-visible:outline-none focus-visible:border-light-300 dark:focus-visible:border-dark-300 transition-colors disabled:cursor-not-allowed disabled:opacity-60 cursor-pointer capitalize pr-12"
|
||||||
|
loading={loading}
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModelSelect;
|
@@ -6,6 +6,8 @@ import {
|
|||||||
UIConfigField,
|
UIConfigField,
|
||||||
} from '@/lib/config/types';
|
} from '@/lib/config/types';
|
||||||
import ModelProvider from './ModelProvider';
|
import ModelProvider from './ModelProvider';
|
||||||
|
import SettingsField from '../../SettingsField';
|
||||||
|
import ModelSelect from './ModelSelector';
|
||||||
|
|
||||||
const Models = ({
|
const Models = ({
|
||||||
fields,
|
fields,
|
||||||
@@ -17,14 +19,21 @@ const Models = ({
|
|||||||
const [providers, setProviders] = useState<ConfigModelProvider[]>(values);
|
const [providers, setProviders] = useState<ConfigModelProvider[]>(values);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 space-y-6 overflow-y-auto px-6 py-6">
|
<div className="flex-1 space-y-6 overflow-y-auto py-6">
|
||||||
<div className="flex flex-row justify-between items-center">
|
<div className="flex flex-col px-6 gap-y-4">
|
||||||
|
<h3 className="text-sm text-black/70 dark:text-white/70">
|
||||||
|
Select models
|
||||||
|
</h3>
|
||||||
|
<ModelSelect providers={values} type="embedding" />
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-light-200 dark:border-dark-200" />
|
||||||
|
<div className="flex flex-row justify-between items-center px-6 ">
|
||||||
<p className="text-sm text-black/70 dark:text-white/70">
|
<p className="text-sm text-black/70 dark:text-white/70">
|
||||||
Manage model provider
|
Manage model provider
|
||||||
</p>
|
</p>
|
||||||
<AddProvider modelProviders={fields} setProviders={setProviders} />
|
<AddProvider modelProviders={fields} setProviders={setProviders} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-y-4">
|
<div className="flex flex-col px-6 gap-y-4">
|
||||||
{providers.map((provider) => (
|
{providers.map((provider) => (
|
||||||
<ModelProvider
|
<ModelProvider
|
||||||
key={`provider-${provider.id}`}
|
key={`provider-${provider.id}`}
|
||||||
|
Reference in New Issue
Block a user