Yaswanth-Bolla commited on
Commit
7a26ec6
·
1 Parent(s): f041270
Files changed (2) hide show
  1. README.md +223 -0
  2. app.py +312 -1
README.md CHANGED
@@ -1040,3 +1040,226 @@ For support and questions:
1040
  ---
1041
 
1042
  **Built with ❤️ for enterprise risk management and business continuity**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1040
  ---
1041
 
1042
  **Built with ❤️ for enterprise risk management and business continuity**
1043
+
1044
+ ---
1045
+
1046
+ ## Site Risk Assessment Endpoint
1047
+
1048
+ ### Overview
1049
+ The Site Risk Assessment endpoint provides comprehensive risk analysis for physical locations based on detailed site characteristics, building information, and compliance status. This endpoint is specifically designed for facilities management and safety assessment.
1050
+
1051
+ ### Endpoint Details
1052
+ - **Method**: `POST`
1053
+ - **URL**: `/api/site-risk-assessment`
1054
+ - **Purpose**: Generate detailed site-specific risk assessments based on physical location characteristics
1055
+
1056
+ ### Use Cases
1057
+ - **Facilities Risk Management**: Comprehensive assessment of physical site risks
1058
+ - **Fire Safety Compliance**: Detailed fire risk analysis for commercial buildings
1059
+ - **Insurance Risk Assessment**: Site-specific risk evaluation for insurance purposes
1060
+ - **Regulatory Compliance**: Assessment against building codes and safety standards
1061
+ - **Emergency Planning**: Risk analysis for emergency response planning
1062
+ - **Property Management**: Ongoing risk monitoring for managed properties
1063
+
1064
+ ### Request Body
1065
+ ```json
1066
+ {
1067
+ "riskCategory": "Fire Safety",
1068
+ "controlQuestion": "Are fire extinguishers available and regularly inspected?",
1069
+ "complianceStatus": "Yes, fire extinguishers are available on each floor and inspected monthly.",
1070
+ "address_of_location": "123 Corporate Park, Mumbai",
1071
+ "nature_of_occupancy": "Office space with attached cafeteria",
1072
+ "building_construction_details": "RCC framed structure with glass facade",
1073
+ "nature_of_other_occupancies": "Shared with retail stores on ground floor, clear separation exists",
1074
+ "total_floors_and_communication": "10 floors with 2 staircases and 3 elevators",
1075
+ "total_floor_area": "25,000 sq. ft.",
1076
+ "maximum_undivided_area": "3,000 sq. ft.",
1077
+ "floors_occupied": "3",
1078
+ "building_age": "12 years",
1079
+ "stability_certificate": "Yes",
1080
+ "fire_noc_availability": "Yes, renewed annually",
1081
+ "people_working_floor_wise": "Ground: 10, 1st: 50, 2nd: 45",
1082
+ "max_visitors_peak_day": "Around 80",
1083
+ "business_hours": "Mon–Fri, 9:00 AM to 6:00 PM",
1084
+ "power_backup_details": "100 kVA DG installed with 8-hour backup",
1085
+ "store_room_stacking": "Properly labeled, no obstruction to exits",
1086
+ "floor_covering_nature": "Antistatic carpet in work areas",
1087
+ "false_ceiling_details": "Gypsum tiles with concealed lighting",
1088
+ "hvac_system_details": "Centralized HVAC with AHUs on each floor",
1089
+ "area_passage_around_building": "2-meter fire vehicle access on all sides"
1090
+ }
1091
+ ```
1092
+
1093
+ ### Response Format
1094
+ ```json
1095
+ {
1096
+ "risk_id": "RISK-001",
1097
+ "category": "Fire Safety",
1098
+ "business_unit": "Facilities",
1099
+ "risk_owner": "Fire Safety Officer",
1100
+ "timeline": "Immediate",
1101
+ "risk_name": "Inadequate fire suppression coverage for office complex",
1102
+ "question": "Are fire extinguishers available and regularly inspected?",
1103
+ "compliance_status": "Yes, fire extinguishers are available on each floor and inspected monthly.",
1104
+ "identified_threat": "Fire spread risk due to limited suppression systems in high-occupancy areas",
1105
+ "likelihood": 6,
1106
+ "impact": 8,
1107
+ "risk_value": 48,
1108
+ "residual_risk": "High",
1109
+ "current_control_description": "Manual fire extinguishers with monthly inspections, no automated suppression",
1110
+ "current_control_rating": "Fair",
1111
+ "mitigation_plan": "Install automated fire suppression systems in high-risk areas, upgrade emergency evacuation systems, and enhance fire detection coverage",
1112
+ "site_details": {
1113
+ "site_name": "Corporate Office Complex - Mumbai",
1114
+ "address": "123 Corporate Park, Mumbai",
1115
+ "building_type": "Commercial Office",
1116
+ "floor_area_sq_ft": 25000,
1117
+ "occupancy_type": "Office space with attached cafeteria",
1118
+ "year_of_construction": 2012,
1119
+ "no_of_floors": 10
1120
+ },
1121
+ "risk_classification_summary": "High-priority fire safety risk due to building age, occupancy density, and limited automated suppression systems. Requires immediate attention per NFPA guidelines.",
1122
+ "mitigation_suggestions": [
1123
+ "Install automatic sprinkler systems per NFPA 13 standards",
1124
+ "Upgrade fire alarm systems with voice evacuation capabilities",
1125
+ "Implement quarterly fire drills and emergency response training",
1126
+ "Establish fire safety committee and regular risk assessments"
1127
+ ],
1128
+ "risk_trends": {
1129
+ "top_category": "Fire Safety",
1130
+ "risk_severity": "High",
1131
+ "observations": [
1132
+ "Buildings over 10 years require enhanced fire safety measures",
1133
+ "High-density office occupancy increases evacuation complexity",
1134
+ "Mixed-use buildings require comprehensive fire separation strategies"
1135
+ ]
1136
+ }
1137
+ }
1138
+ ```
1139
+
1140
+ ### Key Features
1141
+
1142
+ #### **Comprehensive Site Analysis**
1143
+ - **Building Characteristics**: Construction type, age, and structural details
1144
+ - **Occupancy Patterns**: Personnel distribution, visitor capacity, and usage patterns
1145
+ - **Safety Systems**: Fire protection, HVAC, electrical, and emergency systems
1146
+ - **Compliance Status**: Regulatory certifications and inspection records
1147
+
1148
+ #### **Evidence-Based Assessment**
1149
+ - **Building Code References**: NFPA standards, International Building Code (IBC)
1150
+ - **Occupancy Load Analysis**: Egress capacity and evacuation requirements
1151
+ - **Historical Risk Data**: Industry-specific incident patterns and trends
1152
+ - **Regulatory Compliance**: Local fire codes and safety regulations
1153
+
1154
+ #### **Actionable Recommendations**
1155
+ - **Specific Mitigation Plans**: Targeted improvements based on site characteristics
1156
+ - **Timeline Prioritization**: Risk-based scheduling for remediation activities
1157
+ - **Cost-Effectiveness**: Practical solutions considering budget constraints
1158
+ - **Compliance Alignment**: Recommendations aligned with regulatory requirements
1159
+
1160
+ ### Integration Examples
1161
+
1162
+ #### **cURL Example**
1163
+ ```bash
1164
+ curl -X POST "http://localhost:8000/api/site-risk-assessment" \
1165
+ -H "Content-Type: application/json" \
1166
+ -d '{
1167
+ "riskCategory": "Fire Safety",
1168
+ "controlQuestion": "Are fire extinguishers available and regularly inspected?",
1169
+ "complianceStatus": "Yes, fire extinguishers are available on each floor and inspected monthly.",
1170
+ "address_of_location": "123 Corporate Park, Mumbai",
1171
+ "nature_of_occupancy": "Office space with attached cafeteria",
1172
+ "building_construction_details": "RCC framed structure with glass facade",
1173
+ "nature_of_other_occupancies": "Shared with retail stores on ground floor, clear separation exists",
1174
+ "total_floors_and_communication": "10 floors with 2 staircases and 3 elevators",
1175
+ "total_floor_area": "25,000 sq. ft.",
1176
+ "maximum_undivided_area": "3,000 sq. ft.",
1177
+ "floors_occupied": "3",
1178
+ "building_age": "12 years",
1179
+ "stability_certificate": "Yes",
1180
+ "fire_noc_availability": "Yes, renewed annually",
1181
+ "people_working_floor_wise": "Ground: 10, 1st: 50, 2nd: 45",
1182
+ "max_visitors_peak_day": "Around 80",
1183
+ "business_hours": "Mon–Fri, 9:00 AM to 6:00 PM",
1184
+ "power_backup_details": "100 kVA DG installed with 8-hour backup",
1185
+ "store_room_stacking": "Properly labeled, no obstruction to exits",
1186
+ "floor_covering_nature": "Antistatic carpet in work areas",
1187
+ "false_ceiling_details": "Gypsum tiles with concealed lighting",
1188
+ "hvac_system_details": "Centralized HVAC with AHUs on each floor",
1189
+ "area_passage_around_building": "2-meter fire vehicle access on all sides"
1190
+ }'
1191
+ ```
1192
+
1193
+ #### **Python Integration**
1194
+ ```python
1195
+ import requests
1196
+
1197
+ # Site risk assessment request
1198
+ site_data = {
1199
+ "riskCategory": "Fire Safety",
1200
+ "controlQuestion": "Are fire extinguishers available and regularly inspected?",
1201
+ "complianceStatus": "Yes, fire extinguishers are available on each floor and inspected monthly.",
1202
+ "address_of_location": "123 Corporate Park, Mumbai",
1203
+ "nature_of_occupancy": "Office space with attached cafeteria",
1204
+ # ... other site details
1205
+ }
1206
+
1207
+ response = requests.post(
1208
+ "http://localhost:8000/api/site-risk-assessment",
1209
+ json=site_data
1210
+ )
1211
+
1212
+ if response.status_code == 200:
1213
+ assessment = response.json()
1214
+ print(f"Risk Level: {assessment['residual_risk']}")
1215
+ print(f"Risk Score: {assessment['risk_value']}")
1216
+ print(f"Mitigation Plan: {assessment['mitigation_plan']}")
1217
+ else:
1218
+ print(f"Error: {response.text}")
1219
+ ```
1220
+
1221
+ #### **JavaScript Integration**
1222
+ ```javascript
1223
+ const siteAssessment = async (siteData) => {
1224
+ try {
1225
+ const response = await fetch('/api/site-risk-assessment', {
1226
+ method: 'POST',
1227
+ headers: {
1228
+ 'Content-Type': 'application/json',
1229
+ },
1230
+ body: JSON.stringify(siteData)
1231
+ });
1232
+
1233
+ if (response.ok) {
1234
+ const assessment = await response.json();
1235
+ return {
1236
+ riskId: assessment.risk_id,
1237
+ riskLevel: assessment.residual_risk,
1238
+ mitigationPlan: assessment.mitigation_plan,
1239
+ siteDetails: assessment.site_details
1240
+ };
1241
+ } else {
1242
+ throw new Error('Assessment failed');
1243
+ }
1244
+ } catch (error) {
1245
+ console.error('Site assessment error:', error);
1246
+ return null;
1247
+ }
1248
+ };
1249
+ ```
1250
+
1251
+ ### Error Handling
1252
+
1253
+ The endpoint provides comprehensive error handling with specific error codes:
1254
+
1255
+ - **400 Bad Request**: Invalid input data or missing required fields
1256
+ - **422 Validation Error**: Data validation failures
1257
+ - **500 Internal Server Error**: AI processing errors with fallback responses
1258
+
1259
+ ### Fallback Mechanism
1260
+
1261
+ If AI processing fails, the endpoint provides intelligent fallback responses based on:
1262
+ - **Building Age Analysis**: Risk assessment based on construction year
1263
+ - **Occupancy Density**: Risk factors related to personnel count
1264
+ - **Floor Area Considerations**: Space-based risk calculations
1265
+ - **Compliance Status**: Assessment based on current safety measures
app.py CHANGED
@@ -1,10 +1,12 @@
1
  # app.py
