LazyHuman10 commited on
Commit
49bf421
·
1 Parent(s): 8657f7c

sync: fix chat reset and payload errors

Browse files
Files changed (2) hide show
  1. pages/Plexi-Assistant.py +109 -41
  2. utils.py +16 -0
pages/Plexi-Assistant.py CHANGED
@@ -286,6 +286,12 @@ def _send_message(endpoint_url, api_key, model, system_prompt, history, user_pro
286
  if response.status_code == 429:
287
  detail = response.json().get("error", {}).get("message", "Rate limit exceeded.")
288
  raise Exception(f"RATE_LIMITED: {detail}")
 
 
 
 
 
 
289
  if response.status_code == 401:
290
  raise Exception(
291
  "AUTH_ERROR: Invalid API key. Please check your key and try again."
@@ -384,42 +390,12 @@ def render_onboarding(manifest):
384
  "`PLEXI_COOKIE_PASSWORD` is set."
385
  )
386
 
387
- semester_names = sorted(manifest.keys())
388
- default_semester = st.session_state.get("asst_semester")
389
- semester_index = (
390
- semester_names.index(default_semester)
391
- if default_semester in semester_names
392
- else 0
393
- )
394
- selected_semester = st.selectbox(
395
- "Semester",
396
- semester_names,
397
- index=semester_index,
398
- key="ob_semester",
399
- )
400
-
401
- subject_names = sorted(manifest[selected_semester].keys())
402
- default_subject = st.session_state.get("asst_subject")
403
- subject_index = (
404
- subject_names.index(default_subject)
405
- if default_subject in subject_names
406
- else 0
407
- )
408
- selected_subject = st.selectbox(
409
- "Subject",
410
- subject_names,
411
- index=subject_index,
412
- key="ob_subject",
413
- )
414
-
415
  can_start = bool(
416
  model_name
417
- and selected_semester
418
- and selected_subject
419
  and (not needs_key or api_key)
420
  )
421
  if st.button(
422
- "Start Chatting",
423
  type="primary",
424
  disabled=not can_start,
425
  use_container_width=True,
@@ -427,8 +403,6 @@ def render_onboarding(manifest):
427
  st.session_state.cfg_provider = provider_name
428
  st.session_state.cfg_base_url = base_url
429
  st.session_state.cfg_model = model_name
430
- st.session_state.asst_semester = selected_semester
431
- st.session_state.asst_subject = selected_subject
432
  st.session_state.remember_device = remember_device
433
  if api_key:
434
  st.session_state.api_key = api_key
@@ -441,8 +415,6 @@ def render_onboarding(manifest):
441
  "cfg_base_url": base_url,
442
  "cfg_model": model_name,
443
  "api_key": api_key,
444
- "asst_semester": selected_semester,
445
- "asst_subject": selected_subject,
446
  }
447
  )
448
  else:
@@ -480,6 +452,82 @@ def render_onboarding(manifest):
480
  )
481
 
482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  _hydrate_saved_config()
484
  render_sidebar_intro()
485
 
@@ -497,6 +545,10 @@ if not _is_configured():
497
  render_onboarding(manifest)
498
  st.stop()
499
 
 
 
 
 
500
  provider_name = st.session_state.cfg_provider
501
  base_url = st.session_state.cfg_base_url
502
  model_name = st.session_state.cfg_model
@@ -522,12 +574,13 @@ if st.session_state.get("_scope_key") != scope_key:
522
  st.session_state.pop("messages", None)
523
 
524
 
525
- @st.cache_data(show_spinner="Loading study materials...", ttl=300)
526
  def _get_subject_context(semester, subject):
527
  return load_subject_context(manifest, semester, subject)
528
 
529
 
530
- subject_text, source_list = _get_subject_context(selected_semester, selected_subject)
 
531
  if not subject_text.strip():
532
  st.warning("No readable text was found for this subject. Try another selection.")
533
  st.stop()
