IAMTFRMZA commited on
Commit
619c0c2
·
verified ·
1 Parent(s): f6db629

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -120
app.py CHANGED
@@ -55,13 +55,12 @@ for key in ["messages", "thread_id", "image_urls", "pending_prompt", "image_url"
55
  st.session_state[key] = [] if key.endswith("s") else None if "url" in key else False
56
 
57
  # ------------------ Tabs ------------------
58
- show_tab2 = False # Toggle this to True to activate Tab 2
59
-
60
  if show_tab2:
61
  tab1, tab2 = st.tabs(["💬 Chat Assistant", "📷 Visual Reference Search"])
62
  else:
63
- tab1, = st.tabs(["💬 Chat Assistant"])
64
-
65
 
66
  # ------------------ Tab 1: Chat Assistant ------------------
67
  with tab1:
@@ -166,121 +165,139 @@ with tab1:
166
 
167
 
168
  # ------------------ Tab 2: Visual Reference Search ------------------
169
- if show_tab2:
170
- with tab2:
171
- ASSISTANT_ID = "asst_9v09zgizdcuuhNdcFQpRo9RO"
172
-
173
- if "image_thread_id" not in st.session_state:
174
- st.session_state.image_thread_id = None
175
- if "image_response" not in st.session_state:
176
- st.session_state.image_response = None
177
- if "image_results" not in st.session_state:
178
- st.session_state.image_results = []
179
- if "image_lightbox" not in st.session_state:
180
- st.session_state.image_lightbox = None
181
 
182
- image_input = st.chat_input("Ask for histology visual references (e.g. ovary histology, mitosis)")
183
- if image_input:
184
- st.session_state.image_response = None
185
- st.session_state.image_results = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  st.session_state.image_lightbox = None
187
-
188
- try:
189
- if st.session_state.image_thread_id is None:
190
- thread = client.beta.threads.create()
191
- st.session_state.image_thread_id = thread.id
192
-
193
- client.beta.threads.messages.create(
194
- thread_id=st.session_state.image_thread_id,
195
- role="user",
196
- content=image_input
197
- )
198
-
199
- run = client.beta.threads.runs.create(
200
- thread_id=st.session_state.image_thread_id,
201
- assistant_id=ASSISTANT_ID
202
- )
203
-
204
- with st.spinner("🔬 Searching for histology references..."):
205
- while True:
206
- run_status = client.beta.threads.runs.retrieve(
207
- thread_id=st.session_state.image_thread_id,
208
- run_id=run.id
209
- )
210
- if run_status.status in ("completed", "failed", "cancelled"):
211
- break
212
- time.sleep(1)
213
-
214
- if run_status.status == "completed":
215
- messages = client.beta.threads.messages.list(thread_id=st.session_state.image_thread_id)
216
- for msg in reversed(messages.data):
217
- if msg.role == "assistant":
218
- response_text = msg.content[0].text.value
219
- st.session_state.image_response = response_text
220
-
221
- # ✅ Extract Image URLs from assistant markdown
222
- lines = response_text.splitlines()
223
- image_urls = []
224
- expecting_url = False
225
-
226
- for line in lines:
227
- line_clean = line.strip().replace("**", "")
228
- if "Image URL:" in line_clean:
229
- parts = line_clean.split("Image URL:")
230
- if len(parts) > 1 and parts[1].strip().startswith("http"):
231
- image_urls.append(parts[1].strip())
232
- else:
233
- expecting_url = True
234
- elif expecting_url:
235
- if line_clean.startswith("http"):
236
- image_urls.append(line_clean)
237
- expecting_url = False
238
-
239
- st.session_state.image_results = [{"image": url} for url in image_urls]
240
-
241
- if image_urls and not st.session_state.image_lightbox:
242
- st.session_state.image_lightbox = image_urls[0]
243
- break
244
- except Exception as e:
245
- st.error(f"❌ Visual Assistant Error: {e}")
246
-
247
- text_col, image_col = st.columns([2, 1])
248
-
249
- with text_col:
250
- if st.session_state.image_response:
251
- st.markdown("### 🧠 Assistant Response")
252
- st.markdown(st.session_state.image_response, unsafe_allow_html=True)
253
-
254
- with image_col:
255
- if st.session_state.image_results:
256
- st.markdown("### 🖼️ Image Preview(s)")
257
- for i, item in enumerate(st.session_state.image_results):
258
- image_url = item.get("image")
259
- if image_url:
260
- try:
261
- r = requests.get(image_url, timeout=10)
262
- r.raise_for_status()
263
- img = Image.open(BytesIO(r.content))
264
- st.image(img, caption=image_url.split("/")[-1], use_container_width=True)
265
- if st.button("🔍 View Full Image", key=f"full_img_{i}"):
266
- st.session_state.image_lightbox = image_url
267
- except Exception as e:
268
- st.warning(f"⚠️ Could not load: {image_url}")
269
- st.error(f"{e}")
270
- else:
271
- st.info("ℹ️ No image references found yet.")
272
-
273
- if st.session_state.image_lightbox:
274
- st.markdown("### 🔬 Full Image View")
275
- try:
276
- img_url = st.session_state.image_lightbox
277
- r = requests.get(img_url, timeout=10)
278
- r.raise_for_status()
279
- full_img = Image.open(BytesIO(r.content))
280
- st.image(full_img, caption=img_url.split("/")[-1], use_container_width=True)
281
- except Exception as e:
282
- st.warning("⚠️ Could not load full image.")
283
- st.error(str(e))
284
- if st.button("❌ Close Preview"):
285
- st.session_state.image_lightbox = None
286
- st.rerun()
 
55
  st.session_state[key] = [] if key.endswith("s") else None if "url" in key else False
56
 
57
  # ------------------ Tabs ------------------
58
+ show_tab2 = True # Set to True to activate visual tab
 
59
  if show_tab2:
60
  tab1, tab2 = st.tabs(["💬 Chat Assistant", "📷 Visual Reference Search"])
61
  else:
62
+ tab1 = st.tabs(["💬 Chat Assistant"])[0]
63
+ tab2 = None
64
 
65
  # ------------------ Tab 1: Chat Assistant ------------------
66
  with tab1:
 
165
 
166
 
167
  # ------------------ Tab 2: Visual Reference Search ------------------
168
+ import urllib.parse
169
+ import requests
170
+ from PIL import Image
171
+ from io import BytesIO
 
 
 
 
 
 
 
 
172
 
173
+ with tab2:
174
+ ASSISTANT_ID = "asst_9v09zgizdcuuhNdcFQpRo9RO"
175
+
176
+ if "image_thread_id" not in st.session_state:
177
+ st.session_state.image_thread_id = None
178
+ if "image_response" not in st.session_state:
179
+ st.session_state.image_response = None
180
+ if "image_results" not in st.session_state:
181
+ st.session_state.image_results = []
182
+ if "image_lightbox" not in st.session_state:
183
+ st.session_state.image_lightbox = None
184
+
185
+ image_input = st.chat_input("Ask for histology visual references (e.g. ovary histology, mitosis)")
186
+ if image_input:
187
+ st.session_state.image_response = None
188
+ st.session_state.image_results = []
189
+ st.session_state.image_lightbox = None
190
+
191
+ try:
192
+ if st.session_state.image_thread_id is None:
193
+ thread = client.beta.threads.create()
194
+ st.session_state.image_thread_id = thread.id
195
+
196
+ client.beta.threads.messages.create(
197
+ thread_id=st.session_state.image_thread_id,
198
+ role="user",
199
+ content=image_input
200
+ )
201
+
202
+ run = client.beta.threads.runs.create(
203
+ thread_id=st.session_state.image_thread_id,
204
+ assistant_id=ASSISTANT_ID
205
+ )
206
+
207
+ with st.spinner("🔬 Searching for histology references..."):
208
+ while True:
209
+ run_status = client.beta.threads.runs.retrieve(
210
+ thread_id=st.session_state.image_thread_id,
211
+ run_id=run.id
212
+ )
213
+ if run_status.status in ("completed", "failed", "cancelled"):
214
+ break
215
+ time.sleep(1)
216
+
217
+ if run_status.status == "completed":
218
+ messages = client.beta.threads.messages.list(thread_id=st.session_state.image_thread_id)
219
+ for msg in reversed(messages.data):
220
+ if msg.role == "assistant":
221
+ response_text = msg.content[0].text.value
222
+ st.session_state.image_response = response_text
223
+
224
+ # Extract and decode image URLs
225
+ lines = response_text.splitlines()
226
+ image_urls = []
227
+ expecting_url = False
228
+
229
+ for line in lines:
230
+ line_clean = line.strip().replace("**", "")
231
+ if "Image URL:" in line_clean:
232
+ parts = line_clean.split("Image URL:")
233
+ if len(parts) > 1 and parts[1].strip().startswith("http"):
234
+ image_urls.append(urllib.parse.unquote(parts[1].strip()))
235
+ else:
236
+ expecting_url = True
237
+ elif expecting_url:
238
+ if line_clean.startswith("http"):
239
+ image_urls.append(urllib.parse.unquote(line_clean))
240
+ expecting_url = False
241
+
242
+ st.session_state.image_results = [{"image": url} for url in image_urls]
243
+
244
+ if image_urls and not st.session_state.image_lightbox:
245
+ st.session_state.image_lightbox = image_urls[0]
246
+ break
247
+ except Exception as e:
248
+ st.error(f"❌ Visual Assistant Error: {e}")
249
+
250
+ if st.session_state.image_results and st.session_state.image_response:
251
+ st.subheader("🖼️ Image Preview(s)")
252
+
253
+ # Split the assistant response into metadata cards
254
+ cards = []
255
+ blocks = st.session_state.image_response.split("### 🖼️ ")
256
+ for block in blocks:
257
+ if not block.strip():
258
+ continue
259
+ lines = block.strip().splitlines()
260
+ title = lines[0].strip()
261
+ meta = "\n".join(lines[1:])
262
+ cards.append((title, meta))
263
+
264
+ cols = st.columns(4)
265
+ for i, ((title, meta), item) in enumerate(zip(cards, st.session_state.image_results)):
266
+ image_url = item.get("image")
267
+ with cols[i % 4]:
268
+ with st.container():
269
+ # Remove Image Filename and Image URL lines from display
270
+ meta_clean = "\n".join(
271
+ line for line in meta.splitlines()
272
+ if all(x not in line.lower() for x in ["image filename", "image url"])
273
+ )
274
+
275
+ st.markdown(f"**🔬 {title}**")
276
+ st.caption(meta_clean)
277
+ try:
278
+ r = requests.get(image_url, timeout=10)
279
+ r.raise_for_status()
280
+ img = Image.open(BytesIO(r.content))
281
+ st.image(img, caption=image_url.split("/")[-1], use_container_width=True)
282
+ if st.button("🔍 Zoom", key=f"zoom_{i}"):
283
+ st.session_state.image_lightbox = image_url
284
+ except Exception as e:
285
+ st.warning("⚠️ Could not load image.")
286
+ st.error(str(e))
287
+ else:
288
+ st.info("ℹ️ No image references found yet.")
289
+
290
+ if st.session_state.image_lightbox:
291
+ st.markdown("### 🔬 Full Image View")
292
+ try:
293
+ img_url = urllib.parse.unquote(st.session_state.image_lightbox)
294
+ r = requests.get(img_url, timeout=10)
295
+ r.raise_for_status()
296
+ full_img = Image.open(BytesIO(r.content))
297
+ st.image(full_img, caption=img_url.split("/")[-1], use_container_width=True)
298
+ except Exception as e:
299
+ st.warning("⚠️ Could not load full image.")
300
+ st.error(str(e))
301
+ if st.button("❌ Close Preview"):
302
  st.session_state.image_lightbox = None
303
+ st.rerun()