chatbot-ui/components/ui/chat-settings-form.tsx

262 lines
7.0 KiB
TypeScript

"use client"
import { ChatbotUIContext } from "@/context/context"
import { CHAT_SETTING_LIMITS } from "@/lib/chat-setting-limits"
import { ChatSettings } from "@/types"
import { IconInfoCircle } from "@tabler/icons-react"
import { FC, useContext } from "react"
import { ModelSelect } from "../models/model-select"
import { AdvancedSettings } from "./advanced-settings"
import { Checkbox } from "./checkbox"
import { Label } from "./label"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from "./select"
import { Slider } from "./slider"
import { TextareaAutosize } from "./textarea-autosize"
import { WithTooltip } from "./with-tooltip"
import { useTranslation } from 'react-i18next'
interface ChatSettingsFormProps {
chatSettings: ChatSettings
onChangeChatSettings: (value: ChatSettings) => void
useAdvancedDropdown?: boolean
showTooltip?: boolean
}
export const ChatSettingsForm: FC<ChatSettingsFormProps> = ({
chatSettings,
onChangeChatSettings,
useAdvancedDropdown = true,
showTooltip = true
}) => {
const { t } = useTranslation()
const { profile, models } = useContext(ChatbotUIContext)
if (!profile) return null
return (
<div className="space-y-3">
<div className="space-y-1">
<Label>{t("chat.modelLabel")}</Label>
<ModelSelect
selectedModelId={chatSettings.model}
onSelectModel={model => {
onChangeChatSettings({ ...chatSettings, model })
}}
/>
</div>
<div className="space-y-1">
<Label>{t("chat.promptLabel")}</Label>
<TextareaAutosize
className="bg-background border-input border-2"
placeholder={t("chat.promptPlaceholder")}
onValueChange={prompt => {
onChangeChatSettings({ ...chatSettings, prompt })
}}
value={chatSettings.prompt}
minRows={3}
maxRows={6}
/>
</div>
{useAdvancedDropdown ? (
<AdvancedSettings>
<AdvancedContent
chatSettings={chatSettings}
onChangeChatSettings={onChangeChatSettings}
showTooltip={showTooltip}
/>
</AdvancedSettings>
) : (
<div>
<AdvancedContent
chatSettings={chatSettings}
onChangeChatSettings={onChangeChatSettings}
showTooltip={showTooltip}
/>
</div>
)}
</div>
)
}
interface AdvancedContentProps {
chatSettings: ChatSettings
onChangeChatSettings: (value: ChatSettings) => void
showTooltip: boolean
}
const AdvancedContent: FC<AdvancedContentProps> = ({
chatSettings,
onChangeChatSettings,
showTooltip
}) => {
const { t } = useTranslation()
const { profile, selectedWorkspace, availableOpenRouterModels, models } =
useContext(ChatbotUIContext)
const isCustomModel = models.some(
model => model.model_id === chatSettings.model
)
function findOpenRouterModel(modelId: string) {
return availableOpenRouterModels.find(model => model.modelId === modelId)
}
const MODEL_LIMITS = CHAT_SETTING_LIMITS[chatSettings.model] || {
MIN_TEMPERATURE: 0,
MAX_TEMPERATURE: 1,
MAX_CONTEXT_LENGTH:
findOpenRouterModel(chatSettings.model)?.maxContext || 4096
}
return (
<div className="mt-5">
<div className="space-y-3">
<Label className="flex items-center space-x-1">
<div>{t("chat.temperatureLabel")}:</div>
<div>{chatSettings.temperature}</div>
</Label>
<Slider
value={[chatSettings.temperature]}
onValueChange={temperature => {
onChangeChatSettings({
...chatSettings,
temperature: temperature[0]
})
}}
min={MODEL_LIMITS.MIN_TEMPERATURE}
max={MODEL_LIMITS.MAX_TEMPERATURE}
step={0.01}
/>
</div>
<div className="mt-6 space-y-3">
<Label className="flex items-center space-x-1">
<div>{t("chat.contextLengthLabel")}:</div>
<div>{chatSettings.contextLength}</div>
</Label>
<Slider
value={[chatSettings.contextLength]}
onValueChange={contextLength => {
onChangeChatSettings({
...chatSettings,
contextLength: contextLength[0]
})
}}
min={0}
max={
isCustomModel
? models.find(model => model.model_id === chatSettings.model)
?.context_length
: MODEL_LIMITS.MAX_CONTEXT_LENGTH
}
step={1}
/>
</div>
<div className="mt-7 flex items-center space-x-2">
<Checkbox
checked={chatSettings.includeProfileContext}
onCheckedChange={(value: boolean) =>
onChangeChatSettings({
...chatSettings,
includeProfileContext: value
})
}
/>
<Label>{t("chat.includeProfileContextLabel")}</Label>
{showTooltip && (
<WithTooltip
delayDuration={0}
display={
<div className="w-[400px] p-3">
{profile?.profile_context || t("chat.noProfileContext")}
</div>
}
trigger={
<IconInfoCircle className="cursor-hover:opacity-50" size={16} />
}
/>
)}
</div>
<div className="mt-4 flex items-center space-x-2">
<Checkbox
checked={chatSettings.includeWorkspaceInstructions}
onCheckedChange={(value: boolean) =>
onChangeChatSettings({
...chatSettings,
includeWorkspaceInstructions: value
})
}
/>
<Label>{t("chat.includeWorkspaceInstructionsLabel")}</Label>
{showTooltip && (
<WithTooltip
delayDuration={0}
display={
<div className="w-[400px] p-3">
{selectedWorkspace?.instructions ||
"No workspace instructions."}
</div>
}
trigger={
<IconInfoCircle className="cursor-hover:opacity-50" size={16} />
}
/>
)}
</div>
<div className="mt-5">
<Label>{t("chat.embeddingsProviderLabel")}</Label>
<Select
value={chatSettings.embeddingsProvider}
onValueChange={(embeddingsProvider: "openai" | "local") => {
onChangeChatSettings({
...chatSettings,
embeddingsProvider
})
}}
>
<SelectTrigger>
<SelectValue defaultValue="openai" />
</SelectTrigger>
<SelectContent>
<SelectItem value="openai">
{profile?.use_azure_openai ? t("chat.azureOpenAI") : t("chat.openAI")}
</SelectItem>
{window.location.hostname === "localhost" && (
<SelectItem value="local">{t("chat.local")}</SelectItem>
)}
</SelectContent>
</Select>
</div>
</div>
)
}