vex

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 19, 2026 License: MIT Imports: 8 Imported by: 0

README

vex

CI codecov Go Report Card CodeQL Go Reference Go Version Release

Type-safe embedding vector generation for Go. Provider-agnostic, composable reliability, observable.

Text In, Vectors Out

provider := openai.New(openai.Config{APIKey: os.Getenv("OPENAI_API_KEY")})
svc := vex.NewService(provider)

vec, _ := svc.Embed(ctx, "hello world")
// vec is a []float32 of length 1536

Install

go get github.com/zoobzio/vex

Requires Go 1.24 or higher.

Quick Start

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/zoobzio/vex"
    "github.com/zoobzio/vex/openai"
)

func main() {
    ctx := context.Background()

    // Create provider
    provider := openai.New(openai.Config{
        APIKey: os.Getenv("OPENAI_API_KEY"),
        Model:  "text-embedding-3-small",
    })

    // Create service with reliability options
    svc := vex.NewService(provider,
        vex.WithRetry(3),
        vex.WithTimeout(30*time.Second),
    )

    // Embed single text
    vec, err := svc.Embed(ctx, "The quick brown fox")
    if err != nil {
        panic(err)
    }
    fmt.Printf("Vector dimensions: %d\n", len(vec))

    // Embed batch
    texts := []string{"hello", "world", "foo", "bar"}
    vecs, err := svc.Batch(ctx, texts)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Embedded %d texts\n", len(vecs))

    // Compare vectors
    similarity := vecs[0].CosineSimilarity(vecs[1])
    fmt.Printf("Similarity: %.4f\n", similarity)
}

Providers

Provider Models Import
OpenAI text-embedding-3-small, text-embedding-3-large, ada-002 vex/openai
Cohere embed-english-v3.0, embed-multilingual-v3.0 vex/cohere
Voyage voyage-3, voyage-3-lite, voyage-large-2 vex/voyage
Gemini text-embedding-004 vex/gemini

Reliability

Built on pipz for composable reliability:

svc := vex.NewService(provider,
    vex.WithRetry(3),                           // Retry failed requests
    vex.WithBackoff(3, 100*time.Millisecond),   // Exponential backoff
    vex.WithTimeout(30*time.Second),            // Request timeout
    vex.WithCircuitBreaker(5, time.Minute),     // Circuit breaker
    vex.WithRateLimit(10, 20),                  // Rate limiting
    vex.WithFallback(backupService),            // Fallback provider
)

Query vs Document Embeddings

Some providers (Voyage, Cohere, Gemini) optimize embeddings differently based on intent. Use Embed for documents and EmbedQuery for search queries:

// Embedding documents for storage
docVec, _ := svc.Embed(ctx, "The quick brown fox jumps over the lazy dog")

// Embedding queries for search
queryVec, _ := svc.EmbedQuery(ctx, "animals jumping")

// Compare for retrieval
similarity := queryVec.CosineSimilarity(docVec)

For providers without this distinction (OpenAI), EmbedQuery behaves identically to Embed.

Chunking

Handle long texts by splitting and pooling:

chunker := &vex.Chunker{
    Strategy:  vex.ChunkSentence,  // or ChunkParagraph, ChunkFixed
    MaxSize:   512,
    Overlap:   50,
}

svc := vex.NewService(provider).
    WithChunker(chunker).
    WithPooling(vex.PoolMean)  // or PoolMax, PoolFirst

Vector Operations

// Normalise to unit vector
normalised := vec.Normalize()

// Similarity metrics
cosine := vec1.CosineSimilarity(vec2)
dot := vec1.Dot(vec2)
euclidean := vec1.EuclideanDistance(vec2)

// Generic similarity
sim := vec1.Similarity(vec2, vex.Cosine)

Why Vex?

  • Provider-agnostic: Swap providers without changing application code
  • Type-safe: Go generics and strong typing throughout
  • Composable reliability: Mix and match retry, timeout, circuit breaker, rate limiting
  • Observable: Hook signals via capitan for monitoring
  • Chunking built-in: Handle long texts with configurable splitting and pooling

Documentation

Contributing

See CONTRIBUTING.md for development workflow.

License

MIT - see LICENSE

Documentation

Overview

Package vex provides type-safe embedding vector generation for Go.

Index

Constants

This section is empty.

Variables

View Source
var (
	EmbedStarted          = capitan.NewSignal("vex.embed.started", "Embedding request initiated")
	EmbedCompleted        = capitan.NewSignal("vex.embed.completed", "Embedding request succeeded")
	EmbedFailed           = capitan.NewSignal("vex.embed.failed", "Embedding request failed")
	ProviderCallStarted   = capitan.NewSignal("vex.provider.call.started", "Provider HTTP call initiated")
	ProviderCallCompleted = capitan.NewSignal("vex.provider.call.completed", "Provider HTTP call succeeded")
	ProviderCallFailed    = capitan.NewSignal("vex.provider.call.failed", "Provider HTTP call failed")
)