2
- from fastapi import FastAPI
3
  from pydantic import BaseModel
4
  from typing import List, Optional
5
  import os
6
  import openai
7
  import json
 
 
8
 
9
  # Import the new routers
10
  from enterprise_ra import enterprise_ra_router
@@ -264,6 +266,68 @@ class RiskAnalysis(BaseModel):
264
  class RiskMitigationResponse(BaseModel):
265
  risk_analysis: RiskAnalysis
266
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  @app.post("/api/risk-mitigation", response_model=RiskMitigationResponse)
268
  def generate_risk_mitigation(request: RiskRequestModel):
269
  """
@@ -569,3 +633,250 @@ Provide a comprehensive risk analysis with mitigation plan based on this respons
569
  )
570
 
571
  return RiskMitigationResponse(risk_analysis=risk_analysis)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # app.py
2
+ from fastapi import FastAPI, HTTPException
3
  from pydantic import BaseModel
4
  from typing import List, Optional
5
  import os
6
  import openai
7
  import json
8
+ import uuid
9
+ import re
10
 
11
  # Import the new routers
12
  from enterprise_ra import enterprise_ra_router
 
266
  class RiskMitigationResponse(BaseModel):
267
  risk_analysis: RiskAnalysis
268
 
269
+ # Site Risk Assessment Models
270
+ class SiteDetails(BaseModel):
271
+ site_name: Optional[str] = ""
272
+ address: str
273
+ building_type: Optional[str] = ""
274
+ floor_area_sq_ft: Optional[int] = 0
275
+ occupancy_type: str
276
+ year_of_construction: Optional[int] = 0
277
+ no_of_floors: Optional[int] = 0
278
+
279
+ class SiteRiskAssessmentRequest(BaseModel):
280
+ riskCategory: str
281
+ controlQuestion: str
282
+ complianceStatus: str
283
+ address_of_location: str
284
+ nature_of_occupancy: str
285
+ building_construction_details: str
286
+ nature_of_other_occupancies: str
287
+ total_floors_and_communication: str
288
+ total_floor_area: str
289
+ maximum_undivided_area: str
290
+ floors_occupied: str
291
+ building_age: str
292
+ stability_certificate: str
293
+ fire_noc_availability: str
294
+ people_working_floor_wise: str
295
+ max_visitors_peak_day: str
296
+ business_hours: str
297
+ power_backup_details: str
298
+ store_room_stacking: str
299
+ floor_covering_nature: str
300
+ false_ceiling_details: str
301
+ hvac_system_details: str
302
+ area_passage_around_building: str
303
+
304
+ class SiteRiskTrends(BaseModel):
305
+ top_category: str
306
+ risk_severity: str
307
+ observations: List[str]
308
+
309
+ class SiteRiskAssessmentResponse(BaseModel):
310
+ risk_id: str
311
+ category: str
312
+ business_unit: str
313
+ risk_owner: str
314
+ timeline: str
315
+ risk_name: str
316
+ question: str
317
+ compliance_status: str
318
+ identified_threat: str
319
+ likelihood: int
320
+ impact: int
321
+ risk_value: int
322
+ residual_risk: str
323
+ current_control_description: str
324
+ current_control_rating: str
325
+ mitigation_plan: str
326
+ site_details: SiteDetails
327
+ risk_classification_summary: str
328
+ mitigation_suggestions: List[str]
329
+ risk_trends: SiteRiskTrends
330
+
331
  @app.post("/api/risk-mitigation", response_model=RiskMitigationResponse)
332
  def generate_risk_mitigation(request: RiskRequestModel):
333
  """
 
