File size: 1,751 Bytes
8a2dcce | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | """
Category lookups for topic_metadata.json.
Used by the router to resolve "compare this with other X" style queries
that reference the previous topic implicitly, without naming a second
topic explicitly (e.g. "compare BFS with other graph algorithms").
"""
import json
import os
import config
from logs.logger import get_logger
logger = get_logger(__name__)
_metadata_cache = None
def _load_metadata() -> dict:
global _metadata_cache
if _metadata_cache is None:
if not os.path.exists(config.TOPIC_METADATA_PATH):
logger.warning("topic_metadata.json not found; category lookups disabled.")
_metadata_cache = {}
else:
with open(config.TOPIC_METADATA_PATH, "r", encoding="utf-8") as f:
_metadata_cache = json.load(f)
return _metadata_cache
def get_category(topic_name: str) -> str | None:
"""Returns the category string for a canonical topic name, or None."""
for entry in _load_metadata().values():
if entry.get("topic") == topic_name:
return entry.get("category")
return None
def get_sibling_topics(topic_name: str, exclude: list = None, limit: int = 2) -> list:
"""
Returns up to `limit` other topic names sharing the same category as
`topic_name` (e.g. siblings of "Breadth-First Search" in category
"Graph Traversal" -> ["Depth-First Search", "Dijkstra's Algorithm"]).
"""
exclude = set(exclude or []) | {topic_name}
category = get_category(topic_name)
if not category:
return []
siblings = [
entry["topic"]
for entry in _load_metadata().values()
if entry.get("category") == category and entry.get("topic") not in exclude
]
return siblings[:limit] |