Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create utility method that uses ai model to suggest imrpoved description #31

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 100 additions & 75 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,171 +1,196 @@
'''
"""
Flask Application
'''
"""

from flask import Flask, jsonify, request
from models import Experience, Education, Skill, User
from utils import check_phone_number, correct_spelling
from utils import get_suggestion, check_phone_number, correct_spelling


app = Flask(__name__)

data = {
"user": [
User("Jackie Stewart",
"+4478322678",
"jack@resume.com")
],
"user": [User("Jackie Stewart", "+4478322678", "jack@resume.com")],
"experience": [
Experience("Software Developer",
"A Cool Company",
"October 2022",
"Present",
"Writing Python Code",
"example-logo.png"),
Experience("Intern",
"A Nice Company",
"October 2021",
"December 2021",
"Writing Scripts",
"example-logo.png")
Experience(
"Software Developer",
"A Cool Company",
"October 2022",
"Present",
"Writing Python Code",
"example-logo.png",
),
Experience(
"Intern",
"A Nice Company",
"October 2021",
"December 2021",
"Writing Scripts",
"example-logo.png",
),
],
"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",
)
],
"skill": [
Skill("Python",
"1-2 Years",
"example-logo.png")
]
"skill": [Skill("Python", "1-2 Years", "example-logo.png")],
}


@app.route('/test')
@app.route("/test")
def hello_world():
'''
"""
Returns a JSON test message
'''
"""
return jsonify({"message": "Hello, World!"})

@app.route('/resume/user', methods=['GET', 'POST', 'PUT'])

@app.route("/resume/user", methods=["GET", "POST", "PUT"])
def user():
'''
"""
Handles User information
'''
"""

# defining sub function to reduce number of returns
def get_users():
return jsonify([user.__dict__ for user in data['user']]), 200
return jsonify([user.__dict__ for user in data["user"]]), 200

def add_user(body):
# retrieve user's information.
name = body['name']
phone_number = body['phone_number']
email = body['email_address']
name = body["name"]
phone_number = body["phone_number"]
email = body["email_address"]
# store the new user information.
if not check_phone_number(phone_number):
return jsonify({"error": "Incorrect phone number !"}), 400
new_user = User(name, phone_number, email)
data['user'].append(new_user)
data["user"].append(new_user)
return jsonify(new_user.__dict__), 201

# edit the user information.
def edit_user(body):
name = body['name']
phone_number = body['phone_number']
email = body['email_address']
for i, user_ in enumerate(data['user']):
name = body["name"]
phone_number = body["phone_number"]
email = body["email_address"]
for i, user_ in enumerate(data["user"]):
if user_.email_address == email:
if not check_phone_number(phone_number):
return jsonify({"error": "Incorrect phone number !"}), 400
data['user'][i] = User(name, phone_number, email)
return jsonify(data['user'][i].__dict__), 200
data["user"][i] = User(name, phone_number, email)
return jsonify(data["user"][i].__dict__), 200
return jsonify({"error": "User not found !"}), 404

if request.method == 'GET':
if request.method == "GET":
return get_users()
if request.method == 'POST':
if request.method == "POST":
body = request.get_json()
return add_user(body)
if request.method == 'PUT':
if request.method == "PUT":
body = request.get_json()
return edit_user(body)
return jsonify({"error": "Unsupported request method !"}), 405

@app.route('/resume/experience', methods=['GET', 'POST'])

@app.route("/resume/experience", methods=["GET", "POST"])
def experience():
'''
"""
Handle experience requests
'''
if request.method == 'GET':
return jsonify({"experience": [exp.__dict__ for exp in data["experience"]]})
"""

if request.method == 'POST':
if request.method == "GET":
return jsonify(
{"experience": [exp.__dict__ for exp in data["experience"]]})

if request.method == "POST":
new_experience = request.json
experience_instance = Experience(
new_experience["title"],
new_experience["company"],
new_experience["start_date"],
new_experience["end_date"],
new_experience["description"],
new_experience["logo"]
new_experience["logo"],
)
data["experience"].append(experience_instance)
return jsonify({"id": len(data["experience"]) - 1})

return jsonify({})

@app.route('/resume/education', methods=['GET', 'POST'])

@app.route("/resume/education", methods=["GET", "POST"])
def education():
'''
"""
Handles education requests
'''
if request.method == 'GET':
return jsonify({"education": [edu.__dict__ for edu in data["education"]]})
"""
if request.method == "GET":
return jsonify(
{"education": [edu.__dict__ for edu in data["education"]]})

if request.method == 'POST':
if request.method == "POST":
new_education = request.json
education_instance = Education(
new_education["course"],
new_education["school"],
new_education["start_date"],
new_education["end_date"],
new_education["grade"],
new_education["logo"]
new_education["logo"],
)
data["education"].append(education_instance)
return jsonify({"id": len(data["education"]) - 1})

return jsonify({})


@app.route('/resume/skill', methods=['GET', 'POST'])
@app.route("/resume/skill", methods=["GET", "POST"])
def skill():
'''
"""
Handles Skill requests
'''
if request.method == 'GET':
"""

