awacke1 commited on
Commit
15e14c8
·
verified ·
1 Parent(s): 6300d46

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -91
app.py CHANGED
@@ -15,20 +15,17 @@ from urllib.parse import quote
15
  import streamlit as st
16
  import streamlit.components.v1 as components
17
 
18
- # For demonstration, we'll import from huggingface_hub
19
- # (You can omit if you're not using HF or adapt your own client)
20
  from huggingface_hub import InferenceClient
21
 
 
22
  # ----------------------------
23
  # Placeholder data structures
24
  # ----------------------------
25
-
26
- # Example placeholders for prompt prefixes
27
  PromptPrefix = "AI-Search: "
28
  PromptPrefix2 = "AI-Refine: "
29
  PromptPrefix3 = "AI-JS: "
30
 
31
- # Minimal example of a roleplaying glossary
32
  roleplaying_glossary = {
33
  "Core Rulebooks": {
34
  "Dungeons and Dragons": ["Player's Handbook", "Dungeon Master's Guide", "Monster Manual"],
@@ -39,13 +36,15 @@ roleplaying_glossary = {
39
  }
40
  }
41
 
42
- # Minimal example of a transhuman glossary
43
  transhuman_glossary = {
44
  "Neural Interfaces": ["Cortex Jack", "Mind-Machine Fusion"],
45
  "Cybernetics": ["Robotic Limbs", "Augmented Eyes"],
46
  }
47
 
48
- # Just to demonstrate how your "search_arxiv" or "SpeechSynthesis" etc. might be placeholders
 
 
 
49
  def process_text(text):
50
  st.write(f"process_text called with: {text}")
51
 
@@ -67,7 +66,8 @@ def process_video(video_file, seconds_per_frame):
67
  def search_glossary(content):
68
  st.write(f"search_glossary called with: {content}")
69
 
70
- # If you have HF Inference endpoint, set them here, else placeholders
 
71
  API_URL = "https://huggingface-inference-endpoint-placeholder"
72
  API_KEY = "hf_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
73
 
@@ -82,8 +82,7 @@ def InferenceLLM(prompt):
82
  @st.cache_resource
83
  def display_glossary_entity(k):
84
  """
85
- Example of how you'd create multiple links for a glossary entity.
86
- This was in your original snippet. We'll keep it short.
87
  """
88
  search_urls = {
89
  "🚀🌌ArXiv": lambda k: f"/?q={quote(k)}",
@@ -151,8 +150,7 @@ def get_zip_download_link(zip_file):
151
  with open(zip_file, 'rb') as f:
152
  data = f.read()
153
  b64 = base64.b64encode(data).decode()
154
- href = f'<a href="data:application/zip;base64,{b64}" download="{zip_file}">Download All</a>'
155
- return href
156
 
157
  def get_table_download_link(file_path):
158
  """
@@ -174,8 +172,7 @@ def get_table_download_link(file_path):
174
  '.wav': 'audio/wav'
175
  }
176
  mime_type = mime_map.get(ext, 'application/octet-stream')
177
- href = f'<a href="data:{mime_type};base64,{b64}" target="_blank" download="{file_name}">{file_name}</a>'
178
- return href
179
  except:
180
  return ''
181
 
@@ -193,7 +190,7 @@ def compare_and_delete_files(files):
193
  for file in files:
194
  size = os.path.getsize(file)
195
  file_sizes.setdefault(size, []).append(file)
196
- # Remove all but the latest file for each size
197
  for size, paths in file_sizes.items():
198
  if len(paths) > 1:
199
  latest_file = max(paths, key=os.path.getmtime)
@@ -201,24 +198,24 @@ def compare_and_delete_files(files):
201
  if file != latest_file:
202
  os.remove(file)
203
  st.success(f"Deleted {file} as a duplicate.")
204
- st.rerun()
205
 
206
  def FileSidebar():
207
  """
208
  Renders the file sidebar with all the open/view/run/delete logic.
209
  """
210
  all_files = glob.glob("*.md")
211
- # Example logic filtering filenames
212
- all_files = [file for file in all_files if len(os.path.splitext(file)[0]) >= 5]
213
  all_files.sort(key=lambda x: (os.path.splitext(x)[1], x), reverse=True)
214
 
215
- # Buttons for "Delete All" and "Download"
216
  Files1, Files2 = st.sidebar.columns(2)
217
  with Files1:
218
  if st.button("🗑 Delete All"):
219
  for file in all_files:
220
  os.remove(file)
221
- st.rerun()
222
  with Files2:
223
  if st.button("⬇️ Download"):
224
  zip_file = create_zip_of_files(all_files)
@@ -228,11 +225,9 @@ def FileSidebar():
228
  file_name = ''
229
  next_action = ''
230
 
231
- # Each file row
232
  for file in all_files:
233
  col1, col2, col3, col4, col5 = st.sidebar.columns([1,6,1,1,1])
234
  with col1:
235
- # Show an emoji button to do "md"
236
  if st.button("🌐", key="md_"+file):
237
  file_contents = load_file(file)
238
  file_name = file
@@ -258,12 +253,9 @@ def FileSidebar():
258
  with col5:
259
  if st.button("🗑", key="delete_"+file):
260
  os.remove(file)
261
- file_name = file
262
- st.rerun()
263
- next_action = 'delete'
264
- st.session_state['next_action'] = next_action
265
 
266
- # Duplicate detection
267
  file_sizes = [get_file_size(file) for file in all_files]
268
  previous_size = None
269
  st.sidebar.title("File Operations")
@@ -277,28 +269,26 @@ def FileSidebar():
277
  file_content = f.read()
278
  st.code(file_content, language="markdown")
279
  except UnicodeDecodeError:
280
- st.error("Failed to decode the file with UTF-8.")
281
  if st.button("Delete", key=f"delete3_{file}"):
282
  os.remove(file)
283
- st.rerun()
284
  previous_size = size
285
 
286
- # If we have loaded something
287
- if len(file_contents) > 0:
288
  if next_action == 'open':
289
  open1, open2 = st.columns([0.8, 0.2])
290
  with open1:
291
- file_name_input = st.text_input('File Name:', file_name, key='file_name_input', on_change=None)
292
  file_content_area = st.text_area('File Contents:', file_contents, height=300, key='file_content_area')
293
 
294
- # Minimal “Save” stubs
295
  if st.button('💾 Save File'):
296
  with open(file_name_input, 'w', encoding='utf-8') as f:
297
  f.write(file_content_area)
298
  st.markdown(f'Saved {file_name_input} successfully.')
299
 
300
  elif next_action == 'search':
301
- # Example usage
302
  file_content_area = st.text_area("File Contents:", file_contents, height=500)
303
  user_prompt = PromptPrefix2 + file_contents
304
  st.markdown(user_prompt)
@@ -312,9 +302,9 @@ def FileSidebar():
312
  st.write("Running GPT logic placeholder...")
313
 
314
 
315
- # ---------------------------
316
  # Basic Scoring / Glossaries
317
- # ---------------------------
318
  score_dir = "scores"
319
  os.makedirs(score_dir, exist_ok=True)
320
 
@@ -354,7 +344,6 @@ def display_buttons_with_scores(num_columns_text):
354
  "Kindred of the East": "🌅",
355
  "Changeling": "🍃",
356
  }
357
-
358
  topic_emojis = {
359
  "Core Rulebooks": "📚",
360
  "Maps & Settings": "🗺️",
@@ -382,19 +371,18 @@ def display_buttons_with_scores(num_columns_text):
382
  st.markdown(f"Scored **{category} - {game} - {term}** -> {newscore}")
383
 
384
 
385
- # --------------------
386
  # Image & Video Grids
387
- # --------------------
388
  def display_images_and_wikipedia_summaries(num_columns=4):
389
  """
390
- Display all .png images in the current directory in a grid, referencing the name as a 'keyword'.
391
  """
392
  image_files = [f for f in os.listdir('.') if f.endswith('.png')]
393
  if not image_files:
394
  st.write("No PNG images found in the current directory.")
395
  return
396
 
397
- # Sort by length of filename, just as an example
398
  image_files_sorted = sorted(image_files, key=lambda x: len(x.split('.')[0]))
399
  cols = st.columns(num_columns)
400
  col_index = 0
@@ -408,7 +396,7 @@ def display_images_and_wikipedia_summaries(num_columns=4):
408
  display_glossary_entity(k)
409
  # Provide a text input for user interactions
410
  image_text_input = st.text_input(f"Prompt for {image_file}", key=f"image_prompt_{image_file}")
411
- if len(image_text_input) > 0:
412
  response = process_image(image_file, image_text_input)
413
  st.markdown(response)
414
  except:
@@ -417,7 +405,7 @@ def display_images_and_wikipedia_summaries(num_columns=4):
417
 
418
  def display_videos_and_links(num_columns=4):
419
  """
420
- Displays all .mp4 or .webm videos found in the current directory in a grid.
421
  """
422
  video_files = [f for f in os.listdir('.') if f.endswith(('.mp4', '.webm'))]
423
  if not video_files:
@@ -433,11 +421,10 @@ def display_videos_and_links(num_columns=4):
433
  k = video_file.split('.')[0]
434
  st.video(video_file, format='video/mp4', start_time=0)
435
  display_glossary_entity(k)
436
- # Provide a text input
437
  video_text_input = st.text_input(f"Video Prompt for {video_file}", key=f"video_prompt_{video_file}")
438
  if video_text_input:
439
  try:
440
- # Hard-coded example
441
  seconds_per_frame = 10
442
  process_video(video_file, seconds_per_frame)
443
  except ValueError:
@@ -445,19 +432,25 @@ def display_videos_and_links(num_columns=4):
445
  col_index += 1
446
 
447
 
448
- # -------------------------------------
449
- # Query Param Helpers from your snippet
450
- # -------------------------------------
451
- def get_all_query_params(key):
452
- return st.query_params().get(key, [])
453
-
454
  def clear_query_params():
455
- st.query_params()
 
 
 
 
 
 
 
 
 
 
456
 
457
  def display_content_or_image(query):
458
  """
459
- If a query matches something in transhuman_glossary or
460
- a local image, show it. Otherwise warn no match.
461
  """
462
  for category, term_list in transhuman_glossary.items():
463
  for term in term_list:
@@ -478,8 +471,7 @@ def display_content_or_image(query):
478
  # ------------------------------------
479
  def generate_mermaid_html(mermaid_code: str) -> str:
480
  """
481
- Returns HTML embedding a Mermaid diagram. We embed the code
482
- in <div class="mermaid"> and center it with CSS.
483
  """
484
  return f"""
485
  <html>
@@ -492,7 +484,6 @@ def generate_mermaid_html(mermaid_code: str) -> str:
492
  margin: 20px auto;
493
  }}
