DataAnalysisApp / app.py
LeannJoy's picture
Update app.py
05e78d7 verified
import streamlit as st
import pandas as pd
import io
from utils import query_agent, detect_delimiter
from dotenv import load_dotenv
import os
# Set Streamlit page configuration
st.set_page_config(
page_title="HF Data Analyst Agent",
page_icon="πŸ“Š",
layout="centered"
)
# Load environment variables
load_dotenv()
# Retrieve API Token from .env or environment variables
HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
# --- Custom Styling (Tailwind-like aesthetic using Streamlit's style) ---
st.markdown("""
<style>
.main-header {
font-size: 2.5em;
font-weight: 700;
color: #4B0082; /* Deep Purple */
text-align: center;
margin-bottom: 0.5em;
}
.stButton>button {
background-color: #6A5ACD; /* Slate Blue */
color: white;
border-radius: 12px;
border: 2px solid #483D8B;
padding: 10px 20px;
font-size: 16px;
transition: all 0.3s ease;
}
.stButton>button:hover {
background-color: #483D8B; /* Darker Blue */
color: #E0FFFF;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.uploaded-file-details {
margin-top: 15px;
padding: 15px;
border: 1px solid #DDA0DD; /* Plum */
border-radius: 10px;
background-color: #F8F8FF; /* Ghost White */
}
.analysis-input-box {
margin-top: 20px;
padding: 20px;
border: 2px solid #7B68EE; /* Medium Slate Blue */
border-radius: 15px;
background-color: #E6E6FA; /* Lavender */
}
</style>
""", unsafe_allow_html=True)
# --- Application Title and Setup ---
st.markdown('<div class="main-header">πŸ“Š AI Data Analyst powered by Mistral (HF)</div>', unsafe_allow_html=True)
st.markdown(
"""
Upload a CSV file and ask natural language questions about your data.
This application uses the **Mistral-7B-Instruct-v0.2** model via the Hugging Face Inference Endpoint for fast, accurate analysis.
""",
unsafe_allow_html=True
)
if not HUGGINGFACEHUB_API_TOKEN or HUGGINGFACEHUB_API_TOKEN == "YOUR_HUGGINGFACE_TOKEN_HERE":
st.error("⚠️ **API Token Missing!** Please set your `HUGGINGFACEHUB_API_TOKEN` in the `.env` file or as a secret in your Hugging Face Space.")
else:
# --- File Uploader ---
uploaded_file = st.file_uploader(
"Upload your CSV file",
type=["csv"],
accept_multiple_files=False,
help="Upload a CSV file. The app automatically detects delimiters (like comma, semicolon, etc.)."
)
if uploaded_file is not None:
# Read the file content into bytes
file_content_bytes = uploaded_file.getvalue()
st.markdown('<div class="uploaded-file-details">', unsafe_allow_html=True)
st.subheader("Data Preview (First 5 Rows)")
try:
delimiter = detect_delimiter(file_content_bytes)
# Read the DataFrame just for display
data_io = io.StringIO(file_content_bytes.decode('utf-8'))
df_preview = pd.read_csv(data_io, sep=delimiter)
st.dataframe(df_preview.head())
st.write(f"Detected Delimiter: `{delimiter}`")
st.write(f"Shape: {df_preview.shape[0]} rows, {df_preview.shape[1]} columns")
# --- Analysis Input Box ---
st.markdown('</div>', unsafe_allow_html=True)
st.markdown('<div class="analysis-input-box">', unsafe_allow_html=True)
st.subheader("Ask a question about the data")
query = st.text_input(
"Enter your question here:",
placeholder="e.g., What is the average value of the 'Age' column?",
key="user_query"
)
# --- Analysis Execution ---
if st.button("Run Analysis", key="run_analysis_button") and query:
with st.spinner("Analyzing data... The Mistral Agent is working hard!"):
# Pass the Hugging Face API token to the agent function
response = query_agent(file_content_bytes, query, HUGGINGFACEHUB_API_TOKEN)
st.success("Analysis Complete!")
st.markdown("---")
st.subheader("Agent Response")
st.markdown(f"**{response}**")
elif st.button("Run Analysis", key="run_analysis_button_disabled") and not query:
st.warning("Please enter a question to analyze the data.")
st.markdown('</div>', unsafe_allow_html=True)
except Exception as e:
st.error(f"Could not process the uploaded file or generate preview. Error: {e}")