Consumir OpenAI (ChatGPT) com Golang

May 04 2023
Biblioteca cliente My Go para a API OpenAI Introdução A Open AI expõe uma API bastante simples de usar. Ele exige que seus clientes registrem uma chave de API com uma conta em seu site e enviem a chave de API em um cabeçalho de autenticação de portador.

Biblioteca cliente My Go para a API OpenAI

Logotipos OpenAI e Go

Introdução

Open AI expõe uma API bastante simples de usar. Ele exige que seus clientes registrem uma chave de API com uma conta em seu site e enviem a chave de API em um cabeçalho de autenticação de portador.

A documentação da API pode ser encontrada neste link .

Com isso em mente, construí um pacote para implementar seus métodos. Vou descrever a implementação aqui, mas o pacote completo pode ser encontrado neste link do GitHub .

Por favor, sinta-se livre para contribuir e usá-lo.

Desenvolvimento

As chamadas requerem uma chave de API e você também pode querer especificar um id de organização, então primeiro precisamos instanciar o cliente:

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
}

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 {
  Message struct {
    Role    string `json:"role,omitempty"`
    Content string `json:"content,omitempty"`
  } `json:"message"`
  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"`
}

Abaixo está um exemplo de como você chama esse método. (Outros métodos são implementados no link do pacote na introdução).

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
      }
    ]
  }
 */
}

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