494
  .mermaid {{
495
- /* Let the diagram scale or otherwise style as you wish */
496
  max-width: 800px;
497
  }}
498
  </style>
@@ -510,8 +501,7 @@ def generate_mermaid_html(mermaid_code: str) -> str:
510
 
511
  def append_model_param(url: str, model_selected: bool) -> str:
512
  """
513
- If 'Model' checkbox is selected, we append '&model=1' or '?model=1' to the URL.
514
- We'll handle whether the URL already has a '?' or not.
515
  """
516
  if not model_selected:
517
  return url
@@ -519,10 +509,8 @@ def append_model_param(url: str, model_selected: bool) -> str:
519
  return f"{url}{delimiter}model=1"
520
 
521
 
522
- # Default Mermaid diagram with "click" lines
523
  DEFAULT_MERMAID = """
524
  flowchart LR
525
- %% Notice we have "click LLM ..." lines:
526
  U((User 😎)) -- "Talk 🗣️" --> LLM[LLM Agent 🤖\\nExtract Info]
527
  click U "/?q=User%20😎" _self
528
  click LLM "/?q=LLM%20Agent%20Extract%20Info" _self
@@ -537,28 +525,62 @@ flowchart LR
537
  click KG "/?q=Knowledge%20Graph%20Ontology+GAR+RAG" _self
538
  """
