zaheer140 commited on
Commit
9d31fb7
·
verified ·
1 Parent(s): 91596a1

Update agents/live/app/services/sql_agent.py

Browse files
agents/live/app/services/sql_agent.py CHANGED
@@ -382,6 +382,66 @@ FROM tank_reading
382
 
383
  def try_builtin_query(self, question: str, asset_name: str, schema_name: str | None = None, asset_id: str | None = None) -> SQLPlan | None:
384
  lowered = question.lower()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  if not asset_name:
386
  return None
387
 
 
382
 
383
  def try_builtin_query(self, question: str, asset_name: str, schema_name: str | None = None, asset_id: str | None = None) -> SQLPlan | None:
384
  lowered = question.lower()
385
+
386
+ # Multi-asset query check (e.g., "coldroom 1,2,3", "ct1,2,3", "tank 1 and 2", "coldroom 1, coldroom 2, coldroom 3")
387
+ multi_asset_match = re.findall(r'\b(coldroom|cold\s+room|ct|st|physical|tank|boiler|machine)\s*[-_]?\s*(\d+)\b', lowered)
388
+ digits = re.findall(r'\d+', lowered)
389
+ if (len(multi_asset_match) >= 2 or (',' in lowered and len(digits) >= 2)) and digits:
390
+ prefix = multi_asset_match[0][0].replace(" ", "") if multi_asset_match else "coldroom"
391
+ schema = schema_name or self.settings.openremote_schema
392
+ target_norms = []
393
+ for d in digits:
394
+ if prefix in ('coldroom', 'cold'):
395
+ target_norms.extend([f"coldroom{d}", f"coldroom0{d}"])
396
+ elif prefix in ('ct', 'tank', 'physical', 'st'):
397
+ target_norms.extend([f"ct{d}", f"tank{d}", f"physical{int(d):02d}", f"physical{d}"])
398
+ elif prefix == 'boiler':
399
+ target_norms.extend([f"boiler{d}", f"boiler0{d}"])
400
+ else:
401
+ target_norms.append(f"{prefix}{d}")
402
+
403
+ if target_norms:
404
+ in_clause = ", ".join(f"'{tn}'" for tn in target_norms)
405
+ sql = f"""
406
+ WITH target_assets AS (
407
+ SELECT DISTINCT ON (REPLACE(LOWER(name), ' ', ''))
408
+ id, name
409
+ FROM {schema}.asset
410
+ WHERE REPLACE(LOWER(name), ' ', '') IN ({in_clause})
411
+ ORDER BY REPLACE(LOWER(name), ' ', ''), version DESC
412
+ ),
413
+ latest_dp AS (
414
+ SELECT DISTINCT ON (entity_id, attribute_name)
415
+ entity_id, attribute_name, value, timestamp
416
+ FROM {schema}.asset_datapoint
417
+ WHERE entity_id IN (SELECT id FROM target_assets)
418
+ ORDER BY entity_id, attribute_name, timestamp DESC
419
+ ),
420
+ agg_dp AS (
421
+ SELECT
422
+ entity_id,
423
+ COALESCE(jsonb_object_agg(attribute_name, value), '{{}}'::jsonb) AS sensor_data
424
+ FROM latest_dp
425
+ GROUP BY entity_id
426
+ )
427
+ SELECT
428
+ ta.name AS asset_name,
429
+ NOW() + INTERVAL '3 hours' AS local_time,
430
+ (
431
+ COALESCE(
432
+ (SELECT jsonb_object_agg(key, val->'value')
433
+ FROM jsonb_each(a.attributes::jsonb) AS x(key, val)
434
+ WHERE val->'value' IS NOT NULL AND key NOT IN ('notes', 'location', 'info', 'displayIndex')),
435
+ '{{}}'::jsonb
436
+ ) || COALESCE(ad.sensor_data, '{{}}'::jsonb)
437
+ ) AS sensor_data
438
+ FROM target_assets ta
439
+ JOIN {schema}.asset a ON ta.id = a.id
440
+ LEFT JOIN agg_dp ad ON ta.id = ad.entity_id
441
+ ORDER BY ta.name ASC
442
+ """.strip()
443
+ return SQLPlan(needs_sql=True, scenario="multi_asset_comparison", sql=sql, answer_if_no_sql="")
444
+
445
  if not asset_name:
446
  return None
447