| import logging |
| from typing import Dict |
|
|
| from src.recommendation_engine.llm_client import generate_text |
|
|
| logger = logging.getLogger(__name__) |
|
|
| VALID_INTENTS = { |
| "idea", |
| "feature", |
| "full_project", |
| "chat" |
| } |
|
|
| def normalize_intent(text: str) -> str: |
|
|
| if not text: |
| return "chat" |
|
|
| text = text.lower().strip().split()[0] |
|
|
| if text in VALID_INTENTS: |
| return text |
|
|
| return "chat" |
|
|
| def classify_with_llm(user_input: str, state: Dict) -> str: |
|
|
| prompt = f""" |
| You are an intent classifier for a graduation project assistant. |
| |
| Return ONLY ONE word from: |
| idea |
| feature |
| description |
| full_project |
| chat |
| |
| Context: |
| Project Title: {state.get("project_title") or "None"} |
| Has Features: {"yes" if state.get("features") else "no"} |
| Has Description: {"yes" if state.get("description") else "no"} |
| |
| User: |
| "{user_input}" |
| |
| Rules: |
| - Asking for ideas β idea |
| - Asking for another idea β idea |
| - Giving a project idea β feature |
| - Asking for features β feature |
| - Asking for description β description |
| - Asking for full project β full_project |
| - Otherwise β chat |
| """ |
|
|
| try: |
| result = generate_text(prompt, task="intent") |
| return normalize_intent(result) |
|
|
| except Exception as e: |
| logger.warning(f"[INTENT ERROR] {e}") |
| return "chat" |
|
|
| def detect_intent(text: str, state: dict = None) -> str: |
|
|
| if state is None: |
| state = {} |
|
|
| text_clean = text.lower().strip() |
|
|
| has_project = bool(state.get("project_title")) |
| has_features = bool(state.get("features")) |
|
|
| |
| |
| |
|
|
| |
| if any(x in text_clean for x in [ |
| "idea", "project idea", "new idea", "another idea", "suggest" |
| ]): |
| return "idea" |
|
|
| |
| if "feature" in text_clean: |
| return "feature" |
|
|
| |
| if any(x in text_clean for x in [ |
| "full project", "complete", "all details" |
| ]): |
| return "full_project" |
|
|
| |
| |
| |
| |
| if not has_project and len(text_clean.split()) >= 3: |
| return "feature" |
|
|
| |
| |
| |
| intent = classify_with_llm(text, state) |
|
|
| logger.info(f"[INTENT] {intent}") |
|
|
| |
| |
| |
| if intent == "feature" and not has_project: |
| return "feature" |
|
|
| if intent == "description" and not has_project: |
| return "idea" |
|
|
| return intent |
|
|