539
 
 
540
  # ---------------------------
541
- # Streamlit Main App
542
  # ---------------------------
543
  def main():
544
  st.set_page_config(page_title="Mermaid + Clickable Links Demo", layout="wide")
545
 
546
- # 1) Parse query strings on page load
547
- query_params = st.experimental_get_query_params() # original usage
548
- current_q = query_params.get("q", [""])[0] # If present, first string
549
- current_r = query_params.get("r", [""])[0]
550
-
551
- # 2) Let user pick if they want to add the "model=1" param to clickable links
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
  st.sidebar.write("## Diagram Link Settings")
553
  model_selected = st.sidebar.checkbox("Append ?model=1 to each link?")
554
 
555
- # 3) Generate a dynamic Mermaid code, appending model param if user wants
556
  base_diagram = DEFAULT_MERMAID
557
  lines = base_diagram.strip().split("\n")
558
  new_lines = []
559
  for line in lines:
560
  if "click " in line and '"/?' in line:
561
- # e.g. click LLM "/?q=LLM%20Agent" _self
562
  parts = re.split(r'click\s+\S+\s+"([^"]+)"\s+("_self")', line)
563
  if len(parts) == 4:
564
  url = parts[1]
@@ -569,22 +591,18 @@ def main():
569
  new_lines.append(line)
