Skip to content

Commit

Permalink
Merge branch 'main' into delete_existing_skill
Browse files Browse the repository at this point in the history
  • Loading branch information
FortunateOmonuwa authored Feb 10, 2025
2 parents 7cdf0ba + 3d10db0 commit cda6eb8
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 68 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
.venv
.pytest_cache/
__pycache__
.vscode
.vscode
.env
116 changes: 77 additions & 39 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
'''

from flask import Flask, jsonify, request

from models import Education, Experience, Skill
from models import Experience, Education, Skill
from gpt_connection import get_improvement
from validation import validate_experience, validate_education, validate_skill
from spell_check import spell_check

app = Flask(__name__)

Expand All @@ -20,14 +22,13 @@
)
],
"education": [
Education(
"Computer Science",
"University of Tech",
"September 2019",
"July 2022",
"80%",
"example-logo.png",
)
Education("Computer Science",
"University of Tech",
"September 2019",
"July 2022",
"80%",
"example-logo.png",
"I was head of the debate team at university")
],
"skill": [Skill("Python", "1-2 Years", "example-logo.png")],
}
Expand All @@ -42,7 +43,7 @@ def hello_world():


@app.route("/resume/experience", methods=["GET", "POST"])
@app.route("/resume/experience/<int:index>", methods=["GET"])
@app.route("/resume/experience/<int:index>", methods=["GET", "DELETE"])
def experience(index=None):
'''
Handle experience requests
Expand All @@ -57,34 +58,31 @@ def experience(index=None):
return jsonify({"error": "Experience not found"}), 404
return jsonify(data["experience"]), 200

if request.method == "POST":
if request.method == 'POST':
json_data = request.json
try:
new_experience = request.get_json()
if not new_experience:
return jsonify({"error": "No data provided"}), 400
# validate required fields
required_fields = [
"title",
"company",
"start_date",
"end_date",
"description",
"logo",
]
if not all(field in new_experience for field in required_fields):
return jsonify({"error": "Missing required fields"}), 400

experience_obj = Experience(**new_experience)
data["experience"].append(experience_obj)
validated_data = validate_experience(json_data)

data["experience"].append(validated_data)
return jsonify({"id": len(data["experience"]) - 1}), 201
except TypeError as e:
return jsonify({"error": f"Invalid data format: {str(e)}"}), 400
except Exception as e:
return jsonify({"error": f"Internal error: {str(e)}"}), 500

if request.method == "DELETE":
try:
if index is None or index < 0 or index >= len(data["experience"]):
return jsonify({"message": "Resource doesn't exist"}), 404
else:
data['experience'].pop(index)
return jsonify({"message": "Experience Successfully Deleted"}), 200
except Exception as e:
return jsonify({"error": f"An error occurred: {str(e)}"}), 500

return jsonify({"error": "Method not allowed"}), 405


@app.route('/resume/experience/<int:exp_id>', methods=['DELETE'])
def delete_experience(exp_id):
try:
Expand All @@ -97,19 +95,64 @@ def delete_experience(exp_id):
return jsonify({"error": f"An error occurred: {str(e)}"}), 500



@app.route('/resume/spell_check', methods=['POST'])
def spell_check():
json_data = request.json
if json_data.get('description') and isinstance(json_data.get('description'), str):
json_data['description'] = spell_check(json_data['description'])
return jsonify({
"before": request.json,
"after": json_data
})


@app.route("/resume/education", methods=["GET", "POST"])
def education():
@app.route("/resume/education/<int:edu_id>", methods=["GET", "DELETE"])
def education(edu_id=None):
'''
Handles education requests
GET: Returns all educations (unimplemented here)
POST: Creates a new education (unimplemented here)
DELETE: Deletes an education by index
'''
if request.method == "GET":
return jsonify({})

if request.method == "POST":
return jsonify({})

if request.method == "DELETE":
try:
if edu_id is None or edu_id < 0 or edu_id >= len(data["education"]):
return jsonify({"message": "Resource doesn't exist"}), 404
else:
del data["education"][edu_id]
return jsonify({"message": "Education Successfully Deleted"}), 200
except Exception as e:
return jsonify({"error": f"An error occurred: {str(e)}"}), 500

return jsonify({})

@app.route('/resume/reword_description', methods=['GET'])
def reword_description():
'''
Rewords the description using GPT
'''
model = None
try:
model = Experience(**request.json)
except:
model = Education(**request.json)

if model is None:
return jsonify({"error": "Invalid request"}), 400

response = get_improvement(model)
if response is None:
return jsonify({"error": "Failed to get improvement"}), 500

return jsonify({"response": response})

@app.route("/resume/skill", methods=["GET", "POST"])
@app.route('/resume/skill/<int:skill_id>', methods=['DELETE'])
Expand All @@ -123,20 +166,14 @@ def skill(skill_id = None):
if request.method == 'POST':
json_data = request.json
try:
# extract the data from the request
name = json_data["name"]
proficiency = json_data["proficiency"]
logo = json_data["logo"]
validated_data = validate_skill(json_data)

new_skill = Skill(name, proficiency, logo)

