XQ commited on
Commit
43c040b
·
1 Parent(s): 00b6bf5

Update UI

Browse files
Files changed (1) hide show
  1. src/ui/app.py +68 -10
src/ui/app.py CHANGED
@@ -6,6 +6,8 @@ Single-page document search interface with clean sans-serif design.
6
 
7
  import os
8
  import random
 
 
9
 
10
  import streamlit as st
11
  import requests
@@ -30,6 +32,28 @@ EXAMPLE_QUESTIONS: list[str] = [
30
  "Hvad er reglerne for forlænget tid til eksamen?",
31
  ]
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  # ---------------------------------------------------------------------------
34
  # Internationalisation — all UI strings live here
35
  # ---------------------------------------------------------------------------
@@ -70,6 +94,9 @@ TEXTS: dict[str, dict[str, str]] = {
70
  "search_button": "Søg",
71
  "example_button": "Tilfaeldigt eksempel",
72
  "spinner": "Søger i dokumenterne ...",
 
 
 
73
  "confidence_label": "Konfidensgrad",
74
  "intent_label": "Intent",
75
  "strategy_label": "Strategi",
@@ -142,6 +169,9 @@ TEXTS: dict[str, dict[str, str]] = {
142
  "search_button": "Search",
143
  "example_button": "Random question",
144
  "spinner": "Searching documents ...",
 
 
 
145
  "confidence_label": "Confidence",
146
  "intent_label": "Intent",
147
  "strategy_label": "Strategy",
@@ -439,7 +469,10 @@ with st.form(key="search_form", clear_on_submit=False):
439
  # Query logic
440
  # ---------------------------------------------------------------------------
441
  if search_clicked and question.strip():
442
- with st.spinner(t["spinner"]):
 
 
 
443
  try:
444
  resp = requests.post(
445
  f"{API_BASE}/query",
@@ -451,19 +484,44 @@ if search_clicked and question.strip():
451
  timeout=120,
452
  )
453
  resp.raise_for_status()
454
- data = resp.json()
455
- except requests.ConnectionError:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
  st.error(t["err_connection"])
457
- st.stop()
458
- except requests.HTTPError as exc:
459
- if exc.response.status_code == 429:
460
  st.warning(t["err_rate_limit"])
461
  else:
462
- st.error(f'{t["err_api"]}: {exc.response.status_code} -- {exc.response.text}')
463
- st.stop()
464
- except requests.Timeout:
465
  st.error(t["err_timeout"])
466
- st.stop()
 
 
 
 
467
 
468
  # -- Metadata bar --
469
  confidence = data.get("confidence", 0.0)
 
6
 
7
  import os
8
  import random
9
+ import threading
10
+ import time
11
 
12
  import streamlit as st
13
  import requests
 
32
  "Hvad er reglerne for forlænget tid til eksamen?",
33
  ]
34
 
35
+ # ---------------------------------------------------------------------------
36
+ # Pipeline step labels shown during query processing
37
+ # Each tuple: (label, min_seconds_to_show_before_advancing)
38
+ # The last step has None duration — it stays until the request completes.
39
+ # ---------------------------------------------------------------------------
40
+ PIPELINE_STEPS: dict[str, list[tuple[str, float | None]]] = {
41
+ "da": [
42
+ ("Klassificerer forespørgsel ...", 0.7),
43
+ ("Oversætter til dansk om nødvendigt ...", 1.0),
44
+ ("Søger med BM25 og vektorsøgning ...", 1.8),
45
+ ("Fusionerer og reranker resultater ...", 1.2),
46
+ ("Genererer svar med sprogmodel ...", None),
47
+ ],
48
+ "en": [
49
+ ("Classifying query intent ...", 0.7),
50
+ ("Translating to Danish if needed ...", 1.0),
51
+ ("Searching with BM25 and vector search ...", 1.8),
52
+ ("Fusing and reranking results ...", 1.2),
53
+ ("Generating answer with language model ...", None),
54
+ ],
55
+ }
56
+
57
  # ---------------------------------------------------------------------------
58
  # Internationalisation — all UI strings live here
59
  # ---------------------------------------------------------------------------
 
94
  "search_button": "Søg",
95
  "example_button": "Tilfaeldigt eksempel",
96
  "spinner": "Søger i dokumenterne ...",
97
+ "status_label": "Behandler forespørgsel ...",
98
+ "status_done": "Færdig",
99
+ "status_error": "Noget gik galt",
100
  "confidence_label": "Konfidensgrad",
101
  "intent_label": "Intent",
102
  "strategy_label": "Strategi",
 
169
  "search_button": "Search",
170
  "example_button": "Random question",
171
  "spinner": "Searching documents ...",
172
+ "status_label": "Processing query ...",
173
+ "status_done": "Done",
174
+ "status_error": "Something went wrong",
175
  "confidence_label": "Confidence",
176
  "intent_label": "Intent",
177
  "strategy_label": "Strategy",
 
469
  # Query logic
470
  # ---------------------------------------------------------------------------
471
  if search_clicked and question.strip():
472
+ _result: dict = {}
473
+
474
+ def _call_api() -> None:
475
+ """Run the blocking API request in a background thread."""
476
  try:
477
  resp = requests.post(
478
  f"{API_BASE}/query",
 
484
  timeout=120,
485
  )
486
  resp.raise_for_status()
487
+ _result["data"] = resp.json()
488
+ except Exception as _exc: # noqa: BLE001
489
+ _result["error"] = _exc
490
+
491
+ _thread = threading.Thread(target=_call_api, daemon=True)
492
+ _thread.start()
493
+
494
+ with st.status(t["status_label"], expanded=True) as _status:
495
+ for _step_label, _step_duration in PIPELINE_STEPS[lang]:
496
+ st.write(_step_label)
497
+ if _step_duration is not None:
498
+ _deadline = time.monotonic() + _step_duration
499
+ while time.monotonic() < _deadline and _thread.is_alive():
500
+ time.sleep(0.1)
501
+ else:
502
+ _thread.join()
503
+
504
+ if "error" in _result:
505
+ _status.update(label=t["status_error"], state="error", expanded=True)
506
+ else:
507
+ _status.update(label=t["status_done"], state="complete", expanded=False)
508
+
509
+ if "error" in _result:
510
+ _exc = _result["error"]
511
+ if isinstance(_exc, requests.ConnectionError):
512
  st.error(t["err_connection"])
513
+ elif isinstance(_exc, requests.HTTPError):
514
+ if _exc.response.status_code == 429:
 
515
  st.warning(t["err_rate_limit"])
516
  else:
517
+ st.error(f'{t["err_api"]}: {_exc.response.status_code} -- {_exc.response.text}')
518
+ elif isinstance(_exc, requests.Timeout):
 
519
  st.error(t["err_timeout"])
520
+ else:
521
+ st.error(str(_exc))
522
+ st.stop()
523
+
524
+ data = _result.get("data", {})
525
 
526
  # -- Metadata bar --
527
  confidence = data.get("confidence", 0.0)