text-summarizer / frontend.py
janrudolf's picture
Capitaliza device used
2b9d358
"""
Streamlit frontend for the BottleCapAI text summarization service.
Calls the FastAPI backend for the summarization endpoint.
"""
import os
import sentry_sdk
import streamlit as st
import requests
from dotenv import load_dotenv
from pathlib import Path
load_dotenv()
# Monitor errors using Sentry
sentry_sdk.init(
dsn=os.environ.get("SENTRY_DSN"),
send_default_pii=True,
)
sentry_sdk.set_tag("service", "frontend")
# Backend API (FastAPI) - same host when running in Docker, or localhost:8000 for local dev
API_URL = "http://localhost:8000"
LOGO_PATH = Path(__file__).resolve().parent / "img" / "logo.png"
FAVICON_PATH = Path(__file__).resolve().parent / "img" / "favicon.svg"
st.set_page_config(
page_title="BottleCapAI Text Summarizer",
page_icon=str(FAVICON_PATH) if FAVICON_PATH.exists() else "📝",
layout="centered",
)
# --- Header with Bottlecap logo and title (centered) ---
_, center_col, _ = st.columns([1, 2, 1])
with center_col:
if LOGO_PATH.exists():
st.image(str(LOGO_PATH), width="stretch")
else:
st.caption("(Logo: img/logo.png)")
st.title("Text Summarizer")
# --- Backend health check (sidebar) ---
try:
health = requests.get(f"{API_URL}/health", timeout=5)
if health.status_code == 200:
data = health.json()
device = data.get("device", "unknown")
st.sidebar.success(f"Backend online · {device.upper()}")
else:
st.sidebar.warning(f"Backend returned {health.status_code}")
except requests.exceptions.RequestException:
st.sidebar.error(
"Backend offline — start the FastAPI service to use summarization."
)
# --- Main interface (assignment: text in → summary out) ---
st.sidebar.header("Settings")
max_length = st.sidebar.slider(
"Max summary length (tokens)",
min_value=20,
max_value=150,
value=80,
help="Optional: backend may use this if supported.",
)
DEFAULT_TEXT = (
"The man known as Kazu, or 'King Kazu' by some fans, will stay with the second division side past his 49th birthday."
"Kazuyoshi first played for Brazilian side Santos in 1986, so his deal will see his career span over 30 years."
'"I\'m thankful to the club staff and supporters who always offer me support," said Miura, who scored 55 goals in 89 appearances for Japan.'
'"I\'ll continue to give everything I have and strive," added the former Genoa and Dinamo Zagreb striker.'
"Perhaps unsurprisingly, Miura holds the record as the oldest scorer in Japanese football - a winner in a second division match four months after his 48th birthday."
"He was particularly prolific in guiding Japan to the 1998 World Cup, scoring 14 goals in qualifying, and last played for the national side in 2000."
"His career, which started when he moved to Brazil to play youth football aged 15, is one of the longest in football history."
"Last week ex-England striker Teddy Sheringham registered himself as a player for Stevenage - where he is manager - at the age of 49 but opted out of playing in a local cup competition."
)
input_text = st.text_area(
"Enter English text to summarize",
value=DEFAULT_TEXT,
placeholder="Paste or type the text you want summarized…",
height=200,
)
if "summary_result" not in st.session_state:
st.session_state.summary_result = (
None # {"summary": str, "used_device": str} or None
)
if st.button("Summarize", type="primary"):
if not input_text.strip():
st.warning("Please enter some text first.")
st.session_state.summary_result = None
else:
with st.spinner("Summarizing…"):
try:
payload = {
"text": input_text.strip(),
"max_length": max_length,
}
response = requests.post(
f"{API_URL}/summarize",
json=payload,
timeout=60,
)
if response.status_code == 200:
data = response.json()
summary = data.get("summary", data.get("response", str(data)))
st.session_state.summary_result = {
"summary": summary,
"used_device": data.get("used_device"),
}
elif response.status_code == 507:
st.session_state.summary_result = None
st.error(
"Resource limit exceeded. Try shorter input or lower max length."
)
else:
st.session_state.summary_result = None
st.error(f"Error {response.status_code}: {response.text}")
except requests.exceptions.ConnectionError:
st.session_state.summary_result = None
st.error(
"Could not reach the backend. Start the FastAPI server (e.g. on port 8000)."
)
except Exception as e:
st.session_state.summary_result = None
st.exception(e)
if st.session_state.summary_result:
st.subheader("Summary")
st.write(st.session_state.summary_result["summary"])
if st.session_state.summary_result.get("used_device"):
st.caption(
f"Generated on: {st.session_state.summary_result['used_device'].upper()}"
)
st.divider()
st.caption(
"Created by [Jan Rudolf](https://www.janrudolf.com) for [BottleCap AI](https://www.bottlecapai.com) in 2026"
)