Skip to content

mnkrana/imagen

Repository files navigation

imagen

Unified Go library for multi-provider AI image generation with automatic cloud storage upload.

Go Version License: MIT Go Reference

Stop copy-pasting the same OpenAI + GCS pipeline across your Go projects. imagen provides a clean Provider / Storage interface so you can swap AI providers, change storage backends, and generate-and-store images in a single call.


Quick Start

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/mnkrana/imagen"
)

func main() {
	cfg := imagen.LoadConfigFromEnv()

	client, err := imagen.NewClientFromConfig(cfg)
	if err != nil {
		log.Fatalf("client: %v", err)
	}

	result, err := client.GenerateAndStore(context.Background(), &imagen.Request{
		Prompt: "a serene mountain landscape at sunset, photorealistic",
	})
	if err != nil {
		log.Fatalf("generate: %v", err)
	}

	fmt.Println("Generated image:")
	fmt.Printf("  URL:  %s\n", result.URL)
	fmt.Printf("  Size: %d bytes\n", result.Size)
}

Run it:

cp .env.example .env      # fill in your keys and bucket
go run .

Installation

go get github.com/mnkrana/imagen

Requires Go 1.26+.


Configuration

Environment variables

imagen auto-loads a .env file from the current directory if present. Set these variables:

Variable Required Default Description
OPENAI_API_KEY for OpenAI OpenAI API key
STABILITY_API_KEY for Stability Stability AI API key
GCS_BUCKET yes Google Cloud Storage bucket name
IMAGEN_PROVIDER no openai Provider: openai or stability
IMAGEN_MODEL no gpt-image-2 Model name
IMAGEN_SIZE no 1024x1024 Output size
IMAGEN_QUALITY no standard Quality: standard or hd
IMAGEN_OUTPUT_FORMAT no webp Output format (Stability: png, webp, jpeg)
IMAGEN_HTTP_TIMEOUT no 90s HTTP client timeout
GCS_OBJECT_PREFIX no images/ GCS object path prefix
STABILITY_ENDPOINT no https://api.stability.ai/v1 Stability API base URL
STABILITY_MODEL no stable-diffusion-xl-1024-v1-0 Stability model ID
STABILITY_CFG_SCALE no 7.0 Classifier-free guidance scale
STABILITY_STEPS no 30 Number of inference steps
STABILITY_STYLE_PRESET no Style preset (photographic, digital-art, anime, etc.)

Programmatic configuration

provider := imagen.NewOpenAIProvider("sk-...",
    imagen.WithOpenAIModel("gpt-image-2"),
    imagen.WithOpenAISize("1792x1024"),
    imagen.WithOpenAIQuality("hd"),
)

storage := imagen.NewGCSStorage("my-bucket",
    imagen.WithGCSObjectNamer(func(r *imagen.Result) string {
        return fmt.Sprintf("generated/%d%s", time.Now().UnixNano(), ".png")
    }),
)

client := imagen.NewClient(provider, storage)

Architecture

┌──────────┐    ┌──────────────────┐    ┌─────────────┐    ┌──────────┐
│  Request  │───▶│  Client          │───▶│  Provider   │───▶│  Result  │
│  (prompt) │    │  GenerateAndStore│    │  (OpenAI /  │    │  (bytes) │
└──────────┘    │                  │    │   Stability)│    └──────────┘
                │                  │    └─────────────┘         │
                │                  │                            ▼
                │                  │    ┌─────────────┐    ┌──────────┐
                │                  │───▶│  Storage    │───▶│Storage   │
                │                  │    │  (GCS)      │    │Result    │
                └──────────────────┘    └─────────────┘    │(URL)     │
                                                            └──────────┘

Two core interfaces:

type Provider interface {
	Generate(ctx context.Context, req *Request) (*Result, error)
}

type Storage interface {
	Upload(ctx context.Context, result *Result) (*StorageResult, error)
}

Client.GenerateAndStore calls them in sequence, wrapping errors at each step.


Providers

OpenAI

provider := imagen.NewOpenAIProvider("sk-...")

Supports gpt-image-2, dall-e-3, and dall-e-2. Configurable via options:

  • WithOpenAIModel — model name
  • WithOpenAISize — output dimensions
  • WithOpenAIQualitystandard or hd
  • WithOpenAIStylevivid or natural
  • WithOpenAIResponseFormaturl or b64_json
  • WithOpenAIHTTPClient — custom HTTP client

Handles b64_json and url response formats automatically, detects content type via magic bytes, and maps API errors to typed sentinels.

Stability AI

provider := imagen.NewStabilityProvider("...")

Supports SDXL, SD3.5, and any Stability AI text-to-image model. Configurable via options:

  • WithStabilityEndpoint — API base URL
  • WithStabilityModel — model ID (e.g. stable-diffusion-xl-1024-v1-0)
  • WithStabilityCfgScale — classifier-free guidance scale
  • WithStabilitySteps — inference steps
  • WithStabilityStylePreset — style preset (photographic, digital-art, anime, etc.)
  • WithStabilityOutputFormat — output format (png, webp, jpeg)
  • WithStabilityHTTPClient — custom HTTP client

Size is parsed from Request.Size (e.g. "1024x1024"). Returns the seed from the first artifact and detects content type from magic bytes.


Storage

Google Cloud Storage

storage := imagen.NewGCSStorage("my-bucket")

Creates Firebase Storage-compatible download URLs by default. Customizable via options:

  • WithGCSObjectNamer — custom path generation function
  • WithGCSPublicURL — custom URL builder

Also provides:

  • UploadReader — for streaming image data from a reader
  • EnsureFirebaseToken — retrieve or create Firebase download tokens for existing objects

Authentication: Uses Application Default Credentials. For local dev:

gcloud auth application-default login

For production (Cloud Run, GCE, GKE), the default service account is used automatically.


Errors

All provider and storage errors are wrapped with fmt.Errorf("...: %w", err), making them inspectable with errors.Is. Sentinel errors:

var (
	ErrAPIKeyRequired                  // API key is required
	ErrGCSBucketRequired               // GCS bucket is required
	ErrNoImageData                     // no image data returned
	ErrEmptyURL                        // empty image URL
	ErrContentFiltered                 // content filtered by provider policy
	ErrRateLimited                     // rate limited by provider
	ErrUploadFailed                    // upload to storage failed
	ErrInvalidSize                     // invalid image size format
	ErrEmptyPrompt                     // prompt is required
)

Example:

result, err := client.GenerateAndStore(ctx, req)
if errors.Is(err, imagen.ErrContentFiltered) {
    log.Println("Prompt was filtered by safety policy")
}

Retry Utility

The built-in generic retry utility is available for any operation:

result, err := imagen.RetryDo(ctx, imagen.RetryConfig{
    MaxRetries:     3,
    BaseDelay:      1 * time.Second,
    MaxDelay:       30 * time.Second,
    OperationLabel: "my_operation",
}, func(ctx context.Context) (string, error) {
    return myFlakyOperation(ctx)
})

Features exponential backoff with jitter, context cancellation, and configurable ShouldRetry predicate.


Examples

Full working examples are in the examples/ directory:

  • basic — minimal end-to-end generation and upload

Run any example with:

cd examples/basic
cp .env.example .env   # fill in your credentials
go run .

Project Structure

imagen/
├── imagen.go       — Core types, interfaces, Client orchestrator
├── openai.go       — OpenAI provider implementation
├── stability.go    — Stability AI provider implementation
├── gcs.go          — GCS storage implementation
├── config.go       — Config, options, env loading
├── errors.go       — Sentinel errors
├── retry.go        — Generic retry utility
├── retry_test.go   — Retry tests
├── examples/       — Runnable examples
├── Makefile        — Build, test, lint targets
└── .env.example    — Environment variable template

Development

make test         # run tests
make test-race    # run with race detector
make lint         # run golangci-lint
make build        # compile all packages

License

MIT — see LICENSE.


Author

Mayank Rana — built for reusable, production-grade AI image pipelines.

About

Go library for AI image generation across OpenAI and Stability AI with automatic upload to Google Cloud Storage.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors