Parthiban97 commited on
Commit
0212d62
Β·
verified Β·
1 Parent(s): bb53ea0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +555 -112
app.py CHANGED
@@ -3,19 +3,47 @@
3
 
4
  import streamlit as st
5
  import os
6
- from PyPDF2 import PdfReader
7
- import google.generativeai as genai
8
- from dotenv import load_dotenv
9
  import hashlib
10
  import json
 
 
11
  from datetime import datetime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  # Loading the .env keys
14
  load_dotenv()
15
 
16
- # MASTER UNIVERSAL SYSTEM PROMPT - Designed for Maximum Consistency & Global Applicability
17
- # Based on Latest 2025 ATS Optimization Research & AI Best Practices
 
18
 
 
19
  UNIVERSAL_MASTER_PROMPT = """
20
  You are the ULTIMATE ATS OPTIMIZATION ENGINE 3.0 - A state-of-the-art AI system designed to provide CONSISTENT, PRECISE, and GLOBALLY APPLICABLE resume analysis across ALL industries, roles, and experience levels.
21
 
@@ -112,37 +140,17 @@ Always provide results in this EXACT format for consistency:
112
  **πŸ† FINAL VERDICT:**
113
  [EXCEPTIONAL 90-100 | STRONG 75-89 | GOOD 60-74 | DEVELOPING 45-59 | NEEDS WORK <45]
114
 
115
- **GLOBAL INDUSTRY ADAPTATION MATRIX:**
116
- Automatically adapt analysis based on detected industry context:
117
- - Technology: Focus on technical skills, certifications, project impact
118
- - Healthcare: Emphasize compliance, patient outcomes, clinical expertise
119
- - Finance: Highlight risk management, regulatory knowledge, quantitative skills
120
- - Manufacturing: Assess process improvement, safety, operational efficiency
121
- - Marketing: Evaluate campaign results, digital proficiency, creative impact
122
- - Education: Focus on learning outcomes, curriculum development, mentoring
123
- - Legal: Emphasize case outcomes, regulatory expertise, research capabilities
124
- - Consulting: Highlight client impact, analytical skills, strategic thinking
125
-
126
  **CONSISTENCY GUARANTEES:**
127
  - Same resume + same job description = identical analysis (Β±2 points variation max)
128
  - Standardized language and terminology across all evaluations
129
  - Reproducible scoring methodology regardless of domain
130
  - Time-consistent results (same analysis today and tomorrow)
131
-
132
- **QUALITY ASSURANCE CHECKS:**
133
- - Bias detection and mitigation protocols
134
- - Cultural sensitivity and inclusive language
135
- - Legal compliance verification
136
- - Ethical evaluation standards
137
-
138
- Proceed with analysis using this framework while maintaining absolute consistency and global applicability.
139
  """
140
 
141
  # Specialized prompts that extend the master prompt for specific use cases
