"""Blueprint identifying faculty whose research mentions a given topic.""" from __future__ import annotations import re from typing import Any, Dict, List from .base import AnalysisContext, Blueprint, BlueprintResult, Fact class FacultyByTopicBlueprint(Blueprint): """Return faculty whose research interests mention a topic.""" name = "faculty_by_topic" def run(self, context: AnalysisContext, **kwargs: Any) -> BlueprintResult: topic = (kwargs.get("topic") or "").strip() if not topic: return BlueprintResult(self.name, kwargs, facts=[], notes=["No topic provided."]) topic_lower = re.sub(r"[?.!]+$", "", topic.lower()) tokens = [tok for tok in re.split(r"[^a-z0-9]+", topic_lower) if tok] if not tokens: return BlueprintResult(self.name, kwargs, facts=[], notes=[f"Topic '{topic}' is too vague."]) search_terms = set() search_terms.add(" ".join(tokens)) search_terms.update(tokens) if "ai" in tokens: search_terms.add("artificial intelligence") if "ml" in tokens: search_terms.add("machine learning") dataset = context.catalog.get("faculty") matches: List[Fact] = [] for row in dataset.records: research = (row.get("Research Interests") or "").lower() if any(term in research for term in search_terms): matches.append( Fact( subject=row.get("Name", "Unknown"), predicate="research_focus", value=row.get("Research Interests"), source=dataset.origin, ) ) notes: List[str] = [] if not matches: notes.append(f"No faculty rows mention '{topic}'.") return BlueprintResult(self.name, kwargs, facts=matches, notes=notes)