Austin Hunter

Go SDK for Voyage AI

Start Date: March 8, 2025

End Date: Ongoing

Roles: Maintainer

The Go SDK for Voyage AI enables developers to easily generate text embeddings via Voyage AI in their Go projects.

Background

While working on a project that required the generation of text embeddings, I noticed there was no Go SDK for Voyage AI. I decided to just implement my own client, which I later extended to support the entirety of the Voyage API.

This project is open source and any contribution is welcome!

The Client

The Voyage client is just a wrapper around a standard library HTTP Client. There are a number of optional parameters that can be passed to the client when it’s initialized, allowing developers to tweak the client behavior or fall back to reasonable defaults.

// Optional arguments for the client configuration.
type VoyageClientOpts struct {
	Key        string // A Voyage AI API key
	TimeOut    int    // The timeout for all client requests, in milliseconds. No timeout is set by default.
	MaxRetries int    // The maximum number of retries. Requests will not be retried by default.
	BaseURL    string // The BaseURL for the API. Defaults to the Voyage AI API but can be changed for testing and/or mocking.
}

Error Handling

API errors are handled by the client and are considered to be either “recoverable” or “unrecoverable,” where responses that result in recoverable errors can be retried while those resulting in unrecoverable errors cannot be.

// handleAPIError returns true if the given error is recoverable and false otherwise.
// The request retry loop will continue if the error is recoverable and it will abort otherwise.
func (c *VoyageClient) handleAPIError(resp *http.Response) (bool, error) {
	code := resp.StatusCode
	var apiError APIError
	if code >= 400 && code < 500 {
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			return false, err
		}
		err = json.Unmarshal(body, &apiError)
		if err != nil {
			return false, err
		}
	}

	switch code {
	case 400:
		return false, fmt.Errorf("voyage: bad request, detail: %s", apiError.Detail)
	case 401:
		return false, fmt.Errorf("voyage: unauthorized, detail: %s", apiError.Detail)
	case 422:
		return false, fmt.Errorf("voyage: Malformed Request, detail: %s", apiError.Detail)
	case 429:
		return true, fmt.Errorf("voyage: Rate Limit Reached, detail: %s", apiError.Detail)
	default:
		return true, fmt.Errorf("voyage: Server Error")
	}
}

The API

I decided to try to keep the API as close to the one provided for the Python Voyage SDK as possible. This makes it easier for community members to reason about the API. Optional parameters enable a high degree of configurability, but the API only requires a few parameters for each request, making it very easy to get started.

Example: Generating Text Embeddings

Text embeddings can be generated in just few lines using the client api.

	vo := voyageai.NewClient(nil)
	
	embeddings, err := vo.Embed(
		[]string{
			"Embed this text please",
			"And this as well",
		}, 
		"voyage-3-lite", 
		nil,
	)

	if err != nil {
		fmt.Printf("Could not get embedding: %s", err.Error())
	}
	// ... Use the generated embeddings ...

This results in an array of embedding objects of the following form:

type EmbeddingObject struct {
	Object string `json:"object"` // The object type, which is always "embedding".
	Embedding []float32 `json:"embedding"` // An array of embedding objects.
	Index int `json:"index"` // An integer representing the index of the embedding within the list of embeddings.
}

The full API documentation can be found in the Go Docs for the SDK and a quick-start guide can be found in the GitHub repository.