From 7a887f59bc7c8e7d30c6ccd0d712c5bf2e26cf56 Mon Sep 17 00:00:00 2001 From: redesyef Date: Wed, 25 Sep 2024 16:06:28 -0500 Subject: [PATCH] UPDATED cache in suggestions --- src/app.ts | 2 +- src/routes/suggestions.ts | 9 +++++++- src/websocket/messageHandler.ts | 4 ++-- ui/components/ChatWindow.tsx | 35 +++++++++++++++++++++++++++- ui/lib/actions.ts | 41 ++++++++++++++++++++------------- 5 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/app.ts b/src/app.ts index 1889d12..ba0837d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -39,7 +39,7 @@ app.use(async (req: Request, res: Response, next: NextFunction) => { const result = originalSend(body); redisClient - .setEx(cacheKey, 3600, JSON.stringify(body)) + .setEx(cacheKey, 86400, JSON.stringify(body)) .then(() => logger.info(`Cache set for ${cacheKey}`)) .catch((err) => logger.error(`Redis setEx error: ${err}`)); diff --git a/src/routes/suggestions.ts b/src/routes/suggestions.ts index b15ff5f..6a0c113 100644 --- a/src/routes/suggestions.ts +++ b/src/routes/suggestions.ts @@ -4,13 +4,19 @@ import { BaseChatModel } from '@langchain/core/language_models/chat_models'; import { getAvailableChatModelProviders } from '../lib/providers'; import { HumanMessage, AIMessage } from '@langchain/core/messages'; import logger from '../utils/logger'; - +import redisClient from '../utils/redisClient'; const router = express.Router(); router.post('/', async (req, res) => { try { let { chat_history, chat_model, chat_model_provider } = req.body; + const messageId = chat_history[1]?.messageId; + const cachedResponse = await redisClient.get(messageId); + if (cachedResponse) { + logger.info(`Cache hit for messageId: ${messageId}`); + return res.status(200).json(JSON.parse(cachedResponse)); + } chat_history = chat_history.map((msg: any) => { if (msg.role === 'user') { return new HumanMessage(msg.content); @@ -36,6 +42,7 @@ router.post('/', async (req, res) => { const suggestions = await generateSuggestions({ chat_history }, llm); + await redisClient.setEx(messageId, 86400, JSON.stringify({ suggestions })); res.status(200).json({ suggestions: suggestions }); } catch (err) { res.status(500).json({ message: 'An error has occurred.' }); diff --git a/src/websocket/messageHandler.ts b/src/websocket/messageHandler.ts index 6d88bbb..10c698b 100644 --- a/src/websocket/messageHandler.ts +++ b/src/websocket/messageHandler.ts @@ -178,7 +178,7 @@ export const handleMessage = async ( .values({ content: parsedMessage.content, chatId: parsedMessage.chatId, - messageId: id, + messageId: jsonDatabase.messageId, role: 'user', metadata: JSON.stringify({ createdAt: new Date(), @@ -190,7 +190,7 @@ export const handleMessage = async ( .values({ content: jsonDatabase.content, chatId: parsedMessage.chatId, - messageId: id, + messageId: jsonDatabase.messageId, role: jsonDatabase.role, metadata: JSON.stringify({ createdAt: new Date(), diff --git a/ui/components/ChatWindow.tsx b/ui/components/ChatWindow.tsx index 183a2ff..c45b2f9 100644 --- a/ui/components/ChatWindow.tsx +++ b/ui/components/ChatWindow.tsx @@ -167,7 +167,7 @@ const useSocket = ( 'Failed to connect to the server. Please try again later.', ); } - }, 10000); + }, 1000); ws.onopen = () => { console.log('[DEBUG] open'); @@ -280,6 +280,8 @@ const ChatWindow = ({ id }: { id?: string }) => { const [isMessagesLoaded, setIsMessagesLoaded] = useState(false); const [notFound, setNotFound] = useState(false); + const [cache, setCache] = useState(false); + const [newRequest, setNewRequest] = useState(false); useEffect(() => { if ( @@ -361,6 +363,7 @@ const ChatWindow = ({ id }: { id?: string }) => { ]); const messageHandler = async (e: MessageEvent) => { + setNewRequest(true); const data = JSON.parse(e.data); if (data.type === 'error') { @@ -371,6 +374,9 @@ const ChatWindow = ({ id }: { id?: string }) => { if (data.type === 'sources') { sources = data.data; + if (data.cache) { + setCache(true); + } if (typeof sources === 'string') { sources = JSON.parse(data.data); added = false; @@ -490,12 +496,39 @@ const ChatWindow = ({ id }: { id?: string }) => { sendMessage(message.content); }; + const getSuggestionsWithPreviewInfo = async () => { + if ( + messages[1].role === 'assistant' && + messages[1].sources && + messages[1].sources.length > 0 && + !messages[1].suggestions + ) { + const suggestions = await getSuggestions(messagesRef.current); + setMessages((prev) => + prev.map((msg) => { + if (msg.messageId === messages[1].messageId) { + return { ...msg, suggestions: suggestions }; + } + return msg; + }), + ); + } + }; useEffect(() => { if (isReady && initialMessage) { sendMessage(initialMessage); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isReady, initialMessage]); + useEffect(() => { + if ( + (messages.length > 1 && cache) || + (messages.length > 1 && !newRequest) + ) { + getSuggestionsWithPreviewInfo(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [messages]); if (hasError) { return ( diff --git a/ui/lib/actions.ts b/ui/lib/actions.ts index d7eb71f..b14cb8e 100644 --- a/ui/lib/actions.ts +++ b/ui/lib/actions.ts @@ -1,22 +1,31 @@ import { Message } from '@/components/ChatWindow'; -export const getSuggestions = async (chatHisory: Message[]) => { - const chatModel = localStorage.getItem('chatModel'); - const chatModelProvider = localStorage.getItem('chatModelProvider'); +export const getSuggestions = async (chatHistory: Message[]) => { + try { + const chatModel = localStorage.getItem('chatModel'); + const chatModelProvider = localStorage.getItem('chatModelProvider'); - const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/suggestions`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - chat_history: chatHisory, - chat_model: chatModel, - chat_model_provider: chatModelProvider, - }), - }); + const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/suggestions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + chat_history: chatHistory, + chat_model: chatModel, + chat_model_provider: chatModelProvider, + }), + }); - const data = (await res.json()) as { suggestions: string[] }; + if (!res.ok) { + throw new Error(`Error: ${res.status} ${res.statusText}`); + } - return data.suggestions; + const data = (await res.json()) as { suggestions: string[] }; + + return data.suggestions; + } catch (error) { + console.error('Error fetching suggestions:', error); + return []; + } };