|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>AI Doctor Consultation</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
<style> |
|
|
.typing-indicator::after { |
|
|
content: '...'; |
|
|
animation: typing 1.5s infinite; |
|
|
} |
|
|
|
|
|
@keyframes typing { |
|
|
0% { content: '.'; } |
|
|
33% { content: '..'; } |
|
|
66% { content: '...'; } |
|
|
} |
|
|
|
|
|
.chat-container { |
|
|
height: calc(100vh - 200px); |
|
|
} |
|
|
|
|
|
@media (max-width: 640px) { |
|
|
.chat-container { |
|
|
height: calc(100vh - 160px); |
|
|
} |
|
|
} |
|
|
|
|
|
.message-animation { |
|
|
animation: fadeIn 0.3s ease-in-out; |
|
|
} |
|
|
|
|
|
@keyframes fadeIn { |
|
|
from { opacity: 0; transform: translateY(10px); } |
|
|
to { opacity: 1; transform: translateY(0); } |
|
|
} |
|
|
|
|
|
.pulse { |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
|
|
|
@keyframes pulse { |
|
|
0% { opacity: 0.6; } |
|
|
50% { opacity: 1; } |
|
|
100% { opacity: 0.6; } |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gray-100 font-sans"> |
|
|
<div class="container mx-auto max-w-4xl px-4 py-8"> |
|
|
|
|
|
<header class="bg-white rounded-xl shadow-md p-6 mb-6 flex items-center"> |
|
|
<div class="w-16 h-16 rounded-full bg-blue-100 flex items-center justify-center mr-4"> |
|
|
<i class="fas fa-robot text-blue-500 text-2xl"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h1 class="text-2xl font-bold text-gray-800">AI Medical Assistant</h1> |
|
|
<p class="text-gray-600">Powered by HealthGPT</p> |
|
|
<div class="flex items-center mt-1"> |
|
|
<span class="text-yellow-400 mr-1"> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
</span> |
|
|
<span class="text-gray-500 text-sm">4.9 (2,457 reviews)</span> |
|
|
</div> |
|
|
</div> |
|
|
<div class="ml-auto"> |
|
|
<div class="flex items-center bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm"> |
|
|
<div class="w-2 h-2 bg-green-500 rounded-full mr-2"></div> |
|
|
Online now |
|
|
</div> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl shadow-md overflow-hidden"> |
|
|
|
|
|
<div class="bg-blue-600 text-white p-4 flex items-center"> |
|
|
<i class="fas fa-comment-medical mr-3"></i> |
|
|
<h2 class="font-semibold">AI Medical Consultation</h2> |
|
|
<div class="ml-auto flex space-x-2"> |
|
|
<button class="p-2 rounded-full hover:bg-blue-500 transition" title="Connect to human doctor"> |
|
|
<i class="fas fa-user-md"></i> |
|
|
</button> |
|
|
<button class="p-2 rounded-full hover:bg-blue-500 transition" title="Emergency contact"> |
|
|
<i class="fas fa-ambulance"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="chat-container overflow-y-auto p-4 space-y-4" id="chatMessages"> |
|
|
|
|
|
<div class="flex items-start message-animation"> |
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-robot text-blue-500"></i> |
|
|
</div> |
|
|
<div class="max-w-xs md:max-w-md bg-blue-100 text-gray-800 p-3 rounded-xl rounded-tl-none"> |
|
|
<p>Hello! I'm your AI medical assistant. I can help answer your health questions, but please remember:</p> |
|
|
<ul class="list-disc pl-5 mt-2 text-sm"> |
|
|
<li>I'm not a substitute for professional medical advice</li> |
|
|
<li>For emergencies, call your local emergency number</li> |
|
|
<li>Always consult with a healthcare provider for diagnosis</li> |
|
|
</ul> |
|
|
<p class="mt-2">How can I assist you today?</p> |
|
|
<p class="text-xs text-gray-500 mt-1">10:02 AM</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="flex items-start hidden" id="typingIndicator"> |
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-robot text-blue-500"></i> |
|
|
</div> |
|
|
<div class="max-w-xs md:max-w-md bg-blue-100 text-gray-800 p-3 rounded-xl rounded-tl-none"> |
|
|
<p class="typing-indicator"></p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="border-t border-gray-200 p-4 bg-gray-50"> |
|
|
<div class="flex items-center"> |
|
|
<button class="p-2 text-gray-500 hover:text-blue-500 mr-2" id="voiceButton"> |
|
|
<i class="fas fa-microphone"></i> |
|
|
</button> |
|
|
<input type="text" placeholder="Describe your symptoms or ask a question..." |
|
|
class="flex-1 border border-gray-300 rounded-full py-2 px-4 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" |
|
|
id="messageInput"> |
|
|
<button class="ml-2 p-2 bg-blue-500 text-white rounded-full hover:bg-blue-600 transition" |
|
|
id="sendButton"> |
|
|
<i class="fas fa-paper-plane"></i> |
|
|
</button> |
|
|
</div> |
|
|
<div class="mt-3 flex flex-wrap justify-center gap-2"> |
|
|
<button class="text-xs bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded-full flex items-center quick-prompt" data-prompt="I have a headache"> |
|
|
<i class="fas fa-head-side-cough mr-1"></i> Headache |
|
|
</button> |
|
|
<button class="text-xs bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded-full flex items-center quick-prompt" data-prompt="I have a fever"> |
|
|
<i class="fas fa-temperature-high mr-1"></i> Fever |
|
|
</button> |
|
|
<button class="text-xs bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded-full flex items-center quick-prompt" data-prompt="I have stomach pain"> |
|
|
<i class="fas fa-stomach mr-1"></i> Stomach pain |
|
|
</button> |
|
|
<button class="text-xs bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded-full flex items-center quick-prompt" data-prompt="I have a sore throat"> |
|
|
<i class="fas fa-lungs mr-1"></i> Sore throat |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="mt-6 grid grid-cols-2 md:grid-cols-4 gap-4"> |
|
|
<button class="bg-white p-4 rounded-xl shadow-sm hover:shadow-md transition flex flex-col items-center"> |
|
|
<div class="w-12 h-12 bg-green-100 rounded-full flex items-center justify-center mb-2"> |
|
|
<i class="fas fa-file-prescription text-green-500 text-xl"></i> |
|
|
</div> |
|
|
<span class="text-sm font-medium">Medication Info</span> |
|
|
</button> |
|
|
<button class="bg-white p-4 rounded-xl shadow-sm hover:shadow-md transition flex flex-col items-center"> |
|
|
<div class="w-12 h-12 bg-purple-100 rounded-full flex items-center justify-center mb-2"> |
|
|
<i class="fas fa-vial text-purple-500 text-xl"></i> |
|
|
</div> |
|
|
<span class="text-sm font-medium">Test Explanations</span> |
|
|
</button> |
|
|
<button class="bg-white p-4 rounded-xl shadow-sm hover:shadow-md transition flex flex-col items-center"> |
|
|
<div class="w-12 h-12 bg-yellow-100 rounded-full flex items-center justify-center mb-2"> |
|
|
<i class="fas fa-procedures text-yellow-500 text-xl"></i> |
|
|
</div> |
|
|
<span class="text-sm font-medium">Find Specialists</span> |
|
|
</button> |
|
|
<button class="bg-white p-4 rounded-xl shadow-sm hover:shadow-md transition flex flex-col items-center"> |
|
|
<div class="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center mb-2"> |
|
|
<i class="fas fa-first-aid text-red-500 text-xl"></i> |
|
|
</div> |
|
|
<span class="text-sm font-medium">First Aid Guide</span> |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="mt-6 bg-white p-4 rounded-lg shadow-sm text-xs text-gray-500"> |
|
|
<p class="font-medium mb-1">Important Disclaimer:</p> |
|
|
<p>This AI assistant provides general health information and is not a substitute for professional medical advice, diagnosis, or treatment. Always seek the advice of your physician or other qualified health provider with any questions you may have regarding a medical condition.</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
const chatMessages = document.getElementById('chatMessages'); |
|
|
const messageInput = document.getElementById('messageInput'); |
|
|
const sendButton = document.getElementById('sendButton'); |
|
|
const typingIndicator = document.getElementById('typingIndicator'); |
|
|
const voiceButton = document.getElementById('voiceButton'); |
|
|
|
|
|
|
|
|
async function callMedicalLLM(prompt, conversationHistory) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000)); |
|
|
|
|
|
|
|
|
const lowerPrompt = prompt.toLowerCase(); |
|
|
|
|
|
if (lowerPrompt.includes('headache')) { |
|
|
return generateHeadacheResponse(prompt); |
|
|
} else if (lowerPrompt.includes('fever') || lowerPrompt.includes('temperature')) { |
|
|
return generateFeverResponse(prompt); |
|
|
} else if (lowerPrompt.includes('stomach') || lowerPrompt.includes('abdominal')) { |
|
|
return generateStomachResponse(prompt); |
|
|
} else if (lowerPrompt.includes('throat') || lowerPrompt.includes('sore throat')) { |
|
|
return generateThroatResponse(prompt); |
|
|
} else if (lowerPrompt.includes('emergency') || lowerPrompt.includes('help')) { |
|
|
return { |
|
|
text: "Based on your description, this may require immediate medical attention. Please call emergency services or go to the nearest emergency room if you're experiencing: severe pain, difficulty breathing, chest pain, or any life-threatening symptoms.", |
|
|
suggestions: [ |
|
|
"Call 911 (or your local emergency number)", |
|
|
"Find nearest emergency room", |
|
|
"Contact your primary care physician" |
|
|
] |
|
|
}; |
|
|
} else { |
|
|
|
|
|
return { |
|
|
text: `I understand you're asking about "${prompt}". Could you please provide more details about:\n\n1. When the symptoms started\n2. The severity (mild, moderate, severe)\n3. Any other associated symptoms\n4. Any medications you're currently taking\n\nThis will help me provide more accurate information.`, |
|
|
suggestions: [ |
|
|
"How long have you had these symptoms?", |
|
|
"Can you describe the pain?", |
|
|
"Have you taken any medication for this?" |
|
|
] |
|
|
}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function generateHeadacheResponse(prompt) { |
|
|
const responses = [ |
|
|
`Headaches can have various causes. Could you describe:\n\n- Location of the pain (forehead, temples, back of head, etc.)\n- Type of pain (throbbing, dull, sharp)\n- Duration of the headache\n- Any triggers you've noticed\n\nThis will help determine possible causes and remedies.`, |
|
|
`For headaches, consider these possibilities:\n\n1. Tension headache: Often caused by stress, with dull pressure\n2. Migraine: Typically throbbing pain, often with nausea\n3. Cluster headache: Severe pain around one eye\n\nHave you noticed any patterns with your headaches?`, |
|
|
`Some general advice for headaches:\n\n- Stay hydrated\n- Rest in a quiet, dark room\n- Apply a cool compress\n- Consider OTC pain relievers (if no contraindications)\n\nHowever, if headaches are severe, persistent, or accompanied by vision changes, seek medical attention.` |
|
|
]; |
|
|
|
|
|
return { |
|
|
text: responses[Math.floor(Math.random() * responses.length)], |
|
|
suggestions: [ |
|
|
"Does light or sound make it worse?", |
|
|
"Have you had headaches before?", |
|
|
"Any recent head injury?" |
|
|
] |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
function generateFeverResponse(prompt) { |
|
|
return { |
|
|
text: `Fever is often a sign of infection. Important factors to consider:\n\n- Temperature reading if available\n- Duration of the fever\n- Associated symptoms (cough, rash, pain)\n- Age of the patient (children may need different care)\n\nFor adults, fever under 102°F (38.9°C) can often be managed with rest and fluids, but higher fevers or those lasting more than 3 days should be evaluated.`, |
|
|
suggestions: [ |
|
|
"How high is the fever?", |
|
|
"Any other symptoms?", |
|
|
"Any recent travel?" |
|
|
] |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
function generateStomachResponse(prompt) { |
|
|
return { |
|
|
text: `Abdominal pain can stem from many causes. Please describe:\n\n- Exact location of pain\n- Character (cramping, sharp, dull)\n- Relation to eating\n- Any nausea, vomiting, or diarrhea\n\nFor severe, persistent pain or if accompanied by fever or vomiting blood, seek immediate care.`, |
|
|
suggestions: [ |
|
|
"When did the pain start?", |
|
|
"Have you eaten anything unusual?", |
|
|
"Any bowel movement changes?" |
|
|
] |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
function generateThroatResponse(prompt) { |
|
|
return { |
|
|
text: `Sore throat causes include:\n\n1. Viral infections (most common)\n2. Strep throat (bacterial, needs testing)\n3. Allergies or irritants\n\nKey indicators:\n- Fever?\n- White patches on tonsils?\n- Difficulty swallowing?\n\nFor persistent sore throat >48 hours or with fever, consider seeing a doctor for possible strep test.`, |
|
|
suggestions: [ |
|
|
"Do you have swollen glands?", |
|
|
"Any fever?", |
|
|
"Difficulty swallowing?" |
|
|
] |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
async function sendMessage() { |
|
|
const messageText = messageInput.value.trim(); |
|
|
if (messageText === '') return; |
|
|
|
|
|
|
|
|
addMessage(messageText, 'patient'); |
|
|
messageInput.value = ''; |
|
|
|
|
|
|
|
|
typingIndicator.classList.remove('hidden'); |
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
|
|
|
try { |
|
|
|
|
|
const response = await callMedicalLLM(messageText, getConversationHistory()); |
|
|
|
|
|
|
|
|
typingIndicator.classList.add('hidden'); |
|
|
|
|
|
|
|
|
addMessage(response.text, 'ai'); |
|
|
|
|
|
|
|
|
if (response.suggestions && response.suggestions.length > 0) { |
|
|
addSuggestions(response.suggestions); |
|
|
} |
|
|
} catch (error) { |
|
|
typingIndicator.classList.add('hidden'); |
|
|
addMessage("I'm having trouble processing your request. Please try again or contact a healthcare provider directly.", 'ai'); |
|
|
console.error('Error calling LLM:', error); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function getConversationHistory() { |
|
|
const messages = chatMessages.querySelectorAll('.flex.items-start'); |
|
|
const history = []; |
|
|
|
|
|
messages.forEach(msg => { |
|
|
if (msg.querySelector('.bg-blue-500')) { |
|
|
history.push({ |
|
|
role: 'user', |
|
|
content: msg.querySelector('.bg-blue-500 p').textContent |
|
|
}); |
|
|
} else if (msg.querySelector('.bg-blue-100') && !msg.id === 'typingIndicator') { |
|
|
history.push({ |
|
|
role: 'assistant', |
|
|
content: msg.querySelector('.bg-blue-100 p').textContent |
|
|
}); |
|
|
} |
|
|
}); |
|
|
|
|
|
return history; |
|
|
} |
|
|
|
|
|
|
|
|
function addMessage(text, sender) { |
|
|
const now = new Date(); |
|
|
const timeString = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); |
|
|
|
|
|
const messageDiv = document.createElement('div'); |
|
|
messageDiv.className = `flex items-start ${sender === 'patient' ? 'justify-end' : ''} message-animation`; |
|
|
|
|
|
if (sender === 'patient') { |
|
|
messageDiv.innerHTML = ` |
|
|
<div class="max-w-xs md:max-w-md bg-blue-500 text-white p-3 rounded-xl rounded-tr-none"> |
|
|
<p>${text}</p> |
|
|
<p class="text-xs text-blue-100 mt-1">${timeString}</p> |
|
|
</div> |
|
|
<div class="w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center ml-3"> |
|
|
<i class="fas fa-user text-gray-600"></i> |
|
|
</div> |
|
|
`; |
|
|
} else { |
|
|
|
|
|
messageDiv.innerHTML = ` |
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-robot text-blue-500"></i> |
|
|
</div> |
|
|
<div class="max-w-xs md:max-w-md bg-blue-100 text-gray-800 p-3 rounded-xl rounded-tl-none"> |
|
|
<p class="whitespace-pre-line">${text}</p> |
|
|
<p class="text-xs text-gray-500 mt-1">${timeString}</p> |
|
|
</div> |
|
|
`; |
|
|
} |
|
|
|
|
|
chatMessages.appendChild(messageDiv); |
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
} |
|
|
|
|
|
|
|
|
function addSuggestions(suggestions) { |
|
|
const suggestionsDiv = document.createElement('div'); |
|
|
suggestionsDiv.className = 'mt-3 flex flex-wrap justify-start gap-2'; |
|
|
|
|
|
suggestions.forEach(suggestion => { |
|
|
const button = document.createElement('button'); |
|
|
button.className = 'text-xs bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded-full flex items-center suggestion-button'; |
|
|
button.innerHTML = `<i class="fas fa-reply mr-1 text-xs"></i> ${suggestion}`; |
|
|
button.addEventListener('click', () => { |
|
|
messageInput.value = suggestion; |
|
|
suggestionsDiv.remove(); |
|
|
}); |
|
|
suggestionsDiv.appendChild(button); |
|
|
}); |
|
|
|
|
|
chatMessages.appendChild(suggestionsDiv); |
|
|
chatMessages.scrollTop = chatMessages.scrollHeight; |
|
|
} |
|
|
|
|
|
|
|
|
sendButton.addEventListener('click', sendMessage); |
|
|
messageInput.addEventListener('keypress', function(e) { |
|
|
if (e.key === 'Enter') { |
|
|
sendMessage(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.quick-prompt').forEach(button => { |
|
|
button.addEventListener('click', function() { |
|
|
messageInput.value = this.dataset.prompt; |
|
|
messageInput.focus(); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
let voiceRecognitionActive = false; |
|
|
voiceButton.addEventListener('click', function() { |
|
|
if (voiceRecognitionActive) { |
|
|
|
|
|
voiceRecognitionActive = false; |
|
|
voiceButton.innerHTML = '<i class="fas fa-microphone"></i>'; |
|
|
voiceButton.classList.remove('text-red-500', 'pulse'); |
|
|
} else { |
|
|
|
|
|
voiceRecognitionActive = true; |
|
|
voiceButton.innerHTML = '<i class="fas fa-microphone-slash"></i>'; |
|
|
voiceButton.classList.add('text-red-500', 'pulse'); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
if (voiceRecognitionActive) { |
|
|
const samplePhrases = [ |
|
|
"I've had a headache for two days", |
|
|
"My temperature is 101 degrees", |
|
|
"I have pain in my lower right abdomen", |
|
|
"It hurts when I swallow" |
|
|
]; |
|
|
|
|
|
const randomPhrase = samplePhrases[Math.floor(Math.random() * samplePhrases.length)]; |
|
|
messageInput.value = randomPhrase; |
|
|
|
|
|
|
|
|
voiceRecognitionActive = false; |
|
|
voiceButton.innerHTML = '<i class="fas fa-microphone"></i>'; |
|
|
voiceButton.classList.remove('text-red-500', 'pulse'); |
|
|
} |
|
|
}, 1500 + Math.random() * 2000); |
|
|
} |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=kamstar/ai-doc" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |