yashgori20 commited on
Commit
de1356d
·
1 Parent(s): b67a41b
Files changed (1) hide show
  1. app.py +164 -83
app.py CHANGED
@@ -1370,16 +1370,15 @@ def validate_parameters(parameters: List[Dict]) -> Dict:
1370
  Validate parameters for duplicates, missing fields, and consistency.
1371
  Returns a validation report with issues and suggestions.
1372
  """
1373
- # Handle case where parameters might be None or not a list
1374
  if not parameters or not isinstance(parameters, list):
1375
  return {
1376
- "is_valid": False,
1377
  "duplicate_parameters": [],
1378
  "missing_required_fields": [],
1379
  "empty_options": [],
1380
  "invalid_types": [],
1381
  "similar_parameters": [],
1382
- "suggestions": ["No valid parameters provided"]
1383
  }
1384
 
1385
  validation_report = {
@@ -1398,94 +1397,123 @@ def validate_parameters(parameters: List[Dict]) -> Dict:
1398
  if not isinstance(param, dict):
1399
  continue
1400
 
1401
- param_name = param.get("Parameter", "").strip()
1402
- param_lower = param_name.lower()
1403
-
1404
- if param_lower in seen_params:
 
1405
  validation_report["duplicate_parameters"].append({
1406
- "parameter": param_name,
1407
- "indices": [seen_params[param_lower], i]
1408
  })
1409
  validation_report["is_valid"] = False
1410
  else:
1411
- seen_params[param_lower] = i
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1412
 
1413
  return validation_report
1414
 
1415
  def deduplicate_parameters(parameters: List[Dict]) -> List[Dict]:
1416
- """
1417
- Remove duplicate parameters intelligently.
1418
- Merges similar parameters and keeps the most complete version.
1419
- """
1420
- from difflib import SequenceMatcher
1421
 
1422
- # First pass: Remove exact duplicates
1423
  seen = {}
1424
- deduped = []
1425
 
1426
  for param in parameters:
1427
- param_key = param.get("Parameter", "").lower().strip()
1428
-
 
 
 
 
 
1429
  if param_key not in seen:
1430
  seen[param_key] = param
1431
- deduped.append(param)
1432
  else:
1433
  # Merge information from duplicate
1434
  existing = seen[param_key]
1435
 
1436
- # Merge options if applicable
1437
- if param.get("Type") in ["Dropdown", "Checklist"]:
 
 
 
 
1438
  existing_options = existing.get("DropdownOptions", "")
1439
  new_options = param.get("DropdownOptions", "")
1440
 
1441
  if existing_options and new_options:
1442
- # Merge unique options
1443
  existing_list = [opt.strip() for opt in existing_options.split(",")]
1444
  new_list = [opt.strip() for opt in new_options.split(",")]
1445
 
 
1446
  for opt in new_list:
1447
- if opt not in existing_list:
1448
  existing_list.append(opt)
1449
 
1450
  existing["DropdownOptions"] = ", ".join(existing_list)
1451
-
1452
- # Keep the more detailed spec
1453
- if not existing.get("Spec") and param.get("Spec"):
1454
- existing["Spec"] = param.get("Spec")
1455
-
1456
- # Second pass: Merge similar parameters
1457
- final_params = []
1458
- processed = set()
1459
 
1460
- for i, param in enumerate(deduped):
1461
- if i in processed:
1462
- continue
1463
-
1464
- param_name = param.get("Parameter", "")
1465
- merged = False
1466
-
1467
- # Check against remaining parameters
1468
- for j in range(i + 1, len(deduped)):
1469
- if j in processed:
1470
- continue
1471
-
1472
- other_name = deduped[j].get("Parameter", "")
1473
- similarity = SequenceMatcher(None, param_name.lower(), other_name.lower()).ratio()
1474
-
1475
- if similarity > 0.85: # High similarity threshold
1476
- # Merge parameters
1477
- merged_param = merge_similar_parameters(param, deduped[j])
1478
- final_params.append(merged_param)
1479
- processed.add(i)
1480
- processed.add(j)
1481
- merged = True
1482
- break
1483
-
1484
- if not merged:
1485
- final_params.append(param)
1486
- processed.add(i)
1487
-
1488
- return final_params
1489
 
1490
  def merge_similar_parameters(param1: Dict, param2: Dict) -> Dict:
1491
  """