570
  else:
571
  new_lines.append(line)
572
-
573
  mermaid_code = "\n".join(new_lines)
574
 
575
- # 4) Render the top-centered Mermaid diagram
 
 
576
  st.title("Top-Centered Mermaid Diagram with Clickable Links 🏺")
577
  diagram_html = generate_mermaid_html(mermaid_code)
578
  components.html(diagram_html, height=400, scrolling=True)
579
 
580
- # 5) Show inbound ?q / ?r
581
- if current_q:
582
- st.markdown(f"**Detected Query**: `?q={current_q}`")
583
- display_content_or_image(current_q)
584
- if current_r:
585
- st.markdown(f"**Detected Relationship**: `?r={current_r}`")
586
-
587
- # 6) Editor Columns: Markdown & Mermaid
588
  left_col, right_col = st.columns(2)
589
 
590
  # --- Left: Markdown Editor
@@ -592,7 +610,6 @@ def main():
592
  st.subheader("Markdown Side 📝")
593
  if "markdown_text" not in st.session_state:
594
  st.session_state["markdown_text"] = "## Hello!\nType some *Markdown* here.\n"
595
- # Text area
596
  markdown_text = st.text_area(
597
  "Edit Markdown:",
598
  value=st.session_state["markdown_text"],
@@ -600,7 +617,6 @@ def main():
600
  )
601
  st.session_state["markdown_text"] = markdown_text
602
 
603
- # Button row
604
  colA, colB = st.columns(2)
605
  with colA:
606
  if st.button("🔄 Refresh Markdown"):
@@ -608,9 +624,8 @@ def main():
608
  with colB:
609
  if st.button("❌ Clear Markdown"):
610
  st.session_state["markdown_text"] = ""
611
- st.experimental_rerun()
612
 
613
- # Show the rendered Markdown below
614
  st.markdown("---")
615
  st.markdown("**Preview:**")
616
  st.markdown(markdown_text)
@@ -628,23 +643,24 @@ def main():
628
  height=300
629
  )
630
 
631
- # A small button bar
632
  colC, colD = st.columns(2)
633
  with colC:
634
  if st.button("🎨 Refresh Diagram"):
635
  st.session_state["current_mermaid"] = mermaid_input
636
  st.write("**Mermaid** diagram refreshed! 🌈")
637
- st.experimental_rerun()
638
  with colD:
639
  if st.button("❌ Clear Mermaid"):
640
  st.session_state["current_mermaid"] = ""
641
- st.experimental_rerun()
642
 
643
  st.markdown("---")
644
  st.markdown("**Mermaid Source:**")
645
  st.code(mermaid_input, language="python", line_numbers=True)
646
 
647
- # 7) Sliders & image/video galleries
 
 
648
  st.markdown("---")
649
  st.header("Media Galleries")
650
 
@@ -654,7 +670,9 @@ def main():
654
  num_columns_video = st.slider("Choose Number of Video Columns", 1, 15, 5, key="num_columns_video")
655
  display_videos_and_links(num_columns_video)
