|
|
"""CV Screening Agent Module |
|
|
|
|
|
Run as follows: |
|
|
>>> docker compose up --build |
|
|
>>> docker compose run --rm candidates_db_init python -m src.agents.cv_screening.screener |
|
|
""" |
|
|
import json |
|
|
from langchain_openai import ChatOpenAI |
|
|
from langchain.messages import SystemMessage, HumanMessage |
|
|
|
|
|
from dotenv import load_dotenv |
|
|
from src.backend.agents.cv_screening.schemas.output_schema import CVScreeningOutput |
|
|
from src.backend.agents.cv_screening.utils import read_file |
|
|
from src.backend.database.candidates import write_cv_results_to_db |
|
|
from src.backend.prompts import get_prompt |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
SYSTEM_PROMPT = get_prompt( |
|
|
template_name="CV_Screener", |
|
|
latest_version=True |
|
|
) |
|
|
|
|
|
|
|
|
def screen_cv(cv_text: str, jd_text: str) -> CVScreeningOutput: |
|
|
""" |
|
|
Evaluate a candidate's CV against a job description using an LLM. |
|
|
|
|
|
Args: |
|
|
cv_text (str): The text content of the candidate's CV. |
|
|
jd_text (str): The text content of the Job Description. |
|
|
|
|
|
Returns: |
|
|
CVScreeningOutput: The structured screening result. |
|
|
Makes model write feedback before scoring, leading to better calibration |
|
|
and genuine reasoning that leads to more balanced scores. |
|
|
|
|
|
**NOTE**: |
|
|
>>> The model generates feedback first (Chain-of-Thought) |
|
|
>>> to ensure calibrated scores. |
|
|
|
|
|
""" |
|
|
llm = ( |
|
|
ChatOpenAI( |
|
|
model="gpt-4o-mini", |
|
|
temperature=0, |
|
|
max_tokens=1500, |
|
|
) |
|
|
.with_structured_output(CVScreeningOutput) |
|
|
) |
|
|
|
|
|
messages = [ |
|
|
|
|
|
SystemMessage( |
|
|
content=SYSTEM_PROMPT |
|
|
), |
|
|
|
|
|
HumanMessage( |
|
|
content=( |
|
|
f"Job Description:\n{jd_text}\n\n" |
|
|
f"Candidate CV:\n{cv_text}\n" |
|
|
) |
|
|
), |
|
|
] |
|
|
|
|
|
return llm.invoke(messages) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
from pathlib import Path |
|
|
|
|
|
BASE_PATH = Path(__file__).resolve().parents[2] / "database" |
|
|
|
|
|
cv_text = read_file(BASE_PATH / "cvs/parsed/c762271c-af8f-49db-acbb-e37e5f0f0f98_SWefers_CV-sections.txt") |
|
|
jd_text = read_file(BASE_PATH / "cvs/job_postings/ai_engineer.txt") |
|
|
|
|
|
|
|
|
result = screen_cv(cv_text, jd_text) |
|
|
print(json.dumps(result.model_dump(), indent=2)) |
|
|
|
|
|
|
|
|
write_cv_results_to_db( |
|
|
candidate_email="sebastianwefersnz@gmail.com", |
|
|
result=result, |
|
|
job_title="AI Engineer" |
|
|
) |