mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
feat: select options
This commit is contained in:
parent
462660d554
commit
e8b2c2059d
5 changed files with 296 additions and 3 deletions
78
client/package-lock.json
generated
78
client/package-lock.json
generated
|
@ -13,6 +13,7 @@
|
|||
"@radix-ui/react-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||
"@radix-ui/react-label": "^2.0.0",
|
||||
"@radix-ui/react-slider": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/node": "^18.15.10",
|
||||
|
@ -2789,6 +2790,14 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/number": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.0.tgz",
|
||||
"integrity": "sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/primitive": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz",
|
||||
|
@ -3103,6 +3112,29 @@
|
|||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slider": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.1.1.tgz",
|
||||
"integrity": "sha512-0aswLpUKZIraPEOcXfwW25N1KPfLA6Mvm1TxogUChGsbLbys2ihd7uk9XAKsol9ZQPucxh2/mybwdRtAKrs/MQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/number": "1.0.0",
|
||||
"@radix-ui/primitive": "1.0.0",
|
||||
"@radix-ui/react-collection": "1.0.2",
|
||||
"@radix-ui/react-compose-refs": "1.0.0",
|
||||
"@radix-ui/react-context": "1.0.0",
|
||||
"@radix-ui/react-direction": "1.0.0",
|
||||
"@radix-ui/react-primitive": "1.0.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.0.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.0.0",
|
||||
"@radix-ui/react-use-previous": "1.0.0",
|
||||
"@radix-ui/react-use-size": "1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz",
|
||||
|
@ -3181,6 +3213,17 @@
|
|||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-previous": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.0.tgz",
|
||||
"integrity": "sha512-RG2K8z/K7InnOKpq6YLDmT49HGjNmrK+fr82UCVKT2sW0GYfVnYp4wZWBooT/EYfQ5faA9uIjvsuMMhH61rheg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-rect": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz",
|
||||
|
@ -15615,6 +15658,14 @@
|
|||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@radix-ui/number": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.0.tgz",
|
||||
"integrity": "sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
},
|
||||
"@radix-ui/primitive": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz",
|
||||
|
@ -15858,6 +15909,25 @@
|
|||
"@radix-ui/react-use-controllable-state": "1.0.0"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-slider": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.1.1.tgz",
|
||||
"integrity": "sha512-0aswLpUKZIraPEOcXfwW25N1KPfLA6Mvm1TxogUChGsbLbys2ihd7uk9XAKsol9ZQPucxh2/mybwdRtAKrs/MQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/number": "1.0.0",
|
||||
"@radix-ui/primitive": "1.0.0",
|
||||
"@radix-ui/react-collection": "1.0.2",
|
||||
"@radix-ui/react-compose-refs": "1.0.0",
|
||||
"@radix-ui/react-context": "1.0.0",
|
||||
"@radix-ui/react-direction": "1.0.0",
|
||||
"@radix-ui/react-primitive": "1.0.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.0.0",
|
||||
"@radix-ui/react-use-layout-effect": "1.0.0",
|
||||
"@radix-ui/react-use-previous": "1.0.0",
|
||||
"@radix-ui/react-use-size": "1.0.0"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-slot": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz",
|
||||
|
@ -15917,6 +15987,14 @@
|
|||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-use-previous": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.0.0.tgz",
|
||||
"integrity": "sha512-RG2K8z/K7InnOKpq6YLDmT49HGjNmrK+fr82UCVKT2sW0GYfVnYp4wZWBooT/EYfQ5faA9uIjvsuMMhH61rheg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-use-rect": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"@radix-ui/react-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||
"@radix-ui/react-label": "^2.0.0",
|
||||
"@radix-ui/react-slider": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/node": "^18.15.10",
|
||||
|
|
184
client/src/components/Input/OpenAIOptions/Settings.jsx
Normal file
184
client/src/components/Input/OpenAIOptions/Settings.jsx
Normal file
|
@ -0,0 +1,184 @@
|
|||
import React, { useRef, useState } from 'react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { Input } from '~/components/ui/Input.tsx';
|
||||
import { Label } from '~/components/ui/Label.tsx';
|
||||
import { Slider } from '~/components/ui/Slider.tsx';
|
||||
import { cn } from '~/utils/';
|
||||
const defaultTextProps =
|
||||
'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-none dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-none dark:focus:border-transparent dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
||||
|
||||
const optionText = 'p-0 shadow-none text-right pr-1 h-8';
|
||||
|
||||
function Settings() {
|
||||
const [chatGptLabel, setChatGptLabel] = useState('');
|
||||
const [promptPrefix, setPromptPrefix] = useState('');
|
||||
const [temperature, setTemperature] = useState(1);
|
||||
const [maxLength, setMaxLength] = useState(2048);
|
||||
const [topP, setTopP] = useState(1);
|
||||
const [freqP, setFreqP] = useState(0);
|
||||
const [presP, setPresP] = useState(0);
|
||||
const textareaRef = useRef(null);
|
||||
const inputRef = useRef(null);
|
||||
//
|
||||
return (
|
||||
<div>
|
||||
{/* <DialogDescription className="text-gray-600 dark:text-gray-300">
|
||||
Note: important instructions are often better placed in your message rather than the prefix.{' '}
|
||||
<a
|
||||
href="https://platform.openai.com/docs/guides/chat/instructing-chat-models"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<u>More info here</u>
|
||||
</a>
|
||||
</DialogDescription> */}
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label
|
||||
htmlFor="chatGptLabel"
|
||||
className="text-right"
|
||||
>
|
||||
Custom Name
|
||||
</Label>
|
||||
<Input
|
||||
id="chatGptLabel"
|
||||
value={chatGptLabel}
|
||||
ref={inputRef}
|
||||
onChange={e => setChatGptLabel(e.target.value)}
|
||||
placeholder="Set a custom name for ChatGPT"
|
||||
className=" col-span-3 shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 dark:bg-gray-700
|
||||
dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)]"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label
|
||||
htmlFor="promptPrefix"
|
||||
className="text-right"
|
||||
>
|
||||
Prompt Prefix
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
value={promptPrefix}
|
||||
onChange={e => setPromptPrefix(e.target.value)}
|
||||
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
||||
className={cn(defaultTextProps, 'col-span-3 flex h-10 max-h-10 w-full resize-none px-3 py-2 ')}
|
||||
onFocus={() => {
|
||||
textareaRef.current.classList.remove('max-h-10');
|
||||
textareaRef.current.classList.add('max-h-52');
|
||||
}}
|
||||
onBlur={() => {
|
||||
textareaRef.current.classList.remove('max-h-52');
|
||||
textareaRef.current.classList.add('max-h-10');
|
||||
}}
|
||||
ref={textareaRef}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-around">
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<Label
|
||||
htmlFor="temperature"
|
||||
className="mr-2 text-right"
|
||||
>
|
||||
Temperature
|
||||
</Label>
|
||||
<Input
|
||||
id="temp-int"
|
||||
value={temperature}
|
||||
onChange={e => setTemperature(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-9 ${optionText}`)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<Label
|
||||
htmlFor="max-length"
|
||||
className="mr-2 w-full text-right"
|
||||
>
|
||||
Max. length
|
||||
</Label>
|
||||
<Input
|
||||
id="max-length-int"
|
||||
value={maxLength}
|
||||
onChange={e => setMaxLength(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-11 ${optionText}`)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 items-center gap-4">
|
||||
<Slider
|
||||
defaultValue={[1]}
|
||||
onValueChange={value => setTemperature(value)}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="w-full"
|
||||
/>
|
||||
<Slider
|
||||
defaultValue={[2048]}
|
||||
onValueChange={value => setMaxLength(value)}
|
||||
max={2048}
|
||||
min={1}
|
||||
step={1}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-around">
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<Label
|
||||
htmlFor="top-p"
|
||||
className="mr-2 text-right"
|
||||
>
|
||||
Top P
|
||||
</Label>
|
||||
<Input
|
||||
id="top-p-int"
|
||||
value={topP}
|
||||
onChange={e => setTopP(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-9 ${optionText}`)}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<Label
|
||||
htmlFor="freq-penalty"
|
||||
className="mr-2 w-full text-right"
|
||||
>
|
||||
Freq. Penalty
|
||||
</Label>
|
||||
<Input
|
||||
id="freq-penalty-int"
|
||||
value={freqP}
|
||||
onChange={e => setFreqP(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-9 ${optionText}`)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 items-center gap-4">
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
onValueChange={value => setTopP(value)}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="w-full"
|
||||
/>
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
onValueChange={value => setFreqP(value)}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Settings;
|
|
@ -2,6 +2,7 @@ import React, { useState, useEffect, forwardRef } from 'react';
|
|||
import { Tabs, TabsList, TabsTrigger } from '../../ui/Tabs.tsx';
|
||||
import { useRecoilValue, useRecoilState } from 'recoil';
|
||||
import { Button } from '../../ui/Button.tsx';
|
||||
import Settings from './Settings.jsx';
|
||||
|
||||
import store from '~/store';
|
||||
|
||||
|
@ -38,11 +39,12 @@ function OpenAIOptions({ conversation = {} }) {
|
|||
<div
|
||||
className={
|
||||
cardStyle +
|
||||
' p-b-[40px] absolute left-4 right-4 bottom-[40px] flex h-[220px] flex-col rounded-md bg-white'
|
||||
' p-b-[40px] absolute left-4 right-4 bottom-[40px] flex h-[300px] flex-col rounded-md bg-white'
|
||||
}
|
||||
>
|
||||
<div>title</div>
|
||||
<div>content</div>
|
||||
<div>hi there</div>
|
||||
{/* <div>content</div> */}
|
||||
<Settings />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
28
client/src/components/ui/Slider.tsx
Normal file
28
client/src/components/ui/Slider.tsx
Normal file
|
@ -0,0 +1,28 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as SliderPrimitive from "@radix-ui/react-slider"
|
||||
|
||||
import { cn } from "../../utils"
|
||||
|
||||
const Slider = React.forwardRef<
|
||||
React.ElementRef<typeof SliderPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SliderPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex w-full touch-none select-none items-center",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<SliderPrimitive.Track className="relative h-1 w-full grow overflow-hidden rounded-full bg-gray-200 dark:bg-gray-900">
|
||||
<SliderPrimitive.Range className="absolute h-full bg-gray-700 dark:bg-gray-400" />
|
||||
</SliderPrimitive.Track>
|
||||
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border-2 border-gray-700 bg-white transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:border-gray-100 dark:bg-gray-400 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900" />
|
||||
</SliderPrimitive.Root>
|
||||
))
|
||||
Slider.displayName = SliderPrimitive.Root.displayName
|
||||
|
||||
export { Slider }
|
Loading…
Add table
Add a link
Reference in a new issue