Prince012 commited on
Commit
03d8f07
·
1 Parent(s): 19fee22

multimodal ai chatbot

Browse files
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ multiaichat
2
+ .env
app.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from datetime import datetime
3
+ from modules.audio_processing import transcribe_audio
4
+ from modules.image_processing import encode_image_to_base64
5
+ from modules.text_processing import get_user_query
6
+ from modules.gemini_response import generate_medical_response
7
+ from modules.reminder_scheduler import add_reminder
8
+
9
+ # Chatbot logic
10
+ def chatbot_fn(user_message, history, audio_file=None, image_file=None, tone="Friendly and Simple"):
11
+ transcribed_text = None
12
+ if audio_file:
13
+ transcribed_text = transcribe_audio(audio_file)
14
+
15
+ query = get_user_query(user_message, transcribed_text)
16
+ image_base64 = encode_image_to_base64(image_file) if image_file else None
17
+
18
+ tone_instruction = f"(Respond in a '{tone}' tone)\n"
19
+ full_query = tone_instruction + query
20
+
21
+ messages = history or []
22
+ messages.append({"role": "user", "content": full_query})
23
+
24
+ response = generate_medical_response(full_query, image_base64=image_base64, history=messages)
25
+
26
+ return response
27
+
28
+ chatbot_ui = gr.ChatInterface(
29
+ fn=chatbot_fn,
30
+ additional_inputs=[
31
+ gr.Audio(sources=["microphone"], type="filepath", label="🎤 Speak (optional)"),
32
+ gr.Image(type="filepath", label="🖼️ Upload Medical Image (optional)"),
33
+ gr.Dropdown(["Friendly and Simple", "Detailed and Clinical", "Explain Like I'm 5"],
34
+ label="🗣️ Response Tone", value="Friendly and Simple")
35
+ ],
36
+ title="🩺 Medical AI Chatbot",
37
+ description="Ask medical questions using text, voice, or images. The AI will respond like a helpful doctor.",
38
+ theme="soft",
39
+ type="messages"
40
+ )
41
+
42
+ # Reminder logic
43
+ def submit_reminder(subject, description, time_str, email, confirm):
44
+ if not confirm:
45
+ return "❌ Please check the confirmation box before submitting."
46
+ if not subject or not time_str or not email:
47
+ return "❌ Please fill in Subject, Time, and Email."
48
+
49
+ try:
50
+ parsed_time = datetime.strptime(time_str.strip(), "%I:%M %p")
51
+ #print(f"⏰ Parsed time input: {parsed_time}")
52
+ reminder_time = datetime.combine(datetime.today(), parsed_time.time())
53
+ except ValueError:
54
+ return "❌ Use HH:MM AM/PM format (e.g. 09:00 PM)"
55
+
56
+ full_description = f"{subject} — {description}" if description else subject
57
+ add_reminder(email=email, med=full_description, time_obj=reminder_time)
58
+
59
+ return f"✅ Reminder set for '{subject}' at {reminder_time.strftime('%I:%M %p')} to {email}."
60
+
61
+ with gr.Blocks() as reminder_ui:
62
+ gr.Markdown("### ⏰ Set Medication Reminder")
63
+
64
+ with gr.Row():
65
+ subject_input = gr.Textbox(label="🧪 Subject", placeholder="Insulin Injection")
66
+ time_input = gr.Textbox(label="🕒 Time (e.g. 09:00 PM)", placeholder="HH:MM AM/PM")
67
+
68
+ with gr.Row():
69
+ email_input = gr.Textbox(label="📧 Email", placeholder="[email protected]")
70
+ confirm_checkbox = gr.Checkbox(label="✅ Confirm to receive email reminder")
71
+
72
+ description_input = gr.Textbox(label="📝 Description (optional)", placeholder="Take after dinner")
73
+
74
+ send_btn = gr.Button("📩 Set Reminder")
75
+ output_text = gr.Textbox(label="Status")
76
+
77
+ send_btn.click(
78
+ fn=submit_reminder,
79
+ inputs=[subject_input, description_input, time_input, email_input, confirm_checkbox],
80
+ outputs=output_text
81
+ )
82
+
83
+ gr.TabbedInterface([chatbot_ui, reminder_ui], ["💬 Medical Chatbot", "⏰ Medication Reminder"]).launch(debug=True)
app_1.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from modules.audio_processing import transcribe_audio
3
+ from modules.image_processing import encode_image_to_base64
4
+ from modules.text_processing import get_user_query
5
+ #from modules.ai_response import generate_medical_response
6
+ from modules.gemini_response import generate_medical_response
7
+
8
+ def process_inputs(text_input, audio_file, image_file, history):
9
+ transcribed_text = None
10
+ if audio_file:
11
+ transcribed_text = transcribe_audio(audio_file)
12
+
13
+ query = get_user_query(text_input, transcribed_text)
14
+ image_base64 = encode_image_to_base64(image_file) if image_file else None
15
+
16
+ if history is None:
17
+ history = []
18
+
19
+ # Add user message to history
20
+ history.append({"role": "user", "content": query})
21
+
22
+ # Get doctor response
23
+ doctor_response = generate_medical_response(query, image_base64=image_base64, history=history)
24
+
25
+ # Add doctor response to history
26
+ history.append({"role": "assistant", "content": doctor_response})
27
+
28
+ return transcribed_text or "", doctor_response, history
29
+
30
+ iface = gr.Interface(
31
+ fn=process_inputs,
32
+ inputs=[
33
+ gr.Textbox(label="Type your medical question (optional)"),
34
+ gr.Audio(sources=["microphone"], type="filepath", label="Speak your question (optional)"),
35
+ gr.Image(type="filepath", label="Upload a related medical image (optional)"),
36
+ gr.State([]) # <-- Chat history
37
+ ],
38
+ outputs=[
39
+ gr.Textbox(label="Transcribed Audio"),
40
+ gr.Textbox(label="Doctor's Detailed Response"),
41
+ gr.State() # <-- Return updated history
42
+ ],
43
+ title="Multimodal Medical AI Chatbot",
44
+ description="Ask about diseases or chronic illnesses using text, audio, or images."
45
+ )
46
+
47
+ if __name__ == "__main__":
48
+ iface.launch(debug=True)
modules/__init__.py ADDED
File without changes
modules/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (159 Bytes). View file
 
