Rauhan commited on
Commit
ea2094a
·
1 Parent(s): 0c7840b

UPDATE: antigravity test

Browse files
Files changed (3) hide show
  1. prompts.yaml +3 -3
  2. pyproject.toml +0 -14
  3. resumeRewritingService.py +36 -49
prompts.yaml CHANGED
@@ -2,7 +2,7 @@ prompt: |
2
  Act as a Senior Resume Writer and ATS Optimization Specialist with 20+ years of experience in recruitment.
3
 
4
  I am providing you with:
5
- 1. A Current Resume (text or details below).
6
  2. A Target Job Description (JD).
7
  3. The Current Date.
8
 
@@ -26,6 +26,7 @@ prompt: |
26
  - Email Rule: You MUST replace the candidate's email domain with @atomicmail.io.
27
  Example: john.doe@gmail.com becomes john.doe@atomicmail.io.
28
  - Do not alter any other personal contact details.
 
29
 
30
  4. Formatting Constraints:
31
  - The output must be ONLY a code block containing the LaTeX code.
@@ -238,8 +239,7 @@ prompt: |
238
  Target Job Description:
239
  {{JOB_DESCRIPTION}}
240
 
241
- Current Resume Details:
242
- {{CURRENT_RESUME}}
243
 
244
  ### OUTPUT INSTRUCTIONS
245
  Generate ONLY the LaTeX code in a code block. Replace all placeholders with actual content from the resume. Ensure everything is aligned to the job description and immediately compilable.
 
2
  Act as a Senior Resume Writer and ATS Optimization Specialist with 20+ years of experience in recruitment.
3
 
4
  I am providing you with:
5
+ 1. A Current Resume (attached as a file).
6
  2. A Target Job Description (JD).
7
  3. The Current Date.
8
 
 
26
  - Email Rule: You MUST replace the candidate's email domain with @atomicmail.io.
27
  Example: john.doe@gmail.com becomes john.doe@atomicmail.io.
28
  - Do not alter any other personal contact details.
29
+ - ONLY include LinkedIn, GitHub, or Portfolio links if they explicitly appear in the original resume. Do not invent or add them. If they are missing, omit the corresponding `\mbox{...}` and `\AND` separators in the header.
30
 
31
  4. Formatting Constraints:
32
  - The output must be ONLY a code block containing the LaTeX code.
 
239
  Target Job Description:
240
  {{JOB_DESCRIPTION}}
241
 
242
+
 
243
 
244
  ### OUTPUT INSTRUCTIONS
245
  Generate ONLY the LaTeX code in a code block. Replace all placeholders with actual content from the resume. Ensure everything is aligned to the job description and immediately compilable.