656
 
657
- # 8) Optional "Extended" UI
 
 
658
  showExtendedTextInterface = False
659
  if showExtendedTextInterface:
660
  display_glossary_grid(roleplaying_glossary)
@@ -662,10 +680,14 @@ def main():
662
  display_buttons_with_scores(num_columns_text)
663
  st.markdown("Extended text interface is on...")
664
 
665
- # 9) File Sidebar
 
 
666
  FileSidebar()
667
 
668
- # 10) Random Title at bottom
 
 
669
  titles = [
670
  "🧠🎭 Semantic Symphonies & Episodic Encores",
671
  "🌌🎼 AI Rhythms of Memory Lane",
 
15
  import streamlit as st
16
  import streamlit.components.v1 as components
17
 
18
+ # (Optional) If you use huggingface_hub:
 
19
  from huggingface_hub import InferenceClient
20
 
21
+
22
  # ----------------------------
23
  # Placeholder data structures
24
  # ----------------------------
 
 
25
  PromptPrefix = "AI-Search: "
26
  PromptPrefix2 = "AI-Refine: "
27
  PromptPrefix3 = "AI-JS: "
28
 
 
29
  roleplaying_glossary = {
30
  "Core Rulebooks": {
31
  "Dungeons and Dragons": ["Player's Handbook", "Dungeon Master's Guide", "Monster Manual"],
 
36
  }
37
  }
38
 
 
39
  transhuman_glossary = {
40
  "Neural Interfaces": ["Cortex Jack", "Mind-Machine Fusion"],
41
  "Cybernetics": ["Robotic Limbs", "Augmented Eyes"],
42
  }
43
 
44
+
45
+ # ------------------------------------------
46
+ # Example stubs for placeholders
47
+ # ------------------------------------------
48
  def process_text(text):
49
  st.write(f"process_text called with: {text}")
50
 
 
66
  def search_glossary(content):
67
  st.write(f"search_glossary called with: {content}")
68
 
69
+
70
+ # If you have HF Inference endpoints, placeholders here
71
  API_URL = "https://huggingface-inference-endpoint-placeholder"
72
  API_KEY = "hf_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
73
 
 
82
  @st.cache_resource
83
  def display_glossary_entity(k):
84
  """
85
+ Creates multiple links (emojis) for a single entity.
 
86
  """
87
  search_urls = {
88
  "🚀🌌ArXiv": lambda k: f"/?q={quote(k)}",
 
150
  with open(zip_file, 'rb') as f:
151
  data = f.read()
152
  b64 = base64.b64encode(data).decode()
153
+ return f'<a href="data:application/zip;base64,{b64}" download="{zip_file}">Download All</a>'
 
154
 
155
  def get_table_download_link(file_path):
156
  """
 
172
  '.wav': 'audio/wav'
173
  }
174
  mime_type = mime_map.get(ext, 'application/octet-stream')
175
+ return f'<a href="data:{mime_type};base64,{b64}" target="_blank" download="{file_name}">{file_name}</a>'
 
176
  except:
177
  return ''
178
 
 
190
  for file in files:
191
  size = os.path.getsize(file)
192
  file_sizes.setdefault(size, []).append(file)
193
+ # Remove all but the latest file for each size group
194
  for size, paths in file_sizes.items():
195
  if len(paths) > 1:
196
  latest_file = max(paths, key=os.path.getmtime)
 
198
  if file != latest_file:
199
  os.remove(file)
200
  st.success(f"Deleted {file} as a duplicate.")
201
+
202
 
203
  def FileSidebar():
204
  """
205
  Renders the file sidebar with all the open/view/run/delete logic.
206
  """
207
  all_files = glob.glob("*.md")
208
+ # Filter out short-named or undesired files, if needed:
209
+ all_files = [f for f in all_files if len(os.path.splitext(f)[0]) >= 5]
210
  all_files.sort(key=lambda x: (os.path.splitext(x)[1], x), reverse=True)
211
 
212
+ # "Delete All" and "Download" buttons
213
  Files1, Files2 = st.sidebar.columns(2)
214
  with Files1:
215
  if st.button("🗑 Delete All"):
216
  for file in all_files:
217
  os.remove(file)
218
+ st.experimental_rerun() # or remove if you prefer no rerun
219
  with Files2:
220
  if st.button("⬇️ Download"):
221
  zip_file = create_zip_of_files(all_files)
 
225
  file_name = ''
226
  next_action = ''
227
 
 
228
  for file in all_files:
229
  col1, col2, col3, col4, col5 = st.sidebar.columns([1,6,1,1,1])
230
  with col1:
 
231
  if st.button("🌐", key="md_"+file):
232
  file_contents = load_file(file)
233
  file_name = file
 
253
  with col5:
254
  if st.button("🗑", key="delete_"+file):
255
  os.remove(file)
256
+ st.experimental_rerun() # or remove if no rerun needed
 
 
 
257
 
258
+ # Optional: show file sizes
259
  file_sizes = [get_file_size(file) for file in all_files]
260
  previous_size = None
261
  st.sidebar.title("File Operations")
 
269
  file_content = f.read()
270
  st.code(file_content, language="markdown")
271
  except UnicodeDecodeError:
272
+ st.error("Failed to decode file with UTF-8.")
273
  if st.button("Delete", key=f"delete3_{file}"):
274
  os.remove(file)
275
+ st.experimental_rerun()
276
  previous_size = size
277
 
278
+ # If we've loaded content from a file
279
+ if file_contents:
280
  if next_action == 'open':
281
  open1, open2 = st.columns([0.8, 0.2])
282
  with open1:
283
+ file_name_input = st.text_input('File Name:', file_name, key='file_name_input')
284
  file_content_area = st.text_area('File Contents:', file_contents, height=300, key='file_content_area')
285
 
 
286
  if st.button('💾 Save File'):
287
  with open(file_name_input, 'w', encoding='utf-8') as f:
288
  f.write(file_content_area)
289
  st.markdown(f'Saved {file_name_input} successfully.')
290
 
291
  elif next_action == 'search':
 
292
  file_content_area = st.text_area("File Contents:", file_contents, height=500)
293
  user_prompt = PromptPrefix2 + file_contents
294
  st.markdown(user_prompt)
 
302
  st.write("Running GPT logic placeholder...")
303
 
304
 
305
+ # -------------------------------------------
306
  # Basic Scoring / Glossaries
307
+ # -------------------------------------------
308
  score_dir = "scores"
309
  os.makedirs(score_dir, exist_ok=True)
310
 
 
344
  "Kindred of the East": "🌅",
345
  "Changeling": "🍃",
346
  }
 
347
  topic_emojis = {
348
  "Core Rulebooks": "📚",
349
  "Maps & Settings": "🗺️",
 
371
  st.markdown(f"Scored **{category} - {game} - {term}** -> {newscore}")
372
 
373
 
374
+ # --------------------------------------
375
  # Image & Video Grids
376
+ # --------------------------------------
377
  def display_images_and_wikipedia_summaries(num_columns=4):
378
  """
379
+ Display .png images in a grid with text input prompts.
380
  """
381
  image_files = [f for f in os.listdir('.') if f.endswith('.png')]
382
  if not image_files:
383
  st.write("No PNG images found in the current directory.")
384
  return
385
 
 
386
  image_files_sorted = sorted(image_files, key=lambda x: len(x.split('.')[0]))
387
  cols = st.columns(num_columns)
388
  col_index = 0
 
396
  display_glossary_entity(k)
397
  # Provide a text input for user interactions
398
  image_text_input = st.text_input(f"Prompt for {image_file}", key=f"image_prompt_{image_file}")
399
+ if image_text_input:
400
  response = process_image(image_file, image_text_input)
401
  st.markdown(response)
402
  except:
 
405
 
406
  def display_videos_and_links(num_columns=4):
407
  """
408
+ Displays all .mp4/.webm videos in the directory in a grid, with text input prompts.
409
  """
410
  video_files = [f for f in os.listdir('.') if f.endswith(('.mp4', '.webm'))]
411
  if not video_files:
 
421
  k = video_file.split('.')[0]
422
  st.video(video_file, format='video/mp4', start_time=0)
423
  display_glossary_entity(k)
 
424
  video_text_input = st.text_input(f"Video Prompt for {video_file}", key=f"video_prompt_{video_file}")
425
  if video_text_input:
426
  try:
427
+ # For demonstration
428
  seconds_per_frame = 10
429
  process_video(video_file, seconds_per_frame)
430
  except ValueError:
 
432
  col_index += 1
433
 
434
 
435
+ # --------------------------------------
436
+ # Query Param Helpers (No experimental)
437
+ # --------------------------------------
 
 
 
438
  def clear_query_params():
439
+ """
440
+ In Streamlit, there's no direct method to "clear" query params
441
+ without rewriting the URL. One workaround is to do:
442
+
443
+ st.experimental_set_query_params() # with no arguments
444
+
445
+ But if you want to avoid *all* experimental calls,
446
+ you can provide a link or button that leads to a new URL without params.
447
+ """
448
+ st.warning("Use a redirect or link that excludes query parameters.")
449
+
450
 
451
  def display_content_or_image(query):
452
  """
453
+ If a query matches transhuman_glossary or a local image, display it.
 
454
  """
455
  for category, term_list in transhuman_glossary.items():
456
  for term in term_list:
 
471
  # ------------------------------------
472
  def generate_mermaid_html(mermaid_code: str) -> str:
473
  """
474
+ Embeds a mermaid diagram in HTML, centered.
 
475
  """
476
  return f"""
477
  <html>
 
484
  margin: 20px auto;
485
  }}
