import os
import io
import tempfile
import logging
from datetime import datetime, timedelta
from typing import Dict, Any
import torch
import librosa
import numpy as np
import pandas as pd
import plotly.express as px
from PIL import Image
import streamlit as st
import streamlit_authenticator as stauth
from streamlit.runtime.uploaded_file_manager import UploadedFile
from transformers import pipeline
from diffusers import StableDiffusionPipeline
import sentry_sdk
from supabase import create_client, Client
import types
# -----------------------
# ConfiguraΓ§Γ£o Inicial
# -----------------------
st.set_page_config(
page_title="AiiT Services - AI Platform",
page_icon="π€",
layout="wide",
initial_sidebar_state="expanded"
)
# Monkey-patch compat (keeps old code working if needed)
st.context = types.SimpleNamespace(cookies={})
# -----------------------
# Estilos
# -----------------------
st.markdown(
"""
""",
unsafe_allow_html=True,
)
# -----------------------
# Logging & Sentry
# -----------------------
sentry_sdk.init(os.getenv("SENTRY_DSN", ""), traces_sample_rate=1.0)
os.makedirs("private", exist_ok=True)
logging.basicConfig(
filename="private/app_errors.log",
level=logging.ERROR,
format="%(asctime)s - %(levelname)s - %(message)s",
)
# -----------------------
# Supabase (optional)
# -----------------------
SUPABASE_URL = os.getenv("SUPABASE_URL")
SUPABASE_KEY = os.getenv("SUPABASE_KEY")
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) if SUPABASE_URL and SUPABASE_KEY else None
# -----------------------
# DB helper functions
# -----------------------
def connect_db():
"""Connects to Supabase (if configured)."""
if not supabase:
return None
return supabase
def init_db():
"""Quick check to ensure table exists (non-blocking)."""
try:
sb = connect_db()
if not sb:
return
_ = sb.table("users").select("username").limit(1).execute()
except Exception as e:
logging.error(f"Error initializing database: {e}")
def load_users_from_db():
"""
Loads users from Supabase and returns credentials structure compatible with streamlit_authenticator.
If Supabase is not configured or fails, returns a default admin user for local dev.
"""
try:
sb = connect_db()
if not sb:
# fallback default (useful for dev)
default_password = stauth.Hasher(["admin"]).generate()[0]
return {
"credentials": {
"usernames": {
"admin": {
"name": "Administrator",
"password": default_password,
"role": "admin",
}
}
},
"cookie": {"name": "ai_app_cookie", "key": "random_key_123", "expiry_days": 30},
"preauthorized": {"emails": []},
}
resp = sb.table("users").select("username, name, password, role").execute()
rows = getattr(resp, "data", []) or []
users = {}
for row in rows:
# Expecting password already hashed (using stauth.Hasher)
users[row["username"]] = {
"name": row.get("name", row["username"]),
"password": row.get("password", ""),
"role": row.get("role", "user"),
}
return {
"credentials": {"usernames": users},
"cookie": {"name": "ai_app_cookie", "key": "random_key_123", "expiry_days": 30},
"preauthorized": {"emails": []},
}
except Exception as e:
logging.error(f"Error loading users: {e}")
sentry_sdk.capture_exception(e)
st.error("β Error loading authentication configuration")
return None
# -----------------------
# Admin panel
# -----------------------
def admin_panel(authenticator):
sb = connect_db()
role = st.session_state.get("role")
if not sb or role != "admin":
st.warning("β οΈ Admins only")
return
st.sidebar.title("βοΈ Admin Panel")
with st.sidebar.expander("β Add User"):
with st.form("add_user_form"):
u = st.text_input("Username")
n = st.text_input("Name")
p = st.text_input("Password", type="password")
r = st.selectbox("Role", ["user", "admin"])
if st.form_submit_button("Add", use_container_width=True):
try:
hashed = stauth.Hasher([p]).generate()[0]
sb.table("users").insert({"username": u, "name": n, "password": hashed, "role": r}).execute()
st.success(f"β
User '{u}' created!")
except Exception as e:
st.error(f"β Error adding user: {str(e)}")
logging.error(f"Add user error: {e}")
with st.sidebar.expander("ποΈ Remove User"):
with st.form("remove_user_form"):
ur = st.text_input("Username to remove")
if st.form_submit_button("Remove", use_container_width=True):
try:
sb.table("users").delete().eq("username", ur).execute()
st.success(f"β
User '{ur}' removed!")
except Exception as e:
st.error(f"β Error removing user: {str(e)}")
logging.error(f"Remove user error: {e}")
with st.sidebar.expander("π Update Role"):
with st.form("update_role_form"):
uu = st.text_input("Username to update")
nr = st.selectbox("New Role", ["user", "admin"])
if st.form_submit_button("Update", use_container_width=True):
try:
sb.table("users").update({"role": nr}).eq("username", uu).execute()
st.success(f"β
Role of '{uu}' changed to '{nr}'")
except Exception as e:
st.error(f"β Error updating role: {str(e)}")
logging.error(f"Update role error: {e}")
st.sidebar.subheader("π₯ Registered Users")
try:
resp = sb.table("users").select("username,name,role").execute()
for row in getattr(resp, "data", []) or []:
st.sidebar.info(f"**{row['username']}** ({row['name']}) - `{row['role']}`")
except Exception as e:
st.error(f"β Error listing users: {str(e)}")
logging.error(f"List users error: {e}")
# -----------------------
# Model caching/loader
# -----------------------
@st.cache_resource(show_spinner="Loading model...")
def load_model(model_key: str):
"""
Loads and returns a Hugging Face pipeline or Diffusers pipeline.
Uses device index (0 for first GPU or -1 for CPU).
"""
device_index = 0 if torch.cuda.is_available() else -1
cache_dir = "model_cache"
os.makedirs(cache_dir, exist_ok=True)
model_loaders = {
"sentiment_analysis": lambda: pipeline("sentiment-analysis", model="cardiffnlp/twitter-roberta-base-sentiment-latest", device=device_index),
"text_classification": lambda: pipeline("text-classification", model="distilbert-base-uncased-finetuned-sst-2-english", device=device_index),
"summarization": lambda: pipeline("summarization", model="facebook/bart-large-cnn", device=device_index),
"question_answering": lambda: pipeline("question-answering", model="deepset/roberta-base-squad2", device=device_index),
"translation": lambda: pipeline("translation", model="Helsinki-NLP/opus-mt-tc-big-en-pt", device=device_index),
"text_generation": lambda: pipeline("text-generation", model="gpt2", device=device_index, pad_token_id=50256),
"ner": lambda: pipeline("ner", model="dbmdz/bert-large-cased-finetuned-conll03-english", device=device_index, aggregation_strategy="simple"),
"image_classification": lambda: pipeline("image-classification", model="google/vit-base-patch16-224", device=device_index),
"object_detection": lambda: pipeline("object-detection", model="facebook/detr-resnet-50", device=device_index),
"image_segmentation": lambda: pipeline("image-segmentation", model="facebook/detr-resnet-50-panoptic", device=device_index),
"facial_recognition": lambda: pipeline("image-classification", model="mo-thecreator/vit-Facial-Expression-Recognition", device=device_index),
"speech_to_text": lambda: pipeline("automatic-speech-recognition", model="openai/whisper-base", device=device_index),
"audio_classification": lambda: pipeline("audio-classification", model="superb/hubert-base-superb-er", device=device_index),
"text_to_image": lambda: StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5", torch_dtype=torch.float32, cache_dir=cache_dir
).to("cuda" if torch.cuda.is_available() else "cpu"),
}
loader = model_loaders.get(model_key)
if not loader:
return None
try:
return loader()
except Exception as e:
logging.error(f"Error loading model {model_key}: {e}")
sentry_sdk.capture_exception(e)
st.error(f"β Error loading model '{model_key}': {str(e)}")
return None
# -----------------------
# File validation & processing
# -----------------------
def validate_audio_file(file: UploadedFile) -> bool:
valid_extensions = [".wav", ".mp3", ".flac", ".m4a"]
return any(file.name.lower().endswith(ext) for ext in valid_extensions)
def validate_image_file(file: UploadedFile) -> bool:
valid_extensions = [".jpg", ".jpeg", ".png", ".bmp"]
if not any(file.name.lower().endswith(ext) for ext in valid_extensions):
return False
try:
Image.open(file).verify()
return True
except Exception:
return False
def process_audio_file(audio_file: UploadedFile):
"""
Saves uploaded audio to a temporary file and returns the path and sample array.
(ASR pipelines usually accept file path or raw array depending on implementation.)
"""
try:
suffix = os.path.splitext(audio_file.name)[1]
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_file:
tmp_file.write(audio_file.read())
tmp_file_path = tmp_file.name
audio_array, sample_rate = librosa.load(tmp_file_path, sr=16000)
return tmp_file_path, audio_array
except Exception as e:
st.error(f"β Error processing audio: {str(e)}")
logging.error(f"Audio processing error: {e}")
sentry_sdk.capture_exception(e)
return None, None
def process_image_file(image_file: UploadedFile):
try:
image = Image.open(image_file)
if image.mode != "RGB":
image = image.convert("RGB")
return image
except Exception as e:
st.error(f"β Error processing image: {str(e)}")
logging.error(f"Image processing error: {e}")
sentry_sdk.capture_exception(e)
return None
# -----------------------
# Result display (single canonical function)
# -----------------------
def display_results(result: Any, model_key: str, input_text: str = None):
st.markdown("
", unsafe_allow_html=True)
if model_key == "summarization":
st.subheader("π Generated Summary")
if input_text:
with st.expander("π Original Text"):
st.write(input_text)
if isinstance(result, list) and result:
st.info(result[0].get("summary_text", ""))
else:
st.info(result)
elif model_key == "translation":
st.subheader("π Translation")
if isinstance(result, list) and result:
st.success(result[0].get("translation_text", result[0].get("generated_text", "")))
else:
st.success(result)
elif model_key in ["sentiment_analysis", "text_classification"]:
st.subheader("π Results")
df = pd.DataFrame(result)
if "score" in df.columns:
df["score_pct"] = df["score"].apply(lambda x: float(x) * 100)
fig = px.bar(df, x="label", y="score_pct", color="label", labels={"score_pct": "Confidence (%)", "label": "Category"}, title="Probability Distribution")
st.plotly_chart(fig, use_container_width=True)
for _, row in df.iterrows():
st.write(f"- **{row['label']}** β {row['score']:.2%}")
elif model_key == "ner":
st.subheader("π Recognized Entities")
entities = []
for entity in result:
entities.append({"Entity": entity.get("word", ""), "Type": entity.get("entity_group", entity.get("entity")), "Confidence": f"{entity.get('score', 0):.2%}"})
st.table(pd.DataFrame(entities))
elif model_key == "text_generation":
st.subheader("π§ Generated Text")
if isinstance(result, list) and result:
st.write(result[0].get("generated_text", ""))
else:
st.write(result)
elif model_key == "image_classification":
st.subheader("π·οΈ Classification")
top5 = result[:5] if isinstance(result, list) else []
labels = [res["label"] for res in top5]
scores = [res["score"] * 100 for res in top5]
fig = px.bar(x=scores, y=labels, orientation="h", labels={"x": "Confidence (%)", "y": "Category"}, title="Top 5 Classifications")
st.plotly_chart(fig, use_container_width=True)
elif model_key == "object_detection":
st.subheader("π¦ Detected Objects")
objects = [{"Object": obj.get("label", ""), "Confidence": f"{obj.get('score', 0):.2%}"} for obj in result]
st.table(pd.DataFrame(objects))
elif model_key == "image_segmentation":
st.subheader("π§© Segmentation")
# result format varies by pipeline - attempt to show masks/images
if isinstance(result, dict) and "segmentation" in result:
st.image(result["segmentation"], caption="Segmentation Mask", use_column_width=True)
elif isinstance(result, list) and result and isinstance(result[0], dict) and "mask" in result[0]:
st.image(result[0]["mask"], caption="Segmentation Mask", use_column_width=True)
else:
st.write(result)
elif model_key == "facial_recognition":
st.subheader("π Facial Recognition")
df = pd.DataFrame(result[:3])
if "score" in df.columns:
df["score_pct"] = df["score"].apply(lambda x: f"{x:.2%}")
st.table(df[["label", "score_pct"]])
elif model_key == "speech_to_text":
st.subheader("π Transcription")
# pipeline returns a dict with 'text' sometimes or list - handle both
if isinstance(result, dict) and "text" in result:
st.success(result["text"])
elif isinstance(result, str):
st.success(result)
else:
st.success(str(result))
elif model_key == "audio_classification":
st.subheader("π§ Audio Classification")
df = pd.DataFrame(result[:3])
if "score" in df.columns:
df["score_pct"] = df["score"].apply(lambda x: f"{x:.2%}")
st.table(df[["label", "score_pct"]])
elif model_key == "text_to_image":
st.subheader("π¨ Generated Image")
# Expecting a list of PIL images or np arrays
if isinstance(result, (list, tuple)):
for idx, img in enumerate(result):
st.image(img, caption=f"Image {idx + 1}", use_column_width=True)
else:
st.image(result, use_column_width=True)
else:
st.write(result)
st.markdown("
", unsafe_allow_html=True)
# -----------------------
# UI Helpers
# -----------------------
def load_branding(username: str):
branding = {
"admin": {"logo": None, "title": "Welcome, Administrator!", "color": "#2c3e50"},
"cliente": {"logo": None, "title": "Welcome, Client!", "color": "#3498db"},
"empresa1": {"logo": None, "title": "Welcome, Company One!", "color": "#e74c3c"},
}
return branding.get(username, {"logo": None, "title": "Welcome!", "color": "#3498db"})
def feature_card(title: str, description: str, icon: str) -> str:
return f"""
{icon}
{title}
{description}
"""
def get_use_cases():
return {
"chatbot_support": {
"title": "Support Chatbot",
"description": "Automated technical support assistant for first-level tickets.",
"benefit": "Faster response and ticket triage.",
},
"visual_audit": {
"title": "Visual Audit",
"description": "Image-based quality inspection and anomaly detection.",
"benefit": "Scale visual QA with automation.",
},
}
# -----------------------
# Model Handlers (UI)
# -----------------------
def handle_text_models(models: Dict[str, Any], model_key: str, model_name: str):
examples = {
"sentiment_analysis": "The delivery was super fast, I loved it!",
"text_classification": "I am dissatisfied with the product",
"summarization": "Company XYZ reported a 15% growth last quarter, mainly due to increased adoption of product A and operational efficiencies.",
"translation": "Our product ensures high performance",
"ner": "Microsoft signed a contract with company XYZ in New York",
"text_generation": "A future where technology connects everyone",
}
col1, col2 = st.columns([0.85, 0.15])
with col1:
input_text = st.text_area(f"Enter text for {model_name.lower()}:", height=200, placeholder="Paste or type your text here...")
with col2:
st.write("")
st.write("")
if st.button("π Example", use_container_width=True):
input_text = examples.get(model_key, "")
advanced_params = {}
if model_key == "summarization":
with st.expander("βοΈ Advanced Parameters"):
advanced_params["max_length"] = st.slider("Max Length", 50, 300, 150)
advanced_params["min_length"] = st.slider("Min Length", 10, 100, 30)
if model_key == "text_generation":
with st.expander("βοΈ Advanced Parameters"):
advanced_params["max_length"] = st.slider("Text Length", 50, 500, 100)
advanced_params["temperature"] = st.slider("Creativity", 0.1, 1.0, 0.7)
advanced_params["num_return_sequences"] = st.slider("Number of outputs", 1, 5, 1)
if st.button(f"π Run {model_name}", type="primary", use_container_width=True):
if input_text and input_text.strip():
with st.spinner("Processing..."):
try:
result = models[model_key](input_text, **advanced_params) if advanced_params else models[model_key](input_text)
display_results(result, model_key, input_text=input_text)
except Exception as e:
st.error(f"β Error processing text: {str(e)}")
logging.error(f"Text model error ({model_key}): {e}")
sentry_sdk.capture_exception(e)
else:
st.warning("β οΈ Please enter valid text")
def handle_qa_model(models: Dict[str, Any], model_key: str):
col1, col2 = st.columns(2)
with col1:
context = st.text_area("Context:", height=200, placeholder="Text containing the information...", value="Product X has a 2-year warranty and can be configured via app in 5 minutes.")
with col2:
question = st.text_area("Question:", height=150, placeholder="Ask your question about the context...", value="What is the warranty period of product X?")
with st.expander("βοΈ Advanced Parameters"):
confidence_threshold = st.slider("Confidence threshold", 0.0, 1.0, 0.5, 0.01)
if st.button("π Run Question and Answer", type="primary", use_container_width=True):
if context.strip() and question.strip():
with st.spinner("Searching for answer..."):
try:
result = models[model_key](question=question, context=context)
score = result.get("score", 0) if isinstance(result, dict) else 0
if score < confidence_threshold:
st.warning(f"β οΈ Low confidence in answer ({score:.2%})")
st.success("π Answer found:")
st.markdown(f"**Question:** {question}")
st.markdown(f"**Answer:** {result.get('answer', str(result))}")
st.markdown(f"**Confidence:** {score:.2%}")
except Exception as e:
st.error(f"β Error processing Q&A: {str(e)}")
logging.error(f"QA model error: {e}")
sentry_sdk.capture_exception(e)
else:
st.warning("β οΈ Please fill in context and question")
def handle_image_models(models: Dict[str, Any], model_key: str, model_name: str):
uploaded_file = st.file_uploader("Upload an image", type=["jpg", "png", "jpeg", "bmp"], help="Supported formats: JPG, PNG, JPEG, BMP")
if uploaded_file:
if not validate_image_file(uploaded_file):
st.error("β οΈ Invalid format or corrupted file")
return
col1, col2 = st.columns(2)
with col1:
st.subheader("πΌοΈ Original Image")
image = process_image_file(uploaded_file)
if image:
st.image(image, use_column_width=True)
with col2:
st.subheader("π Results")
if st.button(f"π Run {model_name}", type="primary", use_container_width=True):
if image:
with st.spinner("Analyzing image..."):
try:
# Some pipelines accept PIL image directly
result = models[model_key](image)
display_results(result, model_key)
except Exception as e:
st.error(f"β Error processing image: {str(e)}")
logging.error(f"Image model error ({model_key}): {e}")
sentry_sdk.capture_exception(e)
def handle_audio_models(models: Dict[str, Any], model_key: str):
model_name = "Audio Transcription" if model_key == "speech_to_text" else "Audio Classification"
uploaded_file = st.file_uploader(f"Upload an audio file for {model_name}", type=["wav", "mp3", "flac", "m4a"], help="Supported formats: WAV, MP3, FLAC, M4A")
if uploaded_file:
if not validate_audio_file(uploaded_file):
st.error("β οΈ Unsupported file format")
return
st.audio(uploaded_file)
if st.button(f"π Run {model_name}", type="primary", use_container_width=True):
with st.spinner("Processing audio..."):
try:
tmp_path, audio_array = process_audio_file(uploaded_file)
if tmp_path:
# Many ASR pipelines accept a path
result = models[model_key](tmp_path)
display_results(result, model_key)
try:
os.unlink(tmp_path)
except Exception:
pass
else:
st.error("β Error preparing audio for model")
except Exception as e:
st.error(f"β Error processing audio: {str(e)}")
logging.error(f"Audio model error ({model_key}): {e}")
sentry_sdk.capture_exception(e)
def handle_generative_models(models: Dict[str, Any], model_key: str):
prompt = st.text_area("Image description:", height=150, placeholder="Describe the image you want to generate...", value="A tropical landscape at sunset")
with st.expander("βοΈ Advanced Parameters"):
cols = st.columns(2)
with cols[0]:
width = st.slider("Width", 256, 1024, 512, 64)
with cols[1]:
height = st.slider("Height", 256, 1024, 512, 64)
num_images = st.slider("Number of images", 1, 4, 1)
guidance_scale = st.slider("Guidance scale", 1.0, 20.0, 7.5)
if st.button("π Generate Image", type="primary", use_container_width=True):
if prompt and prompt.strip():
with st.spinner("Creating image..."):
try:
pipe: StableDiffusionPipeline = models[model_key]
images = []
for _ in range(num_images):
out = pipe(prompt, height=height, width=width, guidance_scale=guidance_scale)
img = out.images[0]
images.append(img)
display_results(images, model_key)
except Exception as e:
st.error(f"β Error generating image: {str(e)}")
logging.error(f"Text-to-image error: {e}")
sentry_sdk.capture_exception(e)
else:
st.warning("β οΈ Please enter a description for the image")
def handle_use_case_demo(models: Dict[str, Any], key: str, case: Dict[str, str]):
st.info(f"Demo for: {case['title']}")
st.write(case["description"])
st.write("Benefit:", case["benefit"])
# Minimal demo: show which models would be used
if key == "chatbot_support":
st.write("- Uses: question_answering, text_generation, ner, translation")
elif key == "visual_audit":
st.write("- Uses: image_classification, object_detection, image_segmentation")
# -----------------------
# Main UI rendering
# -----------------------
def render_login(authenticator):
st.title("AiiT Services - AI Platform")
st.markdown(
"""
Multimodal Artificial Intelligence
Advanced AI solutions for text, image, and audio analysis
""",
unsafe_allow_html=True,
)
cols = st.columns(3)
with cols[0]:
st.markdown(feature_card("Smart Text", "Text analysis, classification, and generation", "π"), unsafe_allow_html=True)
with cols[1]:
st.markdown(feature_card("Computer Vision", "Image and object recognition", "πΌοΈ"), unsafe_allow_html=True)
with cols[2]:
st.markdown(feature_card("Audio Processing", "Transcription and sentiment analysis in audio", "π΅"), unsafe_allow_html=True)
# capture authenticator output and set session state
name, authentication_status, username = authenticator.login("Login", location="main")
st.session_state["name"] = name
st.session_state["authentication_status"] = authentication_status
st.session_state["username"] = username
def render_main_interface(authenticator, config, models: Dict[str, Any]):
name = st.session_state.get("name", "User")
username = st.session_state.get("username", "unknown")
# Determine role from session or config
role = st.session_state.get("role") or config["credentials"]["usernames"].get(username, {}).get("role", "user")
st.session_state["role"] = role
branding = load_branding(username)
st.sidebar.title(f"π€ {name}")
authenticator.logout("Logout", "sidebar")
if role == "admin":
admin_panel(authenticator)
st.title(f"{branding['title']}")
st.markdown(f"", unsafe_allow_html=True)
model_categories = {
"π Text Processing": [
("Sentiment Analysis", "sentiment_analysis"),
("Text Classification", "text_classification"),
("Text Summarization", "summarization"),
("Question Answering", "question_answering"),
("Translation (ENβPT)", "translation"),
("Named Entity Recognition", "ner"),
("Text Generation", "text_generation"),
],
"πΌοΈ Image Processing": [
("Image Classification", "image_classification"),
("Object Detection", "object_detection"),
("Image Segmentation", "image_segmentation"),
("Facial Recognition", "facial_recognition"),
],
"π΅ Audio Processing": [
("Audio Transcription", "speech_to_text"),
("Emotion Classification", "audio_classification"),
],
"β¨ Generative Models": [("Text to Image", "text_to_image")],
}
tab1, tab2 = st.tabs(["π§ Explore Models", "πΌ Use Cases"])
with tab1:
selected_category = st.sidebar.selectbox("Category", list(model_categories.keys()), index=0)
selected_model = st.sidebar.selectbox("Model", [name for name, key in model_categories[selected_category]], index=0)
model_key = next(key for name, key in model_categories[selected_category] if name == selected_model)
st.header(f"{selected_model}")
st.markdown("", unsafe_allow_html=True)
if model_key not in models:
models[model_key] = load_model(model_key)
if not models[model_key]:
st.error("β Model not available")
else:
try:
if model_key in ["sentiment_analysis", "text_classification", "summarization", "translation", "text_generation", "ner"]:
handle_text_models(models, model_key, selected_model)
elif model_key == "question_answering":
handle_qa_model(models, model_key)
elif model_key in ["image_classification", "object_detection", "image_segmentation", "facial_recognition"]:
handle_image_models(models, model_key, selected_model)
elif model_key in ["speech_to_text", "audio_classification"]:
handle_audio_models(models, model_key)
elif model_key == "text_to_image":
handle_generative_models(models, model_key)
except Exception as e:
st.error(f"β Execution error: {str(e)}")
logging.error(f"Handler execution error ({model_key}): {e}")
sentry_sdk.capture_exception(e)
st.markdown("
", unsafe_allow_html=True)
with tab2:
st.header("πΌ Practical Use Cases")
st.markdown("Explore real applications of our AI models")
use_cases = get_use_cases()
cols = st.columns(2)
for idx, (key, case) in enumerate(use_cases.items()):
with cols[idx % 2]:
st.markdown(
f"""
{case['title']}
Description: {case['description']}
Benefit: {case['benefit']}
""",
unsafe_allow_html=True,
)
if st.button("View Demo", key=f"useCase_{key}"):
handle_use_case_demo(models, key, case)
# -----------------------
# Main
# -----------------------
# -----------------------
# Main App
# -----------------------
def main():
init_db()
# Carregar config de utilizadores do Supabase (ou fallback local)
config = load_users_from_db()
if not config:
st.stop()
# Instanciar autenticaΓ§Γ£o (sem o preauthorized!)
authenticator = stauth.Authenticate(
config["credentials"],
config["cookie"]["name"],
config["cookie"]["key"],
config["cookie"]["expiry_days"],
)
# Login
name, auth_status, username = authenticator.login("Login", "main")
if auth_status:
st.sidebar.success(f"β
Logged in as {name}")
st.session_state["role"] = config["credentials"]["usernames"][username].get("role", "user")
# Branding
branding = load_branding(username)
st.title(branding["title"])
# Painel admin (apenas para admins)
if st.session_state["role"] == "admin":
st.sidebar.subheader("βοΈ Admin Panel")
with st.sidebar.expander("Manage Users"):
# Criar novo utilizador
if st.checkbox("Add new user"):
try:
email_of_registered_user, username_of_registered_user, name_of_registered_user = authenticator.register_user(
preauthorization=config.get("preauthorized", []) # <<-- sΓ³ aqui o preauth
)
st.success(f"β
User {username_of_registered_user} registered successfully")
except Exception as e:
st.error(f"β Error registering user: {e}")
# Reset password
if st.checkbox("Reset password"):
try:
if authenticator.reset_password(username):
st.success("β
Password reset successful")
except Exception as e:
st.error(f"β Error resetting password: {e}")
# Update user details
if st.checkbox("Update user details"):
try:
if authenticator.update_user_details(username):
st.success("β
User details updated")
except Exception as e:
st.error(f"β Error updating user: {e}")
# ----------------------------
# Modelos carregados on-demand
# ----------------------------
models = {
key: load_model(key)
for key in [
"sentiment_analysis", "text_classification", "summarization",
"translation", "ner", "text_generation", "question_answering",
"image_classification", "object_detection", "image_segmentation",
"facial_recognition", "speech_to_text", "audio_classification",
"text_to_image"
]
}
# Sidebar de navegaΓ§Γ£o
st.sidebar.title("π Features")
choice = st.sidebar.radio(
"Select a module",
[
"π Text Analysis",
"β Question Answering",
"πΌοΈ Image Analysis",
"π§ Audio Processing",
"π¨ Generative AI"
]
)
if choice == "π Text Analysis":
task = st.selectbox("Select task", [
"Sentiment Analysis", "Text Classification", "Summarization",
"Translation", "Named Entity Recognition", "Text Generation"
])
mapping = {
"Sentiment Analysis": "sentiment_analysis",
"Text Classification": "text_classification",
"Summarization": "summarization",
"Translation": "translation",
"Named Entity Recognition": "ner",
"Text Generation": "text_generation"
}
handle_text_models(models, mapping[task], task)
elif choice == "β Question Answering":
handle_qa_model(models, "question_answering")
elif choice == "πΌοΈ Image Analysis":
task = st.selectbox("Select task", [
"Image Classification", "Object Detection", "Image Segmentation", "Facial Recognition"
])
mapping = {
"Image Classification": "image_classification",
"Object Detection": "object_detection",
"Image Segmentation": "image_segmentation",
"Facial Recognition": "facial_recognition"
}
handle_image_models(models, mapping[task], task)
elif choice == "π§ Audio Processing":
task = st.selectbox("Select task", ["Speech to Text", "Audio Classification"])
mapping = {
"Speech to Text": "speech_to_text",
"Audio Classification": "audio_classification"
}
handle_audio_models(models, mapping[task])
elif choice == "π¨ Generative AI":
handle_generative_models(models, "text_to_image")
# Logout
authenticator.logout("Logout", "sidebar")
elif auth_status is False:
st.error("β Invalid username or password")
else:
st.warning("β οΈ Please login")
if __name__ == "__main__":
main()