VGreatVig07 commited on
Commit
214ecb2
·
verified ·
1 Parent(s): faed9d9

Upload 8 files

Browse files
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  Backend/shl_vector_index.faiss filter=lfs diff=lfs merge=lfs -text
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  Backend/shl_vector_index.faiss filter=lfs diff=lfs merge=lfs -text
37
+ shl_vector_index.faiss filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile
2
+ FROM python:3.10-slim
3
+
4
+ WORKDIR /app
5
+
6
+ COPY . .
7
+
8
+ RUN pip install --no-cache-dir -r requirements.txt
9
+
10
+ EXPOSE 9000
11
+
12
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Static/index.html ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>SHL Assessment Recommender</title>
6
+ <style>
7
+ body {
8
+ font-family: Arial, sans-serif;
9
+ padding: 20px;
10
+ background-color: #f4f6f8;
11
+ }
12
+
13
+ input, button {
14
+ padding: 10px;
15
+ font-size: 16px;
16
+ margin-right: 10px;
17
+ }
18
+
19
+ button {
20
+ cursor: pointer;
21
+ }
22
+
23
+ .results {
24
+ margin-top: 20px;
25
+ }
26
+
27
+ .card {
28
+ border: 1px solid #ccc;
29
+ padding: 15px;
30
+ margin: 10px 0;
31
+ border-radius: 10px;
32
+ background: #ffffff;
33
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
34
+ }
35
+
36
+ .card h3 {
37
+ margin: 0 0 10px;
38
+ }
39
+ </style>
40
+ </head>
41
+ <body>
42
+ <h2>🔍 SHL Assessment Recommender</h2>
43
+ <input type="text" id="queryInput" placeholder="Enter your job role or requirement..." size="50">
44
+ <button onclick="sendQuery()">Search</button>
45
+
46
+ <div class="results" id="results"></div>
47
+
48
+ <script>
49
+ async function sendQuery() {
50
+ const query = document.getElementById("queryInput").value;
51
+ const resultsDiv = document.getElementById("results");
52
+ resultsDiv.innerHTML = "<p>Searching...</p>";
53
+
54
+ try {
55
+ const response = await fetch("http://localhost:8000/query", {
56
+ method: "POST",
57
+ headers: {
58
+ "Content-Type": "application/json"
59
+ },
60
+ body: JSON.stringify({ query })
61
+ });
62
+
63
+ const data = await response.json();
64
+
65
+ if (data.recommendations && data.recommendations.length > 0) {
66
+ resultsDiv.innerHTML = data.recommendations.map((r, index) => `
67
+ <div class="card">
68
+ <h3>🏆 Rank ${index + 1}: ${r.Assignment_Name}</h3>
69
+ <p>🔗 <a href="${r.Assignment_Link}" target="_blank">${r.Assignment_Link}</a></p>
70
+ <p>🧪 Test Type: ${r.Test_Type}</p>
71
+ <p>⏱️ Duration: ${r.Approximate_Completion_Time} mins</p>
72
+ <p>🌐 Remote Testing: ${r.Remote_Testing_Support}</p>
73
+ <p>📊 Adaptive/IRT: ${r.Adaptive_IRT_Support}</p>
74
+ <p>👤 Job Levels: ${r.Job_Levels}</p>
75
+ </div>
76
+ `).join("");
77
+ } else {
78
+ resultsDiv.innerHTML = "<p>No results found.</p>";
79
+ }
80
+ } catch (error) {
81
+ resultsDiv.innerHTML = `<p style="color:red;">Error: ${error.message}</p>`;
82
+ }
83
+ }
84
+ </script>
85
+ </body>
86
+ </html>
__pycache__/main.cpython-313.pyc ADDED
Binary file (3.96 kB). View file
 
