Spaces:
Sleeping
Sleeping
Update notes/llm_notes_generator.py
Browse files- notes/llm_notes_generator.py +58 -5
notes/llm_notes_generator.py
CHANGED
|
@@ -66,7 +66,7 @@ class FlexibleFinancialNoteGenerator:
|
|
| 66 |
|
| 67 |
"mistralai/mixtral-8x7b-instruct"
|
| 68 |
]
|
| 69 |
-
|
| 70 |
def load_note_templates(self) -> Dict[str, Any]:
|
| 71 |
try:
|
| 72 |
if __name__ == "__main__":
|
|
@@ -276,13 +276,16 @@ GENERATE VALID JSON NOW (NO ADDITIONAL TEXT):"""
|
|
| 276 |
self.api_url,
|
| 277 |
headers=self.headers,
|
| 278 |
json=payload,
|
| 279 |
-
timeout=
|
| 280 |
)
|
| 281 |
response.raise_for_status()
|
| 282 |
result = response.json()
|
| 283 |
content = result['choices'][0]['message']['content']
|
| 284 |
logger.info(f"Successful response from {model}")
|
| 285 |
return content
|
|
|
|
|
|
|
|
|
|
| 286 |
except requests.exceptions.HTTPError as e:
|
| 287 |
if e.response.status_code == 404:
|
| 288 |
logger.warning(f"Model {model} not found (404), trying next model")
|
|
@@ -358,6 +361,47 @@ GENERATE VALID JSON NOW (NO ADDITIONAL TEXT):"""
|
|
| 358 |
|
| 359 |
return None, None
|
| 360 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 361 |
def validate_and_fix_json(self, json_data: Dict[str, Any], note_number: str) -> Dict[str, Any]:
|
| 362 |
fixed_data = json_data.copy()
|
| 363 |
|
|
@@ -377,7 +421,7 @@ GENERATE VALID JSON NOW (NO ADDITIONAL TEXT):"""
|
|
| 377 |
|
| 378 |
metadata_note_num = fixed_data["metadata"].get("note_number")
|
| 379 |
try:
|
| 380 |
-
expected_note_num = int(note_number)
|
| 381 |
|
| 382 |
if (metadata_note_num is None or
|
| 383 |
metadata_note_num == 0 or
|
|
@@ -436,17 +480,26 @@ GENERATE VALID JSON NOW (NO ADDITIONAL TEXT):"""
|
|
| 436 |
if "subcategories" not in struct_elem or not isinstance(struct_elem["subcategories"], list):
|
| 437 |
struct_elem["subcategories"] = []
|
| 438 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
if i > 0 and struct_elem.get("subcategories"):
|
| 440 |
if "total" not in struct_elem:
|
| 441 |
struct_elem["total"] = sum(
|
| 442 |
-
sub.get("value", 0.0)
|
| 443 |
for sub in struct_elem["subcategories"]
|
| 444 |
if isinstance(sub, dict)
|
| 445 |
)
|
| 446 |
|
| 447 |
if "previous_total" not in struct_elem:
|
| 448 |
struct_elem["previous_total"] = sum(
|
| 449 |
-
sub.get("previous_value", 0.0)
|
| 450 |
for sub in struct_elem["subcategories"]
|
| 451 |
if isinstance(sub, dict)
|
| 452 |
)
|
|
|
|
| 66 |
|
| 67 |
"mistralai/mixtral-8x7b-instruct"
|
| 68 |
]
|
| 69 |
+
|
| 70 |
def load_note_templates(self) -> Dict[str, Any]:
|
| 71 |
try:
|
| 72 |
if __name__ == "__main__":
|
|
|
|
| 276 |
self.api_url,
|
| 277 |
headers=self.headers,
|
| 278 |
json=payload,
|
| 279 |
+
timeout=180
|
| 280 |
)
|
| 281 |
response.raise_for_status()
|
| 282 |
result = response.json()
|
| 283 |
content = result['choices'][0]['message']['content']
|
| 284 |
logger.info(f"Successful response from {model}")
|
| 285 |
return content
|
| 286 |
+
except requests.exceptions.Timeout:
|
| 287 |
+
logger.warning(f"Request to {model} timed out after 180s")
|
| 288 |
+
continue
|
| 289 |
except requests.exceptions.HTTPError as e:
|
| 290 |
if e.response.status_code == 404:
|
| 291 |
logger.warning(f"Model {model} not found (404), trying next model")
|
|
|
|
| 361 |
|
| 362 |
return None, None
|
| 363 |
|
| 364 |
+
def safe_numeric_value(self, value, default=0.0):
|
| 365 |
+
"""Convert any value to a safe numeric float, defaulting to 0.0 if conversion fails."""
|
| 366 |
+
if value is None or value == '' or value == '-':
|
| 367 |
+
return default
|
| 368 |
+
|
| 369 |
+
try:
|
| 370 |
+
# If already a number, return it as float
|
| 371 |
+
if isinstance(value, (int, float)):
|
| 372 |
+
return float(value)
|
| 373 |
+
|
| 374 |
+
# Handle string numbers
|
| 375 |
+
if isinstance(value, str):
|
| 376 |
+
# Remove common non-numeric characters
|
| 377 |
+
cleaned = value.replace(',', '').replace('₹', '').replace('Rs', '').replace('Rs.', '').strip()
|
| 378 |
+
|
| 379 |
+
# Handle parentheses for negative numbers (accounting format)
|
| 380 |
+
if cleaned.startswith('(') and cleaned.endswith(')'):
|
| 381 |
+
cleaned = '-' + cleaned[1:-1]
|
| 382 |
+
|
| 383 |
+
# Handle negative numbers
|
| 384 |
+
is_negative = cleaned.startswith('-')
|
| 385 |
+
if is_negative:
|
| 386 |
+
cleaned = cleaned[1:]
|
| 387 |
+
|
| 388 |
+
# Remove any remaining non-numeric characters except decimal point
|
| 389 |
+
cleaned = ''.join(c for c in cleaned if c.isdigit() or c == '.')
|
| 390 |
+
|
| 391 |
+
if not cleaned or cleaned == '.':
|
| 392 |
+
return default
|
| 393 |
+
|
| 394 |
+
# Convert to number
|
| 395 |
+
result = float(cleaned)
|
| 396 |
+
return -result if is_negative else result
|
| 397 |
+
|
| 398 |
+
# Try direct conversion as last resort
|
| 399 |
+
return float(value)
|
| 400 |
+
|
| 401 |
+
except (ValueError, TypeError, AttributeError):
|
| 402 |
+
logger.warning(f"Could not convert value '{value}' to numeric, using default {default}")
|
| 403 |
+
return default
|
| 404 |
+
|
| 405 |
def validate_and_fix_json(self, json_data: Dict[str, Any], note_number: str) -> Dict[str, Any]:
|
| 406 |
fixed_data = json_data.copy()
|
| 407 |
|
|
|
|
| 421 |
|
| 422 |
metadata_note_num = fixed_data["metadata"].get("note_number")
|
| 423 |
try:
|
| 424 |
+
expected_note_num = int(note_number);
|
| 425 |
|
| 426 |
if (metadata_note_num is None or
|
| 427 |
metadata_note_num == 0 or
|
|
|
|
| 480 |
if "subcategories" not in struct_elem or not isinstance(struct_elem["subcategories"], list):
|
| 481 |
struct_elem["subcategories"] = []
|
| 482 |
|
| 483 |
+
# FIX: Ensure all subcategory values are numeric before summing
|
| 484 |
+
for sub in struct_elem.get("subcategories", []):
|
| 485 |
+
if isinstance(sub, dict):
|
| 486 |
+
if "value" in sub:
|
| 487 |
+
sub["value"] = self.safe_numeric_value(sub["value"])
|
| 488 |
+
if "previous_value" in sub:
|
| 489 |
+
sub["previous_value"] = self.safe_numeric_value(sub["previous_value"])
|
| 490 |
+
|
| 491 |
+
# Now safely calculate totals
|
| 492 |
if i > 0 and struct_elem.get("subcategories"):
|
| 493 |
if "total" not in struct_elem:
|
| 494 |
struct_elem["total"] = sum(
|
| 495 |
+
self.safe_numeric_value(sub.get("value", 0.0))
|
| 496 |
for sub in struct_elem["subcategories"]
|
| 497 |
if isinstance(sub, dict)
|
| 498 |
)
|
| 499 |
|
| 500 |
if "previous_total" not in struct_elem:
|
| 501 |
struct_elem["previous_total"] = sum(
|
| 502 |
+
self.safe_numeric_value(sub.get("previous_value", 0.0))
|
| 503 |
for sub in struct_elem["subcategories"]
|
| 504 |
if isinstance(sub, dict)
|
| 505 |
)
|