nikeshn commited on
Commit
d949433
Β·
verified Β·
1 Parent(s): 058b5cb

Update src/api/agent.py

Browse files
Files changed (1) hide show
  1. src/api/agent.py +26 -19
src/api/agent.py CHANGED
@@ -1219,6 +1219,9 @@ BOOLEAN RULES β€” follow strictly:
1219
  - Max 3 AND groups. Each group max 4 OR terms.
1220
  - NEVER put years as Boolean terms β€” put them in year_from/year_to
1221
  - Keep broad enough to return results
 
 
 
1222
 
1223
  EXAMPLES:
1224
  Input: "find articles on global warming and renewable energy"
@@ -1229,6 +1232,14 @@ Input: "peer reviewed articles last 5 years on machine learning healthcare"
1229
  β†’ boolean:("machine learning" OR "deep learning" OR "AI") AND ("healthcare" OR "medicine" OR "clinical")
1230
  β†’ year_from:"{CURRENT_YEAR - 5}", peer_reviewed:true
1231
 
 
 
 
 
 
 
 
 
1232
  Input: "summarize shift in personalized genomic medicine from N-of-1 trials last 24 months"
1233
  β†’ boolean:("personalized genomic medicine" OR "precision medicine") AND ("N-of-1 trials" OR "scalable precision")
1234
  β†’ year_from:"{CURRENT_YEAR - 2}", peer_reviewed:true
@@ -1399,31 +1410,27 @@ async def _semantic_scholar_search(topic: str, limit: int = 8) -> List[dict]:
1399
 
1400
  async def _openalex_search(topic: str, limit: int = 8) -> List[dict]:
1401
  """
1402
- Search OpenAlex using the ?search= relevance engine β€” same approach as the
1403
- clickable OpenAlex link shown to users, which consistently returns relevant results.
1404
-
1405
- Previous approach used ?filter=title.search:X|abstract.search:X β€” a strict
1406
- field-level filter requiring exact token matches in title/abstract only, which
1407
- returned irrelevant or zero results. The ?search= parameter uses OpenAlex's
1408
- full relevance engine across all fields, identical to the browser link.
1409
  """
1410
  try:
1411
- from urllib.parse import quote
1412
 
1413
- # Strip boolean operators and retrieval filler β€” keep only keywords.
1414
- # Matches what the user-facing OpenAlex link does.
1415
  clean = re.sub(r'\b(AND|OR|NOT)\b|[()"\']', ' ', topic, flags=re.IGNORECASE)
1416
  clean = re.sub(
1417
- r'\b(find|search|show|get|give|recent|research on|articles? on'
1418
- r'|papers? on|literature on|studies on|overview of|summary of|review of)\b',
1419
  ' ', clean, flags=re.IGNORECASE,
1420
  )
1421
  clean = re.sub(r'\s+', ' ', clean).strip()[:150]
1422
- encoded = quote(clean, safe='')
1423
 
1424
  select = "id,title,authorships,publication_year,primary_location,abstract_inverted_index,doi,cited_by_count,open_access"
1425
 
