| import System from "@/models/system"; |
| import { CaretDown, CaretUp } from "@phosphor-icons/react"; |
| import { useState, useEffect } from "react"; |
|
|
| export default function NovitaLLMOptions({ settings }) { |
| return ( |
| <div className="w-full flex flex-col gap-y-7"> |
| <div className="w-full flex items-start gap-[36px] mt-1.5"> |
| <div className="flex flex-col w-60"> |
| <label className="text-theme-text-primary text-sm font-semibold block mb-3"> |
| Novita API Key |
| </label> |
| <input |
| type="password" |
| name="NovitaLLMApiKey" |
| className="border-none bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" |
| placeholder="Novita API Key" |
| defaultValue={settings?.NovitaLLMApiKey ? "*".repeat(20) : ""} |
| required={true} |
| autoComplete="off" |
| spellCheck={false} |
| /> |
| </div> |
| {!settings?.credentialsOnly && ( |
| <NovitaModelSelection settings={settings} /> |
| )} |
| </div> |
| <AdvancedControls settings={settings} /> |
| </div> |
| ); |
| } |
|
|
| function AdvancedControls({ settings }) { |
| const [showAdvancedControls, setShowAdvancedControls] = useState(false); |
|
|
| return ( |
| <div className="flex flex-col gap-y-4"> |
| <div className="flex justify-start"> |
| <button |
| type="button" |
| onClick={() => setShowAdvancedControls(!showAdvancedControls)} |
| className="border-none text-theme-text-primary hover:text-theme-text-secondary flex items-center text-sm" |
| > |
| {showAdvancedControls ? "Hide" : "Show"} advanced settings |
| {showAdvancedControls ? ( |
| <CaretUp size={14} className="ml-1" /> |
| ) : ( |
| <CaretDown size={14} className="ml-1" /> |
| )} |
| </button> |
| </div> |
| <div hidden={!showAdvancedControls}> |
| <div className="flex flex-col w-60"> |
| <label className="text-theme-text-primary text-sm font-semibold block mb-3"> |
| Stream Timeout (ms) |
| </label> |
| <input |
| type="number" |
| name="NovitaLLMTimeout" |
| className="border-none bg-theme-settings-input-bg text-theme-text-primary placeholder:text-theme-settings-input-placeholder text-sm rounded-lg focus:outline-primary-button active:outline-primary-button outline-none block w-full p-2.5" |
| placeholder="Timeout value between token responses to auto-timeout the stream" |
| defaultValue={settings?.NovitaLLMTimeout ?? 3_000} |
| autoComplete="off" |
| onScroll={(e) => e.target.blur()} |
| min={500} |
| step={1} |
| /> |
| <p className="text-xs leading-[18px] font-base text-theme-text-primary text-opacity-60 mt-2"> |
| Timeout value between token responses to auto-timeout the stream. |
| </p> |
| </div> |
| </div> |
| </div> |
| ); |
| } |
|
|
| function NovitaModelSelection({ settings }) { |
| const [groupedModels, setGroupedModels] = useState({}); |
| const [loading, setLoading] = useState(true); |
|
|
| useEffect(() => { |
| async function findCustomModels() { |
| setLoading(true); |
| const { models } = await System.customModels("novita"); |
| if (models?.length > 0) { |
| const modelsByOrganization = models.reduce((acc, model) => { |
| acc[model.organization] = acc[model.organization] || []; |
| acc[model.organization].push(model); |
| return acc; |
| }, {}); |
| setGroupedModels(modelsByOrganization); |
| } |
| setLoading(false); |
| } |
| findCustomModels(); |
| }, []); |
|
|
| if (loading || Object.keys(groupedModels).length === 0) { |
| return ( |
| <div className="flex flex-col w-60"> |
| <label className="text-theme-text-primary text-sm font-semibold block mb-3"> |
| Chat Model Selection |
| </label> |
| <select |
| name="NovitaLLMModelPref" |
| disabled={true} |
| className="border-none bg-theme-settings-input-bg text-theme-text-primary border-theme-border text-sm rounded-lg block w-full p-2.5" |
| > |
| <option disabled={true} selected={true}> |
| -- loading available models -- |
| </option> |
| </select> |
| </div> |
| ); |
| } |
|
|
| return ( |
| <div className="flex flex-col w-60"> |
| <label className="text-theme-text-primary text-sm font-semibold block mb-3"> |
| Chat Model Selection |
| </label> |
| <select |
| name="NovitaLLMModelPref" |
| required={true} |
| className="border-none bg-theme-settings-input-bg text-theme-text-primary border-theme-border text-sm rounded-lg block w-full p-2.5" |
| > |
| {Object.keys(groupedModels) |
| .sort() |
| .map((organization) => ( |
| <optgroup key={organization} label={organization}> |
| {groupedModels[organization].map((model) => ( |
| <option |
| key={model.id} |
| value={model.id} |
| selected={settings?.NovitaLLMModelPref === model.id} |
| > |
| {model.name} |
| </option> |
| ))} |
| </optgroup> |
| ))} |
| </select> |
| </div> |
| ); |
| } |
|
|