IAMTFRMZA commited on
Commit
d051f5d
ยท
verified ยท
1 Parent(s): a86432c
Files changed (1) hide show
  1. app.py +46 -66
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import gradio as gr
2
  import os, time, re, json, base64, asyncio, threading, uuid, io
3
  import numpy as np
@@ -90,13 +91,9 @@ def clear_transcript_only(cid):
90
  connections[cid].transcript = ""
91
  return ""
92
 
93
- def clear_chat_only():
94
- return [], None, None
95
-
96
- # Assistant chat handler
97
- def handle_chat(user_input, history, thread_id, image_url):
98
  if not OPENAI_API_KEY or not ASSISTANT_ID:
99
- return "โŒ Missing secrets!", history, thread_id, image_url
100
 
101
  try:
102
  if thread_id is None:
@@ -116,108 +113,91 @@ def handle_chat(user_input, history, thread_id, image_url):
116
  for msg in reversed(msgs.data):
117
  if msg.role == "assistant":
118
  content = msg.content[0].text.value
119
- history.append((user_input, content))
120
  match = re.search(
121
  r'https://raw\.githubusercontent\.com/AndrewLORTech/surgical-pathology-manual/main/[\w\-/]*\.png',
122
  content
123
  )
124
- if match:
125
- image_url = match.group(0)
126
- break
127
 
128
- return "", history, thread_id, image_url
129
 
130
  except Exception as e:
131
- return f"โŒ {e}", history, thread_id, image_url
132
 
133
- # Feed transcript as assistant input
134
- def feed_transcript(transcript, history, thread_id, image_url, cid):
135
  if not transcript.strip():
136
- return gr.update(), history, thread_id, image_url
137
  if cid in connections:
138
  connections[cid].transcript = ""
139
- return handle_chat(transcript, history, thread_id, image_url)
140
-
141
- # Fallback for image display
142
- def update_image_display(image_url):
143
- if image_url and isinstance(image_url, str) and image_url.startswith("http"):
144
- return image_url
145
- return None
146
 
147
  # ============ Gradio UI ============
148
- with gr.Blocks(theme=gr.themes.Soft()) as app:
149
- gr.Markdown("# ๐Ÿ“„ Document AI Assistant")
150
 
 
151
  gr.HTML("""
152
  <style>
 
 
 
 
153
  .big-btn {
154
- font-size: 18px !important;
155
- padding: 14px 28px !important;
156
- border-radius: 8px !important;
157
- width: 100% !important;
158
- margin-top: 10px;
 
 
159
  }
160
  .voice-area {
161
- padding-top: 12px;
162
- border-top: 1px solid #444;
163
- margin-top: 12px;
164
  }
165
  </style>
166
  """)
167
 
168
- chat_state = gr.State([])
169
  thread_state = gr.State()
170
- image_state = gr.State()
171
  client_id = gr.State()
172
 
173
  with gr.Row(equal_height=True):
174
  with gr.Column(scale=1):
175
- image_display = gr.Image(label="๐Ÿ–ผ๏ธ Document", type="filepath", show_download_button=False)
176
-
177
- with gr.Column(scale=1.4):
178
- chat = gr.Chatbot(label="๐Ÿ’ฌ Chat", height=460)
179
-
180
- with gr.Row():
181
- user_prompt = gr.Textbox(placeholder="Ask your question...", show_label=False, scale=8)
182
- send_btn = gr.Button("Send", variant="primary", scale=2)
183
 
184
  with gr.Column(elem_classes="voice-area"):
185
- gr.Markdown("### ๐ŸŽ™๏ธ Voice Input")
186
-
187
- voice_input = gr.Audio(label="Tap to Record", streaming=True, type="numpy", show_label=True)
188
- voice_transcript = gr.Textbox(label="Transcript", lines=2, interactive=False)
189
 
190
- with gr.Row():
191
- voice_send_btn = gr.Button("๐ŸŸข Send Voice to Assistant", elem_classes="big-btn")
192
- clear_transcript_btn = gr.Button("๐Ÿงน Clear Transcript", elem_classes="big-btn")
193
 
194
- with gr.Row():
195
- clear_chat_btn = gr.Button("๐Ÿ—‘๏ธ Clear Chat", elem_classes="big-btn")
 
196
 
197
  # Bindings
198
- send_btn.click(fn=handle_chat,
199
- inputs=[user_prompt, chat_state, thread_state, image_state],
200
- outputs=[user_prompt, chat, thread_state, image_state])
201
 
202
  voice_input.stream(fn=send_audio,
203
  inputs=[voice_input, client_id],
204
- outputs=voice_transcript,
205
  stream_every=0.5)
206
 
207
- voice_send_btn.click(fn=feed_transcript,
208
- inputs=[voice_transcript, chat_state, thread_state, image_state, client_id],
209
- outputs=[user_prompt, chat, thread_state, image_state])
210
 
