File size: 9,142 Bytes
4fd18a2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
"""Cover letter tool for generating personalized cover letters - letter.generate endpoint."""

from typing import Dict, Any

from ..services import LLMService, ProfileService


class CoverLetterTool:
    """Tool for generating personalized cover letters."""

    def __init__(self):
        self.llm_service = LLMService()
        self.profile_service = ProfileService()

    def generate(
        self, user_id: str, job_description: str, tone: str = "professional"
    ) -> Dict[str, Any]:
        """
        Generate a personalized cover letter using LLM.

        This is the main letter.generate endpoint that calls an LLM to create
        a short, personalized cover letter in any tone.

        Args:
            user_id: User identifier to access profile for personalization
            job_description: The job posting description to tailor the letter to
            tone: Tone of the cover letter
                  Options: "professional", "casual", "enthusiastic", "formal"
                  Default: "professional"

        Returns:
            Dict with generated cover letter and metadata:
            {
                "success": True,
                "cover_letter": "Dear Hiring Manager,\n\nI am writing to express...",
                "tone_used": "professional",
                "word_count": 245,
                "character_count": 1456,
                "estimated_reading_time": "1 minute"
            }
        """
        try:
            # Get user profile
            profile = self.profile_service.get_profile(user_id)
            if not profile:
                return {
                    "success": False,
                    "message": "User profile not found. Please create a profile first.",
                }

            # Validate tone
            valid_tones = ["professional", "casual", "enthusiastic", "formal"]
            if tone not in valid_tones:
                return {
                    "success": False,
                    "message": f"Invalid tone. Must be one of: {', '.join(valid_tones)}",
                }

            # Validate job description
            if not job_description or len(job_description.strip()) < 50:
                return {
                    "success": False,
                    "message": "Job description must be at least 50 characters long",
                }

            # Generate cover letter
            result = self.llm_service.generate_cover_letter(
                profile, job_description, tone
            )

            # Add additional metadata if successful
            if result.get("success") and result.get("cover_letter"):
                word_count = result.get("word_count", 0)
                result["estimated_reading_time"] = self._estimate_reading_time(
                    word_count
                )
                result["tips"] = self._get_cover_letter_tips(tone)

            return result

        except Exception as e:
            return {
                "success": False,
                "message": f"Error generating cover letter: {str(e)}",
            }

    def generate_multiple_tones(
        self, user_id: str, job_description: str, tones: list[str] = None
    ) -> Dict[str, Any]:
        """
        Generate cover letters in multiple tones for comparison.

        Args:
            user_id: User identifier
            job_description: Job posting description
            tones: List of tones to generate (default: ["professional", "enthusiastic"])

        Returns:
            Dict with multiple cover letters in different tones
        """
        if tones is None:
            tones = ["professional", "enthusiastic"]

        results = {}
        errors = []

        for tone in tones:
            result = self.generate(user_id, job_description, tone)
            if result.get("success"):
                results[tone] = result
            else:
                errors.append(f"{tone}: {result.get('message', 'Unknown error')}")

        if results:
            return {
                "success": True,
                "cover_letters": results,
                "tones_generated": list(results.keys()),
                "errors": errors if errors else None,
            }
        else:
            return {
                "success": False,
                "message": "Failed to generate any cover letters",
                "errors": errors,
            }

    def customize_for_company(
        self,
        user_id: str,
        job_description: str,
        company_info: str,
        tone: str = "professional",
    ) -> Dict[str, Any]:
        """
        Generate a cover letter with additional company-specific customization.

        Args:
            user_id: User identifier
            job_description: Job posting description
            company_info: Additional information about the company
            tone: Tone for the cover letter

        Returns:
            Dict with customized cover letter
        """
        try:
            # Enhance job description with company info
            enhanced_description = (
                f"{job_description}\n\nCompany Information:\n{company_info}"
            )

            # Generate the cover letter
            result = self.generate(user_id, enhanced_description, tone)

            if result.get("success"):
                result["customization"] = "Company-specific information included"

            return result

        except Exception as e:
            return {
                "success": False,
                "message": f"Error generating customized cover letter: {str(e)}",
            }

    def _estimate_reading_time(self, word_count: int) -> str:
        """Estimate reading time based on word count (average 200 words per minute)."""
        if word_count == 0:
            return "0 minutes"

        minutes = max(1, round(word_count / 200))
        if minutes == 1:
            return "1 minute"
        else:
            return f"{minutes} minutes"

    def _get_cover_letter_tips(self, tone: str) -> list[str]:
        """Get tone-specific tips for cover letters."""
        tips_by_tone = {
            "professional": [
                "Keep it concise and focused on achievements",
                "Use formal language and proper business format",
                "Highlight quantifiable results when possible",
            ],
            "casual": [
                "Show personality while remaining respectful",
                "Use conversational language but avoid slang",
                "Focus on cultural fit and team collaboration",
            ],
            "enthusiastic": [
                "Express genuine excitement for the role",
                "Use energetic language and positive adjectives",
                "Show passion for the company's mission",
            ],
            "formal": [
                "Follow strict business letter format",
                "Use traditional and respectful language",
                "Emphasize credentials and qualifications",
            ],
        }

        return tips_by_tone.get(
            tone, ["Tailor the letter to the specific job and company"]
        )

    def get_cover_letter_template(self, tone: str = "professional") -> Dict[str, Any]:
        """
        Get a basic cover letter template for the specified tone.

        Args:
            tone: Desired tone for the template

        Returns:
            Dict with template structure and guidelines
        """
        templates = {
            "professional": {
                "structure": [
                    "Header with your contact information",
                    "Date and employer contact information",
                    "Professional greeting",
                    "Opening paragraph: Position and brief introduction",
                    "Body paragraph 1: Relevant experience and skills",
                    "Body paragraph 2: Achievements and value proposition",
                    "Closing paragraph: Next steps and gratitude",
                    "Professional closing",
                ],
                "sample_opening": "I am writing to express my strong interest in the [Position Title] role at [Company Name].",
                "sample_closing": "I would welcome the opportunity to discuss how my experience can contribute to your team's success.",
            },
            "enthusiastic": {
                "structure": [
                    "Energetic opening that shows excitement",
                    "Passionate description of relevant experience",
                    "Connection to company mission and values",
                    "Enthusiastic closing with call to action",
                ],
                "sample_opening": "I am thrilled to apply for the [Position Title] position at [Company Name]!",
                "sample_closing": "I can't wait to bring my passion and skills to your amazing team!",
            },
        }

        return {
            "success": True,
            "tone": tone,
            "template": templates.get(tone, templates["professional"]),
            "tips": self._get_cover_letter_tips(tone),
        }