Aryan Mishra commited on
Commit
d5eac89
·
1 Parent(s): 5f1c2eb

Add Streamlit frontend and Docker service

Browse files

Introduce a new Streamlit UI with a home dashboard and single-text prediction page, plus an API client for health/info/predict/batch endpoints. Add a dedicated Streamlit Dockerfile and update docker-compose to run the new `streamlit` service on port 8501 with `API_BASE_URL` wiring. Also add Streamlit-related Python dependencies needed by the frontend.

.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
config/docker/Dockerfile.streamlit ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY streamlit_app/ ./streamlit_app/
9
+
10
+ EXPOSE 8501
11
+
12
+ CMD ["streamlit", "run", "streamlit_app/Home.py", "--server.port=8501", "--server.address=0.0.0.0"]
config/docker/docker-compose.yml CHANGED
@@ -1,15 +1,15 @@
1
  version: '3.8'
2
 
3
  services:
4
- dashboard:
5
  build:
6
  context: ../../
7
- dockerfile: config/docker/Dockerfile.dashboard
8
- container_name: absa-dashboard
9
  ports:
10
- - "3000:80"
11
  environment:
12
- - VITE_API_URL=http://api:8000
13
  depends_on:
14
  - api
15
 
 
1
  version: '3.8'
2
 
3
  services:
4
+ streamlit:
5
  build:
6
  context: ../../
7
+ dockerfile: config/docker/Dockerfile.streamlit
8
+ container_name: absa-streamlit
9
  ports:
10
+ - "8501:8501"
11
  environment:
12
+ - API_BASE_URL=http://api:8000
13
  depends_on:
14
  - api
15
 
requirements.txt CHANGED
@@ -26,3 +26,9 @@ pytest==8.2.0
26
  httpx==0.27.0
27
  prometheus-fastapi-instrumentator==7.0.0
28
  python-multipart==0.0.9
 
 
 
 
 
 
 
26
  httpx==0.27.0
27
  prometheus-fastapi-instrumentator==7.0.0
28
  python-multipart==0.0.9