142
  SPECIALIZED_PROMPTS = {
143
  "evaluate_resume": f"""
144
  {UNIVERSAL_MASTER_PROMPT}
145
-
146
  **SPECIFIC TASK: COMPREHENSIVE RESUME EVALUATION**
147
  Apply the Universal Evaluation Framework above to provide a complete assessment.
148
  Focus on overall candidacy evaluation with balanced perspective on strengths and development areas.
@@ -151,108 +159,87 @@ Maintain professional tone suitable for HR professionals and hiring managers.
151
 
152
  "improve_skills": f"""
153
  {UNIVERSAL_MASTER_PROMPT}
154
-
155
  **SPECIFIC TASK: SKILL ENHANCEMENT STRATEGY**
156
  After completing the standard evaluation, provide additional guidance:
157
-
158
  **πŸ“ˆ SKILL DEVELOPMENT ROADMAP:**
159
  - **Immediate Actions (0-3 months):** Quick wins and foundational improvements
160
  - **Short-term Goals (3-12 months):** Structured learning and certification paths
161
  - **Long-term Vision (1-3 years):** Strategic career advancement opportunities
162
-
163
  **πŸŽ“ LEARNING RESOURCES:**
164
  - Recommended courses, certifications, and training programs
165
  - Industry conferences and networking opportunities
166
  - Practical projects and portfolio development suggestions
167
-
168
  Focus on actionable, measurable improvement strategies with clear timelines.
169
  """,
170
 
171
  "missing_keywords": f"""
172
  {UNIVERSAL_MASTER_PROMPT}
173
-
174
  **SPECIFIC TASK: ATS KEYWORD OPTIMIZATION**
175
  After completing the standard evaluation, provide enhanced keyword analysis:
176
-
177
  **πŸ” ADVANCED KEYWORD ANALYSIS:**
178
  - **CRITICAL MISSING (High Impact):** Essential terms significantly affecting ATS ranking
179
  - **IMPORTANT ADDITIONS (Medium Impact):** Valuable terms improving visibility
180
  - **OPTIMIZATION OPPORTUNITIES (Low Impact):** Supplementary terms for comprehensive coverage
181
-
182
  **πŸ“ INTEGRATION STRATEGY:**
183
  - Specific resume sections for keyword placement
184
  - Natural integration techniques avoiding keyword stuffing
185
  - Industry-appropriate phrasing and terminology
186
-
187
  **πŸ€– ATS COMPATIBILITY SCORE:** [Detailed breakdown of parsing efficiency]
188
  """,
189
 
190
  "percentage_match": f"""
191
  {UNIVERSAL_MASTER_PROMPT}
192
-
193
  **SPECIFIC TASK: PRECISE MATCHING ANALYSIS**
194
  Provide the standard evaluation with enhanced quantitative focus:
195
-
196
  **πŸ“Š DETAILED SCORING BREAKDOWN:**
197
  Present exact point allocation for each category with clear justification.
198
  Include competitive benchmarking and market positioning analysis.
199
  Provide specific improvement strategies for 10-15% score increase.
200
-
201
  **🎯 MATCH PERCENTAGE: [XX%]**
202
  Tier Classification with detailed rationale and next steps.
203
  """,
204
 
205
  "answer_query": f"""
206
  {UNIVERSAL_MASTER_PROMPT}
207
-
208
  **SPECIFIC TASK: EXPERT CONSULTATION**
209
  Apply domain expertise to answer the specific query while considering:
210
  - Resume content and job description context
211
  - Industry best practices and current market trends
212
  - Practical, actionable guidance
213
  - Evidence-based recommendations
214
-
215
  Provide thorough, well-researched responses with specific examples and multiple solution approaches when applicable.
216
  """,
217
 
218
  "executive_assessment": f"""
219
  {UNIVERSAL_MASTER_PROMPT}
220
-
221
  **SPECIFIC TASK: EXECUTIVE-LEVEL EVALUATION**
222
  Apply enhanced criteria for senior leadership positions:
223
-
224
  **πŸ‘” EXECUTIVE COMPETENCY FRAMEWORK:**
225
  - Strategic thinking and vision development
226
  - Change management and transformation leadership
227
  - Financial acumen and business impact
228
  - Board readiness and governance experience
229
-
230
  **πŸ“ˆ LEADERSHIP IMPACT ANALYSIS:**
231
  - Quantifiable business results and achievements
232
  - Market expansion and competitive positioning
233
  - Organizational culture and talent development
234
  - Crisis leadership and resilience
235
-
236
  Provide insights suitable for C-suite and board-level discussions.
237
  """,
238
 
239
  "career_transition": f"""
240
  {UNIVERSAL_MASTER_PROMPT}
241
-
242
  **SPECIFIC TASK: CAREER PIVOT ANALYSIS**
243
  Evaluate career change feasibility with:
244
-
245
  **πŸ”„ TRANSITION ASSESSMENT:**
246
  - Transferable skills mapping across industries
247
  - Market positioning strategy for career change
248
  - Risk mitigation and success probability analysis
249
  - Timeline and milestone planning
250
-
251
  **🎯 TRANSITION ROADMAP:**
252
  - Phase-wise transition strategy
253
  - Skill development priorities
254
  - Network building and industry immersion plan
255
-
256
  Provide strategic guidance maximizing transition success while minimizing career risks.
257
  """
258
  }
@@ -267,20 +254,218 @@ GENERATION_CONFIG = {
267
  }
268
 
269
  # Model options optimized for consistency and performance
270
- MODEL_OPTIONS = [
271
- "gemini-2.5-pro", # Most reliable for consistent outputs
272
- "gemini-2.5-flash" # Fast with good consistency
 
 
273
  ]
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  def create_consistency_hash(resume_text, job_description, prompt_type):
276
  """Create a hash for identical inputs to ensure consistent outputs"""
277
  content = f"{resume_text[:1000]}{job_description[:1000]}{prompt_type}"
278
  return hashlib.md5(content.encode()).hexdigest()
279
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  def get_consistent_gemini_response(model_id, prompt, pdf_content, input_text, consistency_hash):
281
- """Enhanced response generation with consistency protocols"""
282
  try:
283
- model = genai.GenerativeModel(model_id)
 
 
 
 
 
 
 
 
284
 
285
  # Add consistency instruction to prompt
286
  enhanced_prompt = f"""
@@ -289,43 +474,256 @@ def get_consistent_gemini_response(model_id, prompt, pdf_content, input_text, co
289
  **CONSISTENCY PROTOCOL ACTIVE:**
290
  Session ID: {consistency_hash}
291
  Evaluation Date: {datetime.now().strftime('%Y-%m-%d')}
292
-
293
  Apply identical methodology and scoring for consistent results.
294
  Use deterministic analysis patterns and standardized language.
 
 
 
 
 
 
295
  """
296
 
297
  response = model.generate_content(
298
- [enhanced_prompt, pdf_content, input_text],
299
  generation_config=genai.types.GenerationConfig(**GENERATION_CONFIG)
300
  )
301
- return response.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
 
303
  except Exception as e:
304
  st.error(f"⚠️ Analysis Error: {str(e)}")
305
- return "Unable to complete analysis. Please check your API key and try again."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
 
307
- def get_pdf_text(pdf_docs):
308
- """Enhanced PDF text extraction with better error handling"""
309
  text = ""
310
- try:
311
- for doc in pdf_docs:
 
312
  if doc.name.endswith(".pdf"):
313
- pdf_reader = PdfReader(doc)
314
- for page in pdf_reader.pages:
315
- text += page.extract_text() + "\n"
316
- elif doc.name.endswith(".docx"):
 
317
  try:
318
- import docx
319
- doc_reader = docx.Document(doc)
320
- for para in doc_reader.paragraphs:
321
- text += para.text + "\n"
322
- except ImportError:
323
- st.error("πŸ“‹ Please install python-docx package for DOCX support.")
324
- except Exception as e:
325
- st.error(f"πŸ“„ File processing error: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
 
 
327
  return text
328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  # Streamlit App Configuration
330
  st.set_page_config(
331
  page_title="Ultimate Smart ATS System 2025",
@@ -371,6 +769,10 @@ st.markdown("""
371
  display: inline-block;
372
  margin: 0.5rem 0;
373
  }
 
 
 
 
374
  </style>
375
  """, unsafe_allow_html=True)
376
 
@@ -383,18 +785,32 @@ st.markdown("""
383
  </div>
384
  """, unsafe_allow_html=True)
385
 
 
 
 
 
 
 
 
 
 
 
 
386
  # Sidebar Configuration
387
  with st.sidebar:
388
  st.markdown("### πŸ”‘ Configuration")
389
  st.markdown("[Get your Google API Key](https://aistudio.google.com/app/apikey)")
390
 
391
  api_key = st.text_input("πŸ” Google API Key", type="password", help="Your Gemini API key for AI analysis")
 
392
 
393
- selected_model = st.selectbox(
394
- "πŸ€– Select AI Model",
395
- MODEL_OPTIONS,
396
- help="Choose model optimized for consistent results"
397
- )
 
 
398
 
399
  st.markdown("### πŸ“‚ Document Upload")
400
  uploaded_files = st.file_uploader(
@@ -413,12 +829,9 @@ with st.sidebar:
413
  πŸ”Ή **Global Domain Support**: Works across all industries
414
  πŸ”Ή **Advanced ATS Optimization**: 85% better callback rates
415
  πŸ”Ή **Real-time Market Insights**: June 2025 standards
 
416
  """)