@@ -1621,14 +1649,12 @@ def suggest_missing_parameters(parameters: List[Dict], product_name: str) -> Lis
1621
 
1622
  # REPLACE THIS ENTIRE FUNCTION
1623
  def apply_intelligent_fixes(parameters: List[Dict]) -> List[Dict]:
1624
- """
1625
- Apply intelligent fixes to common parameter issues.
1626
- """
1627
- # Fix the bool iteration error
1628
  if not parameters or not isinstance(parameters, list):
1629
  return []
1630
 
1631
  fixed_params = []
 
1632
 
1633
  for param in parameters:
1634
  if not isinstance(param, dict):
@@ -1638,34 +1664,30 @@ def apply_intelligent_fixes(parameters: List[Dict]) -> List[Dict]:
1638
 
1639
  # Fix empty parameter names
1640
  if not fixed_param.get("Parameter", "").strip():
1641
- fixed_param["Parameter"] = f"{fixed_param.get('Type', 'Unknown')} Parameter"
1642
 
1643
  # Fix invalid types
1644
- valid_types = ["Checklist", "Dropdown", "Image Upload", "Remarks", "Text Input", "Numeric Input", "Toggle"]
1645
  if fixed_param.get("Type", "") not in valid_types:
1646
- # Try to infer type from name
1647
  param_name_lower = fixed_param.get("Parameter", "").lower()
1648
 
1649
- if any(word in param_name_lower for word in ["remark", "comment", "note"]):
1650
  fixed_param["Type"] = "Remarks"
1651
- elif any(word in param_name_lower for word in ["photo", "image", "picture"]):
1652
  fixed_param["Type"] = "Image Upload"
1653
- elif any(word in param_name_lower for word in ["weight", "dimension", "temperature", "time"]):
1654
  fixed_param["Type"] = "Numeric Input"
 
 
1655
  elif fixed_param.get("DropdownOptions", ""):
1656
- # Has options, likely dropdown or checklist
1657
  options = fixed_param.get("DropdownOptions", "").split(",")
1658
- if len(options) > 4:
1659
- fixed_param["Type"] = "Checklist"
1660
- else:
1661
- fixed_param["Type"] = "Dropdown"
1662
  else:
1663
  fixed_param["Type"] = "Text Input"
1664
 
1665
  # Add default options for empty dropdowns/checklists
1666
  if fixed_param["Type"] in ["Dropdown", "Checklist"] and not fixed_param.get("DropdownOptions", "").strip():
1667
  if fixed_param["Type"] == "Dropdown":
1668
- fixed_param["DropdownOptions"] = "Option 1, Option 2, Option 3"
1669
  else:
1670
  fixed_param["DropdownOptions"] = "Item 1, Item 2, Item 3, Item 4"
1671
 
@@ -1673,6 +1695,14 @@ def apply_intelligent_fixes(parameters: List[Dict]) -> List[Dict]:
1673
  if not fixed_param.get("Section", "").strip():
1674
  fixed_param["Section"] = "General"
1675
 
 
 
 
 
 
 
 
 
1676
  fixed_params.append(fixed_param)
1677
 
1678
  return fixed_params
@@ -2020,11 +2050,29 @@ def refine_parameters():
2020
  updated_params = apply_intelligent_fixes(updated_params)
2021
 
2022
  # Validate parameters
2023
- # Skip validation for now - just organize and store
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2024
  global_parameters = updated_params
2025
- suggestions = []
2026
 
2027
- print(f"✅ Generated {len(updated_params)} parameters")
2028
 
2029
  print(f"✅ Generated {len(updated_params)} parameters as requested")
2030
 
@@ -2366,12 +2414,45 @@ def edit_parameters():
2366
  print(llm_response[:500] + "..." if len(llm_response) > 500 else llm_response)
2367
  print("=" * 50)
2368
 
 
2369
  # Parse response
2370
  summary_text, changes_list = parse_llm_changes(llm_response)
2371
 
2372
- # For edit operations, we need to handle the response differently
2373
- # The LLM should return the complete parameter list with modifications
2374
- updated_params = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2375
 