486
  .mermaid {{
 
487
  max-width: 800px;
488
  }}
489
  </style>
 
501
 
502
  def append_model_param(url: str, model_selected: bool) -> str:
503
  """
504
+ If 'model=1' is desired, we append it to each URL in the diagram.
 
505
  """
506
  if not model_selected:
507
  return url
 
509
  return f"{url}{delimiter}model=1"
510
 
511
 
 
512
  DEFAULT_MERMAID = """
513
  flowchart LR
 
514
  U((User 😎)) -- "Talk 🗣️" --> LLM[LLM Agent 🤖\\nExtract Info]
515
  click U "/?q=User%20😎" _self
516
  click LLM "/?q=LLM%20Agent%20Extract%20Info" _self
 
525
  click KG "/?q=Knowledge%20Graph%20Ontology+GAR+RAG" _self
526
  """
527
 
528
+
529
  # ---------------------------
530
+ # Main Streamlit App
531
  # ---------------------------
532
  def main():
533
  st.set_page_config(page_title="Mermaid + Clickable Links Demo", layout="wide")
534
 
535
+ # ---------------------------------------------
536
+ # Query Parameter Parsing (No experimental usage)
537
+ # ---------------------------------------------
538
+ try:
539
+ query_params = st.query_params
540
+
541
+ # Look for 'q' or 'query'
542
+ query_list = (query_params.get('q') or query_params.get('query') or [''])
543
+ q_or_query = query_list[0] if len(query_list) > 0 else ''
544
+ if q_or_query.strip():
545
+ filesearch = PromptPrefix + q_or_query
546
+ st.markdown(filesearch)
547
+ process_text(filesearch)
548
+
549
+ except Exception as e:
550
+ st.markdown(" ") # do nothing if there's an error
551
+
552
+ # If 'action' in st.query_params
553
+ if 'action' in st.query_params:
554
+ action_list = st.query_params['action']
555
+ if action_list:
556
+ action = action_list[0]
557
+ if action == 'show_message':
558
+ st.success("Showing a message because 'action=show_message' was found in the URL.")
559
+ elif action == 'clear':
560
+ clear_query_params()
561
+ # If you wanted a full rerun with no params, you'd do a redirect or
562
+ # st.experimental_set_query_params() with no arguments (but that's experimental).
563
+
564
+ # If 'query' param is present, show content or image
565
+ if 'query' in st.query_params:
566
+ query_list2 = st.query_params['query']
567
+ if query_list2 and len(query_list2) > 0:
568
+ query_val = query_list2[0]
569
+ display_content_or_image(query_val)
570
+
571
+ # ---------------------------------------------
572
+ # Let user pick if they want to add ?model=1
573
+ # ---------------------------------------------
574
  st.sidebar.write("## Diagram Link Settings")
