nikeshn commited on
Commit
16ce043
·
verified ·
1 Parent(s): a5e8df0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -21
app.py CHANGED
@@ -1492,9 +1492,7 @@ async def browse_subject(req: SubjectRequest, request: Request):
1492
  }}
1493
 
1494
  # Hard-filter against the real vocabulary. A name the model invented is
1495
- # discarded here rather than being handed to the search, where it would
1496
- # fail the category test and fall through to a broad area match that looks
1497
- # like a real answer.
1498
  bad_category = bool(category) and not is_real_category(category)
1499
  bad_area = bool(area) and not is_real_area(area)
1500
  if bad_category:
@@ -1506,27 +1504,54 @@ async def browse_subject(req: SubjectRequest, request: Request):
1506
  area, req.subject)
1507
  area = ""
1508
 
1509
- if not category and not area:
1510
- usage.usage.record_gap("journal_subject", "subject_unrecognised")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1511
  request.state.usage_recorded = True
1512
- near = suggest_categories(req.subject.strip(), limit=6)
1513
- hint = (" Closest SCImago categories: "
1514
- + ", ".join(n.title() for n in near) + ".") if near else ""
 
 
1515
  return {"result": {
1516
- "confidence": "not_found", "normalised": normalised,
1517
- "user_message": (user_message or
1518
- f"SCImago has no subject category matching '{req.subject.strip()}'."
1519
- + hint),
1520
- "journals": [],
1521
  }}
1522
 
1523
  journals, match_level = search_by_subject(category, area, top_n=30, with_level=True)
1524
 
1525
- # match_level 1 means nothing matched the category and these journals were
1526
- # selected by AREA alone — thousands of them, cut to 30 by h-index. That is
1527
- # a browsing aid, not an answer, and it must be labelled as one. The old
1528
- # `fallback_used` flag never fired for this case because the first search
1529
- # already returned a full page.
1530
  fallback_used = (match_level == 1)
1531
 
1532
  if not journals:
@@ -1561,9 +1586,10 @@ async def browse_subject(req: SubjectRequest, request: Request):
1561
 
1562
  msg = user_message
1563
  if fallback_used:
1564
- warn = (f"No SCImago category matched '{req.subject.strip()}'. "
1565
- f"These are the highest-ranked journals across the whole "
1566
- f"'{area.title()}' area, not a subject-specific list.")
 
1567
  msg = f"{msg} {warn}" if msg else warn
1568
  usage.usage.record_gap("journal_subject", "area_fallback")
1569
  request.state.usage_recorded = True
 
1492
  }}
1493
 
1494
  # Hard-filter against the real vocabulary. A name the model invented is
1495
+ # discarded here rather than handed to the search.
 
 
1496
  bad_category = bool(category) and not is_real_category(category)
1497
  bad_area = bool(area) and not is_real_area(area)
1498
  if bad_category:
 
1504
  area, req.subject)
1505
  area = ""
1506
 
1507
+ # Suggestions the user can act on: the model's nearest names, hard-filtered
1508
+ # to real ones, topped up deterministically. Never invented.
1509
+ def _suggestions() -> list:
1510
+ out, seen = [], set()
1511
+ for n in (parsed.get("nearest_categories") or []):
1512
+ n = str(n).strip().lower()
1513
+ if n and n not in seen and is_real_category(n):
1514
+ seen.add(n); out.append(n)
1515
+ for n in suggest_categories(req.subject.strip(), limit=6):
1516
+ if n not in seen:
1517
+ seen.add(n); out.append(n)
1518
+ counts = subject_vocabulary()["categories"]
1519
+ return [{"category": n.title(), "n_journals": counts.get(n, 0)} for n in out[:6]]
1520
+
1521
+ # An AREA is only a legitimate answer when the user asked for one. If the
1522
+ # model named a category and that category was not real, the user asked for
1523
+ # something specific that this taxonomy does not have — and answering with
1524
+ # 30 top journals from the surrounding area is a confidently wrong answer,
1525
+ # not a partial one. "Crime" is not served by showing Tourism Management.
1526
+ #
1527
+ # Refusing and naming the nearest real categories is both the honest answer
1528
+ # and the more useful one: Law, Sociology and Political Science, and
1529
+ # Pathology and Forensic Medicine are where criminology research is indexed.
1530
+ if bad_category or (not category and not area):
1531
+ usage.usage.record_gap(
1532
+ "journal_subject",
1533
+ "category_invented" if bad_category else "subject_unrecognised")
1534
  request.state.usage_recorded = True
1535
+ sugg = _suggestions()
1536
+ base = (f"SCImago and Scopus have no subject category for "
1537
+ f"'{req.subject.strip()}'.")
1538
+ hint = (" The closest indexed categories are: "
1539
+ + ", ".join(s["category"] for s in sugg) + ".") if sugg else ""
1540
  return {"result": {
1541
+ "confidence": "not_found",
1542
+ "normalised": normalised,
1543
+ "user_message": (user_message + " " if user_message else "") + base + hint,
1544
+ "suggestions": sugg,
1545
+ "journals": [],
1546
  }}
1547
 
1548
  journals, match_level = search_by_subject(category, area, top_n=30, with_level=True)
1549
 
1550
+ # Reaching here with match_level 1 now means only one thing: the model
1551
+ # named NO category and a real area, i.e. the user asked for the area.
1552
+ # "Show me top Engineering journals" is a legitimate request and this is
1553
+ # the correct answer to it — still labelled, because 30 rows out of
1554
+ # thousands ranked by h-index is a browsing aid, not a recommendation.
1555
  fallback_used = (match_level == 1)
1556
 
1557
  if not journals:
 
1586
 
1587
  msg = user_message
1588
  if fallback_used:
1589
+ warn = (f"'{req.subject.strip()}' is a subject AREA, not a specific "
1590
+ f"category. These are the highest-ranked journals across the "
1591
+ f"whole of '{area.title()}' by h-index — narrow to a category "
1592
+ f"for a subject-specific list.")
1593
  msg = f"{msg} {warn}" if msg else warn
1594
  usage.usage.record_gap("journal_subject", "area_fallback")
1595
  request.state.usage_recorded = True