2376
  # If we got a complete list, use it
2377
  if changes_list and all(change.get("Parameter") for change in changes_list):
 
1370
  Validate parameters for duplicates, missing fields, and consistency.
1371
  Returns a validation report with issues and suggestions.
1372
  """
 
1373
  if not parameters or not isinstance(parameters, list):
1374
  return {
1375
+ "is_valid": True, # Changed to True for empty case
1376
  "duplicate_parameters": [],
1377
  "missing_required_fields": [],
1378
  "empty_options": [],
1379
  "invalid_types": [],
1380
  "similar_parameters": [],
1381
+ "suggestions": []
1382
  }
1383
 
1384
  validation_report = {
 
1397
  if not isinstance(param, dict):
1398
  continue
1399
 
1400
+ param_name = param.get("Parameter", "").strip().lower()
1401
+ if not param_name:
1402
+ continue
1403
+
1404
+ if param_name in seen_params:
1405
  validation_report["duplicate_parameters"].append({
1406
+ "parameter": param.get("Parameter", ""),
1407
+ "indices": [seen_params[param_name], i]
1408
  })
1409
  validation_report["is_valid"] = False
1410
  else:
1411
+ seen_params[param_name] = i
1412
+
1413
+ # Check for similar parameters (same meaning)
1414
+ from difflib import SequenceMatcher
1415
+ param_names = [(i, p.get("Parameter", "")) for i, p in enumerate(parameters) if isinstance(p, dict) and p.get("Parameter", "").strip()]
1416
+
1417
+ for i, (idx1, name1) in enumerate(param_names):
1418
+ for j, (idx2, name2) in enumerate(param_names[i+1:], i+1):
1419
+ similarity = SequenceMatcher(None, name1.lower(), name2.lower()).ratio()
1420
+ if similarity > 0.8: # Very similar
1421
+ validation_report["similar_parameters"].append({
1422
+ "param1": name1,
1423
+ "param2": name2,
1424
+ "similarity": round(similarity, 2),
1425
+ "indices": [idx1, idx2]
1426
+ })
1427
+ validation_report["suggestions"].append(
1428
+ f"'{name1}' and '{name2}' seem very similar - consider merging them"
1429
+ )
1430
+
1431
+ # Validate parameter types
1432
+ valid_types = ["Checklist", "Dropdown", "Image Upload", "Remarks", "Text Input", "Numeric Input", "Toggle"]
1433
+
1434
+ for i, param in enumerate(parameters):
1435
+ if not isinstance(param, dict):
1436
+ continue
1437
+
1438
+ param_name = param.get("Parameter", "")
1439
+ param_type = param.get("Type", "")
1440
+
1441
+ # Check required fields
1442
+ if not param_name.strip():
1443
+ validation_report["missing_required_fields"].append({
1444
+ "index": i,
1445
+ "field": "Parameter name"
1446
+ })
1447
+ validation_report["is_valid"] = False
1448
+
1449
+ # Check valid type
1450
+ if param_type not in valid_types:
1451
+ validation_report["invalid_types"].append({
1452
+ "parameter": param_name,
1453
+ "invalid_type": param_type,
1454
+ "suggested_type": "Text Input"
1455
+ })
1456
+ validation_report["is_valid"] = False
1457
+
1458
+ # Check options for Dropdown/Checklist
1459
+ if param_type in ["Dropdown", "Checklist"]:
1460
+ options = param.get("DropdownOptions", "").strip()
1461
+ if not options:
1462
+ validation_report["empty_options"].append({
1463
+ "parameter": param_name,
1464
+ "type": param_type
1465
+ })
1466
+ validation_report["suggestions"].append(
1467
+ f"'{param_name}' is a {param_type} but has no options defined"
1468
+ )
1469
 
1470
  return validation_report
1471
 
1472
  def deduplicate_parameters(parameters: List[Dict]) -> List[Dict]:
1473
+ """Remove exact duplicates and merge very similar parameters"""
1474
+ if not parameters or not isinstance(parameters, list):
1475
+ return []
 
 
1476
 
1477
+ # Remove exact duplicates first
1478
  seen = {}
1479
+ unique_params = []
1480
 
1481
  for param in parameters:
1482
+ if not isinstance(param, dict):
1483
+ continue
1484
+
1485
+ param_key = param.get("Parameter", "").strip().lower()
1486
+ if not param_key:
1487
+ continue
1488
+
1489
  if param_key not in seen:
1490
  seen[param_key] = param
1491
+ unique_params.append(param)
1492
  else:
1493
  # Merge information from duplicate
1494
  existing = seen[param_key]
1495
 
1496
+ # Keep the more detailed spec
1497
+ if not existing.get("Spec", "") and param.get("Spec", ""):
1498
+ existing["Spec"] = param.get("Spec", "")
1499
+
1500
+ # Merge options for dropdowns/checklists
1501
+ if existing.get("Type") in ["Dropdown", "Checklist"]:
1502
  existing_options = existing.get("DropdownOptions", "")
1503
  new_options = param.get("DropdownOptions", "")
1504
 
1505
  if existing_options and new_options:
 
1506
  existing_list = [opt.strip() for opt in existing_options.split(",")]
1507
  new_list = [opt.strip() for opt in new_options.split(",")]
1508
 
1509
+ # Add unique new options
1510
  for opt in new_list:
1511
+ if opt and opt not in existing_list:
1512
  existing_list.append(opt)
1513
 
1514
  existing["DropdownOptions"] = ", ".join(existing_list)
 
 
 
 
 
 
 
 
1515
 
1516
+ return unique_params
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1517
 
1518
  def merge_similar_parameters(param1: Dict, param2: Dict) -> Dict:
1519
  """
 