@@ -824,15 +877,30 @@ if prompt:
824
  if st.button("Retry", type="primary"):
825
  st.rerun()
826
  st.stop()
 
 
 
 
 
 
 
827
  if "AUTH_ERROR" in err_text:
828
- st.error(err_text.split(": ", 1)[1])
829
  _clear_saved_config()
830
  st.session_state.remember_device = False
831
  if "api_key" in st.session_state:
832
  del st.session_state.api_key
833
- st.session_state.messages.pop()
834
- st.stop()
835
- raise
 
 
 
 
 
 
 
 
836
 
837
  st.markdown(answer)
838
 
 
286
  if response.status_code == 429:
287
  detail = response.json().get("error", {}).get("message", "Rate limit exceeded.")
288
  raise Exception(f"RATE_LIMITED: {detail}")
289
+ if response.status_code == 413:
290
+ raise Exception(
291
+ "PAYLOAD_TOO_LARGE: The study materials are too large for this model's context window. "
292
+ "Please try asking a more specific question (e.g., 'Tell me viva questions for Unit 1' instead of the whole subject), "
293
+ "or switch to a model with a larger context window."
294
+ )
295
  if response.status_code == 401:
296
  raise Exception(
297
  "AUTH_ERROR: Invalid API key. Please check your key and try again."
 
390
  "`PLEXI_COOKIE_PASSWORD` is set."
391
  )
392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  can_start = bool(
394
  model_name
 
 
395
  and (not needs_key or api_key)
396
  )
397
  if st.button(
398
+ "Continue",
399
  type="primary",
400
  disabled=not can_start,
401
  use_container_width=True,
 
403
  st.session_state.cfg_provider = provider_name
404
  st.session_state.cfg_base_url = base_url
405
  st.session_state.cfg_model = model_name
 
 
406
  st.session_state.remember_device = remember_device
407
  if api_key:
408
  st.session_state.api_key = api_key
 
415
  "cfg_base_url": base_url,
416
  "cfg_model": model_name,
417
  "api_key": api_key,
 
 
418
  }
419
  )
420
  else:
 
452
  )
453
 
454
 
455
+ def render_scope_selection(manifest):
456
+ """Render the subject selection flow before loading materials."""
457
+ render_page_header(
458
+ "Plexi assistant",
459
+ "Select study materials",
460
+ "Choose a semester and subject to load the corresponding materials for the chat.",
461
+ badges=[st.session_state.cfg_provider, st.session_state.cfg_model],
462
+ )
463
+
464
+ left_col, right_col = st.columns([1.1, 0.9], gap="large")
465
+
466
+ with left_col:
467
+ st.markdown(
468
+ """
469
+ <section class="plexi-panel">
470
+ <div class="plexi-sidecard-title">Choose your subject</div>
471
+ <div class="plexi-muted">
472
+ Materials for this subject will be loaded into the AI's context.
473
+ </div>
474
+ </section>
475
+ """,
476
+ unsafe_allow_html=True,
477
+ )
478
+
479
+ semester_names = sorted(manifest.keys())
480
+ default_semester = st.session_state.get("asst_semester")
481
+ semester_index = (
482
+ semester_names.index(default_semester)
483
+ if default_semester in semester_names
484
+ else 0
485
+ )
486
+ selected_semester = st.selectbox(
487
+ "Semester",
488
+ semester_names,
489
+ index=semester_index,
490
+ key="asst_semester",
491
+ )
492
+
493
+ subject_names = sorted(manifest[selected_semester].keys())
494
+ default_subject = st.session_state.get("asst_subject")
495
+ subject_index = (
496
+ subject_names.index(default_subject)
497
+ if default_subject in subject_names
498
+ else 0
499
+ )
500
+ selected_subject = st.selectbox(
501
+ "Subject",
502
+ subject_names,
503
+ index=subject_index,
504
+ key="asst_subject",
505
+ )
506
+
507
+ if st.button(
508
+ "Load Materials & Start Chat", type="primary", use_container_width=True
509
+ ):
510
+ st.session_state._scope_confirmed = True
511
+
512
+ if st.session_state.get("remember_device"):
513
+ _save_config(
514
+ {
515
+ "cfg_provider": st.session_state.cfg_provider,
516
+ "cfg_base_url": st.session_state.cfg_base_url,
517
+ "cfg_model": st.session_state.cfg_model,
518
+ "api_key": st.session_state.get("api_key", ""),
519
+ "asst_semester": selected_semester,
520
+ "asst_subject": selected_subject,
521
+ }
522
+ )
523
+
524
+ st.session_state.pop("messages", None)
525
+ st.rerun()
526
+
527
+ with right_col:
528
+ render_external_access()
529
+
530
+
531
  _hydrate_saved_config()
