nikeshn commited on
Commit
ea8a00e
Β·
verified Β·
1 Parent(s): 35f7d12

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -4
app.py CHANGED
@@ -1286,6 +1286,29 @@ def _make_boolean(text: str) -> str:
1286
  def _clean_database_keywords(boolean_query: str) -> str:
1287
  return re.sub(r'\s+', ' ', re.sub(r'\b(AND|OR|NOT)\b|[()"]', ' ', boolean_query, flags=re.IGNORECASE)).strip()
1288
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1289
  def _light_strip_retrieval_boilerplate(text: str) -> str:
1290
  cleaned = re.sub(r'^\s*(please\s+)?(?:can you|could you|would you)\s+', '', (text or '').strip(), flags=re.IGNORECASE)
1291
  cleaned = re.sub(r'^\s*(please\s+)?help me\s+', '', cleaned, flags=re.IGNORECASE)
@@ -1583,8 +1606,32 @@ Input: "Find one peer-reviewed article from the last five years on climate chang
1583
  β†’ natural:"Peer-reviewed article from the last five years on climate change and biodiversity. Summarize the methodology and findings."
1584
  β†’ boolean:("climate change" OR "global warming") AND (biodiversity OR ecosystems)
1585
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1586
  Return ONLY valid JSON:
1587
- {{"corrected":"full polished request","natural":"full natural-language research query","boolean":"(A OR B) AND (C OR D)","year_from":"","year_to":"","peer_reviewed":false,"open_access":false}}
1588
 
1589
  Query: "{light_query}"""
1590
  try:
@@ -1598,6 +1645,8 @@ Query: "{light_query}"""
1598
  has_parens = "(" in boolean if boolean else False
1599
  if not has_operators or not has_parens:
1600
  boolean = _make_boolean(corrected)
 
 
