""" Hugging Face Spaces deployment - Combined API and UI """ import os os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python' import gradio as gr import sys import pandas as pd from io import StringIO # Add src to path for imports from recommendation_engine import RecommendationEngine import json # Initialize engine print("Loading recommendation engine...") engine = RecommendationEngine(catalog_path='shl_catalogue.csv') print("Engine loaded!") def get_recommendations(query, top_k=10): """Get recommendations for a query""" try: if not query or len(query.strip()) < 10: return "❌ Query must be at least 10 characters long." # Get recommendations result = engine.recommend(query, top_k=int(top_k)) # Format output output = f"## 🎯 Top {top_k} Recommendations\n\n" output += f"**Query:** {result['query']}\n\n" # Table header output += "| # | Assessment Name | Type | Score |\n" output += "|---|----------------|------|-------|\n" # Recommendations for i, rec in enumerate(result['recommendations'], 1): name = rec['assessment_name'] test_type = rec['test_type_label'] score = f"{rec['similarity_score']:.3f}" output += f"| {i} | [{name}]({rec['url']}) | {test_type} | {score} |\n" # LLM Explanation if result.get('explanation'): output += f"\n### 💡 AI Analysis\n\n{result['explanation']}\n" # Best recommendation if result.get('best_recommendation'): output += f"\n**🏆 Best Match:** {result['best_recommendation']}\n" return output except Exception as e: return f"❌ Error: {str(e)}" def get_recommendations_with_csv(query, top_k=10): """Get recommendations and return both markdown and CSV file""" try: if not query or len(query.strip()) < 10: return "❌ Query must be at least 10 characters long.", None # Get recommendations result = engine.recommend(query, top_k=int(top_k)) # Format markdown output output = f"## 🎯 Top {top_k} Recommendations\n\n" output += f"**Query:** {result['query']}\n\n" # Table header output += "| # | Assessment Name | Type | Score |\n" output += "|---|----------------|------|-------|\n" # Recommendations for i, rec in enumerate(result['recommendations'], 1): name = rec['assessment_name'] test_type = rec['test_type_label'] score = f"{rec['similarity_score']:.3f}" output += f"| {i} | [{name}]({rec['url']}) | {test_type} | {score} |\n" # LLM Explanation if result.get('explanation'): output += f"\n### 💡 AI Analysis\n\n{result['explanation']}\n" # Best recommendation if result.get('best_recommendation'): output += f"\n**🏆 Best Match:** {result['best_recommendation']}\n" # Create CSV file csv_data = [] for i, rec in enumerate(result['recommendations'], 1): csv_data.append({ 'Rank': i, 'Query': result['query'], 'Assessment_Name': rec['assessment_name'], 'Assessment_URL': rec['url'], 'Test_Type': rec['test_type_label'], 'Relevance_Score': round(rec['similarity_score'], 4) }) df = pd.DataFrame(csv_data) csv_file = "recommendations.csv" df.to_csv(csv_file, index=False) return output, csv_file except Exception as e: return f"❌ Error: {str(e)}", None def get_recommendations_json(query, top_k=10): """API endpoint - returns JSON""" try: if not query or len(query.strip()) < 10: return {"error": "Query must be at least 10 characters long."} result = engine.recommend(query, top_k=int(top_k)) # Format as per API specification return { "query": result['query'], "recommendations": [ { "assessment_name": rec['assessment_name'], "url": rec['url'], "relevance_score": rec['similarity_score'], "test_type": rec['test_type_label'] } for rec in result['recommendations'] ], "total_results": result['total_results'], "explanation": result.get('explanation'), "best_recommendation": result.get('best_recommendation') } except Exception as e: return {"error": str(e)} # Create Gradio interface with tabs with gr.Blocks(title="SHL Assessment Recommendation System", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 🎯 SHL Assessment Recommendation System Intelligent AI-powered recommendation system for SHL assessments using RAG (Retrieval-Augmented Generation). **Features:** - 🔍 Semantic search with sentence embeddings - 🤖 AI explanations powered by Google Gemini - ⚖️ Smart balancing of technical & behavioral assessments - 📊 54 assessments from SHL catalog - 📥 Download recommendations as CSV """) with gr.Tabs(): # Tab 1: Web UI with gr.Tab("🌐 Web Interface"): gr.Markdown("### Enter your job description or query:") with gr.Row(): with gr.Column(scale=4): query_input = gr.Textbox( label="Job Query", placeholder="e.g., 'Java developer with collaboration skills'", lines=3 ) with gr.Column(scale=1): top_k_slider = gr.Slider( minimum=1, maximum=10, value=10, step=1, label="Number of Recommendations" ) recommend_btn = gr.Button("🎯 Get Recommendations", variant="primary", size="lg") with gr.Row(): with gr.Column(scale=3): output_md = gr.Markdown() with gr.Column(scale=1): csv_download = gr.File(label="📥 Download CSV", visible=True) recommend_btn.click( fn=get_recommendations_with_csv, inputs=[query_input, top_k_slider], outputs=[output_md, csv_download] ) gr.Examples( examples=[ ["I am hiring for Java developers who can also collaborate effectively with my business teams.", 10], ["Looking to hire mid-level professionals who are proficient in Python, SQL and JavaScript.", 10], ["I am hiring for an analyst and want to screen using Cognitive and personality tests.", 8], ["Entry-level sales professional needed for my team.", 5], ], inputs=[query_input, top_k_slider], ) # Tab 2: API with gr.Tab("🔌 API"): gr.Markdown(""" ### REST API Endpoint Use this interface to test the API JSON response format. **Endpoint:** `/recommend` (POST) **Request Format:** ```json { "query": "Your job description here", "top_k": 10 } ``` """) with gr.Row(): with gr.Column(): api_query_input = gr.Textbox( label="Query", placeholder="Enter job description", lines=3 ) api_top_k = gr.Number(label="top_k", value=10, precision=0) api_btn = gr.Button("📡 Send API Request", variant="primary") with gr.Column(): api_output = gr.JSON(label="API Response") api_btn.click( fn=get_recommendations_json, inputs=[api_query_input, api_top_k], outputs=api_output ) # Launch if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=7860)