575
  model_selected = st.sidebar.checkbox("Append ?model=1 to each link?")
576
 
577
+ # Rebuild the dynamic Mermaid code
578
  base_diagram = DEFAULT_MERMAID
579
  lines = base_diagram.strip().split("\n")
580
  new_lines = []
581
  for line in lines:
582
  if "click " in line and '"/?' in line:
583
+ # e.g. click U "/?q=User" _self
584
  parts = re.split(r'click\s+\S+\s+"([^"]+)"\s+("_self")', line)
585
  if len(parts) == 4:
586
  url = parts[1]
 
591
  new_lines.append(line)
592
  else:
593
  new_lines.append(line)
 
594
  mermaid_code = "\n".join(new_lines)
595
 
596
+ # ---------------------------------------------
597
+ # Render top-centered Mermaid diagram
598
+ # ---------------------------------------------
599
  st.title("Top-Centered Mermaid Diagram with Clickable Links 🏺")
600
  diagram_html = generate_mermaid_html(mermaid_code)
601
  components.html(diagram_html, height=400, scrolling=True)
602
 
603
+ # ---------------------------------------------
604
+ # Two-column layout: Markdown & Mermaid Editors
605
+ # ---------------------------------------------
 
 
 
 
 
606
  left_col, right_col = st.columns(2)
