from __future__ import annotations from typing import Dict, Any from services.llm import llm import json class ProfileAgent: """Parses raw CV text into a structured profile using LLM with fallback.""" def parse(self, cv_text: str) -> Dict[str, Any]: if not cv_text: return {} if not llm.enabled: return { "full_name": "Unknown", "email": "", "skills": [], "experiences": [], "links": {}, "languages": [], "certifications": [], "projects": [], "work_mode": "", "skill_proficiency": {}, } system = ( "You are a CV parser. Extract JSON with fields: full_name, email, phone, location, " "skills (list), experiences (list of {title, company, start_date, end_date, achievements, technologies}), " "education (list of {school, degree, field_of_study, start_date, end_date}), links (map with linkedin/portfolio/website if present). " "Also extract optional: languages (list of {language, level}), certifications (list of {name, issuer, year}), " "projects (list of {title, link, impact}), work_mode (remote/hybrid/on-site if evident), skill_proficiency (map skill->level). " "Keep values concise; do not invent information." ) user = f"Parse this CV into JSON with the schema above. Be strict JSON.\n\n{cv_text}" resp = llm.generate(system, user, max_tokens=900, agent="parser") try: return json.loads(resp) except Exception: return {"raw": resp}