Do0rMaMu commited on
Commit
f708190
·
verified ·
1 Parent(s): b69db98

Upload 2 files

Browse files
Files changed (2) hide show
  1. __init__.py +0 -0
  2. main.py +214 -0
__init__.py ADDED
File without changes
main.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from pydantic import BaseModel
4
+ import databases
5
+ import sqlalchemy
6
+ from sqlalchemy.sql import select, and_
7
+ from fuzzywuzzy import process
8
+ import urllib.parse
9
+ import os
10
+ from dotenv import load_dotenv
11
+ import json
12
+ from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, DateTime, Boolean, Text, JSON
13
+ import time
14
+ from datetime import datetime
15
+
16
+ load_dotenv()
17
+
18
+ class JobQuery(BaseModel):
19
+ budget: str
20
+ experience: str
21
+ startDate: str
22
+ workType: str
23
+ semanticSearchString: str
24
+
25
+ username = urllib.parse.quote_plus('trial_user')
26
+ password = urllib.parse.quote_plus('trial_user_12345#')
27
+ host = '35.224.61.48'
28
+ port = '3306'
29
+ database_name = 'MERCOR_TRIAL_SCHEMA'
30
+
31
+ DATABASE_URL = f"mysql://{username}:{password}@{host}:{port}/{database_name}"
32
+ database = databases.Database(DATABASE_URL)
33
+
34
+ metadata = sqlalchemy.MetaData()
35
+
36
+ skills = sqlalchemy.Table(
37
+ "Skills",
38
+ metadata,
39
+ sqlalchemy.Column("skillId", sqlalchemy.String, primary_key=True),
40
+ sqlalchemy.Column("skillName", sqlalchemy.String),
41
+ sqlalchemy.Column("skillValue", sqlalchemy.String, unique=True),
42
+ )
43
+
44
+ jobs = sqlalchemy.Table(
45
+ "MercorUsers",
46
+ metadata,
47
+ sqlalchemy.Column("userId", sqlalchemy.String, primary_key=True),
48
+ sqlalchemy.Column("email", sqlalchemy.String, unique=True),
49
+ sqlalchemy.Column("name", sqlalchemy.String),
50
+ sqlalchemy.Column("phone", sqlalchemy.String),
51
+ sqlalchemy.Column("residence", JSON),
52
+ sqlalchemy.Column("profilePic", Text),
53
+ sqlalchemy.Column("createdAt", DateTime),
54
+ sqlalchemy.Column("lastLogin", DateTime),
55
+ sqlalchemy.Column("notes", Text),
56
+ sqlalchemy.Column("referralCode", sqlalchemy.String, unique=True),
57
+ sqlalchemy.Column("isGptEnabled", sqlalchemy.Boolean),
58
+ sqlalchemy.Column("preferredRole", sqlalchemy.String),
59
+ sqlalchemy.Column("fullTimeStatus", sqlalchemy.String),
60
+ sqlalchemy.Column("workAvailability", sqlalchemy.String),
61
+ sqlalchemy.Column("fullTimeSalaryCurrency", sqlalchemy.String),
62
+ sqlalchemy.Column("fullTimeSalary", sqlalchemy.String),
63
+ sqlalchemy.Column("partTimeSalaryCurrency", sqlalchemy.String),
64
+ sqlalchemy.Column("partTimeSalary", sqlalchemy.String),
65
+ sqlalchemy.Column("fullTime", sqlalchemy.Boolean),
66
+ sqlalchemy.Column("fullTimeAvailability", sqlalchemy.Integer),
67
+ sqlalchemy.Column("partTime", sqlalchemy.Boolean),
68
+ sqlalchemy.Column("partTimeAvailability", sqlalchemy.Integer),
69
+ sqlalchemy.Column("w8BenUrl", JSON),
70
+ sqlalchemy.Column("tosUrl", Text),
71
+ sqlalchemy.Column("policyUrls", JSON),
72
+ sqlalchemy.Column("isPreVetted", sqlalchemy.Boolean),
73
+ sqlalchemy.Column("isActive", sqlalchemy.Boolean),
74
+ sqlalchemy.Column("isComplete", sqlalchemy.Boolean),
75
+ sqlalchemy.Column("summary", Text),
76
+ sqlalchemy.Column("preVettedAt", DateTime)
77
+ )
78
+
79
+ MercorUserSkills = sqlalchemy.Table(
80
+ "MercorUserSkills",
81
+ metadata,
82
+ sqlalchemy.Column("userId", sqlalchemy.String, sqlalchemy.ForeignKey("MercorUsers.userId"), primary_key=True),
83
+ sqlalchemy.Column("skillId", sqlalchemy.String, sqlalchemy.ForeignKey("Skills.skillId"), primary_key=True),
84
+ sqlalchemy.Column("isPrimary", sqlalchemy.Boolean, default=False),
85
+ sqlalchemy.Column("order", Integer, default=0)
86
+ )
87
+
88
+ UserResume = sqlalchemy.Table(
89
+ "UserResume",
90
+ metadata,
91
+ sqlalchemy.Column("resumeId", sqlalchemy.String, primary_key=True),
92
+ sqlalchemy.Column("userId", sqlalchemy.String, sqlalchemy.ForeignKey("MercorUsers.userId")),
93
+ sqlalchemy.Column("url", Text),
94
+ sqlalchemy.Column("filename", String),
95
+ sqlalchemy.Column("createdAt", DateTime),
96
+ sqlalchemy.Column("updatedAt", DateTime),
97
+ sqlalchemy.Column("source", String),
98
+ sqlalchemy.Column("ocrText", Text),
99
+ sqlalchemy.Column("ocrEmail", String),
100
+ sqlalchemy.Column("ocrGithubUsername", String),
101
+ sqlalchemy.Column("resumeBasedQuestions", Text),
102
+ sqlalchemy.Column("isInvitedToInterview", Boolean),
103
+ sqlalchemy.Column("reminderTasksIds", JSON)
104
+ )
105
+
106
+ WorkExperience = sqlalchemy.Table(
107
+ "WorkExperience",
108
+ metadata,
109
+ sqlalchemy.Column("workExperienceId", sqlalchemy.String, primary_key=True),
110
+ sqlalchemy.Column("company", String),
111
+ sqlalchemy.Column("role", String),
112
+ sqlalchemy.Column("startDate", String),
113
+ sqlalchemy.Column("endDate", String),
114
+ sqlalchemy.Column("description", Text),
115
+ sqlalchemy.Column("locationCity", String),
116
+ sqlalchemy.Column("locationCountry", String),
117
+ sqlalchemy.Column("resumeId", String, sqlalchemy.ForeignKey("UserResume.resumeId"))
118
+ )
119
+
120
+ app = FastAPI()
121
+ # Configure CORS
122
+ origins = [
123
+ "http://localhost:3000", # Adjust this to the URL of your frontend
124
+ "http://127.0.0.1:3000"
125
+ ]
126
+
127
+ app.add_middleware(
128
+ CORSMiddleware,
129
+ allow_origins=origins,
130
+ allow_credentials=True,
131
+ allow_methods=["*"],
132
+ allow_headers=["*"],
133
+ )
134
+
135
+ @app.on_event("startup")
136
+ async def startup():
137
+ await database.connect()
138
+
139
+ @app.on_event("shutdown")
140
+ async def shutdown():
141
+ await database.disconnect()
142
+
143
+ @app.post("/query-jobs/")
144
+ async def query_jobs(query: JobQuery):
145
+ start_time = time.time() # Start timing
146
+
147
+ # Fetch and match skills
148
+ all_skills = await database.fetch_all(select(skills.c.skillId, skills.c.skillName))
149
+ skills_dict = {skill['skillName']: skill['skillId'] for skill in all_skills}
150
+ matching_skills = process.extract(query.semanticSearchString, skills_dict.keys(), limit=10)
151
+ matching_skill_ids = [skills_dict[skill[0]] for skill in matching_skills if skill[1] > 70]
152
+
153
+ if not matching_skill_ids:
154
+ return {"message": "No skills matched your query.", "query": query.semanticSearchString}
155
+
156
+ user_skill_query = select(MercorUserSkills.c.userId).where(MercorUserSkills.c.skillId.in_(matching_skill_ids)).distinct()
157
+ user_ids = await database.fetch_all(user_skill_query)
158
+ user_ids = [user['userId'] for user in user_ids]
159
+
160
+ if not user_ids:
161
+ return {"message": "No users found with the matching skills."}
162
+
163
+ user_query = (
164
+ select(jobs)
165
+ .where(jobs.c.userId.in_(user_ids), jobs.c.fullTimeSalary <= int(query.budget))
166
+ .order_by(jobs.c.fullTimeSalary.desc()) # Sorting by fullTimeSalary descending
167
+ .limit(4) # Limiting to 4 results
168
+ )
169
+ users_with_skills = await database.fetch_all(user_query)
170
+
171
+ result = []
172
+ for user in users_with_skills:
173
+ user_skills_query = select(skills.c.skillName).join(MercorUserSkills, skills.c.skillId == MercorUserSkills.c.skillId).where(MercorUserSkills.c.userId == user['userId'])
174
+ user_skills = await database.fetch_all(user_skills_query)
175
+ user_skills_list = [skill['skillName'] for skill in user_skills]
176
+
177
+ # Fetch resume ID for user
178
+ resume_query = select(UserResume.c.resumeId).where(UserResume.c.userId == user['userId'])
179
+ resume_id = await database.fetch_one(resume_query)
180
+
181
+ # Fetch and process work experience
182
+ experience_query = select(WorkExperience).where(WorkExperience.c.resumeId == resume_id['resumeId'])
183
+ experiences = await database.fetch_all(experience_query)
184
+ companies = set()
185
+ total_experience = 0
186
+
187
+ for exp in experiences:
188
+ companies.add(exp['company'])
189
+ # Calculate duration
190
+ start_date = datetime.strptime(exp['startDate'], '%Y') if exp['startDate'] else None
191
+ end_date = datetime.strptime(exp['endDate'], '%Y') if exp['endDate'] else datetime.now()
192
+ if start_date:
193
+ duration_years = (end_date.year - start_date.year)
194
+ total_experience += duration_years
195
+
196
+ experiences_list = [{'company': exp['company'], 'role': exp['role'], 'startDate': exp['startDate'], 'endDate': exp['endDate']} for exp in experiences]
197
+
198
+ result.append({
199
+ "user_id": user['userId'],
200
+ "name": user['name'],
201
+ "email": user['email'],
202
+ "skills": user_skills_list,
203
+ "full_time_salary": user['fullTimeSalary'],
204
+ "companies": list(companies),
205
+ "total_experience_years": total_experience
206
+ })
207
+
208
+ execution_time = time.time() - start_time # Calculate execution time
209
+
210
+ return {"users": result, "execution_time": execution_time}
211
+
212
+ if __name__ == "__main__":
213
+ import uvicorn
214
+ uvicorn.run(app, host="0.0.0.0", port=8000)