if request.method == "GET":
return jsonify({"skills": [skill.__dict__ for skill in data["skill"]]})

if request.method == 'POST':
if request.method == "POST":
new_skill = request.json
skill_instance = Skill(new_skill["name"], new_skill["proficiency"], new_skill["logo"])
skill_instance = Skill(
new_skill["name"], new_skill["proficiency"], new_skill["logo"]
)
data["skill"].append(skill_instance)
return jsonify({"id": len(data["skill"]) - 1})

return jsonify({})

@app.route('/resume/spellcheck', methods=['POST'])

@app.route("/resume/spellcheck", methods=["POST"])
def spellcheck():
'''
"""
Corrects the spelling of a text
'''
"""
body = request.get_json()
try:
text = body['text']
text = body["text"]
corrected_text = correct_spelling(text)

return jsonify({"before": text, "after": corrected_text}), 200
except KeyError:
return jsonify({"error": "Missing text parameter"}), 400


@app.route("/suggestion", methods=["POST"])
def get_description_suggestion():
"""
Handles suggestion requests
"""
description = request.json.get("description")
description_type = request.json.get("type")
if not description or not description_type:
return jsonify({"error": "Description and type are required"}), 400
suggestion = get_suggestion(description, description_type)
return jsonify({"suggestion": suggestion})
5 changes: 4 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
flask
pytest
pylint
pyspellchecker
google-generativeai
python-dotenv
pyspellchecker

38 changes: 38 additions & 0 deletions test_pytest.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
'''
Tests in Pytest
'''
from unittest.mock import patch
import pytest
from app import app



def test_client():
'''
Makes a request and checks the message received is the same
Expand Down Expand Up @@ -136,3 +139,38 @@ def test_correct_spelling(text, expected):
response = app.test_client().post('/resume/spellcheck', json={'text': text})
assert response.status_code == 200
assert response.json['after'] == expected

# testcases for ai suggested imrpvoed descriptions
@patch('app.get_suggestion')
def test_get_description_suggestion(mock_get_suggestion):
'''
Test the /suggestion route with valid inputs
'''
mock_get_suggestion.return_value = "Improved description"

response = app.test_client().post('/suggestion', json={
'description': 'This is a sample description.',
'type': 'experience'
})

assert response.status_code == 200
assert response.json['suggestion'] == 'Improved description'


def test_get_description_suggestion_missing_fields():
'''
Test the /suggestion route with missing fields
'''
# Missing 'type'
response = app.test_client().post('/suggestion', json={
'description': 'This is a sample description.'
})
assert response.status_code == 400
assert response.json['error'] == 'Description and type are required'

# Missing 'description'
response = app.test_client().post('/suggestion', json={
'type': 'experience'
})
assert response.status_code == 400
assert response.json['error'] == 'Description and type are required'
44 changes: 38 additions & 6 deletions utils.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
""" Util functions for the Flask App."""
"""
Utility Methods File
"""

import os
import re
from spellchecker import SpellChecker
import google.generativeai as genai
from dotenv import load_dotenv


load_dotenv()


GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
genai.configure(api_key=GOOGLE_API_KEY)


def get_suggestion(description, description_type):
"""
give suggestions for description section using gemini (free alternative to openai's chatgpt api)
"""
prompt = ""
if description_type == "education":
prompt = f"Improve the following education \
experience description for resume: {description}"
elif description_type == "experience":
prompt = f"Improve the following professional \
experience description for resume: {description}"

model = genai.GenerativeModel("gemini-pro")
response = model.generate_content(prompt)
return response.text


def check_phone_number(phone_number):
""" Checks if the phone number is valid and follows
the international country code
"""Checks if the phone number is valid and follows
the international country code
"""
regex = re.compile(r'^\+\d{1,3}\d{1,14}$')
regex = re.compile(r"^\+\d{1,3}\d{1,14}$")
return bool(regex.match(phone_number))


def correct_spelling(text: str):
""" Corrects the spelling of a text"""
"""Corrects the spelling of a text"""

spell_checker = SpellChecker()
word_pattern = r'\w+|[^\w\s]'
word_pattern = r"\w+|[^\w\s]"

misspelled = spell_checker.unknown(re.findall(word_pattern, text))
corrected_text = text
Expand Down
Loading