Fix dropdown filter bug and add save button animation

This commit is contained in:
n4ze3m 2024-02-25 23:45:07 +05:30
parent 094615498c
commit 03db4631d7
7 changed files with 272 additions and 85 deletions

View File

@ -1,5 +1,5 @@
import { useState } from "react"
import { CheckIcon } from "lucide-react"
type Props = {
onClick?: () => void
disabled?: boolean
@ -23,13 +23,16 @@ export const SaveButton = ({
type={btnType}
onClick={() => {
setClickedSave(true)
if (onClick) {
onClick()
}
setTimeout(() => {
setClickedSave(false)
}, 1000)
}}
disabled={disabled}
className={`inline-flex mt-4 items-center rounded-md border border-transparent bg-black px-2 py-2 text-sm font-medium leading-4 text-white shadow-sm dark:bg-white dark:text-gray-800 disabled:opacity-50 ${className}`}>
{clickedSave ? <CheckIcon className="w-4 h-4 mr-2" /> : null}
{clickedSave ? textOnSave : text}
</button>
)

View File

@ -262,9 +262,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
{!isSending ? (
<Dropdown.Button
htmlType="submit"
disabled={
isSending || form.values.message.trim().length === 0
}
disabled={isSending}
className="!justify-end !w-auto"
icon={
<svg
@ -287,7 +285,7 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
key: 1,
label: (
<Checkbox
value={sendWhenEnter}
checked={sendWhenEnter}
onChange={(e) =>
setSendWhenEnter(e.target.checked)
}>

View File

@ -1,29 +1,55 @@
import { useQuery } from "@tanstack/react-query"
import { useEffect, useState } from "react"
import { useMutation, useQuery } from "@tanstack/react-query"
import { Form, InputNumber, Select, Skeleton } from "antd"
import { useState } from "react"
import { SaveButton } from "~components/Common/SaveButton"
import { getOllamaURL, setOllamaURL as saveOllamaURL } from "~services/ollama"
import {
defaultEmbeddingChunkOverlap,
defaultEmbeddingChunkSize,
defaultEmbeddingModelForRag,
getAllModels,
getOllamaURL,
saveForRag,
setOllamaURL as saveOllamaURL
} from "~services/ollama"
export const SettingsOllama = () => {
const [ollamaURL, setOllamaURL] = useState<string>("")
const { data: ollamaInfo } = useQuery({
const { data: ollamaInfo, status } = useQuery({
queryKey: ["fetchOllamURL"],
queryFn: async () => {
const ollamaURL = await getOllamaURL()
const [ollamaURL, allModels, chunkOverlap, chunkSize, defaultEM] =
await Promise.all([
getOllamaURL(),
getAllModels(),
defaultEmbeddingChunkOverlap(),
defaultEmbeddingChunkSize(),
defaultEmbeddingModelForRag()
])
setOllamaURL(ollamaURL)
return {
ollamaURL
models: allModels,
chunkOverlap,
chunkSize,
defaultEM
}
}
})
useEffect(() => {
if (ollamaInfo?.ollamaURL) {
setOllamaURL(ollamaInfo.ollamaURL)
const { mutate: saveRAG, isPending: isSaveRAGPending } = useMutation({
mutationFn: async (data: {
model: string
chunkSize: number
overlap: number
}) => {
await saveForRag(data.model, data.chunkSize, data.overlap)
}
}, [ollamaInfo])
})
return (
<div className="">
<div className="flex flex-col gap-3">
{status === "pending" && <Skeleton paragraph={{ rows: 4 }} active />}
{status === "success" && (
<>
<div>
<label
htmlFor="ollamaURL"
@ -49,6 +75,70 @@ export const SettingsOllama = () => {
className="mt-2"
/>
</div>
<Form
layout="vertical"
onFinish={(data) => {
saveRAG({
model: data.defaultEM,
chunkSize: data.chunkSize,
overlap: data.chunkOverlap
})
}}
initialValues={{
chunkSize: ollamaInfo?.chunkSize,
chunkOverlap: ollamaInfo?.chunkOverlap,
defaultEM: ollamaInfo?.defaultEM
}}>
<Form.Item
name="defaultEM"
label="Embedding Model"
help="Highly recommended to use embedding models like `nomic-embed-text`."
rules={[{ required: true, message: "Please select a model!" }]}>
<Select
size="large"
filterOption={(input, option) =>
option.label.toLowerCase().indexOf(input.toLowerCase()) >=
0 ||
option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
showSearch
placeholder="Select a model"
style={{ width: "100%" }}
className="mt-4"
options={ollamaInfo.models?.map((model) => ({
label: model.name,
value: model.model
}))}
/>
</Form.Item>
<Form.Item
name="chunkSize"
label="Chunk Size"
rules={[
{ required: true, message: "Please input your chunk size!" }
]}>
<InputNumber style={{ width: "100%" }} placeholder="Chunk Size" />
</Form.Item>
<Form.Item
name="chunkOverlap"
label="Chunk Overlap"
rules={[
{ required: true, message: "Please input your chunk overlap!" }
]}>
<InputNumber
style={{ width: "100%" }}
placeholder="Chunk Overlap"
/>
</Form.Item>
<div className="flex justify-end">
<SaveButton disabled={isSaveRAGPending} btnType="submit" />
</div>
</Form>
</>
)}
</div>
)
}

View File

@ -1,56 +1,146 @@
import { useQuery } from "@tanstack/react-query"
import { useEffect, useState } from "react"
import { useQuery, useQueryClient } from "@tanstack/react-query"
import { Skeleton, Radio, Form } from "antd"
import React from "react"
import { SaveButton } from "~components/Common/SaveButton"
import {
getWebSearchPrompt,
setSystemPromptForNonRagOption,
systemPromptForNonRagOption
systemPromptForNonRagOption,
geWebSearchFollowUpPrompt,
setWebPrompts
} from "~services/ollama"
export const SettingPrompt = () => {
const [ollamaPrompt, setOllamaPrompt] = useState<string>("")
const { data: ollamaInfo } = useQuery({
const [selectedValue, setSelectedValue] = React.useState<"normal" | "web">(
"normal"
)
const queryClient = useQueryClient()
const { status, data } = useQuery({
queryKey: ["fetchOllaPrompt"],
queryFn: async () => {
const prompt = await systemPromptForNonRagOption()
const [prompt, webSearchPrompt, webSearchFollowUpPrompt] =
await Promise.all([
systemPromptForNonRagOption(),
getWebSearchPrompt(),
geWebSearchFollowUpPrompt()
])
return {
prompt
prompt,
webSearchPrompt,
webSearchFollowUpPrompt
}
}
})
useEffect(() => {
if (ollamaInfo?.prompt) {
setOllamaPrompt(ollamaInfo.prompt)
}
}, [ollamaInfo])
return (
<div className="">
<div className="flex flex-col gap-3">
{status === "pending" && <Skeleton paragraph={{ rows: 4 }} active />}
{status === "success" && (
<div>
<label htmlFor="ollamaPrompt" className="text-sm font-medium dark:text-gray-200">
System Prompt
</label>
<h2 className="text-md font-semibold dark:text-white">Prompt</h2>
<div className="my-3 flex justify-end">
<Radio.Group
defaultValue={selectedValue}
onChange={(e) => setSelectedValue(e.target.value)}>
<Radio.Button value="normal">Normal</Radio.Button>
<Radio.Button value="web">Web</Radio.Button>
</Radio.Group>
</div>
{selectedValue === "normal" && (
<Form
layout="vertical"
onFinish={(values) => {
setSystemPromptForNonRagOption(values?.prompt || "")
queryClient.invalidateQueries({
queryKey: ["fetchOllaPrompt"]
})
}}
initialValues={{
prompt: data.prompt
}}>
<Form.Item label="System Prompt" name="prompt">
<textarea
value={ollamaPrompt}
value={data.prompt}
rows={5}
id="ollamaPrompt"
placeholder="Your System Prompt"
onChange={(e) => {
setOllamaPrompt(e.target.value)
}}
className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100"
/>
</div>
</Form.Item>
<Form.Item>
<div className="flex justify-end">
<SaveButton
onClick={() => {
setSystemPromptForNonRagOption(ollamaPrompt)
<SaveButton btnType="submit" />
</div>{" "}
</Form.Item>
</Form>
)}
{selectedValue === "web" && (
<Form
layout="vertical"
onFinish={(values) => {
setWebPrompts(
values?.webSearchPrompt || "",
values?.webSearchFollowUpPrompt || ""
)
queryClient.invalidateQueries({
queryKey: ["fetchOllaPrompt"]
})
}}
className="mt-2"
initialValues={{
webSearchPrompt: data.webSearchPrompt,
webSearchFollowUpPrompt: data.webSearchFollowUpPrompt
}}>
<Form.Item
label="Web Search Prompt"
name="webSearchPrompt"
help="Do not remove `{search_results}` from the prompt."
rules={[
{
required: true,
message: "Please input your Web Search Prompt!"
}
]}>
<textarea
value={data.webSearchPrompt}
rows={5}
id="ollamaWebSearchPrompt"
placeholder="Your Web Search Prompt"
className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100"
/>
</Form.Item>
<Form.Item
label="Web Search Follow Up Prompt"
name="webSearchFollowUpPrompt"
help="Do not remove `{chat_history}` and `{question}` from the prompt."
rules={[
{
required: true,
message: "Please input your Web Search Follow Up Prompt!"
}
]}>
<textarea
value={data.webSearchFollowUpPrompt}
rows={5}
id="ollamaWebSearchFollowUpPrompt"
placeholder="Your Web Search Follow Up Prompt"
className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100"
/>
</Form.Item>
<Form.Item>
<div className="flex justify-end">
<SaveButton btnType="submit" />
</div>{" "}
</Form.Item>
</Form>
)}
</div>
)}
</div>
)
}

View File

@ -212,7 +212,7 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
<Dropdown.Button
htmlType="submit"
disabled={
isSending || form.values.message.trim().length === 0
isSending
}
className="!justify-end !w-auto"
icon={
@ -236,7 +236,7 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
key: 1,
label: (
<Checkbox
value={sendWhenEnter}
checked={sendWhenEnter}
onChange={(e) =>
setSendWhenEnter(e.target.checked)
}>

View File

@ -280,3 +280,9 @@ export const geWebSearchFollowUpPrompt = async () => {
export const setWebSearchFollowUpPrompt = async (prompt: string) => {
await storage.set("webSearchFollowUpPrompt", prompt)
}
export const setWebPrompts = async (prompt: string, followUpPrompt: string) => {
await setWebSearchPrompt(prompt)
await setWebSearchFollowUpPrompt(followUpPrompt)
}