jake2004 commited on
Commit
2bcbe6e
Β·
verified Β·
1 Parent(s): f4fbd3f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -152
app.py CHANGED
@@ -5,16 +5,15 @@ import streamlit as st
5
  import pandas as pd
6
  import openpyxl
7
  import torch
 
8
  from reportlab.lib.pagesizes import letter
9
  from reportlab.pdfgen import canvas
10
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
 
11
 
12
  # βœ… Streamlit UI Setup
13
  st.set_page_config(page_title="AI-Powered Timetable", layout="wide")
14
- st.markdown(
15
- "<h1 style='text-align: center; color: #4CAF50;'>πŸ“… AI-Powered Timetable</h1>",
16
- unsafe_allow_html=True,
17
- )
18
 
19
  # βœ… API Key Input
20
  st.sidebar.markdown("## πŸ”‘ Enter Hugging Face API Key")
@@ -22,10 +21,10 @@ hf_api_key = st.sidebar.text_input("API Key", type="password")
22
 
23
  # βœ… File Upload Section
24
  st.sidebar.markdown("## πŸ“‚ Upload Your Timetable Files")
25
- uploaded_master = st.sidebar.file_uploader("Upload Master Timetable", type=["xlsx"])
26
- uploaded_lab = st.sidebar.file_uploader("Upload Lab Timetable", type=["xlsx"])
27
- uploaded_classroom = st.sidebar.file_uploader("Upload Classroom Timetable", type=["xlsx"])
28
- uploaded_individual = st.sidebar.file_uploader("Upload Individual Timetable", type=["xlsx"])
29
 