417
 
418
- # Set API key
419
- if api_key:
420
- genai.configure(api_key=api_key)
421
-
422
  # Main Interface
423
  st.markdown("### πŸ“ Job Description Input")
424
  input_text = st.text_area(
@@ -468,47 +881,72 @@ if analysis_triggered:
468
  else:
469
  # Process analysis
470
  with st.spinner("πŸ”„ Analyzing with advanced AI algorithms..."):
471
- pdf_content = get_pdf_text(uploaded_files)
472
 
473
- # Create consistency hash
474
- prompt_type = "evaluate" if evaluate_btn else "improve" if improve_btn else "keywords" if keywords_btn else "match" if match_btn else "executive" if executive_btn else "transition" if transition_btn else "custom"
475
- consistency_hash = create_consistency_hash(pdf_content, input_text, prompt_type)
476
 
477
- # Select appropriate prompt
478
  if evaluate_btn:
479
- prompt = SPECIALIZED_PROMPTS["evaluate_resume"]
480
  elif improve_btn:
481
- prompt = SPECIALIZED_PROMPTS["improve_skills"]
482
  elif keywords_btn:
483
- prompt = SPECIALIZED_PROMPTS["missing_keywords"]
484
  elif match_btn:
485
- prompt = SPECIALIZED_PROMPTS["percentage_match"]
486
  elif executive_btn:
487
- prompt = SPECIALIZED_PROMPTS["executive_assessment"]
488
  elif transition_btn:
489
- prompt = SPECIALIZED_PROMPTS["career_transition"]
490
  elif query_btn:
491
- prompt = f"{SPECIALIZED_PROMPTS['answer_query']}\n\nSPECIFIC QUERY: {custom_query}"
492
-
493
- # Generate response
494
- response = get_consistent_gemini_response(
495
- selected_model, prompt, pdf_content, input_text, consistency_hash
496
- )
497
 
498
- # Display results
499
- st.markdown("## πŸ“‹ Analysis Results")
500
- st.markdown(f"**Consistency ID:** `{consistency_hash[:8]}`")
501
- st.markdown("---")
502
- st.markdown(response)
503
-
504
- # Additional insights
505
- st.markdown("### πŸ’‘ Pro Tips")
506
- st.info("""
507
- πŸ”Ή **Consistency**: Running the same analysis will yield identical results
508
- πŸ”Ή **Optimization**: Use keyword suggestions to improve ATS compatibility
509
- πŸ”Ή **Multi-Domain**: This system works across all industries and roles
510
- πŸ”Ή **Latest Standards**: Analysis based on June 2025 best practices
511
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
 
513
  # Footer
514
  st.markdown("---")
@@ -516,5 +954,10 @@ st.markdown("""
516
  <div style="text-align: center; color: #666;">
517
  <p>πŸš€ Ultimate Smart ATS System 2025 | Powered by Advanced AI | Consistent β€’ Reliable β€’ Universal</p>
518
  <p>Built with cutting-edge strategies for maximum ATS compatibility and career success</p>
 
519
  </div>
520
- """, unsafe_allow_html=True)
 
 
 
 
 
3
 
4
  import streamlit as st
5
  import os
6
+ import re
7
+ import tempfile
8
+ import sqlite3
9
  import hashlib
10
  import json
11
+ import time
12
+ import pickle
13
  from datetime import datetime
14
+ from pathlib import Path
15
+ from functools import wraps
16
+ from PyPDF2 import PdfReader
17
+ import google.generativeai as genai
18
+ from dotenv import load_dotenv
19
+
20
+ # Optional imports with fallbacks
21
+ try:
22
+ import pdfplumber
23
+ HAS_PDFPLUMBER = True
24
+ except ImportError:
25
+ HAS_PDFPLUMBER = False
26
+
27
+ try:
28
+ import docx
29
+ HAS_DOCX = True
30
+ except ImportError:
31
+ HAS_DOCX = False
32
+
33
+ try:
34
+ import tiktoken
35
+ HAS_TIKTOKEN = True
36
+ except ImportError:
37
+ HAS_TIKTOKEN = False
38
 
39
  # Loading the .env keys
40
  load_dotenv()
41
 
42
+ # Create cache directory
43
+ CACHE_DIR = Path("ats_cache")
44
+ CACHE_DIR.mkdir(exist_ok=True)
45
 
46
+ # MASTER UNIVERSAL SYSTEM PROMPT - Designed for Maximum Consistency & Global Applicability
47
  UNIVERSAL_MASTER_PROMPT = """
48
  You are the ULTIMATE ATS OPTIMIZATION ENGINE 3.0 - A state-of-the-art AI system designed to provide CONSISTENT, PRECISE, and GLOBALLY APPLICABLE resume analysis across ALL industries, roles, and experience levels.
49
 
 
140
  **πŸ† FINAL VERDICT:**
141
  [EXCEPTIONAL 90-100 | STRONG 75-89 | GOOD 60-74 | DEVELOPING 45-59 | NEEDS WORK <45]
142
 
 
 
 
 
 
 
 
 
 
 
 
143
  **CONSISTENCY GUARANTEES:**
144
  - Same resume + same job description = identical analysis (Β±2 points variation max)
145
  - Standardized language and terminology across all evaluations
146
  - Reproducible scoring methodology regardless of domain
147
  - Time-consistent results (same analysis today and tomorrow)
 
 
 
 
 
 
 
 
148
  """
149
 
150
  # Specialized prompts that extend the master prompt for specific use cases
151
  SPECIALIZED_PROMPTS = {
152
  "evaluate_resume": f"""
153
  {UNIVERSAL_MASTER_PROMPT}
 
154
  **SPECIFIC TASK: COMPREHENSIVE RESUME EVALUATION**
155
  Apply the Universal Evaluation Framework above to provide a complete assessment.
156
  Focus on overall candidacy evaluation with balanced perspective on strengths and development areas.
 
159
 
160
  "improve_skills": f"""
161
  {UNIVERSAL_MASTER_PROMPT}
 
162
  **SPECIFIC TASK: SKILL ENHANCEMENT STRATEGY**
163
  After completing the standard evaluation, provide additional guidance:
 
164
  **πŸ“ˆ SKILL DEVELOPMENT ROADMAP:**
165
  - **Immediate Actions (0-3 months):** Quick wins and foundational improvements
166
  - **Short-term Goals (3-12 months):** Structured learning and certification paths
167
  - **Long-term Vision (1-3 years):** Strategic career advancement opportunities
 
168
  **πŸŽ“ LEARNING RESOURCES:**
169
  - Recommended courses, certifications, and training programs
170
  - Industry conferences and networking opportunities
171
  - Practical projects and portfolio development suggestions
 
172
  Focus on actionable, measurable improvement strategies with clear timelines.
173
  """,
174
 
175
  "missing_keywords": f"""
176
  {UNIVERSAL_MASTER_PROMPT}
 
177
  **SPECIFIC TASK: ATS KEYWORD OPTIMIZATION**
178
  After completing the standard evaluation, provide enhanced keyword analysis:
 
179
  **πŸ” ADVANCED KEYWORD ANALYSIS:**
180
  - **CRITICAL MISSING (High Impact):** Essential terms significantly affecting ATS ranking
181
  - **IMPORTANT ADDITIONS (Medium Impact):** Valuable terms improving visibility
182
  - **OPTIMIZATION OPPORTUNITIES (Low Impact):** Supplementary terms for comprehensive coverage
 
183
  **πŸ“ INTEGRATION STRATEGY:**
184
  - Specific resume sections for keyword placement
185
  - Natural integration techniques avoiding keyword stuffing
186
  - Industry-appropriate phrasing and terminology
 
187
  **πŸ€– ATS COMPATIBILITY SCORE:** [Detailed breakdown of parsing efficiency]
188
  """,
189
 
190
  "percentage_match": f"""
191
  {UNIVERSAL_MASTER_PROMPT}
 
192
  **SPECIFIC TASK: PRECISE MATCHING ANALYSIS**
193
  Provide the standard evaluation with enhanced quantitative focus:
 
194
  **πŸ“Š DETAILED SCORING BREAKDOWN:**
195
  Present exact point allocation for each category with clear justification.
196
  Include competitive benchmarking and market positioning analysis.
197
  Provide specific improvement strategies for 10-15% score increase.
 
198
  **🎯 MATCH PERCENTAGE: [XX%]**
199
  Tier Classification with detailed rationale and next steps.
200
  """,
201
 
202
  "answer_query": f"""
203
  {UNIVERSAL_MASTER_PROMPT}
 
204
  **SPECIFIC TASK: EXPERT CONSULTATION**
205
  Apply domain expertise to answer the specific query while considering:
206
  - Resume content and job description context
207
  - Industry best practices and current market trends
208
  - Practical, actionable guidance
209
  - Evidence-based recommendations
 
210
  Provide thorough, well-researched responses with specific examples and multiple solution approaches when applicable.
211
  """,
212
 
213
  "executive_assessment": f"""
214
  {UNIVERSAL_MASTER_PROMPT}
 
215
  **SPECIFIC TASK: EXECUTIVE-LEVEL EVALUATION**
216
  Apply enhanced criteria for senior leadership positions:
 
217
  **πŸ‘” EXECUTIVE COMPETENCY FRAMEWORK:**
218
  - Strategic thinking and vision development
219
  - Change management and transformation leadership
220
  - Financial acumen and business impact
221
  - Board readiness and governance experience
 
222
  **πŸ“ˆ LEADERSHIP IMPACT ANALYSIS:**
223
  - Quantifiable business results and achievements
224
  - Market expansion and competitive positioning
225
  - Organizational culture and talent development
226
  - Crisis leadership and resilience
 
227
  Provide insights suitable for C-suite and board-level discussions.
228
  """,
229
 
230
  "career_transition": f"""
231
  {UNIVERSAL_MASTER_PROMPT}
 
232
  **SPECIFIC TASK: CAREER PIVOT ANALYSIS**
233
  Evaluate career change feasibility with:
 
234
  **πŸ”„ TRANSITION ASSESSMENT:**
235
  - Transferable skills mapping across industries
236
  - Market positioning strategy for career change
237
  - Risk mitigation and success probability analysis
238
  - Timeline and milestone planning
 
239
  **🎯 TRANSITION ROADMAP:**
240
  - Phase-wise transition strategy
241
  - Skill development priorities
242
  - Network building and industry immersion plan
 
243
  Provide strategic guidance maximizing transition success while minimizing career risks.
244
  """
245
  }
 
254
  }
