Skip to content

Commit

Permalink
Merge branch 'main' into issue17
Browse files Browse the repository at this point in the history
  • Loading branch information
iyilmaz24 committed Feb 7, 2025
2 parents 52445de + 019780c commit 7caaefc
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 49 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
103 changes: 59 additions & 44 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 Down Expand Up @@ -57,35 +58,33 @@ 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:
except (ValueError, TypeError, KeyError) 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


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


@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"])
@app.route("/resume/education/<int:index>", methods=["GET"])
def education(index=None):
Expand All @@ -100,12 +99,36 @@ def education(index=None):
return jsonify(data["education"][index])
except IndexError:
return jsonify({"error": "Index out of range"})

if request.method == 'POST':
json_data = request.json
try:
validated_data = validate_education(json_data)
return jsonify(validated_data)
except ValueError as e:
return jsonify({"error": str(e)}), 400

return jsonify({})

if request.method == "POST":
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)

return jsonify({})
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"])
def skill():
Expand All @@ -118,25 +141,17 @@ def skill():
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"]

new_skill = Skill(name, proficiency, logo)
validated_data = validate_skill(json_data)

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

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

return jsonify({})

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)
66 changes: 62 additions & 4 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 @@ -70,8 +70,66 @@ 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"

65 changes: 65 additions & 0 deletions validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from models import Experience, Education, Skill

def validate_experience(json_data: dict):
'''
Validates the experience
'''
if 'spell_check' in json_data:
del json_data['spell_check']
try:
return Experience(**json_data)
except Exception as e:
raise ValueError(f"Invalid experience format: {e}")

def validate_education(json_data: dict):
'''
Validates the education
'''
if 'spell_check' in json_data:
del json_data['spell_check']
try:
return Education(**json_data)
except Exception as e:
raise ValueError(f"Invalid education format: {e}")

def validate_skill(json_data: dict):
'''
Validates the skill
'''
if 'spell_check' in json_data:
del json_data['spell_check']
try:
return Skill(**json_data)
except Exception as e:
raise ValueError(f"Invalid skill format: {e}")


data = {
"experience": {
"title": "Software Developer",
"company": "A Cooler Company",
"start_date": "October 2022",
"end_date": "Present",
"description": "Writing JavaScript Code",
"logo": "example-logo.png",
"spell_check": True
},
"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"
}
}

print(validate_experience(data['experience']))
print(validate_education(data['education']))
print(validate_skill(data['skill']))

0 comments on commit 7caaefc

Please sign in to comment.