NeerajAhire commited on
Commit
57be78b
·
verified ·
1 Parent(s): eea040d

Upload chat_app.py

Browse files
Files changed (1) hide show
  1. chat_app.py +363 -0
chat_app.py ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from Client.mcp_client import MCPClientExcelRAG
3
+ from test import run_agent # ← import agent entry point
4
+
5
+ # Initialize MCP client
6
+ client = MCPClientExcelRAG()
7
+ client.start()
8
+
9
+ # --- Supported scope for intent/planner ---
10
+ SUPPORTED_IITS = ["IIT Bombay", "IIT Delhi", "IIT Madras"]
11
+ SUPPORTED_BRANCHES = ["CSE", "ECE", "Mechanical", "Electrical", "Engineering Design"]
12
+ YEARS = ["2024", "2025"]
13
+
14
+ # --- Core ask: writes into selected session and returns messages twice ---
15
+ '''
16
+ def ask(history, question, top_k, temperature, sessions, selected_name):
17
+ history = history or []
18
+ sessions = sessions or []
19
+ selected_name = selected_name or (sessions[-1]["name"] if sessions else None)
20
+
21
+ if not question or not question.strip():
22
+ history.append({"role": "assistant", "content": "⚠️ Please enter a question."})
23
+ # also update the current session if exists
24
+ if selected_name:
25
+ for s in sessions:
26
+ if s["name"] == selected_name:
27
+ s["messages"] = history
28
+ break
29
+ return history, history, sessions
30
+
31
+ # Append user message
32
+ history.append({"role": "user", "content": question})
33
+
34
+ # Agent call: intent → plan → call MCP tools → synthesize
35
+ try:
36
+ final_answer = run_agent(
37
+ user_q=question,
38
+ mcp_client=client,
39
+ available_iits=SUPPORTED_IITS,
40
+ available_branches=SUPPORTED_BRANCHES,
41
+ years=YEARS,
42
+ top_k=int(top_k),
43
+ temperature=float(temperature),
44
+ )
45
+ except Exception as e:
46
+ final_answer = f"❌ Error while processing your request: {str(e)}"
47
+
48
+ # Append assistant message
49
+ history.append({"role": "assistant", "content": final_answer})
50
+
51
+ # Persist into the selected session
52
+ if selected_name:
53
+ for s in sessions:
54
+ if s["name"] == selected_name:
55
+ s["messages"] = history
56
+ break
57
+
58
+ return history, history, sessions
59
+ '''
60
+
61
+ def ask(history, question, top_k, temperature, sessions, selected_name):
62
+ history = history or []
63
+ sessions = sessions or []
64
+ selected_name = selected_name or (sessions[-1]["name"] if sessions else None)
65
+
66
+ if not question or not question.strip():
67
+ history.append({"role": "assistant", "content": "⚠️ Please enter a question."})
68
+ if selected_name:
69
+ for s in sessions:
70
+ if s["name"] == selected_name:
71
+ s["messages"] = history
72
+ break
73
+ return history, history, sessions
74
+
75
+ # Append user message to visible chat
76
+ history.append({"role": "user", "content": question})
77
+
78
+ # --- NEW: gather full session conversation for context ---
79
+ if selected_name:
80
+ for s in sessions:
81
+ if s["name"] == selected_name:
82
+ session_messages = s.get("messages", [])
83
+ # include current question
84
+ conversation = session_messages + [{"role": "user", "content": question}]
85
+ break
86
+ else:
87
+ conversation = history.copy()
88
+
89
+ # Call the agent (NOW conversation-aware)
90
+ try:
91
+ final_answer = run_agent(
92
+ user_q=question,
93
+ mcp_client=client,
94
+ available_iits=SUPPORTED_IITS,
95
+ available_branches=SUPPORTED_BRANCHES,
96
+ years=YEARS,
97
+ conversation=conversation, # <-- PASS HISTORY
98
+ top_k=int(top_k),
99
+ temperature=float(temperature),
100
+ )
101
+ except Exception as e:
102
+ final_answer = f"❌ Error while processing your request: {str(e)}"
103
+
104
+ # Append assistant reply and persist to session
105
+ history.append({"role": "assistant", "content": final_answer})
106
+ if selected_name:
107
+ for s in sessions:
108
+ if s["name"] == selected_name:
109
+ s["messages"] = history
110
+ break
111
+
112
+ return history, history, sessions
113
+
114
+ def clear_chat():
115
+ return [], []
116
+
117
+ # --- New chat: create session, clear history, select it in dropdown ---
118
+ def new_chat_fn(history, sessions, selected_name):
119
+ sessions = sessions or []
120
+ new_idx = len(sessions) + 1
121
+ new_name = f"Chat {new_idx}"
122
+ sessions.append({"name": new_name, "messages": []})
123
+ # Clear current chat view and select the new one
124
+ dropdown_update = gr.update(choices=[s["name"] for s in sessions], value=new_name)
125
+ return [], [], sessions, dropdown_update
126
+
127
+ # --- Load selected session into Chatbot ---
128
+ def load_session_fn(sessions, selected_name):
129
+ sessions = sessions or []
130
+ selected_name = selected_name or None
131
+ messages = []
132
+ if selected_name:
133
+ for s in sessions:
134
+ if s["name"] == selected_name:
135
+ messages = s.get("messages", [])
136
+ break
137
+ # Return messages -> Chatbot and State (keep them in sync)
138
+ return messages, messages
139
+
140
+ with gr.Blocks() as demo:
141
+ # (your CSS and layout remain unchanged)
142
+ gr.HTML("""
143
+ <style>
144
+ /* Hide footer */
145
+ footer {
146
+ display: none !important;
147
+ }
148
+ body, .gradio-container { background-color:#000 !important; color:#fff !important; }
149
+ .left-panel { background:#0d0d0d !important; padding:15px; border-right:1px solid #222; min-height:100vh; }
150
+ .left-panel * { color:#707070 !important; }
151
+
152
+ /* ------------------------------
153
+ FIX 1: Top-K & Temperature labels → black
154
+ ---------------------------------*/
155
+ #top-k-wrapper label,
156
+ #top-k-wrapper .gr-form-label,
157
+ #top-k-wrapper .title,
158
+ #top-k-wrapper span,
159
+ #top-k-wrapper .gr-slider-value,
160
+ #temperature-wrapper label,
161
+ #temperature-wrapper .gr-form-label,
162
+ #temperature-wrapper .title,
163
+ #temperature-wrapper span,
164
+ #temperature-wrapper .gr-slider-value {
165
+ color: #000 !important;
166
+ }
167
+
168
+ /* ------------------------------
169
+ FIX 2: Top-K & Temp reset (↺) icon → black
170
+ ---------------------------------*/
171
+ #top-k-wrapper button[aria-label="reset"] *,
172
+ #temperature-wrapper button[aria-label="reset"] * {
173
+ color:#000 !important;
174
+ fill:#000 !important;
175
+ stroke:#000 !important;
176
+ }
177
+
178
+ /* ------------------------------
179
+ FIX 3: Slider min/max text (1,10 and 0,1) → black
180
+ ---------------------------------*/
181
+ #top-k-wrapper .min-value,
182
+ #top-k-wrapper .max-value,
183
+ #temperature-wrapper .min-value,
184
+ #temperature-wrapper .max-value {
185
+ color:#000 !important;
186
+ }
187
+
188
+ /* ------------------------------
189
+ FIX 4: Dropdown selected text + dropdown menu list items → black
190
+ ---------------------------------*/
191
+ #session-select *,
192
+ #session-select .gr-dropdown,
193
+ #session-select .gr-dropdown * {
194
+ color:#000 !important;
195
+ }
196
+
197
+ /* Dropdown menu options */
198
+ .gradio-container .gr-dropdown ul li {
199
+ color:#000 !important;
200
+ }
201
+ /* Make Top-K & Temperature labels black */
202
+ #top-k-wrapper .label,
203
+ #top-k-wrapper .component-label,
204
+ #top-k-wrapper label,
205
+ #top-k-wrapper span.title,
206
+ #temperature-wrapper .label,
207
+ #temperature-wrapper .component-label,
208
+ #temperature-wrapper label,
209
+ #temperature-wrapper span.title {
210
+ color: #000 !important;
211
+ }
212
+
213
+ /* Make min/max numbers black */
214
+ #top-k-wrapper .min-value,
215
+ #top-k-wrapper .max-value,
216
+ #temperature-wrapper .min-value,
217
+ #temperature-wrapper .max-value {
218
+ color: #000 !important;
219
+ }
220
+
221
+ /* Make reset (↺) icon completely black */
222
+ #top-k-wrapper button[aria-label="reset"] *,
223
+ #temperature-wrapper button[aria-label="reset"] * {
224
+ color:#000 !important;
225
+ fill:#000 !important;
226
+ stroke:#000 !important;
227
+ }
228
+
229
+ /* Text inside the numeric input boxes */
230
+ #top-k-wrapper input[type="number"],
231
+ #temperature-wrapper input[type="number"] {
232
+ color:#000 !important;
233
+ background:#fff !important;
234
+ border:1px solid #777 !important;
235
+ }
236
+
237
+
238
+ /* Ensure note-bar and its link are visibly white */
239
+ #note-bar, #note-bar * { color: #fff !important; }
240
+ #note-bar a,
241
+ #note-bar a:link,
242
+ #note-bar a:visited,
243
+ #note-bar a:hover,
244
+ #note-bar a:active,
245
+ .prose #note-bar a,
246
+ .prose #note-bar a:link,
247
+ .prose #note-bar a:visited,
248
+ .prose #note-bar a:hover,
249
+ .prose #note-bar a:active {
250
+ color: #fff !important;
251
+ text-decoration: underline !important;
252
+ border-bottom: 1px solid rgba(255,255,255,0.6) !important;
253
+ }
254
+
255
+ .note-bar { font-size: 14px !important; margin-top: 8px !important; opacity: 0.95; }
256
+
257
+ .note-text {
258
+ color: white !important;
259
+ }
260
+
261
+ .note-text a {
262
+ color: #87CEFA !important; /* optional: link color (light blue) */
263
+ }
264
+
265
+ .note-text a:hover {
266
+ text-decoration: underline;
267
+ }
268
+ .note-text,
269
+ .note-text em {
270
+ color: white !important;
271
+ }
272
+
273
+ .note-text a {
274
+ color: #87CEFA !important; /* optional link color */
275
+ }
276
+
277
+
278
+
279
+
280
+ .sidebar-title { font-size:22px; margin-bottom:10px; color:#fff !important; }
281
+ .history-title { font-size:18px; margin-top:30px; margin-bottom:10px; color:#ccc !important; }
282
+ #top-k-wrapper label, #top-k-wrapper .gr-form-label, #top-k-wrapper .title { color:#707070 !important; }
283
+ #temperature-wrapper label, #temperature-wrapper .gr-form-label, #temperature-wrapper .title { color:#000 !important; }
284
+ #top-k-wrapper .gradio-row, #top-k-wrapper .gr-form,
285
+ #temperature-wrapper .gradio-row, #temperature-wrapper .gr-form { background: transparent !important; box-shadow:none !important; border:none !important; }
286
+ #top-k-wrapper input[type="number"], #temperature-wrapper input[type="number"] { color:#707070 !important; background:#fff !important; border:1px solid #999 !important; }
287
+ #question-box textarea { color:#000 !important; background:#fff !important; border:1px solid #999 !important; }
288
+ button[aria-label="reset"], button[aria-label="clear"] { color:#000 !important; fill:#000 !important; border-color:#000 !important; background:#fff !important; }
289
+ button[aria-label="reset"] svg, button[aria-label="clear"] svg { color:#000 !important; fill:#000 !important; stroke:#000 !important; }
290
+ #new-chat-btn { color:#000 !important; background:#fff !important; border:1px solid #000 !important; }
291
+ .chatbot { background:#111 !important; color:#707070 !important; }
292
+ </style>
293
+ """)
294
+
295
+ # --- States ---
296
+ history_messages = gr.State([]) # current chat messages
297
+ sessions_state = gr.State([]) # [{"name": "Chat 1", "messages": [...]}, ...]
298
+ selected_session = gr.State(None) # current dropdown selection
299
+
300
+ with gr.Row():
301
+ # LEFT
302
+ with gr.Column(scale=1, min_width=260, elem_classes="left-panel"):
303
+ gr.Markdown("<div class='sidebar-title'>Chatbot</div>")
304
+ new_chat_btn = gr.Button("➕ New Chat", elem_id="new-chat-btn")
305
+ gr.Markdown("<div class='history-title'>Chat History</div>")
306
+ session_select = gr.Dropdown(choices=[], label=None, interactive=True, elem_id="session-select")
307
+
308
+ with gr.Group(elem_id="top-k-wrapper"):
309
+ top_k = gr.Slider(1, 10, value=5, step=1, label="Top-K")
310
+
311
+ with gr.Group(elem_id="temperature-wrapper"):
312
+ temperature = gr.Slider(0.0, 1.0, value=0.1, step=0.1, label="Temperature")
313
+
314
+ # RIGHT
315
+ with gr.Column(scale=3):
316
+ chatbot = gr.Chatbot(height=520, elem_classes=["chatbot"])
317
+ question = gr.Textbox(placeholder="Ask...", lines=2, show_label=False, elem_id="question-box")
318
+ with gr.Row():
319
+ ask_btn = gr.Button("Ask")
320
+ clear_btn = gr.Button("Clear")
321
+
322
+ gr.Markdown(
323
+ """
324
+ <div class="note-text">
325
+ ⚠️ <em>This is an agent just providing some recommendations.</em>
326
+ For final decisions, please visit the official website:<br>
327
+ https://josaa.admissions.nic.in/applicant/seatmatrix/openingclosingrankarchieve.aspx
328
+ JoSAA Opening & Closing Ranks
329
+ </a>
330
+ </div>
331
+ """,
332
+ elem_classes="note-text"
333
+ )
334
+
335
+ # Events
336
+ ask_btn.click(
337
+ ask,
338
+ inputs=[history_messages, question, top_k, temperature, sessions_state, session_select],
339
+ outputs=[chatbot, history_messages, sessions_state]
340
+ )
341
+
342
+ question.submit(
343
+ ask,
344
+ inputs=[history_messages, question, top_k, temperature, sessions_state, session_select],
345
+ outputs=[chatbot, history_messages, sessions_state]
346
+ )
347
+
348
+ clear_btn.click(clear_chat, None, [chatbot, history_messages])
349
+
350
+ new_chat_btn.click(
351
+ new_chat_fn,
352
+ inputs=[history_messages, sessions_state, session_select],
353
+ outputs=[chatbot, history_messages, sessions_state, session_select]
354
+ )
355
+
356
+ session_select.change(
357
+ load_session_fn,
358
+ inputs=[sessions_state, session_select],
359
+ outputs=[chatbot, history_messages]
360
+ )
361
+
362
+ demo.launch()
363
+