Signals for hook events.

View Source
var (
	RequestIDKey    = capitan.NewStringKey("vex.request.id")
	ProviderKey     = capitan.NewStringKey("vex.provider")
	ModelKey        = capitan.NewStringKey("vex.model")
	InputCountKey   = capitan.NewIntKey("vex.input.count")
	DimensionsKey   = capitan.NewIntKey("vex.dimensions")
	DurationMsKey   = capitan.NewIntKey("vex.duration.ms")
	PromptTokensKey = capitan.NewIntKey("vex.tokens.prompt")
	TotalTokensKey  = capitan.NewIntKey("vex.tokens.total")
	ErrorKey        = capitan.NewStringKey("vex.error")
)

Keys for hook event fields.

Functions

func NewTerminal

func NewTerminal(provider Provider) pipz.Chainable[*EmbedRequest]

NewTerminal creates a terminal processor that calls the embedding provider.

Types

type ChunkStrategy

type ChunkStrategy int

ChunkStrategy defines how long texts are split before embedding.

const (
	// ChunkNone performs no chunking.
	ChunkNone ChunkStrategy = iota
	// ChunkSentence splits on sentence boundaries.
	ChunkSentence
	// ChunkParagraph splits on paragraph boundaries.
	ChunkParagraph
	// ChunkFixed splits into fixed-size chunks.
	ChunkFixed
)

type Chunker

type Chunker struct {
	Strategy  ChunkStrategy
	MaxSize   int  // Maximum chunk size in characters (for ChunkFixed)
	Overlap   int  // Overlap between chunks (for ChunkFixed)
	TrimSpace bool // Trim whitespace from chunks
}

Chunker splits text into smaller pieces for embedding.

func DefaultChunker

func DefaultChunker() *Chunker

DefaultChunker returns a chunker with sensible defaults.

func (*Chunker) Chunk

func (c *Chunker) Chunk(text string) []string

Chunk splits text according to the configured strategy.

type EmbedRequest

type EmbedRequest struct {
	Error     error
	Response  *EmbeddingResponse
	RequestID string
	Provider  string
	Texts     []string
}

EmbedRequest represents a request flowing through the pipeline.

type EmbeddingResponse

type EmbeddingResponse struct {
	Model      string
	Vectors    []Vector
	Usage      Usage
	Dimensions int
}

EmbeddingResponse contains the result of an embedding request.

type Option

Option modifies a pipeline for reliability features.

func WithBackoff

func WithBackoff(maxAttempts int, baseDelay time.Duration) Option

WithBackoff adds retry logic with exponential backoff to the pipeline. Failed requests are retried with increasing delays between attempts. The delay starts at baseDelay and doubles after each failure.

func WithCircuitBreaker

func WithCircuitBreaker(failures int, recovery time.Duration) Option

WithCircuitBreaker adds circuit breaker protection to the pipeline. After 'failures' consecutive failures, the circuit opens for 'recovery' duration.

func WithErrorHandler

func WithErrorHandler(handler pipz.Chainable[*pipz.Error[*EmbedRequest]]) Option

WithErrorHandler adds error handling to the pipeline. The error handler receives error context and can process/log/alert as needed.

func WithFallback

func WithFallback(fallback ServiceProvider) Option

WithFallback adds a fallback service for resilience. If the primary fails, the fallback will be tried.

func WithRateLimit

func WithRateLimit(rps float64, burst int) Option

WithRateLimit adds rate limiting to the pipeline. rps = requests per second, burst = burst capacity.

func WithRetry

func WithRetry(maxAttempts int) Option

WithRetry adds retry logic to the pipeline. Failed requests are retried up to maxAttempts times.

func WithTimeout

func WithTimeout(duration time.Duration) Option

WithTimeout adds timeout protection to the pipeline. Operations exceeding this duration will be canceled.

type PoolingMode

type PoolingMode int

PoolingMode defines how multiple chunk vectors are combined.

const (
	// PoolMean averages all vectors.
	PoolMean PoolingMode = iota
	// PoolFirst uses only the first vector.
	PoolFirst
	// PoolMax takes element-wise maximum.
	PoolMax
)

type Provider

type Provider interface {
	// Embed generates embedding vectors for the given texts.
	Embed(ctx context.Context, texts []string) (*EmbeddingResponse, error)

	// Name returns the provider identifier.
	Name() string

	// Dimensions returns the output vector dimensionality.
	Dimensions() int
}

Provider defines the interface for embedding backends.

type QueryProviderFactory

type QueryProviderFactory interface {
	Provider
	// ForQuery returns a provider configured for query embedding mode.
	ForQuery() Provider
}

