Spaces:
Sleeping
Sleeping
import streamlit as st | |
import json | |
import time | |
# Page configuration | |
st.set_page_config( | |
page_title="Manyue's Portfolio Chatbot", | |
page_icon="π€", | |
layout="wide", | |
initial_sidebar_state="collapsed" | |
) | |
# Custom CSS for better UI | |
st.markdown(""" | |
<style> | |
.chat-message { | |
padding: 1.5rem; | |
border-radius: 0.5rem; | |
margin-bottom: 1rem; | |
} | |
.user-message { | |
background-color: #e9ecef; | |
} | |
.bot-message { | |
background-color: #f8f9fa; | |
} | |
.stButton>button { | |
width: 100%; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Initialize session state | |
if 'messages' not in st.session_state: | |
st.session_state.messages = [] | |
if 'knowledge_base' not in st.session_state: | |
st.session_state.knowledge_base = None | |
def load_knowledge_base(): | |
"""Load the knowledge base from JSON file""" | |
if st.session_state.knowledge_base is None: | |
try: | |
with open('knowledge_base.json', 'r', encoding='utf-8') as f: | |
st.session_state.knowledge_base = json.load(f) | |
except Exception as e: | |
st.error(f"Error loading knowledge base: {str(e)}") | |
st.session_state.knowledge_base = {} | |
return st.session_state.knowledge_base | |
def get_enhanced_context(query: str, knowledge_base: dict) -> dict: | |
"""Get relevant context with improved retrieval""" | |
query_lower = query.lower() | |
context = { | |
"type": "general", | |
"content": [], | |
"relevant_sections": [] | |
} | |
# Project-related queries | |
if any(word in query_lower for word in ["project", "build", "develop", "create", "make", "portfolio"]): | |
context["type"] = "project" | |
if "projects" in knowledge_base: | |
for name, project in knowledge_base["projects"].items(): | |
context["content"].append({ | |
"title": name, | |
"description": project.get("description", ""), | |
"skills_used": project.get("skills_used", []), | |
"status": project.get("status", "") | |
}) | |
# Skills and experience | |
elif any(word in query_lower for word in ["skill", "experience", "know", "capable", "ability", "expert"]): | |
context["type"] = "skill" | |
if "skills" in knowledge_base.get("personal_details", {}): | |
context["content"] = knowledge_base["personal_details"]["skills"] | |
# Educational background | |
elif any(word in query_lower for word in ["education", "study", "learn", "degree", "college", "university"]): | |
context["type"] = "education" | |
context["content"] = knowledge_base.get("education", {}) | |
# Career and goals | |
elif any(word in query_lower for word in ["goal", "plan", "future", "career", "aspiration"]): | |
context["type"] = "career" | |
context["content"] = { | |
"short_term": knowledge_base.get("goals_and_aspirations", {}).get("short_term", []), | |
"long_term": knowledge_base.get("goals_and_aspirations", {}).get("long_term", []) | |
} | |
# Personal background | |
elif any(word in query_lower for word in ["background", "journey", "story", "transition"]): | |
context["type"] = "background" | |
context["content"] = knowledge_base.get("personal_journey", {}) | |
# Add FAQ matches if available | |
for qa in knowledge_base.get("frequently_asked_questions", []): | |
if any(word in qa["question"].lower() for word in query_lower.split()): | |
context["relevant_sections"].append({ | |
"type": "faq", | |
"question": qa["question"], | |
"answer": qa["answer"] | |
}) | |
return context | |
def generate_response(query: str, context: dict) -> str: | |
"""Generate natural response based on context""" | |
response_parts = [] | |
# Handle different types of queries | |
if context["type"] == "project": | |
response_parts.append("Let me tell you about my projects.") | |
for project in context["content"]: | |
response_parts.append(f"\n\n**{project['title']}**") | |
response_parts.append(f"{project['description']}") | |
if project['skills_used']: | |
response_parts.append(f"\nSkills used: {', '.join(project['skills_used'])}") | |
if project['status']: | |
response_parts.append(f"\nStatus: {project['status']}") | |
elif context["type"] == "skill": | |
response_parts.append("Here are my key skills and experiences:") | |
for skill, desc in context["content"].items(): | |
response_parts.append(f"\n\n**{skill}**:\n{desc}") | |
elif context["type"] == "education": | |
response_parts.append("Regarding my educational background:") | |
if "academic_background" in context["content"]: | |
response_parts.append(context["content"]["academic_background"]) | |
if "academic_achievements" in context["content"]: | |
response_parts.append("\n\nAchievements:") | |
for achievement in context["content"]["academic_achievements"]: | |
response_parts.append(f"- {achievement}") | |
elif context["type"] == "career": | |
response_parts.append("Let me share my career goals:") | |
response_parts.append("\n\n**Short-term goals:**") | |
for goal in context["content"]["short_term"]: | |
response_parts.append(f"- {goal}") | |
response_parts.append("\n\n**Long-term goals:**") | |
for goal in context["content"]["long_term"]: | |
response_parts.append(f"- {goal}") | |
elif context["type"] == "background": | |
response_parts.append(context["content"].get("mindset", "")) | |
response_parts.append("\n\n" + context["content"].get("motto_or_vision", "")) | |
# Add any relevant FAQ information | |
if context["relevant_sections"]: | |
for section in context["relevant_sections"]: | |
if section["type"] == "faq": | |
response_parts.append(f"\n\n{section['answer']}") | |
# Default response if no specific context matched | |
if not response_parts: | |
response_parts = ["I am Manyue, an aspiring AI/ML engineer. I can tell you about my projects, skills, education, or career goals. What would you like to know?"] | |
return "\n".join(response_parts) | |
def main(): | |
st.title("π¬ Chat with Manyue's Portfolio") | |
st.write("Ask me about my skills, projects, education, or career goals!") | |
# Load knowledge base | |
knowledge_base = load_knowledge_base() | |
# Create two columns for layout | |
col1, col2 = st.columns([3, 1]) | |
with col1: | |
# Display chat messages | |
for message in st.session_state.messages: | |
with st.chat_message(message["role"]): | |
st.markdown(message["content"]) | |
# Chat input | |
if prompt := st.chat_input("What would you like to know?"): | |
# Add user message | |
st.session_state.messages.append({"role": "user", "content": prompt}) | |
# Get context and generate response | |
context = get_enhanced_context(prompt, knowledge_base) | |
response = generate_response(prompt, context) | |
# Display response with typing effect | |
with st.chat_message("assistant"): | |
st.markdown(response) | |
# Add assistant response to history | |
st.session_state.messages.append({"role": "assistant", "content": response}) | |
with col2: | |
st.subheader("Quick Questions") | |
if st.button("π Tell me about your projects"): | |
prompt = "What projects have you worked on?" | |
st.session_state.messages.append({"role": "user", "content": prompt}) | |
st.experimental_rerun() | |
if st.button("π» What are your technical skills?"): | |
prompt = "What are your main technical skills?" | |
st.session_state.messages.append({"role": "user", "content": prompt}) | |
st.experimental_rerun() | |
if st.button("π Educational background?"): | |
prompt = "Tell me about your education" | |
st.session_state.messages.append({"role": "user", "content": prompt}) | |
st.experimental_rerun() | |
if st.button("π― What are your career goals?"): | |
prompt = "What are your career goals?" | |
st.session_state.messages.append({"role": "user", "content": prompt}) | |
st.experimental_rerun() | |
st.markdown("---") | |
if st.button("ποΈ Clear Chat"): | |
st.session_state.messages = [] | |
st.experimental_rerun() | |
if __name__ == "__main__": | |
main() |