entropy25 commited on
Commit
aa80406
Β·
verified Β·
1 Parent(s): 4dc3b76

Upload 7 files

Browse files
Files changed (7) hide show
  1. .dockerignore +50 -50
  2. .gitattributes +35 -35
  3. Dockerfile +39 -39
  4. README.md +10 -10
  5. app.py +475 -467
  6. docker-compose.yml +20 -20
  7. requirements.txt +4 -4
.dockerignore CHANGED
@@ -1,51 +1,51 @@
1
- # Python
2
- __pycache__/
3
- *.py[cod]
4
- *$py.class
5
- *.so
6
- .Python
7
- build/
8
- develop-eggs/
9
- dist/
10
- downloads/
11
- eggs/
12
- .eggs/
13
- lib/
14
- lib64/
15
- parts/
16
- sdist/
17
- var/
18
- wheels/
19
- *.egg-info/
20
- .installed.cfg
21
- *.egg
22
-
23
- # Virtual environments
24
- venv/
25
- env/
26
- ENV/
27
-
28
- # IDE
29
- .vscode/
30
- .idea/
31
- *.swp
32
- *.swo
33
-
34
- # OS
35
- .DS_Store
36
- Thumbs.db
37
-
38
- # Git
39
- .git/
40
- .gitignore
41
-
42
- # Documentation
43
- *.md
44
- docs/
45
-
46
- # Logs
47
- *.log
48
-
49
- # Temporary files
50
- tmp/
51
  temp/
 
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ venv/
25
+ env/
26
+ ENV/
27
+
28
+ # IDE
29
+ .vscode/
30
+ .idea/
31
+ *.swp
32
+ *.swo
33
+
34
+ # OS
35
+ .DS_Store
36
+ Thumbs.db
37
+
38
+ # Git
39
+ .git/
40
+ .gitignore
41
+
42
+ # Documentation
43
+ *.md
44
+ docs/
45
+
46
+ # Logs
47
+ *.log
48
+
49
+ # Temporary files
50
+ tmp/
51
  temp/
