lamossta commited on
Commit
306a26a
·
1 Parent(s): 0150291

streamlit pages

Browse files
Files changed (4) hide show
  1. pages/config.py +69 -0
  2. pages/navigation.py +29 -0
  3. pages/result.py +63 -0
  4. pages/welcome.py +27 -0
pages/config.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ import streamlit as st
4
+ from pydantic import ValidationError
5
+
6
+ from pages.navigation import show_stepper
7
+ from src.schemas.requests import SampleInput
8
+
9
+ show_stepper("Configuration")
10
+
11
+ SAMPLE_INPUT = json.dumps(
12
+ [
13
+ {
14
+ "id": 0,
15
+ "text": "Google had solid Q4 2025 earnings but Microsoft's were not great.",
16
+ "entities": [
17
+ {
18
+ "entity_id": 0,
19
+ "entity_text": "Google",
20
+ "entity_type": "company",
21
+ "positions": [
22
+ {"position_text": "Google", "length": 6, "offset": 0}
23
+ ],
24
+ },
25
+ {
26
+ "entity_id": 1,
27
+ "entity_text": "Microsoft",
28
+ "entity_type": "company",
29
+ "positions": [
30
+ {"position_text": "Microsoft", "length": 9, "offset": 40}
31
+ ],
32
+ },
33
+ ],
34
+ }
35
+ ],
36
+ indent=2,
37
+ )
38
+
39
+ st.header("Configuration")
40
+
41
+ endpoint = st.selectbox(
42
+ "Endpoint",
43
+ options=["predict", "predict-all-models"],
44
+ index=0,
45
+ )
46
+ st.session_state.endpoint = endpoint
47
+
48
+ st.subheader("Input samples (JSON)")
49
+ default = st.session_state.get("input_json", SAMPLE_INPUT)
50
+ input_json = st.text_area("Paste your JSON input here:", value=default, height=300)
51
+ st.session_state.input_json = input_json
52
+
53
+ col1, col2 = st.columns(2)
54
+ with col1:
55
+ if st.button("Previous", use_container_width=True):
56
+ st.switch_page("pages/welcome.py")
57
+ with col2:
58
+ if st.button("Run prediction", use_container_width=True):
59
+ try:
60
+ parsed = json.loads(input_json)
61
+ if not isinstance(parsed, list):
62
+ raise ValueError("Input must be a JSON array of samples.")
63
+ for item in parsed:
64
+ SampleInput(**item)
65
+ st.switch_page("pages/result.py")
66
+ except json.JSONDecodeError as e:
67
+ st.error(f"Invalid JSON: {e}")
68
+ except (ValueError, ValidationError) as e:
69
+ st.error(f"Invalid input: {e}")
pages/navigation.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ PAGES = [
4
+ ("Welcome", "pages/welcome.py"),
5
+ ("Configuration", "pages/config.py"),
6
+ ("Results", "pages/result.py"),
7
+ ]
8
+
9
+
10
+ def show_stepper(current: str):
11
+ """Render a horizontal step indicator. `current` is the page title."""
12
+ cols = st.columns(len(PAGES))
13
+ for i, (title, path) in enumerate(PAGES):
14
+ with cols[i]:
15
+ if title == current:
16
+ st.markdown(
17
+ f"<div style='text-align:center; padding:8px 0; "
18
+ f"border-bottom:3px solid #ff4b4b; font-weight:700;'>"
19
+ f"{i + 1}. {title}</div>",
20
+ unsafe_allow_html=True,
21
+ )
22
+ else:
23
+ st.markdown(
24
+ f"<div style='text-align:center; padding:8px 0; "
25
+ f"border-bottom:3px solid #444; color:#888;'>"
26
+ f"{i + 1}. {title}</div>",
27
+ unsafe_allow_html=True,
28
+ )
29
+ st.write("")
pages/result.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ import streamlit as st
4
+
5
+ from pages.navigation import show_stepper
6
+ from src.fe_handler import call_predict, call_predict_all
7
+
8
+ show_stepper("Results")
9
+
10
+ st.header("Results")
11
+
12
+ input_json = st.session_state.get("input_json")
13
+
14
+ if not input_json:
15
+ st.warning("No input provided. Go back and provide samples.")
16
+ if st.button("Back to config", use_container_width=True):
17
+ st.switch_page("pages/config.py")
18
+ st.stop()
19
+
20
+ try:
21
+ parsed = json.loads(input_json)
22
+ except (json.JSONDecodeError, ValueError) as e:
23
+ st.error(f"Invalid input: {e}")
24
+ if st.button("Back to config", use_container_width=True):
25
+ st.switch_page("pages/config.py")
26
+ st.stop()
27
+
28
+ endpoint = st.session_state.get("endpoint", "predict")
29
+
30
+ try:
31
+ with st.spinner("Running prediction..."):
32
+ if endpoint == "predict":
33
+ results = call_predict(parsed)
34
+ _single = True
35
+ else:
36
+ results = call_predict_all(parsed)
37
+ _single = False
38
+
39
+ if _single:
40
+ for sample in results:
41
+ st.markdown(f"**Sample {sample['id']}**")
42
+ for entity in sample["entities"]:
43
+ color = {"positive": "green", "neutral": "gray", "negative": "red"}.get(
44
+ entity["classification"], "gray"
45
+ )
46
+ st.markdown(f"- {entity['entity_text']}: :{color}[{entity['classification']}]")
47
+ else:
48
+ tabs = st.tabs(list(results.keys()))
49
+ for tab, (mode, preds) in zip(tabs, results.items()):
50
+ with tab:
51
+ for sample in preds:
52
+ st.markdown(f"**Sample {sample['id']}**")
53
+ for entity in sample["entities"]:
54
+ color = {"positive": "green", "neutral": "gray", "negative": "red"}.get(
55
+ entity["classification"], "gray"
56
+ )
57
+ st.markdown(f"- {entity['entity_text']}: :{color}[{entity['classification']}]")
58
+ except Exception as e:
59
+ st.error(f"Prediction failed: {e}")
60
+
61
+ st.write("")
62
+ if st.button("Back to config", use_container_width=True):
63
+ st.switch_page("pages/config.py")
pages/welcome.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ from pages.navigation import show_stepper
4
+ from src.fe_handler import check_health
5
+
6
+ show_stepper("Welcome")
7
+
8
+ st.header("Entity Sentiment Classification")
9
+ st.write(
10
+ "This tool classifies sentiment (positive, neutral, negative) "
11
+ "for specific entities mentioned in text articles."
12
+ )
13
+ st.subheader("Available endpoints")
14
+ st.markdown(
15
+ "- **`/predict`** — classify entities using a single model (marker)\n"
16
+ "- **`/predict-all-models`** — classify entities using all available models "
17
+ "and compare their results side by side"
18
+ )
19
+
20
+ if check_health():
21
+ st.success("Backend is running.")
22
+ else:
23
+ st.error("Backend is not reachable. Make sure the FastAPI server is running.")
24
+
25
+ st.write("")
26
+ if st.button("Next", use_container_width=True):
27
+ st.switch_page("pages/config.py")