255
 
256
  # Model options optimized for consistency and performance
257
+ MODEL_FALLBACK_CHAIN = [
258
+ "gemini-2.0-flash-exp",
259
+ "gemini-1.5-pro",
260
+ "gemini-1.5-flash",
261
+ "gemini-pro"
262
  ]
263
 
264
+ # Rate limiting decorator
265
+ def rate_limit(min_interval=2):
266
+ def decorator(func):
267
+ last_called = [0]
268
+ @wraps(func)
269
+ def wrapper(*args, **kwargs):
270
+ elapsed = time.time() - last_called[0]
271
+ left_to_wait = min_interval - elapsed
272
+ if left_to_wait > 0:
273
+ time.sleep(left_to_wait)
274
+ result = func(*args, **kwargs)
275
+ last_called[0] = time.time()
276
+ return result
277
+ return wrapper
278
+ return decorator
279
+
280
+ # Cache management functions
281
+ def init_cache():
282
+ """Initialize SQLite cache for consistency"""
283
+ conn = sqlite3.connect(CACHE_DIR / "ats_cache.db")
284
+ cursor = conn.cursor()
285
+ cursor.execute("""
286
+ CREATE TABLE IF NOT EXISTS analysis_cache (
287
+ hash_key TEXT PRIMARY KEY,
288
+ response TEXT,
289
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
290
+ model_used TEXT
291
+ )
292
+ """)
293
+ conn.commit()
294
+ conn.close()
295
+
296
+ def get_cached_response(consistency_hash, model_id):
297
+ """Get cached response if available"""
298
+ try:
299
+ conn = sqlite3.connect(CACHE_DIR / "ats_cache.db")
300
+ cursor = conn.cursor()
301
+ cursor.execute(
302
+ "SELECT response FROM analysis_cache WHERE hash_key = ? AND model_used = ?",
303
+ (consistency_hash, model_id)
304
+ )
305
+ result = cursor.fetchone()
306
+ conn.close()
307
+ return result[0] if result else None
308
+ except:
309
+ return None
310
+
311
+ def cache_response(consistency_hash, response, model_id):
312
+ """Cache the response for future use"""
313
+ try:
314
+ conn = sqlite3.connect(CACHE_DIR / "ats_cache.db")
315
+ cursor = conn.cursor()
316
+ cursor.execute(
317
+ "INSERT OR REPLACE INTO analysis_cache (hash_key, response, model_used) VALUES (?, ?, ?)",
318
+ (consistency_hash, response, model_id)
319
+ )
320
+ conn.commit()
321
+ conn.close()
322
+ except Exception as e:
323
+ st.warning(f"Cache save failed: {e}")
324
+
325
+ # Token estimation and content optimization
326
+ def estimate_tokens(text, model="gpt-3.5-turbo"):
327
+ """Estimate token count for text"""
328
+ if HAS_TIKTOKEN:
329
+ try:
330
+ encoding = tiktoken.encoding_for_model(model)
331
+ return len(encoding.encode(text))
332
+ except:
333
+ pass
334
+ # Fallback estimation: roughly 4 characters per token
335
+ return len(text) // 4
336
+
337
+ def optimize_content_length(resume_text, job_description, max_resume_tokens=2000, max_job_tokens=1500):
338
+ """Optimize content length to stay within token limits"""
339
+
340
+ # Prioritize key sections in resume
341
+ resume_sections = {
342
+ 'experience': [],
343
+ 'skills': [],
344
+ 'education': [],
345
+ 'summary': []
346
+ }
347
+
348
+ # Simple section detection
349
+ lines = resume_text.split('\n')
350
+ current_section = 'summary'
351
+
352
+ for line in lines:
353
+ line_lower = line.lower().strip()
354
+ if any(keyword in line_lower for keyword in ['experience', 'work', 'employment']):
355
+ current_section = 'experience'
356
+ elif any(keyword in line_lower for keyword in ['skills', 'technical', 'competencies']):
357
+ current_section = 'skills'
358
+ elif any(keyword in line_lower for keyword in ['education', 'academic', 'degree']):
359
+ current_section = 'education'
360
+
361
+ if line.strip():
362
+ resume_sections[current_section].append(line)
363
+
364
+ # Build optimized resume content
365
+ optimized_resume = []
366
+
367
+ # Add summary (first 300 chars)
368
+ if resume_sections['summary']:
369
+ summary_text = '\n'.join(resume_sections['summary'][:5])
370
+ optimized_resume.append(f"PROFESSIONAL SUMMARY:\n{summary_text[:300]}")
371
+
372
+ # Add experience (prioritize recent)
373
+ if resume_sections['experience']:
374
+ exp_text = '\n'.join(resume_sections['experience'][:15])
375
+ optimized_resume.append(f"WORK EXPERIENCE:\n{exp_text[:800]}")
376
+
377
+ # Add skills
378
+ if resume_sections['skills']:
379
+ skills_text = '\n'.join(resume_sections['skills'][:8])
380
+ optimized_resume.append(f"SKILLS:\n{skills_text[:400]}")
381
+
382
+ # Add education
383
+ if resume_sections['education']:
384
+ edu_text = '\n'.join(resume_sections['education'][:5])
385
+ optimized_resume.append(f"EDUCATION:\n{edu_text[:200]}")
386
+
387
+ optimized_resume_text = '\n\n'.join(optimized_resume)
388
+
389
+ # Ensure we're within token limits
390
+ resume_tokens = estimate_tokens(optimized_resume_text)
391
+ if resume_tokens > max_resume_tokens:
392
+ # Truncate if still too long
393
+ chars_per_token = len(optimized_resume_text) / resume_tokens
394
+ max_chars = int(max_resume_tokens * chars_per_token)
395
+ optimized_resume_text = optimized_resume_text[:max_chars] + "... [truncated]"
396
+
397
+ # Optimize job description
398
+ job_lines = job_description.split('\n')
399
+ important_lines = []
400
+
401
+ for line in job_lines:
402
+ line_lower = line.lower()
403
+ # Prioritize lines with key information
404
+ if any(keyword in line_lower for keyword in [
405
+ 'require', 'must', 'essential', 'experience', 'skill',
406
+ 'qualification', 'bachelor', 'master', 'year', 'certification'
407
+ ]):
408
+ important_lines.append(line)
409
+ elif line.strip() and len(important_lines) < 20:
410
+ important_lines.append(line)
411
+
412
+ optimized_job = '\n'.join(important_lines)
413
+
414
+ # Ensure job description is within limits
415
+ job_tokens = estimate_tokens(optimized_job)
416
+ if job_tokens > max_job_tokens:
417
+ chars_per_token = len(optimized_job) / job_tokens
418
+ max_chars = int(max_job_tokens * chars_per_token)
419
+ optimized_job = optimized_job[:max_chars] + "... [truncated]"
420
+
421
+ return optimized_resume_text, optimized_job
422
+
423
  def create_consistency_hash(resume_text, job_description, prompt_type):
424
  """Create a hash for identical inputs to ensure consistent outputs"""
425
  content = f"{resume_text[:1000]}{job_description[:1000]}{prompt_type}"
426
  return hashlib.md5(content.encode()).hexdigest()
427
 
428
+ def get_available_model():
429
+ """Get the first available model from the fallback chain"""
430
+ for model in MODEL_FALLBACK_CHAIN:
431
+ try:
432
+ test_model = genai.GenerativeModel(
433
+ model,
434
+ safety_settings={
435
+ genai.types.HarmCategory.HARM_CATEGORY_HARASSMENT: genai.types.HarmBlockThreshold.BLOCK_NONE,
436
+ genai.types.HarmCategory.HARM_CATEGORY_HATE_SPEECH: genai.types.HarmBlockThreshold.BLOCK_NONE,
437
+ genai.types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: genai.types.HarmBlockThreshold.BLOCK_NONE,
438
+ genai.types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: genai.types.HarmBlockThreshold.BLOCK_NONE,
439
+ }
440
+ )
441
+ # Test with a simple prompt
442
+ test_response = test_model.generate_content(
443
+ "Say 'OK'",
444
+ generation_config=genai.types.GenerationConfig(
445
+ temperature=0.1,
446
+ max_output_tokens=10
447
+ )
448
+ )
449
+ if test_response.text:
450
+ return model
451
+ except Exception:
452
+ continue
453
+
454
+ raise Exception("No available Gemini models found")
455
+
456
+ @rate_limit(min_interval=2)
457
  def get_consistent_gemini_response(model_id, prompt, pdf_content, input_text, consistency_hash):
