import streamlit as st import chromadb from sentence_transformers import SentenceTransformer import os import requests # ─── Page Config ────────────────────────────────────────────────────────────── st.set_page_config( page_title="HR Policy Assistant · RAG Demo", page_icon="📋", layout="wide", initial_sidebar_state="expanded" ) # ─── Custom CSS ─────────────────────────────────────────────────────────────── st.markdown(""" """, unsafe_allow_html=True) # ─── 10 HR & Policy Documents ───────────────────────────────────────────────── DOCUMENTS = [ { "id": "leave_policy", "title": "Annual Leave & Time-Off Policy", "content": """Annual Leave Entitlement All full-time employees are entitled to 20 days of paid annual leave per calendar year. Part-time employees receive leave on a pro-rata basis. Leave entitlement increases to 25 days after 5 years of continuous service. Leave Request Process Employees must submit leave requests at least 5 working days in advance through the HR portal. Requests are subject to manager approval and business requirements. Emergency leave may be granted at manager discretion. Carry-Over Rules Employees may carry over a maximum of 5 unused leave days into the following calendar year. Carried-over leave must be used by March 31. Unused leave beyond the carry-over limit is forfeited and not paid out. Sick Leave Employees are entitled to 10 days of paid sick leave per year. A medical certificate is required for absences exceeding 3 consecutive days. Sick leave does not carry over to the next year. Public Holidays The company observes all national public holidays. If a public holiday falls on a weekend, the nearest weekday is observed as a compensatory day off.""" }, { "id": "code_of_conduct", "title": "Employee Code of Conduct", "content": """Purpose and Scope The Code of Conduct outlines the standards of behavior expected from all employees, contractors, and interns. It applies in all work settings including offices, remote environments, and company-sponsored events. Professional Behavior Employees must treat all colleagues, clients, and partners with respect and professionalism. Discriminatory language, bullying, intimidation, or any form of harassment will not be tolerated. Conflicts of interest must be disclosed to HR immediately. Confidentiality Employees are required to maintain the confidentiality of all proprietary company information, client data, and trade secrets. Unauthorized sharing of sensitive information internally or externally is a serious violation. Use of Company Resources Company resources including laptops, software, internet access, and office equipment must be used for legitimate business purposes. Limited personal use is acceptable, provided it does not interfere with work duties or violate company policies. Reporting Violations Any employee who witnesses or suspects a violation of this Code must report it to their manager or HR. Anonymous reporting is available through the company ethics hotline. Retaliation against employees who report in good faith is strictly prohibited.""" }, { "id": "remote_work", "title": "Remote Work & Hybrid Policy", "content": """Eligibility Remote work arrangements are available to employees whose roles can be performed effectively outside the office. Eligibility is determined by the employee's manager and HR in consultation with department heads. Hybrid Schedule The standard hybrid arrangement is 3 days in-office and 2 days remote per week. Core in-office days are Tuesday, Wednesday, and Thursday unless otherwise agreed. Fully remote arrangements require VP-level approval. Home Office Requirements Employees working remotely must have a reliable internet connection with a minimum speed of 25 Mbps. A dedicated, distraction-free workspace is expected. The company will provide a one-time home office stipend of $500 for eligible employees. Availability and Communication Remote employees must be available during standard business hours (9 AM to 6 PM local time). Employees must respond to messages within 2 hours during working hours. Video is expected during team meetings and client calls. Security Requirements Employees must use the company VPN when accessing internal systems remotely. Company devices must have full-disk encryption and an active firewall. Sharing company credentials or devices with non-employees is prohibited.""" }, { "id": "performance_review", "title": "Performance Review & Appraisal Policy", "content": """Review Cycle Performance reviews are conducted twice a year: mid-year in July and year-end in December. New employees receive their first review after completing 6 months of service. Rating Scale Performance is rated on a 5-point scale: 1 = Unsatisfactory, 2 = Needs Improvement, 3 = Meets Expectations, 4 = Exceeds Expectations, 5 = Outstanding. The majority of employees are expected to fall within the Meets Expectations range. Self-Assessment Employees are required to complete a self-assessment form before each review cycle. This covers achievements, challenges, goals for the next period, and development needs. Manager Assessment Managers evaluate employees on key performance indicators (KPIs), competencies, and overall contribution to team goals. Manager feedback must be specific, evidence-based, and forward-looking. Calibration Process All ratings above 4 or below 2 must be calibrated with HR and department heads to ensure consistency and fairness. This process helps eliminate bias and maintain rating integrity. Promotion and Salary Review Year-end performance reviews are linked to the annual compensation cycle. Employees rated 4 or above are eligible for merit increases and promotional consideration. Pay adjustments are communicated by the end of January.""" }, { "id": "onboarding", "title": "Employee Onboarding Policy", "content": """Pre-Joining HR will send new employees a welcome package at least 5 business days before their start date, including equipment details, first-day instructions, and required documents. IT will provision access credentials before Day 1. Week One Agenda The first week includes an orientation session covering company values, structure, and key policies. New employees will meet with HR, their manager, and key team members. A dedicated buddy will be assigned to assist during the first 30 days. 30-60-90 Day Plan Each new employee will work with their manager to develop a 30-60-90 day onboarding plan. This plan outlines key learning objectives, initial projects, and success metrics. Progress is reviewed at the 30 and 60 day marks. Probation Period All new hires are subject to a 3-month probation period. Performance is reviewed at the end of probation, and permanent employment is confirmed upon successful completion. Early termination during probation requires 1 week's notice. Required Training Employees must complete mandatory compliance training within the first 30 days. This includes data privacy, anti-harassment, and information security modules. Failure to complete required training may affect probation review outcomes.""" }, { "id": "travel_expense", "title": "Travel & Expense Reimbursement Policy", "content": """Pre-Approval All business travel must be pre-approved by the employee's manager and submitted via the travel request system at least 5 business days in advance. International travel requires additional approval from the department head. Booking Guidelines Employees must book travel through the company's approved travel portal. Economy class is required for flights under 6 hours. Business class may be approved for flights over 6 hours with VP approval. Daily Meal Allowance The daily meal allowance is $60 for domestic travel and $90 for international travel. Alcohol is not reimbursable as part of the meal allowance. Receipts are required for any single meal expense exceeding $25. Accommodation Hotel bookings should not exceed $200 per night for domestic travel and $300 per night for international travel. Employees should select the most cost-effective option available. Expense Submission Expense reports must be submitted within 15 business days of returning from travel. All claims must be supported by original receipts. Late submissions may be denied. Non-Reimbursable Expenses The following are not reimbursable: personal entertainment, laundry for trips under 5 days, mini-bar charges, personal phone calls, fines or penalties, and expenses for accompanying non-employees.""" }, { "id": "data_privacy", "title": "Employee Data Privacy Policy", "content": """Data We Collect The company collects and processes employee personal data necessary for employment, including identification details, payroll information, performance records, and communication logs on company systems. Legal Basis Employee data is processed on the legal bases of contractual necessity, legal obligation, and legitimate business interest. Data is collected only to the extent required and not retained beyond its purpose. Data Access Employee personal data is accessible only to HR, relevant managers, and authorized system administrators. Employees have the right to request access to their own data by submitting a request through HR. Data Retention Employment records are retained for 7 years post-employment to comply with legal obligations. Payroll data is retained for 10 years. Data no longer required is securely deleted or anonymized. Third-Party Sharing Employee data may be shared with third-party service providers such as payroll processors and benefits providers under strict data processing agreements. Data is never sold to external parties. Employee Rights Employees have the right to access, correct, and in certain circumstances request deletion of their personal data. Requests can be submitted to HR or the Data Protection Officer.""" }, { "id": "anti_harassment", "title": "Anti-Harassment & Discrimination Policy", "content": """Zero Tolerance The company has a zero-tolerance policy for harassment, bullying, or discrimination of any kind. This applies to all employees, contractors, clients, and visitors regardless of role or seniority. Covered Behaviors Harassment includes unwanted physical contact, verbal abuse, offensive jokes, exclusion, microaggressions, and inappropriate digital communication. Discrimination on the basis of race, gender, age, religion, disability, sexual orientation, or national origin is strictly prohibited. Reporting Process Employees who experience or witness harassment or discrimination should report it to HR or their skip-level manager immediately. Reports can be submitted verbally, in writing, or anonymously through the ethics hotline. Investigation Procedure All reports are treated confidentially and investigated promptly by HR. Investigations are completed within 30 days. Both the complainant and the accused will be interviewed, and findings communicated to relevant parties. Outcomes If harassment or discrimination is substantiated, the responsible party will face disciplinary action up to and including termination. The company will take corrective measures to prevent recurrence. Non-Retaliation Any retaliation against an employee who reports harassment in good faith is itself a serious violation and grounds for disciplinary action.""" }, { "id": "compensation_benefits", "title": "Compensation & Benefits Policy", "content": """Salary Structure Salaries are determined by role, experience, market benchmarking, and internal equity. The company conducts an annual compensation review aligned with the performance appraisal cycle. All salary adjustments are subject to HR and leadership approval. Pay Schedule Employees are paid monthly on the last business day of each month via direct bank transfer. Payslips are issued electronically through the HR portal at least 3 days before payment. Health Insurance The company provides comprehensive health insurance coverage for all full-time employees effective from Day 1. Coverage includes medical, dental, and vision. Employees may add dependents at their own cost. Retirement Plan The company contributes 5% of the employee's base salary to a retirement fund. Employees may make additional voluntary contributions. Contributions vest fully after 2 years of continuous service. Wellness Benefits Employees receive an annual wellness allowance of $300, which can be used for gym memberships, fitness equipment, or mental health services. Claims must be submitted with receipts through the HR portal. Other Benefits Additional benefits include a $1,000 annual learning and development budget, 5 paid volunteer days per year, a referral bonus of $1,500 for successful hires, and access to an Employee Assistance Program for confidential counseling.""" }, { "id": "termination", "title": "Resignation & Termination Policy", "content": """Voluntary Resignation Employees wishing to resign must submit written notice to their manager and HR. The standard notice period is 4 weeks for non-managerial roles and 8 weeks for managerial and senior roles. The company may choose to waive the notice period. Notice Period During the notice period, employees are expected to complete assigned work and facilitate handover. Accrued annual leave may be used during the notice period with manager approval. Unused leave beyond this may be paid out. Involuntary Termination Termination without cause requires the company to provide written notice or payment in lieu. Termination for cause (gross misconduct) may result in immediate dismissal without notice or severance. Exit Process Upon separation, HR will conduct an exit interview. All company property including laptops, access cards, and documents must be returned on or before the last day. System access will be revoked at the end of the final working day. Final Pay Final salary, including any outstanding reimbursements and accrued leave payout, will be processed in the next payroll cycle following the last working day. Post-Employment Obligations Post-employment confidentiality obligations remain in force indefinitely. Non-compete clauses, where applicable, are in effect for 12 months following termination.""" } ] # ─── RAG Initialization (cached) ───────────────────────────────────────────── @st.cache_resource(show_spinner=False) def init_rag(): model = SentenceTransformer('all-MiniLM-L6-v2') client = chromadb.Client() collection = client.get_or_create_collection( name="hr_policies", metadata={"hnsw:space": "cosine"} ) all_ids, all_embeddings, all_docs, all_metas = [], [], [], [] chunk_count = 0 for doc in DOCUMENTS: paragraphs = [p.strip() for p in doc['content'].split('\n\n') if len(p.strip()) > 40] for i, para in enumerate(paragraphs): chunk_id = f"{doc['id']}_chunk_{i}" embedding = model.encode(para).tolist() all_ids.append(chunk_id) all_embeddings.append(embedding) all_docs.append(para) all_metas.append({"title": doc['title'], "doc_id": doc['id']}) chunk_count += 1 collection.add(ids=all_ids, embeddings=all_embeddings, documents=all_docs, metadatas=all_metas) return model, collection, chunk_count # ─── Groq LLM Call ──────────────────────────────────────────────────────────── def query_groq(prompt: str, api_key: str) -> str: headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"} payload = { "model": "llama-3.3-70b-versatile", "messages": [{"role": "user", "content": prompt}], "max_tokens": 512, "temperature": 0.2, } r = requests.post("https://api.groq.com/openai/v1/chat/completions", headers=headers, json=payload, timeout=30) r.raise_for_status() return r.json()["choices"][0]["message"]["content"] # ─── RAG Pipeline ───────────────────────────────────────────────────────────── def rag_query(question: str, model, collection, api_key: str, top_k: int = 3): # Step 1: embed query q_embedding = model.encode(question).tolist() # Step 2: vector search results = collection.query(query_embeddings=[q_embedding], n_results=top_k) # Step 3: build context chunks = [] for i in range(len(results['documents'][0])): distance = results['distances'][0][i] chunks.append({ "text": results['documents'][0][i], "title": results['metadatas'][0][i]['title'], "relevance": round((1 - distance) * 100, 1), }) context = "\n\n".join([f"[Source: {c['title']}]\n{c['text']}" for c in chunks]) # Step 4: generate prompt = f"""You are a helpful HR assistant for a company. Answer the employee's question using ONLY the policy context provided below. Be friendly, clear, and concise. Reference the specific policy name when answering. If the answer cannot be found in the context, say "I don't have that information in the current policy documents." Policy Context: {context} Employee Question: {question} Answer:""" answer = query_groq(prompt, api_key) return answer, chunks # ─── Sidebar ────────────────────────────────────────────────────────────────── with st.sidebar: st.markdown("## 📋 HR Policy RAG Demo") st.markdown("
Retrieval-Augmented Generation
", unsafe_allow_html=True) st.markdown("---") # API Key — prefer env var (set as HF Space Secret), fallback to input env_key = os.environ.get("GROQ_API_KEY", "") if env_key: api_key = env_key st.success("✅ API key loaded from Space secrets") else: api_key = st.text_input( "🔑 Groq API Key", type="password", placeholder="gsk_...", help="Free key at console.groq.com" ) if not api_key: st.caption("Get a free key → [console.groq.com](https://console.groq.com)") st.markdown("---") st.markdown("
Loaded Documents
", unsafe_allow_html=True) for doc in DOCUMENTS: st.markdown(f"
📄 {doc['title']}
", unsafe_allow_html=True) st.markdown("---") st.markdown("""
Stack
🟣 Embeddings: sentence-transformers
🔵 Vector DB: ChromaDB (in-memory)
🟢 LLM: Groq · Llama 3.3 70B
⚪ Hosting: HuggingFace Spaces
""", unsafe_allow_html=True) # ─── Main UI ────────────────────────────────────────────────────────────────── st.markdown("""

🤖 HR Policy Assistant

Ask any question about company policies — powered by RAG (Retrieval-Augmented Generation)

""", unsafe_allow_html=True) # Pipeline visualization st.markdown("""
📄 10 HR Docs
✂️ Chunking
🔢 Embeddings
🗄️ ChromaDB
🔍 Similarity Search
🧠 Llama 3.3 70B
💬 Answer
""", unsafe_allow_html=True) # Load RAG if not api_key: st.info("👈 Enter your **Groq API key** in the sidebar to start asking questions.") st.markdown("### 💡 Example questions you can ask once set up:") examples_preview = [ "How many days of annual leave do I get?", "Can I carry over unused leave to next year?", "What is the remote work policy?", "How do I report harassment?", "What is the daily meal allowance when travelling?", "How does the performance review work?", "What is the notice period if I resign?", "What happens to my data after I leave the company?", ] cols = st.columns(2) for i, q in enumerate(examples_preview): cols[i % 2].markdown(f"
💬 {q}
", unsafe_allow_html=True) st.stop() # Initialize with st.spinner("⚙️ Loading embedding model & indexing documents... (first load ~30s)"): embed_model, collection, chunk_count = init_rag() # Stats st.markdown(f"""
10
Documents
{chunk_count}
Chunks Indexed
384
Embedding Dims
cosine
Similarity Metric
""", unsafe_allow_html=True) # Query input st.markdown("
Ask a Question
", unsafe_allow_html=True) query = st.text_input("", placeholder="e.g. How many sick days am I entitled to?", label_visibility="collapsed") # Example question buttons st.markdown("
Quick Examples
", unsafe_allow_html=True) example_questions = [ "How many annual leave days do I get?", "What is the hybrid work schedule?", "How do I report harassment at work?", "What is the travel meal allowance?", "How does the year-end review work?", "What is the notice period if I resign?", ] cols = st.columns(3) clicked_example = None for i, q in enumerate(example_questions): if cols[i % 3].button(q, key=f"ex_{i}", use_container_width=True): clicked_example = q final_query = clicked_example or query # Run RAG if final_query: with st.spinner("🔍 Searching policies and generating answer..."): try: answer, chunks = rag_query(final_query, embed_model, collection, api_key) st.markdown(f"""
Your Question
"{final_query}"
Answer
{answer}
""", unsafe_allow_html=True) st.markdown("
Retrieved Context Chunks (what the LLM saw)
", unsafe_allow_html=True) st.caption("These are the exact chunks retrieved from the vector DB and passed as context to the LLM.") for i, chunk in enumerate(chunks): color = "#6366f1" if chunk['relevance'] > 75 else "#f59e0b" if chunk['relevance'] > 55 else "#6b7280" st.markdown(f"""
📄 {chunk['title']}
{chunk['relevance']}% match
{chunk['text']}
""", unsafe_allow_html=True) except requests.HTTPError as e: if e.response.status_code == 401: st.error("❌ Invalid Groq API key. Please check and try again.") else: st.error(f"❌ API error: {str(e)}") except Exception as e: st.error(f"❌ Error: {str(e)}")