pyproject.toml DELETED
@@ -1,14 +0,0 @@
1
- [project]
2
- name = "raftecresumetool"
3
- version = "0.1.0"
4
- description = "Add your description here"
5
- readme = "README.md"
6
- requires-python = ">=3.13"
7
- dependencies = [
8
- "gradio>=6.1.0",
9
- "langchain>=1.1.3",
10
- "langchain-core>=1.2.0",
11
- "langchain-google-genai>=4.0.0",
12
- "pdfplumber>=0.11.8",
13
- "pyyaml>=6.0.3",
14
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
resumeRewritingService.py CHANGED
@@ -1,72 +1,59 @@
1
- from langchain_google_genai import ChatGoogleGenerativeAI
2
- from langchain_core.messages import HumanMessage
3
  from utils import readPrompts
4
  import os
5
- import base64
6
- import pdfplumber
7
- from io import BytesIO
8
-
9
 
10
  class ResumeEditService:
11
  def __init__(self):
12
  prompts = readPrompts(path=os.path.join(os.getcwd(), "prompts.yaml"))
13
  self.prompt_template = prompts.get("prompt")
14
- self.llm = self._initialize_llm()
15
-
16
- def _initialize_llm(self):
17
- """Initialize the Google Generative AI model"""
18
- return ChatGoogleGenerativeAI(
19
- model="gemini-3-flash-preview",
20
- temperature=0.3,
21
- google_api_key=os.getenv("GOOGLE_API_KEY")
22
- )
23
-
24
- def _extract_text_from_pdf_base64(self, base64_pdf: str) -> str:
25
- """
26
- Extract text from base64 encoded PDF
27
-
28
- Args:
29
- base64_pdf: Base64 encoded PDF string
30
-
31
- Returns:
32
- Extracted text from the PDF
33
- """
34
- # Decode base64 to bytes
35
- pdf_bytes = base64.b64decode(base64_pdf)
36
 
37
- # Create a BytesIO object
38
- pdf_file = BytesIO(pdf_bytes)
39
-
40
- # Extract text using PdfPlumber
41
- text = ""
42
-
43
- with pdfplumber.open(pdf_file) as pdf:
44
- for page in pdf.pages:
45
- text += page.extract_text() or ""
46
-
47
- return text.strip()
48
 
49
  def generate_optimized_resume(self, resume_base64: str, job_description: str, current_date: str) -> str:
50
  """
51
- Generate optimized resume based on job description
52
 
53
  Args:
54
- resume_base64: Base64 encoded PDF resume
55
  job_description: The target job description
56
  current_date: Current date for timeline adjustments
57
 
58
  Returns:
59
- Raw response from the LLM (LaTeX code in markdown format)
60
  """
61
- # Extract text from PDF
62
- current_resume = self._extract_text_from_pdf_base64(resume_base64)
63
 
64
- # Manual string replacement (avoiding template parsing issues)
65
  prompt = self.prompt_template.replace("{{CURRENT_DATE}}", current_date)
66
  prompt = prompt.replace("{{JOB_DESCRIPTION}}", job_description)
67
- prompt = prompt.replace("{{CURRENT_RESUME}}", current_resume)
68
 
69
- # Invoke the LLM directly
70
- response = self.llm.invoke([HumanMessage(content=prompt)])
 
 
 
 
 
 
 
71
 
72
- return response.content[0]["text"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import google.generativeai as genai
 
2
  from utils import readPrompts
3
  import os
4
+ import re
 
 
 
5
 
6
  class ResumeEditService:
7
  def __init__(self):
8
  prompts = readPrompts(path=os.path.join(os.getcwd(), "prompts.yaml"))
9
  self.prompt_template = prompts.get("prompt")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # Configure the Gemini API
12
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
13
+ self.model = genai.GenerativeModel('gemini-1.5-flash')
 
 
 
 
 
 
 
 
14
 
15
  def generate_optimized_resume(self, resume_base64: str, job_description: str, current_date: str) -> str:
16
  """
17
+ Generate optimized resume based on job description using Gemini with file attachment.
18
 
19
  Args:
20
+ resume_base64: Base64 encoded PDF/DOCX resume
21
  job_description: The target job description
22
  current_date: Current date for timeline adjustments
23
 
24
  Returns:
25
+ Optimized resume in LaTeX format (code fences stripped)
26
  """
 
 
27
 
28
+ # Prepare the prompt
29
  prompt = self.prompt_template.replace("{{CURRENT_DATE}}", current_date)
30
  prompt = prompt.replace("{{JOB_DESCRIPTION}}", job_description)
 
31
 
32
+ # Prepare the inline data for the file attachment
33
+ # Assuming PDF for now based on app.py, but could support others.
34
+ # The app.py reads the file and base64 encodes it without a mime prefix.
35
+ # We need to construct the part for the model.
36
+
37
+ file_part = {
38
+ "mime_type": "application/pdf",
39
+ "data": resume_base64
40
+ }
41
 
42
+ # Generate content
43
+ response = self.model.generate_content([prompt, file_part])
44
+
45
+ # Extract text
46
+ response_text = response.text
47
+
48
+ # Strip markdown code fences if present
49
+ cleaned_text = self._strip_code_fences(response_text)
50
+
51
+ return cleaned_text
52
+
53
+ def _strip_code_fences(self, text: str) -> str:
54
+ """Removes markdown code fences from the text."""
55
+ # Remove opening fence (e.g. ```latex, ```tex, ```)
56
+ text = re.sub(r'^```\w*\s*', '', text.strip())
57
+ # Remove closing fence
58
+ text = re.sub(r'\s*```$', '', text.strip())
59
+ return text.strip()