ManavDhayeCoder commited on
Commit
7314527
Β·
verified Β·
1 Parent(s): 0328203

uploadfiles

Browse files
Files changed (7) hide show
  1. Dockerfile +20 -0
  2. app.py +59 -0
  3. requirements.txt +9 -0
  4. src/helper.py +10 -0
  5. src/prompt.py +9 -0
  6. static/style.css +167 -0
  7. templates/index.html +115 -0
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use official Python image
2
+ FROM python:3.10
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Copy requirements
8
+ COPY requirements.txt /app/
9
+
10
+ # Install Python dependencies
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # Copy all application files
14
+ COPY . /app/
15
+
16
+ # Expose required port for Hugging Face
17
+ EXPOSE 7860
18
+
19
+ # Command to run Flask app
20
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_google_genai import ChatGoogleGenerativeAI
2
+ from langchain_core.prompts import ChatPromptTemplate
3
+ from langchain.chains.combine_documents import create_stuff_documents_chain
4
+ from langchain.chains import create_retrieval_chain
5
+ from src.helper import download_embeding
6
+ from langchain_pinecone import PineconeVectorStore
7
+ from src.prompt import system_prompt
8
+ import os
9
+ from flask import Flask, render_template, jsonify, request
10
+ from dotenv import load_dotenv
11
+ from pinecone import Pinecone
12
+ load_dotenv()
13
+
14
+ model = ChatGoogleGenerativeAI(model="gemini-2.5-flash", google_api_key=os.getenv("GOOGLE_API_KEY"))
15
+ app=Flask(__name__)
16
+ PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
17
+ pc = Pinecone(api_key=PINECONE_API_KEY)
18
+ index_name='medicalchatbot'
19
+ embedding=download_embeding()
20
+
21
+ docsearch=PineconeVectorStore.from_existing_index(
22
+ index_name=index_name,
23
+ embedding=embedding
24
+ )
25
+
26
+ retiver=docsearch.as_retriever(search_type="similarity", search_kwargs={"k": 3})
27
+
28
+
29
+ prompt = ChatPromptTemplate.from_messages(
30
+ [
31
+ ("system", system_prompt),
32
+ ("human", "{input}"),
33
+ ]
34
+ )
35
+
36
+ question_answer_chain=create_stuff_documents_chain(model,prompt)
37
+ rag_chain=create_retrieval_chain(retiver,question_answer_chain)
38
+
39
+ @app.route("/")
40
+ def index():
41
+ return render_template('index.html')
42
+
43
+ @app.route("/get", methods=["GET", "POST"])
44
+ def chat():
45
+ msg = request.form.get("msg", "").strip()
46
+ if not msg:
47
+ return "Please enter a question.", 400
48
+
49
+ response = rag_chain.invoke({"input": msg})
50
+ answer = response.get("answer", "Sorry, I couldn't generate a response.")
51
+ print("Response:", answer)
52
+ return answer
53
+
54
+
55
+
56
+
57
+ if __name__ == '__main__':
58
+ port = int(os.environ.get("PORT", 7860))
59
+ app.run(host="0.0.0.0", port=port)
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ langchain==0.3.26
2
+ langchain-community==0.3.26
3
+ langchain-core==0.3.26
4
+ flask==3.1.1
5
+ sentence-transformers==5.1.2
6
+ python-dotenv==1.0.1
7
+ langchain-pinecone==0.2.2
8
+ langchain-google-genai==2.0.4
9
+ pinecone-client==4.1.2
src/helper.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.embeddings import HuggingFaceEmbeddings
2
+ import torch
3
+
4
+
5
+ def download_embeding():
6
+ embedding = HuggingFaceEmbeddings(
7
+ model_name="sentence-transformers/all-MiniLM-L6-v2",
8
+ model_kwargs={"device": "cuda" if torch.cuda.is_available() else "cpu"}
9
+ )
10
+ return embedding
src/prompt.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ system_prompt = (
2
+ "You are an Medical assistant for question-answering tasks. "
3
+ "Use the following pieces of retrieved context to answer "
4
+ "the question. If you don't know the answer, say that you "
5
+ "don't know. Use three sentences maximum and keep the "
6
+ "answer concise."
7
+ "\n\n"
8
+ "{context}"
9
+ )
static/style.css ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body.dark {
2
+ background: #1c1c1c !important;
3
+ color: white !important;
4
+ }
5
+
6
+ body.dark .chat-container {
7
+ background: #2b2b2b;
8
+ color: white;
9
+ }
10
+
11
+ body.dark .chat-box {
12
+ background: #333;
13
+ border-color: #444;
14
+ }
15
+
16
+ body.dark .message.user {
17
+ background: #4c6ef5;
18
+ color: white;
19
+ }
20
+
21
+ body.dark .message.bot {
22
+ background: #555;
23
+ color: white;
24
+ }
25
+
26
+ body.dark #sendBtn {
27
+ background: #4c6ef5;
28
+ }
29
+
30
+ body.dark #themeToggle {
31
+ color: white;
32
+ border-color: white;
33
+ }
34
+
35
+ /* Loading Animation */
36
+ .loading {
37
+ display: flex;
38
+ justify-content: center;
39
+ margin: 10px 0;
40
+ }
41
+
42
+ .spinner {
43
+ width: 30px;
44
+ height: 30px;
45
+ border: 4px solid #ccc;
46
+ border-top: 4px solid #007bff;
47
+ border-radius: 50%;
48
+ animation: spin 1s linear infinite;
49
+ }
50
+
51
+ @keyframes spin {
52
+ 0% { transform: rotate(0deg); }
53
+ 100% { transform: rotate(360deg); }
54
+ }
55
+
56
+ /* Doctor Avatar + Bottom Bar */
57
+ .bottom-bar {
58
+ display: flex;
59
+ justify-content: space-between;
60
+ align-items: center;
61
+ margin-top: 10px;
62
+ }
63
+
64
+ .doctor-avatar {
65
+ width: 40px;
66
+ height: 40px;
67
+ border-radius: 50%;
68
+ }
69
+
70
+ body {
71
+ background: linear-gradient(135deg, #5a8dee, #6ed3cf);
72
+ font-family: 'Poppins', sans-serif;
73
+ margin: 0;
74
+ padding: 20px;
75
+ display: flex;
76
+ justify-content: center;
77
+ align-items: center;
78
+ height: 100vh;
79
+ }
80
+
81
+ .chat-container {
82
+ background: #ffffff;
83
+ width: 420px;
84
+ border-radius: 20px;
85
+ padding: 20px;
86
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
87
+ animation: fadeIn 0.7s ease-in-out;
88
+ }
89
+
90
+ .header {
91
+ text-align: center;
92
+ margin-bottom: 20px;
93
+ }
94
+
95
+ .header .logo {
96
+ width: 70px;
97
+ margin-bottom: 10px;
98
+ }
99
+
100
+ .header h2 {
101
+ margin: 0;
102
+ font-weight: 600;
103
+ color: #333;
104
+ }
105
+
106
+ .header p {
107
+ font-size: 14px;
108
+ color: #666;
109
+ }
110
+
111
+ .chat-box {
112
+ height: 360px;
113
+ overflow-y: auto;
114
+ border-radius: 10px;
115
+ padding: 10px;
116
+ background: #f7f9fc;
117
+ margin-bottom: 15px;
118
+ border: 1px solid #e5e5e5;
119
+ }
120
+
121
+ .message {
122
+ padding: 10px;
123
+ margin-bottom: 10px;
124
+ border-radius: 10px;
125
+ max-width: 85%;
126
+ animation: slideIn 0.4s ease-in-out;
127
+ }
128
+
129
+ .message.user {
130
+ background: #d1e8ff;
131
+ align-self: flex-end;
132
+ text-align: right;
133
+ }
134
+
135
+ .message.bot {
136
+ background: #e6e6e6;
137
+ text-align: left;
138
+ }
139
+
140
+ .input-area textarea {
141
+ border-radius: 10px;
142
+ resize: none;
143
+ border: 1px solid #bcd;
144
+ }
145
+
146
+ #sendBtn {
147
+ border-radius: 10px;
148
+ font-weight: 600;
149
+ padding: 10px;
150
+ background: #0066ff;
151
+ }
152
+
153
+ #sendBtn:hover {
154
+ background: #004ecc;
155
+ }
156
+
157
+ /* Animations */
158
+ @keyframes fadeIn {
159
+ from { opacity: 0; transform: translateY(20px); }
160
+ to { opacity: 1; transform: translateY(0); }
161
+ }
162
+
163
+ @keyframes slideIn {
164
+ from { opacity: 0; transform: translateX(20px); }
165
+ to { opacity: 1; transform: translateX(0); }
166
+ }
167
+ to { opacity: 1; transform: translateX(0); }
templates/index.html ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- index.html -->
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Medical Assistant Chatbot</title>
8
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" />
9
+ <link rel="preconnect" href="https://fonts.googleapis.com">
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
12
+ <!-- Bootstrap -->
13
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
14
+ </head>
15
+ <body>
16
+
17
+ <div class="chat-container">
18
+ <div class="header">
19
+ <img src="https://cdn-icons-png.flaticon.com/512/921/921347.png" alt="Medical Icon" class="logo" />
20
+ <h2>AI Medical Assistant</h2>
21
+ <p>Your smart healthcare companion</p>
22
+ </div>
23
+
24
+ <div class="chat-box" id="chatBox">
25
+ <!-- Chat messages will appear here -->
26
+ </div>
27
+
28
+ <div class="input-area">
29
+ <textarea id="userInput" class="form-control" placeholder="Describe your symptoms or ask a medical question..." rows="3"></textarea>
30
+ <button id="sendBtn" class="btn btn-primary mt-2 w-100">Send</button>
31
+ </div>
32
+
33
+ <!-- Doctor Avatar + Toggle Theme -->
34
+ <div class="bottom-bar">
35
+ <img src="https://cdn-icons-png.flaticon.com/512/387/387561.png" class="doctor-avatar" />
36
+ <button id="themeToggle" class="btn btn-outline-secondary btn-sm">πŸŒ™ Dark Mode</button>
37
+ </div>
38
+
39
+ </div>
40
+
41
+ <script>
42
+ const chatBox = document.getElementById('chatBox');
43
+ const sendBtn = document.getElementById('sendBtn');
44
+ const userInput = document.getElementById('userInput');
45
+
46
+ function appendMessage(sender, message) {
47
+ const msg = document.createElement('div');
48
+ msg.classList.add('message', sender);
49
+ msg.innerHTML = `<p>${message}</p>`;
50
+ chatBox.appendChild(msg);
51
+ chatBox.scrollTop = chatBox.scrollHeight;
52
+ }
53
+
54
+ function showLoading() {
55
+ const loading = document.createElement('div');
56
+ loading.classList.add('loading');
57
+ loading.innerHTML = `<div class="spinner"></div>`;
58
+ chatBox.appendChild(loading);
59
+ chatBox.scrollTop = chatBox.scrollHeight;
60
+ }
61
+
62
+ function hideLoading() {
63
+ const loading = document.querySelector('.loading');
64
+ if (loading) loading.remove();
65
+ }
66
+
67
+ sendBtn.addEventListener('click', sendMessage);
68
+ userInput.addEventListener('keypress', (e) => {
69
+ if (e.key === 'Enter' && !e.shiftKey) {
70
+ e.preventDefault();
71
+ sendMessage();
72
+ }
73
+ });
74
+
75
+ function sendMessage() {
76
+ const text = userInput.value.trim();
77
+ if (!text) return;
78
+
79
+ appendMessage('user', text);
80
+ userInput.value = '';
81
+
82
+ showLoading();
83
+
84
+ fetch("/get", {
85
+ method: "POST",
86
+ headers: {
87
+ "Content-Type": "application/x-www-form-urlencoded",
88
+ },
89
+ body: `msg=${encodeURIComponent(text)}`
90
+ })
91
+ .then(res => res.text())
92
+ .then(data => {
93
+ hideLoading();
94
+ appendMessage("bot", data);
95
+ })
96
+ .catch(err => {
97
+ hideLoading();
98
+ appendMessage("bot", "Error connecting to server.");
99
+ console.error(err);
100
+ });
101
+ }
102
+
103
+ // Dark / Light Theme Toggle
104
+ const themeToggle = document.getElementById('themeToggle');
105
+ themeToggle.addEventListener('click', () => {
106
+ document.body.classList.toggle('dark');
107
+ themeToggle.textContent = document.body.classList.contains('dark')
108
+ ? "β˜€ Light Mode"
109
+ : "πŸŒ™ Dark Mode";
110
+ });
111
+ </script>
112
+
113
+ </body>
114
+ </html>
115
+