Spaces:
Sleeping
Sleeping
| # %%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": {} | |
| } |