532
  render_sidebar_intro()
533
 
 
545
  render_onboarding(manifest)
546
  st.stop()
547
 
548
+ if not st.session_state.get("_scope_confirmed"):
549
+ render_scope_selection(manifest)
550
+ st.stop()
551
+
552
  provider_name = st.session_state.cfg_provider
553
  base_url = st.session_state.cfg_base_url
554
  model_name = st.session_state.cfg_model
 
574
  st.session_state.pop("messages", None)
575
 
576
 
577
+ @st.cache_data(show_spinner=False, ttl=300)
578
  def _get_subject_context(semester, subject):
579
  return load_subject_context(manifest, semester, subject)
580
 
581
 
582
+ with st.spinner("Loading study materials..."):
583
+ subject_text, source_list = _get_subject_context(selected_semester, selected_subject)
584
  if not subject_text.strip():
585
  st.warning("No readable text was found for this subject. Try another selection.")
586
  st.stop()
 
877
  if st.button("Retry", type="primary"):
878
  st.rerun()
879
  st.stop()
880
+ if "PAYLOAD_TOO_LARGE" in err_text:
881
+ err_msg = err_text.split(": ", 1)[1]
882
+ st.session_state.messages.append({
883
+ "role": "assistant",
884
+ "content": f"**System Error:** {err_msg}"
885
+ })
886
+ st.rerun()
887
  if "AUTH_ERROR" in err_text:
888
+ err_msg = err_text.split(": ", 1)[1]
889
  _clear_saved_config()
890
  st.session_state.remember_device = False
891
  if "api_key" in st.session_state:
892
  del st.session_state.api_key
893
+ st.session_state.messages.append({
894
+ "role": "assistant",
895
+ "content": f"**System Error:** {err_msg}"
896
+ })
897
+ st.rerun()
898
+
899
+ st.session_state.messages.append({
900
+ "role": "assistant",
901
+ "content": f"**System Error:** {err_text}"
902
+ })
903
+ st.rerun()
904
 
905
  st.markdown(answer)
906
 
utils.py CHANGED
@@ -503,6 +503,22 @@ $palette_vars
503
  background: var(--plexi-expander-background);
504
  }
505
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  div[data-baseweb="popover"],
507
  div[data-baseweb="popover"] > div,
508
  div[data-baseweb="popover"] > div > div,
 
503
  background: var(--plexi-expander-background);
504
  }
505
 
506
+ div[data-testid="stToast"] {
507
+ background: var(--plexi-panel-strong) !important;
508
+ color: var(--plexi-ink) !important;
509
+ border: 1px solid var(--plexi-line) !important;
510
+ box-shadow: var(--plexi-shadow) !important;
511
+ }
512
+
513
+ div[data-testid="toastContainer"] * {
514
+ color: var(--plexi-ink) !important;
515
+ }
516
+
517
+ div[data-testid="stSpinner"] > div,
518
+ div[data-testid="stSpinner"] * {
519
+ color: var(--plexi-ink) !important;
520
+ }
521
+
522
  div[data-baseweb="popover"],
523
  div[data-baseweb="popover"] > div,
524
  div[data-baseweb="popover"] > div > div,