Modèles

La page Modèles des paramètres d’un produit d’IA. Un modèle par défaut avec son contexte, sa vitesse et son coût en un coup d’œil, un effort par défaut qui sait ce que prend en charge chaque modèle, une liste de modèles consultable groupée par fournisseur avec filtres, épingles et bascules groupées, des serveurs compatibles OpenAI avec un vrai test de connexion, et une actualisation qui indique les nouveautés.

Chaque produit d’IA finit par avoir une page Modèles : quels modèles apparaissent dans le sélecteur, avec lequel démarrent les nouveaux chats, à quel point il réfléchit et quel petit modèle exécute les tâches d’arrière-plan. Models est cette page sous forme d’un seul composant, ModelSettings, qui s’intègre dans n’importe quelle section Settings et enregistre via le même îlot que le reste de vos paramètres.

Default model ouvre un menu des modèles activés, groupés par fournisseur, chacun avec son contexte, son coût et ses capacités. Sous le sélecteur, des chips montrent la fenêtre de contexte, la vitesse et le coût du modèle choisi, donc le compromis est visible avant d’ouvrir un chat. Default effort utilise le curseur d’effort de Prompt Input et sait ce que prend en charge le modèle par défaut. Faites glisser au-delà de ses capacités et le curseur se fixe sur son niveau le plus élevé, la ligne en dessous en explique la raison, et les lecteurs d’écran l’entendent aussi. Les modèles qui ne raisonnent pas grisent le curseur et expliquent que l’effort ne s’applique pas.

La liste des modèles se recherche par nom, fournisseur et capacité, et se filtre sur Enabled, Reasoning, Fast ou Vision. Les modèles sont groupés par fournisseur avec le nombre de ceux qui sont activés et un switch pour activer ou désactiver tout un fournisseur. Chaque ligne affiche le contexte, une échelle de coût à quatre points et des badges New et Preview. Épinglez les modèles que vous utilisez le plus depuis le menu d’une ligne et ils passent dans un groupe Pinned en haut, dans l’ordre où le sélecteur les affiche. Déplacez-les avec Move up et Move down, ou Alt et les flèches, sans rien faire glisser.

Add model connecte n’importe quel serveur compatible OpenAI, y compris local. Il vérifie l’URL, signale un modèle déjà ajouté et teste la connexion avant d’ajouter, en montrant le temps de réponse du serveur ou la raison de l’échec. Le champ de clé la masque jusqu’à ce que vous l’affichiez. Refresh demande à votre serveur le dernier catalogue et affiche une bannière discrète comme « 2 new models: Nova 3.5 and Atlas 2 Vision », avec Show pour filtrer sur eux. Les nouveaux modèles arrivent désactivés, donc rien ne change dans le sélecteur tant que vous n’avez pas choisi.

Task models donne à la sous-agent d’exploration, aux titres de chat et aux résumés leur propre modèle, ou Auto. Rien n’est enregistré tant que vous n’enregistrez pas : chaque changement fait apparaître la barre d’enregistrement de Settings, Discard remet tout en place, y compris les modèles personnalisés retirés, et le modèle par défaut ne peut pas être désactivé par accident.

  1. Ajouter le registre Pro à components.json

    components.json
    {
      "registries": {
        "@hextaui-pro": {
          "url": "https://hextaui.com/r/pro/{name}.json",
          "headers": {
            "Authorization": "Bearer ${HEXTAUI_PRO_TOKEN}"
          }
        }
      }
    }
  2. Ajouter votre token

    Créez un token sur votre page de compte et placez-le dans .env.local sous le nom HEXTAUI_PRO_TOKEN.

  3. Ajouter le block

    pnpm dlx shadcn@latest add @hextaui-pro/models

Branchez-le à votre API

Placez ModelSettings dans une SettingsSection. Passez le catalogue et ce qui est enregistré, enregistrez dans onSave et renvoyez le dernier catalogue depuis onRefresh. Levez une erreur dans l’un ou l’autre pour afficher le message, et le brouillon est conservé.

"use client"

import { IconCube } from "@tabler/icons-react"