458
+ """Enhanced response generation with robust error handling"""
459
  try:
460
+ model = genai.GenerativeModel(
461
+ model_id,
462
+ safety_settings={
463
+ genai.types.HarmCategory.HARM_CATEGORY_HARASSMENT: genai.types.HarmBlockThreshold.BLOCK_NONE,
464
+ genai.types.HarmCategory.HARM_CATEGORY_HATE_SPEECH: genai.types.HarmBlockThreshold.BLOCK_NONE,
465
+ genai.types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: genai.types.HarmBlockThreshold.BLOCK_NONE,
466
+ genai.types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: genai.types.HarmBlockThreshold.BLOCK_NONE,
467
+ }
468
+ )
469
 
470
  # Add consistency instruction to prompt
471
  enhanced_prompt = f"""
 
474
  **CONSISTENCY PROTOCOL ACTIVE:**
475
  Session ID: {consistency_hash}
476
  Evaluation Date: {datetime.now().strftime('%Y-%m-%d')}
 
477
  Apply identical methodology and scoring for consistent results.
478
  Use deterministic analysis patterns and standardized language.
479
+
480
+ **RESUME CONTENT:**
481
+ {pdf_content[:3000]}
482
+
483
+ **JOB DESCRIPTION:**
484
+ {input_text[:2000]}
485
  """
486
 
487
  response = model.generate_content(
488
+ enhanced_prompt,
489
  generation_config=genai.types.GenerationConfig(**GENERATION_CONFIG)
490
  )
491
+
492
+ # Enhanced error checking
493
+ if hasattr(response, 'candidates') and response.candidates:
494
+ candidate = response.candidates[0]
495
+
496
+ # Check finish reason
497
+ if hasattr(candidate, 'finish_reason'):
498
+ if candidate.finish_reason == 1: # STOP - Normal completion
499
+ return response.text if hasattr(response, 'text') and response.text else "Analysis completed but no content returned."
500
+ elif candidate.finish_reason == 2: # MAX_TOKENS
501
+ return "⚠️ Analysis truncated due to length. Please try with a shorter resume or job description."
502
+ elif candidate.finish_reason == 3: # SAFETY
503
+ return "⚠️ Content filtered for safety. Please review your input for any potentially problematic content."
504
+ elif candidate.finish_reason == 4: # RECITATION
505
+ return "⚠️ Content blocked due to recitation concerns. Please try rephrasing your input."
506
+ else:
507
+ return f"⚠️ Generation stopped with reason: {candidate.finish_reason}"
508
+
509
+ # Try to get text anyway
510
+ try:
511
+ return response.text if response.text else "No analysis content generated."
512
+ except:
513
+ return "Analysis completed but content could not be retrieved."
514
+
515
+ return "No response candidates generated. Please try again."
516
 
517
  except Exception as e:
518
  st.error(f"⚠️ Analysis Error: {str(e)}")
519
+
520
+ # Fallback with simpler model configuration
521
+ try:
522
+ simple_model = genai.GenerativeModel("gemini-pro")
523
+ simple_prompt = f"Analyze this resume against the job description:\n\nResume: {pdf_content[:1000]}\n\nJob: {input_text[:1000]}"
524
+
525
+ fallback_response = simple_model.generate_content(simple_prompt)
526
+ return f"⚠️ Using fallback analysis:\n\n{fallback_response.text}"
527
+ except:
528
+ return "Unable to complete analysis. Please check your API key, reduce content length, and try again."
529
+
530
+ def clean_extracted_text(text):
531
+ """Clean and format extracted text"""
532
+ # Remove excessive whitespace
533
+ text = re.sub(r'\n\s*\n\s*\n', '\n\n', text)
534
+ text = re.sub(r'[ \t]+', ' ', text)
535
+
536
+ # Fix common extraction issues
537
+ text = re.sub(r'([a-z])([A-Z])', r'\1 \2', text) # Add space before capitals
538
+ text = re.sub(r'(\w)([β€’Β·β–ͺβ–«])', r'\1 \2', text) # Space before bullets
539
+ text = re.sub(r'([β€’Β·β–ͺβ–«])(\w)', r'\1 \2', text) # Space after bullets
540
+
541
+ # Remove page markers
542
+ text = re.sub(r'--- Page \d+ ---', '', text)
543
+
544
+ # Normalize line endings
545
+ text = text.replace('\r\n', '\n').replace('\r', '\n')
546
+
547
+ # Remove empty lines at start and end
548
+ text = text.strip()
549
+
550
+ return text
551
 
552
+ def enhanced_pdf_processing(pdf_docs):
553
+ """Enhanced PDF processing with better text extraction and formatting"""
554
  text = ""
555
+
556
+ for doc in pdf_docs:
557
+ try:
558
  if doc.name.endswith(".pdf"):
