steph_PA / app.py
LOLMAN65's picture
Update app.py
1cd1233 verified
Raw
History Blame Contribute Delete
7.97 kB
# ============================================
# app.py - For HuggingFace Spaces Deployment
# Simple & Clean UI (No Purple)
# ============================================
import os
import gradio as gr
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
# Get API key from HuggingFace Secrets
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
if not OPENAI_API_KEY:
raise ValueError("Please set OPENAI_API_KEY in HuggingFace Secrets")
# Path to your vector store
VECTOR_STORE_PATH = "./chroma_db"
# Load vector store
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002", openai_api_key=OPENAI_API_KEY)
try:
vector_store = Chroma(
persist_directory=VECTOR_STORE_PATH,
embedding_function=embeddings
)
print(f"✅ Loaded {vector_store._collection.count()} vectors")
except Exception as e:
print(f"⚠️ Vector store not found: {e}")
vector_store = None
if vector_store:
retriever = vector_store.as_retriever(search_kwargs={"k": 4})
prompt_template = ChatPromptTemplate.from_messages([
("system", """You are an AI assistant answering questions about Stephen Manickam's resume and CV.
Use the context below to answer accurately and helpfully. If the information is not in the context,
say "I don't see that in the resume" rather than making up information.
Be concise, professional, and friendly.
Context:
{context}
"""),
("human", "{question}")
])
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.2, openai_api_key=OPENAI_API_KEY)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt_template
| llm
| StrOutputParser()
)
def respond(message, history):
if not message.strip():
return "Please enter a question."
try:
return rag_chain.invoke(message)
except Exception as e:
return f"Error: {str(e)}"
else:
def respond(message, history):
return "Vector store not found. Please upload your resume first."
# ============================================
# Simple & Clean CSS (No Purple, Neutral Colors)
# ============================================
custom_css = """
/* Main container - clean white background */
.gradio-container {
background: #f8fafc !important;
}
/* Header styling */
.header-title {
text-align: center;
font-size: 2.5rem !important;
font-weight: 600 !important;
color: #1e293b !important;
margin-bottom: 0.5rem !important;
}
.header-subtitle {
text-align: center;
color: #64748b !important;
font-size: 1.1rem !important;
margin-bottom: 2rem !important;
}
/* Chat bubble styling */
.user-message {
background: #3b82f6 !important;
color: white !important;
border-radius: 20px !important;
padding: 12px 18px !important;
margin: 8px 0 !important;
}
.bot-message {
background: #ffffff !important;
color: #1e293b !important;
border: 1px solid #e2e8f0 !important;
border-radius: 20px !important;
padding: 12px 18px !important;
margin: 8px 0 !important;
}
/* Input box styling */
input[type="text"], textarea {
border-radius: 30px !important;
border: 1px solid #cbd5e1 !important;
padding: 12px 20px !important;
font-size: 1rem !important;
transition: all 0.2s ease !important;
background: white !important;
}
input[type="text"]:focus, textarea:focus {
border-color: #3b82f6 !important;
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1) !important;
outline: none !important;
}
/* Button styling */
button {
border-radius: 30px !important;
background: #3b82f6 !important;
color: white !important;
border: none !important;
padding: 10px 24px !important;
font-weight: 500 !important;
transition: background 0.2s ease !important;
}
button:hover {
background: #2563eb !important;
}
/* Secondary buttons (examples) */
.gr-button-secondary {
background: white !important;
color: #3b82f6 !important;
border: 1px solid #cbd5e1 !important;
}
.gr-button-secondary:hover {
background: #f1f5f9 !important;
border-color: #3b82f6 !important;
}
/* Accordion styling */
.accordion-header {
background: white !important;
border-radius: 12px !important;
border: 1px solid #e2e8f0 !important;
}
/* Footer styling */
.footer {
text-align: center;
color: #94a3b8 !important;
font-size: 0.85rem !important;
margin-top: 2rem !important;
padding: 1rem !important;
border-top: 1px solid #e2e8f0 !important;
}
"""
# Create the interface
with gr.Blocks(css=custom_css, title="Stephen Manickam - Resume Q&A Assistant") as demo:
gr.HTML("""
<div style="text-align: center; padding: 20px 0 10px 0;">
<h1 style="color: #1e293b; font-size: 2.5rem; font-weight: 600; margin-bottom: 0.5rem;">
📄 Stephen Manickam
</h1>
<h2 style="color: #475569; font-size: 1.3rem; font-weight: 500; margin-bottom: 0.25rem;">
Resume & CV Q&A Assistant
</h2>
<p style="color: #64748b; font-size: 1rem; margin-bottom: 1.5rem;">
Ask me anything about Stephen's education, work experience, skills, projects, and achievements
</p>
</div>
""")
with gr.Row():
with gr.Column(scale=1, min_width=50):
pass
with gr.Column(scale=8):
chatbot = gr.ChatInterface(
fn=respond,
examples=[
"What is Stephen's educational background?",
"What technical skills does Stephen have?",
"Summarize his work experience",
"What projects has he worked on?",
"What awards has Stephen received?",
"Tell me about his volunteer experience",
"What leadership roles has he held?",
"What is Stephen passionate about?",
],
cache_examples=False,
)
with gr.Column(scale=1, min_width=50):
pass
# Information panel
with gr.Row():
with gr.Column(scale=1, min_width=30):
pass
with gr.Column(scale=10):
with gr.Accordion("ℹ️ About This Assistant", open=False):
gr.Markdown("""
**Welcome to Stephen Manickam's Resume Assistant!**
This AI-powered assistant answers questions about Stephen Manickam's professional background:
- 🎓 **Education** - NTU Mechanical Engineering, Singapore Polytechnic
- 💼 **Work Experience** - MENCAST, Blue OC, NTU PEAK (Singtel & Thales), AAG
- 🚀 **Projects** - EY Urban Heat Detection, Exoplanets, Blue Horizon, Bug Banisher, Solar PV
- 🛠️ **Technical Skills** - Python, AI/LLMs, Data Science, Computer Vision, CAD
- 🏆 **Awards** - Most Promising Leader Award, SIEMENS Award, Judges Choice Award
- ❤️ **Volunteer Work** - IMH Mental Health, OCEP Vietnam, Women's Shelter
**How to use:** Type your question in the chat box above.
""")
with gr.Column(scale=1, min_width=30):
pass
# Footer
gr.HTML("""
<div class="footer">
<p>Powered by OpenAI GPT-3.5-Turbo • Chroma Vector Store • LangChain RAG</p>
</div>
""")
# Launch the app
demo.launch(theme=gr.themes.Base())