607
 
608
  # --- Left: Markdown Editor
 
610
  st.subheader("Markdown Side 📝")
611
  if "markdown_text" not in st.session_state:
612
  st.session_state["markdown_text"] = "## Hello!\nType some *Markdown* here.\n"
 
613
  markdown_text = st.text_area(
614
  "Edit Markdown:",
615
  value=st.session_state["markdown_text"],
 
617
  )
618
  st.session_state["markdown_text"] = markdown_text
619
 
 
620
  colA, colB = st.columns(2)
621
  with colA:
622
  if st.button("🔄 Refresh Markdown"):
 
624
  with colB:
625
  if st.button("❌ Clear Markdown"):
626
  st.session_state["markdown_text"] = ""
627
+ st.rerun() # non-experimental re-run if available in your Streamlit version
628
 
 
629
  st.markdown("---")
630
  st.markdown("**Preview:**")
631
  st.markdown(markdown_text)
 
643
  height=300
644
  )
645
 
 
646
  colC, colD = st.columns(2)
647
  with colC:
648
  if st.button("🎨 Refresh Diagram"):
649
  st.session_state["current_mermaid"] = mermaid_input
650
  st.write("**Mermaid** diagram refreshed! 🌈")
651
+ st.rerun()
652
  with colD:
653
  if st.button("❌ Clear Mermaid"):
654
  st.session_state["current_mermaid"] = ""
655
+ st.rerun()
656
 
657
  st.markdown("---")
658
  st.markdown("**Mermaid Source:**")
659
  st.code(mermaid_input, language="python", line_numbers=True)
660
 
661
+ # ---------------------------------------------
662
+ # Media Galleries
663
+ # ---------------------------------------------
664
  st.markdown("---")
665
  st.header("Media Galleries")
666
 
 
670
  num_columns_video = st.slider("Choose Number of Video Columns", 1, 15, 5, key="num_columns_video")
671
  display_videos_and_links(num_columns_video)
672
 
673
+ # ---------------------------------------------
674
+ # Optional Extended UI
675
+ # ---------------------------------------------
676
  showExtendedTextInterface = False
677
  if showExtendedTextInterface:
678
  display_glossary_grid(roleplaying_glossary)
 
680
  display_buttons_with_scores(num_columns_text)
681
  st.markdown("Extended text interface is on...")
682
 
683
+ # ---------------------------------------------
684
+ # File Sidebar
685
+ # ---------------------------------------------
686
  FileSidebar()
687
 
688
+ # ---------------------------------------------
689
+ # Random Title at the bottom
690
+ # ---------------------------------------------
691
  titles = [
692
  "🧠🎭 Semantic Symphonies & Episodic Encores",
693
  "🌌🎼 AI Rhythms of Memory Lane",