data["skill"].append(new_skill)
data["skill"].append(validated_data)

# return ID of new skill
return jsonify(
{"id": len(data["skill"]) - 1}
), 201

except KeyError:
return jsonify({"error": "Invalid request"}), 400

Expand All @@ -149,7 +186,8 @@ def skill(skill_id = None):
else:
del data['skill'][skill_id]
return jsonify({"message": "Skill Successfully Deleted"}), 200

except (ValueError, TypeError, KeyError) as e:
return jsonify({"error": f"Invalid request: {str(e)}"}), 400
except Exception as e:
return jsonify({"error": f"An error occurred: {str(e)}"}), 500

Expand Down
31 changes: 31 additions & 0 deletions gpt_connection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@


from openai import OpenAI
import os
from dotenv import load_dotenv
from models import Experience, Education
load_dotenv()

client = OpenAI(
api_key=os.getenv("OPENAI_API_KEY")
)

def get_improvement(model : Experience | Education):
prompt = f"Improve the following description for the {model.__class__.__name__}: {model.description}"

response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant that improves descriptions for resumes."},
{"role": "assistant", "content": "Here is the improved description:"},
{"role": "system", "content": f"Consider the following information about the {model.__class__.__name__}: {model.model_dump_json()}"},
{"role": "user", "content": prompt},
]
)
try:
return response.choices[0].message.content
except:
return None



13 changes: 13 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
'''

from dataclasses import dataclass
import json


@dataclass
Expand All @@ -19,6 +20,11 @@ class Experience:
description: str
logo: str

def model_dump_json(self):
'''
Dumps the class into a JSON string
'''
return json.dumps(self, default=lambda o: o.__dict__)

@dataclass
class Education:
Expand All @@ -31,6 +37,13 @@ class Education:
end_date: str
grade: str
logo: str
description: str

def model_dump_json(self):
'''
Dumps the class into a JSON string
'''
return json.dumps(self, default=lambda o: o.__dict__)


@dataclass
Expand Down
13 changes: 13 additions & 0 deletions spell_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""
Module for spell checking functionality using autocorrect library.
"""

from autocorrect import Speller

spell = Speller(lang='en')

def spell_check(text):
'''
Spell checks the text
'''
return spell(text)
92 changes: 64 additions & 28 deletions test_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
'''
from app import app


def test_client():
'''
Makes a request and checks the message received is the same
Expand Down Expand Up @@ -35,33 +35,6 @@ def test_experience():



# def test_delete_experience():

# example_experience = {
# "title": "Mechanic",
# "company": "Decepticons .Ent",
# "start_date": "January 2020",
# "end_date": "Present",
# "description": "Hail Megatron",
# "logo" : "example-log.png"
# }
# response = app.test_client().post('/resume/experience', json= example_experience)
# assert response.status_code == 200

# get_all_experiences = app.test_client().get('/resume/experience')
# experience_id = len(get_all_experiences.json) - 1

# delete_response = app.test_client().delete(f'/resume/experience/{experience_id}')
# assert delete_response.status_code == 200
# deleted_experience = delete_response.json['deleted_experience']

# assert example_experience == deleted_experience

# get_exp = app.test_client().get('/resume/experience')
# for experience in get_exp.json:
# assert experience != deleted_experience


def test_education():
'''
Add a new education and then get all educations.
Expand Down Expand Up @@ -98,8 +71,71 @@ def test_skill():
item_id = app.test_client().post('/resume/skill',
json=example_skill).json['id']


response = app.test_client().get('/resume/skill')
assert response.json[item_id] == example_skill

response = app.test_client().get(f'/resume/skill/{item_id}')
assert response.json == example_skill


def test_model_validation():
'''
Test that the model validation returns a valid response
'''
data = {
"experience": {
"title": "Software Developer",
"company": "A Cooler Company",
"start_date": "October 2022",
"end_date": "Present",
"description": "Writing JavaScript Code",
"logo": "example-logo.png"
},
"education": {
"course": "Engineering",
"school": "NYU",
"start_date": "October 2022",
"end_date": "August 2024",
"grade": "86%",
"logo": "example-logo.png",
"description": "I was head of the debate team at university"
},
"skill": {
"name": "JavaScript",
"proficiency": "2-4 years",
"logo": "example-logo.png"
}
}
response_education = app.test_client().post('/resume/education',
json=data['education'])
response_experience = app.test_client().post('/resume/experience',
json=data['experience'])
response_skill = app.test_client().post('/resume/skill',
json=data['skill'])
assert response_education.status_code == 200
assert response_experience.status_code == 200
assert response_skill.status_code == 200

def test_spell_check():
'''
Test that the spell check endpoint returns a valid response
'''

example_education = {
"course": "Engineering",
"school": "NYU",
"start_date": "October 2022",
"end_date": "August 2024",
"grade": "86%",
"logo": "example-logo.png",
"description": "I was head of the debaite team at university",
"spell_check": True
}

response = app.test_client().post('/resume/education',
json=example_education)

assert response.json['description'] == "I was head of the debate team at university"


Loading

0 comments on commit cda6eb8

Please sign in to comment.