559
+ # Save uploaded file temporarily
560
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file:
561
+ tmp_file.write(doc.getvalue())
562
+ tmp_path = tmp_file.name
563
+
564
  try:
565
+ # Try multiple extraction methods
566
+ pdf_reader = PdfReader(tmp_path)
567
+ extracted_text = ""
568
+
569
+ for page_num, page in enumerate(pdf_reader.pages):
570
+ page_text = page.extract_text()
571
+
572
+ # Clean up common PDF extraction issues
573
+ page_text = re.sub(r'\s+', ' ', page_text) # Normalize whitespace
574
+ page_text = re.sub(r'([a-z])([A-Z])', r'\1 \2', page_text) # Add spaces between words
575
+
576
+ extracted_text += f"\n--- Page {page_num + 1} ---\n{page_text}\n"
577
+
578
+ # If extraction is poor, try alternative method
579
+ if len(extracted_text.strip()) < 100 and HAS_PDFPLUMBER:
580
+ try:
581
+ with pdfplumber.open(tmp_path) as pdf:
582
+ for page in pdf.pages:
583
+ page_text = page.extract_text()
584
+ if page_text:
585
+ extracted_text += page_text + "\n"
586
+ except Exception:
587
+ pass
588
+
589
+ text += extracted_text
590
+
591
+ finally:
592
+ # Clean up temporary file
593
+ os.unlink(tmp_path)
594
+
595
+ elif doc.name.endswith(".docx") and HAS_DOCX:
596
+ try:
597
+ # Save uploaded file temporarily
598
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp_file:
599
+ tmp_file.write(doc.getvalue())
600
+ tmp_path = tmp_file.name
601
+
602
+ try:
603
+ doc_reader = docx.Document(tmp_path)
604
+
605
+ # Extract paragraphs
606
+ for para in doc_reader.paragraphs:
607
+ if para.text.strip():
608
+ text += para.text + "\n"
609
+
610
+ # Extract tables
611
+ for table in doc_reader.tables:
612
+ for row in table.rows:
613
+ row_text = " | ".join([cell.text.strip() for cell in row.cells])
614
+ if row_text.strip():
615
+ text += row_text + "\n"
616
+
617
+ finally:
618
+ os.unlink(tmp_path)
619
+
620
+ except Exception as e:
621
+ st.error(f"πŸ“‹ Error processing DOCX {doc.name}: {str(e)}")
622
+
623
+ except Exception as e:
624
+ st.error(f"πŸ“„ Error processing {doc.name}: {str(e)}")
625
+ continue
626
 
627
+ # Clean and format the extracted text
628
+ text = clean_extracted_text(text)
629
  return text
630
 
631
+ def validate_resume_content(text):
632
+ """Validate that the extracted text looks like a resume"""
633
+ text_lower = text.lower()
634
+
635
+ # Check for common resume indicators
636
+ resume_indicators = [
637
+ 'experience', 'education', 'skills', 'work', 'employment',
638
+ 'university', 'college', 'degree', 'certification', 'project',
639
+ 'email', 'phone', 'address', 'linkedin'
640
+ ]
641
+
642
+ found_indicators = sum(1 for indicator in resume_indicators if indicator in text_lower)
643
+
644
+ if found_indicators < 3:
645
+ st.warning("⚠️ The uploaded file may not be a resume. Please verify the content.")
646
+ return False
647
+
648
+ if len(text.strip()) < 200:
649
+ st.warning("⚠️ The extracted text seems too short. Please check your file.")
650
+ return False
651
+
652
+ return True
653
+
654
+ def validate_configuration():
655
+ """Validate system configuration"""
656
+ issues = []
657
+
658
+ # Check API key
659
+ if not os.getenv("GOOGLE_API_KEY") and not st.session_state.get("api_key"):
660
+ issues.append("❌ Google API Key not configured")
661
+
662
+ # Check optional packages
663
+ if not HAS_DOCX:
664
+ issues.append("⚠️ Optional: Install python-docx for better DOCX support (pip install python-docx)")
665
+
666
+ if not HAS_PDFPLUMBER:
667
+ issues.append("⚠️ Optional: Install pdfplumber for better PDF extraction (pip install pdfplumber)")
668
+
669
+ if not HAS_TIKTOKEN:
670
+ issues.append("⚠️ Optional: Install tiktoken for better token estimation (pip install tiktoken)")
671
+
672
+ return issues
673
+
674
+ @st.cache_data
675
+ def load_system_status():
676
+ """Load and cache system status"""
677
+ issues = validate_configuration()
678
+ return issues
679
+
680
+ def perform_enhanced_analysis(resume_text, job_description, analysis_type, custom_query=None):
681
+ """Main analysis function with all improvements"""
682
+
683
+ # Initialize cache
684
+ init_cache()
685
+
686
+ # Optimize content length
687
+ optimized_resume, optimized_job = optimize_content_length(resume_text, job_description)
688
+
689
+ # Create consistency hash
690
+ consistency_hash = create_consistency_hash(optimized_resume, optimized_job, analysis_type)
691
+
692
+ # Try to get from cache first
693
+ model_id = get_available_model()
694
+ cached_response = get_cached_response(consistency_hash, model_id)
695
+
696
+ if cached_response:
697
+ st.success("⚑ Retrieved from cache for consistency")
698
+ return cached_response, consistency_hash
699
+
700
+ # Select prompt
701
+ prompt_map = {
702
+ "evaluate": "evaluate_resume",
703
+ "improve": "improve_skills",
704
+ "keywords": "missing_keywords",
705
+ "match": "percentage_match",
706
+ "executive": "executive_assessment",
707
+ "transition": "career_transition",
708
+ "custom": "answer_query"
709
+ }
710
+
711
+ base_prompt = SPECIALIZED_PROMPTS[prompt_map.get(analysis_type, "evaluate_resume")]
712
+
713
+ if analysis_type == "custom" and custom_query:
714
+ base_prompt = f"{base_prompt}\n\nSPECIFIC QUERY: {custom_query}"
715
+
716
+ # Generate response
717
+ response = get_consistent_gemini_response(
718
+ model_id, base_prompt, optimized_resume, optimized_job, consistency_hash
719
+ )
720
+
721
+ # Cache the response
722
+ if response and not response.startswith("⚠️"):
723
+ cache_response(consistency_hash, response, model_id)
724
+
725
+ return response, consistency_hash
726
+
727
  # Streamlit App Configuration