import { SettingsSection, SettingsShell, type SettingsSectionItem } from "../settings/settings"
import { ModelSettings, type ModelInfo, type ModelSettingsValues } from "@/components/blocks/models/model-settings"

const sections: SettingsSectionItem[] = [{ id: "models", label: "Models", icon: <IconCube /> }]

export function ModelsPage({
  models,
  values,
}: {
  models: ModelInfo[]
  values: ModelSettingsValues
}) {
  return (
    <SettingsShell sections={sections} className="h-svh">
      <SettingsSection id="models">
        <ModelSettings
          models={models}
          values={values}
          onSave={async (next) => {
            const response = await fetch("/api/settings/models", {
              method: "PUT",
              body: JSON.stringify(next),
            })
            if (!response.ok) throw new Error("Check your connection and try again.")
          }}
          onRefresh={async () => {
            const response = await fetch("/api/models")
            if (!response.ok) throw new Error("The model list is unavailable.")
            return (await response.json()) as ModelInfo[]
          }}
        />
      </SettingsSection>
    </SettingsShell>
  )
}

Tester les serveurs personnalisés

onTestConnection reçoit l’URL de base, l’ID du modèle et la clé. Résolvez quand le serveur répond, ou levez une erreur avec un message exploitable. Add model exécute d’abord le même test, donc un serveur défaillant n’arrive jamais dans la liste.

"use client"

import { ModelSettings, type ModelConnection, type ModelInfo, type ModelSettingsValues } from "@/components/blocks/models/model-settings"

async function testConnection({ baseUrl, model, apiKey }: ModelConnection) {
  const response = await fetch(`${baseUrl}/chat/completions`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
    },
    body: JSON.stringify({ model, max_tokens: 1, messages: [{ role: "user", content: "ping" }] }),
  }).catch(() => {
    throw new Error(`Couldn’t reach ${new URL(baseUrl).host}. Check the URL and that the server is running.`)
  })
  if (response.status === 401) throw new Error("The server said 401. Check the API key.")
  if (response.status === 404) throw new Error(`The server doesn’t know “${model}”.`)
  if (!response.ok) throw new Error(`The server said ${response.status}.`)
}

export function ModelsWithCustomServers({
  models,
  values,
  onSave,
}: {
  models: ModelInfo[]
  values: ModelSettingsValues
  onSave: (values: ModelSettingsValues) => Promise<void>
}) {
  return (
    <ModelSettings
      models={models}
      values={values}
      onSave={onSave}
      onTestConnection={testConnection}
    />
  )
}

Vos propres niveaux d’effort et tâches

efforts définit les niveaux du curseur, et le efforts de chaque modèle liste ceux qu’il prend en charge. tasks définit les tâches d’arrière-plan qui ont leur propre modèle.

"use client"

import { ModelSettings, type ModelInfo, type ModelSettingsValues } from "@/components/blocks/models/model-settings"

const models: ModelInfo[] = [
  {
    id: "nova-3",
    name: "Nova 3",
    provider: "Hexta",
    context: 200_000,
    speed: "balanced",
    price: 2,
    efforts: ["none", "light", "deep"],
    recommendedEffort: "light",
  },
  {
    id: "nova-3-mini",
    name: "Nova 3 Mini",
    provider: "Hexta",
    context: 128_000,
    speed: "fast",
    price: 1,
    efforts: ["none", "light"],
  },
]

const efforts = [
  { value: "none", label: "None" },
  { value: "light", label: "Light" },
  { value: "deep", label: "Deep" },
]

const tasks = [
  { id: "titles", label: "Chat titles", description: "Names new chats from the first message." },
]

export function ModelsWithOwnLevels({
  values,
  onSave,
}: {
  values: ModelSettingsValues
  onSave: (values: ModelSettingsValues) => Promise<void>
}) {
  return (
    <ModelSettings models={models} values={values} onSave={onSave} efforts={efforts} tasks={tasks} />
  )
}

Anatomie

Les parties à composer, de l’extérieur vers l’intérieur.

