kasitbot / config.py
snygginghani's picture
Rebuild backend from scratch, replace static cards with interactive popups
c26a997
import os
from pathlib import Path
from dotenv import load_dotenv
load_dotenv(dotenv_path=Path(__file__).parent / "env")
# ── Paths ─────────────────────────────────────────────────────────────────
BASE_DIR = Path(__file__).parent
INDEX_DIR = BASE_DIR / "faiss_index"
INDEX_FILE = INDEX_DIR / "index.faiss"
METADATA_FILE = INDEX_DIR / "metadata.json"
# ── API keys ──────────────────────────────────────────────────────────────
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "")
OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY", "")
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1"
# ── Embedding & query expansion ──────────────────────────────────────────
EMBEDDING_MODEL = "text-embedding-3-large"
QUERY_EXPANSION_MODEL = "gpt-4o-mini"
# ── Available LLM models ─────────────────────────────────────────────────
AVAILABLE_MODELS = {
"gpt-4o": {
"label": "GPT-4o",
"desc": "Flagship multimodal · best accuracy",
"provider": "openai",
"price_in": 2.50,
"price_out": 10.00,
},
"gpt-4o-mini": {
"label": "GPT-4o mini",
"desc": "Fast & affordable · great for simple tasks",
"provider": "openai",
"price_in": 0.15,
"price_out": 0.60,
},
"gpt-4.1-mini": {
"label": "GPT-4.1 mini",
"desc": "Latest mini · improved instruction-following",
"provider": "openai",
"price_in": 0.40,
"price_out": 1.60,
},
"gpt-5.4-mini": {
"label": "GPT-5.4 mini",
"desc": "Next-gen mini · advanced reasoning at low cost",
"provider": "openai",
"price_in": 0.25,
"price_out": 1.00,
},
"openai/gpt-4o-mini-2024-07-18": {
"label": "GPT-4o OSS 120B",
"desc": "Open-weight GPT-4o class · 120B params",
"provider": "openrouter",
"price_in": 0.15,
"price_out": 0.60,
},
"anthropic/claude-sonnet-4.6": {
"label": "Claude Sonnet 4.6",
"desc": "Anthropic · strong reasoning & long context",
"provider": "openrouter",
"price_in": 3.00,
"price_out": 15.00,
},
"moonshotai/kimi-k2": {
"label": "Kimi K2",
"desc": "Moonshot AI · efficient multilingual",
"provider": "openrouter",
"price_in": 0.60,
"price_out": 2.50,
},
"deepseek/deepseek-chat-v3-0324": {
"label": "DeepSeek V3 Flash",
"desc": "DeepSeek · ultra-low cost, strong reasoning",
"provider": "openrouter",
"price_in": 0.14,
"price_out": 0.28,
},
"google/gemini-2.0-flash-001": {
"label": "Gemini 2.0 Flash",
"desc": "Google · fast multimodal, 1M context window",
"provider": "openrouter",
"price_in": 0.10,
"price_out": 0.40,
},
"qwen/qwen3-235b-a22b": {
"label": "Qwen3 235B",
"desc": "Alibaba · massive MoE, hybrid thinking mode",
"provider": "openrouter",
"price_in": 0.13,
"price_out": 0.40,
},
"meta-llama/llama-4-maverick": {
"label": "Llama 4 Maverick",
"desc": "Meta · mixture-of-experts, best open-weight",
"provider": "openrouter",
"price_in": 0.20,
"price_out": 0.60,
},
}
DEFAULT_MODEL = "gpt-4o-mini"
# ── Retrieval tuning ─────────────────────────────────────────────────────
TOP_K_VECTOR = 15
TOP_K_BM25 = 15
TOP_K_FINAL = 5
MIN_RETRIEVAL_SCORE = 0.25
# ── Generation tuning ────────────────────────────────────────────────────
TEMPERATURE = 0.2
MAX_RESPONSE_TOKENS = 800
# ── Request limits ────────────────────────────────────────────────────────
MAX_MESSAGE_LENGTH = 2_000
MAX_MESSAGES_PER_REQ = 50
MAX_HISTORY_MESSAGES = 8
# ── System prompts ────────────────────────────────────────────────────────
SYSTEM_EN = """\
You are KASITBot, the official academic assistant for KASIT \
(King Abdullah II School of Information Technology) at the University of Jordan.
Your role:
- Help students with courses, exams, fees, graduation requirements, office hours, \
scholarships (makruma), academic regulations, study plans, and faculty contacts.
- Answer ONLY from the provided context documents. Do NOT invent, guess, or fabricate \
any information such as dates, numbers, names, fees, or schedules.
- If the context does not contain the answer, say clearly: \
"I don't have this information in my current documents. Please check with the KASIT \
administration or visit the official University of Jordan website."
- Never hallucinate course codes, professor names, exam dates, fee amounts, or any factual data.
- When listing information (courses, schedules, fees), present it in a clear, structured format \
using tables or bullet points.
- Reply in the same language the student used. If they write in Arabic, respond in Arabic. \
If in English, respond in English.
- Be concise, accurate, and helpful. Students depend on you for correct academic guidance.\
"""
SYSTEM_AR = """\
أنت كاسيت بوت، المساعد الأكاديمي الرسمي لكلية الملك عبدالله الثاني لتكنولوجيا المعلومات \
(KASIT) في الجامعة الأردنية.
دورك:
- مساعدة الطلاب في المساقات والامتحانات والرسوم ومتطلبات التخرج وساعات المكتب \
والمكرمات والأنظمة الأكاديمية والخطط الدراسية والتواصل مع أعضاء هيئة التدريس.
- أجب فقط من الوثائق والسياق المتاح لك. لا تخترع أو تتوقع أو تُلفّق أي معلومات \
مثل التواريخ أو الأرقام أو الأسماء أو الرسوم أو الجداول.
- إذا لم يحتوِ السياق على الإجابة، قل بوضوح: \
"لا تتوفر لدي هذه المعلومة في الوثائق الحالية. يرجى مراجعة إدارة كلية كاسيت \
أو زيارة الموقع الرسمي للجامعة الأردنية."
- لا تختلق أبداً أرقام مساقات أو أسماء أساتذة أو تواريخ امتحانات أو مبالغ رسوم \
أو أي بيانات واقعية.
- عند عرض المعلومات (مساقات، جداول، رسوم)، قدمها بشكل منظم وواضح \
باستخدام جداول أو نقاط.
- أجب بنفس اللغة التي يستخدمها الطالب.
- كن موجزاً ودقيقاً ومفيداً. الطلاب يعتمدون عليك للحصول على إرشاد أكاديمي صحيح.\
"""
# ── Student portal tool definitions ───────────────────────────────────────
PORTAL_TOOLS = [
{
"type": "function",
"function": {
"name": "get_student_profile",
"description": (
"Retrieve the registered student's full profile: name, student ID, email, "
"GPA, major, year, semester, academic year, enrollment status, total enrolled "
"courses, and total credit hours this semester. Call this whenever the user "
"asks about who they are, their GPA, their ID, their email, their major, or "
"a general summary of their registration."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "get_enrolled_courses",
"description": (
"Return the list of courses the student is currently enrolled in this semester, "
"including course number, name, instructor, days, times, room, credits, and category. "
"Call this when the user asks about their current courses, schedule, what they are "
"taking, credit hours, or any specific enrolled course detail."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "get_available_courses",
"description": (
"Return all courses currently available for the student to add/register, "
"including seats available, prerequisites, instructor, and schedule. "
"Call this when the user asks what courses they can add, available courses, "
"or courses offered this semester that they are NOT enrolled in."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "get_schedule",
"description": (
"Return the student's full weekly schedule with all enrolled courses ordered by time. "
"Call this when the user asks for their schedule, timetable, or wants to print/download "
"their course schedule."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "enroll_course",
"description": (
"Enroll (add/register) the student into a course. Call this when the user explicitly "
"asks to add, enroll in, register for, or sign up for a course. "
"You must provide the exact course_number. If the user gives a course name instead, "
"first call get_available_courses to find the matching course_number."
),
"parameters": {
"type": "object",
"properties": {
"course_number": {
"type": "string",
"description": "The exact course code/number (e.g., 'CS5502', '1915471')",
}
},
"required": ["course_number"],
},
},
},
{
"type": "function",
"function": {
"name": "drop_course",
"description": (
"Drop (withdraw/remove) the student from an enrolled course. Call this when the user "
"explicitly asks to drop, remove, withdraw from, or delete a course. "
"You must provide the exact course_number. If the user gives a course name instead, "
"first call get_enrolled_courses to find the matching course_number."
),
"parameters": {
"type": "object",
"properties": {
"course_number": {
"type": "string",
"description": "The exact course code/number to drop (e.g., '1915471')",
}
},
"required": ["course_number"],
},
},
},
{
"type": "function",
"function": {
"name": "update_gpa",
"description": (
"Update the student's GPA to a new value. Only call this when the user explicitly "
"asks to update, change, or set their GPA. The GPA must be between 0.0 and 4.0."
),
"parameters": {
"type": "object",
"properties": {
"gpa": {
"type": "number",
"description": "The new GPA value, must be between 0.0 and 4.0",
}
},
"required": ["gpa"],
},
},
},
{
"type": "function",
"function": {
"name": "get_semester_history",
"description": (
"Return the student's complete semester-by-semester academic history: "
"every semester's GPA, credit hours taken, cumulative GPA, cumulative credits, "
"year level, and registration status — going back to the first semester. "
"Call this for ANY question about past or historical GPA, a specific semester's "
"performance, grade trends, cumulative credits, academic level, or year-by-year progress."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "get_absence_records",
"description": (
"Return the student's absence count for each currently enrolled course, "
"including warning flags for courses approaching the 25% absence limit. "
"Call this for ANY question about absences, attendance, missed classes, "
"or risk of being barred from exams."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
]