AI Driven CLI tool using Go
Tags: go, cli, chatgpt, openai
Published: 2024-02-04 03:30:00

## 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](https://go.dev/doc/install)
- OpenAI API Key: log-in/Sign-up to [Openai](https://platform.openai.com/api-keys) 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](https://cobra.dev/) 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](https://github.com/Siddheshk02/gpt-mail).

To get more information about Golang concepts, projects, etc. and to stay updated on the Tutorials do follow [Siddhesh on Twitter](https://twitter.com/siddhesh1102) and [GitHub](https://github.com/Siddheshk02).

Until then **Keep Learning**, **Keep Building** 🚀🚀