ultisuite-client/lib/llm/llm-provider-catalog.ts
R3D347HR4Y 9e9fd208ad
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(admin-settings): enhance admin settings with new components and layout improvements
- Introduced new components for managing admin settings, including AdminListControls, AdminSettingsCard, and TechBrandSelectLabel.
- Implemented dynamic loading for admin settings sections to optimize performance.
- Enhanced the layout of various admin settings sections for better user experience.
- Updated the AiAssistantSection to include LLM provider management and improved model selection.
- Refactored authentication settings to streamline configuration and improve accessibility.
2026-06-15 00:22:20 +02:00

234 lines
8.2 KiB
TypeScript

import type { ApiLLMProvider, ApiLLMProviderType } from "@/lib/contacts/discovery-types"
import { techBrandIcon } from "@/lib/admin-settings/tech-brand-icons"
export type { ApiLLMProviderType }
export type LLMProviderCatalogEntry = {
type: ApiLLMProviderType
label: string
description: string
icon?: string
docsUrl?: string
defaultBaseURL: string
defaultModel: string
baseURLPlaceholder?: string
}
export const LLM_PROVIDER_CATALOG: LLMProviderCatalogEntry[] = [
{
type: "openai",
label: "OpenAI",
description: "API officielle OpenAI (GPT, o-series).",
icon: techBrandIcon("openai"),
docsUrl: "https://platform.openai.com/docs/api-reference",
defaultBaseURL: "https://api.openai.com/v1",
defaultModel: "gpt-4o-mini",
},
{
type: "anthropic",
label: "Anthropic",
description: "Claude via la couche OpenAI-compatible d'Anthropic.",
icon: techBrandIcon("anthropic"),
docsUrl: "https://platform.claude.com/docs/en/api/openai-sdk",
defaultBaseURL: "https://api.anthropic.com/v1",
defaultModel: "claude-sonnet-4-6",
},
{
type: "mistral",
label: "Mistral AI",
description: "API Mistral (OpenAI-compatible).",
icon: techBrandIcon("mistral"),
docsUrl: "https://docs.mistral.ai/api/",
defaultBaseURL: "https://api.mistral.ai/v1",
defaultModel: "mistral-small-latest",
},
{
type: "azure_openai",
label: "Azure OpenAI",
description: "Modèles OpenAI déployés sur Azure AI Foundry.",
icon: techBrandIcon("azure_openai"),
docsUrl: "https://learn.microsoft.com/azure/ai-foundry/openai/reference",
defaultBaseURL: "https://VOTRE_RESSOURCE.openai.azure.com/openai/v1",
defaultModel: "gpt-4o-mini",
baseURLPlaceholder: "https://ma-ressource.openai.azure.com/openai/v1",
},
{
type: "azure_ai_anthropic",
label: "Anthropic via Azure",
description:
"Claude sur Microsoft Foundry. Remplacez VOTRE_RESSOURCE ; vérifiez la compatibilité OpenAI de votre déploiement.",
icon: techBrandIcon("azure_ai_anthropic"),
docsUrl:
"https://learn.microsoft.com/azure/ai-foundry/foundry-models/how-to/use-foundry-models-claude",
defaultBaseURL: "https://VOTRE_RESSOURCE.services.ai.azure.com/anthropic/v1",
defaultModel: "claude-sonnet-4-6",
baseURLPlaceholder:
"https://ma-ressource.services.ai.azure.com/anthropic/v1",
},
{
type: "aws_bedrock",
label: "Anthropic via AWS Bedrock",
description: "Claude et autres modèles via Bedrock (OpenAI-compatible).",
icon: techBrandIcon("aws_bedrock"),
docsUrl: "https://docs.aws.amazon.com/bedrock/latest/userguide/inference-chat-completions-mantle.html",
defaultBaseURL: "https://bedrock-runtime.us-east-1.amazonaws.com/openai/v1",
defaultModel: "us.anthropic.claude-sonnet-4-6",
baseURLPlaceholder: "https://bedrock-runtime.eu-west-1.amazonaws.com/openai/v1",
},
{
type: "google_gemini",
label: "Google Gemini",
description: "API Gemini en mode OpenAI-compatible.",
icon: techBrandIcon("google_gemini"),
docsUrl: "https://ai.google.dev/gemini-api/docs/openai",
defaultBaseURL: "https://generativelanguage.googleapis.com/v1beta/openai/",
defaultModel: "gemini-2.0-flash",
},
{
type: "groq",
label: "Groq",
description: "Inférence rapide (Llama, Mixtral, etc.).",
icon: techBrandIcon("groq"),
docsUrl: "https://console.groq.com/docs/openai",
defaultBaseURL: "https://api.groq.com/openai/v1",
defaultModel: "llama-3.3-70b-versatile",
},
{
type: "deepseek",
label: "DeepSeek",
description: "Modèles DeepSeek (OpenAI-compatible).",
icon: techBrandIcon("deepseek"),
docsUrl: "https://api-docs.deepseek.com/",
defaultBaseURL: "https://api.deepseek.com/v1",
defaultModel: "deepseek-chat",
},
{
type: "openrouter",
label: "OpenRouter",
description: "Passerelle multi-fournisseurs (Claude, GPT, Llama…).",
icon: techBrandIcon("openrouter"),
docsUrl: "https://openrouter.ai/docs",
defaultBaseURL: "https://openrouter.ai/api/v1",
defaultModel: "anthropic/claude-sonnet-4",
},
{
type: "together",
label: "Together AI",
description: "Modèles open-source hébergés.",
icon: techBrandIcon("together"),
docsUrl: "https://docs.together.ai/docs/openai-api",
defaultBaseURL: "https://api.together.xyz/v1",
defaultModel: "meta-llama/Llama-3.3-70B-Instruct-Turbo",
},
{
type: "fireworks",
label: "Fireworks AI",
description: "Inférence serverless pour modèles open-source.",
icon: techBrandIcon("fireworks"),
docsUrl: "https://docs.fireworks.ai/tools-sdks/openai-compatibility",
defaultBaseURL: "https://api.fireworks.ai/inference/v1",
defaultModel: "accounts/fireworks/models/llama-v3p3-70b-instruct",
},
{
type: "xai",
label: "xAI (Grok)",
description: "API Grok (OpenAI-compatible).",
icon: techBrandIcon("xai"),
docsUrl: "https://docs.x.ai/docs/guides/chat-completions",
defaultBaseURL: "https://api.x.ai/v1",
defaultModel: "grok-2-latest",
},
{
type: "ollama",
label: "Ollama (local)",
description: "Serveur Ollama local avec API OpenAI-compatible.",
icon: techBrandIcon("ollama"),
docsUrl: "https://github.com/ollama/ollama/blob/main/docs/openai.md",
defaultBaseURL: "http://localhost:11434/v1",
defaultModel: "llama3.2",
},
{
type: "ollama_cloud",
label: "Ollama Cloud",
description: "Modèles hébergés sur ollama.com (clé API requise).",
icon: techBrandIcon("ollama"),
docsUrl: "https://docs.ollama.com/cloud",
defaultBaseURL: "https://ollama.com/v1",
defaultModel: "gpt-oss:120b",
},
{
type: "custom",
label: "Endpoint personnalisé",
description: "Toute API compatible OpenAI (/v1/chat/completions).",
icon: techBrandIcon("custom"),
defaultBaseURL: "",
defaultModel: "",
baseURLPlaceholder: "https://api.example.com/v1",
},
]
export function llmCatalogEntry(type: ApiLLMProviderType): LLMProviderCatalogEntry {
return LLM_PROVIDER_CATALOG.find((entry) => entry.type === type) ?? LLM_PROVIDER_CATALOG.at(-1)!
}
export function emptyLlmProvider(type: ApiLLMProviderType = "openai"): ApiLLMProvider {
const entry = llmCatalogEntry(type)
return {
id: crypto.randomUUID(),
type,
name: entry.label,
base_url: entry.defaultBaseURL,
api_key: "",
default_model: entry.defaultModel,
}
}
export function inferLlmProviderType(provider: ApiLLMProvider): ApiLLMProviderType {
if (provider.type) return provider.type
const url = provider.base_url?.toLowerCase() ?? ""
if (url.includes("api.openai.com")) return "openai"
if (url.includes("api.anthropic.com")) return "anthropic"
if (url.includes("api.mistral.ai")) return "mistral"
if (url.includes("openai.azure.com")) return "azure_openai"
if (url.includes("services.ai.azure.com/anthropic")) return "azure_ai_anthropic"
if (url.includes("bedrock")) return "aws_bedrock"
if (url.includes("ollama.com")) return "ollama_cloud"
if (url.includes("localhost:11434") || url.includes("127.0.0.1:11434")) return "ollama"
if (url.includes("generativelanguage.googleapis.com")) return "google_gemini"
if (url.includes("api.groq.com")) return "groq"
if (url.includes("api.deepseek.com")) return "deepseek"
if (url.includes("openrouter.ai")) return "openrouter"
if (url.includes("api.together.xyz")) return "together"
if (url.includes("api.fireworks.ai")) return "fireworks"
if (url.includes("api.x.ai")) return "xai"
return "custom"
}
export function normalizeLlmProvider(provider: ApiLLMProvider): ApiLLMProvider {
const type = inferLlmProviderType(provider)
const entry = llmCatalogEntry(type)
return {
...provider,
type,
name: provider.name?.trim() || entry.label,
}
}
export function isLlmProviderConfigured(
provider: ApiLLMProvider,
options?: { apiKeyConfigured?: boolean },
): boolean {
const type = inferLlmProviderType(provider)
const entry = llmCatalogEntry(type)
if (!provider.base_url?.trim() && type !== "custom") {
return false
}
if (type === "ollama") {
return Boolean(provider.base_url?.trim())
}
if (type === "custom") {
return Boolean(provider.base_url?.trim())
}
return Boolean(provider.api_key?.trim() || options?.apiKeyConfigured)
}