Mangesh223 commited on
Commit
b27339a
·
verified ·
1 Parent(s): c3c33a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -31
app.py CHANGED
@@ -30,52 +30,81 @@ def process_uploaded_file(file):
30
  raise ValueError("Unsupported file format. Please upload a PDF or Word document.")
31
 
32
  # Function to call Together API (unchanged except for timeout)
33
- def analyze_with_mistral(resume_text, job_description):
34
- TOGETHER_API_KEY = os.getenv("HUGGINGFACE_API_KEY")
35
- url = "https://api.together.xyz/v1/chat/completions"
36
-
37
- messages= [
38
- {
39
- "role": "system",
40
- "content": "You are an AI expert in ATS resume analysis. Your task is to analyze a resume against a job description for ATS compatibility and return the result in a structured JSON format. You must strictly follow the JSON schema provided and output ONLY JSON."
41
- },
42
- {
43
- "role": "user",
44
- "content": f"""Analyze the provided resume against the job description for ATS compatibility. Evaluate **keywords, formatting, skills, experience relevance, and education** based on ATS best practices.\n\nStrict Instructions:\n- **Return ONLY valid JSON** that matches the exact schema below. NO explanations, comments, or extra text.\n- **Ensure all fields are populated** (use empty lists or defaults if no suggestions apply).\n- **Use integer values (0-100)** for scores.\n- **Ensure 'Overall' is the rounded average** of all score fields.\n\n### **JSON Schema:**\n```json\n{{\n \"ATS Parameters\": {{\n \"Keywords\": {{\n \"Match\": <integer 0-100>,\n \"Recommendation\": [<list of 0-5 strings>]\n }},\n \"Formatting\": {{\n \"Match\": <integer 0-100>,\n \"Recommendation\": [<list of 0-5 strings>]\n }},\n \"Skills Match\": {{\n \"Match\": <integer 0-100>,\n \"Recommendation\": [<list of 0-5 strings>]\n }},\n \"Experience Relevance\": {{\n \"Match\": <integer 0-100>,\n \"Recommendation\": [<list of 0-5 strings>]\n }},\n \"Education\": {{\n \"Match\": <integer 0-100>,\n \"Recommendation\": [<list of 0-5 strings>]\n }}\n }},\n \"Score\": {{\n \"Keywords\": <integer 0-100>,\n \"Formatting\": <integer 0-100>,\n \"Skills Match\": <integer 0-100>,\n \"Experience Relevance\": <integer 0-100>,\n \"Education\": <integer 0-100>,\n \"Overall\": <integer 0-100, rounded average of all scores>\n }}\n}}\n```\n\n### **Processing Rules:**\n- **Score Calculation:** Base your evaluation on **ATS resume best practices** (keyword density, formatting simplicity, skills relevance, etc.).\n- **Recommendations:** Provide actionable suggestions to improve compatibility.\n- **Strict JSON Format:** No preamble, no explanations—return ONLY the completed JSON.\n\nResume:\n{resume_text}\n\nJob Description:\n{job_description}"""
45
-
46
- }
47
- ]
48
 
49
 
 
 
 
50
 
51
- payload = {
52
- "model": "mistralai/Mistral-7B-Instruct-v0.3",
53
- "messages": messages,
54
- "max_tokens": 1500,
55
- "temperature": 0.7,
56
- "top_p": 0.9,
57
- "response_format": {"type": "json_object"}
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  headers = {
61
- "Authorization": f"Bearer {TOGETHER_API_KEY}",
62
  "Content-Type": "application/json",
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
65
  try:
66
- response = requests.post(url, json=payload, headers=headers, timeout=30)
67
  response.raise_for_status()
 
 
68
  result = response.json()
69
- content = result.get("choices", [{}])[0].get("message", {}).get("content", "{}")
 
 
 
 
 
 
 
 
70
 
71
- # Parse and validate the JSON structure
72
- parsed = json.loads(content)
73
- if "ATS Parameters" not in parsed or "Score" not in parsed:
74
- raise ValueError("API returned invalid format")
75
  return parsed
76
 
77
  except Exception as e:
78
- return {"error": f"API request failed: {str(e)}"}
79
 
80
  # Main function (only added JSON validation)
81
  def analyze_resume(file, job_description):
 
30
  raise ValueError("Unsupported file format. Please upload a PDF or Word document.")
31
 
32
  # Function to call Together API (unchanged except for timeout)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
 
35
+ def analyze_with_huggingface(resume_text, job_description):
36
+ HF_API_KEY = os.getenv("HUGGINGFACE_API_KEY")
37
+ API_URL = "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.3"
38
 
39
+ # Truncate inputs to stay within token limits
40
+ resume_text = resume_text[:3000] # Limit resume to 3000 chars
41
+ job_description = job_description[:1000] # Limit JD to 1000 chars
42
+
43
+ prompt = f"""<s>[INST] <<SYS>>
44
+ You are an AI expert in ATS resume analysis. Return ONLY valid JSON matching this schema:
45
+ {{
46
+ "ATS Parameters": {{
47
+ "Keywords": {{"Match": <int>, "Recommendation": [<str>]}},
48
+ "Formatting": {{"Match": <int>, "Recommendation": [<str>]}},
49
+ "Skills Match": {{"Match": <int>, "Recommendation": [<str>]}},
50
+ "Experience Relevance": {{"Match": <int>, "Recommendation": [<str>]}},
51
+ "Education": {{"Match": <int>, "Recommendation": [<str>]}}
52
+ }},
53
+ "Score": {{
54
+ "Keywords": <int>,
55
+ "Formatting": <int>,
56
+ "Skills Match": <int>,
57
+ "Experience Relevance": <int>,
58
+ "Education": <int>,
59
+ "Overall": <int>
60
+ }}
61
+ }}
62
+ <</SYS>>
63
+
64
+ Analyze this resume against the job description for ATS compatibility:
65
+ Resume: {resume_text}
66
+ Job Description: {job_description}
67
+ Return ONLY the JSON output with no additional text or explanations.[/INST]"""
68
 
69
  headers = {
70
+ "Authorization": f"Bearer {HF_API_KEY}",
71
  "Content-Type": "application/json",
72
  }
73
 
74
+ payload = {
75
+ "inputs": prompt,
76
+ "parameters": {
77
+ "max_new_tokens": 800,
78
+ "temperature": 0.7,
79
+ "do_sample": True,
80
+ "return_full_text": False
81
+ }
82
+ }
83
+
84
  try:
85
+ response = requests.post(API_URL, headers=headers, json=payload, timeout=30)
86
  response.raise_for_status()
87
+
88
+ # Extract JSON from response
89
  result = response.json()
90
+ if isinstance(result, list):
91
+ content = result[0].get("generated_text", "{}")
92
+ else:
93
+ content = result.get("generated_text", "{}")
94
+
95
+ # Clean the output (sometimes models add extra text)
96
+ json_start = content.find('{')
97
+ json_end = content.rfind('}') + 1
98
+ json_str = content[json_start:json_end]
99
 
100
+ parsed = json.loads(json_str)
101
+ if not all(k in parsed for k in ["ATS Parameters", "Score"]):
102
+ raise ValueError("Invalid JSON structure")
103
+
104
  return parsed
105
 
106
  except Exception as e:
107
+ return {"error": f"Hugging Face API error: {str(e)}"}
108
 
109
  # Main function (only added JSON validation)
110
  def analyze_resume(file, job_description):