* feat: adding create bot functionality Signed-off-by: James <james@jan.ai> * update the temperature progress bar Signed-off-by: James <james@jan.ai> * WIP baselayout * Mapping plugins with available preferences * Added loader component * WIP working another screen * Cleanup types and avoid import one by one * Prepare bottom bar * Add css variables colors to enable user select the accent * Enable change accent color * Seperate css variable * Fix conflict * Add blank state of my model empty * Restyle explore models page * Enable user config left sidebar * Restyle my models page * WIP styling chat page * Restyling chat message * Fix conflict * Adde form preferences setting plugins * Fixed form bot info * Sidebar bot chat * Showing rightbar for both setting when user created bot * Fix style bot info * Using overflow auto intead of scroll * Remove script built UI from root package * Fix missig import * Resolve error linter * fix e2e tests Signed-off-by: James <james@jan.ai> --------- Signed-off-by: James <james@jan.ai> Co-authored-by: James <james@jan.ai>
170 lines
5.5 KiB
TypeScript
170 lines
5.5 KiB
TypeScript
import { activeBotAtom } from '@helpers/atoms/Bot.atom'
|
|
import { useAtomValue } from 'jotai'
|
|
import React, { useState } from 'react'
|
|
import ExpandableHeader from '../ExpandableHeader'
|
|
import { useDebouncedCallback } from 'use-debounce'
|
|
import useUpdateBot from '@hooks/useUpdateBot'
|
|
import { formatTwoDigits } from '@utils/converter'
|
|
|
|
const delayBeforeUpdateInMs = 1000
|
|
|
|
const BotSetting: React.FC = () => {
|
|
const activeBot = useAtomValue(activeBotAtom)
|
|
const [temperature, setTemperature] = useState(
|
|
activeBot?.customTemperature ?? 0
|
|
)
|
|
|
|
const [maxTokens, setMaxTokens] = useState(activeBot?.maxTokens ?? 0)
|
|
const [frequencyPenalty, setFrequencyPenalty] = useState(
|
|
activeBot?.frequencyPenalty ?? 0
|
|
)
|
|
const [presencePenalty, setPresencePenalty] = useState(
|
|
activeBot?.presencePenalty ?? 0
|
|
)
|
|
|
|
const { updateBot } = useUpdateBot()
|
|
|
|
const debouncedTemperature = useDebouncedCallback((value) => {
|
|
if (!activeBot) return
|
|
if (activeBot.customTemperature === value) return
|
|
updateBot(activeBot, { customTemperature: value })
|
|
}, delayBeforeUpdateInMs)
|
|
|
|
const debouncedMaxToken = useDebouncedCallback((value) => {
|
|
if (!activeBot) return
|
|
if (activeBot.maxTokens === value) return
|
|
updateBot(activeBot, { maxTokens: value })
|
|
}, delayBeforeUpdateInMs)
|
|
|
|
const debouncedFreqPenalty = useDebouncedCallback((value) => {
|
|
if (!activeBot) return
|
|
if (activeBot.frequencyPenalty === value) return
|
|
updateBot(activeBot, { frequencyPenalty: value })
|
|
}, delayBeforeUpdateInMs)
|
|
|
|
const debouncedPresencePenalty = useDebouncedCallback((value) => {
|
|
if (!activeBot) return
|
|
if (activeBot.presencePenalty === value) return
|
|
updateBot(activeBot, { presencePenalty: value })
|
|
}, delayBeforeUpdateInMs)
|
|
|
|
const debouncedSystemPrompt = useDebouncedCallback((value) => {
|
|
if (!activeBot) return
|
|
if (activeBot.systemPrompt === value) return
|
|
updateBot(activeBot, { systemPrompt: value })
|
|
}, delayBeforeUpdateInMs)
|
|
|
|
if (!activeBot) return null
|
|
|
|
return (
|
|
<div className="my-3 flex flex-col">
|
|
<ExpandableHeader title="BOT SETTINGS" />
|
|
<div className="mx-2 mt-3 flex flex-shrink-0 flex-col gap-4">
|
|
{/* System prompt */}
|
|
<div>
|
|
<label htmlFor="comment" className="block">
|
|
System prompt
|
|
</label>
|
|
<div className="mt-1">
|
|
<textarea
|
|
rows={4}
|
|
name="comment"
|
|
id="comment"
|
|
className="bg-background/80 text-background-reverse ring-border placeholder:text-muted-foreground focus:ring-accent/50 block w-full resize-none rounded-md border-0 py-1.5 text-xs leading-relaxed shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset"
|
|
defaultValue={activeBot.systemPrompt}
|
|
onChange={(e) => debouncedSystemPrompt(e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* TODO: clean up this code */}
|
|
{/* Max temp */}
|
|
<p>Max tokens</p>
|
|
<div className="mt-2 flex items-center gap-2">
|
|
<input
|
|
className="flex-1"
|
|
type="range"
|
|
defaultValue={activeBot.maxTokens ?? 0}
|
|
min={0}
|
|
max={4096}
|
|
step={1}
|
|
onChange={(e) => {
|
|
const value = Number(e.target.value)
|
|
setMaxTokens(value)
|
|
debouncedMaxToken(value)
|
|
}}
|
|
/>
|
|
<span className="border-accent rounded-md border px-2 py-1">
|
|
{formatTwoDigits(maxTokens)}
|
|
</span>
|
|
</div>
|
|
|
|
<p>Frequency penalty</p>
|
|
<div className="mt-2 flex items-center gap-2">
|
|
<input
|
|
className="flex-1"
|
|
type="range"
|
|
defaultValue={activeBot.frequencyPenalty ?? 0}
|
|
min={0}
|
|
max={1}
|
|
step={0.01}
|
|
onChange={(e) => {
|
|
const value = Number(e.target.value)
|
|
setFrequencyPenalty(value)
|
|
debouncedFreqPenalty(value)
|
|
}}
|
|
/>
|
|
<span className="border-accent rounded-md border px-2 py-1">
|
|
{formatTwoDigits(frequencyPenalty)}
|
|
</span>
|
|
</div>
|
|
|
|
<p>Presence penalty</p>
|
|
<div className="mt-2 flex items-center gap-2">
|
|
<input
|
|
className="flex-1"
|
|
type="range"
|
|
defaultValue={activeBot.maxTokens ?? 0}
|
|
min={0}
|
|
max={1}
|
|
step={0.01}
|
|
onChange={(e) => {
|
|
const value = Number(e.target.value)
|
|
setPresencePenalty(value)
|
|
debouncedPresencePenalty(value)
|
|
}}
|
|
/>
|
|
<span className="border-accent rounded-md border px-2 py-1">
|
|
{formatTwoDigits(presencePenalty)}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Custom temp */}
|
|
<p>Temperature</p>
|
|
<div className="mt-2 flex items-center gap-2">
|
|
<input
|
|
className="flex-1"
|
|
type="range"
|
|
id="volume"
|
|
name="volume"
|
|
defaultValue={activeBot.customTemperature ?? 0}
|
|
min="0"
|
|
max="1"
|
|
step="0.01"
|
|
onChange={(e) => {
|
|
const newTemp = Number(e.target.value)
|
|
setTemperature(newTemp)
|
|
debouncedTemperature(Number(e.target.value))
|
|
}}
|
|
/>
|
|
<span className="border-accent rounded-md border px-2 py-1">
|
|
{formatTwoDigits(temperature)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default BotSetting
|