QueryProviderFactory is optionally implemented by providers that distinguish query vs document embeddings. Providers implementing this interface can generate query-optimized embeddings for improved retrieval quality.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service wraps an embedding provider with pipeline-based reliability.

func NewService

func NewService(provider Provider, opts ...Option) *Service

NewService creates a new embedding Service with the given provider and options.

func (*Service) Batch

func (s *Service) Batch(ctx context.Context, texts []string) ([]Vector, error)

Batch generates embeddings for multiple texts.

func (*Service) BatchQuery

func (s *Service) BatchQuery(ctx context.Context, texts []string) ([]Vector, error)

BatchQuery generates query-optimized embeddings for multiple texts. For providers that distinguish query vs document embeddings, this uses query-optimized mode. Otherwise behaves identically to Batch.

func (*Service) Dimensions

func (s *Service) Dimensions() int

Dimensions returns the output vector dimensionality from the provider.

func (*Service) Embed

func (s *Service) Embed(ctx context.Context, text string) (Vector, error)

Embed generates an embedding for a single text. Uses document mode for providers that distinguish query vs document embeddings.

func (*Service) EmbedQuery

func (s *Service) EmbedQuery(ctx context.Context, text string) (Vector, error)

EmbedQuery generates an embedding optimized for search queries. For providers that distinguish query vs document embeddings (Voyage, Cohere, Gemini), this uses query-optimized mode. For providers without this distinction (OpenAI), this behaves identically to Embed.

func (*Service) GetPipeline

func (s *Service) GetPipeline() pipz.Chainable[*EmbedRequest]

GetPipeline returns the internal pipeline for composition.

func (*Service) Provider

func (s *Service) Provider() Provider

Provider returns the underlying embedding provider.

func (*Service) WithChunker

func (s *Service) WithChunker(c *Chunker) *Service

WithChunker sets the chunking strategy.

func (*Service) WithNormalize

func (s *Service) WithNormalize(normalize bool) *Service

WithNormalize sets whether to L2-normalize output vectors.

func (*Service) WithPooling

func (s *Service) WithPooling(mode PoolingMode) *Service

WithPooling sets the pooling mode for chunked embeddings.

type ServiceConfig

type ServiceConfig struct {
	Chunker     *Chunker
	PoolingMode PoolingMode
	Normalize   bool
}

ServiceConfig configures a Service.

type ServiceProvider

type ServiceProvider interface {
	GetPipeline() pipz.Chainable[*EmbedRequest]
}

ServiceProvider is implemented by types that can provide a pipeline for composition.

type SimilarityMetric

type SimilarityMetric int

SimilarityMetric defines how vectors are compared.

const (
	// Cosine measures the cosine of the angle between vectors.
	Cosine SimilarityMetric = iota
	// DotProduct computes the dot product of vectors.
	DotProduct
	// Euclidean computes the Euclidean distance between vectors.
	Euclidean
)

type Usage

type Usage struct {
	PromptTokens int
	TotalTokens  int
}

Usage tracks token consumption for an embedding request.

type Vector

type Vector []float32

Vector represents an embedding vector. Uses float32 for compatibility with vector databases (pgvector, Pinecone, Qdrant, etc.).

func Pool

func Pool(vectors []Vector, mode PoolingMode) Vector

Pool combines multiple vectors using the specified pooling mode.

func (Vector) CosineSimilarity

func (v Vector) CosineSimilarity(other Vector) float64

CosineSimilarity computes cosine similarity with another vector. Returns value in range [-1, 1], where 1 means identical direction.

func (Vector) Dot

func (v Vector) Dot(other Vector) float64

Dot computes the dot product with another vector.

func (Vector) EuclideanDistance

func (v Vector) EuclideanDistance(other Vector) float64

EuclideanDistance computes the Euclidean distance to another vector.

func (Vector) Norm

func (v Vector) Norm() float64

Norm returns the L2 norm (magnitude) of the vector.

func (Vector) Normalize

func (v Vector) Normalize() Vector

Normalize returns a unit vector (L2 normalized).

func (Vector) Similarity

func (v Vector) Similarity(other Vector, metric SimilarityMetric) float64

Similarity computes similarity using the specified metric.

Directories

Path Synopsis
Package cohere provides an embedding provider for the Cohere API.
Package cohere provides an embedding provider for the Cohere API.
Package gemini provides an embedding provider for the Google Gemini API.
Package gemini provides an embedding provider for the Google Gemini API.
Package openai provides an embedding provider for the OpenAI API.
Package openai provides an embedding provider for the OpenAI API.
Package testing provides test utilities for vex.
Package testing provides test utilities for vex.
Package voyage provides an embedding provider for the Voyage AI API.
Package voyage provides an embedding provider for the Voyage AI API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL