OpenAI Go SDK

repository·main·Indexed 25 days ago

https://github.com/openai/openai-go

An idiomatic Go client for interacting with the OpenAI REST API. The library provides support for the Responses API, Conversations API, Chat Completions, and tool calling. It features built-in support for streaming, structured outputs via JSON schema, auto-paging for lists, and webhook signature verification. The SDK utilizes Go 1.24+ omitzero semantics for request fields and supports functional options for configuration, including custom timeouts and retry logic.

Tokens
35.8K
Snippets
44
Records
267
Agent score
83%

What's inside openai-go

  1. Use Azure OpenAI in Azure AI Foundry Models

    main

    To use this library with Azure OpenAI, use the option.RequestOption functions provided in the azure package. You can authenticate using either a TokenCredential (via azure.WithTokenCredential) or an API Key (via azure.WithAPIKey). You must also specify the Azure OpenAI endpoint and the appropriate API version using azure.WithEndpoint.

    package main
    
    import (
    	"fmt"
    	"os"
    
    	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    	"github.com/openai/openai-go/v3"
    	"github.com/openai/openai-go/v3/azure"
    )
    
    func main() {
    	const azureOpenAIEndpoint = "https://<azure-openai-resource>.openai.azure.com"
    
    	// The latest API versions, including previews, can be found here:
    	// https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning
    	const azureOpenAIAPIVersion = "2024-06-01"
    
    	tokenCredential, err := azidentity.NewDefaultAzureCredential(nil)
    
    	if err != nil {
    		fmt.Printf("Failed to create the DefaultAzureCredential: %s", err)
    		os.Exit(1)
    	}
    
    	client := openai.NewClient(
    		azure.WithEndpoint(azureOpenAIEndpoint, azureOpenAIAPIVersion),
    
    		// Choose between authenticating using a TokenCredential or an API Key
    		azure.WithTokenCredential(tokenCredential),
    		// or azure.WithAPIKey(azureOpenAIAPIKey),
    	)
    }
  2. Use Struct-based Request Unions instead of Interfaces

    main

    Request unions have transitioned from interfaces (which required type assertions) to structs containing optional fields for each variant.

    • To set a variant: Initialize the union struct with the specific field for that variant (e.g., OfCat or OfDog).
    • To access fields: Use the provided Get methods (e.g., GetName()) which return pointers to fields shared across multiple variants, rather than using a switch on the type.
    // Before (Interface based)
    type AnimalParam interface { ImplAnimalParam() }
    var dog AnimalParam = DogParam{Name: "spot"}
    
    // After (Struct based)
    type AnimalUnionParam struct {
        OfCat  *Cat  `json:",omitzero,inline`
        OfDog  *Dog  `json:",omitzero,inline`
    }
    
    dog := AnimalUnionParam{
        OfDog: &DogParam{Name: "spot"},
    }
    
    // Accessing fields
    var name *string = animal.GetName()
  3. Use Amazon Bedrock with the bedrock package

    main

    The bedrock package allows calling OpenAI models through Amazon Bedrock's OpenAI-compatible API. It uses the standard AWS SDK credential chain by default.

    Configuration

    • Region: Resolved from AWSRegion, AWS_REGION, AWS_DEFAULT_REGION, or standard AWS config.
    • Base URL: Resolved from BaseURL, AWS_BEDROCK_BASE_URL, or https://bedrock-mantle.{region}.api.aws/openai/v1.
    • Profiles: Use AWSProfile in bedrock.Config to select a named profile.
    • Credentials: Supports static credentials or an aws.CredentialsProvider.

    Note: Explicit bearer tokens (APIKey) and AWS SigV4 authentication are mutually exclusive. Ambient OPENAI_* credentials are NOT inherited by a Bedrock client.

    import "github.com/openai/openai-go/v3/bedrock"
    
    client, err := bedrock.NewClient(context.Background(), bedrock.Config{
    	AWSRegion: "us-west-2",
    	AWSProfile: "production",
    })
  4. Authenticate using Workload Identity (Kubernetes, Azure, GCP)

    main

    For cloud workloads, use option.WithWorkloadIdentity to use short-lived, automatically refreshed tokens instead of API keys.

    Kubernetes

    Use auth.K8sServiceAccountTokenProvider("").

    Azure Managed Identity

    Use auth.AzureManagedIdentityTokenProvider(nil).

    Google Cloud Compute Engine

    Use auth.GCPIDTokenProvider(nil).

    Custom Provider

    Implement the auth.SubjectTokenProvider interface with TokenType() and GetToken(ctx, httpClient) methods.

    Refresh Buffer

    Tokens refresh 20 minutes before expiry by default. Customize this using RefreshBufferSeconds in auth.WorkloadIdentity.

    // Kubernetes Example
    client := openai.NewClient(
    	option.WithWorkloadIdentity(auth.WorkloadIdentity{
    		IdentityProviderID: "idp-123",
    		ServiceAccountID:   "sa-456",
    		Provider:           auth.K8sServiceAccountTokenProvider(""),
    	}),
    )
  5. Make undocumented requests to endpoints or params

    main

    If you need to access undocumented API features, the library provides several escape hatches:

    1. Undocumented Endpoints: Use client.Get, client.Post, etc. with a path string. Client RequestOptions (like retries) are respected.
    2. Undocumented Parameters: Use option.WithQuerySet() or option.WithJSONSet() to inject arbitrary keys into requests.
    3. Undocumented Response Properties:
      • Access raw JSON as a string via result.JSON.RawJSON().
      • Access a specific field's raw JSON via result.JSON.Foo.Raw().
      • Access all unknown fields via result.JSON.ExtraFields(), which returns a map[string]Field.
  6. Install the OpenAI Go SDK

    main

    To use the OpenAI Go library, import the v3 module into your project. You can also pin a specific SDK version using go get to ensure compatibility with your Go environment.

    Import path: github.com/openai/openai-go/v3 (imported as openai)

    Pinning a version:

    go get -u 'github.com/openai/openai-go/v3@v3.47.0'
    import (
    	"github.com/openai/openai-go/v3"
    ) // imported as openai
  7. Update development tools manually

    main

    The tools module is used to pin repository-only tools (like govulncheck) without adding their dependencies to the main OpenAI SDK module graph. To manually update the tools pinned in this module, navigate to the tools directory and run the update commands.

    cd tools
    go get -tool golang.org/x/vuln/cmd/govulncheck@latest
    go mod tidy
  8. Check Go version requirements

    main

    The requirements for the OpenAI Go SDK depend on the version you are using:

    • SDK v3.45.0 and later: Requires Go 1.25 or later.
    • Go 1.22–1.24: You must pin the SDK to v3.44.0, which is the final compatible release for these Go versions.

    Note that older SDK releases do not receive guaranteed fixes or security backports.

  9. Migrate from `param.Field[T]` and `openai.F()` to `omitzero` semantics

    main

    The new SDK has removed openai.F() and param.Field[T]. It now uses Go's json:"...,omitzero" semantics to handle omitted fields.

    • For non-primitive types (structs, slices, maps, enums): Simply remove openai.F() and use the type directly. These fields will be omitted from JSON if they contain their zero value.
    • For optional primitives (e.g., string, int64): Use param.Opt[T] and construct values using helper functions like openai.String(string), openai.Int(int), or openai.Bool(bool).

    Caution on Required Primitives: Required primitive fields (those with json:"...,required") do not use omitzero. If you do not explicitly set a required primitive field, its zero value (e.g., 0 or "") will be serialized and sent to the API. Ensure all required fields are explicitly initialized.

    // Before
    foo = FooParams{
        RequiredString: openai.String("hello"),
        OptionalString: openai.String("hi"),
        Array: openai.F([]BarParam{
            BarParam{Prop: ... }
        }),
        RequiredObject: openai.F(BarParam{ ... }),
        OptionalObject: openai.F(BarParam{ ... }),
        StringEnum: openai.F[BazEnum]("baz-ok"),
    }
    
    // After
    foo = FooParams{
        RequiredString: "hello",
        OptionalString: openai.String("hi"),
        Array: []BarParam{
            BarParam{Prop: ... }
        },
        RequiredObject: BarParam{ ... },
        OptionalObject: openai.String("hi"), // if using param.Opt
        StringEnum: "baz-ok",
    }
  10. Configure request retries with WithMaxRetries

    main

    The library automatically retries certain errors (connection errors, 408, 409, 429, and >=500) up to 2 times by default using exponential backoff.

    You can configure the retry behavior globally when creating the client or override it for a specific request using option.WithMaxRetries(n).

    // Configure the default for all requests (e.g., disable retries):
    client := openai.NewClient(
    	option.WithMaxRetries(0), // default is 2
    )
    
    // Override per-request:
    client.Responses.New(
    	context.TODO(),
    	params,
    	option.WithMaxRetries(5),
    )
  11. Handle usage result unions with AsAny()

    main

    Many usage response data results are returned as a union type (e.g., AdminOrganizationUsageAudioSpeechesResponseDataResultUnion). To access the specific data for a particular usage type, use the AsAny() method combined with a type switch, or use the provided As<VariantName>() methods.

    Example pattern for switching on the variant:

    switch variant := resultUnion.AsAny().(type) {
    case openai.AdminOrganizationUsageAudioSpeechesResponseDataResultOrganizationUsageCompletionsResult:
        // Handle completions result
    case openai.AdminOrganizationUsageAudioSpeechesResponseDataResultOrganizationUsageEmbeddingsResult:
        // Handle embeddings result
    // ... other cases
    default:
        // Handle error
    }
  12. Handle API Errors

    main

    Non-success status codes return an *openai.Error. This error type includes StatusCode, *http.Request, *http.Response, and the error body JSON. Use errors.As to inspect these errors and apierr.DumpRequest(true) or apierr.DumpResponse(true) to debug the serialized HTTP traffic.

    if err != nil {
    	var apierr *openai.Error
    	if errors.As(err, &apierr) {
    		println(string(apierr.DumpRequest(true)))
    		println(string(apierr.DumpResponse(true)))
    	}
    	panic(err.Error())
    }