CapProj commited on
Commit
444431c
·
verified ·
1 Parent(s): 90dc317

Delete ats_optimizer

Browse files
ats_optimizer/README.md DELETED
@@ -1,28 +0,0 @@
1
- # ATS Optimizer Pro
2
-
3
- Complete solution to optimize resumes for applicant tracking systems.
4
-
5
- ## Features
6
-
7
- 1. **Format-Preserving Analysis**
8
- - Parses PDF/Word resumes while keeping original formatting
9
- - Advanced section detection
10
-
11
- 2. **5-Factor ATS Scoring**
12
- - Keyword matching (TF-IDF + exact match)
13
- - Section completeness
14
- - Semantic similarity (Qdrant vectors)
15
- - Experience matching
16
- - Education verification
17
-
18
- 3. **AI-Powered Optimization**
19
- - DeepSeek API integration
20
- - 3-step iterative refinement
21
- - Format-aware rewriting
22
-
23
- ## Setup
24
-
25
- 1. Install requirements:
26
- ```bash
27
- pip install -r requirements.txt
28
- python -m spacy download en_core_web_md
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/__init__.py DELETED
File without changes
ats_optimizer/app.py DELETED
@@ -1,139 +0,0 @@
1
- import streamlit as st
2
- from ats_optimizer.core import ResumeAnalyzer, ResumeOptimizer
3
- from ats_optimizer.data_models import Resume, JobDescription
4
- from ats_optimizer.utils.file_handlers import FileHandler # Updated import
5
- # from ats_optimizer.utils import FileHandler, Config
6
- from ats_optimizer.utils.config_manager import Config
7
- from pathlib import Path
8
- import tempfile
9
- import sys
10
-
11
- # Fix module imports for Hugging Face
12
- sys.path.append(str(Path(__file__).parent))
13
-
14
- # def main():
15
- # # Initialize components
16
- # config = Config('config.yaml')
17
- # analyzer = ResumeAnalyzer()
18
- # optimizer = ResumeOptimizer(config.deepseek_api_key)
19
-
20
- # # Streamlit UI
21
- # st.title("🚀 ATS Optimizer Pro")
22
- # st.markdown("Upload your resume and job description to analyze and optimize for ATS compatibility")
23
-
24
- # # File upload section
25
- # with st.expander("Upload Files", expanded=True):
26
- # col1, col2 = st.columns(2)
27
- # with col1:
28
- # resume_file = st.file_uploader("Resume", type=["pdf", "docx"], key="resume_upload")
29
- # with col2:
30
- # jd_file = st.file_uploader("Job Description", type=["pdf", "docx", "txt"], key="jd_upload")
31
-
32
- # if st.button("Analyze", type="primary"):
33
- # if resume_file and jd_file:
34
- # with st.spinner("Processing files..."):
35
- # try:
36
- # # Save uploaded files
37
- # with tempfile.TemporaryDirectory() as temp_dir:
38
- # resume_path = FileHandler.save_uploaded_file(resume_file, temp_dir)
39
- # jd_path = FileHandler.save_uploaded_file(jd_file, temp_dir)
40
-
41
- # if not resume_path or not jd_path:
42
- # st.error("Failed to process uploaded files")
43
- # return
44
-
45
- # # Analyze documents
46
- # resume = analyzer.parse_resume(resume_path)
47
- # jd = analyzer.parse_jd(jd_path)
48
-
49
- # # Calculate score
50
- # score = analyzer.calculate_ats_score(resume, jd)
51
-
52
- # # Display results
53
- # st.subheader("📊 Analysis Results")
54
- # st.metric("Overall ATS Score", f"{score['overall_score']:.1f}%")
55
-
56
- # with st.expander("Detailed Scores"):
57
- # st.write(f"Keyword Match: {score['keyword_score']:.1f}%")
58
- # st.write(f"Section Completeness: {score['section_score']:.1f}%")
59
- # st.write(f"Experience Match: {score['experience_score']:.1f}%")
60
-
61
- # # Optimization section
62
- # st.subheader("🛠 Optimization")
63
- # if st.button("Optimize Resume", key="optimize_btn"):
64
- # with st.spinner("Rewriting resume..."):
65
- # optimized = optimizer.rewrite_resume(resume, jd)
66
- # temp_output = Path(temp_dir) / "optimized_resume.docx"
67
- # FileHandler.save_resume(optimized, str(temp_output))
68
-
69
- # st.success("Optimization complete!")
70
- # with open(temp_output, "rb") as f:
71
- # st.download_button(
72
- # "Download Optimized Resume",
73
- # data=f,
74
- # file_name="optimized_resume.docx",
75
- # mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document"
76
- # )
77
-
78
- # except Exception as e:
79
- # st.error(f"An error occurred: {str(e)}")
80
- # st.stop()
81
- # else:
82
- # st.warning("Please upload both resume and job description files")
83
-
84
- # if __name__ == "__main__":
85
- # main()
86
-
87
- def main():
88
- # Initialize components
89
- config = Config('config.yaml')
90
- analyzer = ResumeAnalyzer()
91
- optimizer = ResumeOptimizer(config.deepseek_api_key)
92
-
93
- # Streamlit UI
94
- st.title("ATS Optimizer Pro")
95
-
96
- # File upload
97
- resume_file = st.file_uploader("Upload Resume", type=["pdf", "docx"])
98
- jd_file = st.file_uploader("Upload Job Description", type=["pdf", "docx", "txt"])
99
-
100
- if st.button("Analyze"):
101
- if resume_file and jd_file:
102
- with st.spinner("Processing..."):
103
- try:
104
- # Create temp directory
105
- with tempfile.TemporaryDirectory() as temp_dir:
106
- # Save uploaded files
107
- resume_path = FileHandler.save_uploaded_file(resume_file, temp_dir)
108
- jd_path = FileHandler.save_uploaded_file(jd_file, temp_dir)
109
-
110
- if not resume_path or not jd_path:
111
- st.error("Failed to process uploaded files")
112
- return
113
-
114
- # Analyze documents
115
- resume = analyzer.parse_resume(resume_path)
116
- jd = analyzer.parse_jd(jd_path)
117
-
118
- # Calculate score
119
- score = analyzer.calculate_ats_score(resume, jd)
120
-
121
- # Display results
122
- st.subheader("Analysis Results")
123
- st.json(score)
124
-
125
- # Optimization
126
- if st.button("Optimize Resume"):
127
- optimized = optimizer.rewrite_resume(resume, jd)
128
- output_path = os.path.join(temp_dir, "optimized_resume.docx")
129
- if FileHandler.save_resume(optimized, output_path):
130
- with open(output_path, "rb") as f:
131
- st.download_button(
132
- "Download Optimized Resume",
133
- data=f,
134
- file_name="optimized_resume.docx"
135
- )
136
- except Exception as e:
137
- st.error(f"An error occurred: {str(e)}")
138
- else:
139
- st.warning("Please upload both resume and job description files")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/config.yaml DELETED
@@ -1,18 +0,0 @@
1
- deepseek:
2
- api_key: "sk-cf0b89ca56e44cb9980113909ebe687e"
3
- model: "deepseek-chat"
4
- temperature: 0.7
5
-
6
- google_sheets:
7
- enabled: true # Set to true if using Google Sheets or else false
8
- credentials: "credentials.json"
9
- # sheet_id: "your-sheet-id"
10
- sheet_name: "Job Applications"
11
-
12
- scoring:
13
- weights:
14
- keyword: 0.3
15
- section: 0.2
16
- vector: 0.25
17
- experience: 0.15
18
- education: 0.1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/__init__.py DELETED
@@ -1,10 +0,0 @@
1
- # from .analyzer import ResumeAnalyzer
2
- # from .optimizer import ResumeOptimizer
3
- # from .tracker import ApplicationTracker
4
-
5
- from ats_optimizer.core.analyzer import ResumeAnalyzer
6
- from ats_optimizer.core.optimizer import ResumeOptimizer
7
- from ats_optimizer.core.tracker import ApplicationTracker
8
-
9
- __all__ = ['ResumeAnalyzer', 'ResumeOptimizer', 'ApplicationTracker']
10
- # __all__ = ['ResumeAnalyzer', 'ResumeOptimizer'] #if doesnt want to use tracker & comment above import too
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/analyzer.py DELETED
@@ -1,41 +0,0 @@
1
- from qdrant_client import QdrantClient
2
- from ats_optimizer.data_models.resume import Resume
3
- from ats_optimizer.data_models.job_description import JobDescription
4
- # from utils.logger import logger
5
- # from ..utils.logger import logger
6
- from ats_optimizer.utils.logger import logger
7
-
8
- class ResumeAnalyzer:
9
- def __init__(self):
10
- self.client = QdrantClient(":memory:")
11
- self.client.set_model("BAAI/bge-base-en")
12
-
13
- def parse_resume(self, file_path: str) -> Resume:
14
- """Step 1: Parse resume with formatting preservation"""
15
- # Uses python-docx for Word docs, pdfminer for PDFs
16
- raw_text, formatting = FileHandler.extract_with_formatting(file_path)
17
- return Resume(raw_text, formatting)
18
-
19
- def parse_jd(self, file_path: str) -> JobDescription:
20
- """Step 2: Analyze job description"""
21
- raw_text = FileHandler.extract_text(file_path)
22
- return JobDescription(raw_text)
23
-
24
- def calculate_ats_score(self, resume: Resume, jd: JobDescription) -> dict:
25
- """Step 3: Comprehensive ATS scoring"""
26
- # Enhanced scoring with 5 factors
27
- scores = {
28
- 'keyword': self._keyword_match_score(resume, jd),
29
- 'section': self._section_completeness(resume, jd),
30
- 'vector': self._vector_similarity(resume, jd),
31
- 'experience': self._experience_match(resume, jd),
32
- 'education': self._education_match(resume, jd)
33
- }
34
- scores['overall'] = sum(w * s for w, s in [
35
- (0.3, scores['keyword']),
36
- (0.2, scores['section']),
37
- (0.25, scores['vector']),
38
- (0.15, scores['experience']),
39
- (0.1, scores['education'])
40
- ])
41
- return scores
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/form_filler/background.js DELETED
@@ -1,10 +0,0 @@
1
- chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2
- if (request.action === "fillForm") {
3
- chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
4
- chrome.tabs.sendMessage(tabs[0].id, {
5
- action: "fillFields",
6
- resumeData: request.data
7
- });
8
- });
9
- }
10
- });
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/form_filler/content.js DELETED
@@ -1,14 +0,0 @@
1
- chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
2
- if (msg.action === "fillFields") {
3
- const fields = {
4
- 'input[name*="name"]': msg.resumeData.name,
5
- 'input[name*="email"]': msg.resumeData.email,
6
- 'textarea[name*="experience"]': msg.resumeData.experience
7
- };
8
-
9
- Object.entries(fields).forEach(([selector, value]) => {
10
- const el = document.querySelector(selector);
11
- if (el) el.value = value;
12
- });
13
- }
14
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/form_filler/manifest.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "manifest_version": 3,
3
- "name": "ATS AutoFill",
4
- "version": "1.0",
5
- "permissions": ["activeTab", "storage"],
6
- "action": {
7
- "default_popup": "popup.html",
8
- "default_icon": "icon.png"
9
- },
10
- "background": {
11
- "service_worker": "background.js"
12
- },
13
- "content_scripts": [{
14
- "matches": ["*://*/*"],
15
- "js": ["content.js"]
16
- }]
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/form_filler/popup.html DELETED
@@ -1,10 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>ATS AutoFill</title>
5
- <script src="popup.js"></script>
6
- </head>
7
- <body>
8
- <button id="fillButton">Fill Form</button>
9
- </body>
10
- </html>
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/optimizer.py DELETED
@@ -1,39 +0,0 @@
1
- import requests
2
- from docx import Document
3
- from data_models.resume import Resume
4
-
5
- from ats_optimizer.data_models.job_description import JobDescription
6
- from ats_optimizer.data_models.resume import Resume
7
-
8
- class ResumeOptimizer:
9
- def __init__(self, api_key: str):
10
- self.api_key = api_key
11
- # self.template = "templates/professional.docx"
12
- self.template = "templates/Ramen_DXC.docx"
13
-
14
- def rewrite_resume(self, resume: Resume, jd: JobDescription) -> Resume:
15
- """Step 4: AI rewriting with formatting preservation"""
16
- prompt = self._build_optimization_prompt(resume, jd)
17
-
18
- response = requests.post(
19
- "https://api.deepseek.com/v1/chat/completions",
20
- headers={"Authorization": f"Bearer {self.api_key}"},
21
- json={
22
- "model": "deepseek-chat",
23
- "messages": [{
24
- "role": "user",
25
- "content": prompt
26
- }],
27
- "temperature": 0.7
28
- }
29
- )
30
-
31
- # Apply optimized content to original format
32
- optimized_content = response.json()["choices"][0]["message"]["content"]
33
- return self._apply_formatting(resume, optimized_content)
34
-
35
- def _apply_formatting(self, original: Resume, new_content: str) -> Resume:
36
- """Preserve original formatting with new content"""
37
- doc = Document(original.file_path)
38
- # Advanced formatting preservation logic
39
- return Resume.from_docx(doc, new_content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/core/tracker.py DELETED
@@ -1,57 +0,0 @@
1
- import gspread
2
- from oauth2client.service_account import ServiceAccountCredentials
3
- from pathlib import Path
4
- import logging
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
- '''
9
- class ApplicationTracker:
10
- def __init__(self, creds_path: str):
11
- self.scope = ["https://www.googleapis.com/auth/spreadsheets"]
12
- self.creds = ServiceAccountCredentials.from_json_keyfile_name(creds_path, self.scope)
13
-
14
- def track(self, application_data: dict):
15
- """Track application in Google Sheets with enhanced fields"""
16
- client = gspread.authorize(self.creds)
17
- sheet = client.open("Job Applications").sheet1
18
-
19
- sheet.append_row([
20
- application_data['company'],
21
- application_data['position'],
22
- application_data['date'],
23
- application_data['status'],
24
- application_data['score'],
25
- application_data['url'],
26
- application_data['resume_version'],
27
- application_data['notes']
28
- ])
29
- '''
30
- class ApplicationTracker:
31
- def __init__(self, creds_path: str):
32
- if not Path(creds_path).exists():
33
- raise FileNotFoundError(f"Credentials file not found at {creds_path}")
34
-
35
- try:
36
- self.scope = ["https://www.googleapis.com/auth/spreadsheets"]
37
- self.creds = ServiceAccountCredentials.from_json_keyfile_name(creds_path, self.scope)
38
- self.client = gspread.authorize(self.creds)
39
- except Exception as e:
40
- logger.error(f"Google Sheets auth failed: {e}")
41
- raise
42
-
43
- def track(self, application_data: dict, sheet_name="Job Applications"):
44
- try:
45
- sheet = self.client.open(sheet_name).sheet1
46
- sheet.append_row([
47
- application_data.get('company', ''),
48
- application_data.get('position', ''),
49
- application_data.get('date_applied', ''),
50
- application_data.get('status', 'Applied'),
51
- application_data.get('score', ''),
52
- application_data.get('url', '')
53
- ])
54
- return True
55
- except Exception as e:
56
- logger.error(f"Tracking failed: {e}")
57
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/credentials.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "type": "service_account",
3
- "project_id": "formal-theater-458022-d2",
4
- "private_key_id": "e7494ef90b6d43b0dc15ce9f9db0922225a48694",
5
- "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDGjEU29ETZSyx\nqr8zakizg+q3IqWq3pQdMVHH72GLq/vugkZiqao11YdFK3igyKIRApacpLAACjmm\nEoUwcKEh1R7WKExbAvyFTLIm65j9wZ2Z2LeAuRRZFjU2uQ+iCXOTQA7YgIPU3sMg\nLI+cMAITr0C4hLRnjgUcPeNQRG8M/Io3Oq4KeTDvEKS99aqVvA7zgGH98awdBd2c\ncciYGHaTUq5sJxK72AKFnPxrLHgbq9hiuc5fw7YdCVzmuVY/LXkwSkosbIsIrxUx\nPHwlnYdoWHZ0aI76x3qluw+MUqZoIEp3ctkIfHaZbLf4yuqTcbUuQ7RtkPFLifge\ndFsM7BnhAgMBAAECggEASLQr8h/wC5A6VYLReXFz4iGYh+JLZh9HhpFobl8QNKJE\nYZ7+Z6neGe2WWPpYG2JosnoKchkU1Q76aJ6iL2jpQthOg3PE8G1ueKYaBVLqUjWi\na0BNMZTGtmQGNHxGDRYEkazfW2KYvey9PfIdGhDx1TALqDcbmzNbSCjv2muGDoou\nzmEcAzdil5M0UNVctqxqAOk4PK3l59dSUdRgJLP6LsceT1xqNDw9Ps9x8vOUY3iq\n0kkOeXu+eTVIkgTxIsJGnBQ0wr+Ao5r12zJ8Y/iyXDVN/RTOl+aakegYiIYjeVZu\nEPyZ2fMNnQCtfSGzoLrcHyFxkhh1Fl2E4ZhW4hWh+QKBgQDgjtlnhBdhNuBGHOp0\nknRKWlhtRXzuIDklCmIS/vK0ZXpCF2wacXo7UKHQ7oVPsA5+0MqeV9teu8hqQm/Y\nZRipHU911zlsR81ZejR4WQ8xDci4Ewpt5JVkx+DfPlNXuPapgGTtg/KBDfKHWnnv\nNr/BSeRSNb5iSPkS/j4ENnrhEwKBgQDea4U0cy9J2YvBhOmb/Bk9fOIBcnlz/B2v\nWt/+ddIZnW1IOYgSd/W8W3GyQ803OzzuHa+y0vLNnGBwapOMPJ8foagy36XYbRxr\nSu8He+oTTJTgwidEnUz1DS8B3IIgi+FJK8YLUL8hVupuBqqI/r9G/wtULTFutzvD\n5/N/rCaruwKBgADOIlNvstHDa5x0wBZ46/fUSRrjM+Z6sRnD5sQgq+gfsQeJo/aY\nT5Lk4B+qq0m03OhxgTh+Iig9ziMrZ9FD04nPtBg9FFSiEUdv275Ou3I2lXCriM8K\nEcsRuGm0hIH9BM1oy3PalEUIMsVvep5z+M4NoMb2sF8T2ejKhphnRZuHAoGAL+rM\nFMOn8WoLwNJIndFPAr8v1Y36+nDbWFbkoOZzMA+JZqD2Xrw3VbABq50NzhNWChqd\nKpJlusQwxqc/SFwbD+581RD3osvG7pqDKoKYqDW8cTuCyDZ3SOfhM6503lwkWeYz\nUWbA9obKFJAdF0yCmuIBZ84gszCIkKkc/WlyH1cCgYEAtkmceBmt/YCPnaVDhk/L\n4hWqcVHqD2RU4DPPhjIXppjahDrcOzjD7Lt9swKK3QZEE840DcIAKVU140V2Neie\nOXqzgrLn/dIe0j15FK4lmY9GhCVU3kTx08JwxEiBIDoi0Z6F926C9dvjGxarpsi7\n77pNNpxzZ9i6mx9dK9ECuMI=\n-----END PRIVATE KEY-----\n",
6
- "client_email": "[email protected]",
7
- "client_id": "102212927624577642135",
8
- "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
- "token_uri": "https://oauth2.googleapis.com/token",
10
- "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
- "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/ats-optimizer%40formal-theater-458022-d2.iam.gserviceaccount.com",
12
- "universe_domain": "googleapis.com"
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/data_models/__init__.py DELETED
@@ -1,5 +0,0 @@
1
- # from .resume import Resume
2
- from .resume import Resume
3
- from .job_description import JobDescription
4
-
5
- __all__ = ['Resume', 'JobDescription']
 
 
 
 
 
 
ats_optimizer/data_models/job_description.py DELETED
@@ -1,32 +0,0 @@
1
- from dataclasses import dataclass
2
- from typing import Dict, List
3
-
4
- @dataclass
5
- class JobDescription:
6
- # raw_text: str
7
- # extracted_keywords: List[str]
8
- # keyterms: List[tuple]
9
- # entities: List[str]
10
- raw_text: str
11
- extracted_keywords: list
12
- keyterms: list
13
- entities: list
14
-
15
- @property
16
- def required_skills(self) -> List[str]:
17
- return [kw for kw in self.extracted_keywords if 'skill' in kw.lower()]
18
-
19
- @property
20
- def experience_requirements(self) -> Dict:
21
- return {
22
- 'years': self._extract_years(),
23
- 'technologies': self._extract_tech()
24
- }
25
-
26
- def _extract_years(self) -> int:
27
- # Extract years requirement using regex
28
- pass
29
-
30
- def _extract_tech(self) -> List[str]:
31
- # Extract required technologies
32
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/data_models/resume.py DELETED
@@ -1,23 +0,0 @@
1
- from dataclasses import dataclass
2
- from typing import Dict, List
3
-
4
- @dataclass
5
- class Resume:
6
- # raw_text: str
7
- # formatting: Dict
8
- # metadata: Dict
9
- # scores: Dict = None
10
- raw_text: str
11
- extracted_keywords: list
12
- keyterms: list
13
- entities: list
14
-
15
- @classmethod
16
- def from_docx(cls, file_path: str):
17
- """Parse while preserving formatting"""
18
- text, formatting = parse_docx_with_formatting(file_path)
19
- return cls(text, formatting, extract_metadata(text))
20
-
21
- def to_docx(self, output_path: str):
22
- """Export with original formatting"""
23
- apply_formatting(self.raw_text, self.formatting, output_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/requirement.txt DELETED
@@ -1,22 +0,0 @@
1
- # Core
2
- python-docx==0.8.11
3
- pdfminer.six==20221105
4
- #python-docx-template==0.16.0
5
- docxtpl==0.16.0
6
- pdf2docx==0.5.6
7
- qdrant-client==1.6.4
8
- sentence-transformers==2.2.2
9
-
10
- # API & Services
11
- google-api-python-client==2.104.0
12
- gspread==5.11.3
13
- requests==2.31.0
14
- oauth2client==4.1.3
15
-
16
- # UI
17
- streamlit==1.29.0
18
- plotly==5.18.0
19
-
20
- # NLP
21
- spacy==3.7.2
22
- en-core-web-md @ https://github.com/explosion/spacy-models/releases/download/en_core_web_md-3.7.0/en_core_web_md-3.7.0-py3-none-any.whl
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/setup.py DELETED
@@ -1,16 +0,0 @@
1
- # setup.py
2
- from setuptools import setup, find_packages
3
-
4
- setup(
5
- name="ats_optimizer",
6
- version="0.1",
7
- packages=find_packages(),
8
- install_requires=[
9
- 'python-docx>=0.8.11',
10
- 'pdfminer.six>=20221105',
11
- 'pyyaml>=6.0',
12
- 'streamlit>=1.28.0',
13
- 'spacy>=3.7.2',
14
- ],
15
- python_requires='>=3.9',
16
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/templates/Ramen_DXC.docx DELETED
Binary file (39.9 kB)
 
ats_optimizer/templates/professional.docx DELETED
File without changes
ats_optimizer/utils/__init__.py DELETED
@@ -1,5 +0,0 @@
1
- from .file_handlers import FileHandler
2
- from .logger import setup_logger
3
- from .config_manager import Config
4
-
5
- __all__ = ['FileHandler', 'setup_logger', 'Config']
 
 
 
 
 
 
ats_optimizer/utils/config_manager.py DELETED
@@ -1,9 +0,0 @@
1
- import yaml
2
-
3
- class Config:
4
- def __init__(self, config_path: str):
5
- with open(config_path, 'r') as f:
6
- self.config = yaml.safe_load(f)
7
-
8
- def __getattr__(self, name):
9
- return self.config.get(name)
 
 
 
 
 
 
 
 
 
 
ats_optimizer/utils/file_handlers.py DELETED
@@ -1,69 +0,0 @@
1
- import os
2
- from docx import Document
3
- from pdfminer.high_level import extract_text
4
- from pathlib import Path
5
- from tempfile import NamedTemporaryFile
6
- import uuid
7
-
8
- class FileHandler:
9
- @staticmethod
10
- def read_file(file_path: str) -> str:
11
- if file_path.endswith('.docx'):
12
- return FileHandler._read_docx(file_path)
13
- elif file_path.endswith('.pdf'):
14
- return extract_text(file_path)
15
- else:
16
- with open(file_path, 'r') as f:
17
- return f.read()
18
- #--
19
-
20
- @staticmethod
21
- def save_uploaded_file(uploaded_file, directory="temp_uploads"):
22
- """Save Streamlit uploaded file to a temporary directory"""
23
- try:
24
- # Create directory if it doesn't exist
25
- Path(directory).mkdir(exist_ok=True)
26
-
27
- # Generate unique filename
28
- file_ext = Path(uploaded_file.name).suffix
29
- unique_id = uuid.uuid4().hex
30
- temp_file = Path(directory) / f"{unique_id}{file_ext}"
31
-
32
- # Save file
33
- with open(temp_file, "wb") as f:
34
- f.write(uploaded_file.getbuffer())
35
-
36
- return str(temp_file)
37
- except Exception as e:
38
- print(f"Error saving file: {e}")
39
- return None
40
-
41
- @staticmethod
42
- def cleanup_temp_files(directory="temp_uploads"):
43
- """Remove temporary files"""
44
- try:
45
- for file in Path(directory).glob("*"):
46
- file.unlink()
47
- except Exception as e:
48
- print(f"Error cleaning files: {e}")
49
- #--
50
-
51
- @staticmethod
52
- def _read_docx(file_path: str) -> str:
53
- doc = Document(file_path)
54
- return '\n'.join([para.text for para in doc.paragraphs])
55
-
56
- @staticmethod
57
- def save_resume(resume_data: dict, output_path: str):
58
- if output_path.endswith('.docx'):
59
- FileHandler._save_as_docx(resume_data, output_path)
60
- else:
61
- with open(output_path, 'w') as f:
62
- f.write(resume_data['content'])
63
-
64
- @staticmethod
65
- def _save_as_docx(resume_data: dict, output_path: str):
66
- doc = Document()
67
- # Add formatting preservation logic here
68
- doc.save(output_path)
69
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/utils/file_handlers1.py DELETED
@@ -1,55 +0,0 @@
1
- import os
2
- from pathlib import Path
3
- import uuid
4
- from docx import Document
5
- from pdfminer.high_level import extract_text
6
-
7
- class FileHandler:
8
- @staticmethod
9
- def save_uploaded_file(uploaded_file, directory="temp_uploads"):
10
- """Save Streamlit uploaded file to temporary directory"""
11
- try:
12
- # Create directory if needed
13
- Path(directory).mkdir(exist_ok=True)
14
-
15
- # Generate unique filename
16
- file_ext = Path(uploaded_file.name).suffix
17
- unique_id = uuid.uuid4().hex
18
- temp_file = Path(directory) / f"{unique_id}{file_ext}"
19
-
20
- # Save file
21
- with open(temp_file, "wb") as f:
22
- f.write(uploaded_file.getbuffer())
23
-
24
- return str(temp_file)
25
- except Exception as e:
26
- print(f"Error saving file: {e}")
27
- return None
28
-
29
- @staticmethod
30
- def save_resume(resume_data, output_path):
31
- """Save resume content to file"""
32
- try:
33
- if output_path.endswith('.docx'):
34
- doc = Document()
35
- for paragraph in resume_data.split('\n'):
36
- doc.add_paragraph(paragraph)
37
- doc.save(output_path)
38
- else:
39
- with open(output_path, 'w') as f:
40
- f.write(resume_data)
41
- return True
42
- except Exception as e:
43
- print(f"Error saving resume: {e}")
44
- return False
45
-
46
- @staticmethod
47
- def cleanup_temp_files(directory="temp_uploads"):
48
- """Remove temporary files"""
49
- try:
50
- for file in Path(directory).glob("*"):
51
- file.unlink()
52
- return True
53
- except Exception as e:
54
- print(f"Error cleaning files: {e}")
55
- return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ats_optimizer/utils/logger.py DELETED
@@ -1,18 +0,0 @@
1
- import logging
2
-
3
- def setup_logger(name: str = 'ats_optimizer'):
4
- logger = logging.getLogger(name)
5
- logger.setLevel(logging.INFO)
6
-
7
- handler = logging.StreamHandler()
8
- formatter = logging.Formatter(
9
- '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
10
- )
11
- handler.setFormatter(formatter)
12
- logger.addHandler(handler)
13
-
14
- return logger
15
-
16
-
17
- # Create a module-level logger instance
18
- logger = setup_logger()