1601
  return {
1602
  "corrected": corrected,
1603
  "natural": natural,
@@ -2516,14 +2565,21 @@ async def agent_query(req: AgentRequest):
2516
  combined = synthesis_pool + [r for r in combined if r not in synthesis_pool]
2517
  else:
2518
  from urllib.parse import quote as _quote
2519
- # Use the Boolean query in PRIMO advanced search β€” same format as the frontend buildSearchCard
2520
- # URL format: query=any,contains,{encoded_boolean},AND&tab=Everything&search_scope=MyInst_and_CI&mode=advanced
2521
- _bool = search_plan.get("boolean") or database_query
 
 
 
 
 
 
2522
  _primo_url = (
2523
  "https://khalifa.primo.exlibrisgroup.com/discovery/search"
2524
  + "?query=any,contains," + _quote(_bool) + ",AND"
2525
  + "&tab=Everything&search_scope=MyInst_and_CI"
2526
  + "&vid=971KUOSTAR_INST:KU&lang=en&mode=advanced&offset=0"
 
2527
  )
2528
  answer = (
2529
  "I searched PRIMO for literature on this topic but couldn't retrieve "
 
1286
  def _clean_database_keywords(boolean_query: str) -> str:
1287
  return re.sub(r'\s+', ' ', re.sub(r'\b(AND|OR|NOT)\b|[()"]', ' ', boolean_query, flags=re.IGNORECASE)).strip()
1288
 
1289
+ def _sanitize_boolean_for_primo(boolean: str) -> str:
1290
+ """
1291
+ Clean an LLM-generated Boolean string so it works in PRIMO advanced search URLs.
1292
+ PRIMO accepts: ("smart city" OR "urban mobility") AND ("technocentricity")
1293
+ PRIMO rejects: single quotes, year-only groups, overly long strings.
1294
+ """
1295
+ if not boolean:
1296
+ return boolean
1297
+ # Replace single quotes with double quotes around terms
1298
+ # e.g. ('Technocentricity') β†’ ("Technocentricity")
1299
+ boolean = re.sub(r"'([^']+)'", r'"\1"', boolean)
1300
+ # Remove pure-year groups like (2025 OR 2026) or (2024) β€” years belong in date facets
1301
+ boolean = re.sub(r'\(\s*(?:(?:19|20)\d{2}\s*(?:OR\s*(?:19|20)\d{2}\s*)*)\)', '', boolean, flags=re.IGNORECASE)
1302
+ # Remove dangling AND/OR at start or end after year group removal
1303
+ boolean = re.sub(r'^\s*(AND|OR)\s*', '', boolean, flags=re.IGNORECASE)
1304
+ boolean = re.sub(r'\s*(AND|OR)\s*$', '', boolean, flags=re.IGNORECASE)
1305
+ # Collapse double AND/OR
1306
+ boolean = re.sub(r'(AND|OR)\s+(AND|OR)', r'\1', boolean, flags=re.IGNORECASE)
1307
+ # Collapse excess whitespace
1308
+ boolean = re.sub(r'\s+', ' ', boolean).strip()
1309
+ return boolean
1310
+
1311
+
1312
  def _light_strip_retrieval_boilerplate(text: str) -> str:
1313
  cleaned = re.sub(r'^\s*(please\s+)?(?:can you|could you|would you)\s+', '', (text or '').strip(), flags=re.IGNORECASE)
1314
  cleaned = re.sub(r'^\s*(please\s+)?help me\s+', '', cleaned, flags=re.IGNORECASE)
 
1606
  β†’ natural:"Peer-reviewed article from the last five years on climate change and biodiversity. Summarize the methodology and findings."
1607
  β†’ boolean:("climate change" OR "global warming") AND (biodiversity OR ecosystems)
1608
 
1609
+ BOOLEAN RULES β€” follow strictly:
1610
+ - Use DOUBLE quotes only around multi-word phrases: ("smart city" OR "urban mobility")
1611
+ - NEVER use single quotes: wrong: ('smart city') right: ("smart city")
1612
+ - Max 3 AND groups. Each group max 4 OR terms.
1613
+ - NEVER put years (2024, 2025, 2026) as Boolean terms β€” put them in year_from/year_to instead.
1614
+ - Comparison topics (e.g. "London vs Bogota", "Global vs Emerging cities") β†’ extract the CONCEPT
1615
+ as a search term, not the city names: e.g. ("smart city" OR "urban governance") AND ("smart mobility")
1616
+ - Keep it simple enough to return results. Prefer broader terms over hyper-specific phrases.
1617
+
1618
+ YEAR DETECTION: if question mentions "2025-2026", "last year", "recent", "current" β†’ set year_from appropriately.
1619
+
1620
+ Examples:
1621
+ Input: "Technocentricity vs Citizen-Centricity in Smart City development, contrast 2025-2026 outcomes of smart mobility in Global Metropolitan Leaders vs Emerging Global Cities"
1622
+ β†’ boolean:("smart city" OR "urban governance") AND ("technocentricity" OR "citizen-centric") AND ("smart mobility" OR "urban transport")
1623
+ β†’ year_from:"2023", year_to:"", peer_reviewed:true
1624
+
1625
+ Input: "Summarize shift in Personalized Genomic Medicine from N-of-1 trials to Scalable Precision Platforms last 24 months"
1626
+ β†’ boolean:("personalized genomic medicine" OR "precision medicine") AND ("N-of-1 trials" OR "scalable precision")
1627
+ β†’ year_from:"{year-2}", peer_reviewed:true
1628
+
1629
+ Input: "Find one peer-reviewed article from the last five years on climate change and biodiversity"
1630
+ β†’ boolean:("climate change" OR "global warming") AND (biodiversity OR ecosystems)
1631
+ β†’ year_from:"{year-5}", peer_reviewed:true
1632
+
1633
  Return ONLY valid JSON:
1634
+ {{"corrected":"full polished request","natural":"full natural-language research query","boolean":"(\"A\" OR \"B\") AND (\"C\" OR \"D\")","year_from":"","year_to":"","peer_reviewed":false,"open_access":false}}
1635
 
1636
  Query: "{light_query}"""
1637
  try:
 
1645
  has_parens = "(" in boolean if boolean else False
1646
  if not has_operators or not has_parens:
1647
  boolean = _make_boolean(corrected)
1648
+ # Sanitize: fix single quotes β†’ double quotes, strip year groups (years go in facets)
1649
+ boolean = _sanitize_boolean_for_primo(boolean)
1650
  return {
1651
  "corrected": corrected,
1652
  "natural": natural,
 
2565
  combined = synthesis_pool + [r for r in combined if r not in synthesis_pool]
2566
  else:
2567
  from urllib.parse import quote as _quote
2568
+ # Sanitize boolean: fix single quotes -> double quotes, strip year groups
2569
+ _bool_raw = search_plan.get("boolean") or database_query
2570
+ _bool = _sanitize_boolean_for_primo(_bool_raw)
2571
+ # Build URL using the SAME format as the frontend buildSearchCard (Approach 1 β€” confirmed working):
2572
+ # query=any,contains,{encoded_full_boolean},AND&tab=Everything&search_scope=MyInst_and_CI&mode=advanced
2573
+ _facet = ""
2574
+ if year_from:
2575
+ _yt = year_to or str(datetime.now().year)
2576
+ _facet = "&multiFacets=facet_searchcreationdate,include," + year_from + "%7C,%7C" + _yt
2577
  _primo_url = (
2578
  "https://khalifa.primo.exlibrisgroup.com/discovery/search"
2579
  + "?query=any,contains," + _quote(_bool) + ",AND"
2580
  + "&tab=Everything&search_scope=MyInst_and_CI"
2581
  + "&vid=971KUOSTAR_INST:KU&lang=en&mode=advanced&offset=0"
2582
+ + _facet
2583
  )
2584
  answer = (
2585
  "I searched PRIMO for literature on this topic but couldn't retrieve "