Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -187,6 +187,18 @@ class FinancialAnalyzer:
|
|
187 |
print(f"Error extracting metrics: {str(e)}")
|
188 |
return {}
|
189 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
def get_sentiment_analysis(self, metrics):
|
191 |
"""Get financial sentiment analysis using FinBERT"""
|
192 |
try:
|
@@ -197,20 +209,69 @@ class FinancialAnalyzer:
|
|
197 |
Interest coverage: {metrics['Ratios'].get('Interest_Coverage', 0):.2f}
|
198 |
Current ratio: {metrics['Ratios'].get('Current_Ratio', 0):.2f}
|
199 |
"""
|
200 |
-
|
201 |
inputs = self.finbert_tokenizer(financial_text, return_tensors="pt", padding=True, truncation=True)
|
202 |
outputs = self.finbert_model(**inputs)
|
203 |
probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
|
204 |
sentiment_scores = probabilities.detach().numpy()[0]
|
205 |
-
|
206 |
sentiments = ['negative', 'neutral', 'positive']
|
207 |
-
sentiment_dict = dict(zip(sentiments, sentiment_scores))
|
208 |
-
|
209 |
return sentiment_dict
|
210 |
except Exception as e:
|
211 |
print(f"Error in sentiment analysis: {str(e)}")
|
212 |
return {}
|
213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
def generate_prompt(self, metrics, sentiment_dict):
|
215 |
"""Create enhanced analysis prompt with sentiment"""
|
216 |
try:
|
|
|
187 |
print(f"Error extracting metrics: {str(e)}")
|
188 |
return {}
|
189 |
|
190 |
+
def convert_to_serializable(obj):
|
191 |
+
"""Convert numpy values to Python native types"""
|
192 |
+
if isinstance(obj, np.float32):
|
193 |
+
return float(obj)
|
194 |
+
elif isinstance(obj, np.ndarray):
|
195 |
+
return obj.tolist()
|
196 |
+
elif isinstance(obj, dict):
|
197 |
+
return {key: convert_to_serializable(value) for key, value in obj.items()}
|
198 |
+
elif isinstance(obj, list):
|
199 |
+
return [convert_to_serializable(item) for item in obj]
|
200 |
+
return obj
|
201 |
+
|
202 |
def get_sentiment_analysis(self, metrics):
|
203 |
"""Get financial sentiment analysis using FinBERT"""
|
204 |
try:
|
|
|
209 |
Interest coverage: {metrics['Ratios'].get('Interest_Coverage', 0):.2f}
|
210 |
Current ratio: {metrics['Ratios'].get('Current_Ratio', 0):.2f}
|
211 |
"""
|
212 |
+
|
213 |
inputs = self.finbert_tokenizer(financial_text, return_tensors="pt", padding=True, truncation=True)
|
214 |
outputs = self.finbert_model(**inputs)
|
215 |
probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
|
216 |
sentiment_scores = probabilities.detach().numpy()[0]
|
217 |
+
|
218 |
sentiments = ['negative', 'neutral', 'positive']
|
219 |
+
sentiment_dict = dict(zip(sentiments, [float(score) for score in sentiment_scores]))
|
220 |
+
|
221 |
return sentiment_dict
|
222 |
except Exception as e:
|
223 |
print(f"Error in sentiment analysis: {str(e)}")
|
224 |
return {}
|
225 |
|
226 |
+
def analyze_financials(self, balance_sheet_file, income_stmt_file):
|
227 |
+
"""Main analysis function"""
|
228 |
+
try:
|
229 |
+
# Validate input files
|
230 |
+
if not (self.is_valid_markdown(balance_sheet_file) and self.is_valid_markdown(income_stmt_file)):
|
231 |
+
return "Error: One or both files are invalid or not in Markdown format."
|
232 |
+
|
233 |
+
# Read files
|
234 |
+
with open(balance_sheet_file, 'r') as f:
|
235 |
+
balance_sheet = f.read()
|
236 |
+
with open(income_stmt_file, 'r') as f:
|
237 |
+
income_stmt = f.read()
|
238 |
+
|
239 |
+
# Process financial data
|
240 |
+
income_data = self.parse_financial_data(income_stmt)
|
241 |
+
balance_data = self.parse_financial_data(balance_sheet)
|
242 |
+
metrics = self.extract_metrics(income_data, balance_data)
|
243 |
+
|
244 |
+
# Get sentiment analysis
|
245 |
+
sentiment_dict = self.get_sentiment_analysis(metrics)
|
246 |
+
|
247 |
+
# Generate and get analysis
|
248 |
+
prompt = self.generate_prompt(metrics, sentiment_dict)
|
249 |
+
analysis = self.generate_analysis(prompt)
|
250 |
+
|
251 |
+
# Convert all numpy values to Python native types
|
252 |
+
metrics = convert_to_serializable(metrics)
|
253 |
+
sentiment_dict = convert_to_serializable(sentiment_dict)
|
254 |
+
|
255 |
+
# Prepare final results
|
256 |
+
results = {
|
257 |
+
"Financial Analysis": {
|
258 |
+
"Key Metrics": metrics,
|
259 |
+
"Market Sentiment": sentiment_dict,
|
260 |
+
"AI Insights": analysis,
|
261 |
+
"Analysis Period": "2021-2025",
|
262 |
+
"Note": "All monetary values in millions ($M)"
|
263 |
+
}
|
264 |
+
}
|
265 |
+
|
266 |
+
return json.dumps(results, indent=2)
|
267 |
+
|
268 |
+
except Exception as e:
|
269 |
+
return f"Error in analysis: {str(e)}\n\nDetails: {type(e).__name__}"
|
270 |
+
|
271 |
+
|
272 |
+
|
273 |
+
|
274 |
+
|
275 |
def generate_prompt(self, metrics, sentiment_dict):
|
276 |
"""Create enhanced analysis prompt with sentiment"""
|
277 |
try:
|