From 714c59067bbd8a9817403a8923c0b1e0441857d2 Mon Sep 17 00:00:00 2001 From: Sinan Date: Sun, 6 Oct 2024 23:46:45 +0530 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20=20chat=20bot=20added=20sussessfyll?= =?UTF-8?q?y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chatbot/ChatBotController.tsx | 11 ++++-- .../page-components/chatbot/ChatSection.tsx | 39 +++++++++++-------- .../chatbot/MessageDisplay.tsx | 21 +++++++--- client/lib/hooks/chatbot/useChatBot.ts | 2 +- client/lib/utils/index.ts | 4 ++ server/src/config/chatBotConfig.ts | 24 +++++++----- .../repositories/ChatBotMessageRepository.ts | 2 +- .../services/GeminiBotService.ts | 7 +--- 8 files changed, 66 insertions(+), 44 deletions(-) diff --git a/client/components/page-components/chatbot/ChatBotController.tsx b/client/components/page-components/chatbot/ChatBotController.tsx index 77b3ad8a..8bde0df1 100644 --- a/client/components/page-components/chatbot/ChatBotController.tsx +++ b/client/components/page-components/chatbot/ChatBotController.tsx @@ -1,22 +1,22 @@ -import { Button } from "@/components/ui/button"; +import { ButtonV2 } from "@/components/button/ButtonV2"; import { Input } from "@/components/ui/input"; import { CardFooter } from "@/components/ui/card"; import { Send } from "lucide-react"; -import { ButtonV2 } from "@/components/button/ButtonV2"; type ChatBotControllerProps = { inputMessage: string; setInputMessage: (value: string) => void; sendMessage: () => void; + isSending: boolean; }; -const ChatBotController = ({ inputMessage, setInputMessage, sendMessage }: ChatBotControllerProps) => { +const ChatBotController = ({ inputMessage, setInputMessage, sendMessage, isSending }: ChatBotControllerProps) => { return (
{ e.preventDefault(); - sendMessage(); + if (!isSending) sendMessage(); }} className="flex w-full items-center space-x-3" > @@ -27,6 +27,7 @@ const ChatBotController = ({ inputMessage, setInputMessage, sendMessage }: ChatB onChange={(e) => setInputMessage(e.target.value)} className="flex-grow bg-dark-100 text-white placeholder-gray-400 border-gray-600 focus:border-green-500 focus:ring-green-500 text-sm py-3 rounded-full" aria-label="Type your message" + onKeyDown={(e) => e.key === 'Enter' && sendMessage()} /> e.key === 'Enter' && sendMessage()} > diff --git a/client/components/page-components/chatbot/ChatSection.tsx b/client/components/page-components/chatbot/ChatSection.tsx index 4a935ae8..4ce61475 100644 --- a/client/components/page-components/chatbot/ChatSection.tsx +++ b/client/components/page-components/chatbot/ChatSection.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState, useEffect, useRef } from 'react' +import { useState, useEffect, useRef, memo } from 'react' import { Card } from "@/components/ui/card" import { motion, AnimatePresence } from "framer-motion" import ChatBotController from './ChatBotController' @@ -10,6 +10,7 @@ import { IChatBotMessage } from '@/types/entities' import { useCreateMessage } from '@/lib/hooks/chatbot/useChatBot' import { useGetMessage } from '@/lib/hooks/chatbot/useChatBot' import { toast } from '@/components/ui/use-toast' +import { getRandomId } from '@/lib/utils' type Props = { isVisible: boolean; @@ -18,40 +19,43 @@ type Props = { } const ChatSection = ({ isVisible, setIsOpen, isAuthenticated }: Props) => { - const { data, isLoading } = useGetMessage() - const [messages, setMessages] = useState(data ?? []); + const { data } = useGetMessage(); + const [messages, setMessages] = useState([]); const [inputMessage, setInputMessage] = useState(''); - const scrollAreaRef = useRef(null); const { mutate: createMessage, isPending } = useCreateMessage(); useEffect(() => { - if (scrollAreaRef.current) { - scrollAreaRef.current.scrollTop = scrollAreaRef.current.scrollHeight; + if (data && data?.length > 0) { + setMessages(data); } - }, [messages]); + }, [data]); const handleClose = () => { setIsOpen(false); - } + }; const sendMessage = () => { if (inputMessage.trim()) { + const id = getRandomId() + const tempMessage: IChatBotMessage = { isBotMessage: false, message: inputMessage, _id:id, patientId:id }; + setMessages(prev => [...prev, tempMessage]); createMessage({ message: inputMessage }, { - onSuccess: (messages) => { - setMessages(prev => [...prev, ...messages]); + onSuccess: (newMessages) => { + setInputMessage(""); + setMessages(prev => [...prev, newMessages]); }, onError: (error) => { toast({ title: "Error Occurred while sending message", variant: "destructive", description: error.response?.data.message || "Unknown error Occurred" - }) + }); } } - ) + ); } - } + }; return ( setIsOpen(false)}> @@ -65,11 +69,12 @@ const ChatSection = ({ isVisible, setIsOpen, isAuthenticated }: Props) => { > {isAuthenticated ? ( - + ) : ( @@ -78,7 +83,7 @@ const ChatSection = ({ isVisible, setIsOpen, isAuthenticated }: Props) => { )} - ) -} + ); +}; -export default ChatSection; +export default memo(ChatSection); diff --git a/client/components/page-components/chatbot/MessageDisplay.tsx b/client/components/page-components/chatbot/MessageDisplay.tsx index b148dea2..0c61a514 100644 --- a/client/components/page-components/chatbot/MessageDisplay.tsx +++ b/client/components/page-components/chatbot/MessageDisplay.tsx @@ -4,16 +4,24 @@ import { motion } from "framer-motion" import Image from "next/image" import ChatBotCardHeader from "./ChatBotCardHeader" import { IChatBotMessage } from "@/types/entities" - - +import { useEffect, useRef } from "react" type Props = { - scrollAreaRef: React.RefObject; handleClose: () => void; - messages?:IChatBotMessage[]; + messages?: IChatBotMessage[]; } -const MessageDisplay = ({ scrollAreaRef, handleClose, messages }: Props) => { +const MessageDisplay = ({ handleClose, messages }: Props) => { + const scrollAreaRef = useRef(null); + const bottomRef = useRef(null); + + const scrollToBottom = () => { + bottomRef.current?.scrollIntoView({ behavior: 'auto' }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages]); return ( <> @@ -49,13 +57,14 @@ const MessageDisplay = ({ scrollAreaRef, handleClose, messages }: Props) => { }

{msg.message}

))} +
diff --git a/client/lib/hooks/chatbot/useChatBot.ts b/client/lib/hooks/chatbot/useChatBot.ts index b24e1e90..a793030d 100644 --- a/client/lib/hooks/chatbot/useChatBot.ts +++ b/client/lib/hooks/chatbot/useChatBot.ts @@ -5,7 +5,7 @@ import { useMutation, useQuery } from "@tanstack/react-query" import { AxiosError } from "axios" export const useCreateMessage = () => { - return useMutation, { message: string }>({ + return useMutation, { message: string }>({ mutationFn: ({ message }) => createChatMessage(message) }) }; diff --git a/client/lib/utils/index.ts b/client/lib/utils/index.ts index d4cae976..7e1dd995 100644 --- a/client/lib/utils/index.ts +++ b/client/lib/utils/index.ts @@ -15,3 +15,7 @@ export const formatDate = (date: Date): string => { const year = date.getFullYear(); return `${day}/${month}/${year}`; }; + +export const getRandomId = () => { + return (Math.random() * 121 / 12).toString() + new Date() +} \ No newline at end of file diff --git a/server/src/config/chatBotConfig.ts b/server/src/config/chatBotConfig.ts index 7d6858df..c90cbffc 100644 --- a/server/src/config/chatBotConfig.ts +++ b/server/src/config/chatBotConfig.ts @@ -1,15 +1,21 @@ const chatBotConfig = { - description: "You are an Ayurvedic hospital chatbot. You assist users with health-related queries about Ayurveda, allopathy, treatments, medicines, appointments, and hospital services. Respond politely, with helpful and informative guidance. ", + description: "You are an Ayurvedic hospital chatbot. You assist users with health-related queries about Ayurveda, allopathy, treatments, medicines, appointments, and hospital services. Respond politely, with helpful and informative guidance.", + behavior_rules: ` - Only respond to health-related queries about Ayurveda, allopathy, medicines, hospital services, and hospital contact/location information. - - Provide dosage information and potential side effects for Ayurvedic and allopathic medicines, when appropriate. - - Ask follow-up questions based on symptoms to suggest treatments or guide users toward consultations. - - Offer Ayurvedic lifestyle and dietary recommendations. - - Support multiple languages (if applicable). - - When necessary, refer users to contact hospital staff for more personalized advice. - - Be culturally sensitive and align responses with Ayurvedic principles. - - Always offer additional help at the end of each response. + - Avoid starting responses with “I understand...” and instead use more neutral, conversational phrases to gather details. + - Example questions to ask when a user mentions symptoms like a headache: + * "Could you tell me more about how long you’ve been experiencing the headache?" + * "Where exactly do you feel the headache?" + * "How would you rate the intensity of the headache (mild, moderate, or severe)?" + * "Are you experiencing any additional symptoms alongside the headache?" + * "Have you taken any medication for this?" + - Ask follow-up questions to provide better recommendations but keep the tone neutral and avoid assuming any diagnosis. + - Provide general advice based on symptoms but suggest consulting an Ayurvedic doctor for personalized treatment. + - Be mindful of not over-personalizing conversations—keep responses professional and neutral, allowing users to describe their condition in detail. + - Always offer additional assistance at the end of each response: "Let me know if you'd like further advice or to consult with one of our doctors." + - Align all health-related advice with Ayurvedic principles while also offering modern allopathic guidance if necessary. ` } -export default chatBotConfig; \ No newline at end of file +export default chatBotConfig; diff --git a/server/src/infrastructure/repositories/ChatBotMessageRepository.ts b/server/src/infrastructure/repositories/ChatBotMessageRepository.ts index 6f76a9e5..86f2a199 100644 --- a/server/src/infrastructure/repositories/ChatBotMessageRepository.ts +++ b/server/src/infrastructure/repositories/ChatBotMessageRepository.ts @@ -5,7 +5,7 @@ import ChatbotMessageModel from "../model/ChatBotMessageModel"; export default class ChaBotMessageRepository implements IChatBotMessageRepository { model = ChatbotMessageModel; async getMessagesByPatientId(patientId: string): Promise { - return await this.model.find({ patientId }).lean(true); + return await this.model.find({ patientId }).limit(50).lean(true); } async create(message: IChatBotMessage): Promise { return await this.model.create(message); diff --git a/server/src/infrastructure/services/GeminiBotService.ts b/server/src/infrastructure/services/GeminiBotService.ts index 2950f7a2..691ce96e 100644 --- a/server/src/infrastructure/services/GeminiBotService.ts +++ b/server/src/infrastructure/services/GeminiBotService.ts @@ -22,12 +22,7 @@ export default class GeminiBotService implements IChatBotService { } async generateResponse(userMessage: string): Promise { - const prompt = ` - **User Message:** ${userMessage} - - **Behavior Rules:** - ${chatBotConfig.behavior_rules} - `; + const prompt = `**User Message:** ${userMessage}`; const result = await this.model.generateContent({ contents: [