fix: increase context size window does not popup first time
This commit is contained in:
parent
906c539541
commit
16aab0d661
@ -35,7 +35,6 @@ import { ModelLoader } from '@/containers/loaders/ModelLoader'
|
||||
import DropdownToolsAvailable from '@/containers/DropdownToolsAvailable'
|
||||
import { getConnectedServers } from '@/services/mcp'
|
||||
import { stopAllModels } from '@/services/models'
|
||||
import { useOutOfContextPromiseModal } from './dialogs/OutOfContextDialog'
|
||||
|
||||
type ChatInputProps = {
|
||||
className?: string
|
||||
@ -55,8 +54,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { spellCheckChatInput } = useGeneralSetting()
|
||||
|
||||
const { showModal, PromiseModal: OutOfContextModal } =
|
||||
useOutOfContextPromiseModal()
|
||||
const maxRows = 10
|
||||
|
||||
const { selectedModel } = useModelProvider()
|
||||
@ -107,7 +104,7 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
||||
return
|
||||
}
|
||||
setMessage('')
|
||||
sendMessage(prompt, showModal)
|
||||
sendMessage(prompt)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -599,7 +596,6 @@ const ChatInput = ({ model, className, initialMessage }: ChatInputProps) => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<OutOfContextModal />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -83,7 +83,6 @@ export const ThreadContent = memo(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
streamTools?: any
|
||||
contextOverflowModal?: React.ReactNode | null
|
||||
showContextOverflowModal?: () => Promise<unknown>
|
||||
}
|
||||
) => {
|
||||
const [message, setMessage] = useState(item.content?.[0]?.text?.value || '')
|
||||
@ -134,10 +133,7 @@ export const ThreadContent = memo(
|
||||
}
|
||||
if (toSendMessage) {
|
||||
deleteMessage(toSendMessage.thread_id, toSendMessage.id ?? '')
|
||||
sendMessage(
|
||||
toSendMessage.content?.[0]?.text?.value || '',
|
||||
item.showContextOverflowModal
|
||||
)
|
||||
sendMessage(toSendMessage.content?.[0]?.text?.value || '')
|
||||
}
|
||||
}, [deleteMessage, getMessages, item, sendMessage])
|
||||
|
||||
@ -179,16 +175,9 @@ export const ThreadContent = memo(
|
||||
deleteMessage(threadMessages[i].thread_id, threadMessages[i].id)
|
||||
}
|
||||
|
||||
sendMessage(message, item.showContextOverflowModal)
|
||||
sendMessage(message)
|
||||
},
|
||||
[
|
||||
deleteMessage,
|
||||
getMessages,
|
||||
item.thread_id,
|
||||
message,
|
||||
sendMessage,
|
||||
item.showContextOverflowModal,
|
||||
]
|
||||
[deleteMessage, getMessages, item.thread_id, message, sendMessage]
|
||||
)
|
||||
|
||||
const isToolCalls =
|
||||
|
||||
@ -8,108 +8,76 @@ import {
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
|
||||
import { ReactNode, useCallback, useState } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useContextSizeApproval } from '@/hooks/useModelContextApproval'
|
||||
|
||||
export function useOutOfContextPromiseModal() {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [modalProps, setModalProps] = useState<{
|
||||
resolveRef:
|
||||
| ((value: 'ctx_len' | 'context_shift' | undefined) => void)
|
||||
| null
|
||||
}>({
|
||||
resolveRef: null,
|
||||
})
|
||||
// Function to open the modal and return a Promise
|
||||
const showModal = useCallback(() => {
|
||||
return new Promise((resolve) => {
|
||||
setModalProps({
|
||||
resolveRef: resolve,
|
||||
})
|
||||
setIsOpen(true)
|
||||
})
|
||||
}, [])
|
||||
export default function OutOfContextPromiseModal() {
|
||||
const { isModalOpen, modalProps, setModalOpen } = useContextSizeApproval()
|
||||
if (!modalProps) {
|
||||
return null
|
||||
}
|
||||
const { onApprove, onDeny } = modalProps
|
||||
|
||||
const PromiseModal = useCallback((): ReactNode => {
|
||||
if (!isOpen) {
|
||||
return null
|
||||
const handleContextLength = () => {
|
||||
onApprove('ctx_len')
|
||||
}
|
||||
|
||||
const handleContextShift = () => {
|
||||
onApprove('context_shift')
|
||||
}
|
||||
|
||||
const handleDialogOpen = (open: boolean) => {
|
||||
setModalOpen(open)
|
||||
if (!open) {
|
||||
onDeny()
|
||||
}
|
||||
}
|
||||
|
||||
const handleContextLength = () => {
|
||||
setIsOpen(false)
|
||||
if (modalProps.resolveRef) {
|
||||
modalProps.resolveRef('ctx_len')
|
||||
}
|
||||
}
|
||||
|
||||
const handleContextShift = () => {
|
||||
setIsOpen(false)
|
||||
if (modalProps.resolveRef) {
|
||||
modalProps.resolveRef('context_shift')
|
||||
}
|
||||
}
|
||||
const handleCancel = () => {
|
||||
setIsOpen(false)
|
||||
if (modalProps.resolveRef) {
|
||||
modalProps.resolveRef(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => {
|
||||
setIsOpen(open)
|
||||
if (!open) handleCancel()
|
||||
}}
|
||||
>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{t('outOfContextError.title', 'Out of context error')}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
{t(
|
||||
'outOfContextError.description',
|
||||
'This chat is reaching the AI’s memory limit, like a whiteboard filling up. We can expand the memory window (called context size) so it remembers more, but it may use more of your computer’s memory. We can also truncate the input, which means it will forget some of the chat history to make room for new messages.'
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
{t(
|
||||
'outOfContextError.increaseContextSizeDescription',
|
||||
'Do you want to increase the context size?'
|
||||
)}
|
||||
</DialogDescription>
|
||||
<DialogFooter className="flex gap-2">
|
||||
<Button
|
||||
variant="default"
|
||||
className="bg-transparent border border-main-view-fg/20 hover:bg-main-view-fg/4"
|
||||
onClick={() => {
|
||||
handleContextShift()
|
||||
setIsOpen(false)
|
||||
}}
|
||||
>
|
||||
{t('outOfContextError.truncateInput', 'Truncate Input')}
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
onClick={() => {
|
||||
handleContextLength()
|
||||
setIsOpen(false)
|
||||
}}
|
||||
>
|
||||
<span className="text-main-view-fg/70">
|
||||
{t(
|
||||
'outOfContextError.increaseContextSize',
|
||||
'Increase Context Size'
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}, [isOpen, modalProps])
|
||||
return { showModal, PromiseModal }
|
||||
return (
|
||||
<Dialog open={isModalOpen} onOpenChange={handleDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
{t('outOfContextError.title', 'Out of context error')}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
{t(
|
||||
'outOfContextError.description',
|
||||
'This chat is reaching the AI’s memory limit, like a whiteboard filling up. We can expand the memory window (called context size) so it remembers more, but it may use more of your computer’s memory. We can also truncate the input, which means it will forget some of the chat history to make room for new messages.'
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
{t(
|
||||
'outOfContextError.increaseContextSizeDescription',
|
||||
'Do you want to increase the context size?'
|
||||
)}
|
||||
</DialogDescription>
|
||||
<DialogFooter className="flex gap-2">
|
||||
<Button
|
||||
variant="default"
|
||||
className="bg-transparent border border-main-view-fg/20 hover:bg-main-view-fg/4"
|
||||
onClick={() => {
|
||||
handleContextShift()
|
||||
}}
|
||||
>
|
||||
{t('outOfContextError.truncateInput', 'Truncate Input')}
|
||||
</Button>
|
||||
<Button
|
||||
asChild
|
||||
onClick={() => {
|
||||
handleContextLength()
|
||||
}}
|
||||
>
|
||||
<span className="text-main-view-fg/70">
|
||||
{t(
|
||||
'outOfContextError.increaseContextSize',
|
||||
'Increase Context Size'
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ import { useToolApproval } from '@/hooks/useToolApproval'
|
||||
import { useToolAvailable } from '@/hooks/useToolAvailable'
|
||||
import { OUT_OF_CONTEXT_SIZE } from '@/utils/error'
|
||||
import { updateSettings } from '@/services/providers'
|
||||
import { useContextSizeApproval } from './useModelContextApproval'
|
||||
|
||||
export const useChat = () => {
|
||||
const { prompt, setPrompt } = usePrompt()
|
||||
@ -47,6 +48,8 @@ export const useChat = () => {
|
||||
|
||||
const { approvedTools, showApprovalModal, allowAllMCPPermissions } =
|
||||
useToolApproval()
|
||||
const { showApprovalModal: showIncreaseContextSizeModal } =
|
||||
useContextSizeApproval()
|
||||
const { getDisabledToolsForThread } = useToolAvailable()
|
||||
|
||||
const { getProviderByName, selectedModel, selectedProvider } =
|
||||
@ -223,11 +226,7 @@ export const useChat = () => {
|
||||
)
|
||||
|
||||
const sendMessage = useCallback(
|
||||
async (
|
||||
message: string,
|
||||
showModal?: () => Promise<unknown>,
|
||||
troubleshooting = true
|
||||
) => {
|
||||
async (message: string, troubleshooting = true) => {
|
||||
const activeThread = await getCurrentThread()
|
||||
|
||||
resetTokenSpeed()
|
||||
@ -361,7 +360,7 @@ export const useChat = () => {
|
||||
selectedModel &&
|
||||
troubleshooting
|
||||
) {
|
||||
const method = await showModal?.()
|
||||
const method = await showIncreaseContextSizeModal()
|
||||
if (method === 'ctx_len') {
|
||||
/// Increase context size
|
||||
activeProvider = await increaseModelContextSize(
|
||||
@ -447,8 +446,7 @@ export const useChat = () => {
|
||||
updateThreadTimestamp,
|
||||
setPrompt,
|
||||
selectedModel,
|
||||
currentAssistant?.instructions,
|
||||
currentAssistant.parameters,
|
||||
currentAssistant,
|
||||
tools,
|
||||
updateLoadingModel,
|
||||
getDisabledToolsForThread,
|
||||
@ -456,6 +454,7 @@ export const useChat = () => {
|
||||
allowAllMCPPermissions,
|
||||
showApprovalModal,
|
||||
updateTokenSpeed,
|
||||
showIncreaseContextSizeModal,
|
||||
increaseModelContextSize,
|
||||
toggleOnContextShifting,
|
||||
]
|
||||
|
||||
53
web-app/src/hooks/useModelContextApproval.ts
Normal file
53
web-app/src/hooks/useModelContextApproval.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { create } from 'zustand'
|
||||
|
||||
export type ApprovalModalProps = {
|
||||
onApprove: (method: 'ctx_len' | 'context_shift') => void
|
||||
onDeny: () => void
|
||||
}
|
||||
|
||||
type ApprovalState = {
|
||||
// Modal state
|
||||
isModalOpen: boolean
|
||||
modalProps: ApprovalModalProps | null
|
||||
|
||||
showApprovalModal: () => Promise<'ctx_len' | 'context_shift' | undefined>
|
||||
closeModal: () => void
|
||||
setModalOpen: (open: boolean) => void
|
||||
}
|
||||
|
||||
export const useContextSizeApproval = create<ApprovalState>()((set, get) => ({
|
||||
isModalOpen: false,
|
||||
modalProps: null,
|
||||
|
||||
showApprovalModal: async () => {
|
||||
return new Promise<'ctx_len' | 'context_shift' | undefined>((resolve) => {
|
||||
set({
|
||||
isModalOpen: true,
|
||||
modalProps: {
|
||||
onApprove: (method) => {
|
||||
get().closeModal()
|
||||
resolve(method)
|
||||
},
|
||||
onDeny: () => {
|
||||
get().closeModal()
|
||||
resolve(undefined)
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
closeModal: () => {
|
||||
set({
|
||||
isModalOpen: false,
|
||||
modalProps: null,
|
||||
})
|
||||
},
|
||||
|
||||
setModalOpen: (open: boolean) => {
|
||||
set({ isModalOpen: open })
|
||||
if (!open) {
|
||||
get().closeModal()
|
||||
}
|
||||
},
|
||||
}))
|
||||
@ -18,6 +18,7 @@ import { AnalyticProvider } from '@/providers/AnalyticProvider'
|
||||
import { useLeftPanel } from '@/hooks/useLeftPanel'
|
||||
import { cn } from '@/lib/utils'
|
||||
import ToolApproval from '@/containers/dialogs/ToolApproval'
|
||||
import OutOfContextPromiseModal from '@/containers/dialogs/OutOfContextDialog'
|
||||
|
||||
export const Route = createRootRoute({
|
||||
component: RootLayout,
|
||||
@ -94,6 +95,7 @@ function RootLayout() {
|
||||
{/* <TanStackRouterDevtools position="bottom-right" /> */}
|
||||
<CortexFailureDialog />
|
||||
<ToolApproval />
|
||||
<OutOfContextPromiseModal />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ import { useAppState } from '@/hooks/useAppState'
|
||||
import DropdownAssistant from '@/containers/DropdownAssistant'
|
||||
import { useAssistant } from '@/hooks/useAssistant'
|
||||
import { useAppearance } from '@/hooks/useAppearance'
|
||||
import { useOutOfContextPromiseModal } from '@/containers/dialogs/OutOfContextDialog'
|
||||
|
||||
// as route.threadsDetail
|
||||
export const Route = createFileRoute('/threads/$threadId')({
|
||||
@ -48,8 +47,6 @@ function ThreadDetail() {
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null)
|
||||
const isFirstRender = useRef(true)
|
||||
const messagesCount = useMemo(() => messages?.length ?? 0, [messages])
|
||||
const { showModal, PromiseModal: OutOfContextModal } =
|
||||
useOutOfContextPromiseModal()
|
||||
|
||||
// Function to check scroll position and scrollbar presence
|
||||
const checkScrollState = () => {
|
||||
@ -196,8 +193,6 @@ function ThreadDetail() {
|
||||
|
||||
if (!messages || !threadModel) return null
|
||||
|
||||
const contextOverflowModalComponent = <OutOfContextModal />
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<HeaderPage>
|
||||
@ -243,8 +238,6 @@ function ThreadDetail() {
|
||||
))
|
||||
}
|
||||
index={index}
|
||||
showContextOverflowModal={showModal}
|
||||
contextOverflowModal={contextOverflowModalComponent}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user