Modelos

A página Modelos das configurações de um produto de IA. Um modelo padrão com contexto, velocidade e custo à primeira vista, um esforço padrão que sabe o que cada modelo suporta, uma lista de modelos pesquisável agrupada por provedor com filtros, fixações e alternâncias em massa, servidores compatíveis com a OpenAI com um teste de conexão real e uma atualização que informa o que há de novo.

Todo produto de IA acaba ganhando uma página de Modelos: quais modelos aparecem no seletor, com qual os novos chats começam, o quanto ele pensa e qual modelo pequeno executa as tarefas em segundo plano. O Models é essa página como um único componente, ModelSettings, que se encaixa em qualquer seção de Configurações e salva pela mesma ilha do restante das suas configurações.

Default model abre um menu dos modelos que estão ativados, agrupados por provedor, cada um com contexto, custo e capacidades. Sob o seletor, chips mostram a janela de contexto, a velocidade e o custo do modelo escolhido, para que o equilíbrio fique visível antes de alguém abrir um chat. Default effort usa o slider de esforço do Prompt Input e sabe o que o modelo padrão suporta. Arraste além do que ele consegue e o slider se acomoda no nível mais alto, a linha abaixo explica por quê, e os leitores de tela também ouvem isso. Modelos que não raciocinam deixam o slider acinzentado e explicam que o esforço não se aplica.

A lista de modelos pesquisa por nome, provedor e capacidade, e filtra por Enabled, Reasoning, Fast ou Vision. Os modelos são agrupados por provedor, com a contagem do que está ativo e um switch para ligar ou desligar um provedor inteiro. Cada linha mostra o contexto, uma escala de custo de quatro pontos e badges para New e Preview. Fixe os modelos que você mais usa pelo menu da linha e eles vão para um grupo Pinned no topo, na ordem em que o seletor os mostra. Mova-os com Move up e Move down, ou com Alt e as setas, sem arrastar nada.

Add model conecta qualquer servidor compatível com a OpenAI, inclusive locais. Ele verifica a URL, sinaliza um modelo que você já adicionou e testa a conexão antes de adicionar, mostrando quanto tempo o servidor levou para responder ou o motivo da falha. O campo da chave oculta a chave até você exibi-la. Refresh pede ao seu servidor o catálogo mais recente e mostra um banner discreto como "2 novos modelos: Nova 3.5 e Atlas 2 Vision", com Show para filtrar por eles. Os modelos novos chegam desligados, então nada muda no seletor até você escolher.

Task models dão ao subagente de exploração, aos títulos de chat e aos resumos o seu próprio modelo, ou Auto. Nada é salvo até você salvar: toda mudança faz a barra de salvar do Settings subir, Discard restaura tudo, inclusive os modelos personalizados removidos, e o modelo padrão não pode ser desligado por acidente.

  1. Adicione o registro Pro ao components.json

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

    Crie um token na sua página de conta e coloque-o em .env.local como HEXTAUI_PRO_TOKEN.

  3. Adicione o bloco

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

Conecte à sua API

Coloque o ModelSettings dentro de um SettingsSection. Passe o catálogo e o que está salvo, salve em onSave e retorne o catálogo mais recente de onRefresh. Lance um erro em qualquer um para mostrar a mensagem, e o rascunho permanece.

"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>
  )
}

Teste servidores personalizados

onTestConnection recebe a URL base, o ID do modelo e a chave. Resolva quando o servidor responder, ou lance um erro com uma mensagem que as pessoas possam usar. Add model executa o mesmo teste antes, então um servidor com problema nunca entra na lista.

"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}
    />
  )
}

Seus próprios níveis de esforço e tarefas

efforts define os níveis do slider, e o efforts de cada modelo lista os que ele suporta. tasks define as tarefas em segundo plano que recebem seu próprio modelo.

"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} />
  )
}

Anatomia

As partes que você compõe, de fora para dentro.

