How to Use Golang with OpenAI's ChatGPT

Photo by DeepMind on Unsplash

How to Use Golang with OpenAI's ChatGPT

My Go client library for the OpenAI API

OpenAI and Go logos

Introduction

Open AI exposes an API that is quite simple to use. It requires its clients to register an API Key with an account on their website and send the API Key in a bearer authentication header.

The documentation for the API can be found at this link.

With that in mind, I’ve built a package to implement its methods. I will describe the implementation here, but the full package can be found at this GitHub link.

Please, feel free to contribute and use it.

Development

The calls require an API key, and you might want to specify an organization id as well, so first, we need to instantiate the client:

type Client struct {
 apiKey       string
 Organization string
}

// NewClient creates a new client
func NewClient(apiKey string, organization string) *Client {
 return &Client{
  apiKey:       apiKey,
  Organization: organization,
 }
}

// Post makes a post request
func (c *Client) Post(url string, input any) (response []byte, err error) {
 response = make([]byte, 0)

 rJson, err := json.Marshal(input)
 if err != nil {
  return response, err
 }

 resp, err := c.Call(http.MethodPost, url, bytes.NewReader(rJson))
 if err != nil {
  return response, err
 }
 defer resp.Body.Close()

 response, err = io.ReadAll(resp.Body)
 return response, err
}

// Get makes a get request
func (c *Client) Get(url string, input any) (response []byte, err error) {
 if input != nil {
  vals, _ := query.Values(input)
  query := vals.Encode()

  if query != "" {
   url += "?" + query
  }
 }

 resp, err := c.Call(http.MethodGet, url, nil)
 if err != nil {
  return response, err
 }
 defer resp.Body.Close()

 response, err = io.ReadAll(resp.Body)
 return response, err
}

// Call makes a request
func (c *Client) Call(method string, url string, body io.Reader) (response *http.Response, err error) {
 req, err := http.NewRequest(method, url, body)
 if err != nil {
  return response, err
 }

 req.Header.Add("Authorization", "Bearer "+c.apiKey)
 req.Header.Add("Content-Type", "application/json")
 if c.Organization != "" {
  req.Header.Add("OpenAI-Organization", c.Organization)
 }

 client := &http.Client{}
 resp, err := client.Do(req)
 return resp, err
}

After that, I will create wrappers for the specific endpoints of the API. I will show here the create completions method, as it is the first to be shown in the documentation as well:

import (
 "encoding/json"
)

const COMPLETIONS_URL = "https://api.openai.com/v1/chat/completions"

type CreateCompletionsRequest struct {
 Model            string            `json:"model,omitempty"`
 Messages         []Message         `json:"messages,omitempty"`
 Prompt           StrArray          `json:"prompt,omitempty"`
 Suffix           string            `json:"suffix,omitempty"`
 MaxTokens        int               `json:"max_tokens,omitempty"`
 Temperature      float64           `json:"temperature,omitempty"`
 TopP             float64           `json:"top_p,omitempty"`
 N                int               `json:"n,omitempty"`
 Stream           bool              `json:"stream,omitempty"`
 LogProbs         int               `json:"logprobs,omitempty"`
 Echo             bool              `json:"echo,omitempty"`
 Stop             StrArray          `json:"stop,omitempty"`
 PresencePenalty  float64           `json:"presence_penalty,omitempty"`
 FrequencyPenalty float64           `json:"frequency_penalty,omitempty"`
 BestOf           int               `json:"best_of,omitempty"`
 LogitBias        map[string]string `json:"logit_bias,omitempty"`
 User             string            `json:"user,omitempty"`
}

func (c *Client) CreateCompletionsRaw(r CreateCompletionsRequest) ([]byte, error) {
 return c.Post(COMPLETIONS_URL, r)
}

func (c *Client) CreateCompletions(r CreateCompletionsRequest) (response CreateCompletionsResponse, err error) {
 raw, err := c.CreateCompletionsRaw(r)
 if err != nil {
  return response, err
 }

 err = json.Unmarshal(raw, &response)
 return response, err
}

type CreateCompletionsResponse struct {
 ID      string `json:"id,omitempty"`
 Object  string `json:"object,omitempty"`
 Created int    `json:"created,omitempty"`
 Model   string `json:"model,omitempty"`
 Choices []struct {
  Text         string      `json:"text,omitempty"`
  Index        int         `json:"index,omitempty"`
  Logprobs     interface{} `json:"logprobs,omitempty"`
  FinishReason string      `json:"finish_reason,omitempty"`
 } `json:"choices,omitempty"`
 Usage struct {
  PromptTokens     int `json:"prompt_tokens,omitempty"`
  CompletionTokens int `json:"completion_tokens,omitempty"`
  TotalTokens      int `json:"total_tokens,omitempty"`
 } `json:"usage,omitempty"`

 Error Error `json:"error,omitempty"`
}

// Error is the error standard response from the API
type Error struct {
 Message string      `json:"message,omitempty"`
 Type    string      `json:"type,omitempty"`
 Param   interface{} `json:"param,omitempty"`
 Code    interface{} `json:"code,omitempty"`
}

type Message struct {
 Role    string `json:"role,omitempty"`
 Content string `json:"content,omitempty"`
}

With that, you should be ready to go!

Below is an example of how you call this method. (Other methods are implemented at the package link in the introduction).

package main

import (
 "fmt"
 "os"

 "github.com/franciscoescher/goopenai"
)

func main() {
 apiKey := os.Getenv("API_KEY")
 organization := os.Getenv("API_ORG")

 client := goopenai.NewClient(apiKey, organization)

 r := goopenai.CreateCompletionsRequest{
  Model: "gpt-3.5-turbo",
  Messages: []goopenai.Message{
   {
    Role:    "user",
    Content: "Say this is a test!",
   },
  },
  Temperature: 0.7,
 }

 completions, err := client.CreateCompletions(r)
 if err != nil {
  panic(err)
 }

 fmt.Println(completions)
 /* Response should be like this
  {
    "id": "chatcmpl-xxx",
    "object": "chat.completion",
    "created": 1678667132,
    "model": "gpt-3.5-turbo-0301",
    "usage": {
      "prompt_tokens": 13,
      "completion_tokens": 7,
      "total_tokens": 20
    },
    "choices": [
      {
        "message": {
          "role": "assistant",
          "content": "\n\nThis is a test!"
        },
        "finish_reason": "stop",
        "index": 0
      }
    ]
  }
 */
}

Run the code using the following:

API_KEY=<your-api-key> API_ORG=<your-org-id> go run .

Thank you for reading! This is a simple usage of the Open AI API using Golang.