refactor(byok): move models suggestions list to server config models-list and fetch dynamically via API
This commit is contained in:
@@ -22,6 +22,8 @@ const createSchema = z.object({
|
|||||||
baseUrl: z.string().url().optional(),
|
baseUrl: z.string().url().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import { PROVIDER_MODEL_SUGGESTIONS } from '@/lib/ai/models-list';
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
if (!session?.user?.id) {
|
if (!session?.user?.id) {
|
||||||
@@ -36,6 +38,7 @@ export async function GET() {
|
|||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
keys: keys.map(toPublicApiKey),
|
keys: keys.map(toPublicApiKey),
|
||||||
allowedProviders: getAllowedByokProviders(await getEffectiveTier(session.user.id)),
|
allowedProviders: getAllowedByokProviders(await getEffectiveTier(session.user.id)),
|
||||||
|
providerModels: PROVIDER_MODEL_SUGGESTIONS,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type PublicKey = {
|
|||||||
async function fetchByokKeys(): Promise<{
|
async function fetchByokKeys(): Promise<{
|
||||||
keys: PublicKey[]
|
keys: PublicKey[]
|
||||||
allowedProviders: string[]
|
allowedProviders: string[]
|
||||||
|
providerModels: Record<string, string[]>
|
||||||
}> {
|
}> {
|
||||||
const res = await fetch('/api/user/api-keys')
|
const res = await fetch('/api/user/api-keys')
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -42,18 +43,6 @@ function providerLabel(t: (key: string) => string, provider: string): string {
|
|||||||
return translated === key ? provider : translated
|
return translated === key ? provider : translated
|
||||||
}
|
}
|
||||||
|
|
||||||
const PROVIDER_MODEL_SUGGESTIONS: Record<string, string[]> = {
|
|
||||||
openai: ['gpt-4o-mini', 'gpt-4o', 'gpt-3.5-turbo'],
|
|
||||||
anthropic: ['claude-3-5-sonnet-latest', 'claude-3-5-haiku-latest', 'claude-3-opus-latest'],
|
|
||||||
google: ['gemini-1.5-flash', 'gemini-1.5-pro', 'gemini-2.0-flash-exp'],
|
|
||||||
deepseek: ['deepseek-chat', 'deepseek-coder'],
|
|
||||||
minimax: ['abab6.5-chat', 'abab6.5s-chat'],
|
|
||||||
mistral: ['mistral-small-latest', 'mistral-medium-latest', 'mistral-large-latest'],
|
|
||||||
glm: ['glm-4', 'glm-4-flash'],
|
|
||||||
openrouter: ['openai/gpt-4o-mini', 'anthropic/claude-3.5-sonnet', 'deepseek/deepseek-chat'],
|
|
||||||
custom: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ByokSettingsPanel() {
|
export function ByokSettingsPanel() {
|
||||||
const { t } = useLanguage()
|
const { t } = useLanguage()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@@ -64,9 +53,16 @@ export function ByokSettingsPanel() {
|
|||||||
const [customModel, setCustomModel] = useState('')
|
const [customModel, setCustomModel] = useState('')
|
||||||
const [isCustomModel, setIsCustomModel] = useState(false)
|
const [isCustomModel, setIsCustomModel] = useState(false)
|
||||||
|
|
||||||
|
const { data, isLoading, error } = useQuery({
|
||||||
|
queryKey: ['user', 'api-keys'],
|
||||||
|
queryFn: fetchByokKeys,
|
||||||
|
})
|
||||||
|
|
||||||
|
const providerModels = data?.providerModels ?? {}
|
||||||
|
|
||||||
const handleProviderChange = (p: string) => {
|
const handleProviderChange = (p: string) => {
|
||||||
setProvider(p)
|
setProvider(p)
|
||||||
const sug = PROVIDER_MODEL_SUGGESTIONS[p] || []
|
const sug = providerModels[p] || []
|
||||||
if (sug.length > 0) {
|
if (sug.length > 0) {
|
||||||
setModel(sug[0])
|
setModel(sug[0])
|
||||||
setIsCustomModel(false)
|
setIsCustomModel(false)
|
||||||
@@ -77,11 +73,6 @@ export function ByokSettingsPanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data, isLoading, error } = useQuery({
|
|
||||||
queryKey: ['user', 'api-keys'],
|
|
||||||
queryFn: fetchByokKeys,
|
|
||||||
})
|
|
||||||
|
|
||||||
const invalidate = useCallback(() => {
|
const invalidate = useCallback(() => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['user', 'api-keys'] })
|
queryClient.invalidateQueries({ queryKey: ['user', 'api-keys'] })
|
||||||
queryClient.invalidateQueries({ queryKey: ['usage', 'current'] })
|
queryClient.invalidateQueries({ queryKey: ['usage', 'current'] })
|
||||||
@@ -240,7 +231,7 @@ export function ByokSettingsPanel() {
|
|||||||
<div className="grid gap-4 sm:grid-cols-2 pt-2 border-t border-border/40">
|
<div className="grid gap-4 sm:grid-cols-2 pt-2 border-t border-border/40">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="byok-model-select" className="text-[10px] font-bold uppercase tracking-widest text-concrete">Modèle de l'IA (Optionnel)</Label>
|
<Label htmlFor="byok-model-select" className="text-[10px] font-bold uppercase tracking-widest text-concrete">Modèle de l'IA (Optionnel)</Label>
|
||||||
{PROVIDER_MODEL_SUGGESTIONS[provider] && PROVIDER_MODEL_SUGGESTIONS[provider].length > 0 ? (
|
{providerModels[provider] && providerModels[provider].length > 0 ? (
|
||||||
<Select
|
<Select
|
||||||
value={isCustomModel ? 'custom' : model}
|
value={isCustomModel ? 'custom' : model}
|
||||||
onValueChange={(val) => {
|
onValueChange={(val) => {
|
||||||
@@ -257,7 +248,7 @@ export function ByokSettingsPanel() {
|
|||||||
<SelectValue placeholder="Choisir un modèle..." />
|
<SelectValue placeholder="Choisir un modèle..." />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{PROVIDER_MODEL_SUGGESTIONS[provider].map((m) => (
|
{providerModels[provider].map((m) => (
|
||||||
<SelectItem key={m} value={m}>
|
<SelectItem key={m} value={m}>
|
||||||
{m}
|
{m}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
@@ -272,7 +263,7 @@ export function ByokSettingsPanel() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(isCustomModel || !(PROVIDER_MODEL_SUGGESTIONS[provider] && PROVIDER_MODEL_SUGGESTIONS[provider].length > 0)) && (
|
{(isCustomModel || !(providerModels[provider] && providerModels[provider].length > 0)) && (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="byok-model-custom" className="text-[10px] font-bold uppercase tracking-widest text-concrete">Saisir le nom du modèle</Label>
|
<Label htmlFor="byok-model-custom" className="text-[10px] font-bold uppercase tracking-widest text-concrete">Saisir le nom du modèle</Label>
|
||||||
<Input
|
<Input
|
||||||
|
|||||||
11
memento-note/lib/ai/models-list.ts
Normal file
11
memento-note/lib/ai/models-list.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export const PROVIDER_MODEL_SUGGESTIONS: Record<string, string[]> = {
|
||||||
|
openai: ['gpt-4o-mini', 'gpt-4o', 'gpt-4-turbo', 'gpt-3.5-turbo'],
|
||||||
|
anthropic: ['claude-3-5-sonnet-latest', 'claude-3-5-haiku-latest', 'claude-3-opus-latest'],
|
||||||
|
google: ['gemini-1.5-flash', 'gemini-1.5-pro', 'gemini-2.0-flash-exp'],
|
||||||
|
deepseek: ['deepseek-chat', 'deepseek-coder'],
|
||||||
|
minimax: ['abab6.5-chat', 'abab6.5s-chat'],
|
||||||
|
mistral: ['mistral-small-latest', 'mistral-medium-latest', 'mistral-large-latest'],
|
||||||
|
glm: ['glm-4', 'glm-4-flash'],
|
||||||
|
openrouter: ['openai/gpt-4o-mini', 'anthropic/claude-3.5-sonnet', 'deepseek/deepseek-chat'],
|
||||||
|
custom: [],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user