jobs-monorepo/internal/openai
Elshimy Ziad Magdy Taha fcbe2f04f9 Collapse shared Go packages into the root module
internal/ and libs/ were split into 9 single-package Go modules, held
together by 22 replace directives across 7 go.mod files. The module
boundaries bought nothing: internal/dto, internal/browser and
internal/migrations were already plain packages in the root module and
worked fine.

Delete the 9 go.mod/go.sum pairs so those packages belong to the root
github.com/jobs-scraper module. Import paths are unchanged --
github.com/jobs-scraper/internal/domain resolves identically whether it
is its own module or a package inside the root module -- so no .go file
is touched by this commit.

Each deployable module now needs one require + one replace on the root
module instead of four to six:

  go.work entries:      14 -> 5
  replace directives:   22 -> 4
  go.mod files:         14 -> 5

Dependency versions are deliberately held at their previous pins. A bare
go mod tidy resolved several to latest once the per-package constraints
were gone (lib/pq 1.10.9 -> 1.12.3, amqp091-go 1.10.0 -> 1.13.0,
migrate 4.19.0 -> 4.19.1, go-openai 1.41.2 -> 1.42.0, genai
1.39.0 -> 1.66.0); all five are pinned back, since a structural refactor
should not move dependency versions.

Side effect worth noting: `go build ./...` at the repo root previously
matched only 2 packages, because everything else sat behind a module
boundary. It now covers all 12 shared packages, so the build and vet
steps in .forgejo/workflows/ actually exercise the shared code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 17:27:10 +05:00
..
interface.go fix errors and restructure project 2026-01-26 17:33:48 +05:00
openai.go fix errors and restructure project 2026-01-26 17:33:48 +05:00
README.md fix errors and restructure project 2026-01-26 17:33:48 +05:00

OpenAI Service

This package provides an OpenAI-powered service for job analysis and CV generation using the official OpenAI Go SDK.

Features

  • Job Analysis: Analyze job descriptions against CVs to determine fit and provide recommendations
  • CV Generation: Create tailored CVs based on job descriptions
  • Cover Letter Generation: Generate personalized cover letters

Setup

  1. Install the OpenAI Go SDK:
go get github.com/sashabaranov/go-openai
  1. Set your OpenAI API key as an environment variable:
export OPENAI_API_KEY="your-api-key-here"
  1. (Optional) Set a custom base URL:
export OPENAI_BASE_URL="https://your-custom-endpoint.com/v1"

Usage

Basic Job Analysis

package main

import (
    "fmt"
    "os"
    
    "github.com/jobs-scraper/internal/domain"
    "github.com/jobs-scraper/internal/openai"
)

func main() {
    // Create service
    apiKey := os.Getenv("OPENAI_API_KEY")
    service := openai.NewOpenAIService(apiKey, "gpt-4o-mini")
    
    // Prepare job description
    jobDesc := domain.JobDescription{
        JobID:       1,
        Description: "Looking for a Go developer...",
        Criteria: map[string]string{
            "experience": "5+ years",
            "languages":  "Go, JavaScript",
        },
    }
    
    // Analyze job
    result, err := service.AnalyzeJobDescription(cv, jobDesc)
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("Should apply: %t\n", result.ShouldApply())
    fmt.Printf("Confidence: %d%%\n", result.ConfidenceScore)
}

Using Custom Base URL

You can configure a custom base URL in two ways:

Method 1: Environment Variable

export OPENAI_BASE_URL="https://api.openai-proxy.com/v1"
# Service will automatically use this URL
service := openai.NewOpenAIService(apiKey, "gpt-4o-mini")

Method 2: Direct Parameter

// Use a custom base URL directly
service := openai.NewOpenAIServiceWithBaseURL(apiKey, "gpt-4o-mini", "https://api.openai-proxy.com/v1")

// Or use Azure OpenAI
service := openai.NewOpenAIServiceWithBaseURL(apiKey, "gpt-4", "https://your-resource.openai.azure.com/")

Generate Tailored CV

tailoredCV, err := service.GenerateCV(originalCV, jobDesc)
if err != nil {
    panic(err)
}
fmt.Println(tailoredCV)

Generate Cover Letter

coverLetter, err := service.GenerateCoverLetter(cv, jobDesc, "Tech Company Inc")
if err != nil {
    panic(err)
}
fmt.Println(coverLetter)

Models

The service supports all OpenAI models. Common choices:

  • gpt-4o-mini - Cost-effective, good performance (default)
  • gpt-4o - Higher quality, more expensive
  • gpt-3.5-turbo - Fastest, most cost-effective

Environment Variables

  • OPENAI_API_KEY - Your OpenAI API key (required)
  • OPENAI_BASE_URL - Custom base URL for OpenAI API (optional)
  • OPENAI_MODEL - Default model to use (optional)

Response Structure

JobAnalysisResult

type JobAnalysisResult struct {
    Recommendation         string   // "apply" or "do_not_apply"
    ConfidenceScore        int      // 0-100
    MatchingSkills         []string
    MissingSkills          []string
    ExperienceMatch        string   // "excellent", "good", "fair", "poor"
    Summary                string
    ImprovementSuggestions []string
}

Error Handling

The service handles common errors:

  • API authentication issues
  • Rate limiting
  • Invalid JSON responses
  • Network timeouts

Always check for errors when calling service methods.

Testing

Run the example test:

cd internal/pkg/openai
go test -v

Make sure to set OPENAI_API_KEY environment variable before running tests that make actual API calls.