LeannJoy commited on
Commit
05e78d7
·
verified ·
1 Parent(s): 243528d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -85
app.py CHANGED
@@ -1,103 +1,130 @@
1
  import streamlit as st
 
 
 
2
  from dotenv import load_dotenv
3
  import os
4
- from utils import query_agent
5
- import io
6
 
7
- # Load environment variables (like HUGGINGFACEHUB_API_TOKEN) from .env
 
 
 
 
 
 
 
8
  load_dotenv()
 
 
9
 
10
- def display_data_preview(uploaded_file_bytes):
11
- """Utility function to display a preview of the uploaded data."""
12
- try:
13
- # Use utils' logic to detect delimiter
14
- from utils import detect_csv_delimiter
15
- delimiter = detect_csv_delimiter(uploaded_file_bytes)
16
-
17
- # Reset stream and load for preview
18
- uploaded_file_bytes.seek(0)
19
- df_preview = pd.read_csv(uploaded_file_bytes, sep=delimiter, nrows=5)
20
-
21
- st.subheader("Data Preview (First 5 Rows)")
22
- st.dataframe(df_preview, use_container_width=True)
23
- st.caption(f"File loaded using detected delimiter: `{delimiter}`")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- # Reset stream position again for the main agent function
26
- uploaded_file_bytes.seek(0)
27
- return True
28
- except Exception as e:
29
- st.error(f"Failed to read or preview the CSV file. Please ensure it is a valid CSV format. Error: {e}")
30
- return False
31
 
32
- # --- Main Streamlit Application ---
33
- def main():
34
- """Main function to run the Streamlit application."""
35
- st.set_page_config(
36
- page_title="NL Data Analyst (LLM Powered)",
37
- layout="wide",
38
- initial_sidebar_state="expanded"
39
- )
40
 
41
- st.title("📊 Natural Language Data Analyst")
42
- st.markdown("Upload a CSV file and ask questions about your data using plain English.")
43
-
44
- # Check for API key presence
45
- if not os.getenv("HUGGINGFACEHUB_API_TOKEN"):
46
- st.error("🚨 HUGGINGFACEHUB_API_TOKEN not found. Please ensure your `.env` file is set up correctly.")
47
- return
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
- # --- Sidebar for File Upload ---
50
- with st.sidebar:
51
- st.header("1. Upload CSV File")
52
- uploaded_file = st.file_uploader(
53
- "Choose a CSV file",
54
- type=["csv"],
55
- help="The app automatically detects the delimiter (comma, semicolon, etc.)."
56
- )
57
-
58
- st.markdown("---")
59
- st.subheader("2. Example Queries")
60
- st.info(
61
- """
62
- - What is the average value of the 'Sales' column?
63
- - Show me the top 5 highest 'Profit' rows.
64
- - How many unique values are there in 'Customer Name'?
65
- - Plot a histogram of the 'Age' column.
66
- """
67
- )
68
-
69
- # --- Main Content Area ---
70
  if uploaded_file is not None:
71
- # Convert uploaded file to BytesIO object for multiple reads
72
- uploaded_file_bytes = io.BytesIO(uploaded_file.getvalue())
73
 
74
- # Display file preview
75
- if not display_data_preview(uploaded_file_bytes):
76
- return # Stop execution if preview fails
 
 
 
 
 
 
 
 
 
 
77
 
78
- st.subheader("3. Ask Your Data Question")
79
- user_query = st.text_input(
80
- "Enter your query here (e.g., 'What is the sum of the Price column?'):",
81
- key="user_input_query",
82
- placeholder="E.g., What is the average customer age?"
83
- )
 
 
 
 
84
 
85
- if user_query:
86
- with st.spinner("🤖 Analyzing data with LangChain Agent..."):
87
- try:
88
- # Call the core analysis function
89
- result = query_agent(uploaded_file_bytes, user_query)
90
 
91
  st.success("Analysis Complete!")
92
- st.markdown("### Answer")
93
- st.write(result)
94
-
95
- except Exception as e:
96
- st.error(f"An unexpected error occurred: {e}")
 
97
 
98
- else:
99
- st.info("Please upload a CSV file in the sidebar to begin the data analysis.")
100
 
101
- if __name__ == "__main__":
102
- import pandas as pd
103
- main()
 
1
  import streamlit as st
2
+ import pandas as pd
3
+ import io
4
+ from utils import query_agent, detect_delimiter
5
  from dotenv import load_dotenv
6
  import os
 
 
7
 
8
+ # Set Streamlit page configuration
9
+ st.set_page_config(
10
+ page_title="HF Data Analyst Agent",
11
+ page_icon="📊",
12
+ layout="centered"
13
+ )
14
+
15
+ # Load environment variables
16
  load_dotenv()
17
+ # Retrieve API Token from .env or environment variables
18
+ HUGGINGFACEHUB_API_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
19
 
