Timetable2 / app.py
jake2004's picture
Update app.py
fc208c7 verified
import json
import requests
import os
import streamlit as st
import pandas as pd
import openpyxl
import faiss
import torch
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from sentence_transformers import SentenceTransformer
from transformers import AutoModelForCausalLM, AutoTokenizer
# βœ… Streamlit UI Setup
st.set_page_config(page_title="AI-Powered Timetable", layout="wide")
st.markdown("<h1 style='text-align: center; color: #4CAF50;'>πŸ“… AI-Powered Timetable</h1>", unsafe_allow_html=True)
# βœ… API Key Input
st.sidebar.markdown("## πŸ”‘ Enter Hugging Face API Key")
hf_api_key = st.sidebar.text_input("API Key", type="password")
# βœ… File Upload Section
st.sidebar.markdown("## πŸ“‚ Upload Your Timetable Files")
uploaded_master = st.sidebar.file_uploader("Upload Master Timetable", type=["xlsx"])
uploaded_lab = st.sidebar.file_uploader("Upload Lab Timetable", type=["xlsx"])
uploaded_classroom = st.sidebar.file_uploader("Upload Classroom Timetable", type=["xlsx"])
uploaded_individual = st.sidebar.file_uploader("Upload Individual Timetable", type=["xlsx"])
uploaded_files = {
"Master Timetable": uploaded_master,
"Lab Timetable": uploaded_lab,
"Classroom Timetable": uploaded_classroom,
"Individual Timetable": uploaded_individual,
}
# βœ… Load Timetable Data (Directly from Uploaded File)
def load_timetable(file):
if not file:
return None
wb = openpyxl.load_workbook(file)
sheet = wb.active
return [row for row in sheet.iter_rows(values_only=True)]
# βœ… Initialize Sentence Transformer for Embeddings
embedder = SentenceTransformer("all-MiniLM-L6-v2")
# βœ… Process Uploaded Files and Create RAG Index
rag_data = {}
for name, file in uploaded_files.items():
if file:
timetable_data = load_timetable(file)
if timetable_data:
rag_data[name] = timetable_data
# βœ… Convert timetable data to text format
data_texts = ["\n".join(map(str, data)) for data in rag_data.values() if data]
if not data_texts:
st.error("Error: No extracted timetable content available for AI processing.")
st.stop()
# βœ… Generate FAISS Embeddings
data_embeddings = embedder.encode(data_texts, convert_to_tensor=True)
if len(data_embeddings) == 0:
st.error("Error: No valid embeddings created. Check your timetable files.")
st.stop()
dimension = data_embeddings.shape[1] # FIXED ERROR: Ensuring valid shape
index = faiss.IndexFlatL2(dimension)
index.add(data_embeddings.cpu().numpy())
# βœ… Function to Retrieve Relevant Data from FAISS
def retrieve_relevant_text(query, top_k=2):
query_embedding = embedder.encode([query], convert_to_tensor=True).cpu().numpy()
distances, indices = index.search(query_embedding, top_k)
retrieved_texts = [data_texts[idx] for idx in indices[0] if idx < len(data_texts)]
return "\n".join(retrieved_texts)
# βœ… Ask LLaMA-3 AI via API
def ask_llama_api(query):
if not hf_api_key:
return "Error: Please enter your API key."
retrieved_text = retrieve_relevant_text(query)
context = f"Relevant timetable data:\n{retrieved_text}\n\nUser Query: {query}"
url = "https://api-inference.huggingface.co/v1/chat/completions"
headers = {
"Authorization": f"Bearer {hf_api_key}",
"Content-Type": "application/json"
}
payload = {
"model": "meta-llama/Meta-Llama-3-8B",
"messages": [{"role": "user", "content": context}],
"max_tokens": 500
}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"]
else:
return f"API Error: {response.status_code} - {response.text}"
# βœ… Auto-Schedule Missing Slots
def auto_schedule(file):
if not file:
return "No timetable uploaded."
wb = openpyxl.load_workbook(file)
sheet = wb.active
empty_slots = []
for row_idx, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
if None in row or "" in row:
empty_slots.append(row_idx)
for row_idx in empty_slots:
query = f"Suggest a subject and faculty for the empty slot in row {row_idx}."
suggestion = ask_llama_api(query)
try:
subject, faculty = suggestion.split(", Faculty: ")
sheet.cell(row=row_idx, column=4, value=subject.strip())
sheet.cell(row=row_idx, column=5, value=faculty.strip())
except:
continue
return f"Auto-scheduling completed for {len(empty_slots)} slots."
# βœ… AI Query Section
st.markdown("## πŸ€– Ask LLaMA-3 AI About Your Timetable")
user_query = st.text_input("Type your question here (e.g., 'Who is free at 10 AM on Monday?')")
if st.button("Ask AI via API"):
ai_response = ask_llama_api(user_query)
st.write("🧠 **LLaMA-3 AI Suggests:**", ai_response)
# βœ… Auto-Schedule Feature
st.markdown("## πŸ“… Auto-Schedule Missing Timetable Slots")
selected_file = st.selectbox("Choose a timetable file to auto-fill missing slots:", list(uploaded_files.keys()))
if st.button("Auto-Schedule"):
result = auto_schedule(uploaded_files[selected_file])
st.write("βœ…", result)
# βœ… Display Uploaded Timetables
st.markdown("## πŸ“œ View Uploaded Timetables")
for name, file in uploaded_files.items():
if file:
df = pd.read_excel(file)
st.markdown(f"### {name}")
st.dataframe(df)