1649
 
1650
  # REPLACE THIS ENTIRE FUNCTION
1651
  def apply_intelligent_fixes(parameters: List[Dict]) -> List[Dict]:
1652
+ """Apply intelligent fixes to parameter issues"""
 
 
 
1653
  if not parameters or not isinstance(parameters, list):
1654
  return []
1655
 
1656
  fixed_params = []
1657
+ valid_types = ["Checklist", "Dropdown", "Image Upload", "Remarks", "Text Input", "Numeric Input", "Toggle"]
1658
 
1659
  for param in parameters:
1660
  if not isinstance(param, dict):
 
1664
 
1665
  # Fix empty parameter names
1666
  if not fixed_param.get("Parameter", "").strip():
1667
+ fixed_param["Parameter"] = f"Parameter {len(fixed_params) + 1}"
1668
 
1669
  # Fix invalid types
 
1670
  if fixed_param.get("Type", "") not in valid_types:
 
1671
  param_name_lower = fixed_param.get("Parameter", "").lower()
1672
 
1673
+ if any(word in param_name_lower for word in ["remark", "comment", "note", "observation"]):
1674
  fixed_param["Type"] = "Remarks"
1675
+ elif any(word in param_name_lower for word in ["photo", "image", "picture", "visual"]):
1676
  fixed_param["Type"] = "Image Upload"
1677
+ elif any(word in param_name_lower for word in ["weight", "temperature", "dimension", "size", "measurement"]):
1678
  fixed_param["Type"] = "Numeric Input"
1679
+ elif any(word in param_name_lower for word in ["acceptable", "pass", "fail", "yes", "no"]):
1680
+ fixed_param["Type"] = "Toggle"
1681
  elif fixed_param.get("DropdownOptions", ""):
 
1682
  options = fixed_param.get("DropdownOptions", "").split(",")
1683
+ fixed_param["Type"] = "Checklist" if len(options) > 4 else "Dropdown"
 
 
 
1684
  else:
1685
  fixed_param["Type"] = "Text Input"
1686
 
1687
  # Add default options for empty dropdowns/checklists
1688
  if fixed_param["Type"] in ["Dropdown", "Checklist"] and not fixed_param.get("DropdownOptions", "").strip():
1689
  if fixed_param["Type"] == "Dropdown":
1690
+ fixed_param["DropdownOptions"] = "Acceptable, Marginal, Not Acceptable"
1691
  else:
1692
  fixed_param["DropdownOptions"] = "Item 1, Item 2, Item 3, Item 4"
1693
 
 
1695
  if not fixed_param.get("Section", "").strip():
