perplexity-clone / rag /router.py
Naveen-2007's picture
Perplexity AI Clone - Full Production Version with 8 Modes
b02630d
import re
from config.config import Config
class RouterAgent:
"""
Production-grade router exactly like Perplexity:
1. Rule-based fast routing
2. NER-based entity detection
3. Real-time classifier
4. LLM semantic classifier (handles ANY query)
"""
def __init__(self):
self.llm = Config.get_llm()
# ---------------- FAST RULES ----------------
def contains(self, q, words):
q = q.lower()
return any(w in q for w in words)
def is_greeting(self, q):
q_low = q.lower().strip()
return q_low in ["hi", "hello", "hey", "yo", "sup", "hi there", "hello there"]
def is_image_query(self, q):
image_words = ["image", "photo", "pic", "picture", "logo", "wallpaper", "screenshot"]
return self.contains(q, image_words)
def is_realtime(self, q):
realtime = [
"today", "now", "latest", "current",
"price", "stock", "weather", "news",
"update", "live", "score", "match", "schedule"
]
return self.contains(q, realtime)
def is_world_fact(self, q):
patterns = [
"prime minister", "president", "capital of",
"ceo", "founder", "population", "richest",
"oldest", "largest", "smallest", "currency",
"country", "state", "city", "minister",
"government", "party"
]
return self.contains(q, patterns)
def is_ai_model(self, q):
ai_models = ["gpt", "gemini", "llama", "claude", "grok", "mistral", "phi"]
return self.contains(q, ai_models)
def is_definition(self, q):
q = q.lower()
return q.startswith(("what is", "define", "explain"))
def is_deep(self, q):
q = q.lower()
return any(x in q for x in [
"compare", "analysis", "impact", "advantages", "disadvantages",
"evaluate", "future", "strategy", "risk"
])
def is_entity(self, q):
"""Detects entities by uppercase words"""
words = q.split()
caps = [w for w in words if w[:1].isupper()]
return len(caps) >= 1
# ---------------- LLM CLASSIFIER ----------------
def llm_decide(self, q):
"""
FINAL DECISION MAKER.
If rules fail or query is unusual β†’ LLM decides mode.
"""
system = {
"role": "system",
"content": """
Classify this query into exactly one mode:
- "web" β†’ real-time facts, entities, news, people, companies, trending topics
- "rag" β†’ definitions, conceptual explanations, structured factual info
- "llm" β†’ normal chat, creative tasks, responses without external info
- "deep_research" β†’ multi-step analysis, long reports, deep comparisons
Return ONLY one word: web, rag, llm, or deep_research.
"""
}
user = {"role": "user", "content": q}
resp = self.llm.invoke([system, user]).content.strip().lower()
if resp in ["web", "rag", "llm", "deep_research"]:
return resp
return "llm"
# ---------------- FINAL ROUTER ----------------
def route(self, q: str) -> str:
q = q.strip()
# LAYER 1 β€” FAST RULES
if self.is_greeting(q): return "llm"
if self.is_image_query(q): return "image"
if self.is_realtime(q): return "web"
if self.is_world_fact(q): return "web"
if self.is_ai_model(q): return "web"
# Short entity queries (1-2 words) β†’ web
if len(q.split()) <= 2 and self.is_entity(q): return "web"
if self.is_deep(q): return "deep_research"
if self.is_definition(q): return "rag"
# LAYER 2 β€” LLM SEMANTIC CLASSIFICATION
return self.llm_decide(q)