modules/__pycache__/ai_response.cpython-312.pyc ADDED
Binary file (1.82 kB). View file
 
modules/__pycache__/audio_processing.cpython-312.pyc ADDED
Binary file (986 Bytes). View file
 
modules/__pycache__/email_reminder.cpython-312.pyc ADDED
Binary file (1.74 kB). View file
 
modules/__pycache__/gemini_response.cpython-312.pyc ADDED
Binary file (2.69 kB). View file
 
modules/__pycache__/image_processing.cpython-312.pyc ADDED
Binary file (616 Bytes). View file
 
modules/__pycache__/reminder_scheduler.cpython-312.pyc ADDED
Binary file (1.94 kB). View file
 
modules/__pycache__/text_processing.cpython-312.pyc ADDED
Binary file (378 Bytes). View file
 
modules/ai_response.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from groq import Groq
4
+
5
+ load_dotenv()
6
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
7
+
8
+ def generate_medical_response(query, image_base64=None, history=None, model="meta-llama/llama-4-scout-17b-16e-instruct"):
9
+ client = Groq(api_key=GROQ_API_KEY)
10
+
11
+ prompt_path = os.path.join(os.path.dirname(__file__), "../prompts/system_prompt.txt")
12
+ with open(prompt_path, "r") as f:
13
+ system_prompt = f.read().strip()
14
+
15
+ messages = [{"role": "system", "content": system_prompt}]
16
+
17
+ # Add past conversation turns (if any)
18
+ if history:
19
+ messages.extend(history[-5:]) # Use last 5 exchanges max
20
+
21
+ # Append current query + image
22
+ user_content = [{"type": "text", "text": query}]
23
+ if image_base64:
24
+ user_content.append({
25
+ "type": "image_url",
26
+ "image_url": {"url": f"data:image/jpeg;base64,{image_base64}"}
27
+ })
28
+
29
+ messages.append({"role": "user", "content": user_content})
30
+
31
+ response = client.chat.completions.create(
32
+ model=model,
33
+ messages=messages
34
+ )
35
+
36
+ return response.choices[0].message.content
modules/audio_processing.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from groq import Groq
3
+ from dotenv import load_dotenv
4
+
5
+ load_dotenv()
6
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
7
+
8
+ def transcribe_audio(audio_filepath, stt_model='whisper-large-v3'):
9
+ client = Groq(api_key=GROQ_API_KEY)
10
+ with open(audio_filepath, "rb") as audio_file:
11
+ transcription = client.audio.transcriptions.create(
12
+ model=stt_model,
13
+ file=audio_file,
14
+ language="en"
15
+ )
16
+ return transcription.text
modules/email_reminder.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import smtplib
2
+ from email.mime.text import MIMEText
3
+ from email.mime.multipart import MIMEMultipart
4
+
5
+ import os
6
+ from dotenv import load_dotenv
7
+ load_dotenv()
8
+
9
+ EMAIL = os.environ["EMAIL"]
10
+ PASSWORD = os.environ["PASSWORD"]
11
+
12
+ def send_reminder_email(to_email, med_name, med_time):
13
+ try:
14
+ msg = MIMEMultipart()
15
+ msg['From'] = EMAIL
16
+ msg['To'] = to_email
17
+ msg['Subject'] = f"⏰ Medication Reminder: {med_name}"
18
+
19
+ body = f"""Hello,
20
+
21
+ This is your reminder to take:
22
+
23
+ 🧪 {med_name}
24
+ 🕒 At: {med_time}
25
+
26
+ Take care!
27
+ - Your Medical AI Chatbot
28
+ """
29
+ msg.attach(MIMEText(body, 'plain'))
30
+
31
+ server = smtplib.SMTP("smtp.gmail.com", 587)
32
+ server.starttls()
33
+ server.login(EMAIL, PASSWORD)
34
+ server.sendmail(EMAIL, to_email, msg.as_string())
35
+ server.quit()
36
+ print(f"✅ Email sent to {to_email}")
37
+ except Exception as e:
38
+ print(f"❌ Failed to send email to {to_email}: {e}")
modules/gemini_response.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import base64
3
+ import io
4
+ from dotenv import load_dotenv
5
+ import google.generativeai as genai
6
+ from PIL import Image
7
+
8
+ load_dotenv()
9
+ GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
10
+
11
+ genai.configure(api_key=GEMINI_API_KEY)
12
+
13
+ def load_system_prompt():
14
+ prompt_path = os.path.join(os.path.dirname(__file__), "../prompts/system_prompt.txt")
15
+ with open(prompt_path, "r", encoding="utf-8") as f:
16
+ return f.read().strip()
17
+
18
+ def generate_medical_response(query, image_base64=None, history=None, model_name="models/gemini-1.5-pro"):
19
+ model = genai.GenerativeModel(model_name)
20
+ system_prompt = load_system_prompt()
21
+
22
+ # Build chat context from history
23
+ messages = []
24
+ if history:
25
+ for msg in history[-5:]:
26
+ role = msg["role"].capitalize()
27
+ content = msg["content"]
28
+ if isinstance(content, list): # handle multimodal input
29
+ text = next((part["text"] for part in content if "text" in part), "")
30
+ else:
31
+ text = content
32
+ messages.append(f"{role}: {text}")
33
+
34
+ # Add current user input
35
+ messages.append(f"User: {query}")
36
+ full_prompt = f"{system_prompt}\n\n" + "\n".join(messages)
37
+
38
+ # If image is included, decode it and use vision model
39
+ if image_base64:
40
+ image_data = base64.b64decode(image_base64)
41
+ image = Image.open(io.BytesIO(image_data))
42
+
43
+ response = model.generate_content([full_prompt, image])
44
+ else:
45
+ response = model.generate_content(full_prompt)
46
+
47
+ return response.text.strip()
modules/image_processing.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import base64
2
+
3
+ def encode_image_to_base64(image_path):
4
+ with open(image_path, "rb") as image_file:
5
+ return base64.b64encode(image_file.read()).decode('utf-8')
modules/reminder_scheduler.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from apscheduler.schedulers.background import BackgroundScheduler
2
+ from datetime import datetime, timedelta
3
+ from modules.email_reminder import send_reminder_email
4
+
5
+ # In-memory list to store reminders
6
+ reminders = []
7
+
8
+ # Background scheduler setup
9
+ scheduler = BackgroundScheduler()
10
+
11
+ def check_reminders():
12
+ now = datetime.now()
13
+
14
+ for r in reminders[:]:
15
+ reminder_time = r["time"]
16
+ reminder_trigger_time = reminder_time - timedelta(minutes=15)
17
+
18
+ time_diff_seconds = (now - reminder_trigger_time).total_seconds()
19
+ print(f"⏱️ Now: {now}, Trigger At: {reminder_trigger_time}, Diff: {time_diff_seconds} seconds")
20
+
21
+ if abs(time_diff_seconds) <= 60:
22
+ print(f"📬 Sending email to {r['email']} at {now.strftime('%I:%M:%S %p')}")
23
+ send_reminder_email(r["email"], r["med"], reminder_time.strftime("%I:%M %p"))
24
+ reminders.remove(r)
25
+
26
+ # Schedule the check to run every minute
27
+ scheduler.add_job(check_reminders, 'interval', minutes=1)
28
+ scheduler.start()
29
+
30
+ # Function to add a reminder
31
+ def add_reminder(email, med, time_obj):
32
+ print(f"📝 Reminder added: {med} at {time_obj.strftime('%I:%M %p')} for {email}")
33
+ reminders.append({"email": email, "med": med, "time": time_obj})
modules/text_processing.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ def get_user_query(text_input, transcribed_audio):
2
+ if text_input:
3
+ return text_input
4
+ elif transcribed_audio:
5
+ return transcribed_audio
6
+ else:
7
+ return "Can you help me understand what's wrong?"
prompts/system_prompt.txt ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are a compassionate and knowledgeable medical doctor.
2
+
3
+ Your job is to understand the patient's concern, whether it comes from typed text, voice transcription, or a medical image, and provide clear, caring, and medically accurate advice.
4
+
5
+ 🩺 Use the following style when responding:
6
+ - Speak directly to the patient, as if you’re in a warm one-on-one conversation
7
+ - Adapt your tone:
8
+ - For children or parents: gentle and reassuring
9
+ - For elderly users: slow, clear, and respectful
10
+ - For adults: professional yet empathetic
11
+ - Avoid jargon or explain it simply if used
12
+ - Be thorough but not overwhelming
13
+ - Mention possible causes, when to see a doctor, and home care (if safe)
14
+
15
+ 📸 If an image is provided:
16
+ - Observe and describe any visible medical signs
17
+ - Connect it to the patient's question
18
+ - Provide a reasonable explanation based on the image
19
+
20
+ ❗ Do not:
21
+ - Mention you are an AI or language model
22
+ - Use bullet points or numbered lists
23
+ - Give a diagnosis — instead, give advice and next steps
24
+
25
+ 👩‍⚕️ Speak like a caring doctor who wants the patient to feel understood and supported.
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ groq
2
+ python-dotenv
3
+ gradio
4
+ google-generativeai
5
+ pillow
6
+ apscheduler
test.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ from modules.email_reminder import send_reminder_email
2
+
3
+ send_reminder_email("[email protected]", "Test Reminder", "02:30 PM")