selecao-dev-api / app.py
JeffersonCorreiax's picture
Update app.py
dd8445d verified
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import PlainTextResponse
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi import Request
import joblib
import PyPDF2
import re
import logging
import tempfile
import os
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
logging.basicConfig(level=logging.INFO)
try:
model = joblib.load("react_classifier.joblib")
except Exception as e:
logging.error(f"Erro ao carregar o modelo: {e}")
raise
def clean_text(text):
text = text.lower()
text = re.sub(r'[^\w\s]', ' ', text)
text = re.sub(r'\s+', ' ', text)
return text.strip()
def extract_text_from_pdf(file_path):
text = ""
try:
with open(file_path, 'rb') as f:
reader = PyPDF2.PdfReader(f)
for page in reader.pages:
page_text = page.extract_text()
if page_text:
text += page_text + "\n"
except Exception as e:
raise Exception(f"Erro ao extrair texto do PDF: {e}")
return text
def avaliar_candidato(
anosEstudoTecnologia: int,
tempoDesenvolvedor: int,
tempoExperiencia: int,
nivelIngles: int,
graduacao: int
) -> dict:
score_estudo = anosEstudoTecnologia / 6
score_desenvolv = tempoDesenvolvedor / 6
score_experiencia = tempoExperiencia / 6
score_ingles = nivelIngles / 4
score_graduacao = graduacao / 7
peso_estudo = 0.15
peso_desenvolv = 0.2
peso_experiencia = 0.3
peso_ingles = 0.25
peso_graduacao = 0.1
score_final = (
score_estudo * peso_estudo +
score_desenvolv * peso_desenvolv +
score_experiencia * peso_experiencia +
score_ingles * peso_ingles +
score_graduacao * peso_graduacao
)
score_percentual = round(score_final * 100, 2)
aprovado = score_percentual >= 70.0
return {
"score": score_percentual,
"aprovado": aprovado
}
@app.post("/classificar")
async def classify_resume(file: UploadFile = File(...)):
try:
suffix = os.path.splitext(file.filename)[-1]
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp:
temp.write(await file.read())
temp_path = temp.name
raw_text = extract_text_from_pdf(temp_path)
cleaned = clean_text(raw_text)
proba = model.predict_proba([cleaned])[0]
prediction = model.predict([cleaned])[0]
result = {
"classificacao": "React Developer" if prediction == 1 else "Outra Área",
"probabilidade": f"{proba[1]*100:.2f}%",
"trecho_texto": cleaned[:500] + "..." if len(cleaned) > 500 else cleaned
}
return JSONResponse(content=result)
except Exception as e:
logging.error(f"Erro no processamento: {e}")
raise HTTPException(status_code=500, detail=str(e))
finally:
if 'temp_path' in locals() and os.path.exists(temp_path):
os.remove(temp_path)
@app.post("/avaliar")
async def avaliar_formulario(request: Request):
try:
data = await request.json()
resultado = avaliar_candidato(
anosEstudoTecnologia=int(data.get("anosEstudoTecnologia", 0)),
tempoDesenvolvedor=int(data.get("tempoDesenvolvedor", 0)),
tempoExperiencia=int(data.get("tempoExperiencia", 0)),
nivelIngles=int(data.get("nivelIngles", 0)),
graduacao=int(data.get("graduacao", 0))
)
return JSONResponse(
status_code=200,
content={
"avaliacao": "Aprovado" if resultado["aprovado"] else "Reprovado",
"score": resultado["score"]
}
)
except Exception as e:
logging.error(f"Erro na avaliação do formulário: {e}")
raise HTTPException(status_code=500, detail="Erro ao processar os dados.")
@app.get("/", response_class=PlainTextResponse)
async def root():
return (
"Esta API possui duas rotas POST:\n"
" /classificar → espera um arquivo PDF de currículo\n"
" /avaliar → espera um JSON como este:\n"
'{\n'
' "anosEstudoTecnologia": 6,\n'
' "tempoDesenvolvedor": 6,\n'
' "tempoExperiencia": 6,\n'
' "nivelIngles": 3,\n'
' "graduacao": 7\n'
'}\n'
)