walaa2022 commited on
Commit
74f7ba2
·
verified ·
1 Parent(s): b2501de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +178 -130
app.py CHANGED
@@ -1,161 +1,209 @@
1
  import gradio as gr
2
- import torch
3
  import pandas as pd
 
4
  import json
5
- from transformers import (
6
- AutoTokenizer,
7
- AutoModelForCausalLM,
8
- AutoModelForSequenceClassification,
9
- T5ForConditionalGeneration,
10
- T5Tokenizer
11
- )
12
-
13
- class FinancialAnalyzer:
14
  def __init__(self):
15
- print("Loading models...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  try:
17
- # Initialize TinyLlama
18
- self.tiny_tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
19
- self.tiny_model = AutoModelForCausalLM.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
20
 
21
- # Initialize FinBERT
22
- self.finbert_tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
23
- self.finbert_model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- self.device = "cpu"
26
- self._move_models_to_device()
27
- print("Models loaded successfully!")
28
  except Exception as e:
29
- print(f"Error loading models: {str(e)}")
30
- raise
31
 
32
- def _move_models_to_device(self):
33
- self.tiny_model.to(self.device)
34
- self.finbert_model.to(self.device)
 
 
 
 
 
35
 
36
- def read_file_content(self, file_path):
37
- if file_path is None:
38
- return "No file uploaded"
39
-
40
- try:
41
- if file_path.endswith('.csv'):
42
- df = pd.read_csv(file_path)
43
- return df.to_string()
44
- elif file_path.endswith(('.xls', '.xlsx')):
45
- df = pd.read_excel(file_path)
46
- return df.to_string()
47
- elif file_path.endswith('.md'):
48
- with open(file_path, 'r') as f:
49
- return f.read()
50
- else:
51
- return "Unsupported file format. Please upload CSV, Excel, or Markdown files."
52
- except Exception as e:
53
- return f"Error processing file: {str(e)}"
54
 
55
- def analyze_financial_data(self, balance_sheet_path, income_statement_path):
56
- try:
57
- # Read file contents
58
- balance_sheet = self.read_file_content(balance_sheet_path)
59
- income_statement = self.read_file_content(income_statement_path)
60
-
61
- if "Error" in balance_sheet or "Error" in income_statement:
62
- return "Error processing files. Please check the file format and content."
63
 
64
- # Format prompt for analysis
65
- prompt = f"""<human>Analyze these financial statements:
66
-
67
- Balance Sheet:
68
- {balance_sheet[:800]}
69
-
70
- Income Statement:
71
- {income_statement[:800]}
72
-
73
- Provide:
74
- 1. Key financial metrics
75
- 2. Growth trends
76
- 3. Risk analysis
77
- 4. Recommendations</human>
78
-
79
- <assistant>Here's my analysis:"""
80
-
81
- # Tokenize input
82
- inputs = self.tiny_tokenizer(
83
- prompt,
84
- return_tensors="pt",
85
- truncation=True,
86
- max_length=2048
87
- ).to(self.device)
88
-
89
- # Generate response
90
- outputs = self.tiny_model.generate(
91
- inputs["input_ids"],
92
- do_sample=True,
93
- temperature=0.7,
94
- top_p=0.95,
95
- repetition_penalty=1.2,
96
- max_length=2048 # Total length including input
97
- )
98
-
99
- # Decode response
100
- analysis = self.tiny_tokenizer.decode(outputs[0], skip_special_tokens=True)
101
 
102
- # Generate sentiment
103
- sentiment = self.analyze_sentiment(balance_sheet, income_statement)
 
 
 
 
 
 
104
 
105
- # Format results
106
- results = {
107
- "Analysis": analysis,
108
- "Sentiment": sentiment,
109
- "Note": "Analysis based on financial statements from 2021-2025"
110
- }
111
 
112
- return json.dumps(results, indent=2)
 
 
 
 
 
 
113
 
114
- except Exception as e:
115
- return f"Error during analysis: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- def analyze_sentiment(self, balance_sheet, income_statement):
 
 
 
 
 
 
 
 
 
 
118
  try:
119
- text = f"{balance_sheet[:500]}\n{income_statement[:500]}"
120
- inputs = self.finbert_tokenizer(
121
- text,
122
- return_tensors="pt",
123
- truncation=True,
124
- max_length=512
125
- ).to(self.device)
126
 
127
- outputs = self.finbert_model(**inputs)
128
- probs = torch.nn.functional.softmax(outputs.logits, dim=1)
129
- labels = ['negative', 'neutral', 'positive']
130
 
131
- return {
132
- 'sentiment': labels[probs.argmax().item()],
133
- 'confidence': f"{probs.max().item():.2f}"
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
 
 
 
135
  except Exception as e:
136
- return f"Error in sentiment analysis: {str(e)}"
137
 
138
  def create_interface():
139
- analyzer = FinancialAnalyzer()
140
 
141
  iface = gr.Interface(
142
- fn=analyzer.analyze_financial_data,
143
  inputs=[
144
- gr.File(
145
- label="Upload Balance Sheet (CSV, Excel, or Markdown)",
146
- type="filepath"
147
- ),
148
- gr.File(
149
- label="Upload Income Statement (CSV, Excel, or Markdown)",
150
- type="filepath"
151
- )
152
  ],
153
- outputs=gr.Textbox(
154
- label="Analysis Results",
155
- lines=20
156
- ),
157
- title="Financial Statement Analyzer",
158
- description="Upload your financial statements (Balance Sheet and Income Statement) to get AI-powered insights and analysis."
159
  )
160
 
161
  return iface
 
1
  import gradio as gr
 
2
  import pandas as pd
3
+ import numpy as np
4
  import json
5
+ import chromadb
6
+ from chromadb.config import Settings
7
+ from datetime import datetime
8
+
9
+ class FastFinancialAnalyzer:
 
 
 
 
10
  def __init__(self):
11
+ # Initialize ChromaDB
12
+ self.client = chromadb.Client(Settings(anonymized_telemetry=False))
13
+
14
+ # Create financial metrics collection
15
+ self.collection = self.client.create_collection(
16
+ name="financial_metrics_" + datetime.now().strftime("%Y%m%d_%H%M%S")
17
+ )
18
+
19
+ # Initialize ratio benchmarks
20
+ self.initialize_ratio_benchmarks()
21
+
22
+ def initialize_ratio_benchmarks(self):
23
+ """Initialize benchmark ratios for comparison"""
24
+ self.benchmarks = {
25
+ "liquidity_ratios": {
26
+ "current_ratio": {"good": 2.0, "warning": 1.0},
27
+ "quick_ratio": {"good": 1.0, "warning": 0.5}
28
+ },
29
+ "profitability_ratios": {
30
+ "gross_margin": {"good": 0.4, "warning": 0.2},
31
+ "net_margin": {"good": 0.1, "warning": 0.05}
32
+ },
33
+ "efficiency_ratios": {
34
+ "inventory_turnover": {"good": 4, "warning": 2},
35
+ "asset_turnover": {"good": 0.5, "warning": 0.25}
36
+ }
37
+ }
38
+
39
+ def calculate_ratios(self, balance_sheet_df, income_stmt_df):
40
+ """Calculate key financial ratios"""
41
  try:
42
+ ratios = {}
 
 
43
 
44
+ # Clean numeric data
45
+ for df in [balance_sheet_df, income_stmt_df]:
46
+ for col in df.select_dtypes(include=['object']).columns:
47
+ df[col] = pd.to_numeric(df[col].astype(str).str.replace(r'[^\d.-]', ''), errors='coerce')
48
+
49
+ # Calculate ratios for each year
50
+ years = [col for col in balance_sheet_df.columns if str(col).isdigit()]
51
+ for year in years:
52
+ ratios[year] = {
53
+ "liquidity": {
54
+ "current_ratio": balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Assets', year].values[0] /
55
+ balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Liabilities', year].values[0],
56
+ "quick_ratio": (balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Assets', year].values[0] -
57
+ balance_sheet_df.loc[balance_sheet_df['Account'] == 'Inventory', year].values[0]) /
58
+ balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Liabilities', year].values[0]
59
+ },
60
+ "profitability": {
61
+ "gross_margin": income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Gross Profit', year].values[0] /
62
+ income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', year].values[0],
63
+ "net_margin": income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Net Earnings', year].values[0] /
64
+ income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', year].values[0]
65
+ },
66
+ "growth": {
67
+ "revenue_growth": None if year == years[0] else
68
+ (income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', year].values[0] -
69
+ income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', str(int(year)-1)].values[0]) /
70
+ income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', str(int(year)-1)].values[0] * 100
71
+ }
72
+ }
73
+
74
+ return ratios
75
 
 
 
 
76
  except Exception as e:
77
+ return f"Error calculating ratios: {str(e)}"
 
78
 
79
+ def analyze_trends(self, ratios):
80
+ """Analyze financial trends"""
81
+ trends = {
82
+ "liquidity": self.analyze_ratio_trend("current_ratio", ratios),
83
+ "profitability": self.analyze_ratio_trend("net_margin", ratios),
84
+ "growth": self.analyze_revenue_growth(ratios)
85
+ }
86
+ return trends
87
 
88
+ def analyze_ratio_trend(self, ratio_name, ratios):
89
+ """Analyze trend for a specific ratio"""
90
+ values = []
91
+ years = sorted(ratios.keys())
92
+
93
+ for year in years:
94
+ if ratio_name in ratios[year].get("liquidity", {}):
95
+ values.append(ratios[year]["liquidity"][ratio_name])
96
+ elif ratio_name in ratios[year].get("profitability", {}):
97
+ values.append(ratios[year]["profitability"][ratio_name])
 
 
 
 
 
 
 
 
98
 
99
+ if not values:
100
+ return "No data available"
 
 
 
 
 
 
101
 
102
+ trend = np.polyfit(range(len(values)), values, 1)[0]
103
+
104
+ if trend > 0.05:
105
+ return "Strong upward trend"
106
+ elif trend > 0:
107
+ return "Slight upward trend"
108
+ elif trend > -0.05:
109
+ return "Stable"
110
+ else:
111
+ return "Downward trend"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
+ def analyze_revenue_growth(self, ratios):
114
+ """Analyze revenue growth trend"""
115
+ growth_rates = []
116
+ years = sorted(ratios.keys())[1:] # Skip first year as it won't have growth rate
117
+
118
+ for year in years:
119
+ if ratios[year]["growth"]["revenue_growth"] is not None:
120
+ growth_rates.append(ratios[year]["growth"]["revenue_growth"])
121
 
122
+ if not growth_rates:
123
+ return "No growth data available"
 
 
 
 
124
 
125
+ avg_growth = np.mean(growth_rates)
126
+ if avg_growth > 10:
127
+ return f"Strong growth (avg {avg_growth:.1f}%)"
128
+ elif avg_growth > 0:
129
+ return f"Moderate growth (avg {avg_growth:.1f}%)"
130
+ else:
131
+ return f"Declining growth (avg {avg_growth:.1f}%)"
132
 
133
+ def generate_insights(self, ratios, trends):
134
+ """Generate actionable insights"""
135
+ insights = []
136
+
137
+ # Liquidity insights
138
+ current_ratio = ratios[max(ratios.keys())]["liquidity"]["current_ratio"]
139
+ if current_ratio < self.benchmarks["liquidity_ratios"]["current_ratio"]["warning"]:
140
+ insights.append("ALERT: Liquidity needs immediate attention")
141
+ elif current_ratio < self.benchmarks["liquidity_ratios"]["current_ratio"]["good"]:
142
+ insights.append("WATCH: Liquidity is below ideal levels")
143
+
144
+ # Profitability insights
145
+ net_margin = ratios[max(ratios.keys())]["profitability"]["net_margin"]
146
+ if net_margin > self.benchmarks["profitability_ratios"]["net_margin"]["good"]:
147
+ insights.append("STRONG: Excellent profit margins")
148
+ elif net_margin < self.benchmarks["profitability_ratios"]["net_margin"]["warning"]:
149
+ insights.append("ALERT: Profit margins need improvement")
150
 
151
+ # Growth insights
152
+ if "growth" in trends:
153
+ if "Strong" in trends["growth"]:
154
+ insights.append("POSITIVE: Strong revenue growth trend")
155
+ elif "Declining" in trends["growth"]:
156
+ insights.append("WATCH: Revenue growth is slowing")
157
+
158
+ return insights
159
+
160
+ def analyze_financials(self, balance_sheet_file, income_stmt_file):
161
+ """Main analysis function"""
162
  try:
163
+ # Read files
164
+ balance_sheet_df = pd.read_csv(balance_sheet_file)
165
+ income_stmt_df = pd.read_csv(income_stmt_file)
166
+
167
+ # Calculate ratios
168
+ ratios = self.calculate_ratios(balance_sheet_df, income_stmt_df)
 
169
 
170
+ # Analyze trends
171
+ trends = self.analyze_trends(ratios)
 
172
 
173
+ # Generate insights
174
+ insights = self.generate_insights(ratios, trends)
175
+
176
+ # Prepare comprehensive analysis
177
+ analysis = {
178
+ "Financial Ratios": ratios,
179
+ "Trend Analysis": trends,
180
+ "Key Insights": insights,
181
+ "Summary": {
182
+ "Latest Year Analysis": {
183
+ "Current Ratio": f"{ratios[max(ratios.keys())]['liquidity']['current_ratio']:.2f}",
184
+ "Net Margin": f"{ratios[max(ratios.keys())]['profitability']['net_margin']:.2%}",
185
+ "Revenue Growth": f"{ratios[max(ratios.keys())]['growth']['revenue_growth']:.2f}%" if ratios[max(ratios.keys())]['growth']['revenue_growth'] else "N/A"
186
+ }
187
+ }
188
  }
189
+
190
+ return json.dumps(analysis, indent=2)
191
+
192
  except Exception as e:
193
+ return f"Error in analysis: {str(e)}"
194
 
195
  def create_interface():
196
+ analyzer = FastFinancialAnalyzer()
197
 
198
  iface = gr.Interface(
199
+ fn=analyzer.analyze_financials,
200
  inputs=[
201
+ gr.File(label="Balance Sheet (CSV)", type="filepath"),
202
+ gr.File(label="Income Statement (CSV)", type="filepath")
 
 
 
 
 
 
203
  ],
204
+ outputs=gr.Textbox(label="Analysis Results", lines=20),
205
+ title="Fast Financial Statement Analyzer",
206
+ description="Upload financial statements for instant analysis with ratio calculations and trend detection."
 
 
 
207
  )
208
 
209
  return iface