30
  uploaded_files = {
31
  "Master Timetable": uploaded_master,
@@ -34,28 +33,61 @@ uploaded_files = {
34
  "Individual Timetable": uploaded_individual,
35
  }
36
 
37
- # βœ… Load Timetable Data (Directly from Uploaded File)
38
  def load_timetable(file):
39
  if not file:
40
  return None
41
- wb = openpyxl.load_workbook(file)
42
- sheet = wb.active
43
- return [row for row in sheet.iter_rows(values_only=True)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
- # βœ… Ask LLaMA-3 API via Hugging Face
 
 
 
 
 
 
46
  def ask_llama_api(query):
47
  if not hf_api_key:
48
  return "Error: Please enter your API key."
 
 
 
49
 
50
  url = "https://api-inference.huggingface.co/v1/chat/completions"
51
  headers = {
52
  "Authorization": f"Bearer {hf_api_key}",
53
- "Content-Type": "application/json",
54
  }
55
  payload = {
56
  "model": "meta-llama/Meta-Llama-3-8B",
57
- "messages": [{"role": "user", "content": query}],
58
- "max_tokens": 500,
59
  }
60
 
61
  response = requests.post(url, headers=headers, json=payload)
@@ -64,158 +96,45 @@ def ask_llama_api(query):
64
  else:
65
  return f"API Error: {response.status_code} - {response.text}"
66
 
67
- # βœ… Auto-Schedule Missing Slots
68
- def auto_schedule(file):
69
- if not file:
70
- return "No timetable uploaded."
71
-
72
- wb = openpyxl.load_workbook(file)
73
- sheet = wb.active
74
-
75
- empty_slots = []
76
- for row_idx, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
77
- if None in row or "" in row:
78
- empty_slots.append(row_idx)
79
-
80
- for row_idx in empty_slots:
81
- query = f"Suggest a subject and faculty for the empty slot in row {row_idx}."
82
- suggestion = ask_llama_api(query)
83
-
84
- try:
85
- subject, faculty = suggestion.split(", Faculty: ")
86
- sheet.cell(row=row_idx, column=4, value=subject.strip())
87
- sheet.cell(row=row_idx, column=5, value=faculty.strip())
88
- except:
89
- continue
90
-
91
- return f"Auto-scheduling completed for {len(empty_slots)} slots."
92
-
93
- # βœ… PDF Generation for Timetable
94
- def generate_pdf(file, filename="generated_timetable.pdf"):
95
- if not file:
96
- return "No timetable uploaded."
97
-
98
- wb = openpyxl.load_workbook(file)
99
- sheet = wb.active
100
-
101
- pdf_filename = os.path.join(os.getcwd(), filename)
102
- c = canvas.Canvas(pdf_filename, pagesize=letter)
103
- width, height = letter
104
- y = height - 50
105
-
106
- c.setFont("Helvetica-Bold", 14)
107
- c.drawString(200, y, "Generated Timetable")
108
- y -= 30
109
-
110
- c.setFont("Helvetica", 10)
111
- for row in sheet.iter_rows(values_only=True):
112
- row_text = " | ".join(str(cell) if cell else "" for cell in row)
113
- c.drawString(50, y, row_text)
114
- y -= 20
115
- if y < 50:
116
- c.showPage()
117
- c.setFont("Helvetica", 10)
118
- y = height - 50
119
-
120
- c.save()
121
- return pdf_filename
122
-
123
  # βœ… AI Query Section
124
  st.markdown("## πŸ€– Ask LLaMA-3 AI About Your Timetable")
125
  user_query = st.text_input("Type your question here (e.g., 'Who is free at 10 AM on Monday?')")
126
 
127
- if st.button("Ask AI via API"):
128
  ai_response = ask_llama_api(user_query)
129
  st.write("🧠 **LLaMA-3 AI Suggests:**", ai_response)
130
 
131
  # βœ… Auto-Schedule Feature
132
  st.markdown("## πŸ“… Auto-Schedule Missing Timetable Slots")
133
- selected_file = st.selectbox(
134
- "Choose a timetable file to auto-fill missing slots:", list(uploaded_files.keys())
135
- )
136
 
137
  if st.button("Auto-Schedule"):
138
- result = auto_schedule(uploaded_files[selected_file])
139
  st.write("βœ…", result)
140
 
141
- # βœ… Generate PDF
142
- st.markdown("## πŸ“„ Generate PDF of Timetable")
143
- if st.button("Download PDF"):
144
- pdf_path = generate_pdf(uploaded_files[selected_file])
145
- with open(pdf_path, "rb") as pdf_file:
146
- st.download_button("Download Timetable PDF", pdf_file, file_name="timetable.pdf")
147
-
148
  # βœ… Display Uploaded Timetables
149
  st.markdown("## πŸ“œ View Uploaded Timetables")
150
 
151
  for name, file in uploaded_files.items():
152
  if file:
153
- df = pd.read_excel(file)
154
  st.markdown(f"### {name}")
155
- st.dataframe(df)
156
-
157
- # βœ… Inject JavaScript for Real-Time Chat
158
- st.markdown(
159
- """
160
- <script>
161
- async function fetchChatResponse() {
162
- const apiKey = document.getElementById("hf-api-key").value;
163
- const userInput = document.getElementById("user-input").value;
164
- if (!apiKey) {
165
- alert("Please enter your Hugging Face API key.");
166
- return;
167
- }
168
-
169
- try {
170
- const response = await fetch("https://api-inference.huggingface.co/v1/chat/completions", {
171
- method: "POST",
172
- headers: {
173
- "Authorization": `Bearer ${apiKey}`,
174
- "Content-Type": "application/json"
175
- },
176
- body: JSON.stringify({
177
- model: "meta-llama/Meta-Llama-3-8B",
178
- messages: [{ role: "user", content: userInput }],
179
- max_tokens: 500
180
- })
181
- });
182
-
183
- if (!response.ok) {
184
- throw new Error(`API Error: ${response.statusText}`);
185
- }
186
-
187
- const data = await response.json();
188
- const botMessage = data.choices[0].message.content;
189
-
190
- document.getElementById("chat-box").innerHTML +=
191
- `<div class='bot-message'><strong>VarunGPT-3:</strong> ${botMessage}</div>`;
192
-
193
- } catch (error) {
194
- console.error("Error fetching chat response:", error);
195
- document.getElementById("chat-box").innerHTML +=
196
- `<div class='bot-message'><strong>Error:</strong> Unable to fetch response.</div>`;
197
- }
198
- }
199
- </script>
200
- """,
201
- unsafe_allow_html=True,
202
- )
203
-
204
- # βœ… Chat UI with User Input for API Key
205
- st.markdown(
206
- """
207
- <div style="text-align: center;">
208
- <input id="hf-api-key" type="password" placeholder="Enter Hugging Face API Key"
209
- style="width: 50%; padding: 8px; margin-bottom: 10px;"/>
210
- <br/>
211
- <input id="user-input" type="text" placeholder="Type your message..."
212
- style="width: 50%; padding: 8px;"/>
213
- <button onclick="fetchChatResponse()"
214
- style="padding: 10px 20px; background-color: #4CAF50; color: white; border: none; cursor:pointer;">
215
- Ask AI
216
- </button>
217
- <div id="chat-box" style="margin-top: 20px; text-align: left;"></div>
218
- </div>
219
- """,
220
- unsafe_allow_html=True,
221
- )
 
5
  import pandas as pd
6
  import openpyxl
7
  import torch
8
+ import faiss
9
  from reportlab.lib.pagesizes import letter
10
  from reportlab.pdfgen import canvas
11
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
12
+ from sentence_transformers import SentenceTransformer
13
 
14
  # βœ… Streamlit UI Setup
15
  st.set_page_config(page_title="AI-Powered Timetable", layout="wide")
16
+ st.markdown("<h1 style='text-align: center; color: #4CAF50;'>πŸ“… AI-Powered Timetable with RAG</h1>", unsafe_allow_html=True)
 
 
 
17
 
18
  # βœ… API Key Input
19
  st.sidebar.markdown("## πŸ”‘ Enter Hugging Face API Key")
 
21
 
22
  # βœ… File Upload Section
23
  st.sidebar.markdown("## πŸ“‚ Upload Your Timetable Files")
24
+ uploaded_master = st.sidebar.file_uploader("Upload Master Timetable", type=["xlsx", "pdf"])
25
+ uploaded_lab = st.sidebar.file_uploader("Upload Lab Timetable", type=["xlsx", "pdf"])
26
+ uploaded_classroom = st.sidebar.file_uploader("Upload Classroom Timetable", type=["xlsx", "pdf"])
27
+ uploaded_individual = st.sidebar.file_uploader("Upload Individual Timetable", type=["xlsx", "pdf"])
28
 
29
  uploaded_files = {
30
  "Master Timetable": uploaded_master,
 
33
  "Individual Timetable": uploaded_individual,
34
  }
35
 
36
+ # βœ… Load Timetable Data
37
  def load_timetable(file):
38
  if not file:
39
  return None
40
+ if file.name.endswith('.xlsx'):
41
+ wb = openpyxl.load_workbook(file)
42
+ sheet = wb.active
43
+ return [row for row in sheet.iter_rows(values_only=True)]
44
+ elif file.name.endswith('.pdf'):
45
+ import PyPDF2
46
+ pdf_reader = PyPDF2.PdfReader(file)
47
+ text = ""
48
+ for page in pdf_reader.pages:
49
+ text += page.extract_text() + "\n"
50
+ return text
51
+
52
+ # βœ… Extract and Store Data
53
+ rag_data = {}
54
+ for name, file in uploaded_files.items():
55
+ if file:
56
+ rag_data[name] = load_timetable(file)
57
+
58
+ # βœ… Encode Timetable Data with Sentence Embeddings
59
+ embedder = SentenceTransformer("all-MiniLM-L6-v2")
60
+ data_texts = ["\n".join(map(str, data)) for data in rag_data.values() if data]
61
+ data_embeddings = embedder.encode(data_texts, convert_to_tensor=True)
62
+
63
+ # βœ… Create FAISS Vector Store
64
+ dimension = data_embeddings.shape[1]
65
+ index = faiss.IndexFlatL2(dimension)
66
+ index.add(data_embeddings.cpu().numpy())
67
 
68
+ # βœ… Retrieve Relevant Data using RAG
69
+ def retrieve_data(query):
70
+ query_embedding = embedder.encode([query], convert_to_tensor=True)
71
+ D, I = index.search(query_embedding.cpu().numpy(), k=1)
72
+ return data_texts[I[0][0]] if I[0][0] < len(data_texts) else "No relevant data found."
73
+
74
+ # βœ… Ask LLaMA-3-8B with RAG Context
75
  def ask_llama_api(query):
76
  if not hf_api_key:
77
  return "Error: Please enter your API key."
78
+
79
+ context = retrieve_data(query) # Get relevant timetable data
80
+ final_query = f"Based on the timetable data:\n{context}\nAnswer this query: {query}"
81
 
82
  url = "https://api-inference.huggingface.co/v1/chat/completions"
83
  headers = {
84
  "Authorization": f"Bearer {hf_api_key}",
85
+ "Content-Type": "application/json"
86
  }
87
  payload = {
88
  "model": "meta-llama/Meta-Llama-3-8B",
89
+ "messages": [{"role": "user", "content": final_query}],
90
+ "max_tokens": 500
91
  }
92
 
93
  response = requests.post(url, headers=headers, json=payload)
 
96
  else:
97
  return f"API Error: {response.status_code} - {response.text}"
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  # βœ… AI Query Section
100
  st.markdown("## πŸ€– Ask LLaMA-3 AI About Your Timetable")
101
  user_query = st.text_input("Type your question here (e.g., 'Who is free at 10 AM on Monday?')")
102
 
103
+ if st.button("Ask AI via RAG"):
104
  ai_response = ask_llama_api(user_query)
105
  st.write("🧠 **LLaMA-3 AI Suggests:**", ai_response)
106
 
107
  # βœ… Auto-Schedule Feature
108
  st.markdown("## πŸ“… Auto-Schedule Missing Timetable Slots")
109
+ selected_file = st.selectbox("Choose a timetable file to auto-fill missing slots:", list(uploaded_files.keys()))
 
 
110
 
111
  if st.button("Auto-Schedule"):
112
+ result = retrieve_data(selected_file)
113
  st.write("βœ…", result)
114
 
 
 
 
 
 
 
 
115
  # βœ… Display Uploaded Timetables
116
  st.markdown("## πŸ“œ View Uploaded Timetables")
117
 
118
  for name, file in uploaded_files.items():
119
  if file:
120
+ df = pd.read_excel(file) if file.name.endswith(".xlsx") else None
121
  st.markdown(f"### {name}")
122
+ if df is not None:
123
+ st.dataframe(df)
124
+ else:
125
+ st.text(rag_data[name])
126
+
127
+ # βœ… PDF Export Feature
128
+ st.sidebar.markdown("## πŸ“„ Export AI Responses to PDF")
129
+ if st.sidebar.button("Export as PDF"):
130
+ c = canvas.Canvas("Timetable_Responses.pdf", pagesize=letter)
131
+ c.drawString(100, 750, "AI-Powered Timetable Responses")
132
+ y = 720
133
+ for query, response in [("Example Query", "Example Response")]: # Replace with actual
134
+ c.drawString(50, y, f"Q: {query}")
135
+ y -= 20
136
+ c.drawString(70, y, f"A: {response}")
137
+ y -= 30
138
+ c.save()
139
+ st.sidebar.success("PDF Exported: Timetable_Responses.pdf")
140
+