subhan971's picture
Update app.py
ca51c38 verified
import streamlit as st
import PyPDF2
from groq import Groq
import time
import os
from dotenv import load_dotenv
import pdf
import io
# Page configuration
st.set_page_config(
page_title="Zouq-ul-ilm - AI Notes Generator",
page_icon="πŸ“š",
layout="wide",
initial_sidebar_state="collapsed"
)
# Custom CSS
st.markdown("""
<style>
.stApp {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.main-container {
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
padding: 2rem;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
}
h1 {
color: #667eea;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-weight: 700;
text-align: center;
margin-bottom: 0.5rem;
}
.subtitle {
text-align: center;
color: #6c757d;
font-size: 1.1rem;
margin-bottom: 2rem;
}
.stButton > button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
padding: 0.6rem 2rem;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.stButton > button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
}
.topic-item {
background: white;
border-radius: 8px;
padding: 0.8rem 1rem;
margin: 0.5rem 0;
border-left: 3px solid #667eea;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.success-box {
background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
color: white;
padding: 1rem;
border-radius: 10px;
text-align: center;
font-weight: 600;
margin: 1rem 0;
}
.stProgress > div > div {
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
}
.info-box {
background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
border-radius: 10px;
padding: 1rem;
border-left: 4px solid #667eea;
margin: 1rem 0;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state
if 'topics' not in st.session_state:
st.session_state.topics = []
if 'notes_generated' not in st.session_state:
st.session_state.notes_generated = False
if 'pdf_bytes' not in st.session_state:
st.session_state.pdf_bytes = None
# Load environment variables
load_dotenv()
# Groq client
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
GROQ_MODELS = [
"llama-3.3-70b-versatile",
"llama3-70b-8192",
"llama3-8b-8192",
"gemma2-9b-it",
"llama-3.1-8b-instant", # replaced deprecated mixtral
]
def groq_generate(prompt, model_name, max_tokens=2048):
try:
response = groq_client.chat.completions.create(
model=model_name,
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
temperature=0.8,
top_p=0.9,
)
return response.choices[0].message.content
except Exception as e:
try:
response = groq_client.chat.completions.create(
model=GROQ_MODELS[0],
messages=[{"role": "user", "content": prompt}],
max_tokens=max_tokens,
temperature=0.8,
top_p=0.9,
)
return response.choices[0].message.content
except Exception as e2:
return f"[Error: {e2}]"
# Header
st.markdown("<h1>πŸ“š Zouq-ul-ilm</h1>", unsafe_allow_html=True)
st.markdown("<p class='subtitle'>AI-Powered Notes Generator for Students</p>", unsafe_allow_html=True)
with st.container():
st.markdown("<div class='main-container'>", unsafe_allow_html=True)
# Step 1: File Upload
st.markdown("### πŸ“„ Step 1: Upload Course Outline")
st.markdown("<div class='info-box'>Upload your course outline (PDF format) to extract topics automatically.</div>", unsafe_allow_html=True)
uploaded_file = st.file_uploader(
"Drag and drop your file here",
type=['pdf'],
help="Upload a PDF file containing your course outline"
)
if uploaded_file is not None:
# Read file into memory β€” no disk needed
file_bytes = uploaded_file.read()
st.success(f"βœ… File uploaded: {uploaded_file.name}")
# Step 2: Extract Topics
st.markdown("---")
st.markdown("### πŸ” Step 2: Extract Topics")
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
if st.button("πŸš€ Extract Topics", use_container_width=True):
with st.spinner("πŸ”„ Analyzing course outline and extracting topics..."):
try:
extracted_text = ""
reader = PyPDF2.PdfReader(io.BytesIO(file_bytes))
for i in range(len(reader.pages)):
page = reader.pages[i]
text1 = page.extract_text()
if not text1:
continue
response_text = groq_generate(
prompt=f"""Analyze the outline and write down topics that are included:
{text1}
I just need topics, not anything else. Follow strictly:
- Do NOT write the heading "topics included"
- Ignore attendance, presentation, book names, grading policy
- Just write short, simple topic names only""",
model_name=GROQ_MODELS[0],
max_tokens=300
)
extracted_text += response_text + "\n\n"
time.sleep(1)
topics_list = [line.strip() for line in extracted_text.split("\n") if line.strip()]
st.session_state.topics = list(topics_list)
st.success(f"βœ… Extracted {len(st.session_state.topics)} topics successfully!")
except Exception as e:
st.error(f"❌ Error extracting topics: {str(e)}")
# Step 3: Display and Edit Topics
if st.session_state.topics:
st.markdown("---")
st.markdown("### ✏️ Step 3: Review & Edit Topics")
st.markdown("<div class='info-box'>Review the extracted topics below. You can add new topics or remove unwanted ones.</div>", unsafe_allow_html=True)
col1, col2 = st.columns([3, 1])
with col1:
new_topic = st.text_input("Add a new topic", placeholder="Enter topic name...")
with col2:
st.markdown("<br>", unsafe_allow_html=True)
if st.button("βž• Add Topic"):
if new_topic and new_topic.strip():
st.session_state.topics.append(new_topic.strip())
st.rerun()
st.markdown("#### πŸ“‹ Current Topics")
for idx, topic in enumerate(st.session_state.topics):
col1, col2 = st.columns([5, 1])
with col1:
st.markdown(f"<div class='topic-item'>{idx + 1}. {topic}</div>", unsafe_allow_html=True)
with col2:
if st.button("πŸ—‘οΈ", key=f"delete_{idx}"):
st.session_state.topics.pop(idx)
st.rerun()
# Step 4: Generate Notes
st.markdown("---")
st.markdown("### πŸ€– Step 4: Generate Comprehensive Notes")
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
if st.button("✨ Generate Notes", use_container_width=True):
st.session_state.notes_generated = False
st.session_state.pdf_bytes = None
progress_bar = st.progress(0)
status_text = st.empty()
try:
ext_text = ""
total_topics = len(st.session_state.topics)
mod = 0
for p, topic in enumerate(st.session_state.topics):
status_text.text(f"πŸ“ Generating notes for topic {p + 1} of {total_topics}: {topic[:50]}...")
progress_bar.progress((p + 1) / total_topics)
if mod == 4:
mod = 1
if p % 5 == 0:
mod = mod + 1
current_model = GROQ_MODELS[mod]
response_text = groq_generate(
prompt=f"""Make detailed yet easy-to-understand notes on {topic}.
Cover all key points from a university syllabus in simple, clear language.
Ensure the notes are complete and informative for students exam preparation.
Include: definition, key concepts, types/categories if any, important points, and a brief summary.""",
model_name=current_model,
max_tokens=2048
)
if response_text:
ext_text += f"\n\n=== {topic.upper()} ===\n\n{response_text}\n\n"
time.sleep(2)
# Generate PDF into memory (returns bytes)
status_text.text("πŸ“„ Creating PDF document...")
pdf_data = pdf.pdf1(ext_text)
st.session_state.pdf_bytes = pdf_data
st.session_state.notes_generated = True
progress_bar.progress(1.0)
status_text.empty()
st.markdown("<div class='success-box'>βœ… Notes generated successfully!</div>", unsafe_allow_html=True)
st.balloons()
except Exception as e:
st.error(f"❌ Error generating notes: {str(e)}")
# Step 5: Download Notes
if st.session_state.notes_generated and st.session_state.pdf_bytes:
st.markdown("---")
st.markdown("### πŸ“₯ Step 5: Download Your Notes")
col1, col2, col3 = st.columns([1, 2, 1])
with col2:
st.download_button(
label="πŸ“„ Download Notes (PDF)",
data=st.session_state.pdf_bytes,
file_name="my_course_notes.pdf",
mime="application/pdf",
use_container_width=True
)
st.markdown("</div>", unsafe_allow_html=True)
# Footer
st.markdown("---")
st.markdown("<p style='text-align: center; color: white; padding: 1rem;'>Made with ❀️ by Zouq-ul-ilm Team | Powered by Groq AI</p>", unsafe_allow_html=True)