# ------------------------------------------------------------------------------
# Intent detection patterns
# ------------------------------------------------------------------------------
TIME_PATTERNS = [
r"\bwhat(?:'s|\s+is)?\s+(?:the\s+)?time\s*(?:is\s+it|right\s+now|now)?\s*[?.]?\s*$",
r"\bwhat(?:'s|\s+is)?\s+(?:the\s+)?time\s+(?:in|for)\s+(?!an?\s+(?:hour|minute|second|moment|sec|min)\b)(?!a\s+while\b)(?!about\b)(?!\d+\b).+",
r"\b(?:current|local)\s+time\b",
r"\btime\s+(?:right\s+)?now\b",
r"^\s*now\??\s*$",
r"\bwhat(?:'s|\s+is)?\s+(?:the\s+)?date\b",
r"\btoday'?s?\s+date\b",
r"\bdate\s+today\b",
r"\bwhat\s+day\s+is\s+it\b",
r"\bday\s+of\s+week\b",
r"\byesterday\b",
r"\btime\s+(?:in|for)\s+(?!an?\s+(?:hour|minute|second|moment|sec|min)\b)(?!\d+\b)(.+)",
]
def has_time_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
return any(re.search(p, m, re.IGNORECASE) for p in TIME_PATTERNS)
WEATHER_PATTERNS = [
r"\bweather\b",
r"\bforecast\b",
r"\bwhat(?:'s|\s+is)?\s+(?:the\s+)?weather\b",
r"\bweather\s+(?:in|for)\s+.+",
r"\bwhat(?:'s|\s+is)?\s+(?:the\s+)?temperature\s*(?:in\b|for\b|\?|$)",
r"\btemperature\s+(?:in|for)\s+\S",
r"\bhow\s+(?:hot|cold|warm)\s+is\s+it\b",
r"\brain(?:ing)?\s+(?:in|for|today|now|outside|tomorrow)\b",
r"\b(?:in|for|today|now|outside|tomorrow)\s+rain(?:ing)?\b",
r"\bsnow(?:ing)?\b",
]
def has_weather_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
matches = [re.search(p, m, re.IGNORECASE) for p in WEATHER_PATTERNS]
if any(matches):
if re.search(r"\bsnow(?:ing)?\b", m, re.IGNORECASE):
if not re.search(r"\b(in|for|today|tomorrow|now|outside)\b", m, re.IGNORECASE):
return False
return True
return False
IMAGE_INTENT_PATTERNS = [
r"\b(generate|create|draw|make)\s+(?:an?\s+)?image\b",
r"\bimage\s+of\s+(?!my|your|his|her|our|their|this|that\b)",
r"\bpicture\s+of\s+(?!my|your|his|her|our|their|this|that\b)",
r"\bgenerate\s+(?:art|illustration|photo|graphic)\b",
r"\bdraw\s+me\b",
r"\bimagine\s+.+",
]
def has_image_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
if has_generate_video_intent(msg):
return False
return any(re.search(p, m, re.IGNORECASE) for p in IMAGE_INTENT_PATTERNS)
VIDEO_INTENT_PATTERNS = [
r"\byoutube\s+link\b",
r"\blink\s+to\s+(?:youtube|video)\b",
r"\b(?:give|find|share|play|watch)\s+(?:me\s+)?a\s+(?:youtube|video)\s+link\b",
r"\bsong\s+(?:video|link)\b",
r"\bmusic\s+video\b",
r"\bfunny\s+video\b"
]
VIDEO_GEN_KEYWORDS = re.compile(
r"\b(animate|generate\s+(?:a\s+)?video|create\s+(?:a\s+)?video|make\s+(?:a\s+)?video)\b", re.IGNORECASE
)
def has_video_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
if VIDEO_GEN_KEYWORDS.search(m):
return False
return any(re.search(p, m, re.IGNORECASE) for p in VIDEO_INTENT_PATTERNS)
EMAIL_PATTERNS = [
r"\bsend\s+(?:an?\s+)?email\b",
r"\bping\s+.+@.+\b",
r"\bcontact\s+ceo\b"
]
def has_email_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
return any(re.search(p, m, re.IGNORECASE) for p in EMAIL_PATTERNS)
NEWS_PATTERNS = [
r"\bnews\b",
r"\b(give|tell|what's|what is) (?:me )?(?:the )?news\b",
r"\bnews (?:for|in|about) (.+)\b",
r"\bheadlines\b",
r"\btop stories\b",
r"\bcurrent events\b",
r"\bbreaking news\b"
]
def has_news_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
return any(re.search(p, m, re.IGNORECASE) for p in NEWS_PATTERNS)
ANIMATE_LAST_PATTERNS = [
r"\b(turn|make|convert|transform|animate)\s+(?:the\s+)?(?:last|previous|recent)\s+(?:image|picture|photo)\b",
r"\bvideo\s+of\s+(?:the\s+)?last\b",
r"\badd\s+motion\s+to\s+last\b"
]
def has_animate_last_image_intent(msg: str) -> bool:
return any(re.search(p, msg.lower()) for p in ANIMATE_LAST_PATTERNS)
# Direct video generation (animate a cat, generate video of X)
GENERATE_VIDEO_PATTERNS = [
r"\banimate\s+(?:an?\s+)?(.+)",
r"\b(?:generate|create|make)\s+(?:an?\s+)?video\s+(?:of\s+)?(.+)",
r"\bvideo\s+of\s+(.+)",
]
def has_generate_video_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
if has_animate_last_image_intent(msg):
return False
return any(re.search(p, m, re.IGNORECASE) for p in GENERATE_VIDEO_PATTERNS)
def extract_video_prompt(msg: str) -> str:
"""Extract the subject/prompt from a direct video generation request."""
for p in GENERATE_VIDEO_PATTERNS:
m = re.search(p, msg.lower(), re.IGNORECASE)
if m and m.group(1):
prompt = m.group(1).strip()
prompt = re.sub(r"[?.!,;:\s]+$", "", prompt)
if len(prompt) > 3:
return prompt[:300]
return msg.strip()[:300]
def extract_motion_description(msg: str) -> str:
lower = msg.lower()
for kw in ["move", "dance", "walk", "run", "fly", "live", "cinematic", "animated"]:
if kw in lower:
idx = lower.find(kw)
tail = msg[idx:].strip()
tail = re.sub(r"^(?:the\s+)?(?:last|previous)\s+(?:image|picture)\s*", "", tail, flags=re.I)
if len(tail.strip()) > 5:
return tail[:150]
return "smooth cinematic animation, dynamic motion, high quality"
def is_hard_query(msg: str) -> bool:
lower_msg = msg.lower().strip()
if len(msg) < 50 or has_time_intent(msg) or has_weather_intent(msg) or "joke" in lower_msg or has_image_intent(msg) or has_video_intent(msg) or has_email_intent(msg) or has_news_intent(msg) or lower_msg.startswith(("hi", "hello", "sup", "what is", "who is", "tell me about", "what should i")):
return False
if any(kw in lower_msg for kw in ["math", "solve", "prove", "code", "program", "puzzle", "explain why", "how does", "think step by step", "analyze", "reason", "multi-step", "complex"]) or len(msg) > 100:
return True
return False
# Help intent
HELP_PATTERNS = [r"^help$", r"^what can you do", r"^commands$", r"^capabilities$"]
def has_help_intent(msg: str) -> bool:
m = (msg or "").strip().lower()
return any(re.search(p, m, re.IGNORECASE) for p in HELP_PATTERNS)
HELP_TEXT = (
"Here's what I can do:\n"
"Images: 'draw me a cat' / 'generate image of a sunset' / 'imagine a dragon'\n"
"Video: 'animate a dancing robot' / 'make a video of fireworks' / 'animate the last image'\n"
"Weather: 'weather in London' / 'forecast for NYC'\n"
"Time: 'what time is it in Tokyo'\n"
"News: 'give me the news' / 'news for UK'\n"
"YouTube: 'youtube link to Bohemian Rhapsody'\n"
"Email: 'send an email to user@example.com'\n"
"Clear context: 'clear my context'\n"
"Or just chat with me about anything!"
)