20
+ # --- Custom Styling (Tailwind-like aesthetic using Streamlit's style) ---
21
+ st.markdown("""
22
+ <style>
23
+ .main-header {
24
+ font-size: 2.5em;
25
+ font-weight: 700;
26
+ color: #4B0082; /* Deep Purple */
27
+ text-align: center;
28
+ margin-bottom: 0.5em;
29
+ }
30
+ .stButton>button {
31
+ background-color: #6A5ACD; /* Slate Blue */
32
+ color: white;
33
+ border-radius: 12px;
34
+ border: 2px solid #483D8B;
35
+ padding: 10px 20px;
36
+ font-size: 16px;
37
+ transition: all 0.3s ease;
38
+ }
39
+ .stButton>button:hover {
40
+ background-color: #483D8B; /* Darker Blue */
41
+ color: #E0FFFF;
42
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
43
+ }
44
+ .uploaded-file-details {
45
+ margin-top: 15px;
46
+ padding: 15px;
47
+ border: 1px solid #DDA0DD; /* Plum */
48
+ border-radius: 10px;
49
+ background-color: #F8F8FF; /* Ghost White */
50
+ }
51
+ .analysis-input-box {
52
+ margin-top: 20px;
53
+ padding: 20px;
54
+ border: 2px solid #7B68EE; /* Medium Slate Blue */
55
+ border-radius: 15px;
56
+ background-color: #E6E6FA; /* Lavender */
57
+ }
58
+ </style>
59
+ """, unsafe_allow_html=True)
60
 
 
 
 
 
 
 
61
 
62
+ # --- Application Title and Setup ---
 
 
 
 
 
 
 
63
 
64
+ st.markdown('<div class="main-header">📊 AI Data Analyst powered by Mistral (HF)</div>', unsafe_allow_html=True)
65
+ st.markdown(
66
+ """
67
+ Upload a CSV file and ask natural language questions about your data.
68
+ This application uses the **Mistral-7B-Instruct-v0.2** model via the Hugging Face Inference Endpoint for fast, accurate analysis.
69
+ """,
70
+ unsafe_allow_html=True
71
+ )
72
+
73
+ if not HUGGINGFACEHUB_API_TOKEN or HUGGINGFACEHUB_API_TOKEN == "YOUR_HUGGINGFACE_TOKEN_HERE":
74
+ st.error("⚠️ **API Token Missing!** Please set your `HUGGINGFACEHUB_API_TOKEN` in the `.env` file or as a secret in your Hugging Face Space.")
75
+ else:
76
+ # --- File Uploader ---
77
+ uploaded_file = st.file_uploader(
78
+ "Upload your CSV file",
79
+ type=["csv"],
80
+ accept_multiple_files=False,
81
+ help="Upload a CSV file. The app automatically detects delimiters (like comma, semicolon, etc.)."
82
+ )
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  if uploaded_file is not None:
85
+ # Read the file content into bytes
86
+ file_content_bytes = uploaded_file.getvalue()
87
 
88
+ st.markdown('<div class="uploaded-file-details">', unsafe_allow_html=True)
89
+ st.subheader("Data Preview (First 5 Rows)")
90
+
91
+ try:
92
+ delimiter = detect_delimiter(file_content_bytes)
93
+
94
+ # Read the DataFrame just for display
95
+ data_io = io.StringIO(file_content_bytes.decode('utf-8'))
96
+ df_preview = pd.read_csv(data_io, sep=delimiter)
97
+
98
+ st.dataframe(df_preview.head())
99
+ st.write(f"Detected Delimiter: `{delimiter}`")
100
+ st.write(f"Shape: {df_preview.shape[0]} rows, {df_preview.shape[1]} columns")
101
 
102
+ # --- Analysis Input Box ---
103
+ st.markdown('</div>', unsafe_allow_html=True)
104
+ st.markdown('<div class="analysis-input-box">', unsafe_allow_html=True)
105
+
106
+ st.subheader("Ask a question about the data")
107
+ query = st.text_input(
108
+ "Enter your question here:",
109
+ placeholder="e.g., What is the average value of the 'Age' column?",
110
+ key="user_query"
111
+ )
112
 
113
+ # --- Analysis Execution ---
114
+ if st.button("Run Analysis", key="run_analysis_button") and query:
115
+ with st.spinner("Analyzing data... The Mistral Agent is working hard!"):
116
+ # Pass the Hugging Face API token to the agent function
117
+ response = query_agent(file_content_bytes, query, HUGGINGFACEHUB_API_TOKEN)
118
 
119
  st.success("Analysis Complete!")
120
+ st.markdown("---")
121
+ st.subheader("Agent Response")
122
+ st.markdown(f"**{response}**")
123
+
124
+ elif st.button("Run Analysis", key="run_analysis_button_disabled") and not query:
125
+ st.warning("Please enter a question to analyze the data.")
126
 
127
+ st.markdown('</div>', unsafe_allow_html=True)
 
128
 
129
+ except Exception as e:
130
+ st.error(f"Could not process the uploaded file or generate preview. Error: {e}")