.gitattributes CHANGED
@@ -1,35 +1,35 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
Dockerfile CHANGED
@@ -1,40 +1,40 @@
1
- # Use Python 3.9 slim image
2
- FROM python:3.9-slim
3
-
4
- # Set working directory
5
- WORKDIR /app
6
-
7
- # Set environment variables
8
- ENV PYTHONDONTWRITEBYTECODE=1
9
- ENV PYTHONUNBUFFERED=1
10
- ENV STREAMLIT_SERVER_PORT=7860
11
- ENV STREAMLIT_SERVER_ADDRESS=0.0.0.0
12
-
13
- # Install system dependencies
14
- RUN apt-get update && apt-get install -y \
15
- build-essential \
16
- curl \
17
- software-properties-common \
18
- && rm -rf /var/lib/apt/lists/*
19
-
20
- # Copy requirements first for better caching
21
- COPY requirements.txt .
22
-
23
- # Install Python dependencies
24
- RUN pip install --no-cache-dir -r requirements.txt
25
-
26
- # Copy application files
27
- COPY . .
28
-
29
- # Create .streamlit directory and config
30
- RUN mkdir -p .streamlit
31
- COPY .streamlit/config.toml .streamlit/
32
-
33
- # Expose port
34
- EXPOSE 7860
35
-
36
- # Health check
37
- HEALTHCHECK CMD curl --fail http://localhost:7860/_stcore/health
38
-
39
- # Run the application
40
  CMD ["streamlit", "run", "app.py", "--server.port=7860", "--server.address=0.0.0.0"]
 
1
+ # Use Python 3.9 slim image
2
+ FROM python:3.9-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Set environment variables
8
+ ENV PYTHONDONTWRITEBYTECODE=1
9
+ ENV PYTHONUNBUFFERED=1
10
+ ENV STREAMLIT_SERVER_PORT=7860
11
+ ENV STREAMLIT_SERVER_ADDRESS=0.0.0.0
12
+
13
+ # Install system dependencies
14
+ RUN apt-get update && apt-get install -y \
15
+ build-essential \
16
+ curl \
17
+ software-properties-common \
18
+ && rm -rf /var/lib/apt/lists/*
19
+
20
+ # Copy requirements first for better caching
21
+ COPY requirements.txt .
22
+
23
+ # Install Python dependencies
24
+ RUN pip install --no-cache-dir -r requirements.txt
25
+
26
+ # Copy application files
27
+ COPY . .
28
+
29
+ # Create .streamlit directory and config
30
+ RUN mkdir -p .streamlit
31
+ COPY .streamlit/config.toml .streamlit/
32
+
33
+ # Expose port
34
+ EXPOSE 7860
35
+
36
+ # Health check
37
+ HEALTHCHECK CMD curl --fail http://localhost:7860/_stcore/health
38
+
39
+ # Run the application
40
  CMD ["streamlit", "run", "app.py", "--server.port=7860", "--server.address=0.0.0.0"]
README.md CHANGED
@@ -1,10 +1,10 @@
1
- ---
2
- title: Report
3
- emoji: 😻
4
- colorFrom: blue
5
- colorTo: indigo
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ ---
2
+ title: Report
3
+ emoji: 😻
4
+ colorFrom: blue
5
+ colorTo: indigo
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -1,468 +1,476 @@
1
- import streamlit as st
2
- import pandas as pd
3
- import plotly.express as px
4
- import plotly.graph_objects as go
5
- from plotly.subplots import make_subplots
6
- import numpy as np
7
- from datetime import datetime
8
- import io
9
-
10
- # Initialize session state
11
- if 'data_loaded' not in st.session_state:
12
- st.session_state.data_loaded = False
13
- if 'analyzer' not in st.session_state:
14
- st.session_state.analyzer = None
15
-
16
- # Page configuration
17
- st.set_page_config(
18
- page_title="πŸ“Š FinanceGPT Analyzer",
19
- page_icon="πŸ“Š",
20
- layout="wide",
21
- initial_sidebar_state="expanded"
22
- )
23
-
24
- # Custom CSS for better styling
25
- st.markdown("""
26
- <style>
27
- .metric-card {
28
- background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
29
- padding: 1rem;
30
- border-radius: 10px;
31
- color: white;
32
- text-align: center;
33
- margin: 0.5rem 0;
34
- }
35
- .insight-box {
36
- background: #f8f9fa;
37
- padding: 1rem;
38
- border-left: 4px solid #007bff;
39
- border-radius: 5px;
40
- margin: 1rem 0;
41
- }
42
- .warning-box {
43
- background: #fff3cd;
44
- padding: 1rem;
45
- border-left: 4px solid #ffc107;
46
- border-radius: 5px;
47
- margin: 1rem 0;
48
- }
49
- </style>
50
- """, unsafe_allow_html=True)
51
-
52
- class FinanceAnalyzer:
53
- def __init__(self):
54
- self.data = None
55
- self.processed_data = {}
56
-
57
- def load_sample_data(self):
58
- """Load sample financial data"""
59
- sample_data = {
60
- 'Year': [2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024,
61
- 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023],
62
- 'Statement_Type': ['Income Statement'] * 10 + ['Income Statement'] * 10,
63
- 'Account_Name_Norwegian': ['Salgsinntekt', 'Varekostnad', 'Bruttoresultat', 'LΓΈnnskostnad',
64
- 'Andre driftskostnader', 'Driftsresultat', 'Finansinntekter',
65
- 'Finanskostnader', 'Ordinært resultat før skatt', 'Årsresultat'] * 2,
66
- 'Account_Name_English': ['Sales Revenue', 'Cost of Goods Sold', 'Gross Profit', 'Salary Costs',
67
- 'Other Operating Expenses', 'Operating Result', 'Financial Income',
68
- 'Financial Expenses', 'Profit Before Tax', 'Net Profit'] * 2,
69
- '2024_Amount_NOK': [25107008, -15064205, 10042803, -3521456, -1987234, 4534113, 123456,
70
- -234567, 4422002, 3537602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
71
- '2023_Amount_NOK': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4891891, -2934535, 1957356, -1234567,
72
- -654321, 68468, 45678, -123456, -9310, -7448]
73
- }
74
- return pd.DataFrame(sample_data)
75
-
76
- def process_financial_data(self, df):
77
- """Process uploaded financial data"""
78
- self.data = df
79
-
80
- # Create pivot tables for easier analysis
81
- income_2024 = df[df['Year'] == 2024]['2024_Amount_NOK'].values
82
- income_2023 = df[df['Year'] == 2023]['2023_Amount_NOK'].values
83
- accounts = df[df['Year'] == 2024]['Account_Name_English'].values
84
-
85
- self.processed_data = {
86
- 'revenue_2024': income_2024[0] if len(income_2024) > 0 else 0,
87
- 'revenue_2023': income_2023[0] if len(income_2023) > 0 else 0,
88
- 'net_profit_2024': income_2024[9] if len(income_2024) > 9 else 0,
89
- 'net_profit_2023': income_2023[9] if len(income_2023) > 9 else 0,
90
- 'cogs_2024': abs(income_2024[1]) if len(income_2024) > 1 else 0,
91
- 'cogs_2023': abs(income_2023[1]) if len(income_2023) > 1 else 0,
92
- 'operating_profit_2024': income_2024[5] if len(income_2024) > 5 else 0,
93
- 'operating_profit_2023': income_2023[5] if len(income_2023) > 5 else 0,
94
- }
95
-
96
- def calculate_metrics(self):
97
- """Calculate key financial metrics"""
98
- if not self.processed_data:
99
- return {}
100
-
101
- data = self.processed_data
102
-
103
- # Growth rates
104
- revenue_growth = ((data['revenue_2024'] - data['revenue_2023']) /
105
- abs(data['revenue_2023']) * 100) if data['revenue_2023'] != 0 else 0
106
-
107
- # Profitability ratios
108
- gross_margin_2024 = ((data['revenue_2024'] - data['cogs_2024']) /
109
- data['revenue_2024'] * 100) if data['revenue_2024'] != 0 else 0
110
- net_margin_2024 = (data['net_profit_2024'] / data['revenue_2024'] * 100) if data['revenue_2024'] != 0 else 0
111
-
112
- return {
113
- 'revenue_growth': revenue_growth,
114
- 'gross_margin_2024': gross_margin_2024,
115
- 'net_margin_2024': net_margin_2024,
116
- 'revenue_2024_m': data['revenue_2024'] / 1000000,
117
- 'net_profit_2024_m': data['net_profit_2024'] / 1000000,
118
- }
119
-
120
- def create_revenue_trend_chart(self):
121
- """Create revenue trend visualization"""
122
- if not self.processed_data:
123
- return go.Figure()
124
-
125
- fig = go.Figure()
126
-
127
- years = [2023, 2024]
128
- revenues = [self.processed_data['revenue_2023']/1000000,
129
- self.processed_data['revenue_2024']/1000000]
130
- net_profits = [self.processed_data['net_profit_2023']/1000000,
131
- self.processed_data['net_profit_2024']/1000000]
132
-
133
- fig.add_trace(go.Scatter(x=years, y=revenues, mode='lines+markers',
134
- name='Revenue (M NOK)', line=dict(color='#1f77b4', width=3)))
135
- fig.add_trace(go.Scatter(x=years, y=net_profits, mode='lines+markers',
136
- name='Net Profit (M NOK)', line=dict(color='#ff7f0e', width=3)))
137
-
138
- fig.update_layout(title='Revenue vs Profit Trend', xaxis_title='Year',
139
- yaxis_title='Amount (M NOK)', height=400)
140
- return fig
141
-
142
- def create_financial_health_radar(self):
143
- """Create financial health radar chart"""
144
- metrics = self.calculate_metrics()
145
-
146
- categories = ['Revenue Growth', 'Gross Margin', 'Net Margin', 'Profitability', 'Efficiency']
147
- values = [
148
- min(metrics.get('revenue_growth', 0) / 5, 100), # Scale revenue growth
149
- metrics.get('gross_margin_2024', 0),
150
- max(metrics.get('net_margin_2024', 0), 0),
151
- 70, # Sample value
152
- 65 # Sample value
153
- ]
154
-
155
- fig = go.Figure()
156
- fig.add_trace(go.Scatterpolar(
157
- r=values,
158
- theta=categories,
159
- fill='toself',
160
- name='Financial Health'
161
- ))
162
-
163
- fig.update_layout(
164
- polar=dict(
165
- radialaxis=dict(visible=True, range=[0, 100])
166
- ),
167
- title="Financial Health Score",
168
- height=400
169
- )
170
- return fig
171
-
172
- def main():
173
- st.title("πŸ“Š FinanceGPT Analyzer")
174
- st.markdown("### Professional Financial Analysis Dashboard")
175
-
176
- # Initialize analyzer
177
- if st.session_state.analyzer is None:
178
- st.session_state.analyzer = FinanceAnalyzer()
179
-
180
- analyzer = st.session_state.analyzer
181
-
182
- # Sidebar navigation
183
- with st.sidebar:
184
- st.header("Navigation")
185
- page = st.selectbox("Choose Analysis Page", [
186
- "🏠 Dashboard",
187
- "πŸ’° Income Analysis",
188
- "πŸ›οΈ Balance Sheet Analysis",
189
- "πŸ’Έ Cash Flow Analysis",
190
- "πŸ“Š Financial Ratios Hub",
191
- "πŸ€– AI Finance Assistant"
192
- ])
193
-
194
- st.header("Data Upload")
195
- uploaded_file = st.file_uploader("Upload CSV file", type=['csv'])
196
-
197
- if st.button("Use Sample Data"):
198
- analyzer.data = analyzer.load_sample_data()
199
- analyzer.process_financial_data(analyzer.data)
200
- st.session_state.data_loaded = True
201
- st.success("Sample data loaded!")
202
- st.rerun()
203
-
204
- if uploaded_file is not None:
205
- try:
206
- df = pd.read_csv(uploaded_file)
207
- analyzer.data = df
208
- analyzer.process_financial_data(df)
209
- st.session_state.data_loaded = True
210
- st.success("Data uploaded successfully!")
211
- st.rerun()
212
- except Exception as e:
213
- st.error(f"Error loading file: {e}")
214
-
215
- # Main content based on selected page
216
- if page == "🏠 Dashboard":
217
- dashboard_page(analyzer)
218
- elif page == "πŸ’° Income Analysis":
219
- income_analysis_page(analyzer)
220
- elif page == "πŸ›οΈ Balance Sheet Analysis":
221
- balance_sheet_page(analyzer)
222
- elif page == "πŸ’Έ Cash Flow Analysis":
223
- cash_flow_page(analyzer)
224
- elif page == "πŸ“Š Financial Ratios Hub":
225
- ratios_page(analyzer)
226
- elif page == "πŸ€– AI Finance Assistant":
227
- ai_assistant_page(analyzer)
228
-
229
- def dashboard_page(analyzer):
230
- """Main dashboard page"""
231
- st.header("πŸ“Š Financial Dashboard")
232
-
233
- if analyzer.data is None:
234
- st.warning("Please upload data or use sample data to begin analysis.")
235
- return
236
-
237
- metrics = analyzer.calculate_metrics()
238
-
239
- # Key metrics cards
240
- col1, col2, col3, col4 = st.columns(4)
241
-
242
- with col1:
243
- st.markdown("""
244
- <div class="metric-card">
245
- <h3>πŸ’° Revenue</h3>
246
- <h2>{:.1f}M NOK</h2>
247
- <p>+{:.0f}% πŸ”₯</p>
248
- </div>
249
- """.format(metrics.get('revenue_2024_m', 0), metrics.get('revenue_growth', 0)),
250
- unsafe_allow_html=True)
251
-
252
- with col2:
253
- st.markdown("""
254
- <div class="metric-card">
255
- <h3>πŸ“ˆ Net Profit</h3>
256
- <h2>{:.1f}M NOK</h2>
257
- <p>Profitable βœ…</p>
258
- </div>
259
- """.format(metrics.get('net_profit_2024_m', 0)), unsafe_allow_html=True)
260
-
261
- with col3:
262
- st.markdown("""
263
- <div class="metric-card">
264
- <h3>πŸ“Š Gross Margin</h3>
265
- <h2>{:.1f}%</h2>
266
- <p>Healthy πŸ’ͺ</p>
267
- </div>
268
- """.format(metrics.get('gross_margin_2024', 0)), unsafe_allow_html=True)
269
-
270
- with col4:
271
- st.markdown("""
272
- <div class="metric-card">
273
- <h3>🎯 Net Margin</h3>
274
- <h2>{:.1f}%</h2>
275
- <p>Strong πŸ“ˆ</p>
276
- </div>
277
- """.format(metrics.get('net_margin_2024', 0)), unsafe_allow_html=True)
278
-
279
- # Charts section
280
- col1, col2 = st.columns(2)
281
-
282
- with col1:
283
- st.plotly_chart(analyzer.create_revenue_trend_chart(), use_container_width=True)
284
-
285
- with col2:
286
- st.plotly_chart(analyzer.create_financial_health_radar(), use_container_width=True)
287
-
288
- # Quick insights
289
- st.markdown("""
290
- <div class="insight-box">
291
- <h4>🎯 Quick Insights</h4>
292
- <ul>
293
- <li>βœ… Revenue growth of {:.0f}% indicates explosive business development</li>
294
- <li>πŸ’‘ Net profit margin of {:.1f}% shows strong profitability</li>
295
- <li>πŸ“ˆ Gross margin of {:.1f}% demonstrates healthy pricing power</li>
296
- </ul>
297
- </div>
298
- """.format(
299
- metrics.get('revenue_growth', 0),
300
- metrics.get('net_margin_2024', 0),
301
- metrics.get('gross_margin_2024', 0)
302
- ), unsafe_allow_html=True)
303
-
304
- def income_analysis_page(analyzer):
305
- """Income statement analysis page"""
306
- st.header("πŸ’° Income Analysis")
307
-
308
- if analyzer.data is None:
309
- st.warning("Please upload data to begin analysis.")
310
- return
311
-
312
- # Revenue analysis
313
- st.subheader("πŸ“ˆ Revenue Trend Analysis")
314
- st.plotly_chart(analyzer.create_revenue_trend_chart(), use_container_width=True)
315
-
316
- # Cost structure
317
- st.subheader("πŸ₯§ Cost Structure Analysis")
318
- if analyzer.processed_data:
319
- data = analyzer.processed_data
320
- costs = ['Cost of Goods Sold', 'Operating Expenses', 'Financial Expenses']
321
- values = [data['cogs_2024'], 2000000, 234567] # Sample values
322
-
323
- fig = px.pie(values=values, names=costs, title="Cost Breakdown 2024")
324
- st.plotly_chart(fig, use_container_width=True)
325
-
326
- # Profitability metrics
327
- st.subheader("πŸ“Š Profitability Indicators")
328
- metrics = analyzer.calculate_metrics()
329
-
330
- col1, col2, col3 = st.columns(3)
331
- with col1:
332
- st.metric("Gross Margin", f"{metrics.get('gross_margin_2024', 0):.1f}%")
333
- with col2:
334
- st.metric("Net Margin", f"{metrics.get('net_margin_2024', 0):.1f}%")
335
- with col3:
336
- st.metric("Revenue Growth", f"{metrics.get('revenue_growth', 0):.1f}%")
337
-
338
- def balance_sheet_page(analyzer):
339
- """Balance sheet analysis page"""
340
- st.header("πŸ›οΈ Balance Sheet Analysis")
341
-
342
- if analyzer.data is None:
343
- st.warning("Please upload balance sheet data to begin analysis.")
344
- return
345
-
346
- st.info("Balance sheet analysis requires additional data. Please upload complete financial statements.")
347
-
348
- # Sample asset structure chart
349
- assets = ['Current Assets', 'Fixed Assets', 'Intangible Assets']
350
- values = [45, 35, 20]
351
-
352
- fig = px.pie(values=values, names=assets, title="Asset Structure")
353
- st.plotly_chart(fig, use_container_width=True)
354
-
355
- def cash_flow_page(analyzer):
356
- """Cash flow analysis page"""
357
- st.header("πŸ’Έ Cash Flow Analysis")
358
-
359
- if analyzer.data is None:
360
- st.warning("Please upload cash flow data to begin analysis.")
361
- return
362
-
363
- st.info("Cash flow analysis requires additional data. Please upload complete cash flow statements.")
364
-
365
- # Sample cash flow chart
366
- categories = ['Operating CF', 'Investing CF', 'Financing CF']
367
- values = [5000000, -2000000, -1000000]
368
-
369
- fig = go.Figure(go.Waterfall(
370
- name="Cash Flow", orientation="v",
371
- measure=["relative", "relative", "relative"],
372
- x=categories, y=values,
373
- text=[f"{v/1000000:.1f}M" for v in values]
374
- ))
375
- fig.update_layout(title="Cash Flow Waterfall")
376
- st.plotly_chart(fig, use_container_width=True)
377
-
378
- def ratios_page(analyzer):
379
- """Financial ratios analysis page"""
380
- st.header("πŸ“Š Financial Ratios Hub")
381
-
382
- if analyzer.data is None:
383
- st.warning("Please upload data to calculate ratios.")
384
- return
385
-
386
- # Ratio categories
387
- col1, col2, col3, col4 = st.columns(4)
388
-
389
- with col1:
390
- if st.button("Profitability"):
391
- st.session_state.ratio_category = "profitability"
392
- with col2:
393
- if st.button("Liquidity"):
394
- st.session_state.ratio_category = "liquidity"
395
- with col3:
396
- if st.button("Efficiency"):
397
- st.session_state.ratio_category = "efficiency"
398
- with col4:
399
- if st.button("Growth"):
400
- st.session_state.ratio_category = "growth"
401
-
402
- # Display ratios based on selection
403
- metrics = analyzer.calculate_metrics()
404
-
405
- st.subheader("Key Financial Ratios")
406
-
407
- col1, col2, col3 = st.columns(3)
408
- with col1:
409
- st.metric("Gross Profit Margin", f"{metrics.get('gross_margin_2024', 0):.1f}%", "A+")
410
- with col2:
411
- st.metric("Net Profit Margin", f"{metrics.get('net_margin_2024', 0):.1f}%", "A")
412
- with col3:
413
- st.metric("Revenue Growth", f"{metrics.get('revenue_growth', 0):.1f}%", "A+")
414
-
415
- def ai_assistant_page(analyzer):
416
- """AI finance assistant page"""
417
- st.header("πŸ€– AI Finance Assistant")
418
-
419
- if analyzer.data is None:
420
- st.warning("Please upload data to enable AI analysis.")
421
- return
422
-
423
- # Chat interface
424
- st.subheader("πŸ’¬ Ask Your Financial Questions")
425
-
426
- # Predefined questions
427
- col1, col2 = st.columns(2)
428
- with col1:
429
- if st.button("Analyze my financial health"):
430
- st.session_state.ai_query = "financial_health"
431
- if st.button("Find the biggest risks"):
432
- st.session_state.ai_query = "risks"
433
-
434
- with col2:
435
- if st.button("Give investment advice"):
436
- st.session_state.ai_query = "investment"
437
- if st.button("Create improvement plan"):
438
- st.session_state.ai_query = "improvement"
439
-
440
- # Text input for custom questions
441
- user_question = st.text_input("Or ask your own question:")
442
-
443
- if user_question or 'ai_query' in st.session_state:
444
- metrics = analyzer.calculate_metrics()
445
-
446
- # Simple AI-like responses based on data
447
- if user_question or st.session_state.get('ai_query') == 'financial_health':
448
- st.markdown("""
449
- <div class="insight-box">
450
- <h4>🎯 Financial Health Analysis</h4>
451
- <p>Based on your financial data:</p>
452
- <ul>
453
- <li>βœ… <strong>Revenue Growth:</strong> {:.0f}% growth shows strong market performance</li>
454
- <li>βœ… <strong>Profitability:</strong> {:.1f}% net margin indicates healthy operations</li>
455
- <li>πŸ“Š <strong>Overall Rating:</strong> A- (Strong financial position)</li>
456
- </ul>
457
- </div>
458
- """.format(
459
- metrics.get('revenue_growth', 0),
460
- metrics.get('net_margin_2024', 0)
461
- ), unsafe_allow_html=True)
462
-
463
- # Clear the session state
464
- if 'ai_query' in st.session_state:
465
- del st.session_state.ai_query
466
-
467
- if __name__ == "__main__":
 
 
 
 
 
 
 
 
468
  main()
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import plotly.express as px
4
+ import plotly.graph_objects as go
5
+ from plotly.subplots import make_subplots
6
+ import numpy as np
7
+ from datetime import datetime
8
+ import io
9
+
10
+ # Initialize session state
11
+ if 'data_loaded' not in st.session_state:
12
+ st.session_state.data_loaded = False
13
+ if 'analyzer' not in st.session_state:
14
+ st.session_state.analyzer = None
15
+
16
+ # Page configuration
17
+ st.set_page_config(
18
+ page_title="πŸ“Š FinanceGPT Analyzer",
19
+ page_icon="πŸ“Š",
20
+ layout="wide",
21
+ initial_sidebar_state="expanded"
22
+ )
23
+
24
+ # Custom CSS for better styling
25
+ st.markdown("""
26
+ <style>
27
+ .metric-card {
28
+ background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
29
+ padding: 1rem;
30
+ border-radius: 10px;
31
+ color: white;
32
+ text-align: center;
33
+ margin: 0.5rem 0;
34
+ }
35
+ .insight-box {
36
+ background: #f8f9fa;
37
+ padding: 1rem;
38
+ border-left: 4px solid #007bff;
39
+ border-radius: 5px;
40
+ margin: 1rem 0;
41
+ }
42
+ .warning-box {
43
+ background: #fff3cd;
44
+ padding: 1rem;
45
+ border-left: 4px solid #ffc107;
46
+ border-radius: 5px;
47
+ margin: 1rem 0;
48
+ }
49
+ </style>
50
+ """, unsafe_allow_html=True)
51
+
52
+ class FinanceAnalyzer:
53
+ def __init__(self):
54
+ self.data = None
55
+ self.processed_data = {}
56
+
57
+ def load_sample_data(self):
58
+ """Load sample financial data"""
59
+ sample_data = {
60
+ 'Year': [2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024, 2024,
61
+ 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023, 2023],
62
+ 'Statement_Type': ['Income Statement'] * 10 + ['Income Statement'] * 10,
63
+ 'Account_Name_Norwegian': ['Salgsinntekt', 'Varekostnad', 'Bruttoresultat', 'LΓΈnnskostnad',
64
+ 'Andre driftskostnader', 'Driftsresultat', 'Finansinntekter',
65
+ 'Finanskostnader', 'Ordinært resultat før skatt', 'Årsresultat'] * 2,
66
+ 'Account_Name_English': ['Sales Revenue', 'Cost of Goods Sold', 'Gross Profit', 'Salary Costs',
67
+ 'Other Operating Expenses', 'Operating Result', 'Financial Income',
68
+ 'Financial Expenses', 'Profit Before Tax', 'Net Profit'] * 2,
69
+ '2024_Amount_NOK': [25107008, -15064205, 10042803, -3521456, -1987234, 4534113, 123456,
70
+ -234567, 4422002, 3537602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
71
+ '2023_Amount_NOK': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4891891, -2934535, 1957356, -1234567,
72
+ -654321, 68468, 45678, -123456, -9310, -7448]
73
+ }
74
+ return pd.DataFrame(sample_data)
75
+
76
+ def process_financial_data(self, df):
77
+ """Process uploaded financial data"""
78
+ self.data = df
79
+
80
+ # Create pivot tables for easier analysis
81
+ income_2024 = df[df['Year'] == 2024]['2024_Amount_NOK'].values
82
+ income_2023 = df[df['Year'] == 2023]['2023_Amount_NOK'].values
83
+ accounts = df[df['Year'] == 2024]['Account_Name_English'].values
84
+
85
+ self.processed_data = {
86
+ 'revenue_2024': income_2024[0] if len(income_2024) > 0 else 0,
87
+ 'revenue_2023': income_2023[0] if len(income_2023) > 0 else 0,
88
+ 'net_profit_2024': income_2024[9] if len(income_2024) > 9 else 0,
89
+ 'net_profit_2023': income_2023[9] if len(income_2023) > 9 else 0,
90
+ 'cogs_2024': abs(income_2024[1]) if len(income_2024) > 1 else 0,
91
+ 'cogs_2023': abs(income_2023[1]) if len(income_2023) > 1 else 0,
92
+ 'operating_profit_2024': income_2024[5] if len(income_2024) > 5 else 0,
93
+ 'operating_profit_2023': income_2023[5] if len(income_2023) > 5 else 0,
94
+ }
95
+
96
+ def calculate_metrics(self):
97
+ """Calculate key financial metrics"""
98
+ if not self.processed_data:
99
+ return {}
100
+
101
+ data = self.processed_data
102
+
103
+ # Growth rates
104
+ revenue_growth = ((data['revenue_2024'] - data['revenue_2023']) /
105
+ abs(data['revenue_2023']) * 100) if data['revenue_2023'] != 0 else 0
106
+
107
+ # Profitability ratios
108
+ gross_margin_2024 = ((data['revenue_2024'] - data['cogs_2024']) /
109
+ data['revenue_2024'] * 100) if data['revenue_2024'] != 0 else 0
110
+ net_margin_2024 = (data['net_profit_2024'] / data['revenue_2024'] * 100) if data['revenue_2024'] != 0 else 0
111
+
112
+ return {
113
+ 'revenue_growth': revenue_growth,
114
+ 'gross_margin_2024': gross_margin_2024,
115
+ 'net_margin_2024': net_margin_2024,
116
+ 'revenue_2024_m': data['revenue_2024'] / 1000000,
117
+ 'net_profit_2024_m': data['net_profit_2024'] / 1000000,
118
+ }
119
+
120
+ def create_revenue_trend_chart(self):
121
+ """Create revenue trend visualization"""
122
+ if not self.processed_data:
123
+ return go.Figure().add_annotation(text="No data available",
124
+ xref="paper", yref="paper",
125
+ x=0.5, y=0.5, showarrow=False)
126
+
127
+ fig = go.Figure()
128
+
129
+ years = [2023, 2024]
130
+ revenues = [self.processed_data['revenue_2023']/1000000,
131
+ self.processed_data['revenue_2024']/1000000]
132
+ net_profits = [self.processed_data['net_profit_2023']/1000000,
133
+ self.processed_data['net_profit_2024']/1000000]
134
+
135
+ fig.add_trace(go.Scatter(x=years, y=revenues, mode='lines+markers',
136
+ name='Revenue (M NOK)', line=dict(color='#1f77b4', width=3)))
137
+ fig.add_trace(go.Scatter(x=years, y=net_profits, mode='lines+markers',
138
+ name='Net Profit (M NOK)', line=dict(color='#ff7f0e', width=3)))
139
+
140
+ fig.update_layout(title='Revenue vs Profit Trend', xaxis_title='Year',
141
+ yaxis_title='Amount (M NOK)', height=400)
142
+ return fig
143
+
144
+ def create_financial_health_radar(self):
145
+ """Create financial health radar chart"""
146
+ metrics = self.calculate_metrics()
147
+
148
+ categories = ['Revenue Growth', 'Gross Margin', 'Net Margin', 'Profitability', 'Efficiency']
149
+ values = [
150
+ min(metrics.get('revenue_growth', 0) / 5, 100), # Scale revenue growth
151
+ metrics.get('gross_margin_2024', 0),
152
+ max(metrics.get('net_margin_2024', 0), 0),
153
+ 70, # Sample value
154
+ 65 # Sample value
155
+ ]
156
+
157
+ fig = go.Figure()
158
+ fig.add_trace(go.Scatterpolar(
159
+ r=values,
160
+ theta=categories,
161
+ fill='toself',
162
+ name='Financial Health'
163
+ ))
164
+
165
+ fig.update_layout(
166
+ polar=dict(
167
+ radialaxis=dict(visible=True, range=[0, 100])
168
+ ),
169
+ title="Financial Health Score",
170
+ height=400
171
+ )
172
+ return fig
173
+
174
+ def main():
175
+ st.title("πŸ“Š FinanceGPT Analyzer")
176
+ st.markdown("### Professional Financial Analysis Dashboard")
177
+
178
+ # Initialize analyzer
179
+ if st.session_state.analyzer is None:
180
+ st.session_state.analyzer = FinanceAnalyzer()
181
+
182
+ analyzer = st.session_state.analyzer
183
+
184
+ # Sidebar navigation
185
+ with st.sidebar:
186
+ st.header("Navigation")
187
+ page = st.selectbox("Choose Analysis Page", [
188
+ "🏠 Dashboard",
189
+ "πŸ’° Income Analysis",
190
+ "πŸ›οΈ Balance Sheet Analysis",
191
+ "πŸ’Έ Cash Flow Analysis",
192
+ "πŸ“Š Financial Ratios Hub",
193
+ "πŸ€– AI Finance Assistant"
194
+ ])
195
+
196
+ st.header("Data Upload")
197
+ uploaded_file = st.file_uploader("Upload CSV file", type=['csv'])
198
+
199
+ if st.button("Use Sample Data"):
200
+ analyzer.data = analyzer.load_sample_data()
201
+ analyzer.process_financial_data(analyzer.data)
202
+ st.session_state.data_loaded = True
203
+ st.success("Sample data loaded!")
204
+ st.rerun()
205
+
206
+ if uploaded_file is not None:
207
+ try:
208
+ df = pd.read_csv(uploaded_file)
209
+ analyzer.data = df
210
+ analyzer.process_financial_data(df)
211
+ st.session_state.data_loaded = True
212
+ st.success("Data uploaded successfully!")
213
+ st.rerun()
214
+ except Exception as e:
215
+ st.error(f"Error loading file: {e}")
216
+
217
+ # Main content based on selected page
218
+ if page == "🏠 Dashboard":
219
+ dashboard_page(analyzer)
220
+ elif page == "πŸ’° Income Analysis":
221
+ income_analysis_page(analyzer)
222
+ elif page == "πŸ›οΈ Balance Sheet Analysis":
223
+ balance_sheet_page(analyzer)
224
+ elif page == "πŸ’Έ Cash Flow Analysis":
225
+ cash_flow_page(analyzer)
226
+ elif page == "πŸ“Š Financial Ratios Hub":
227
+ ratios_page(analyzer)
228
+ elif page == "πŸ€– AI Finance Assistant":
229
+ ai_assistant_page(analyzer)
230
+
231
+ def dashboard_page(analyzer):
232
+ """Main dashboard page"""
233
+ st.header("πŸ“Š Financial Dashboard")
234
+
235
+ if analyzer.data is None or not st.session_state.data_loaded:
236
+ st.warning("Please upload data or use sample data to begin analysis.")
237
+ st.info("πŸ‘ˆ Use the sidebar to upload your CSV file or click 'Use Sample Data'")
238
+ return
239
+
240
+ metrics = analyzer.calculate_metrics()
241
+
242
+ # Key metrics cards
243
+ col1, col2, col3, col4 = st.columns(4)
244
+
245
+ with col1:
246
+ st.markdown("""
247
+ <div class="metric-card">
248
+ <h3>πŸ’° Revenue</h3>
249
+ <h2>{:.1f}M NOK</h2>
250
+ <p>+{:.0f}% πŸ”₯</p>
251
+ </div>
252
+ """.format(metrics.get('revenue_2024_m', 0), metrics.get('revenue_growth', 0)),
253
+ unsafe_allow_html=True)
254
+
255
+ with col2:
256
+ st.markdown("""
257
+ <div class="metric-card">
258
+ <h3>πŸ“ˆ Net Profit</h3>
259
+ <h2>{:.1f}M NOK</h2>
260
+ <p>Profitable βœ…</p>
261
+ </div>
262
+ """.format(metrics.get('net_profit_2024_m', 0)), unsafe_allow_html=True)
263
+
264
+ with col3:
265
+ st.markdown("""
266
+ <div class="metric-card">
267
+ <h3>πŸ“Š Gross Margin</h3>
268
+ <h2>{:.1f}%</h2>
269
+ <p>Healthy πŸ’ͺ</p>
270
+ </div>
271
+ """.format(metrics.get('gross_margin_2024', 0)), unsafe_allow_html=True)
272
+
273
+ with col4:
274
+ st.markdown("""
275
+ <div class="metric-card">
276
+ <h3>🎯 Net Margin</h3>
277
+ <h2>{:.1f}%</h2>
278
+ <p>Strong πŸ“ˆ</p>
279
+ </div>
280
+ """.format(metrics.get('net_margin_2024', 0)), unsafe_allow_html=True)
281
+
282
+ # Charts section
283
+ col1, col2 = st.columns(2)
284
+
285
+ with col1:
286
+ st.plotly_chart(analyzer.create_revenue_trend_chart(), use_container_width=True)
287
+
288
+ with col2:
289
+ st.plotly_chart(analyzer.create_financial_health_radar(), use_container_width=True)
290
+
291
+ # Quick insights
292
+ st.markdown("""
293
+ <div class="insight-box">
294
+ <h4>🎯 Quick Insights</h4>
295
+ <ul>
296
+ <li>βœ… Revenue growth of {:.0f}% indicates explosive business development</li>
297
+ <li>πŸ’‘ Net profit margin of {:.1f}% shows strong profitability</li>
298
+ <li>πŸ“ˆ Gross margin of {:.1f}% demonstrates healthy pricing power</li>
299
+ </ul>
300
+ </div>
301
+ """.format(
302
+ metrics.get('revenue_growth', 0),
303
+ metrics.get('net_margin_2024', 0),
304
+ metrics.get('gross_margin_2024', 0)
305
+ ), unsafe_allow_html=True)
306
+
307
+ def income_analysis_page(analyzer):
308
+ """Income statement analysis page"""
309
+ st.header("πŸ’° Income Analysis")
310
+
311
+ if analyzer.data is None or not st.session_state.data_loaded:
312
+ st.warning("Please upload data to begin analysis.")
313
+ st.info("πŸ‘ˆ Use the sidebar to upload your CSV file or click 'Use Sample Data'")
314
+ return
315
+
316
+ # Revenue analysis
317
+ st.subheader("πŸ“ˆ Revenue Trend Analysis")
318
+ st.plotly_chart(analyzer.create_revenue_trend_chart(), use_container_width=True)
319
+
320
+ # Cost structure
321
+ st.subheader("πŸ₯§ Cost Structure Analysis")
322
+ if analyzer.processed_data:
323
+ data = analyzer.processed_data
324
+ costs = ['Cost of Goods Sold', 'Operating Expenses', 'Financial Expenses']
325
+ values = [data['cogs_2024'], 2000000, 234567] # Sample values
326
+
327
+ fig = px.pie(values=values, names=costs, title="Cost Breakdown 2024")
328
+ st.plotly_chart(fig, use_container_width=True)
329
+
330
+ # Profitability metrics
331
+ st.subheader("πŸ“Š Profitability Indicators")
332
+ metrics = analyzer.calculate_metrics()
333
+
334
+ col1, col2, col3 = st.columns(3)
335
+ with col1:
336
+ st.metric("Gross Margin", f"{metrics.get('gross_margin_2024', 0):.1f}%")
337
+ with col2:
338
+ st.metric("Net Margin", f"{metrics.get('net_margin_2024', 0):.1f}%")
339
+ with col3:
340
+ st.metric("Revenue Growth", f"{metrics.get('revenue_growth', 0):.1f}%")
341
+
342
+ def balance_sheet_page(analyzer):
343
+ """Balance sheet analysis page"""
344
+ st.header("πŸ›οΈ Balance Sheet Analysis")
345
+
346
+ if analyzer.data is None or not st.session_state.data_loaded:
347
+ st.warning("Please upload balance sheet data to begin analysis.")
348
+ st.info("πŸ‘ˆ Use the sidebar to upload your CSV file or click 'Use Sample Data'")
349
+ return
350
+
351
+ st.info("Balance sheet analysis requires additional data. Please upload complete financial statements.")
352
+
353
+ # Sample asset structure chart
354
+ assets = ['Current Assets', 'Fixed Assets', 'Intangible Assets']
355
+ values = [45, 35, 20]
356
+
357
+ fig = px.pie(values=values, names=assets, title="Asset Structure")
358
+ st.plotly_chart(fig, use_container_width=True)
359
+
360
+ def cash_flow_page(analyzer):
361
+ """Cash flow analysis page"""
362
+ st.header("πŸ’Έ Cash Flow Analysis")
363
+
364
+ if analyzer.data is None or not st.session_state.data_loaded:
365
+ st.warning("Please upload cash flow data to begin analysis.")
366
+ st.info("πŸ‘ˆ Use the sidebar to upload your CSV file or click 'Use Sample Data'")
367
+ return
368
+
369
+ st.info("Cash flow analysis requires additional data. Please upload complete cash flow statements.")
370
+
371
+ # Sample cash flow chart
372
+ categories = ['Operating CF', 'Investing CF', 'Financing CF']
373
+ values = [5000000, -2000000, -1000000]
374
+
375
+ fig = go.Figure(go.Waterfall(
376
+ name="Cash Flow", orientation="v",
377
+ measure=["relative", "relative", "relative"],
378
+ x=categories, y=values,
379
+ text=[f"{v/1000000:.1f}M" for v in values]
380
+ ))
381
+ fig.update_layout(title="Cash Flow Waterfall")
382
+ st.plotly_chart(fig, use_container_width=True)
383
+
384
+ def ratios_page(analyzer):
385
+ """Financial ratios analysis page"""
386
+ st.header("πŸ“Š Financial Ratios Hub")
387
+
388
+ if analyzer.data is None or not st.session_state.data_loaded:
389
+ st.warning("Please upload data to calculate ratios.")
390
+ st.info("πŸ‘ˆ Use the sidebar to upload your CSV file or click 'Use Sample Data'")
391
+ return
392
+
393
+ # Ratio categories
394
+ col1, col2, col3, col4 = st.columns(4)
395
+
396
+ with col1:
397
+ if st.button("Profitability"):
398
+ st.session_state.ratio_category = "profitability"
399
+ with col2:
400
+ if st.button("Liquidity"):
401
+ st.session_state.ratio_category = "liquidity"
402
+ with col3:
403
+ if st.button("Efficiency"):
404
+ st.session_state.ratio_category = "efficiency"
405
+ with col4:
406
+ if st.button("Growth"):
407
+ st.session_state.ratio_category = "growth"
408
+
409
+ # Display ratios based on selection
410
+ metrics = analyzer.calculate_metrics()
411
+
412
+ st.subheader("Key Financial Ratios")
413
+
414
+ col1, col2, col3 = st.columns(3)
415
+ with col1:
416
+ st.metric("Gross Profit Margin", f"{metrics.get('gross_margin_2024', 0):.1f}%", "A+")
417
+ with col2:
418
+ st.metric("Net Profit Margin", f"{metrics.get('net_margin_2024', 0):.1f}%", "A")
419
+ with col3:
420
+ st.metric("Revenue Growth", f"{metrics.get('revenue_growth', 0):.1f}%", "A+")
421
+
422
+ def ai_assistant_page(analyzer):
423
+ """AI finance assistant page"""
424
+ st.header("πŸ€– AI Finance Assistant")
425
+
426
+ if analyzer.data is None or not st.session_state.data_loaded:
427
+ st.warning("Please upload data to enable AI analysis.")
428
+ st.info("πŸ‘ˆ Use the sidebar to upload your CSV file or click 'Use Sample Data'")
429
+ return
430
+
431
+ # Chat interface
432
+ st.subheader("πŸ’¬ Ask Your Financial Questions")
433
+
434
+ # Predefined questions
435
+ col1, col2 = st.columns(2)
436
+ with col1:
437
+ if st.button("Analyze my financial health"):
438
+ st.session_state.ai_query = "financial_health"
439
+ if st.button("Find the biggest risks"):
440
+ st.session_state.ai_query = "risks"
441
+
442
+ with col2:
443
+ if st.button("Give investment advice"):
444
+ st.session_state.ai_query = "investment"
445
+ if st.button("Create improvement plan"):
446
+ st.session_state.ai_query = "improvement"
447
+
448
+ # Text input for custom questions
449
+ user_question = st.text_input("Or ask your own question:")
450
+
451
+ if user_question or 'ai_query' in st.session_state:
452
+ metrics = analyzer.calculate_metrics()
453
+
454
+ # Simple AI-like responses based on data
455
+ if user_question or st.session_state.get('ai_query') == 'financial_health':
456
+ st.markdown("""
457
+ <div class="insight-box">
458
+ <h4>🎯 Financial Health Analysis</h4>
459
+ <p>Based on your financial data:</p>
460
+ <ul>
461
+ <li>βœ… <strong>Revenue Growth:</strong> {:.0f}% growth shows strong market performance</li>
462
+ <li>βœ… <strong>Profitability:</strong> {:.1f}% net margin indicates healthy operations</li>
463
+ <li>πŸ“Š <strong>Overall Rating:</strong> A- (Strong financial position)</li>
464
+ </ul>
465
+ </div>
466
+ """.format(
467
+ metrics.get('revenue_growth', 0),
468
+ metrics.get('net_margin_2024', 0)
469
+ ), unsafe_allow_html=True)
470
+
471
+ # Clear the session state
472
+ if 'ai_query' in st.session_state:
473
+ del st.session_state.ai_query
474
+
475
+ if __name__ == "__main__":
476
  main()
docker-compose.yml CHANGED
@@ -1,21 +1,21 @@
1
- version: '3.8'
2
-
3
- services:
4
- finance-analyzer:
5
- build: .
6
- ports:
7
- - "7860:7860"
8
- environment:
9
- - STREAMLIT_SERVER_PORT=7860
10
- - STREAMLIT_SERVER_ADDRESS=0.0.0.0
11
- - STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
12
- - STREAMLIT_GLOBAL_DEVELOPMENT_MODE=false
13
- volumes:
14
- - ./data:/app/data # Optional: for persistent data storage
15
- restart: unless-stopped
16
- healthcheck:
17
- test: ["CMD", "curl", "-f", "http://localhost:7860/_stcore/health"]
18
- interval: 30s
19
- timeout: 10s
20
- retries: 3
21
  start_period: 40s
 
1
+ version: '3.8'
2
+
3
+ services:
4
+ finance-analyzer:
5
+ build: .
6
+ ports:
7
+ - "7860:7860"
8
+ environment:
9
+ - STREAMLIT_SERVER_PORT=7860
10
+ - STREAMLIT_SERVER_ADDRESS=0.0.0.0
11
+ - STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
12
+ - STREAMLIT_GLOBAL_DEVELOPMENT_MODE=false
13
+ volumes:
14
+ - ./data:/app/data # Optional: for persistent data storage
15
+ restart: unless-stopped
16
+ healthcheck:
17
+ test: ["CMD", "curl", "-f", "http://localhost:7860/_stcore/health"]
18
+ interval: 30s
19
+ timeout: 10s
20
+ retries: 3
21
  start_period: 40s
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
- streamlit>=1.28.0
2
- pandas>=2.0.0
3
- plotly>=5.15.0
4
- numpy>=1.24.0
5
  openpyxl>=3.1.0
 
1
+ streamlit>=1.28.0
2
+ pandas>=2.0.0
3
+ plotly>=5.15.0
4
+ numpy>=1.24.0
5
  openpyxl>=3.1.0