# %%writefile core/jd_processor.py import logging import json import os from openai import OpenAI, APIError from utils.prompts import JD_PROMPT logger = logging.getLogger(__name__) client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) def generate_jd_rubric(jd_text, max_retries=3): """Generate JD rubric with retry logic and better error handling.""" for attempt in range(max_retries): try: response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "You are an experienced HR Talent Manager AI assistant. Your specialty is analyzing job descriptions and creating structured hiring rubrics."}, {"role": "user", "content": JD_PROMPT.format(jd_text=jd_text)} ], temperature=0.2, response_format={"type": "json_object"} # New: Force JSON response ) content = response.choices[0].message.content logger.debug(f"LLM response (attempt {attempt+1}): {content[:200]}...") # Parse JSON jd_data = json.loads(content) # No need for find() with response_format # Validate structure required_keys = {"role_title", "must_have_skills", "nice_to_have_skills", "soft_skills", "minimum_years_experience", "recommended_weights"} if not all(key in jd_data for key in required_keys): raise ValueError("Missing required keys in response") return jd_data except json.JSONDecodeError as e: logger.warning(f"JSON decode failed (attempt {attempt+1}): {e}") if attempt == max_retries - 1: return get_empty_template() except APIError as e: logger.error(f"OpenAI API error: {e}") if attempt == max_retries - 1: return get_empty_template() except Exception as e: logger.error(f"Unexpected error: {e}") return get_empty_template() return get_empty_template() def get_empty_template(): """Return empty rubric template.""" return { "role_title": "", "must_have_skills": [], "nice_to_have_skills": [], "soft_skills": [], "minimum_years_experience": 0, "recommended_weights": {} }