1426
- # FIX: use ?search= β€” same as the clickable OpenAlex link
1427
  url = (
1428
  f"https://api.openalex.org/works"
1429
  f"?search={encoded}"
@@ -1581,8 +1588,8 @@ async def _search_primo_catalog(context: SearchContextPayload, limit: int = 5) -
1581
  boolean = clean_topic or context.topic
1582
  result = await search_primo(
1583
  SearchRequest(
1584
- query=context.topic, # plain topic as q= fallback
1585
- boolean_query=boolean, # FIX: boolean goes here so _boolean_to_primo_params() fires
1586
  source="primo",
1587
  limit=limit,
1588
  peer_reviewed=context.peer_reviewed,
@@ -2382,7 +2389,7 @@ async def _research_snapshot(context: SearchContextPayload, model: str) -> Tuple
2382
 
2383
  # Parallel fetch: OpenAlex (fast, free) + PRIMO
2384
  papers, (primo_result, primo_url) = await _asyncio.gather(
2385
- _openalex_search(context.ai_tool_query or context.topic, limit=8), # FIX: richer natural query
2386
  _search_primo_catalog(context, limit=6),
2387
  )
2388
 
@@ -2814,7 +2821,7 @@ async def _run_search_mode(
2814
  if use_openalex:
2815
  (result, source_url), oa_papers = await _aio.gather(
2816
  _search_pubmed_articles(context, limit=6),
2817
- _openalex_search(context.ai_tool_query or context.topic, limit=5), # FIX: richer natural query
2818
  )
2819
  else:
2820
  result, source_url = await _search_pubmed_articles(context, limit=6)
@@ -2824,7 +2831,7 @@ async def _run_search_mode(
2824
  if use_openalex:
2825
  (result, source_url), oa_papers = await _aio.gather(
2826
  _search_primo_catalog(context, limit=6),
2827
- _openalex_search(context.ai_tool_query or context.topic, limit=5), # FIX: richer natural query
2828
  )
2829
  else:
2830
  result, source_url = await _search_primo_catalog(context, limit=6)
 
1219
  - Max 3 AND groups. Each group max 4 OR terms.
1220
  - NEVER put years as Boolean terms β€” put them in year_from/year_to
1221
  - Keep broad enough to return results
1222
+ - NAMED ENTITIES: Any specific keyword that is a country, island, city, person,
1223
+ organisation, or proper noun MUST be kept as its own AND group. Never drop it.
1224
+ e.g. "Maldives" β†’ AND ("Maldives" OR "Maldivian") ; "UAE" β†’ AND ("UAE" OR "United Arab Emirates")
1225
 
1226
  EXAMPLES:
1227
  Input: "find articles on global warming and renewable energy"
 
1232
  β†’ boolean:("machine learning" OR "deep learning" OR "AI") AND ("healthcare" OR "medicine" OR "clinical")
1233
  β†’ year_from:"{CURRENT_YEAR - 5}", peer_reviewed:true
1234
 
1235
+ Input: "impact of global warming in Maldives"
1236
+ β†’ boolean:("global warming" OR "climate change") AND ("Maldives" OR "sea level rise" OR "small island")
1237
+ β†’ year_from:"", peer_reviewed:false
1238
+
1239
+ Input: "water scarcity solutions in UAE"
1240
+ β†’ boolean:("water scarcity" OR "water stress") AND ("UAE" OR "United Arab Emirates" OR "Gulf region")
1241
+ β†’ year_from:"", peer_reviewed:false
1242
+
1243
  Input: "summarize shift in personalized genomic medicine from N-of-1 trials last 24 months"
1244
  β†’ boolean:("personalized genomic medicine" OR "precision medicine") AND ("N-of-1 trials" OR "scalable precision")
1245
  β†’ year_from:"{CURRENT_YEAR - 2}", peer_reviewed:true
 
1410
 
1411
  async def _openalex_search(topic: str, limit: int = 8) -> List[dict]:
1412
  """
1413
+ Search OpenAlex using the ?search= relevance engine.
1414
+ This matches the clickable OpenAlex link shown to users.
1415
+ The previous ?filter=title.search:X|abstract.search:X approach was a strict
1416
+ field-level filter that returned irrelevant results. The ?search= parameter
1417
+ uses OpenAlex full relevance ranking across all fields.
 
 
1418
  """
1419
  try:
1420
+ from urllib.parse import quote as _oa_quote
1421
 
1422
+ # Strip boolean operators and common retrieval filler words.
 
1423
  clean = re.sub(r'\b(AND|OR|NOT)\b|[()"\']', ' ', topic, flags=re.IGNORECASE)
1424
  clean = re.sub(
1425
+ r'\b(find|search|show|get|give|research on|articles on'
1426
+ r'|papers on|literature on|studies on|overview of|summary of|review of)\b',
1427
  ' ', clean, flags=re.IGNORECASE,
1428
  )
1429
  clean = re.sub(r'\s+', ' ', clean).strip()[:150]
1430
+ encoded = _oa_quote(clean, safe='')
1431
 
1432
  select = "id,title,authorships,publication_year,primary_location,abstract_inverted_index,doi,cited_by_count,open_access"
1433
 
 
1434
  url = (
1435
  f"https://api.openalex.org/works"
1436
  f"?search={encoded}"
 
1588
  boolean = clean_topic or context.topic
1589
  result = await search_primo(
1590
  SearchRequest(
1591
+ query=context.topic,
1592
+ boolean_query=boolean,
1593
  source="primo",
1594
  limit=limit,
1595
  peer_reviewed=context.peer_reviewed,
 
2389
 
2390
  # Parallel fetch: OpenAlex (fast, free) + PRIMO
2391
  papers, (primo_result, primo_url) = await _asyncio.gather(
2392
+ _openalex_search(context.ai_tool_query or context.topic, limit=8),
2393
  _search_primo_catalog(context, limit=6),
2394
  )
2395
 
 
2821
  if use_openalex:
2822
  (result, source_url), oa_papers = await _aio.gather(
2823
  _search_pubmed_articles(context, limit=6),
2824
+ _openalex_search(context.ai_tool_query or context.topic, limit=5),
2825
  )
2826
  else:
2827
  result, source_url = await _search_pubmed_articles(context, limit=6)
 
2831
  if use_openalex:
2832
  (result, source_url), oa_papers = await _aio.gather(
2833
  _search_primo_catalog(context, limit=6),
2834
+ _openalex_search(context.ai_tool_query or context.topic, limit=5),
2835
  )
2836
  else:
2837
  result, source_url = await _search_primo_catalog(context, limit=6)