211
  clear_transcript_btn.click(fn=clear_transcript_only,
212
  inputs=[client_id],
213
- outputs=voice_transcript)
214
-
215
- clear_chat_btn.click(fn=clear_chat_only,
216
- outputs=[chat, thread_state, image_state])
217
-
218
- image_state.change(fn=update_image_display,
219
- inputs=image_state,
220
- outputs=image_display)
221
 
222
  app.load(fn=create_ws, outputs=[client_id])
223
 
 
1
+ # app.py
2
  import gradio as gr
3
  import os, time, re, json, base64, asyncio, threading, uuid, io
4
  import numpy as np
 
91
  connections[cid].transcript = ""
92
  return ""
93
 
94
+ def handle_chat(user_input, thread_id):
 
 
 
 
95
  if not OPENAI_API_KEY or not ASSISTANT_ID:
96
+ return "โŒ Missing secrets!", thread_id, "", None
97
 
98
  try:
99
  if thread_id is None:
 
113
  for msg in reversed(msgs.data):
114
  if msg.role == "assistant":
115
  content = msg.content[0].text.value
 
116
  match = re.search(
117
  r'https://raw\.githubusercontent\.com/AndrewLORTech/surgical-pathology-manual/main/[\w\-/]*\.png',
118
  content
119
  )
120
+ image_url = match.group(0) if match else None
121
+ response = f"### โ“ Question\n{user_input}\n\n---\n\n### ๐Ÿ’ก Answer\n{content}"
122
+ return response, thread_id, image_url
123
 
124
+ return "No response from assistant.", thread_id, None
125
 
126
  except Exception as e:
127
+ return f"โŒ {e}", thread_id, None
128
 
129
+ def feed_transcript(transcript, thread_id, cid):
 
130
  if not transcript.strip():
131
+ return gr.update(), thread_id, None
132
  if cid in connections:
133
  connections[cid].transcript = ""
134
+ return handle_chat(transcript, thread_id,)
 
 
 
 
 
 
135
 
136
  # ============ Gradio UI ============
 
 
137
 
138
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
139
  gr.HTML("""
140
  <style>
141
+ body {
142
+ font-family: 'Inter', sans-serif;
143
+ background-color: #f9f9fb;
144
+ }
145
  .big-btn {
146
+ font-size: 16px;
147
+ padding: 12px 20px;
148
+ border-radius: 12px;
149
+ width: 100%;
150
+ background-color: #4f46e5;
151
+ color: white;
152
+ border: none;
153
  }
154
  .voice-area {
155
+ padding-top: 16px;
156
+ margin-top: 16px;
157
+ border-top: 1px solid #ddd;
158
  }
159
  </style>
160
  """)
161
 
 
162
  thread_state = gr.State()
 
163
  client_id = gr.State()
164
 
165
  with gr.Row(equal_height=True):
166
  with gr.Column(scale=1):
167
+ user_input = gr.Textbox(placeholder="Ask your question...", label="Prompt")
168
+ submit_btn = gr.Button("๐Ÿš€ Ask", variant="primary")
169
+ result_md = gr.Markdown()
170
+ image_output = gr.Image(label="๐Ÿ–ผ๏ธ Preview", type="filepath", show_download_button=False)
 
 
 
 
171
 
172
  with gr.Column(elem_classes="voice-area"):
173
+ gr.Markdown("๐ŸŽ™๏ธ Real-time Voice Input")
174
+ voice_input = gr.Audio(label="Tap to Speak", streaming=True, type="numpy")
175
+ transcript_box = gr.Textbox(label="Transcript", lines=2, interactive=False)
 
176
 
177
+ voice_submit_btn = gr.Button("Send Voice", elem_classes="big-btn")
178
+ clear_transcript_btn = gr.Button("๐Ÿงน Clear Transcript", elem_classes="big-btn")
 
179
 
180
+ with gr.Column(scale=1.4):
181
+ gr.Markdown("### โฑ๏ธ Assistant Response")
182
+ result_area = gr.Markdown()
183
 
184
  # Bindings
185
+ submit_btn.click(fn=handle_chat,
186
+ inputs=[user_input, thread_state],
187
+ outputs=[result_area, thread_state, image_output])
188
 
189
  voice_input.stream(fn=send_audio,
190
  inputs=[voice_input, client_id],
191
+ outputs=transcript_box,
192
  stream_every=0.5)
193
 
194
+ voice_submit_btn.click(fn=feed_transcript,
195
+ inputs=[transcript_box, thread_state, client_id],
196
+ outputs=[result_area, thread_state, image_output])
197
 
198
  clear_transcript_btn.click(fn=clear_transcript_only,
199
  inputs=[client_id],
200
+ outputs=transcript_box)
 
 
 
 
 
 
 
201
 
202
  app.load(fn=create_ws, outputs=[client_id])
203