Spaces:
Sleeping
Sleeping
| import os | |
| import warnings | |
| # === CRITICAL: Set cache directories BEFORE any other imports === | |
| os.environ['HF_HOME'] = '/tmp/huggingface_cache' | |
| os.environ['TRANSFORMERS_CACHE'] = '/tmp/transformers_cache' | |
| os.environ['HF_DATASETS_CACHE'] = '/tmp/datasets_cache' | |
| warnings.filterwarnings("ignore") | |
| import json | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| from dotenv import load_dotenv | |
| from google.adk.agents import Agent | |
| from google.adk.sessions import InMemorySessionService | |
| from google.adk.runners import Runner | |
| from google.genai import types | |
| import re | |
| import asyncio | |
| from tools import ( | |
| db_tool, | |
| tavily_tool, | |
| predictor_tool, | |
| mentor_tool, | |
| add_query_to_sheet | |
| ) | |
| # === LOAD ENV === | |
| load_dotenv() | |
| HF_TOKEN = os.getenv("HUGGINGFACE_TOKEN") | |
| GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY") | |
| # === PREPROCESSING DICTIONARY === | |
| INSTITUTE_MAPPING = { | |
| "iit": ["indian institute of technology"], | |
| "IIT": ["indian institute of technology"], | |
| "i.i.t": ["indian institute of technology"], | |
| "I.I.T": ["indian institute of technology"], | |
| "i i t": ["indian institute of technology"], | |
| "I I T": ["indian institute of technology"], | |
| "indian institute of technology": ["indian institute of technology"], | |
| "Indian Institute of Technology": ["indian institute of technology"], | |
| "nit": ["national institute of technology"], | |
| "NIT": ["national institute of technology"], | |
| "n.i.t": ["national institute of technology"], | |
| "N.I.T": ["national institute of technology"], | |
| "n i t": ["national institute of technology"], | |
| "N I T": ["national institute of technology"], | |
| "national institute of technology": ["national institute of technology"], | |
| "National Institute of Technology": ["national institute of technology"], | |
| "iiit": ["indian institute of information technology"], | |
| "IIIT": ["indian institute of information technology"], | |
| "i.i.i.t": ["indian institute of information technology"], | |
| "I.I.I.T": ["indian institute of information technology"], | |
| "i i i t": ["indian institute of information technology"], | |
| "I I I T": ["indian institute of information technology"], | |
| "indian institute of information technology": ["indian institute of information technology"], | |
| "Indian Institute of Information Technology": ["indian institute of information technology"], | |
| "bit": ["birla institute of technology"], | |
| "BIT": ["birla institute of technology"], | |
| "b.i.t": ["birla institute of technology"], | |
| "B.I.T": ["birla institute of technology"], | |
| "b i t": ["birla institute of technology"], | |
| "B I T": ["birla institute of technology"], | |
| "birla institute of technology": ["birla institute of technology"], | |
| "Birla Institute of Technology": ["birla institute of technology"], | |
| "bits": ["birla institute of technology and science"], | |
| "BITS": ["birla institute of technology and science"], | |
| "b.i.t.s": ["birla institute of technology and science"], | |
| "B.I.T.S": ["birla institute of technology and science"], | |
| "b i t s": ["birla institute of technology and science"], | |
| "B I T S": ["birla institute of technology and science"], | |
| "birla institute of technology and science": ["birla institute of technology and science"], | |
| "Birla Institute of Technology and Science": ["birla institute of technology and science"], | |
| "dtu": ["delhi technological university"], | |
| "DTU": ["delhi technological university"], | |
| "nsut": ["netaji subhas university of technology"], | |
| "NSUT": ["netaji subhas university of technology"], | |
| "iiitd": ["indraprastha institute of information technology delhi"], | |
| "IIITD": ["indraprastha institute of information technology delhi"], | |
| "iiith": ["international institute of information technology hyderabad"], | |
| "IIITH": ["international institute of information technology hyderabad"], | |
| "iiitb": ["international institute of information technology bangalore"], | |
| "IIITB": ["international institute of information technology bangalore"], | |
| "vit": ["vellore institute of technology"], | |
| "VIT": ["vellore institute of technology"], | |
| "srm": ["srm institute of science and technology"], | |
| "SRM": ["srm institute of science and technology"], | |
| "mit": ["manipal institute of technology"], | |
| "MIT": ["manipal institute of technology"], | |
| "pes": ["pes university"], | |
| "PES": ["pes university"], | |
| "bms": ["bms college of engineering"], | |
| "BMS": ["bms college of engineering"], | |
| "rv": ["rv college of engineering"], | |
| "RV": ["rv college of engineering"], | |
| "ramaiah": ["ms ramaiah institute of technology"], | |
| "RAMAIAH": ["ms ramaiah institute of technology"], | |
| "thapar": ["thapar institute of engineering and technology"], | |
| "THAPAR": ["thapar institute of engineering and technology"], | |
| "ism": ["indian school of mines"], | |
| "ISM": ["indian school of mines"], | |
| "spa": ["school of planning & architecture"], | |
| "SPA": ["school of planning & architecture"], | |
| "vnit": ["visvesvaraya national institute of technology"], | |
| "VNIT": ["visvesvaraya national institute of technology"], | |
| "manit": ["maulana azad national institute of technology"], | |
| "MANIT": ["maulana azad national institute of technology"], | |
| "svnit": ["sardar vallabhbhai national institute of technology"], | |
| "SVNIT": ["sardar vallabhbhai national institute of technology"], | |
| "mnit": ["malaviya national institute of technology"], | |
| "MNIT": ["malaviya national institute of technology"], | |
| "mnnit": ["motilal nehru national institute of technology"], | |
| "MNNIT": ["motilal nehru national institute of technology"], | |
| "sliet": ["sant longowal institute of engineering and technology"], | |
| "SLIET": ["sant longowal institute of engineering and technology"], | |
| "iiest": ["indian institute of engineering science and technology"], | |
| "IIEST": ["indian institute of engineering science and technology"], | |
| "cusat": ["cochin university of science and technology"], | |
| "CUSAT": ["cochin university of science and technology"], | |
| "niftem": ["national institute of food technology entrepreneurship and management"], | |
| "NIFTEM": ["national institute of food technology entrepreneurship and management"], | |
| "iiht": ["indian institute of handloom technology"], | |
| "IIHT": ["indian institute of handloom technology"], | |
| "ict": ["institute of chemical technology"], | |
| "ICT": ["institute of chemical technology"], | |
| "iitram": ["institute of infrastructure, technology, research and management"], | |
| "IITRAM": ["institute of infrastructure, technology, research and management"], | |
| "csvtu": ["chhattisgarh swami vivekanada technical university"], | |
| "CSVTU": ["chhattisgarh swami vivekanada technical university"], | |
| "gkc": ["ghani khan choudhary institute of engineering and technology"], | |
| "GKC": ["ghani khan choudhary institute of engineering and technology"], | |
| "nerist": ["north eastern regional institute of science and technology"], | |
| "NERIST": ["north eastern regional institute of science and technology"], | |
| "cit": ["central institute of technology"], | |
| "CIT": ["central institute of technology"], | |
| "tezu": ["tezpur university"], | |
| "TEZU": ["tezpur university"], | |
| "nehu": ["north-eastern hill university"], | |
| "NEHU": ["north-eastern hill university"], | |
| "mizoram": ["mizoram university"], | |
| "MIZORAM": ["mizoram university"], | |
| "assam": ["assam university"], | |
| "ASSAM": ["assam university"], | |
| "smvdu": ["shri mata vaishno devi university"], | |
| "SMVDU": ["shri mata vaishno devi university"], | |
| "pu": ["puducherry university"], | |
| "PU": ["puducherry university"], | |
| "ptu": ["puducherry technological university"], | |
| "PTU": ["puducherry technological university"], | |
| "jnu": ["jawaharlal nehru university"], | |
| "JNU": ["jawaharlal nehru university"], | |
| "uoh": ["university of hyderabad"], | |
| "UOH": ["university of hyderabad"], | |
| "ggu": ["guru ghasidas vishwavidyalaya"], | |
| "GGU": ["guru ghasidas vishwavidyalaya"], | |
| "cu": ["central university"], | |
| "CU": ["central university"], | |
| "gsv": ["gati shakti vishwavidyalaya"], | |
| "GSV": ["gati shakti vishwavidyalaya"], | |
| "gkv": ["gurukula kangri vishwavidyalaya"], | |
| "GKV": ["gurukula kangri vishwavidyalaya"] | |
| } | |
| BRANCH_MAPPING = { | |
| "cse": "computer science and engineering", | |
| "CSE": "computer science and engineering", | |
| "cs": "computer science and engineering", | |
| "CS": "computer science and engineering", | |
| "ece": "electronics and communication engineering", | |
| "ECE": "electronics and communication engineering", | |
| "ee": "electrical engineering", | |
| "EE": "electrical engineering", | |
| "MECH": "mechanical engineering", | |
| "mech": "mechanical engineering", | |
| "ce": "civil engineering", | |
| "CE": "civil engineering", | |
| "che": "chemical engineering", | |
| "CHE": "chemical engineering", | |
| "aero": "aerospace engineering", | |
| "AERO": "aerospace engineering", | |
| "bio": "biotechnology", | |
| "BIO": "biotechnology" | |
| } | |
| # === PREPROCESSING FUNCTION === | |
| def preprocess_query(query: str) -> str: | |
| sorted_institutes = sorted(INSTITUTE_MAPPING.keys(), key=len, reverse=True) | |
| for key in sorted_institutes: | |
| pattern = rf'\b{re.escape(key)}\b' | |
| query = re.sub(pattern, INSTITUTE_MAPPING[key][0], query, flags=re.IGNORECASE) | |
| for key, full_name in BRANCH_MAPPING.items(): | |
| pattern = rf'\b{re.escape(key)}\b' | |
| query = re.sub(pattern, full_name, query, flags=re.IGNORECASE) | |
| return query | |
| # === AGENT SETUP === | |
| async def create_agent_runner(user_id: str, session_id: str): | |
| instruction_text=""" | |
| You are a highly experienced college counselor specializing in helping high school students choose the right engineering colleges. You have access to several tools to help answer student queries. | |
| AVAILABLE TOOLS: | |
| 1. db_tool - Search local college database | |
| 2. tavily_tool - Search internet for college information | |
| 3. predictor_tool - Predict colleges based on rank and preferences | |
| 4. mentor_tool - Find mentors from specific colleges | |
| WORKFLOW: | |
| Step 1: Classify the user's query into one of these categories: | |
| a. "Know college based on my rank" | |
| b. "Know about a college" | |
| c. "Talk to a college student/mentor" | |
| d. "General query" | |
| e. "JOSAA or CSAB queries" | |
| f. "Unrelated query" | |
| Step 2: Based on category, follow these steps: | |
| For Category A (College predictions): | |
| - Extract: userCrl (Common Rank List or category rank), userCategory, userGender, userHomeState | |
| - Optional: collegeName, branchName preferences | |
| - ALWAYS call the predictor_tool if userCrl is provided. | |
| - After Extracting the params from the query pass the params inside predictor_tool. | |
| - Display the output in bullet points format showing predicted colleges, branches, cutoffs, etc. | |
| - Add this at end of the response 'For detailed and better filters please visit https://www.precollege.in/college-predictor' | |
| For Category B (College information): | |
| - Extract college name | |
| - Call db_tool | |
| - If db_tool fails to return meaningful output(Answer according to query), fallback to tavily_tool to fetch data from the internet. | |
| - Present a brief, well-structured summary in natural language. | |
| For Category C (Find mentors): | |
| - Extract college name | |
| - Call mentor_tool | |
| - Provide the top 6 mentor details using mentor_tool(in name:link to mentor profile format) and include this at end of the respose 'For more mentor details: visit: https://precollege.in/mentors | |
| For Category D (General queries): | |
| - Answer using db_tool | |
| - If db_tool doesn't provide enough, fallback to tavily_tool | |
| - Summarize the answer clearly and informatively. | |
| For Category E (JOSAA or CSAB queries): | |
| - Answer using tavily_tool using JOSAA and CSAB offical websites.(https://josaa.nic.in/, https://csab.nic.in/) | |
| - Answer clearly and informatively in points. | |
| For Category F (Unrelated query): | |
| - If the query is unrelated to JoSAA counseling, colleges, branches, or mentoring: | |
| - Respond: "Sorry, this is beyond my capabilities." | |
| IMPORTANT RULES: | |
| - ALWAYS use the tools specified above based on the workflow. | |
| - Never invent data. If something cannot be found, say so clearly. | |
| - Use clean formatting and polite tone. | |
| - Always give output in bullet points | |
| - Do not skip steps or tools. Follow the workflow strictly. | |
| """ | |
| agent = Agent( | |
| name="college_info_agent", | |
| model="gemini-1.5-flash", | |
| instruction=instruction_text, | |
| tools=[db_tool, tavily_tool, predictor_tool, mentor_tool], | |
| generate_content_config=types.GenerateContentConfig( | |
| max_output_tokens=1500, | |
| temperature=0.1, | |
| ), | |
| ) | |
| session_svc = InMemorySessionService() | |
| # Handle potential async session creation | |
| try: | |
| session = session_svc.create_session( | |
| app_name="college_agent_app", | |
| user_id=user_id, | |
| session_id=session_id | |
| ) | |
| # If it's a coroutine, await it | |
| if asyncio.iscoroutine(session): | |
| session = await session | |
| except Exception as e: | |
| print(f"Session creation error: {e}") | |
| # Fallback: create a simple session object | |
| class SimpleSession: | |
| def __init__(self, session_id): | |
| self.id = session_id | |
| session = SimpleSession(session_id) | |
| runner = Runner(agent=agent, app_name="college_agent_app", session_service=session_svc) | |
| return runner, session | |
| # === FASTAPI SETUP === | |
| app = FastAPI( | |
| title="College Counselor Agent", | |
| description="AI Agent for college counseling and selection", | |
| version="1.0.0" | |
| ) | |
| class ChatRequest(BaseModel): | |
| user_id: str | |
| session_id: str | |
| question: str | |
| class ChatResponse(BaseModel): | |
| session_id: str | |
| answer: str | |
| async def root(): | |
| return { | |
| "message": "College Counselor Agent is running!", | |
| "docs": "/docs", | |
| "health": "/healthz" | |
| } | |
| async def chat_endpoint(req: ChatRequest): | |
| try: | |
| runner, session = await create_agent_runner(req.user_id, req.session_id) | |
| processed_query = preprocess_query(req.question) | |
| user_msg = types.Content(role="user", parts=[types.Part(text=processed_query)]) | |
| reply_text = "" | |
| # Handle potential async runner execution | |
| try: | |
| events = runner.run(user_id=req.user_id, session_id=session.id, new_message=user_msg) | |
| # If events is a coroutine, await it | |
| if asyncio.iscoroutine(events): | |
| events = await events | |
| except Exception as runner_error: | |
| print(f"Runner error: {runner_error}") | |
| return ChatResponse( | |
| session_id=session.id, | |
| answer="Sorry, I encountered an error processing your request. Please try again." | |
| ) | |
| # Process events | |
| try: | |
| for ev in events: | |
| if hasattr(ev, 'is_final_response') and ev.is_final_response(): | |
| try: | |
| for part in ev.content.parts: | |
| if hasattr(part, 'text') and part.text: | |
| reply_text = part.text | |
| break | |
| except Exception: | |
| try: | |
| reply_text = getattr(ev, 'text', '') | |
| except Exception: | |
| try: | |
| reply_text = str(getattr(ev, 'message', '')) | |
| except Exception: | |
| reply_text = "Sorry, I couldn't process the response properly." | |
| break | |
| except Exception as event_error: | |
| print(f"Event processing error: {event_error}") | |
| reply_text = "Sorry, I encountered an error while processing the response." | |
| # Fallback if no reply_text | |
| if not reply_text: | |
| reply_text = "I'm sorry, I couldn't generate a proper response. Please try rephrasing your question." | |
| # Log to sheet (handle potential errors) | |
| try: | |
| add_query_to_sheet(req.user_id, processed_query, reply_text) | |
| except Exception as sheet_error: | |
| print(f"Sheet logging error: {sheet_error}") | |
| # Don't fail the request if logging fails | |
| return ChatResponse(session_id=session.id, answer=reply_text) | |
| except Exception as e: | |
| print(f"Chat endpoint error: {str(e)}") | |
| raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}") | |
| def health_check(): | |
| return {"status": "ok", "service": "college-counselor-agent"} | |
| # Add a simple test endpoint | |
| async def test_endpoint(): | |
| return { | |
| "message": "Test endpoint working", | |
| "env_vars": { | |
| "HF_HOME": os.environ.get('HF_HOME'), | |
| "TRANSFORMERS_CACHE": os.environ.get('TRANSFORMERS_CACHE') | |
| } | |
| } |