Documentation
¶
Overview ¶
Package proxy provides a high-performance LLM request proxy with support for multiple providers, intelligent routing, caching, and extensible middleware.
Package proxy provides the core business logic for LLM request proxying
Index ¶
- Constants
- Variables
- func ExtractProviderFromModel(modelID string) (provider, model string)
- func OverheadMS(ctx context.Context) (int64, bool)
- func StartOverhead(ctx context.Context) context.Context
- func TransformChatRequest(req *ChatCompletionRequest) (*connectors.ChatRequest, error)
- func TransformEmbeddingsRequest(req *EmbeddingsRequest) *connectors.EmbeddingsRequest
- func ValidateChatCompletionRequest(req *ChatCompletionRequest) error
- func ValidateEmbeddingsRequest(req *EmbeddingsRequest) error
- func ValidateImagesRequest(req *ImagesRequest) error
- func ValidateModerationRequest(req *ModerationRequest) error
- func ValidateRerankRequest(req *RerankRequest) error
- func ValidateSpeechRequest(req *SpeechRequest) error
- func ValidateTranscriptionRequest(req *TranscriptionRequest) error
- func ValidateVideoAssetReference(req *VideoAssetRequest) error
- func ValidateVideoJobReference(req *VideoJobRequest) error
- func ValidateVideoJobRequest(req *VideoSubmitRequest) error
- type APIKeyRoutingConfig
- type AuthorInfo
- type AuthorsResponse
- type CacheConfig
- type CacheCost
- type CacheManager
- type CacheMiddleware
- type CacheSimilarityProvider
- type CacheStatusProvider
- type ChatCompletionRequest
- type ChatCompletionResponse
- type ChatCompletionStreamResponse
- type Config
- type CredentialFieldInfo
- type EmbeddingsRequest
- type EmbeddingsResponse
- type EndpointInfo
- type FileResolver
- type GatewayEmbedder
- type GatewayModerator
- type GuardrailVerdictProvider
- type Guardrails
- type ImagesRequest
- type ImagesResponse
- type JobAccountant
- type MediaRequest
- type MediaResponse
- type Middleware
- type ModelArchitecture
- type ModelAuthorInfo
- type ModelEndpointsResponse
- type ModelInfo
- type ModelLineageInfo
- type ModelOfferingInfo
- type ModelPricing
- type ModelsResponse
- type ModerationRequest
- type ModerationResponse
- type OfferingPricingInfo
- type OperationRequest
- type OperationResponse
- type Option
- type PresetResolver
- type PresetSource
- type ProviderError
- type ProviderInfo
- type ProviderPolicyInfo
- type ProviderPreferences
- type ProvidersResponse
- type Proxy
- type RerankRequest
- type RerankResponse
- type RoutingError
- type SemanticEmbedIdentity
- type SemanticEmbedder
- type SpeechRequest
- type SpeechResponse
- type StoredDocument
- type StreamUnwrapper
- type TopProviderInfo
- type TranscriptionRequest
- type TranscriptionResponse
- type UsageCapture
- type UsageObserver
- type UsageRecorder
- type ValidationError
- type VideoAsset
- type VideoAssetReference
- type VideoAssetRequest
- type VideoJobAnswer
- type VideoJobReference
- type VideoJobRequest
- type VideoJobRunner
- func (r *VideoJobRunner) Cancel(ctx context.Context, handle jobs.Handle) (jobs.Report, error)
- func (r *VideoJobRunner) Fetch(ctx context.Context, handle jobs.Handle, maxBytes int64) (jobs.Asset, error)
- func (r *VideoJobRunner) Poll(ctx context.Context, handle jobs.Handle) (jobs.Report, error)
- func (r *VideoJobRunner) Submit(ctx context.Context) (jobs.Acceptance, error)
- type VideoSubmitRequest
Constants ¶
const ( // CacheStatusKey is the context key for cache status CacheStatusKey contextKey = "X-Cache" // CacheStatusHit indicates a cache hit CacheStatusHit = "HIT" // CacheStatusMiss indicates a cache miss CacheStatusMiss = "MISS" )
const OverheadHeader = "x-starport-overhead-ms"
OverheadHeader carries the gateway-added latency of one proxied response in whole milliseconds. The value excludes upstream provider time; on a stream it covers the work before the first byte reaches the client.
const PresetReferencePrefix = "@preset/"
PresetReferencePrefix selects a stored preset through the model field, matching OpenRouter's "@preset/<name>" reference.
Variables ¶
var ( // ErrNoValidModel indicates no valid model was specified ErrNoValidModel = errors.New("no valid model specified") // ErrNoAvailableProvider indicates no provider is available for the request ErrNoAvailableProvider = errors.New("no available provider for model") // ErrInvalidRequest indicates the request is malformed ErrInvalidRequest = errors.New("invalid request") ErrProviderUnavailable = errors.New("provider temporarily unavailable") // ErrRateLimitExceeded indicates rate limit has been exceeded ErrRateLimitExceeded = errors.New("rate limit exceeded") // ErrInsufficientQuota indicates the user has insufficient quota ErrInsufficientQuota = errors.New("insufficient quota") // ErrStreamingNotSupported indicates streaming is not supported for this request ErrStreamingNotSupported = errors.New("streaming not supported") // ErrEmbeddingsNotSupported indicates embeddings are not supported by the provider ErrEmbeddingsNotSupported = errors.New("embeddings not supported by provider") // ErrPresetNotFound indicates a request referenced an unknown preset ErrPresetNotFound = errors.New("preset not found") // ErrStoredFileNotFound indicates a request referenced a stored file this // account does not hold. A file another account holds reads the same way, // because a different answer would report which identifiers exist. ErrStoredFileNotFound = errors.New("stored file not found") )
Common proxy errors
Functions ¶
func ExtractProviderFromModel ¶
ExtractProviderFromModel extracts a provider-scoped model ID.
func OverheadMS ¶ added in v1.1.0
OverheadMS reports the gateway-added milliseconds measured so far. The second result is false when the request never started a timer.
func StartOverhead ¶ added in v1.1.0
StartOverhead begins overhead measurement for one request. The HTTP layer calls it once before dispatch; attempt callbacks mark upstream waits on the same timer through the context.
func TransformChatRequest ¶
func TransformChatRequest(req *ChatCompletionRequest) (*connectors.ChatRequest, error)
TransformChatRequest converts the canonical use-case request at the provider boundary.
func TransformEmbeddingsRequest ¶
func TransformEmbeddingsRequest(req *EmbeddingsRequest) *connectors.EmbeddingsRequest
TransformEmbeddingsRequest converts a proxy EmbeddingsRequest to a connector EmbeddingsRequest
func ValidateChatCompletionRequest ¶
func ValidateChatCompletionRequest(req *ChatCompletionRequest) error
ValidateChatCompletionRequest validates one canonical gateway chat request.
func ValidateEmbeddingsRequest ¶
func ValidateEmbeddingsRequest(req *EmbeddingsRequest) error
ValidateEmbeddingsRequest validates one canonical embedding request.
func ValidateImagesRequest ¶ added in v1.1.0
func ValidateImagesRequest(req *ImagesRequest) error
ValidateImagesRequest checks one image generation or image edit request.
func ValidateModerationRequest ¶ added in v1.2.0
func ValidateModerationRequest(req *ModerationRequest) error
ValidateModerationRequest checks one canonical moderation request. Like the rerank validator, it repeats the emptiness checks the codec performed so the guarantee belongs to the operation rather than to one wire format.
func ValidateRerankRequest ¶ added in v1.1.0
func ValidateRerankRequest(req *RerankRequest) error
ValidateRerankRequest checks one canonical rerank request. The codec already refuses an empty query and an empty document list, so this guard covers the caller the codec does not cover: a gateway-internal one that builds the request itself.
func ValidateSpeechRequest ¶ added in v1.1.0
func ValidateSpeechRequest(req *SpeechRequest) error
ValidateSpeechRequest checks one text-to-speech request.
func ValidateTranscriptionRequest ¶ added in v1.1.0
func ValidateTranscriptionRequest(req *TranscriptionRequest) error
ValidateTranscriptionRequest checks one speech-to-text request.
func ValidateVideoAssetReference ¶ added in v1.1.0
func ValidateVideoAssetReference(req *VideoAssetRequest) error
ValidateVideoAssetReference checks one read of a finished job's asset. It adds the stored bound to the reference checks: a read with no bound would let the provider's answer size this deployment's storage.
func ValidateVideoJobReference ¶ added in v1.1.0
func ValidateVideoJobReference(req *VideoJobRequest) error
ValidateVideoJobReference checks one poll or cancel of an accepted job. A reference with no provider would plan a route to whichever provider the catalog ranked first, and that provider never issued the identifier.
func ValidateVideoJobRequest ¶ added in v1.1.0
func ValidateVideoJobRequest(req *VideoSubmitRequest) error
ValidateVideoJobRequest checks one video generation submission.
Types ¶
type APIKeyRoutingConfig ¶
type APIKeyRoutingConfig struct {
AllowedProviders []string
AllowedModels []string
ModelOverrides map[string]string
RateLimitTier string
CredentialStrategy keyring.Strategy
// Access carries the account's paired provider and model grants. Nil
// grants every provider and model.
Access []routing.ProviderAccess
// BYOKProviders gates which providers the BYOK credential source may
// serve: nil allows every provider, an empty list none, a non-empty
// list only its members. It is the account's BYOK policy resolved to
// plain data, so this package never learns the account vocabulary.
BYOKProviders *[]string
}
APIKeyRoutingConfig contains API-key scoped routing restrictions.
type AuthorInfo ¶ added in v1.1.0
type AuthorInfo = view.AuthorInfo
AuthorInfo represents one catalog author or organization.
type AuthorsResponse ¶ added in v1.1.0
type AuthorsResponse struct {
Authors []AuthorInfo `json:"authors"`
// Internal fields (not serialized)
CacheStatus string `json:"-"`
}
AuthorsResponse represents catalog author information
type CacheConfig ¶
type CacheConfig struct {
// Enable caching for different endpoints
EnableChatCache bool `env:"ENABLE_CHAT_CACHE,default=true"`
EnableEmbeddingCache bool `env:"ENABLE_EMBEDDING_CACHE,default=true"`
EnableModelCache bool `env:"ENABLE_MODEL_CACHE,default=true"`
EnableProviderCache bool `env:"ENABLE_PROVIDER_CACHE,default=true"`
// Skip cache for specific models or patterns
SkipCacheModels []string `env:"SKIP_CACHE_MODELS"`
// Force cache refresh header
CacheControlHeader string `env:"CACHE_CONTROL_HEADER,default=X-Cache-Control"`
// EnableSemanticCache turns on the similarity layer beside the exact
// identity. Each request still opts in per call, and the layer only
// runs where the exact cache already deemed the request cacheable.
// Composition sets these fields from the deployment configuration, so
// they carry no env tags.
EnableSemanticCache bool
// SemanticThreshold is the minimum cosine similarity that answers.
// Zero takes the cache package default.
SemanticThreshold float64
// SemanticMaxEntries bounds the vectors one similarity scope holds.
// Zero takes the cache package default.
SemanticMaxEntries int
// SemanticEmbedder embeds the canonical prompt text through the
// gateway's own embeddings path. Nil keeps the layer off.
SemanticEmbedder SemanticEmbedder
}
CacheConfig defines caching behavior
type CacheCost ¶
type CacheCost struct {
WriteTokens float64 `json:"write_tokens"` // Cost of writing tokens to cache
ReadTokens float64 `json:"read_tokens"` // Cost of reading tokens from cache
TotalCost float64 `json:"total_cost"` // Total cost including cache operations
}
CacheCost represents the cost of cache operations
type CacheManager ¶
type CacheManager interface {
GetModel(ctx context.Context, key string) (any, bool, error)
SetModel(ctx context.Context, key string, value any) error
GetResponse(ctx context.Context, key string) ([]byte, bool, error)
SetResponse(ctx context.Context, key string, response []byte) error
}
CacheManager interface defines the cache operations used by the proxy
type CacheMiddleware ¶
type CacheMiddleware struct {
// contains filtered or unexported fields
}
CacheMiddleware provides caching functionality for proxy services.
func (*CacheMiddleware) Wrap ¶
func (m *CacheMiddleware) Wrap(next Proxy) Proxy
Wrap wraps the service with caching functionality.
type CacheSimilarityProvider ¶ added in v1.2.0
type CacheSimilarityProvider interface {
GetCacheSimilarity() float64
}
CacheSimilarityProvider reports the cosine similarity a semantic cache hit served under. A stream that does not implement it, or answers zero, served exactly or not from cache at all.
type CacheStatusProvider ¶
type CacheStatusProvider interface {
GetCacheStatus() string
GetCacheAge() int // Returns cache age in seconds, or 0 if not cached
}
CacheStatusProvider is an interface to check cache status on streams
type ChatCompletionRequest ¶
type ChatCompletionRequest struct {
Request inference.ChatRequest
Route string
Provider *ProviderPreferences
// Preset names a stored preset selected by the request body. A
// "@preset/<name>" model reference selects one the same way and wins
// over this field.
Preset string
// Internal fields
APIKey string `json:"-"`
// AccountID is the account the request runs under. Credential selection,
// response cache scope, and account limits read this.
AccountID string `json:"-"`
// KeyID is the gateway API key that authenticated the request. Usage
// attribution and per-key limits read this. Many keys share one account, so
// the two values are distinct and neither substitutes for the other.
KeyID string `json:"-"`
// TeamID is the team the serving key is attributed to, or empty for a
// teamless key. Usage attribution and the team budget read this.
TeamID string `json:"-"`
APIKeyConfig *APIKeyRoutingConfig `json:"-"`
RequestID string `json:"-"`
Protocol string `json:"-"` // Protocol surface that received the request
// BatchID names the batch this request runs inside, or is empty for an
// online request. The usage record carries it, so an operator can read
// what one batch spent.
BatchID string `json:"-"`
// SemanticCache opts this request into the similarity layer, when the
// deployment enables one. The X-Semantic-Cache header states it.
SemanticCache bool `json:"-"`
}
ChatCompletionRequest is a canonical chat request plus gateway policy and identity.
type ChatCompletionResponse ¶
type ChatCompletionResponse struct {
Response inference.ChatResponse
// ExtractionCached reports that every document this turn attached came
// back from the extraction cache. It is separate from CacheStatus below,
// which reports the response cache: a turn can read its attachments from
// the cache and still call the model, and that is the common case for a
// conversation about one document.
ExtractionCached bool `json:"-"`
// The rest of the document read, as the usage record reports it: which
// engine ran, how many pages it read each way, which model recognized
// them, what that cost in integer nano-USD, and how long it took.
ExtractionEngine string `json:"-"`
ExtractionPages int `json:"-"`
RecognizedPages int `json:"-"`
NativePages int `json:"-"`
ExtractionOffering string `json:"-"`
ExtractionNanoUSD int64 `json:"-"`
ExtractionUnpriced bool `json:"-"`
ExtractionDuration time.Duration `json:"-"`
// Internal fields (not serialized)
CacheStatus string `json:"-"`
CacheAge int `json:"-"` // Seconds since cached
ETag string `json:"-"` // Entity tag for response
CacheCost *CacheCost `json:"-"` // Cache pricing information
// CacheSimilarity is the cosine similarity a semantic hit served
// under, or zero for an exact hit or a miss. The X-Cache-Similarity
// header reports it beside the shared cache status vocabulary.
CacheSimilarity float64 `json:"-"`
// Route evidence (not serialized)
ProviderUsed string `json:"-"`
CredentialSource string `json:"-"`
Attempts int `json:"-"`
RoutingDuration time.Duration `json:"-"`
CatalogSnapshot *runtimecatalog.RoutableSnapshot `json:"-"`
// GuardrailVerdict is the strongest verdict the guardrail pipeline
// answered over this turn: allow, redact, or refuse. Empty means no
// guardrail ran. The usage record carries it; the wire never does.
GuardrailVerdict string `json:"-"`
}
ChatCompletionResponse is a canonical result plus gateway response metadata.
func TransformChatResponse ¶
func TransformChatResponse(resp *connectors.ChatResponse, modelUsed string) (*ChatCompletionResponse, error)
TransformChatResponse converts a connector ChatResponse to a proxy ChatCompletionResponse
type ChatCompletionStreamResponse ¶
type ChatCompletionStreamResponse interface {
// Read returns the next canonical event or io.EOF when done.
Read() (*inference.StreamEvent, error)
// Close releases any resources
Close() error
}
ChatCompletionStreamResponse represents a streaming response
type Config ¶
type Config struct {
// Registry provides access to LLM provider connectors
Registry connectors.LeasingRegistry
// Router handles intelligent model selection and failover
Router router.ModelRouter
// CacheManager handles response caching (optional)
CacheManager CacheManager
// CacheConfig configures caching behavior (optional)
CacheConfig *CacheConfig
// TokenEstimator synthesizes estimated usage for streams that end
// without provider-reported usage (optional)
TokenEstimator *tokenize.Estimator
// FileResolver reads the bytes behind a stored document reference
// (optional). A deployment without one refuses a request that names a
// file rather than sending the model an empty document.
FileResolver FileResolver
// DocumentExtractor is the native parser engine, with the page and time
// bounds this deployment sets (optional). A deployment without one reads
// documents under the engine's own default bounds.
DocumentExtractor *document.Extractor
// DocumentCache holds one document's text for reuse inside a window
// (optional). A deployment without one reads every attachment on every
// turn, which is correct and pays the page price each time.
DocumentCache *document.Cache
}
Config holds the configuration for creating a new proxy service.
type CredentialFieldInfo ¶ added in v1.1.0
type CredentialFieldInfo = view.CredentialFieldInfo
CredentialFieldInfo is the catalog-declared inference credential field a caller supplies for BYOK. It carries no secret values.
type EmbeddingsRequest ¶
type EmbeddingsRequest struct {
Request inference.EmbeddingRequest
// Internal fields
APIKey string `json:"-"`
// AccountID is the account the request runs under. Credential selection,
// response cache scope, and account limits read this.
AccountID string `json:"-"`
// KeyID is the gateway API key that authenticated the request. Usage
// attribution and per-key limits read this. Many keys share one account, so
// the two values are distinct and neither substitutes for the other.
KeyID string `json:"-"`
// TeamID is the team the serving key is attributed to, or empty for a
// teamless key. Usage attribution and the team budget read this.
TeamID string `json:"-"`
APIKeyConfig *APIKeyRoutingConfig `json:"-"`
RequestID string `json:"-"`
Protocol string `json:"-"` // Protocol surface that received the request
// BatchID names the batch this request runs inside, or is empty for an
// online request. The usage record carries it, so an operator can read
// what one batch spent.
BatchID string `json:"-"`
}
EmbeddingsRequest is a canonical embedding request plus gateway identity.
type EmbeddingsResponse ¶
type EmbeddingsResponse struct {
Response inference.EmbeddingResponse
// Internal fields (not serialized)
CacheStatus string `json:"-"`
CacheAge int `json:"-"` // Seconds since cached
ETag string `json:"-"` // Entity tag for response
CacheCost *CacheCost `json:"-"` // Cache pricing information
// Route evidence (not serialized)
ModelUsed string `json:"-"`
ProviderUsed string `json:"-"`
CredentialSource string `json:"-"`
Attempts int `json:"-"`
RoutingDuration time.Duration `json:"-"`
CatalogSnapshot *runtimecatalog.RoutableSnapshot `json:"-"`
}
EmbeddingsResponse is a canonical embedding result plus gateway metadata.
type EndpointInfo ¶
type EndpointInfo = view.EndpointInfo
EndpointInfo represents an endpoint that can serve a model
type FileResolver ¶ added in v1.1.0
type FileResolver interface {
ResolveDocument(ctx context.Context, account, id string) (StoredDocument, bool, error)
}
FileResolver reads one stored document for one account.
This package names the port rather than importing the file service, so the concept that owns a stored file keeps its own vocabulary and the proxy keeps the one shape it needs.
The account argument is not advisory. A resolver reports an identifier belonging to another account as absent, exactly as it reports an unknown identifier, because an answer that distinguished the two would tell one account which identifiers another account holds.
type GatewayEmbedder ¶ added in v1.2.0
type GatewayEmbedder struct {
// contains filtered or unexported fields
}
GatewayEmbedder adapts the gateway's own embeddings surface to the SemanticEmbedder seam. The embedding rides the account's own identity: credential selection, usage capture, and limits treat it as the account's own embedding request. The gateway is late-bound because composition finishes after the cache middleware is built.
func NewGatewayEmbedder ¶ added in v1.2.0
func NewGatewayEmbedder(model string, gateway func() Proxy) *GatewayEmbedder
NewGatewayEmbedder builds the adapter around a catalog embedding model and a late-bound gateway.
func (*GatewayEmbedder) Embed ¶ added in v1.2.0
func (e *GatewayEmbedder) Embed(ctx context.Context, identity SemanticEmbedIdentity, text string) ([]float32, error)
Embed implements SemanticEmbedder over the gateway's embeddings path.
type GatewayModerator ¶ added in v1.2.0
type GatewayModerator struct {
// contains filtered or unexported fields
}
GatewayModerator adapts the gateway's own moderation surface to the guardrail Moderator seam. The classification rides the account's own routing: it runs under the calling request's identity, so credential selection, usage capture, and limits treat it as the account's own moderation request. The gateway is late-bound because composition finishes after the guardrail pipeline is built.
func NewGatewayModerator ¶ added in v1.2.0
func NewGatewayModerator(model string, gateway func() Proxy) *GatewayModerator
NewGatewayModerator builds the adapter around a catalog moderation model and a late-bound gateway.
func (*GatewayModerator) Moderate ¶ added in v1.2.0
func (m *GatewayModerator) Moderate(ctx context.Context, text string) ([]guardrails.CategoryScore, error)
Moderate implements guardrails.Moderator.
type GuardrailVerdictProvider ¶ added in v1.2.0
type GuardrailVerdictProvider interface {
GuardrailVerdict() string
}
GuardrailVerdictProvider exposes the strongest verdict a stream saw, so the usage middleware outside this one can record it at stream end.
type Guardrails ¶ added in v1.2.0
type Guardrails struct {
// contains filtered or unexported fields
}
Guardrails is a proxy middleware that runs the account's guardrail pipeline over canonical text: the request messages before planning, and the answer before the caller reads it. Composition skips this middleware entirely when no check is configured, so an unconfigured deployment pays nothing here.
func NewGuardrails ¶ added in v1.2.0
func NewGuardrails(policy guardrails.Policy) *Guardrails
NewGuardrails creates the middleware around one policy.
func (*Guardrails) Wrap ¶ added in v1.2.0
func (g *Guardrails) Wrap(next Proxy) Proxy
Wrap implements Middleware.
type ImagesRequest ¶ added in v1.1.0
type ImagesRequest = OperationRequest[inference.ImagesRequest]
ImagesRequest is one gateway image generation or image edit request.
type ImagesResponse ¶ added in v1.1.0
type ImagesResponse = OperationResponse[inference.ImagesResponse]
ImagesResponse is one gateway image result.
type JobAccountant ¶ added in v1.1.0
type JobAccountant struct {
// contains filtered or unexported fields
}
JobAccountant prices one finished job and writes its single usage record.
It lives here rather than in internal/jobs because pricing reads a Starmap offering, and internal/jobs owns job state and nothing else. It lives here rather than in the composition root because this package already holds the catalog-to-cost rules that every other operation uses, and a video priced by a second copy of them would drift from the rest of the bill.
It is deliberately not a method on Proxy. Nothing on the request path calls it: a job settles when a poll, a cancel, or the sweep reaches its terminal state, which may be long after the submitting request returned.
func NewJobAccountant ¶ added in v1.1.0
func NewJobAccountant( snapshots func() *runtimecatalog.RoutableSnapshot, recorder UsageRecorder, ) *JobAccountant
NewJobAccountant returns an accountant over one catalog reader and one record store. Either may be absent, which is what a deployment with usage recording switched off gets: the job still settles and still frees its slot.
func (*JobAccountant) RecordJob ¶ added in v1.1.0
func (a *JobAccountant) RecordJob(ctx context.Context, entry jobs.AccountingEntry) error
RecordJob writes the one usage record a terminal job draws.
A failed job and a cancelled job draw a record with no cost rather than no record. The work is a real event in the account's history, and a spend report that showed only the jobs that succeeded would answer "what did this account do" with a shorter list than the truth. Their cost is zero, which is what CostReasonNoUsage already means everywhere else.
type MediaRequest ¶ added in v1.1.0
type MediaRequest[Request any] = OperationRequest[Request]
MediaRequest routes one canonical media request. The shared carrier is OperationRequest.
type MediaResponse ¶ added in v1.1.0
type MediaResponse[Response any] = OperationResponse[Response]
MediaResponse is one media result. The shared carrier is OperationResponse: reranking is not media, and a media name on the answer it returns would say it was.
type Middleware ¶
type Middleware interface {
// Wrap wraps the given proxy with the middleware functionality
Wrap(Proxy) Proxy
}
Middleware wraps a Proxy with additional functionality. The caching, preset-resolution, and usage-capture seams each implement it, and the composition root layers them around the core proxy.
func NewCacheMiddleware ¶
func NewCacheMiddleware(manager CacheManager, config *CacheConfig, runtime runtimeGenerationSource) Middleware
NewCacheMiddleware creates a new cache middleware.
type ModelArchitecture ¶
type ModelArchitecture = view.ModelArchitecture
ModelArchitecture describes protocol-facing model capabilities.
type ModelAuthorInfo ¶ added in v1.1.0
type ModelAuthorInfo = view.ModelAuthorInfo
ModelAuthorInfo names one catalog author of a model.
type ModelEndpointsResponse ¶
type ModelEndpointsResponse struct {
Model string `json:"model"`
Endpoints []EndpointInfo `json:"endpoints"`
}
ModelEndpointsResponse represents available endpoints for a model
type ModelLineageInfo ¶ added in v1.1.0
type ModelLineageInfo = view.ModelLineageInfo
ModelLineageInfo describes canonical model-family relationships.
type ModelOfferingInfo ¶ added in v1.1.0
type ModelOfferingInfo = view.ModelOfferingInfo
ModelOfferingInfo is one provider's routable offering of a model.
type ModelPricing ¶
type ModelPricing = view.ModelPricing
ModelPricing represents model pricing information
type ModelsResponse ¶
type ModelsResponse struct {
Object string `json:"object"`
Data []ModelInfo `json:"data"`
// Internal fields (not serialized)
CacheStatus string `json:"-"`
}
ModelsResponse represents a list of available models
type ModerationRequest ¶ added in v1.2.0
type ModerationRequest = OperationRequest[inference.ModerationRequest]
ModerationRequest is one gateway moderation request.
type ModerationResponse ¶ added in v1.2.0
type ModerationResponse = OperationResponse[inference.ModerationResponse]
ModerationResponse is one gateway classified input list. It is not cached for the same reason a rerank answer is not: the result reads by position in one caller's own input list.
type OfferingPricingInfo ¶ added in v1.1.0
type OfferingPricingInfo = view.OfferingPricingInfo
OfferingPricingInfo carries every token price dimension of one offering.
type OperationRequest ¶ added in v1.1.0
type OperationRequest[Request any] struct { Request Request APIKey string `json:"-"` // AccountID is the account the request runs under. Credential selection // and account limits read this. AccountID string `json:"-"` // KeyID is the gateway API key that authenticated the request. Usage // attribution and per-key limits read this. KeyID string `json:"-"` // TeamID is the team the serving key is attributed to, or empty for a // teamless key. Usage attribution and the team budget read this. TeamID string `json:"-"` APIKeyConfig *APIKeyRoutingConfig `json:"-"` RequestID string `json:"-"` Protocol string `json:"-"` }
OperationRequest is one canonical request plus gateway identity. Every operation past chat carries the identity a chat request carries, so one type states it once.
type OperationResponse ¶ added in v1.1.0
type OperationResponse[Response any] struct { Response Response ModelUsed string `json:"-"` ProviderUsed string `json:"-"` CredentialSource string `json:"-"` Attempts int `json:"-"` RoutingDuration time.Duration `json:"-"` CatalogSnapshot *runtimecatalog.RoutableSnapshot `json:"-"` // Cost is what this turn cost, once the accounting middleware has priced it // against the snapshot that routed it. It is nil until then, and it stays // nil on a turn the catalog could not price. A protocol that names a cost on // its usage block reads this field, so the number the caller sees and the // number the account is billed come from one derivation. Cost *usage.Cost `json:"-"` }
OperationResponse is one canonical result plus gateway route evidence. It carries no cache fields. A media answer is not cached, because an image and an audio file are large and a caller that repeats a prompt expects a new rendering rather than the previous one. A rerank answer is not cached either, because its result names positions in one caller's own document list and a second caller's list holds different text at those positions.
type Option ¶
type Option func(*Config)
Option configures the proxy service.
func WithCache ¶
func WithCache(manager CacheManager, config *CacheConfig) Option
WithCache enables caching with the specified cache manager and configuration.
func WithDocumentCache ¶ added in v1.1.0
WithDocumentCache reuses one document's text across the turns of a conversation that keeps resending it.
func WithDocumentExtractor ¶ added in v1.1.0
WithDocumentExtractor sets the bounds the native parser engine reads under.
func WithFiles ¶ added in v1.1.0
func WithFiles(resolver FileResolver) Option
WithFiles lets a chat request name a document this gateway already stores instead of carrying its bytes.
func WithTokenEstimator ¶ added in v1.1.0
WithTokenEstimator guarantees every chat stream ends with a usage event: when the provider reports none, the estimator synthesizes estimated counts.
type PresetResolver ¶ added in v1.1.0
type PresetResolver struct {
// contains filtered or unexported fields
}
PresetResolver is a proxy middleware that resolves preset references on chat requests and merges the stored configuration into them. Fields the request supplies win over preset fields; an unknown preset fails the request with ErrPresetNotFound before any routing happens.
func NewPresetResolver ¶ added in v1.1.0
func NewPresetResolver(source PresetSource) *PresetResolver
NewPresetResolver creates the resolution middleware around one source.
func (*PresetResolver) Wrap ¶ added in v1.1.0
func (r *PresetResolver) Wrap(next Proxy) Proxy
Wrap implements Middleware.
type PresetSource ¶ added in v1.1.0
type PresetSource interface {
Get(ctx context.Context, name string) (presets.Record, error)
GetRevision(ctx context.Context, name string, revision uint64) (presets.Record, error)
}
PresetSource resolves one stored preset by name, or one pinned revision of it. The concept-owned repository in internal/presets satisfies it.
type ProviderError ¶
ProviderError represents an error from a provider
func (*ProviderError) Error ¶
func (e *ProviderError) Error() string
func (*ProviderError) Unwrap ¶
func (e *ProviderError) Unwrap() error
type ProviderPolicyInfo ¶ added in v1.1.0
type ProviderPolicyInfo = view.ProviderPolicyInfo
ProviderPolicyInfo summarizes the provider's published data policies.
type ProviderPreferences ¶
type ProviderPreferences struct {
Order []string `json:"order,omitempty"`
Ignore []string `json:"ignore,omitempty"`
Only []string `json:"only,omitempty"`
AllowFallback bool `json:"allow_fallback,omitempty"`
// Sort selects route ordering: "price", "latency", "throughput"
// (routed by measured latency), or "spread" (weighted balance inside
// the leading ranking band). Empty keeps the server default.
Sort string `json:"sort,omitempty"`
// MaxPromptPricePer1M and MaxCompletionPricePer1M cap the accepted route
// price in USD per million tokens. Zero means no cap.
MaxPromptPricePer1M float64 `json:"max_prompt_price_per_1m,omitempty"`
MaxCompletionPricePer1M float64 `json:"max_completion_price_per_1m,omitempty"`
}
ProviderPreferences represents provider routing preferences
type ProvidersResponse ¶
type ProvidersResponse struct {
Providers []ProviderInfo `json:"providers"`
// Internal fields (not serialized)
CacheStatus string `json:"-"`
}
ProvidersResponse represents provider information
type Proxy ¶
type Proxy interface {
// ProcessChatCompletion handles chat completion requests with routing and processing
ProcessChatCompletion(ctx context.Context, req *ChatCompletionRequest) (*ChatCompletionResponse, error)
// ProcessChatCompletionStream handles streaming chat completion requests
ProcessChatCompletionStream(ctx context.Context, req *ChatCompletionRequest) (ChatCompletionStreamResponse, error)
// ProcessEmbeddings handles embedding generation requests
ProcessEmbeddings(ctx context.Context, req *EmbeddingsRequest) (*EmbeddingsResponse, error)
// ProcessRerank scores one document list against a query and answers with
// the caller's own document positions in ranked order.
ProcessRerank(ctx context.Context, req *RerankRequest) (*RerankResponse, error)
// ProcessModerations classifies each input against a provider's harm
// categories and answers with a verdict and a score per category.
ProcessModerations(ctx context.Context, req *ModerationRequest) (*ModerationResponse, error)
// ProcessImages handles image generation and image edit requests.
ProcessImages(ctx context.Context, req *ImagesRequest) (*ImagesResponse, error)
// ProcessSpeech handles text-to-speech requests.
ProcessSpeech(ctx context.Context, req *SpeechRequest) (*SpeechResponse, error)
// ProcessTranscription handles speech-to-text requests, in the spoken
// language or translated into English.
ProcessTranscription(ctx context.Context, req *TranscriptionRequest) (*TranscriptionResponse, error)
// SubmitVideoJob starts one video generation and answers with the
// provider's own job identifier. Nothing above this interface stores that
// identifier except the job record, which never hands it back out.
SubmitVideoJob(ctx context.Context, req *VideoSubmitRequest) (*VideoJobAnswer, error)
// PollVideoJob asks the provider that accepted a job where it got to.
PollVideoJob(ctx context.Context, req *VideoJobRequest) (*VideoJobAnswer, error)
// CancelVideoJob asks the provider that accepted a job to stop it.
CancelVideoJob(ctx context.Context, req *VideoJobRequest) (*VideoJobAnswer, error)
// FetchVideoAsset reads the finished output of one accepted job.
FetchVideoAsset(ctx context.Context, req *VideoAssetRequest) (*VideoAsset, error)
// VideoJobRunner returns the provider side of one caller's video jobs,
// bound to the gateway identity the request carries. The record store
// drives a job through this value and names no transport itself.
VideoJobRunner(req *VideoSubmitRequest) jobs.Runner
// ListModels returns available models based on routing configuration
ListModels(ctx context.Context) (*ModelsResponse, error)
// ListProviders returns available provider information
ListProviders(ctx context.Context) (*ProvidersResponse, error)
// ListAuthors returns catalog author information
ListAuthors(ctx context.Context) (*AuthorsResponse, error)
// GetAuthor returns one catalog author. It reports a not_found
// provider error for an unknown author ID.
GetAuthor(ctx context.Context, authorID string) (*AuthorInfo, error)
// GetModelEndpoints returns provider endpoints for a specific model
GetModelEndpoints(ctx context.Context, modelID string) (*ModelEndpointsResponse, error)
// GetLogo returns the catalog-carried SVG brand mark for one provider
// or author. It reports a not_found provider error when the catalog
// carries no bytes for this kind and ID.
GetLogo(ctx context.Context, kind view.LogoKind, id string) ([]byte, error)
}
Proxy defines the core proxy interface for LLM request handling. This interface serves three primary purposes: 1. Testing - allows easy mocking in unit tests 2. Middleware composition - enables wrapping with caching, logging, metrics, etc. 3. Dependency injection - provides clean separation for HTTP handlers
The proxy handles routing requests to appropriate LLM providers, managing fallbacks, and transforming between different API formats.
func New ¶
func New(registry connectors.LeasingRegistry, router router.ModelRouter, opts ...Option) Proxy
New creates a new proxy service with the given registry and router. Additional functionality can be added using options.
Example:
// Basic proxy
proxy := proxy.New(registry, router)
// Proxy with caching
proxy := proxy.New(registry, router,
proxy.WithCache(cacheManager, cacheConfig),
)
type RerankRequest ¶ added in v1.1.0
type RerankRequest = OperationRequest[inference.RerankRequest]
RerankRequest is one gateway rerank request.
type RerankResponse ¶ added in v1.1.0
type RerankResponse = OperationResponse[inference.RerankResponse]
RerankResponse is one gateway ranked document list.
type RoutingError ¶
RoutingError represents an error during model routing
func (*RoutingError) Error ¶
func (e *RoutingError) Error() string
func (*RoutingError) Unwrap ¶
func (e *RoutingError) Unwrap() error
type SemanticEmbedIdentity ¶ added in v1.2.0
type SemanticEmbedIdentity struct {
AccountID string
KeyID string
TeamID string
RequestID string
Protocol string
}
SemanticEmbedIdentity carries the gateway identity a cache embedding call runs under, so the call pays and meters like the account's own request.
type SemanticEmbedder ¶ added in v1.2.0
type SemanticEmbedder interface {
Embed(ctx context.Context, identity SemanticEmbedIdentity, text string) ([]float32, error)
}
SemanticEmbedder turns canonical prompt text into one vector.
type SpeechRequest ¶ added in v1.1.0
type SpeechRequest = OperationRequest[inference.SpeechRequest]
SpeechRequest is one gateway text-to-speech request.
type SpeechResponse ¶ added in v1.1.0
type SpeechResponse = OperationResponse[inference.SpeechResponse]
SpeechResponse is one gateway speech result.
type StoredDocument ¶ added in v1.1.0
StoredDocument is one stored file's bytes and the name it was stored under.
type StreamUnwrapper ¶ added in v1.1.0
type StreamUnwrapper interface {
Unwrap() ChatCompletionStreamResponse
}
StreamUnwrapper exposes the inner stream of a decorating stream wrapper so cross-cutting middleware can reach route evidence on the routed stream.
type TopProviderInfo ¶
type TopProviderInfo = view.TopProviderInfo
TopProviderInfo describes the selected representative offering limits.
type TranscriptionRequest ¶ added in v1.1.0
type TranscriptionRequest = OperationRequest[inference.TranscriptionRequest]
TranscriptionRequest is one gateway speech-to-text request.
type TranscriptionResponse ¶ added in v1.1.0
type TranscriptionResponse = OperationResponse[inference.TranscriptionResponse]
TranscriptionResponse is one gateway transcript.
type UsageCapture ¶ added in v1.1.0
type UsageCapture struct {
// contains filtered or unexported fields
}
UsageCapture is a proxy middleware that records one usage.Record per completed inference request. Writes are asynchronous, bounded, and best-effort: capture failure never fails or delays a request.
func NewUsageCapture ¶ added in v1.1.0
func NewUsageCapture(recorder UsageRecorder, observers ...UsageObserver) *UsageCapture
NewUsageCapture creates the capture middleware around one recorder. Each observer sees every captured record synchronously, so an observer must be cheap; counter arithmetic is, a network call is not.
func (*UsageCapture) Flush ¶ added in v1.1.0
func (c *UsageCapture) Flush()
Flush waits for every in-flight record write to finish.
func (*UsageCapture) Wrap ¶ added in v1.1.0
func (c *UsageCapture) Wrap(next Proxy) Proxy
Wrap implements Middleware.
type UsageObserver ¶ added in v1.2.0
UsageObserver sees every record this middleware captures, before the asynchronous write. The telemetry seam satisfies it, which is how one choke point feeds both the activity store and the scrape.
type UsageRecorder ¶ added in v1.1.0
UsageRecorder persists one usage record. The concept-owned repository in internal/usage satisfies it.
type ValidationError ¶
ValidationError represents a request validation error
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
type VideoAsset ¶ added in v1.1.0
VideoAsset is one finished output with the route evidence that names who served it. The bytes arrive whole: the caller stores them, and the bound it sent is what makes holding them safe.
type VideoAssetReference ¶ added in v1.1.0
type VideoAssetReference = router.VideoAssetReference
VideoAssetReference names the finished output of one accepted job.
type VideoAssetRequest ¶ added in v1.1.0
type VideoAssetRequest = MediaRequest[VideoAssetReference]
VideoAssetRequest is one gateway read of a finished job's asset.
type VideoJobAnswer ¶ added in v1.1.0
type VideoJobAnswer struct {
ProviderJobID string
State jobs.JobState
Reason string
ModelUsed string
ProviderUsed string
}
VideoJobAnswer is what a provider reported about one job, with the route evidence that names who reported it.
type VideoJobReference ¶ added in v1.1.0
type VideoJobReference = router.VideoJobReference
VideoJobReference names one job a provider already accepted. It is the router type rather than a copy of it, because a copy would be one more place a provider job identifier has to be carried by hand.
type VideoJobRequest ¶ added in v1.1.0
type VideoJobRequest = MediaRequest[VideoJobReference]
VideoJobRequest is one gateway poll or cancel of an accepted job.
type VideoJobRunner ¶ added in v1.1.0
type VideoJobRunner struct {
// contains filtered or unexported fields
}
VideoJobRunner is the provider side of one caller's video jobs.
It exists so internal/jobs can start, poll, and stop work without importing a provider transport or a credential policy. The record hands it a handle for one call, it spends the handle on one request, and it answers in the vocabulary the record keeps.
func (*VideoJobRunner) Fetch ¶ added in v1.1.0
func (r *VideoJobRunner) Fetch( ctx context.Context, handle jobs.Handle, maxBytes int64, ) (jobs.Asset, error)
Fetch reads the finished output of the accepted job.
maxBytes arrives as an argument rather than as a setting this side reads. The record store is the half that holds the bytes, so it is the half that decides how large an asset it is willing to hold.
func (*VideoJobRunner) Submit ¶ added in v1.1.0
func (r *VideoJobRunner) Submit(ctx context.Context) (jobs.Acceptance, error)
Submit starts the work this runner was built for.
type VideoSubmitRequest ¶ added in v1.1.0
type VideoSubmitRequest = MediaRequest[inference.VideoJobRequest]
VideoSubmitRequest is one gateway video generation submission.