Do0rMaMu commited on
Commit
d2ebccb
·
verified ·
1 Parent(s): 18829ed

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +215 -214
main.py CHANGED
@@ -1,214 +1,215 @@
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)
 
 
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
+ from fastapi.middleware.cors import CORSMiddleware
128
+ app.add_middleware(
129
+ CORSMiddleware,
130
+ allow_origins=["*"], # Allows all origins
131
+ allow_credentials=True,
132
+ allow_methods=["*"], # Allows all methods
133
+ allow_headers=["*"] # Allows all headers
134
+ )
135
+
136
+ @app.on_event("startup")
137
+ async def startup():
138
+ await database.connect()
139
+
140
+ @app.on_event("shutdown")
141
+ async def shutdown():
142
+ await database.disconnect()
143
+
144
+ @app.post("/query-jobs/")
145
+ async def query_jobs(query: JobQuery):
146
+ start_time = time.time() # Start timing
147
+
148
+ # Fetch and match skills
149
+ all_skills = await database.fetch_all(select(skills.c.skillId, skills.c.skillName))
150
+ skills_dict = {skill['skillName']: skill['skillId'] for skill in all_skills}
151
+ matching_skills = process.extract(query.semanticSearchString, skills_dict.keys(), limit=10)
152
+ matching_skill_ids = [skills_dict[skill[0]] for skill in matching_skills if skill[1] > 70]
153
+
154
+ if not matching_skill_ids:
155
+ return {"message": "No skills matched your query.", "query": query.semanticSearchString}
156
+
157
+ user_skill_query = select(MercorUserSkills.c.userId).where(MercorUserSkills.c.skillId.in_(matching_skill_ids)).distinct()
158
+ user_ids = await database.fetch_all(user_skill_query)
159
+ user_ids = [user['userId'] for user in user_ids]
160
+
161
+ if not user_ids:
162
+ return {"message": "No users found with the matching skills."}
163
+
164
+ user_query = (
165
+ select(jobs)
166
+ .where(jobs.c.userId.in_(user_ids), jobs.c.fullTimeSalary <= int(query.budget))
167
+ .order_by(jobs.c.fullTimeSalary.desc()) # Sorting by fullTimeSalary descending
168
+ .limit(4) # Limiting to 4 results
169
+ )
170
+ users_with_skills = await database.fetch_all(user_query)
171
+
172
+ result = []
173
+ for user in users_with_skills:
174
+ user_skills_query = select(skills.c.skillName).join(MercorUserSkills, skills.c.skillId == MercorUserSkills.c.skillId).where(MercorUserSkills.c.userId == user['userId'])
175
+ user_skills = await database.fetch_all(user_skills_query)
176
+ user_skills_list = [skill['skillName'] for skill in user_skills]
177
+
178
+ # Fetch resume ID for user
179
+ resume_query = select(UserResume.c.resumeId).where(UserResume.c.userId == user['userId'])
180
+ resume_id = await database.fetch_one(resume_query)
181
+
182
+ # Fetch and process work experience
183
+ experience_query = select(WorkExperience).where(WorkExperience.c.resumeId == resume_id['resumeId'])
184
+ experiences = await database.fetch_all(experience_query)
185
+ companies = set()
186
+ total_experience = 0
187
+
188
+ for exp in experiences:
189
+ companies.add(exp['company'])
190
+ # Calculate duration
191
+ start_date = datetime.strptime(exp['startDate'], '%Y') if exp['startDate'] else None
192
+ end_date = datetime.strptime(exp['endDate'], '%Y') if exp['endDate'] else datetime.now()
193
+ if start_date:
194
+ duration_years = (end_date.year - start_date.year)
195
+ total_experience += duration_years
196
+
197
+ experiences_list = [{'company': exp['company'], 'role': exp['role'], 'startDate': exp['startDate'], 'endDate': exp['endDate']} for exp in experiences]
198
+
199
+ result.append({
200
+ "user_id": user['userId'],
201
+ "name": user['name'],
202
+ "email": user['email'],
203
+ "skills": user_skills_list,
204
+ "full_time_salary": user['fullTimeSalary'],
205
+ "companies": list(companies),
206
+ "total_experience_years": total_experience
207
+ })
208
+
209
+ execution_time = time.time() - start_time # Calculate execution time
210
+
211
+ return {"users": result, "execution_time": execution_time}
212
+
213
+ if __name__ == "__main__":
214
+ import uvicorn
215
+ uvicorn.run(app, host="0.0.0.0", port=8000)