feat: Add system and quick prompts on side panel

This commit is contained in:
n4ze3m 2024-09-14 12:07:54 +05:30
parent 5602714ee2
commit 53d999a596
9 changed files with 115 additions and 31 deletions

View File

@ -4,20 +4,27 @@ import { BookIcon, ComputerIcon, ZapIcon } from "lucide-react"
import React from "react" import React from "react"
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import { getAllPrompts } from "@/db" import { getAllPrompts } from "@/db"
import { useMessageOption } from "@/hooks/useMessageOption"
export const PromptSelect: React.FC = () => { type Props = {
setSelectedSystemPrompt: (promptId: string | undefined) => void
setSelectedQuickPrompt: (prompt: string | undefined) => void
selectedSystemPrompt: string | undefined
className?: string
}
export const PromptSelect: React.FC<Props> = ({
setSelectedQuickPrompt,
setSelectedSystemPrompt,
selectedSystemPrompt,
className = "dark:text-gray-300"
}) => {
const { t } = useTranslation("option") const { t } = useTranslation("option")
const {
selectedSystemPrompt,
setSelectedQuickPrompt,
setSelectedSystemPrompt
} = useMessageOption()
const { data } = useQuery({ const { data } = useQuery({
queryKey: ["getAllPromptsForSelect"], queryKey: ["getAllPromptsForSelect"],
queryFn: getAllPrompts queryFn: getAllPrompts
}) })
const handlePromptChange = (value?: string) => { const handlePromptChange = (value?: string) => {
if (!value) { if (!value) {
setSelectedSystemPrompt(undefined) setSelectedSystemPrompt(undefined)
@ -79,7 +86,7 @@ export const PromptSelect: React.FC = () => {
placement={"topLeft"} placement={"topLeft"}
trigger={["click"]}> trigger={["click"]}>
<Tooltip title={t("selectAPrompt")}> <Tooltip title={t("selectAPrompt")}>
<button type="button" className="dark:text-gray-300"> <button type="button" className={className}>
<BookIcon className="h-5 w-5" /> <BookIcon className="h-5 w-5" />
</button> </button>
</Tooltip> </Tooltip>

View File

@ -45,7 +45,7 @@ export const Header: React.FC<Props> = ({
setSelectedQuickPrompt, setSelectedQuickPrompt,
setSelectedSystemPrompt, setSelectedSystemPrompt,
messages, messages,
streaming streaming,
} = useMessageOption() } = useMessageOption()
const { const {
data: models, data: models,
@ -182,7 +182,11 @@ export const Header: React.FC<Props> = ({
/> />
</div> </div>
<div className="lg:hidden"> <div className="lg:hidden">
<PromptSelect /> <PromptSelect
selectedSystemPrompt={selectedSystemPrompt}
setSelectedSystemPrompt={setSelectedSystemPrompt}
setSelectedQuickPrompt={setSelectedQuickPrompt}
/>
</div> </div>
<SelectedKnowledge /> <SelectedKnowledge />
</div> </div>

View File

@ -24,7 +24,6 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
const { sendWhenEnter, setSendWhenEnter } = useWebUI() const { sendWhenEnter, setSendWhenEnter } = useWebUI()
const [typing, setTyping] = React.useState<boolean>(false) const [typing, setTyping] = React.useState<boolean>(false)
const { t } = useTranslation(["playground", "common"]) const { t } = useTranslation(["playground", "common"])
const form = useForm({ const form = useForm({
initialValues: { initialValues: {
message: "", message: "",
@ -37,7 +36,7 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
resetTranscript, resetTranscript,
start: startListening, start: startListening,
stop: stopSpeechRecognition, stop: stopSpeechRecognition,
supported: browserSupportsSpeechRecognition supported: browserSupportsSpeechRecognition,
} = useSpeechRecognition() } = useSpeechRecognition()
const stopListening = async () => { const stopListening = async () => {
@ -118,12 +117,14 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
onSubmit, onSubmit,
selectedModel, selectedModel,
chatMode, chatMode,
speechToTextLanguage,
stopStreamingRequest, stopStreamingRequest,
streaming, streaming,
setChatMode, setChatMode,
webSearch, webSearch,
setWebSearch setWebSearch,
selectedQuickPrompt,
setSelectedQuickPrompt,
speechToTextLanguage
} = useMessage() } = useMessage()
React.useEffect(() => { React.useEffect(() => {
@ -139,6 +140,23 @@ export const SidepanelForm = ({ dropedFile }: Props) => {
form.setFieldValue("message", transcript) form.setFieldValue("message", transcript)
} }
}, [transcript]) }, [transcript])
React.useEffect(() => {
if (selectedQuickPrompt) {
const word = getVariable(selectedQuickPrompt)
form.setFieldValue("message", selectedQuickPrompt)
if (word) {
textareaRef.current?.focus()
const interval = setTimeout(() => {
textareaRef.current?.setSelectionRange(word.start, word.end)
setSelectedQuickPrompt(null)
}, 100)
return () => {
clearInterval(interval)
}
}
}
}, [selectedQuickPrompt])
const { mutateAsync: sendMessage, isPending: isSending } = useMutation({ const { mutateAsync: sendMessage, isPending: isSending } = useMutation({
mutationFn: onSubmit, mutationFn: onSubmit,
onSuccess: () => { onSuccess: () => {

View File

@ -7,13 +7,22 @@ import { useTranslation } from "react-i18next"
import { CurrentChatModelSettings } from "@/components/Common/Settings/CurrentChatModelSettings" import { CurrentChatModelSettings } from "@/components/Common/Settings/CurrentChatModelSettings"
import React from "react" import React from "react"
import { useStorage } from "@plasmohq/storage/hook" import { useStorage } from "@plasmohq/storage/hook"
import { PromptSelect } from "@/components/Common/PromptSelect"
export const SidepanelHeader = () => { export const SidepanelHeader = () => {
const [hideCurrentChatModelSettings] = useStorage( const [hideCurrentChatModelSettings] = useStorage(
"hideCurrentChatModelSettings", "hideCurrentChatModelSettings",
false false
) )
const { clearChat, isEmbedding, messages, streaming } = useMessage() const {
clearChat,
isEmbedding,
messages,
streaming,
selectedSystemPrompt,
setSelectedSystemPrompt,
setSelectedQuickPrompt
} = useMessage()
const { t } = useTranslation(["sidepanel", "common"]) const { t } = useTranslation(["sidepanel", "common"])
const [openModelSettings, setOpenModelSettings] = React.useState(false) const [openModelSettings, setOpenModelSettings] = React.useState(false)
@ -44,11 +53,13 @@ export const SidepanelHeader = () => {
<EraserIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" /> <EraserIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" />
</button> </button>
)} )}
{/* <Tooltip title={t("tooltip.history")}> <PromptSelect
<Link to="/history"> selectedSystemPrompt={selectedSystemPrompt}
<HistoryIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" /> setSelectedSystemPrompt={setSelectedSystemPrompt}
</Link> setSelectedQuickPrompt={setSelectedQuickPrompt}
</Tooltip> */} className="text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"
/>
{!hideCurrentChatModelSettings && ( {!hideCurrentChatModelSettings && (
<Tooltip title={t("common:currentChatModelSettings")}> <Tooltip title={t("common:currentChatModelSettings")}>
<button <button

View File

@ -17,6 +17,7 @@ import { ChatHistory } from "@/store/option"
import { import {
deleteChatForEdit, deleteChatForEdit,
generateID, generateID,
getPromptById,
removeMessageUsingHistoryId, removeMessageUsingHistoryId,
updateMessageByIndex updateMessageByIndex
} from "@/db" } from "@/db"
@ -75,9 +76,18 @@ export const useMessage = () => {
setIsEmbedding, setIsEmbedding,
isEmbedding, isEmbedding,
currentURL, currentURL,
setCurrentURL setCurrentURL,
selectedQuickPrompt,
setSelectedQuickPrompt,
selectedSystemPrompt,
setSelectedSystemPrompt
} = useStoreMessage() } = useStoreMessage()
const [speechToTextLanguage, setSpeechToTextLanguage] = useStorage(
"speechToTextLanguage",
"en-US"
)
const [keepTrackOfEmbedding, setKeepTrackOfEmbedding] = React.useState<{ const [keepTrackOfEmbedding, setKeepTrackOfEmbedding] = React.useState<{
[key: string]: MemoryVectorStore [key: string]: MemoryVectorStore
}>({}) }>({})
@ -488,6 +498,7 @@ export const useMessage = () => {
try { try {
const prompt = await systemPromptForNonRag() const prompt = await systemPromptForNonRag()
const selectedPrompt = await getPromptById(selectedSystemPrompt)
let humanMessage = new HumanMessage({ let humanMessage = new HumanMessage({
content: [ content: [
@ -514,7 +525,7 @@ export const useMessage = () => {
const applicationChatHistory = generateHistory(history) const applicationChatHistory = generateHistory(history)
if (prompt) { if (prompt && !selectedPrompt) {
applicationChatHistory.unshift( applicationChatHistory.unshift(
new SystemMessage({ new SystemMessage({
content: [ content: [
@ -526,6 +537,18 @@ export const useMessage = () => {
}) })
) )
} }
if (selectedPrompt) {
applicationChatHistory.unshift(
new SystemMessage({
content: [
{
text: selectedPrompt.content,
type: "text"
}
]
})
)
}
const chunks = await ollama.stream( const chunks = await ollama.stream(
[...applicationChatHistory, humanMessage], [...applicationChatHistory, humanMessage],
@ -1231,6 +1254,12 @@ export const useMessage = () => {
regenerateLastMessage, regenerateLastMessage,
webSearch, webSearch,
setWebSearch, setWebSearch,
isSearchingInternet isSearchingInternet,
selectedQuickPrompt,
setSelectedQuickPrompt,
selectedSystemPrompt,
setSelectedSystemPrompt,
speechToTextLanguage,
setSpeechToTextLanguage
} }
} }

View File

@ -55,8 +55,6 @@ export const useMessageOption = () => {
setIsProcessing, setIsProcessing,
chatMode, chatMode,
setChatMode, setChatMode,
speechToTextLanguage,
setSpeechToTextLanguage,
webSearch, webSearch,
setWebSearch, setWebSearch,
isSearchingInternet, isSearchingInternet,
@ -70,7 +68,10 @@ export const useMessageOption = () => {
} = useStoreMessageOption() } = useStoreMessageOption()
const currentChatModelSettings = useStoreChatModelSettings() const currentChatModelSettings = useStoreChatModelSettings()
const [selectedModel, setSelectedModel] = useStorage("selectedModel") const [selectedModel, setSelectedModel] = useStorage("selectedModel")
const [ speechToTextLanguage, setSpeechToTextLanguage ] = useStorage(
"speechToTextLanguage",
"en-US"
)
const { ttsEnabled } = useWebUI() const { ttsEnabled } = useWebUI()
const { t } = useTranslation("option") const { t } = useTranslation("option")
@ -411,8 +412,6 @@ export const useMessageOption = () => {
const prompt = await systemPromptForNonRagOption() const prompt = await systemPromptForNonRagOption()
const selectedPrompt = await getPromptById(selectedSystemPrompt) const selectedPrompt = await getPromptById(selectedSystemPrompt)
// message = message.trim().replaceAll("\n", " ")
let humanMessage = new HumanMessage({ let humanMessage = new HumanMessage({
content: [ content: [
{ {

View File

@ -329,13 +329,15 @@ export const saveForRag = async (
chunkSize: number, chunkSize: number,
overlap: number, overlap: number,
totalFilePerKB: number, totalFilePerKB: number,
noOfRetrievedDocs: number noOfRetrievedDocs?: number
) => { ) => {
await setDefaultEmbeddingModelForRag(model) await setDefaultEmbeddingModelForRag(model)
await setDefaultEmbeddingChunkSize(chunkSize) await setDefaultEmbeddingChunkSize(chunkSize)
await setDefaultEmbeddingChunkOverlap(overlap) await setDefaultEmbeddingChunkOverlap(overlap)
await setTotalFilePerKB(totalFilePerKB) await setTotalFilePerKB(totalFilePerKB)
await setNoOfRetrievedDocs(noOfRetrievedDocs) if(noOfRetrievedDocs) {
await setNoOfRetrievedDocs(noOfRetrievedDocs)
}
} }
export const getWebSearchPrompt = async () => { export const getWebSearchPrompt = async () => {

View File

@ -40,6 +40,11 @@ type State = {
setSpeechToTextLanguage: (speechToTextLanguage: string) => void setSpeechToTextLanguage: (speechToTextLanguage: string) => void
currentURL: string currentURL: string
setCurrentURL: (currentURL: string) => void setCurrentURL: (currentURL: string) => void
selectedSystemPrompt: string | null
setSelectedSystemPrompt: (selectedSystemPrompt: string) => void
selectedQuickPrompt: string | null
setSelectedQuickPrompt: (selectedQuickPrompt: string) => void
} }
export const useStoreMessage = create<State>((set) => ({ export const useStoreMessage = create<State>((set) => ({
@ -68,5 +73,11 @@ export const useStoreMessage = create<State>((set) => ({
setSpeechToTextLanguage: (speechToTextLanguage) => setSpeechToTextLanguage: (speechToTextLanguage) =>
set({ speechToTextLanguage }), set({ speechToTextLanguage }),
currentURL: "", currentURL: "",
setCurrentURL: (currentURL) => set({ currentURL }) setCurrentURL: (currentURL) => set({ currentURL }),
selectedSystemPrompt: null,
setSelectedSystemPrompt: (selectedSystemPrompt) =>
set({ selectedSystemPrompt }),
selectedQuickPrompt: null,
setSelectedQuickPrompt: (selectedQuickPrompt) => set({ selectedQuickPrompt })
})) }))

View File

@ -62,6 +62,9 @@ type State = {
selectedKnowledge: Knowledge | null selectedKnowledge: Knowledge | null
setSelectedKnowledge: (selectedKnowledge: Knowledge) => void setSelectedKnowledge: (selectedKnowledge: Knowledge) => void
setSpeechToTextLanguage: (language: string) => void
speechToTextLanguage: string
} }
export const useStoreMessageOption = create<State>((set) => ({ export const useStoreMessageOption = create<State>((set) => ({