PartieDescription
ModelSettingsToute la section Models : valeurs par défaut, liste du sélecteur de modèles et task models. À placer dans une SettingsSection.
Default modelUn menu des modèles activés avec leurs statistiques, et des chips pour le contexte, la vitesse et le coût du modèle choisi.
Default effortLe curseur d’effort de Prompt Input, limité aux niveaux pris en charge par le modèle par défaut.
Model pickerRecherche, filtres, bannière d’actualisation, groupe Pinned et un groupe par fournisseur, chaque ligne avec un switch et un menu.
Add model dialogURL de base, ID du modèle, nom d’affichage et clé d’API d’un serveur compatible OpenAI, avec un test de connexion.
Task modelsUn modèle par tâche d’arrière-plan, ou Auto.

ModelSettings

Doit être rendu dans SettingsShell, généralement dans une SettingsSection, car il enregistre via la barre d’enregistrement de la coque.

PropTypePar défaut
modelsLe catalogue. { id, name, provider, context?, speed?, price?, vision?, efforts?, recommendedEffort?, status?, description? }. speed vaut "fast" | "balanced" | "thorough", price va de 1 à 4, efforts liste les valeurs d’effort prises en charge par le modèle (omettez-le pour les modèles qui ne raisonnent pas), et status vaut "new" | "preview".
ModelInfo[]–
valuesCe qui est enregistré : { defaultModel, effort, enabled, pinned, tasks, custom }. enabled et pinned sont des ids de modèles, pinned dans l’ordre du sélecteur. tasks associe un id de tâche à un id de modèle ou à "auto". custom contient les serveurs ajoutés.
ModelSettingsValues–
onSaveEnregistre le brouillon. Levez une erreur pour afficher le message dans la barre d’enregistrement et conserver le brouillon.
(values) => void | Promise<void>–
onRefreshRécupère le dernier catalogue. Les modèles dont l’id est inconnu reçoivent un badge New et une bannière. Levez une erreur pour afficher la raison avec Try again. Omettez-le pour masquer le bouton d’actualisation.
() => Promise<ModelInfo[]>–
onTestConnectionTeste un serveur personnalisé. Résolvez s’il répond et levez une erreur avec un message sinon. Omettez-le pour ajouter des modèles personnalisés sans test.
(connection: { baseUrl, model, apiKey }) => Promise<void>–
effortsLes niveaux d’effort, du plus rapide au plus intelligent.
{ value, label }[]Low, Medium, High, Max
tasksTâches d’arrière-plan qui ont leur propre modèle. Passez [] pour masquer le groupe.
{ id, label, description? }[]Explore subagent, Chat titles, Summaries
ToucheAction
EscapeDans la recherche, efface la requête.
EnterDans la recherche sans résultat, ouvre Add model avec la requête comme ID du modèle.
←→Passe d’un filtre à l’autre. Dans le curseur d’effort, change le niveau, en s’arrêtant à ce que prend en charge le modèle par défaut.
SpaceActive ou désactive le modèle ayant le focus.
Alt↑Sur le switch ou le menu d’un modèle épinglé, le monte dans le sélecteur. Alt+↓ le descend. Le focus reste sur le même contrôle.
⌘SEnregistre, comme le reste de Settings. Ctrl+S sous Windows et Linux.
  • Chaque fournisseur et le groupe Pinned est une liste nommée par son titre, et chaque ligne est nommée par son modèle.
  • Les switches sont libellés par le nom du modèle et décrits par son contexte, son coût et ses capacités. Le switch du modèle par défaut est désactivé et en indique la raison.
  • Une région live polie annonce combien de modèles correspondent à une recherche ou un filtre, les résultats d’actualisation, les changements groupés, les épingles, les déplacements et le moment où l’effort est limité par le modèle.
  • Quand un modèle épinglé se déplace ou qu’une ligne change de groupe, le focus la suit sur le même contrôle.
  • L’échelle de coût a un nom textuel, comme Low cost, donc les points ne sont jamais le seul signal.
  • Avec réduction des animations, la bannière, la surbrillance de ligne et le curseur ne s’animent pas.

Construit avec

Les composants HextaUI gratuits dont Models est constitué. Chacun s’installe séparément.

Code

4 fichiers, ajoutés à components/blocks/models.