""" AI Service for Job Forge - Handles document generation and AI processing """ import structlog from typing import Dict, Optional import anthropic import openai from ..core.config import settings logger = structlog.get_logger() class AIService: def __init__(self): self.claude_client = None self.openai_client = None # Initialize Claude client if API key is available if settings.claude_api_key: self.claude_client = anthropic.Anthropic(api_key=settings.claude_api_key) # Initialize OpenAI client if API key is available if settings.openai_api_key: self.openai_client = openai.AsyncOpenAI(api_key=settings.openai_api_key) async def generate_cover_letter( self, job_description: str, company_name: str, role_title: str, user_name: str, user_resume: Optional[str] = None ) -> Dict[str, str]: """ Generate a personalized cover letter using AI """ try: # Construct the prompt prompt = f""" You are a professional career coach helping someone write a compelling cover letter. JOB DETAILS: - Company: {company_name} - Role: {role_title} - Job Description: {job_description} USER INFORMATION: - Name: {user_name} {f"- Resume/Background: {user_resume[:1000]}..." if user_resume else ""} TASK: Write a professional, personalized cover letter that: 1. Shows genuine interest in the specific role and company 2. Highlights relevant skills from the job description 3. Demonstrates understanding of the company's needs 4. Uses a professional but engaging tone 5. Is 3-4 paragraphs long 6. Includes a strong opening and closing Format the response as a complete cover letter without any meta-commentary. """ # Try Claude first, fallback to OpenAI if self.claude_client: logger.info("Generating cover letter with Claude") response = self.claude_client.messages.create( model="claude-3-haiku-20240307", max_tokens=1000, messages=[ {"role": "user", "content": prompt} ] ) content = response.content[0].text model_used = "claude-3-haiku" elif self.openai_client: logger.info("Generating cover letter with OpenAI") response = await self.openai_client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are a professional career coach helping write cover letters."}, {"role": "user", "content": prompt} ], max_tokens=1000, temperature=0.7 ) content = response.choices[0].message.content model_used = "gpt-3.5-turbo" else: # Fallback to template-based generation logger.warning("No AI API keys available, using template") content = self._generate_template_cover_letter( company_name, role_title, user_name, job_description ) model_used = "template" return { "content": content, "model_used": model_used, "prompt": prompt[:500] + "..." if len(prompt) > 500 else prompt } except Exception as e: logger.error("AI cover letter generation failed", error=str(e)) # Fallback to template content = self._generate_template_cover_letter( company_name, role_title, user_name, job_description ) return { "content": content, "model_used": "template-fallback", "prompt": "Template fallback due to AI service error" } async def generate_resume_optimization( self, current_resume: str, job_description: str, role_title: str ) -> Dict[str, str]: """ Optimize resume for specific job requirements """ try: prompt = f""" You are an expert resume writer helping optimize a resume for a specific job. CURRENT RESUME: {current_resume} TARGET JOB: - Role: {role_title} - Job Description: {job_description} TASK: Optimize this resume by: 1. Highlighting relevant skills mentioned in the job description 2. Reordering sections to emphasize most relevant experience 3. Using keywords from the job posting 4. Maintaining truthfulness - only reorganize/reword existing content 5. Keeping the same general structure and format Return the optimized resume without meta-commentary. """ if self.claude_client: response = self.claude_client.messages.create( model="claude-3-haiku-20240307", max_tokens=2000, messages=[ {"role": "user", "content": prompt} ] ) content = response.content[0].text model_used = "claude-3-haiku" elif self.openai_client: response = await self.openai_client.chat.completions.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are an expert resume writer."}, {"role": "user", "content": prompt} ], max_tokens=2000, temperature=0.5 ) content = response.choices[0].message.content model_used = "gpt-3.5-turbo" else: content = f"Resume optimization for {role_title}\n\n{current_resume}\n\n[AI optimization would be applied here with API keys configured]" model_used = "template" return { "content": content, "model_used": model_used, "prompt": prompt[:500] + "..." if len(prompt) > 500 else prompt } except Exception as e: logger.error("Resume optimization failed", error=str(e)) return { "content": f"Optimized Resume for {role_title}\n\n{current_resume}", "model_used": "template-fallback", "prompt": "Template fallback due to AI service error" } def _generate_template_cover_letter( self, company_name: str, role_title: str, user_name: str, job_description: str ) -> str: """ Generate a basic template cover letter when AI services are unavailable """ # Extract a few keywords from job description keywords = [] common_skills = ["python", "javascript", "react", "sql", "aws", "docker", "git", "api", "database"] for skill in common_skills: if skill.lower() in job_description.lower(): keywords.append(skill.title()) skills_text = f" with expertise in {', '.join(keywords[:3])}" if keywords else "" return f"""Dear Hiring Manager, I am writing to express my strong interest in the {role_title} position at {company_name}. Based on the job description, I am excited about the opportunity to contribute to your team{skills_text}. Your requirements align well with my background and experience. I am particularly drawn to this role because it represents an excellent opportunity to apply my skills in a dynamic environment while contributing to {company_name}'s continued success. I would welcome the opportunity to discuss how my experience and enthusiasm can benefit your team. Thank you for considering my application, and I look forward to hearing from you. Best regards, {user_name} --- [Generated by Job Forge AI Assistant - Configure API keys for enhanced personalization]""" # Create a singleton instance ai_service = AIService()