feat(cover): add cover letter name generation
This commit is contained in:
@@ -51,13 +51,13 @@ func Post(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Call chat and ask for cover letter nicely
|
||||
coverLetter, err := chatgpt.GenerateCoverLetter(templates[0].Template, data.Application)
|
||||
generatedCover, err := chatgpt.GenerateCoverLetter(templates[0].Template, data.Application)
|
||||
if err != nil {
|
||||
res.Error(c, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
res.Success(c, coverLetter)
|
||||
res.Success(c, generatedCover)
|
||||
}
|
||||
|
||||
func Put(c *gin.Context) {
|
||||
|
||||
@@ -10,9 +10,14 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type ResponseFormat struct {
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type ChatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []ChatMessage `json:"messages"`
|
||||
Model string `json:"model"`
|
||||
Messages []ChatMessage `json:"messages"`
|
||||
ResponseFormat *ResponseFormat `json:"response_format,omitempty"`
|
||||
}
|
||||
|
||||
type ChatMessage struct {
|
||||
@@ -20,40 +25,44 @@ type ChatMessage struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func GenerateCoverLetter(templateHTML string, jobHTML string) (string, error) {
|
||||
type GeneratedCover struct {
|
||||
Name string `json:"name"`
|
||||
Cover string `json:"cover"`
|
||||
}
|
||||
|
||||
func GenerateCoverLetter(templateHTML string, jobHTML string) (GeneratedCover, error) {
|
||||
apiKey := config.Env["CHATGPT_KEY"]
|
||||
if apiKey == "" {
|
||||
return "", errors.New("no API key chat gpt provided")
|
||||
return GeneratedCover{}, errors.New("no API key chat gpt provided")
|
||||
}
|
||||
|
||||
payload := ChatRequest{
|
||||
Model: "gpt-4o", // o4-mini
|
||||
ResponseFormat: &ResponseFormat{Type: "json_object"},
|
||||
Messages: []ChatMessage{
|
||||
{
|
||||
Role: "system",
|
||||
Content: `You are a helpful assistant that fills out cover letter templates in HTML format. Replace all <...> tags like <company>, <experience>, etc., with appropriate content based on the job application.`,
|
||||
Content: `You are a helpful assistant that fills out cover letter templates in HTML format and provides a name for it. Replace all <...> tags like <company>, <experience>, etc., with appropriate content based on the job application. You must respond with a JSON object with two keys: "name" for the cover letter title (e.g., "Cover Letter for a Software Engineer"), and "cover" for the filled HTML cover letter.`,
|
||||
},
|
||||
{
|
||||
Role: "user",
|
||||
Content: fmt.Sprintf(`Template:
|
||||
Content: fmt.Sprintf(`Template:
|
||||
%s
|
||||
|
||||
Job description:
|
||||
%s
|
||||
|
||||
Respond with ONLY the filled HTML cover letter.`, templateHTML, jobHTML),
|
||||
%s`, templateHTML, jobHTML),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
body, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return GeneratedCover{}, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", "https://api.openai.com/v1/chat/completions", bytes.NewBuffer(body))
|
||||
if err != nil {
|
||||
return "", err
|
||||
return GeneratedCover{}, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
@@ -62,7 +71,7 @@ Respond with ONLY the filled HTML cover letter.`, templateHTML, jobHTML),
|
||||
client := &http.Client{Timeout: 20 * time.Second}
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return GeneratedCover{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
@@ -75,12 +84,17 @@ Respond with ONLY the filled HTML cover letter.`, templateHTML, jobHTML),
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
|
||||
return "", err
|
||||
return GeneratedCover{}, err
|
||||
}
|
||||
|
||||
if len(result.Choices) == 0 {
|
||||
return "", fmt.Errorf("no response from GPT")
|
||||
return GeneratedCover{}, fmt.Errorf("no response from GPT")
|
||||
}
|
||||
|
||||
return result.Choices[0].Message.Content, nil
|
||||
var cover GeneratedCover
|
||||
if err := json.Unmarshal([]byte(result.Choices[0].Message.Content), &cover); err != nil {
|
||||
return GeneratedCover{}, fmt.Errorf("failed to parse GPT response: %w", err)
|
||||
}
|
||||
|
||||
return cover, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user