633
  )
634
 
635
  return RiskMitigationResponse(risk_analysis=risk_analysis)
636
+
637
+ @app.post("/api/site-risk-assessment", response_model=SiteRiskAssessmentResponse)
638
+ def generate_site_risk_assessment(request: SiteRiskAssessmentRequest):
639
+ """
640
+ Generate comprehensive site-specific risk assessment based on physical location details
641
+ """
642
+
643
+ system_prompt = """You are a comprehensive risk assessment expert specializing in site-specific risk analysis. Your task is to analyze physical site details and generate detailed risk assessments based on the provided information.
644
+
645
+ CRITICAL: You must respond with ONLY a valid JSON object. Do not include any markdown formatting, code blocks, or additional text.
646
+
647
+ For the site risk assessment, consider:
648
+ - Physical building characteristics and construction details
649
+ - Occupancy patterns and usage
650
+ - Fire safety systems and compliance status
651
+ - Emergency egress and accessibility
652
+ - HVAC and electrical systems
653
+ - Regulatory compliance (fire NOC, stability certificates)
654
+ - Site-specific vulnerabilities and threats
655
+ - Industry standards (NFPA, building codes, occupational safety)
656
+
657
+ Provide evidence-based assessments that reference:
658
+ - Building codes and fire safety standards (NFPA 101, IBC)
659
+ - Occupancy load calculations and egress requirements
660
+ - Construction type fire ratings and vulnerability factors
661
+ - Historical incident data for similar occupancies
662
+ - Industry best practices for risk mitigation
663
+ - Regulatory compliance requirements
664
+
665
+ RESPOND WITH ONLY THIS EXACT JSON FORMAT:
666
+ {
667
+ "risk_id": "Unique risk identifier starting with RISK-",
668
+ "category": "Risk category from input",
669
+ "business_unit": "Relevant business unit",
670
+ "risk_owner": "Appropriate risk owner role",
671
+ "timeline": "Risk mitigation timeline",
672
+ "risk_name": "Specific risk name based on site analysis",
673
+ "question": "Control question from input",
674
+ "compliance_status": "Compliance status from input",
675
+ "identified_threat": "Specific threat based on site characteristics",
676
+ "likelihood": "Numeric likelihood score 1-10",
677
+ "impact": "Numeric impact score 1-10",
678
+ "risk_value": "Calculated risk value",
679
+ "residual_risk": "Risk level (Low/Medium/High/Critical)",
680
+ "current_control_description": "Description of current controls",
681
+ "current_control_rating": "Rating of current controls",
682
+ "mitigation_plan": "Specific mitigation recommendations",
683
+ "site_details": {
684
+ "site_name": "Derived site name",
685
+ "address": "Address from input",
686
+ "building_type": "Building type derived from occupancy",
687
+ "floor_area_sq_ft": "Numeric floor area",
688
+ "occupancy_type": "Occupancy type from input",
689
+ "year_of_construction": "Calculated year",
690
+ "no_of_floors": "Number of floors from input"
691
+ },
692
+ "risk_classification_summary": "Summary of risk classification and reasoning",
693
+ "mitigation_suggestions": ["List of specific mitigation suggestions"],
694
+ "risk_trends": {
695
+ "top_category": "Risk category",
696
+ "risk_severity": "Severity level",
697
+ "observations": ["List of trend observations"]
698
+ }
699
+ }"""
700
+
701
+ # Convert request to structured input
702
+ input_data = {
703
+ "risk_category": request.riskCategory,
704
+ "control_question": request.controlQuestion,
705
+ "compliance_status": request.complianceStatus,
706
+ "site_information": {
707
+ "address": request.address_of_location,
708
+ "occupancy_nature": request.nature_of_occupancy,
709
+ "building_construction": request.building_construction_details,
710
+ "neighboring_occupancies": request.nature_of_other_occupancies,
711
+ "floors_and_communication": request.total_floors_and_communication,
712
+ "total_floor_area": request.total_floor_area,
713
+ "max_undivided_area": request.maximum_undivided_area,
714
+ "floors_occupied": request.floors_occupied,
715
+ "building_age": request.building_age,
716
+ "stability_certificate": request.stability_certificate,
717
+ "fire_noc": request.fire_noc_availability,
718
+ "occupancy_details": request.people_working_floor_wise,
719
+ "visitor_capacity": request.max_visitors_peak_day,
720
+ "operating_hours": request.business_hours,
721
+ "power_systems": request.power_backup_details,
722
+ "storage_conditions": request.store_room_stacking,
723
+ "flooring": request.floor_covering_nature,
724
+ "ceiling_details": request.false_ceiling_details,
725
+ "hvac_system": request.hvac_system_details,
726
+ "building_access": request.area_passage_around_building
727
+ }
728
+ }
729
+
730
+ user_message = f"""Analyze the following site information and generate a comprehensive risk assessment:
731
+
732
+ {json.dumps(input_data, indent=2)}
733
+
734
+ Provide a detailed site-specific risk assessment considering all physical characteristics, occupancy patterns, compliance status, and potential vulnerabilities. Include specific recommendations based on the building details and current control status."""
735
+
736
+ try:
737
+ result = generate_response(system_prompt, user_message)
738
+
739
+ # Clean the response - remove markdown code blocks if present
740
+ cleaned_result = result.strip()
741
+ if cleaned_result.startswith('```json'):
742
+ cleaned_result = cleaned_result[7:]
743
+ elif cleaned_result.startswith('```'):
744
+ cleaned_result = cleaned_result[3:]
745
+ if cleaned_result.endswith('```'):
746
+ cleaned_result = cleaned_result[:-3]
747
+ cleaned_result = cleaned_result.strip()
748
+
749
+ # Extract JSON from the response
750
+ json_start = cleaned_result.find('{')
751
+ json_end = cleaned_result.rfind('}') + 1
752
+
753
+ if json_start != -1 and json_end > json_start:
754
+ json_str = cleaned_result[json_start:json_end]
755
+ # Clean up any problematic characters
756
+ json_str = re.sub(r'\r\s*', ' ', json_str)
757
+ json_str = re.sub(r'\t+', ' ', json_str)
758
+ json_str = re.sub(r'\s+', ' ', json_str)
759
+ assessment_data = json.loads(json_str)
760
+
761
+ # Extract site details
762
+ site_info = assessment_data.get("site_details", {})
763
+ site_details = SiteDetails(
764
+ site_name=site_info.get("site_name", ""),
765
+ address=site_info.get("address", request.address_of_location),
766
+ building_type=site_info.get("building_type", ""),
767
+ floor_area_sq_ft=site_info.get("floor_area_sq_ft", 0),
768
+ occupancy_type=site_info.get("occupancy_type", request.nature_of_occupancy),
769
+ year_of_construction=site_info.get("year_of_construction", 0),
770
+ no_of_floors=site_info.get("no_of_floors", 0)
771
+ )
772
+
773
+ # Extract risk trends
774
+ trends_info = assessment_data.get("risk_trends", {})
775
+ risk_trends = SiteRiskTrends(
776
+ top_category=trends_info.get("top_category", request.riskCategory),
777
+ risk_severity=trends_info.get("risk_severity", "Medium"),
778
+ observations=trends_info.get("observations", [])
779
+ )
780
+
781
+ return SiteRiskAssessmentResponse(
782
+ risk_id=assessment_data.get("risk_id", f"RISK-{str(uuid.uuid4())[:8].upper()}"),
783
+ category=assessment_data.get("category", request.riskCategory),
784
+ business_unit=assessment_data.get("business_unit", "Facilities"),
785
+ risk_owner=assessment_data.get("risk_owner", "Risk Manager"),
786
+ timeline=assessment_data.get("timeline", "Short-term"),
787
+ risk_name=assessment_data.get("risk_name", f"Site-specific {request.riskCategory} risk"),
788
+ question=assessment_data.get("question", request.controlQuestion),
789
+ compliance_status=assessment_data.get("compliance_status", request.complianceStatus),
790
+ identified_threat=assessment_data.get("identified_threat", f"Site-specific {request.riskCategory} vulnerability"),
791
+ likelihood=assessment_data.get("likelihood", 5),
792
+ impact=assessment_data.get("impact", 5),
793
+ risk_value=assessment_data.get("risk_value", 25),
794
+ residual_risk=assessment_data.get("residual_risk", "Medium"),
795
+ current_control_description=assessment_data.get("current_control_description", "Standard site controls in place"),
796
+ current_control_rating=assessment_data.get("current_control_rating", "Fair"),
797
+ mitigation_plan=assessment_data.get("mitigation_plan", "Implement enhanced site-specific controls"),
798
+ site_details=site_details,
799
+ risk_classification_summary=assessment_data.get("risk_classification_summary", "Site risk requiring attention"),
800
+ mitigation_suggestions=assessment_data.get("mitigation_suggestions", []),
801
+ risk_trends=risk_trends
802
+ )
803
+ else:
804
+ raise ValueError("No valid JSON found in response")
805
+
806
+ except (json.JSONDecodeError, ValueError) as e:
807
+ # Fallback response based on input data
808
+ building_age_num = 0
809
+ try:
810
+ # Extract numeric age from building age string
811
+ age_match = re.search(r'\d+', request.building_age)
812
+ if age_match:
813
+ building_age_num = int(age_match.group())
814
+ except:
815
+ building_age_num = 10
816
+
817
+ # Extract floor area
818
+ floor_area_num = 0
819
+ try:
820
+ area_match = re.search(r'[\d,]+', request.total_floor_area.replace(',', ''))
821
+ if area_match:
822
+ floor_area_num = int(area_match.group().replace(',', ''))
823
+ except:
824
+ floor_area_num = 25000
825
+
826
+ # Extract number of floors
827
+ floors_num = 0
828
+ try:
829
+ floors_match = re.search(r'\d+', request.total_floors_and_communication)
830
+ if floors_match:
831
+ floors_num = int(floors_match.group())
832
+ except:
833
+ floors_num = 3
834
+
835
+ fallback_response = SiteRiskAssessmentResponse(
836
+ risk_id=f"RISK-{str(uuid.uuid4())[:8].upper()}",
837
+ category=request.riskCategory,
838
+ business_unit="Facilities Management",
839
+ risk_owner="Fire Safety Officer" if "fire" in request.riskCategory.lower() else "Risk Manager",
840
+ timeline="Immediate" if "critical" in request.complianceStatus.lower() else "Short-term",
841
+ risk_name=f"Site-specific {request.riskCategory} control deficiency",
842
+ question=request.controlQuestion,
843
+ compliance_status=request.complianceStatus,
844
+ identified_threat=f"Inadequate {request.riskCategory.lower()} controls may lead to property damage, personnel injury, and operational disruption",
845
+ likelihood=7 if building_age_num > 15 else 5,
846
+ impact=8 if floor_area_num > 20000 else 6,
847
+ risk_value=56 if building_age_num > 15 and floor_area_num > 20000 else 30,
848
+ residual_risk="High" if building_age_num > 15 and floor_area_num > 20000 else "Medium",
849
+ current_control_description=f"Current {request.riskCategory.lower()} controls include basic safety measures as described in compliance status",
850
+ current_control_rating="Fair" if "yes" in request.complianceStatus.lower() else "Poor",
851
+ mitigation_plan=f"Enhance {request.riskCategory.lower()} control systems, implement regular inspections, and ensure compliance with relevant safety standards",
852
+ site_details=SiteDetails(
853
+ site_name=f"Commercial Facility - {request.address_of_location.split(',')[-1].strip() if ',' in request.address_of_location else 'Location'}",
854
+ address=request.address_of_location,
855
+ building_type=request.nature_of_occupancy.split()[0] if request.nature_of_occupancy else "Commercial",
856
+ floor_area_sq_ft=floor_area_num,
857
+ occupancy_type=request.nature_of_occupancy,
858
+ year_of_construction=2024 - building_age_num if building_age_num > 0 else 2010,
859
+ no_of_floors=floors_num
860
+ ),
861
+ risk_classification_summary=f"Site-specific {request.riskCategory} risk assessment based on building characteristics and current control status",
862
+ mitigation_suggestions=[
863
+ f"Upgrade {request.riskCategory.lower()} detection and suppression systems",
864
+ "Conduct regular safety training and emergency drills",
865
+ "Implement preventive maintenance programs",
866
+ "Ensure compliance with local safety regulations"
867
+ ],
868
+ risk_trends=SiteRiskTrends(
869
+ top_category=request.riskCategory,
870
+ risk_severity="High" if building_age_num > 15 else "Medium",
871
+ observations=[
872
+ f"Building age of {building_age_num} years increases maintenance requirements",
873
+ f"Floor area of {floor_area_num:,} sq ft requires comprehensive safety systems",
874
+ f"Multi-floor occupancy increases emergency response complexity"
875
+ ]
876
+ )
877
+ )
878
+
879
+ return fallback_response
880
+
881
+ except Exception as e:
882
+ raise HTTPException(status_code=500, detail=f"Error generating site risk assessment: {str(e)}")