walaa2022 commited on
Commit
9e42b37
·
verified ·
1 Parent(s): c714b22

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -138
app.py CHANGED
@@ -5,8 +5,6 @@ import torch
5
  import logging
6
  import gc
7
  from transformers import pipeline
8
- import json
9
- import csv
10
 
11
  # Setup logging
12
  logging.basicConfig(
@@ -24,22 +22,6 @@ def clear_gpu_memory():
24
  torch.cuda.empty_cache()
25
  gc.collect()
26
 
27
- def clean_financial_value(value):
28
- try:
29
- if isinstance(value, str):
30
- value = value.strip().replace('"', '').replace(' ', '')
31
- if '(' in value and ')' in value:
32
- value = '-' + value.replace('(', '').replace(')', '')
33
- value = value.replace(',', '')
34
- try:
35
- return float(value)
36
- except ValueError:
37
- return 0.0
38
- return float(value) if isinstance(value, (int, float)) else 0.0
39
- except Exception as e:
40
- logger.error(f"Error cleaning value: {str(e)}")
41
- return 0.0
42
-
43
  class FinancialAnalyzer:
44
  def __init__(self):
45
  self.analysis_model = None
@@ -48,14 +30,12 @@ class FinancialAnalyzer:
48
 
49
  def load_models(self):
50
  try:
51
- # Load analysis model
52
  self.analysis_model = pipeline(
53
  "text-generation",
54
  model="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
55
  torch_dtype=torch.float16 if DEVICE == "cuda" else torch.float32
56
  )
57
 
58
- # Load sentiment model
59
  self.sentiment_model = pipeline(
60
  "text-classification",
61
  model="ProsusAI/finbert",
@@ -67,172 +47,168 @@ class FinancialAnalyzer:
67
  logger.error(f"Error loading models: {str(e)}")
68
  raise
69
 
70
- def analyze_financials(self, context):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  try:
72
- # Generate sentiment analysis
 
 
 
 
 
 
 
73
  sentiment = self.sentiment_model(
74
- context,
75
- truncation=True,
76
- max_length=512
77
  )[0]
78
 
79
  # Generate analysis
80
- analysis_prompt = f"""[INST] As a financial analyst, analyze this data:
81
 
82
- {context}
83
 
84
- Sentiment: {sentiment['label']} ({sentiment['score']:.2%})
85
 
86
- Provide:
87
- 1. Business Status and Health Assessment
88
- 2. Key Financial Insights and Metrics
89
- 3. Strategic Recommendations and Action Plan
90
-
91
- Be specific and data-driven in your analysis.
92
- [/INST]"""
93
 
94
  response = self.analysis_model(
95
  analysis_prompt,
96
- max_new_tokens=1500,
97
- do_sample=False,
98
  num_return_sequences=1,
99
  truncation=True
100
  )
101
 
102
- return self.format_response(response[0]['generated_text'], sentiment, context)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  except Exception as e:
104
- logger.error(f"Error in analysis: {str(e)}")
105
- return f"Error generating analysis: {str(e)}"
106
 
107
- def format_response(self, analysis_text, sentiment, context):
108
  try:
109
- output = [
110
  "# Financial Analysis Report\n\n",
111
- f"## Overall Sentiment: {sentiment['label'].upper()} ({sentiment['score']:.2%})\n\n",
112
- "## Financial Data\n```\n",
113
- context,
114
- "\n```\n\n"
115
  ]
116
 
117
- sections = analysis_text.split('\n\n')
118
  current_section = None
119
-
120
- for section in sections:
121
- section = section.strip()
122
- if not section:
123
  continue
124
 
125
- if "Business Status" in section:
126
- output.append("## Business Status\n")
127
- elif "Financial Insights" in section:
128
- output.append("\n## Key Insights\n")
129
- elif "Strategic Recommendations" in section:
130
- output.append("\n## Recommendations\n")
131
- else:
132
- if not section.startswith('-'):
133
- section = f"- {section}"
134
- output.append(f"{section}\n")
135
 
136
- return "".join(output)
137
  except Exception as e:
138
  logger.error(f"Error formatting response: {str(e)}")
139
- return "Error formatting analysis results"
140
-
141
- def save_organized_data(structured_data, filename):
142
- try:
143
- with open(filename, 'w') as f:
144
- json.dump(structured_data, f, indent=4)
145
- return True
146
- except Exception as e:
147
- logger.error(f"Error saving data: {str(e)}")
148
- return False
149
 
150
  def analyze_statements(income_statement, balance_sheet):
151
  try:
152
  if not income_statement or not balance_sheet:
153
- return "Please upload both Income Statement and Balance Sheet CSV files."
154
-
155
- # Read and organize data
156
- try:
157
- income_df = pd.read_csv(income_statement)
158
- balance_df = pd.read_csv(balance_sheet)
159
-
160
- # Clean and structure data
161
- financial_data = {
162
- "income_statement": income_df.to_dict(orient='records'),
163
- "balance_sheet": balance_df.to_dict(orient='records')
164
- }
165
-
166
- # Save structured data
167
- save_organized_data(financial_data, "organized_financial_data.json")
168
-
169
- # Create analysis context
170
- context = f"""Financial Data Summary:
171
-
172
- Income Statement:
173
- {income_df.to_string()}
174
-
175
- Balance Sheet:
176
- {balance_df.to_string()}
177
- """
178
-
179
- # Initialize analyzer and generate analysis
180
- analyzer = FinancialAnalyzer()
181
- result = analyzer.analyze_financials(context)
182
-
183
- clear_gpu_memory()
184
- return result
185
-
186
- except Exception as e:
187
- logger.error(f"Error processing files: {str(e)}")
188
- raise
189
 
 
 
 
 
 
 
 
 
 
190
  except Exception as e:
191
- logger.error(f"Analysis error: {str(e)}")
192
  return f"""Analysis Error: {str(e)}
193
 
194
- Please verify:
195
- 1. Files are in CSV format
196
- 2. Files contain financial data
197
- 3. Files are not corrupted"""
198
 
199
  # Create Gradio interface
200
  iface = gr.Interface(
201
  fn=analyze_statements,
202
  inputs=[
203
  gr.File(
204
- label="Upload Income Statement (CSV)",
205
  file_types=[".csv"]
206
  ),
207
  gr.File(
208
- label="Upload Balance Sheet (CSV)",
209
  file_types=[".csv"]
210
  )
211
  ],
212
  outputs=gr.Markdown(),
213
- title="AI Financial Statement Analyzer",
214
- description="""## Financial Analysis Tool
215
-
216
- Upload your financial statements to get:
217
- - Business Status Assessment
218
- - Key Financial Insights
219
- - Strategic Recommendations
220
-
221
- Requirements:
222
- - CSV files with financial data
223
- - Standard financial statement format""",
224
- flagging_mode="never"
225
  )
226
 
227
- # Launch the interface
228
  if __name__ == "__main__":
229
- try:
230
- iface.queue()
231
- iface.launch(
232
- share=False,
233
- server_name="0.0.0.0",
234
- server_port=7860
235
- )
236
- except Exception as e:
237
- logger.error(f"Launch error: {str(e)}")
238
- sys.exit(1)
 
5
  import logging
6
  import gc
7
  from transformers import pipeline
 
 
8
 
9
  # Setup logging
10
  logging.basicConfig(
 
22
  torch.cuda.empty_cache()
23
  gc.collect()
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  class FinancialAnalyzer:
26
  def __init__(self):
27
  self.analysis_model = None
 
30
 
31
  def load_models(self):
32
  try:
 
33
  self.analysis_model = pipeline(
34
  "text-generation",
35
  model="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
36
  torch_dtype=torch.float16 if DEVICE == "cuda" else torch.float32
37
  )
38
 
 
39
  self.sentiment_model = pipeline(
40
  "text-classification",
41
  model="ProsusAI/finbert",
 
47
  logger.error(f"Error loading models: {str(e)}")
48
  raise
49
 
50
+ def format_number(self, number):
51
+ try:
52
+ if isinstance(number, str):
53
+ number = float(number.replace(',', '').replace('$', '').strip())
54
+ return f"${number:,.0f}"
55
+ except:
56
+ return str(number)
57
+
58
+ def process_dataframe(self, df, statement_type):
59
+ try:
60
+ df_cleaned = df.copy()
61
+ # Clean column names
62
+ df_cleaned.columns = df_cleaned.columns.str.strip()
63
+
64
+ # Clean numeric values
65
+ numeric_cols = df_cleaned.select_dtypes(include=['float64', 'int64']).columns
66
+ for col in numeric_cols:
67
+ df_cleaned[col] = pd.to_numeric(df_cleaned[col].astype(str).str.replace('[$,()]', '', regex=True), errors='coerce')
68
+
69
+ return df_cleaned
70
+ except Exception as e:
71
+ logger.error(f"Error processing {statement_type}: {str(e)}")
72
+ raise
73
+
74
+ def analyze_financials(self, income_df, balance_df):
75
  try:
76
+ # Process dataframes
77
+ income_clean = self.process_dataframe(income_df, "income_statement")
78
+ balance_clean = self.process_dataframe(balance_df, "balance_sheet")
79
+
80
+ # Create analysis context
81
+ context = self.create_analysis_context(income_clean, balance_clean)
82
+
83
+ # Generate sentiment
84
  sentiment = self.sentiment_model(
85
+ context[:512],
86
+ truncation=True
 
87
  )[0]
88
 
89
  # Generate analysis
90
+ analysis_prompt = f"""[INST] Analyze these financial metrics:
91
 
92
+ {context}
93
 
94
+ Market Sentiment: {sentiment['label']} ({sentiment['score']:.2%})
95
 
96
+ Provide concise analysis of:
97
+ 1. Financial Health
98
+ 2. Key Insights
99
+ 3. Strategic Recommendations
100
+ [/INST]"""
 
 
101
 
102
  response = self.analysis_model(
103
  analysis_prompt,
104
+ max_new_tokens=500,
105
+ temperature=0.7,
106
  num_return_sequences=1,
107
  truncation=True
108
  )
109
 
110
+ return self.format_response(response[0]['generated_text'], sentiment)
111
+
112
+ except Exception as e:
113
+ logger.error(f"Analysis error: {str(e)}")
114
+ return f"Error in analysis: {str(e)}"
115
+
116
+ def create_analysis_context(self, income_df, balance_df):
117
+ try:
118
+ # Extract latest year metrics
119
+ latest_metrics = {
120
+ 'Revenue': income_df.loc[income_df['year'] == 'Total Net Revenue', '2025'].iloc[0],
121
+ 'Net_Income': income_df.loc[income_df['year'] == 'Net Income', '2025'].iloc[0],
122
+ 'Assets': balance_df.loc[balance_df['year'] == 'Total Assets', '2025'].iloc[0],
123
+ 'Liabilities': balance_df.loc[balance_df['year'] == 'Total Liabilities', '2025'].iloc[0],
124
+ 'Equity': balance_df.loc[balance_df['year'] == "Shareholder's Equity", '2025'].iloc[0]
125
+ }
126
+
127
+ return f"""Financial Metrics (2025):
128
+ Revenue: {self.format_number(latest_metrics['Revenue'])}
129
+ Net Income: {self.format_number(latest_metrics['Net_Income'])}
130
+ Total Assets: {self.format_number(latest_metrics['Assets'])}
131
+ Total Liabilities: {self.format_number(latest_metrics['Liabilities'])}
132
+ Shareholder's Equity: {self.format_number(latest_metrics['Equity'])}"""
133
+
134
  except Exception as e:
135
+ logger.error(f"Error creating context: {str(e)}")
136
+ raise
137
 
138
+ def format_response(self, analysis_text, sentiment):
139
  try:
140
+ sections = [
141
  "# Financial Analysis Report\n\n",
142
+ f"## Market Sentiment: {sentiment['label'].upper()} ({sentiment['score']:.2%})\n\n"
 
 
 
143
  ]
144
 
 
145
  current_section = None
146
+ for line in analysis_text.split('\n'):
147
+ line = line.strip()
148
+ if not line:
 
149
  continue
150
 
151
+ if "Financial Health" in line:
152
+ sections.append("## Financial Health\n")
153
+ elif "Key Insights" in line:
154
+ sections.append("\n## Key Insights\n")
155
+ elif "Strategic Recommendations" in line:
156
+ sections.append("\n## Strategic Recommendations\n")
157
+ elif line:
158
+ sections.append(f"- {line}\n")
 
 
159
 
160
+ return "".join(sections)
161
  except Exception as e:
162
  logger.error(f"Error formatting response: {str(e)}")
163
+ return "Error formatting analysis"
 
 
 
 
 
 
 
 
 
164
 
165
  def analyze_statements(income_statement, balance_sheet):
166
  try:
167
  if not income_statement or not balance_sheet:
168
+ return "Please upload both financial statements."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
+ income_df = pd.read_csv(income_statement)
171
+ balance_df = pd.read_csv(balance_sheet)
172
+
173
+ analyzer = FinancialAnalyzer()
174
+ result = analyzer.analyze_financials(income_df, balance_df)
175
+
176
+ clear_gpu_memory()
177
+ return result
178
+
179
  except Exception as e:
180
+ logger.error(f"Error: {str(e)}")
181
  return f"""Analysis Error: {str(e)}
182
 
183
+ Please check:
184
+ 1. CSV format is correct
185
+ 2. Required financial data is present
186
+ 3. Files are not corrupted"""
187
 
188
  # Create Gradio interface
189
  iface = gr.Interface(
190
  fn=analyze_statements,
191
  inputs=[
192
  gr.File(
193
+ label="Income Statement",
194
  file_types=[".csv"]
195
  ),
196
  gr.File(
197
+ label="Balance Sheet",
198
  file_types=[".csv"]
199
  )
200
  ],
201
  outputs=gr.Markdown(),
202
+ title="Financial Statement Analyzer",
203
+ description="Upload financial statements for AI analysis",
204
+ theme="default",
205
+ allow_flagging=False
 
 
 
 
 
 
 
 
206
  )
207
 
208
+ # Launch with basic configuration
209
  if __name__ == "__main__":
210
+ iface.launch(
211
+ server_name="0.0.0.0",
212
+ server_port=7860,
213
+ share=False
214
+ )