Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import os | |
| from groq import Groq | |
| from typing import Generator | |
| # ==================== CONFIGURATION ==================== | |
| st.set_page_config( | |
| page_title="Zainab Bibi | AI Portfolio Assistant", | |
| page_icon="πΌ", | |
| layout="centered", | |
| initial_sidebar_state="collapsed" | |
| ) | |
| # ==================== CUSTOM CSS ==================== | |
| st.markdown(""" | |
| <style> | |
| .main { | |
| background-color: #f8f9fa; | |
| } | |
| .stChatMessage { | |
| background-color: white; | |
| border-radius: 10px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| padding: 10px; | |
| margin: 5px 0; | |
| } | |
| .stChatInput > div { | |
| border-radius: 20px; | |
| } | |
| .stButton button { | |
| border-radius: 20px; | |
| transition: all 0.3s; | |
| background-color: #667eea; | |
| color: white; | |
| } | |
| .stButton button:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 8px rgba(0,0,0,0.15); | |
| background-color: #5568d3; | |
| } | |
| .header-container { | |
| text-align: center; | |
| padding: 2rem 0; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| border-radius: 10px; | |
| margin-bottom: 2rem; | |
| } | |
| .header-title { | |
| font-size: 2.5rem; | |
| font-weight: bold; | |
| margin-bottom: 0.5rem; | |
| } | |
| .header-subtitle { | |
| font-size: 1.1rem; | |
| opacity: 0.9; | |
| } | |
| .skill-badge { | |
| display: inline-block; | |
| background-color: #e0e7ff; | |
| color: #4338ca; | |
| padding: 4px 12px; | |
| border-radius: 12px; | |
| margin: 2px; | |
| font-size: 0.9rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # ==================== PORTFOLIO DATA ==================== | |
| PORTFOLIO_DATA = { | |
| "name": "Zainab Bibi", | |
| "title": "Frontend & Python Developer | BSSE Student", | |
| "summary": "A passionate Frontend & Python Developer currently in 5th semester of BS Software Engineering at University of Haripur (CGPA: 3.90). I enjoy building digital solutions, exploring modern technologies, and turning ideas into reality through code. I specialize in creating modern, responsive websites and web applications using HTML, CSS, JavaScript, React, and Python.", | |
| "location": "Hassan Abdal, Pakistan", | |
| "skills": { | |
| "technical": [ | |
| "HTML & CSS (Advanced)", | |
| "JavaScript (ES6+)", | |
| "React.js", | |
| "Python", | |
| "SQL", | |
| "WordPress", | |
| "Graphic Designing", | |
| "Tkinter", | |
| "PHP", | |
| "REST APIs" | |
| ], | |
| "soft": [ | |
| "Problem Solving", | |
| "Continuous Learning", | |
| "Creativity", | |
| "Attention to Detail", | |
| "Self-motivated" | |
| ], | |
| "languages": [ | |
| "English (Professional)", | |
| "Urdu (Native)" | |
| ] | |
| }, | |
| "education": [ | |
| { | |
| "degree": "Bachelor of Science in Software Engineering (BSSE)", | |
| "school": "University of Haripur", | |
| "year": "2023 - Present (5th Semester)", | |
| "focus": "CGPA: 3.90/4.0", | |
| "status": "Currently Studying" | |
| }, | |
| { | |
| "degree": "FSc Pre-Engineering", | |
| "school": "Govt Degree College For Women Hassan Abdal", | |
| "year": "2021 - 2023", | |
| "focus": "Grade: A+" | |
| }, | |
| { | |
| "degree": "Matriculation", | |
| "school": "Govt Girls High School Hassan Abdal", | |
| "year": "2019 - 2021", | |
| "focus": "Grade: A+" | |
| } | |
| ], | |
| "projects": [ | |
| { | |
| "name": "Personal Portfolio Website", | |
| "description": "A full-featured personal portfolio website showcasing projects, skills, and professional background with modern responsive design.", | |
| "tech": ["HTML", "CSS", "JavaScript"], | |
| "live_demo": "https://raw.githack.com/zainabawan994/ZAINAB_BIBI_PORTFOLIO/main/zainab_awan.html", | |
| "code": "https://github.com/zainabawan994/ZAINAB_BIBI_PORTFOLIO", | |
| "highlights": ["Responsive Design", "Modern UI/UX", "Project Showcase"] | |
| }, | |
| { | |
| "name": "PDF to Audio & MCQs Maker", | |
| "description": "A desktop application that reads PDF files, converts text to audio files (text-to-speech), and automatically generates MCQ-type questions from the content using Python.", | |
| "tech": ["Python", "Tkinter", "PyPDF2", "gTTS", "NLP"], | |
| "live_demo": None, | |
| "code": "https://github.com/zainabawan994/Internship-Project", | |
| "highlights": ["Text-to-Speech", "PDF Processing", "Automated Quiz Generation"] | |
| }, | |
| { | |
| "name": "Root Alert - Smart Plant Care System", | |
| "description": "A comprehensive web application for plant care that allows users to set plant watering alarms, access plant care information, and manage their garden digitally.", | |
| "tech": ["JavaScript", "REST API", "PHP", "HTML/CSS"], | |
| "live_demo": "https://raw.githack.com/zainabawan994/Smart_Plant_Care_System/main/index.html", | |
| "code": "https://github.com/zainabawan994/Smart_Plant_Care_System", | |
| "highlights": ["Alarm System", "Plant Database", "Interactive UI"] | |
| } | |
| ], | |
| "certificates": [ | |
| { | |
| "title": "WordPress Web Development", | |
| "issuer": "Learning With Earning", | |
| "year": "2023", | |
| "description": "Mastered WordPress development including custom themes, plugins, and advanced website optimization techniques." | |
| }, | |
| { | |
| "title": "Python Developer Internship", | |
| "issuer": "TechNiK Nest", | |
| "year": "2025", | |
| "description": "Completed comprehensive Python Developer internship, gaining hands-on experience in building scripts, automating tasks, and working with data using Python libraries." | |
| }, | |
| { | |
| "title": "SQL", | |
| "issuer": "DataCamp", | |
| "year": "2025", | |
| "description": "Awarded Certificate of Completion for SQL, recognizing hands-on experience in database design, query writing, and optimization." | |
| } | |
| ], | |
| "experience": [ | |
| { | |
| "role": "Python Developer Intern", | |
| "company": "TechNiK Nest", | |
| "period": "2025", | |
| "highlights": [ | |
| "Built automation scripts using Python", | |
| "Worked with data processing libraries", | |
| "Developed desktop applications with Tkinter" | |
| ] | |
| } | |
| ], | |
| "interests": [ | |
| "Hiking in the mountains", | |
| "Reading books", | |
| "Exploring new technologies", | |
| "Continuous learning" | |
| ], | |
| "contact": { | |
| "email": "zainabawan3316@gmail.com", | |
| "phone": "+92 3055586271", | |
| "linkedin": "linkedin.com/in/zainab-bibi-b08810312", | |
| "github": "github.com/zainabawan994", | |
| "location": "Hassan Abdal, Pakistan", | |
| "availability": "Open to internship opportunities, freelance projects, and part-time development roles" | |
| } | |
| } | |
| # ==================== SYSTEM PROMPT ==================== | |
| def get_system_prompt(): | |
| """Construct the system prompt with portfolio data.""" | |
| return f"""You are a professional portfolio assistant chatbot for Zainab Bibi. Your job is to help visitors learn about Zainab's skills, projects, education, and experience in a friendly, confident, and professional tone. Keep answers clear, enthusiastic, and concise (2-4 sentences ideally). | |
| ABOUT ZAINAB: | |
| Name: {PORTFOLIO_DATA['name']} | |
| Title: {PORTFOLIO_DATA['title']} | |
| Location: {PORTFOLIO_DATA['location']} | |
| Summary: {PORTFOLIO_DATA['summary']} | |
| TECHNICAL SKILLS: {', '.join(PORTFOLIO_DATA['skills']['technical'])} | |
| SOFT SKILLS: {', '.join(PORTFOLIO_DATA['skills']['soft'])} | |
| LANGUAGES: {', '.join(PORTFOLIO_DATA['skills']['languages'])} | |
| EDUCATION: | |
| {chr(10).join([f"- {e['degree']} at {e['school']} ({e['year']}): {e['focus']}" for e in PORTFOLIO_DATA['education']])} | |
| PROJECTS: | |
| {chr(10).join([f"- {p['name']}: {p['description']} (Built with: {', '.join(p['tech'])})" for p in PORTFOLIO_DATA['projects']])} | |
| CERTIFICATES: | |
| {chr(10).join([f"- {c['title']} from {c['issuer']} ({c['year']}): {c['description']}" for c in PORTFOLIO_DATA['certificates']])} | |
| EXPERIENCE: | |
| {chr(10).join([f"{e['role']} at {e['company']} ({e['period']}): {', '.join(e['highlights'])}" for e in PORTFOLIO_DATA['experience']])} | |
| CONTACT INFORMATION: | |
| - Email: {PORTFOLIO_DATA['contact']['email']} | |
| - Phone: {PORTFOLIO_DATA['contact']['phone']} | |
| - LinkedIn: {PORTFOLIO_DATA['contact']['linkedin']} | |
| - GitHub: {PORTFOLIO_DATA['contact']['github']} | |
| - Location: {PORTFOLIO_DATA['contact']['location']} | |
| - Availability: {PORTFOLIO_DATA['contact']['availability']} | |
| INTERESTS: {', '.join(PORTFOLIO_DATA['interests'])} | |
| IMPORTANT INSTRUCTIONS: | |
| 1. Always be concise but informative (max 3-4 sentences per answer). | |
| 2. Mention specific project names when discussing work (Portfolio Website, PDF to Audio tool, Root Alert). | |
| 3. If asked about contact info, provide the email, phone, and LinkedIn URL. | |
| 4. If asked about current status, mention she is in 5th semester of BSSE with 3.90 CGPA. | |
| 5. If asked something NOT contained in the information above, or unrelated to the portfolio, say exactly: "That's a great question! You can contact me directly for more details." | |
| 6. Never make up information not provided above. | |
| 7. Be enthusiastic, professional, and encouraging. | |
| 8. If asked about availability or hiring, mention she is open to internships and freelance opportunities. | |
| 9. When discussing the PDF to Audio project, mention it's a Python desktop app using Tkinter. | |
| 10. When discussing Root Alert, mention it's a plant care web app with alarm features.""" | |
| # ==================== GROQ CLIENT SETUP ==================== | |
| def get_groq_client(): | |
| """Initialize Groq client with API key from secrets or environment.""" | |
| try: | |
| api_key = st.secrets["GROQ_API_KEY"] | |
| except KeyError: | |
| api_key = os.getenv("GROQ_API_KEY") | |
| if not api_key: | |
| st.error("π¨ **GROQ_API_KEY not found!**") | |
| st.info(""" | |
| Please set your Groq API key: | |
| - **Local**: Create `.streamlit/secrets.toml` with `GROQ_API_KEY = "your-key"` | |
| - **Hugging Face**: Go to Settings β Secrets and add `GROQ_API_KEY` | |
| """) | |
| st.stop() | |
| return Groq(api_key=api_key) | |
| client = get_groq_client() | |
| # ==================== SIDEBAR ==================== | |
| with st.sidebar: | |
| st.markdown("### π©βπ» About Zainab") | |
| st.write(f"**{PORTFOLIO_DATA['title']}**") | |
| st.write(f"π {PORTFOLIO_DATA['location']}") | |
| st.write(f"π BSSE Student (CGPA: 3.90)") | |
| st.divider() | |
| st.subheader("π¬ Contact") | |
| st.write(f"π§ {PORTFOLIO_DATA['contact']['email']}") | |
| st.write(f"π± {PORTFOLIO_DATA['contact']['phone']}") | |
| st.write(f"πΌ [LinkedIn]({PORTFOLIO_DATA['contact']['linkedin']})") | |
| st.write(f"π [GitHub]({PORTFOLIO_DATA['contact']['github']})") | |
| st.divider() | |
| st.subheader("π οΈ Top Skills") | |
| skills_html = "" | |
| for skill in PORTFOLIO_DATA['skills']['technical'][:6]: | |
| skills_html += f'<span class="skill-badge">{skill}</span>' | |
| st.markdown(skills_html, unsafe_allow_html=True) | |
| st.divider() | |
| st.subheader("π Quick Actions") | |
| if st.button("ποΈ Clear Chat", use_container_width=True): | |
| st.session_state.messages = [] | |
| st.rerun() | |
| if st.button("π§ Email Me", use_container_width=True): | |
| st.markdown(f'<a href="mailto:{PORTFOLIO_DATA["contact"]["email"]}">Send Email</a>', unsafe_allow_html=True) | |
| st.divider() | |
| st.caption("π€ Powered by Groq + Llama 3") | |
| st.caption("Built with β€οΈ by Zainab Bibi") | |
| # ==================== MAIN INTERFACE ==================== | |
| st.markdown(f""" | |
| <div class="header-container"> | |
| <div class="header-title">Hi, I'm {PORTFOLIO_DATA['name']} π</div> | |
| <div class="header-subtitle">Frontend & Python Developer | BSSE Student</div> | |
| <div style="margin-top: 1rem; opacity: 0.9; font-size: 1rem;"> | |
| Ask me about my projects, skills, or education! | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Project quick links | |
| st.subheader("π Featured Projects") | |
| cols = st.columns(3) | |
| projects = PORTFOLIO_DATA['projects'] | |
| for i, col in enumerate(cols): | |
| with col: | |
| st.markdown(f"**{projects[i]['name']}**") | |
| st.caption(f"{' | '.join(projects[i]['tech'][:2])}") | |
| if st.button(f"Ask about this", key=f"proj_{i}", use_container_width=True): | |
| st.session_state.suggested_prompt = f"Tell me about your {projects[i]['name']} project" | |
| st.rerun() | |
| st.divider() | |
| # Suggested questions | |
| col1, col2, col3 = st.columns(3) | |
| suggested_questions = [ | |
| "What are your technical skills?", | |
| "Tell me about your Python internship experience", | |
| "How can I contact you for a project?" | |
| ] | |
| for i, col in enumerate([col1, col2, col3]): | |
| with col: | |
| if st.button(suggested_questions[i], key=f"suggest_{i}", use_container_width=True): | |
| st.session_state.suggested_prompt = suggested_questions[i] | |
| st.rerun() | |
| # ==================== CHAT INTERFACE ==================== | |
| if "messages" not in st.session_state: | |
| st.session_state.messages = [ | |
| { | |
| "role": "assistant", | |
| "content": f"""Hello! Welcome to my portfolio. I'm Zainab Bibi, a Frontend & Python Developer currently studying BS Software Engineering at University of Haripur. | |
| I love building digital solutions and turning ideas into code! Feel free to ask me about: | |
| β’ My projects (Portfolio Website, PDF to Audio tool, Root Alert) | |
| β’ My technical skills in HTML, CSS, JavaScript, React, and Python | |
| β’ My education or internship experience | |
| β’ How we can work together! | |
| What would you like to know?""" | |
| } | |
| ] | |
| # Display chat messages | |
| for message in st.session_state.messages: | |
| avatar = "π§" if message["role"] == "user" else "π€" | |
| with st.chat_message(message["role"], avatar=avatar): | |
| st.markdown(message["content"]) | |
| # Handle suggested questions | |
| if "suggested_prompt" in st.session_state: | |
| prompt = st.session_state.suggested_prompt | |
| del st.session_state.suggested_prompt | |
| else: | |
| prompt = st.chat_input("Type your question here...") | |
| if prompt: | |
| st.session_state.messages.append({"role": "user", "content": prompt}) | |
| with st.chat_message("user", avatar="π§"): | |
| st.markdown(prompt) | |
| with st.chat_message("assistant", avatar="π€"): | |
| message_placeholder = st.empty() | |
| full_response = "" | |
| try: | |
| with st.spinner("Zainab's AI Assistant is thinking..."): | |
| stream = client.chat.completions.create( | |
| model="llama-3.1-8b-instant", | |
| messages=[ | |
| {"role": "system", "content": get_system_prompt()}, | |
| *[{"role": m["role"], "content": m["content"]} for m in st.session_state.messages] | |
| ], | |
| temperature=0.7, | |
| max_tokens=1024, | |
| stream=True | |
| ) | |
| for chunk in stream: | |
| if chunk.choices[0].delta.content: | |
| full_response += chunk.choices[0].delta.content | |
| message_placeholder.markdown(full_response + "β") | |
| message_placeholder.markdown(full_response) | |
| st.session_state.messages.append({"role": "assistant", "content": full_response}) | |
| except Exception as e: | |
| st.error(f"β οΈ Error: {str(e)}") | |
| st.info("Please try again or contact me directly at zainabawan3316@gmail.com") | |
| # Footer | |
| st.divider() | |
| st.caption("π‘ This AI assistant represents Zainab Bibi. All information is accurate as of 2025.") |