ParteDescrição
ModelSettingsA seção Models inteira: padrões, a lista do seletor de modelos e os task models. Coloque-a dentro de um SettingsSection.
Default modelUm menu dos modelos habilitados com suas estatísticas, e chips para o contexto, a velocidade e o custo do escolhido.
Default effortO slider de esforço do Prompt Input, limitado aos níveis que o modelo padrão suporta.
Model pickerBusca, filtros, um banner de atualização, um grupo Pinned e um grupo por provedor, cada linha com um switch e um menu.
Add model dialogURL base, ID do modelo, nome de exibição e chave de API de um servidor compatível com a OpenAI, com um teste de conexão.
Task modelsUm modelo por tarefa em segundo plano, ou Auto.

ModelSettings

Deve ser renderizado dentro do SettingsShell, geralmente em um SettingsSection, porque salva pela barra de salvar do shell.

PropTipoPadrão
modelsO catálogo. { id, name, provider, context?, speed?, price?, vision?, efforts?, recommendedEffort?, status?, description? }. speed é "fast" | "balanced" | "thorough", price vai de 1 a 4, efforts lista os valores de esforço que o modelo suporta (omita para modelos que não raciocinam) e status é "new" | "preview".
ModelInfo[]–
valuesO que está salvo: { defaultModel, effort, enabled, pinned, tasks, custom }. enabled e pinned são ids de modelo, e pinned segue a ordem do seletor. tasks mapeia o id de uma tarefa para um id de modelo ou "auto". custom guarda os servidores adicionados.
ModelSettingsValues–
onSaveSalva o rascunho. Lance um erro para mostrar a mensagem na barra de salvar e manter o rascunho.
(values) => void | Promise<void>–
onRefreshBusca o catálogo mais recente. Modelos com ids que ele não viu recebem um badge New e um banner. Lance um erro para mostrar o motivo com Try again. Omita para ocultar o botão de atualizar.
() => Promise<ModelInfo[]>–
onTestConnectionVerifica um servidor personalizado. Resolva se ele responder e lance um erro com uma mensagem se não. Omita para adicionar modelos personalizados sem teste.
(connection: { baseUrl, model, apiKey }) => Promise<void>–
effortsOs níveis de esforço, do mais rápido ao mais inteligente.
{ value, label }[]Low, Medium, High, Max
tasksTarefas em segundo plano que recebem seu próprio modelo. Passe [] para ocultar o grupo.
{ id, label, description? }[]Explore subagent, Chat titles, Summaries
TeclaAção
EscapeNa busca, limpa a consulta.
EnterNa busca sem resultados, abre Add model com a consulta como ID do modelo.
←→Alterna entre os filtros. No slider de esforço, muda o nível, parando no que o modelo padrão suporta.
SpaceLiga ou desliga o modelo em foco.
Alt↑No switch ou no menu de um modelo fixado, sobe-o no seletor. Alt+↓ o desce. O foco permanece no mesmo controle.
⌘SSalva, como o resto do Settings. Ctrl+S no Windows e no Linux.
  • Cada provedor e o grupo Pinned é uma lista nomeada pelo seu título, e cada linha é nomeada pelo seu modelo.
  • Os switches são rotulados com o nome do modelo e descritos por seu contexto, custo e capacidades. O switch do modelo padrão fica desabilitado e diz o motivo.
  • Uma região live polite anuncia quantos modelos correspondem a uma busca ou filtro, os resultados da atualização, as mudanças em massa, as fixações, as movimentações e quando o esforço é limitado pelo modelo.
  • Quando um modelo fixado se move ou uma linha muda de grupo, o foco o acompanha até o mesmo controle.
  • A escala de custo tem um nome em texto, como Low cost, então os pontos nunca são o único sinal.
  • Com movimento reduzido, o banner, o destaque da linha e o slider não são animados.

Construído com

Os componentes gratuitos do HextaUI de que Models é feito. Cada um é instalado separadamente.

Código

4 arquivos, adicionados a components/blocks/models.