fix: RAG enhancements (#1965)
* fix: rag enhancements * fix: remove auto generate prompt when user attach file * fix: remove auto generate promp attach file via dropzone * finalize RAG enhancements * customize title of action sidebar panel * remove useless import * fix miss align retrieval toggle with switch check
This commit is contained in:
parent
dfaab4fd28
commit
9e7348e623
@ -1,6 +1,6 @@
|
|||||||
.input {
|
.input {
|
||||||
@apply border-border placeholder:text-muted-foreground flex h-9 w-full rounded-lg border bg-transparent px-3 py-1 transition-colors;
|
@apply border-border placeholder:text-muted-foreground flex h-9 w-full rounded-lg border bg-transparent px-3 py-1 transition-colors;
|
||||||
@apply disabled:cursor-not-allowed disabled:bg-zinc-100 disabled:dark:bg-zinc-800 disabled:dark:text-zinc-600;
|
@apply disabled:text-muted-foreground disabled:cursor-not-allowed disabled:bg-zinc-100 disabled:dark:bg-zinc-800 disabled:dark:text-zinc-600;
|
||||||
@apply focus-within:outline-none focus-visible:outline-0 focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1;
|
@apply focus-within:outline-none focus-visible:outline-0 focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1;
|
||||||
@apply file:border-0 file:bg-transparent file:font-medium;
|
@apply file:border-0 file:bg-transparent file:font-medium;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.select {
|
.select {
|
||||||
@apply placeholder:text-muted-foreground border-border flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm disabled:cursor-not-allowed [&>span]:line-clamp-1;
|
@apply placeholder:text-muted-foreground border-border flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm disabled:cursor-not-allowed [&>span]:line-clamp-1;
|
||||||
@apply disabled:cursor-not-allowed disabled:bg-zinc-100 disabled:dark:bg-zinc-800 disabled:dark:text-zinc-600;
|
@apply disabled:text-muted-foreground disabled:cursor-not-allowed disabled:bg-zinc-100 disabled:dark:bg-zinc-800 disabled:dark:text-zinc-600;
|
||||||
@apply focus-within:outline-none focus-visible:outline-0 focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1;
|
@apply focus-within:outline-none focus-visible:outline-0 focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1;
|
||||||
|
|
||||||
&-caret {
|
&-caret {
|
||||||
|
|||||||
@ -156,7 +156,10 @@ export default function CardSidebar({
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
Opens <span className="lowercase">{title}.json.</span>
|
Opens{' '}
|
||||||
|
<span className="lowercase">
|
||||||
|
{title === 'Tools' ? 'assistant' : title}.json.
|
||||||
|
</span>
|
||||||
Changes affect all new threads.
|
Changes affect all new threads.
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { useContext } from 'react'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Assistant,
|
Assistant,
|
||||||
ConversationalExtension,
|
ConversationalExtension,
|
||||||
@ -6,13 +8,15 @@ import {
|
|||||||
ThreadAssistantInfo,
|
ThreadAssistantInfo,
|
||||||
ThreadState,
|
ThreadState,
|
||||||
Model,
|
Model,
|
||||||
MessageStatus,
|
AssistantTool,
|
||||||
} from '@janhq/core'
|
} from '@janhq/core'
|
||||||
import { atom, useAtomValue, useSetAtom } from 'jotai'
|
import { atom, useAtomValue, useSetAtom } from 'jotai'
|
||||||
|
|
||||||
import { selectedModelAtom } from '@/containers/DropdownListSidebar'
|
import { selectedModelAtom } from '@/containers/DropdownListSidebar'
|
||||||
import { fileUploadAtom } from '@/containers/Providers/Jotai'
|
import { fileUploadAtom } from '@/containers/Providers/Jotai'
|
||||||
|
|
||||||
|
import { FeatureToggleContext } from '@/context/FeatureToggle'
|
||||||
|
|
||||||
import { generateThreadId } from '@/utils/thread'
|
import { generateThreadId } from '@/utils/thread'
|
||||||
|
|
||||||
import useRecommendedModel from './useRecommendedModel'
|
import useRecommendedModel from './useRecommendedModel'
|
||||||
@ -54,6 +58,7 @@ export const useCreateNewThread = () => {
|
|||||||
const setSelectedModel = useSetAtom(selectedModelAtom)
|
const setSelectedModel = useSetAtom(selectedModelAtom)
|
||||||
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
|
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
|
||||||
const messages = useAtomValue(getCurrentChatMessagesAtom)
|
const messages = useAtomValue(getCurrentChatMessagesAtom)
|
||||||
|
const { experimentalFeature } = useContext(FeatureToggleContext)
|
||||||
|
|
||||||
const { recommendedModel, downloadedModels } = useRecommendedModel()
|
const { recommendedModel, downloadedModels } = useRecommendedModel()
|
||||||
|
|
||||||
@ -72,11 +77,18 @@ export const useCreateNewThread = () => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modify assistant tools when experimental on, retieval toggle enabled in default
|
||||||
|
const assistantTools: AssistantTool = {
|
||||||
|
type: 'retrieval',
|
||||||
|
enabled: true,
|
||||||
|
settings: assistant.tools && assistant.tools[0].settings,
|
||||||
|
}
|
||||||
|
|
||||||
const createdAt = Date.now()
|
const createdAt = Date.now()
|
||||||
const assistantInfo: ThreadAssistantInfo = {
|
const assistantInfo: ThreadAssistantInfo = {
|
||||||
assistant_id: assistant.id,
|
assistant_id: assistant.id,
|
||||||
assistant_name: assistant.name,
|
assistant_name: assistant.name,
|
||||||
tools: assistant.tools,
|
tools: experimentalFeature ? [assistantTools] : assistant.tools,
|
||||||
model: {
|
model: {
|
||||||
id: defaultModel?.id ?? '*',
|
id: defaultModel?.id ?? '*',
|
||||||
settings: defaultModel?.settings ?? {},
|
settings: defaultModel?.settings ?? {},
|
||||||
|
|||||||
@ -25,6 +25,7 @@ export const usePath = () => {
|
|||||||
if (!selectedModel) return
|
if (!selectedModel) return
|
||||||
filePath = await joinPath(['models', selectedModel.id])
|
filePath = await joinPath(['models', selectedModel.id])
|
||||||
break
|
break
|
||||||
|
case 'Tools':
|
||||||
case 'Assistant':
|
case 'Assistant':
|
||||||
if (!assistantId) return
|
if (!assistantId) return
|
||||||
filePath = await joinPath(['assistants', assistantId])
|
filePath = await joinPath(['assistants', assistantId])
|
||||||
@ -59,6 +60,7 @@ export const usePath = () => {
|
|||||||
filePath = await joinPath(['models', selectedModel.id, 'model.json'])
|
filePath = await joinPath(['models', selectedModel.id, 'model.json'])
|
||||||
break
|
break
|
||||||
case 'Assistant':
|
case 'Assistant':
|
||||||
|
case 'Tools':
|
||||||
if (!assistantId) return
|
if (!assistantId) return
|
||||||
filePath = await joinPath(['assistants', assistantId, 'assistant.json'])
|
filePath = await joinPath(['assistants', assistantId, 'assistant.json'])
|
||||||
break
|
break
|
||||||
|
|||||||
@ -112,14 +112,12 @@ const ChatInput: React.FC = () => {
|
|||||||
const file = event.target.files?.[0]
|
const file = event.target.files?.[0]
|
||||||
if (!file) return
|
if (!file) return
|
||||||
setFileUpload([{ file: file, type: 'pdf' }])
|
setFileUpload([{ file: file, type: 'pdf' }])
|
||||||
setCurrentPrompt('Summarize this for me')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = event.target.files?.[0]
|
const file = event.target.files?.[0]
|
||||||
if (!file) return
|
if (!file) return
|
||||||
setFileUpload([{ file: file, type: 'image' }])
|
setFileUpload([{ file: file, type: 'image' }])
|
||||||
setCurrentPrompt('What do you see in this image?')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderPreview = (fileUpload: any) => {
|
const renderPreview = (fileUpload: any) => {
|
||||||
|
|||||||
@ -1,11 +1,20 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
|
|
||||||
import { InferenceEngine } from '@janhq/core'
|
import {
|
||||||
import { Input, Textarea, Switch } from '@janhq/uikit'
|
Input,
|
||||||
|
Textarea,
|
||||||
|
Switch,
|
||||||
|
Tooltip,
|
||||||
|
TooltipArrow,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipPortal,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@janhq/uikit'
|
||||||
|
|
||||||
import { atom, useAtomValue } from 'jotai'
|
import { atom, useAtomValue } from 'jotai'
|
||||||
|
|
||||||
|
import { InfoIcon } from 'lucide-react'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
import LogoMark from '@/containers/Brand/Logo/Mark'
|
import LogoMark from '@/containers/Brand/Logo/Mark'
|
||||||
@ -134,76 +143,174 @@ const Sidebar: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{experimentalFeature && (
|
|
||||||
<div>
|
|
||||||
{activeThread?.assistants[0]?.tools &&
|
|
||||||
componentDataAssistantSetting.length > 0 && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<CardSidebar
|
|
||||||
title="Retrieval"
|
|
||||||
asChild
|
|
||||||
rightAction={
|
|
||||||
<Switch
|
|
||||||
name="retrieval"
|
|
||||||
className="mr-2"
|
|
||||||
checked={
|
|
||||||
activeThread?.assistants[0].tools[0].enabled
|
|
||||||
}
|
|
||||||
onCheckedChange={(e) => {
|
|
||||||
if (activeThread)
|
|
||||||
updateThreadMetadata({
|
|
||||||
...activeThread,
|
|
||||||
assistants: [
|
|
||||||
{
|
|
||||||
...activeThread.assistants[0],
|
|
||||||
tools: [
|
|
||||||
{
|
|
||||||
type: 'retrieval',
|
|
||||||
enabled: e,
|
|
||||||
settings:
|
|
||||||
(activeThread.assistants[0].tools &&
|
|
||||||
activeThread.assistants[0]
|
|
||||||
.tools[0]?.settings) ??
|
|
||||||
{},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{activeThread?.assistants[0]?.tools[0].enabled && (
|
|
||||||
<div className="px-2 py-4">
|
|
||||||
<div className="mb-4">
|
|
||||||
<label
|
|
||||||
id="tool-title"
|
|
||||||
className="mb-2 inline-block font-bold text-zinc-500 dark:text-gray-300"
|
|
||||||
>
|
|
||||||
Embedding Engine
|
|
||||||
</label>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<label className="font-medium text-zinc-500 dark:text-gray-300">
|
|
||||||
{selectedModel?.engine ===
|
|
||||||
InferenceEngine.openai
|
|
||||||
? 'OpenAI'
|
|
||||||
: 'Nitro'}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<AssistantSetting
|
|
||||||
componentData={componentDataAssistantSetting}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardSidebar>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</CardSidebar>
|
</CardSidebar>
|
||||||
|
|
||||||
|
{experimentalFeature && (
|
||||||
|
<div>
|
||||||
|
{activeThread?.assistants[0]?.tools &&
|
||||||
|
componentDataAssistantSetting.length > 0 && (
|
||||||
|
<div className="mt-2">
|
||||||
|
<CardSidebar title="Tools">
|
||||||
|
<div className="px-2 pt-4">
|
||||||
|
<div className="mb-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<label
|
||||||
|
id="retrieval"
|
||||||
|
className="inline-flex items-center font-bold text-zinc-500 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
Retrieval
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<InfoIcon
|
||||||
|
size={16}
|
||||||
|
className="ml-2 flex-shrink-0 text-black dark:text-gray-500"
|
||||||
|
/>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
<TooltipContent
|
||||||
|
side="top"
|
||||||
|
className="max-w-[240px]"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Retrieval helps the assistant use
|
||||||
|
information from files you send to it. Once
|
||||||
|
you share a file, the assistant
|
||||||
|
automatically fetches the relevant content
|
||||||
|
based on your request.
|
||||||
|
</span>
|
||||||
|
<TooltipArrow />
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Switch
|
||||||
|
name="retrieval"
|
||||||
|
className="mr-2"
|
||||||
|
checked={
|
||||||
|
activeThread?.assistants[0].tools[0].enabled
|
||||||
|
}
|
||||||
|
onCheckedChange={(e) => {
|
||||||
|
if (activeThread)
|
||||||
|
updateThreadMetadata({
|
||||||
|
...activeThread,
|
||||||
|
assistants: [
|
||||||
|
{
|
||||||
|
...activeThread.assistants[0],
|
||||||
|
tools: [
|
||||||
|
{
|
||||||
|
type: 'retrieval',
|
||||||
|
enabled: e,
|
||||||
|
settings:
|
||||||
|
(activeThread.assistants[0]
|
||||||
|
.tools &&
|
||||||
|
activeThread.assistants[0]
|
||||||
|
.tools[0]?.settings) ??
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{activeThread?.assistants[0]?.tools[0].enabled && (
|
||||||
|
<div className="pb-4 pt-2">
|
||||||
|
<div className="mb-4">
|
||||||
|
<div className="item-center mb-2 flex">
|
||||||
|
<label
|
||||||
|
id="embedding-model"
|
||||||
|
className="inline-flex font-bold text-zinc-500 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
Embedding Model
|
||||||
|
</label>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<InfoIcon
|
||||||
|
size={16}
|
||||||
|
className="ml-2 flex-shrink-0 dark:text-gray-500"
|
||||||
|
/>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
<TooltipContent
|
||||||
|
side="top"
|
||||||
|
className="max-w-[240px]"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Embedding model is crucial for
|
||||||
|
understanding and processing the input
|
||||||
|
text effectively by converting text to
|
||||||
|
numerical representations. Align the model
|
||||||
|
choice with your task, evaluate its
|
||||||
|
performance, and consider factors like
|
||||||
|
resource availability. Experiment to find
|
||||||
|
the best fit for your specific use case.
|
||||||
|
</span>
|
||||||
|
<TooltipArrow />
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Input value={selectedModel?.name} disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-4">
|
||||||
|
<div className="mb-2 flex items-center">
|
||||||
|
<label
|
||||||
|
id="vector-database"
|
||||||
|
className="inline-block font-bold text-zinc-500 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
Vector Database
|
||||||
|
</label>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<InfoIcon
|
||||||
|
size={16}
|
||||||
|
className="ml-2 flex-shrink-0 dark:text-gray-500"
|
||||||
|
/>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipPortal>
|
||||||
|
<TooltipContent
|
||||||
|
side="top"
|
||||||
|
className="max-w-[240px]"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Vector Database is crucial for efficient
|
||||||
|
storage and retrieval of embeddings.
|
||||||
|
Consider your specific task, available
|
||||||
|
resources, and language requirements.
|
||||||
|
Experiment to find the best fit for your
|
||||||
|
specific use case.
|
||||||
|
</span>
|
||||||
|
<TooltipArrow />
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Input value="HNSWLib" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<AssistantSetting
|
||||||
|
componentData={componentDataAssistantSetting}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</CardSidebar>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<CardSidebar title="Model">
|
<CardSidebar title="Model">
|
||||||
<div className="px-2 pt-4">
|
<div className="px-2 pt-4">
|
||||||
<DropdownListSidebar />
|
<DropdownListSidebar />
|
||||||
|
|||||||
@ -110,11 +110,6 @@ const ChatScreen: React.FC = () => {
|
|||||||
const imageType = files[0]?.type.includes('image')
|
const imageType = files[0]?.type.includes('image')
|
||||||
setFileUpload([{ file: files[0], type: imageType ? 'image' : 'pdf' }])
|
setFileUpload([{ file: files[0], type: imageType ? 'image' : 'pdf' }])
|
||||||
setDragOver(false)
|
setDragOver(false)
|
||||||
if (imageType) {
|
|
||||||
setCurrentPrompt('What do you see in this image?')
|
|
||||||
} else {
|
|
||||||
setCurrentPrompt('Summarize this for me')
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDropRejected: (e) => {
|
onDropRejected: (e) => {
|
||||||
if (
|
if (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user