main.py ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request
2
+ from fastapi.staticfiles import StaticFiles
3
+ from fastapi.responses import FileResponse
4
+ from pydantic import BaseModel
5
+ import google.generativeai as genai
6
+ from dotenv import load_dotenv
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ import os
9
+ import json
10
+ import pandas as pd
11
+ import faiss
12
+ from sentence_transformers import SentenceTransformer
13
+ import uvicorn
14
+ import math
15
+
16
+ # Load environment variables and configure Gemini
17
+ load_dotenv()
18
+ genai.configure(api_key=os.getenv("API_KEY"))
19
+ gemini_model = genai.GenerativeModel("gemini-2.0-flash")
20
+
21
+ # Load vector index and dataframe
22
+ index = faiss.read_index("shl_vector_index.faiss")
23
+ df = pd.read_csv("shl_combined_assessments.csv")
24
+ model = SentenceTransformer("all-MiniLM-L6-v2")
25
+
26
+ # FastAPI app
27
+ app = FastAPI()
28
+
29
+ app.mount("/static", StaticFiles(directory="Static"), name="static")
30
+
31
+
32
+ app.add_middleware(
33
+ CORSMiddleware,
34
+ allow_origins=["*"], # or specify your frontend origin like ["http://localhost:3000"]
35
+ allow_credentials=True,
36
+ allow_methods=["*"], # allows all HTTP methods including OPTIONS
37
+ allow_headers=["*"],
38
+ )
39
+
40
+ @app.get("/")
41
+ async def read_index():
42
+ return FileResponse(os.path.join("Static", "index.html"))
43
+
44
+ # Request schema
45
+ class Query(BaseModel):
46
+ query: str
47
+
48
+ # Format result
49
+ def format_row(row):
50
+ def safe_cast(val, cast_type, default):
51
+ try:
52
+ if val is None or (isinstance(val, float) and math.isnan(val)):
53
+ return default
54
+ return cast_type(val)
55
+ except Exception:
56
+ return default
57
+
58
+ return {
59
+ "Assignment_Name": str(row["Assignment_Name"]),
60
+ "Assignment_Link": str(row["Assignment_Link"]),
61
+ "Test_Type": str(row["Test_Type"]),
62
+ "Approximate_Completion_Time": safe_cast(row["Approximate_Completion_Time"], int, -1),
63
+ "Remote_Testing_Support": bool(row["Remote_Testing_Support"]),
64
+ "Adaptive_IRT_Support": bool(row["Adaptive_IRT_Support"]),
65
+ "Job_Levels": str(row.get("Job_Levels", "N/A")),
66
+ }
67
+
68
+ # API endpoint
69
+ @app.post("/query")
70
+ async def query_assessments(payload: Query):
71
+ query_embedding = model.encode([payload.query]).astype("float32")
72
+ D, I = index.search(query_embedding, 10) # Top 10 results
73
+
74
+ results = [format_row(df.iloc[idx]) for idx in I[0]]
75
+ return {"query": payload.query, "recommendations": results}
76
+
77
+ # if __name__ == "__main__":
78
+ # uvicorn.run("main:app", host="0.0.0.0", port=9000, reload=True)
render.yaml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ - type: web
3
+ name: shl-fastapi-backend
4
+ runtime: python
5
+ buildCommand: pip install -r requirements.txt
6
+ startCommand: uvicorn main:app --host 0.0.0.0 --port 9000
7
+ envVars:
8
+ - key: PORT
9
+ value: 9000
10
+ plan: free
requirements.txt ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==24.1.0
2
+ annotated-types==0.7.0
3
+ anyio==4.9.0
4
+ attrs==25.3.0
5
+ beautifulsoup4==4.13.3
6
+ bs4==0.0.2
7
+ cachetools==5.5.2
8
+ certifi==2025.1.31
9
+ charset-normalizer==3.4.1
10
+ click==8.1.8
11
+ faiss-cpu==1.10.0
12
+ fastapi==0.115.12
13
+ filelock==3.18.0
14
+ firecrawl-py==1.15.0
15
+ fsspec==2025.3.2
16
+ google==3.0.0
17
+ google-ai-generativelanguage==0.6.15
18
+ google-api-core==2.24.2
19
+ google-api-python-client==2.166.0
20
+ google-auth==2.38.0
21
+ google-auth-httplib2==0.2.0
22
+ google-genai==1.9.0
23
+ google-generativeai==0.8.4
24
+ google.py==0.1.1
25
+ googleapis-common-protos==1.69.2
26
+ greenlet==3.1.1
27
+ grpcio==1.71.0
28
+ grpcio-status==1.71.0
29
+ h11==0.14.0
30
+ httpcore==1.0.7
31
+ httplib2==0.22.0
32
+ httpx==0.28.1
33
+ huggingface-hub==0.30.1
34
+ idna==3.10
35
+ Jinja2==3.1.6
36
+ joblib==1.4.2
37
+ jsonpatch==1.33
38
+ jsonpointer==3.0.0
39
+ langchain==0.3.23
40
+ langchain-core==0.3.51
41
+ langchain-text-splitters==0.3.8
42
+ langsmith==0.3.24
43
+ MarkupSafe==3.0.2
44
+ mpmath==1.3.0
45
+ nest-asyncio==1.6.0
46
+ networkx==3.4.2
47
+ numpy==2.2.4
48
+ orjson==3.10.16
49
+ outcome==1.3.0.post0
50
+ packaging==24.2
51
+ pandas==2.2.3
52
+ pillow==11.1.0
53
+ playwright==1.51.0
54
+ proto-plus==1.26.1
55
+ protobuf==5.29.4
56
+ pyasn1==0.6.1
57
+ pyasn1_modules==0.4.2
58
+ pydantic==2.11.2
59
+ pydantic_core==2.33.1
60
+ pyee==12.1.1
61
+ pyparsing==3.2.3
62
+ PySocks==1.7.1
63
+ python-dateutil==2.9.0.post0
64
+ python-dotenv==1.1.0
65
+ pytz==2025.2
66
+ PyYAML==6.0.2
67
+ regex==2024.11.6
68
+ requests==2.32.3
69
+ requests-toolbelt==1.0.0
70
+ rsa==4.9
71
+ safetensors==0.5.3
72
+ scikit-learn==1.6.1
73
+ scipy==1.15.2
74
+ selenium==4.31.0
75
+ sentence-transformers==4.0.2
76
+ setuptools==78.1.0
77
+ six==1.17.0
78
+ sniffio==1.3.1
79
+ sortedcontainers==2.4.0
80
+ soupsieve==2.6
81
+ SQLAlchemy==2.0.40
82
+ starlette==0.46.1
83
+ sympy==1.13.1
84
+ tenacity==9.1.2
85
+ threadpool==1.3.2
86
+ threadpoolctl==3.6.0
87
+ tokenizers==0.21.1
88
+ torch==2.6.0
89
+ tqdm==4.67.1
90
+ transformers==4.50.3
91
+ trio==0.29.0
92
+ trio-websocket==0.12.2
93
+ typing-inspection==0.4.0
94
+ typing_extensions==4.13.1
95
+ tzdata==2025.2
96
+ uritemplate==4.1.1
97
+ urllib3==2.3.0
98
+ uvicorn==0.34.0
99
+ webdriver-manager==4.0.2
100
+ websocket-client==1.8.0
101
+ websockets==15.0.1
102
+ wsproto==1.2.0
103
+ zstandard==0.23.0
shl_combined_assessments.csv ADDED
The diff for this file is too large to render. See raw diff
 
shl_vector_index.faiss ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:56ece2437be1d6a57dab2687c453c864f3c7ac5445a73e334f653e25d2a6e0cd
3
+ size 795693