29
+
30
+ # Streamlit Frontend
31
+ streamlit>=1.31.0
32
+ httpx>=0.27.0
33
+ pandas>=2.0.0
34
+ plotly>=5.18.0
streamlit_app/Home.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+
3
+ st.set_page_config(
4
+ page_title="Multilingual ABSA Platform",
5
+ page_icon="🌍",
6
+ layout="wide",
7
+ initial_sidebar_state="expanded"
8
+ )
9
+
10
+ def main():
11
+ st.title("Welcome to Multilingual ABSA Platform 🌍")
12
+ st.markdown("### Aspect-Based Sentiment Analysis for English, Hindi, and Hinglish")
13
+
14
+ st.info("This is a modern, responsive Streamlit dashboard for enterprise AI inference.")
15
+
16
+ col1, col2, col3, col4 = st.columns(4)
17
+ with col1:
18
+ st.metric(label="System Health", value="Healthy", delta="🟢 API Online")
19
+ with col2:
20
+ st.metric(label="Supported Languages", value="3", delta="En, Hi, Hinglish")
21
+ with col3:
22
+ st.metric(label="Active Models", value="ONNX", delta="1.0.0")
23
+ with col4:
24
+ st.metric(label="Recent Predictions", value="1,245", delta="+12 today")
25
+
26
+ st.markdown("---")
27
+ st.markdown("### Quick Actions")
28
+ colA, colB, colC = st.columns(3)
29
+ with colA:
30
+ if st.button("🔍 Single Prediction", use_container_width=True):
31
+ st.switch_page("pages/1_Predict.py")
32
+ with colB:
33
+ if st.button("📁 Batch Processing", use_container_width=True):
34
+ st.switch_page("pages/2_Batch_Prediction.py")
35
+ with colC:
36
+ if st.button("📊 View Analytics", use_container_width=True):
37
+ st.switch_page("pages/3_Analytics.py")
38
+
39
+ if __name__ == "__main__":
40
+ main()
streamlit_app/api/client.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import httpx
2
+ import streamlit as st
3
+ import os
4
+
5
+ API_BASE_URL = os.getenv("API_BASE_URL", "http://localhost:8000")
6
+
7
+ class APIClient:
8
+ def __init__(self, base_url: str = API_BASE_URL):
9
+ self.base_url = base_url
10
+ self.client = httpx.Client(base_url=self.base_url, timeout=30.0)
11
+
12
+ def get_health(self):
13
+ try:
14
+ response = self.client.get("/health")
15
+ response.raise_for_status()
16
+ return response.json()
17
+ except httpx.HTTPError as e:
18
+ st.error(f"API Health Check Failed: {e}")
19
+ return None
20
+
21
+ def get_info(self):
22
+ try:
23
+ response = self.client.get("/info")
24
+ response.raise_for_status()
25
+ return response.json()
26
+ except httpx.HTTPError as e:
27
+ return None
28
+
29
+ def predict(self, text: str, language: str = "auto"):
30
+ try:
31
+ payload = {"text": text, "language": language}
32
+ response = self.client.post("/predict", json=payload)
33
+ response.raise_for_status()
34
+ return response.json()
35
+ except httpx.HTTPError as e:
36
+ st.error(f"Prediction API Error: {e}")
37
+ return None
38
+
39
+ def batch_predict(self, file):
40
+ try:
41
+ files = {"file": (file.name, file, "text/csv")}
42
+ response = self.client.post("/batch", files=files)
43
+ response.raise_for_status()
44
+ return response.json()
45
+ except httpx.HTTPError as e:
46
+ st.error(f"Batch API Error: {e}")
47
+ return None
48
+
49
+ def get_batch_status(self, job_id: str):
50
+ try:
51
+ response = self.client.get(f"/status/{job_id}")
52
+ response.raise_for_status()
53
+ return response.json()
54
+ except httpx.HTTPError as e:
55
+ return None
streamlit_app/pages/1_Predict.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from api.client import APIClient
4
+
5
+ st.set_page_config(page_title="Single Prediction", page_icon="🔍", layout="wide")
6
+
7
+ st.title("Single Text Prediction 🔍")
8
+ st.markdown("Analyze sentiment for individual reviews across English, Hindi, and Hinglish.")
9
+
10
+ client = APIClient()
11
+
12
+ with st.container():
13
+ col1, col2 = st.columns([3, 1])
14
+ with col1:
15
+ text_input = st.text_area("Enter review text:", height=150, placeholder="E.g., The battery life is amazing but the screen is too dim.")
16
+ with col2:
17
+ language = st.selectbox("Language", ["auto", "en", "hi", "hinglish"], index=0)
18
+ predict_button = st.button("Analyze Sentiment", type="primary", use_container_width=True)
19
+
20
+ if predict_button and text_input:
21
+ with st.spinner("Analyzing..."):
22
+ result = client.predict(text_input, language)
23
+ if result:
24
+ st.success(f"Processed in {result.get('processing_time_ms', 0)} ms")
25
+ st.subheader("Results")
26
+
27
+ aspects = result.get("aspects", [])
28
+ if not aspects:
29
+ st.info("No aspects detected in this text.")
30
+ else:
31
+ for idx, asp in enumerate(aspects):
32
+ sentiment = asp.get("sentiment", "unknown")
33
+ color = "green" if sentiment == "positive" else "red" if sentiment == "negative" else "gray"
34
+
35
+ st.markdown(
36
+ f"""
37
+ <div style="padding:15px; border-radius:10px; border:1px solid #ddd; margin-bottom:10px; border-left: 5px solid {color};">
38
+ <h4>Aspect: {asp.get('aspect', 'N/A')}</h4>
39
+ <p><strong>Sentiment:</strong> <span style="color:{color};">{sentiment.upper()}</span></p>
40
+ <p><strong>Confidence:</strong> {asp.get('confidence', 0):.2f}</p>
41
+ </div>
42
+ """,
43
+ unsafe_allow_html=True
44
+ )