728
  st.set_page_config(
729
  page_title="Ultimate Smart ATS System 2025",
 
769
  display: inline-block;
770
  margin: 0.5rem 0;
771
  }
772
+ .stButton > button {
773
+ height: 3rem;
774
+ font-weight: 600;
775
+ }
776
  </style>
777
  """, unsafe_allow_html=True)
778
 
 
785
  </div>
786
  """, unsafe_allow_html=True)
787
 
788
+ # Check system status
789
+ config_issues = load_system_status()
790
+
791
+ if config_issues:
792
+ with st.expander("⚠️ System Status", expanded=any("❌" in issue for issue in config_issues)):
793
+ for issue in config_issues:
794
+ if "❌" in issue:
795
+ st.error(issue)
796
+ else:
797
+ st.info(issue)
798
+
799
  # Sidebar Configuration
800
  with st.sidebar:
801
  st.markdown("### πŸ”‘ Configuration")
802
  st.markdown("[Get your Google API Key](https://aistudio.google.com/app/apikey)")
803
 
804
  api_key = st.text_input("πŸ” Google API Key", type="password", help="Your Gemini API key for AI analysis")
805
+ st.session_state["api_key"] = api_key
806
 
807
+ if api_key:
808
+ try:
809
+ genai.configure(api_key=api_key)
810
+ model_id = get_available_model()
811
+ st.success(f"βœ… Connected to {model_id}")
812
+ except Exception as e:
813
+ st.error(f"❌ API Key Error: {str(e)}")
814
 
815
  st.markdown("### πŸ“‚ Document Upload")
816
  uploaded_files = st.file_uploader(
 
829
  πŸ”Ή **Global Domain Support**: Works across all industries
830
  πŸ”Ή **Advanced ATS Optimization**: 85% better callback rates
831
  πŸ”Ή **Real-time Market Insights**: June 2025 standards
832
+ πŸ”Ή **Smart Caching**: Instant results for repeated analyses
833
  """)
834
 
 
 
 
 
835
  # Main Interface
836
  st.markdown("### πŸ“ Job Description Input")
837
  input_text = st.text_area(
 
881
  else:
882
  # Process analysis
883
  with st.spinner("πŸ”„ Analyzing with advanced AI algorithms..."):
884
+ pdf_content = enhanced_pdf_processing(uploaded_files)
885
 
886
+ # Validate content
887
+ if not validate_resume_content(pdf_content):
888
+ st.warning("⚠️ Please verify that your uploaded file is a valid resume.")
889
 
890
+ # Determine analysis type
891
  if evaluate_btn:
892
+ analysis_type = "evaluate"
893
  elif improve_btn:
894
+ analysis_type = "improve"
895
  elif keywords_btn:
896
+ analysis_type = "keywords"
897
  elif match_btn:
898
+ analysis_type = "match"
899
  elif executive_btn:
900
+ analysis_type = "executive"
901
  elif transition_btn:
902
+ analysis_type = "transition"
903
  elif query_btn:
904
+ analysis_type = "custom"
 
 
 
 
 
905
 
906
+ try:
907
+ # Perform analysis
908
+ response, consistency_hash = perform_enhanced_analysis(
909
+ pdf_content, input_text, analysis_type, custom_query
910
+ )
911
+
912
+ # Display results
913
+ st.markdown("## πŸ“‹ Analysis Results")
914
+
915
+ # Show metadata
916
+ col1, col2 = st.columns(2)
917
+ with col1:
918
+ st.markdown(f"**Consistency ID:** `{consistency_hash[:8]}`")
919
+ with col2:
920
+ st.markdown(f"**Analysis Type:** {analysis_type.title()}")
921
+
922
+ st.markdown("---")
923
+ st.markdown(response)
924
+
925
+ # Additional insights
926
+ st.markdown("### πŸ’‘ Pro Tips")
927
+ st.info("""
928
+ πŸ”Ή **Consistency**: Running the same analysis will yield identical results
929
+ πŸ”Ή **Optimization**: Use keyword suggestions to improve ATS compatibility
930
+ πŸ”Ή **Multi-Domain**: This system works across all industries and roles
931
+ πŸ”Ή **Latest Standards**: Analysis based on June 2025 best practices
932
+ πŸ”Ή **Caching**: Repeated analyses are retrieved instantly from cache
933
+ """)
934
+
935
+ # Show content optimization info
936
+ if st.checkbox("πŸ” Show Content Optimization Details"):
937
+ optimized_resume, optimized_job = optimize_content_length(pdf_content, input_text)
938
+
939
+ col1, col2 = st.columns(2)
940
+ with col1:
941
+ st.metric("Resume Tokens", estimate_tokens(optimized_resume))
942
+ st.metric("Original Resume Length", len(pdf_content))
943
+ with col2:
944
+ st.metric("Job Description Tokens", estimate_tokens(optimized_job))
945
+ st.metric("Original Job Length", len(input_text))
946
+
947
+ except Exception as e:
948
+ st.error(f"Analysis failed: {str(e)}")
949
+ st.info("Please try again with a shorter document or check your API key.")
950
 
951
  # Footer
952
  st.markdown("---")
 
954
  <div style="text-align: center; color: #666;">
955
  <p>πŸš€ Ultimate Smart ATS System 2025 | Powered by Advanced AI | Consistent β€’ Reliable β€’ Universal</p>
956
  <p>Built with cutting-edge strategies for maximum ATS compatibility and career success</p>
957
+ <small>Version 3.0 - Enhanced with Error Handling, Caching, and Content Optimization</small>
958
  </div>
959
+ """, unsafe_allow_html=True)
960
+
961
+ # Initialize cache on startup
962
+ if __name__ == "__main__":
963
+ init_cache()