AI Driven CLI tool using Go

AI Driven CLI tool using Go

ยท

5 min read

Introduction

Hey There ๐Ÿ‘‹,
In this blog post, we'll create a practical CLI tool in Go that leverages OpenAI GPT API to generate personalized cold emails. By the end of this tutorial blog, you'll have a good understanding of CLI's and its integration with OpenAI API.

Prerequisites

To continue with the tutorial, you need to have Golang installed.

  • Golang

  • OpenAI API Key: log-in/Sign-up to Openai and create the API key.

Getting Started ๐Ÿ› 

Let's get started by creating the main project directory gpt-mail by using the following command.

mkdir gpt-mail //Creates a 'gpt-mail' directory
cd gpt-mail //Change directory to 'gpt-mail'

For building the CLI tool we'll be using the Cobra-cli Framework. For installing Cobra-CLI you can go to Cobra or run go install github.com/spf13/cobra-cli@latest in the terminal.

Now initialize a mod file. (If you publish a module, this must be a path from which your module can be downloaded by Go tools. That would be your code's repository.)

go mod init github.com/<username>/gpt-mail //<username> is your github username
Cobra-cli init

This command initializes the CLI and creates a main.go file along with cmd folder containing root.go.

Now, run the command Cobra-cli add generate, this will create a file generate.go in the cmd folder for the command generate.

Let's make a new file for the code that will execute after the command is called, for this create a folder lib and a new file email.go inside it.

Create a .env file in the root directory i.e. gpt-mail and save the OpenAI API Key that you created earlier in the file.

OPENAI_API_KEY=<YOUR_API_KEY>

Make the following changes in the root.go file.

package cmd

import (
    "os"

    "github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
    Use:   "gpt-mail",
    Short: "A AI-driven Tool for Generating Email",
}

func Execute() {
    err := rootCmd.Execute()
    if err != nil {
        os.Exit(1)
    }
}

func init() {
    rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

In root.go, function Execute gets called from main.go and it executes the rootCmd. Use is used to define the command to be used and Short and Long contains the information or description for the Command in short and long format respectively.

Update the variable generateCmd in the generate.go file with the following code,

var generateCmd = &cobra.Command{
    Use:   "generate",
    Short: "Command to Generate the Email",
    Run: func(cmd *cobra.Command, args []string) {
        res, err := lib.Email()

        if err != nil {
            log.Fatal(err)
        }

        fmt.Println("> Response: ")
        fmt.Println("")
        fmt.Println(res)
    },
}

Here, we are calling the function Email from the lib package and getting the response.

Let's write the code for the main feature of our CLI tool i.e. integrating with OpenAI API and getting the response. Add the following code in the email.go file created earlier,

package lib

import (
    "bufio"
    "context"
    "fmt"
    "log"
    "os"

    "github.com/joho/godotenv"
    "github.com/sashabaranov/go-openai"
)

func Email() (string, error) {

    godotenv.Load()

    fmt.Print("> Enter the Subject for the Email : ")
    reader := bufio.NewReader(os.Stdin)
    Subject, err := reader.ReadString('\n')
    if err != nil {
        log.Fatal(err)
    }

    fmt.Print("> Enter the Audience for the Email : ")
    Audience, err := reader.ReadString('\n')
    if err != nil {
        log.Fatal(err)
    }

    fmt.Print("> Enter the Purpose/Information for the Email : ")
    Purpose, err := reader.ReadString('\n')
    if err != nil {
        log.Fatal(err)
    }

    prompt := fmt.Sprintf("Subject: %s Audience: %s Purpose/Information: %s\n", Subject, Audience, Purpose)

    apiKey := os.Getenv("OPENAI_API_KEY")
    if apiKey == "" {
        log.Fatalln("Invalid API Key!!")
    }

    prompt_prefix := os.Getenv("Prompt_prefix")

    client := openai.NewClient(apiKey)

    resp, err := client.CreateChatCompletion(
        context.Background(),
        openai.ChatCompletionRequest{
            Model: openai.GPT3Dot5Turbo,
            Messages: []openai.ChatCompletionMessage{
                {
                    Role:    "user",
                    Content: prompt_prefix + prompt,
                },
            },
        })

    if err != nil {
        fmt.Printf("Completion error: %v\n", err)
    }

    res := resp.Choices[0].Message.Content

    return res, nil
}
  • Firstly, we are taking user inputs for the Subject, Audience and Purpose of the Email.

  • Then, we are creating a Prompt using the prompt_prefix and the user inputs for the email generation. For this, a prompt_prefix string is created and its value is stored in the .env file as Prompt_prefix="Generate the Cold Email content having ".

  • For creating the client to interact with the API we are using the github.com/sashabaranov/go-openai package. To import this run go get github.com/sashabaranov/go-openai.

  • Here we are using the model as GPT3Dot5Turbo. For other models information visit https://platform.openai.com/docs/models .

  • After getting the response, return the response string.

Testing

Now, run the command go build . to build a binary executable file for the CLI, it will be created as gpt-mail.exe. Then, run the command ./gpt-mail, this will run the gpt-mail.exe file.

> ./gpt-mail         
A AI-driven Tool for Generating Email

Usage:
  gpt-mail [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  generate    Command to Generate the Email
  help        Help about any command

Flags:
  -h, --help     help for gpt-mail
  -t, --toggle   Help message for toggle

Use "gpt-mail [command] --help" for more information about a command.

Now, run the command ./gpt-mail generate

Example Input :

Subject : Job Inquiry
Audience : Hiring Manager, Recruiter
Purpose/Information : Inquiring about available job positions and expressing interest in joining the team.

Output :

> Response:

Dear [Hiring Manager/Recruiter],

I hope this email finds you well. I am writing to inquire about any job opportunities that may be available within your esteemed company. I have admired your organization's achievements and culture, and I am eager to contribute my skills and experience to your team.

I have recently completed my [degree/certification] in [relevant field], and I am excited to embark on a new professional journey. Through my studies and previous work experiences, I have developed a strong foundation in [specific skills or industry knowledge]. I believe that these skills, along with my passion for [specific industry or field], would make me a valuable asset to your company.

I have researched your company extensively, and I am particularly impressed by [specific accomplishment or project]. It is evident that your team is highly skilled and driven, and I would be honored to be a part of it.

Attached to this email, please find my resume for your perusal. I would greatly appreciate the opportunity to discuss how my qualifications align with any available job positions, and to learn more about the team and company culture. I am available at your convenience for a phone call or virtual meeting.

Thank you for considering my application. I look forward to the possibility of joining your team and contributing to your continued success.

Sincerely,
[Your Name]
[Contact Information]

Conclusion

You can find the complete code repository for this tutorial here.

To get more information about Golang concepts, projects, etc. and to stay updated on the Tutorials do follow Siddhesh on Twitter and GitHub.

Until then Keep Learning, Keep Building ๐Ÿš€๐Ÿš€

ย