1696
  fixed_param["Section"] = "General"
1697
 
1698
+ # Set default values for missing fields
1699
+ if not fixed_param.get("Spec"):
1700
+ fixed_param["Spec"] = ""
1701
+ if not fixed_param.get("IncludeRemarks"):
1702
+ fixed_param["IncludeRemarks"] = "No"
1703
+ if not fixed_param.get("ClauseReference"):
1704
+ fixed_param["ClauseReference"] = ""
1705
+
1706
  fixed_params.append(fixed_param)
1707
 
1708
  return fixed_params
 
2050
  updated_params = apply_intelligent_fixes(updated_params)
2051
 
2052
  # Validate parameters
2053
+ # Validate and fix parameters
2054
+ validation_report = validate_parameters(updated_params)
2055
+
2056
+ if not validation_report["is_valid"]:
2057
+ print("⚠️ Validation issues found, applying fixes...")
2058
+
2059
+ # Remove duplicates
2060
+ if validation_report["duplicate_parameters"]:
2061
+ updated_params = deduplicate_parameters(updated_params)
2062
+ print(f"✅ Removed {len(validation_report['duplicate_parameters'])} duplicate parameters")
2063
+
2064
+ # Fix invalid types and missing fields
2065
+ if validation_report["invalid_types"] or validation_report["missing_required_fields"]:
2066
+ updated_params = apply_intelligent_fixes(updated_params)
2067
+ print("✅ Fixed parameter issues")
2068
+
2069
+ # Re-validate after fixes
2070
+ validation_report = validate_parameters(updated_params)
2071
+
2072
+ suggestions = validation_report.get("suggestions", [])
2073
  global_parameters = updated_params
 
2074
 
2075
+ print(f"✅ Generated {len(updated_params)} validated parameters")
2076
 
2077
  print(f"✅ Generated {len(updated_params)} parameters as requested")
2078
 
 
2414
  print(llm_response[:500] + "..." if len(llm_response) > 500 else llm_response)
2415
  print("=" * 50)
2416
 
2417
+
2418
  # Parse response
2419
  summary_text, changes_list = parse_llm_changes(llm_response)
2420
 
2421
+ # Apply changes and validate for duplicates
2422
+ if isinstance(changes_list, list):
2423
+ updated_params = []
2424
+
2425
+ # If we got a complete list, use it
2426
+ if changes_list and all(change.get("Parameter") for change in changes_list):
2427
+ for change in changes_list:
2428
+ param_type = change.get("Type", "Text Input")
2429
+ if param_type not in ["Checklist", "Dropdown", "Image Upload", "Remarks", "Text Input", "Numeric Input", "Toggle"]:
2430
+ param_type = "Text Input"
2431
+
2432
+ updated_params.append({
2433
+ "Parameter": change.get("Parameter", ""),
2434
+ "Type": param_type,
2435
+ "Spec": change.get("Spec", ""),
2436
+ "DropdownOptions": change.get("DropdownOptions", "") or change.get("ChecklistOptions", ""),
2437
+ "IncludeRemarks": change.get("IncludeRemarks", "No"),
2438
+ "Section": change.get("Section", "General"),
2439
+ "ClauseReference": change.get("ClauseReference", "")
2440
+ })
2441
+ else:
2442
+ # Fallback to applying changes to existing parameters
2443
+ updated_params = apply_changes_to_params(existing_parameters.copy(), changes_list)
2444
+ else:
2445
+ print(f"⚠️ Warning: changes_list is not a list: {type(changes_list)}")
2446
+ updated_params = existing_parameters.copy()
2447
+
2448
+ # Validate for duplicates and similar parameters in edits
2449
+ validation_report = validate_parameters(updated_params)
2450
+
2451
+ if validation_report["duplicate_parameters"] or validation_report["similar_parameters"]:
2452
+ print("⚠️ Found duplicates/similar parameters in edit, cleaning up...")
2453
+ updated_params = deduplicate_parameters(updated_params)
2454
+ updated_params = apply_intelligent_fixes(updated_params)
2455
+ print("✅ Cleaned up duplicate parameters")
2456
 
2457
  # If we got a complete list, use it
2458
  if changes_list and all(change.get("Parameter") for change in changes_list):