import os import logging import sys import gradio as gr from pinecone import Pinecone from llama_index.core import VectorStoreIndex, Settings, StorageContext from llama_index.vector_stores.pinecone import PineconeVectorStore from llama_index.llms.openai import OpenAI from llama_index.embeddings.openai import OpenAIEmbedding # --- Logging --- logging.basicConfig(stream=sys.stdout, level=logging.INFO) # --- Secrets from Hugging Face Spaces --- PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY") OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") if not PINECONE_API_KEY: raise ValueError("Missing PINECONE_API_KEY in Hugging Face Space secrets.") if not OPENAI_API_KEY: raise ValueError("Missing OPENAI_API_KEY in Hugging Face Space secrets.") # --- LlamaIndex Settings --- Settings.llm = OpenAI( model="gpt-4o-mini", temperature=0.2, api_key=OPENAI_API_KEY ) Settings.embed_model = OpenAIEmbedding( model="text-embedding-ada-002", api_key=OPENAI_API_KEY ) Settings.chunk_size = 600 Settings.chunk_overlap = 200 # --- System Prompt --- system_prompt = ''' You are Ayesha, the Decoding Data Science (DDS) Enterprise HR Chatbot. Your objective is to interact politely and professionally with employees, answering only HR-related questions. Use only information directly from the connected HR documents to provide your answers. Always provide an explicit citation indicating the document source for every answer. Do not offer information or suggestions beyond what is present in these documents. If the requested information cannot be found in the connected documents, politely instruct the user to email connect@decodingdatascience.com for further assistance. For questions outside of HR, inform the user that you can only answer HR-related questions. If a question is unclear or possibly HR-related but ambiguous, ask the user to rephrase. Never attempt to answer non-HR, personal, or unrelated questions. - Remain polite and professional in all interactions. - Respond exclusively to HR-related topics using only the connected HR documents. - Always include an explicit citation to the relevant document(s) for every answer. - If a question is off-topic, state that you can only address HR questions. - If you are unsure whether the question is HR-related, politely ask for clarification or rephrasing. - For HR-related questions where the answer is not in the connected documents, kindly direct the user to email connect@decodingdatascience.com. - Use a friendly and formal tone. Respond in short, clear paragraphs (2-4 sentences). Do not use markdown or code blocks. Every answer must include the citation showing which document(s) the information is sourced from. ''' # --- Connect to existing Pinecone index --- index_name = "quickstart" pc = Pinecone(api_key=PINECONE_API_KEY) pinecone_index = pc.Index(index_name) # --- Connect LlamaIndex to existing Pinecone vector store --- vector_store = PineconeVectorStore(pinecone_index=pinecone_index) storage_context = StorageContext.from_defaults(vector_store=vector_store) index = VectorStoreIndex.from_vector_store( vector_store=vector_store, storage_context=storage_context ) # --- Query Engine --- query_engine = index.as_query_engine( system_prompt=system_prompt, similarity_top_k=2 ) # --- App Logic (unchanged) --- def query_doc(prompt): try: if not prompt or not prompt.strip(): return "Please enter an HR-related question." response = query_engine.query(prompt) return str(response) except Exception as e: return f"Error: {str(e)}" def fill_example(example_text): return example_text # IMPORTANT: # GitHub "blob" links do not directly render as images in many apps. # Use the RAW version of your logo URL instead. LOGO_URL = "https://raw.githubusercontent.com/Decoding-Data-Science/airesidency/main/dds-logo-removebg-preview.png" faq_questions = [ "What is the leave policy?", "How many annual leave days do employees get?", "What is the probation period policy?", "What is the work from home policy?", "How is sick leave handled?", "What is the process for reimbursement claims?", "What are the office working hours?", "How does the company handle public holidays?" ] custom_css = """ body { font-family: Arial, sans-serif; } .gradio-container { max-width: 1250px !important; margin: auto !important; } .hero-card, .faq-card, .chat-card, .note-card { border-radius: 16px; padding: 18px; border: 1px solid #e5e7eb; background: #ffffff; box-shadow: 0 4px 14px rgba(0,0,0,0.06); } .brand-title { font-size: 28px; font-weight: 700; margin-bottom: 6px; color: #111827; } .brand-subtitle { font-size: 15px; color: #4b5563; line-height: 1.6; } .section-title { font-size: 18px; font-weight: 700; margin-bottom: 10px; color: #111827; } .small-note { font-size: 13px; color: #6b7280; line-height: 1.5; } .logo-wrap { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; } .logo-wrap img { max-height: 72px; width: auto; } .footer-note { font-size: 12px; color: #6b7280; margin-top: 8px; } """ with gr.Blocks(css=custom_css, title="DDS Enterprise HR Chatbot") as demo: gr.HTML( f"""
DDS Logo
DDS Enterprise HR Chatbot
A professional HR assistant powered by LlamaIndex, Pinecone, and OpenAI. Ask policy-related questions based only on indexed HR documents.
""" ) with gr.Row(equal_height=True): with gr.Column(scale=1, min_width=320): gr.HTML('
') gr.Markdown("### HR FAQ / Quick Questions") gr.Markdown( "Use the examples below to quickly test common HR policy questions." ) example_box = gr.Textbox( label="Selected FAQ Question", placeholder="Click an example below or type your own question on the right." ) with gr.Column(): for q in faq_questions: btn = gr.Button(q, variant="secondary") btn.click(fn=fill_example, inputs=gr.State(q), outputs=example_box) gr.Markdown( "### Suggested Topics\n" "- Leave policy\n" "- Sick leave\n" "- Reimbursements\n" "- Working hours\n" "- Probation period\n" "- Public holidays" ) gr.HTML( """ """ ) gr.HTML("
") with gr.Column(scale=2, min_width=500): gr.HTML('
') gr.Markdown("### Ask Your HR Question") prompt = gr.Textbox( label="Your Question", placeholder="Example: What is the annual leave policy for full-time employees?", lines=4 ) answer = gr.Textbox( label="Assistant Response", lines=12, interactive=False ) with gr.Row(): ask_btn = gr.Button("Ask HR Assistant", variant="primary") clear_btn = gr.Button("Clear") gr.Markdown( "### Notes\n" "- Responses are based only on indexed HR documents.\n" "- Every answer should include a document citation.\n" "- If the answer is not found, users are directed to connect@decodingdatascience.com." ) gr.HTML("
") gr.HTML('
') gr.Markdown("### Copy Selected FAQ into the Question Box") use_example_btn = gr.Button("Use Selected FAQ Question", variant="secondary") gr.HTML("
") # Button actions ask_btn.click(fn=query_doc, inputs=prompt, outputs=answer) prompt.submit(fn=query_doc, inputs=prompt, outputs=answer) use_example_btn.click(fn=fill_example, inputs=example_box, outputs=prompt) clear_btn.click( fn=lambda: ("", "", ""), inputs=[], outputs=[prompt, answer, example_box] ) if __name__ == "__main__": demo.launch()