models

package
v0.2.0-beta.19 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package models manages AI model resources: an inference engine (Ollama, vLLM, llama.cpp) running as a container on a GPU node, with an OpenAI-compatible endpoint fronted by an API-key gateway.

Index

Constants

View Source
const (
	MetricEngineKVCachePercent = "engine_kv_cache_percent"
	MetricEngineRunning        = "engine_requests_running"
	MetricEngineWaiting        = "engine_requests_waiting"
	MetricEnginePrefixHitPct   = "engine_prefix_cache_hit_percent"
	MetricEngineGenRate        = "engine_tokens_per_second"
	MetricEngineTTFTSeconds    = "engine_ttft_seconds"
	MetricEngineVRAMBytes      = "engine_vram_bytes"
	MetricEngineOffloadPercent = "engine_offload_percent"
)

Sample metric names written for a model's engine under resource "model:<name>".

View Source
const (
	EngineHealthOK      = "ok"
	EngineHealthWarn    = "warn"
	EngineHealthUnknown = "unknown"
)

Engine health states.

View Source
const (
	EngineOllama   = "ollama"
	EngineVLLM     = "vllm"
	EngineLlamaCpp = "llamacpp"
)

Supported engines.

View Source
const (
	WeightsExact     = "exact"
	WeightsEstimated = "estimated"
	WeightsUnknown   = "unknown"
)

Source of the weight size behind a fit result.

View Source
const (
	HFStatusOK          = "ok"
	HFStatusNotFound    = "not_found"
	HFStatusGated       = "gated"
	HFStatusRateLimited = "rate_limited"
	HFStatusUnavailable = "unavailable"
	HFStatusUnsupported = "unsupported"
)

Hub statuses reported by Preflight.

View Source
const (
	FitFits    = "fits"
	FitTight   = "tight"
	FitWontFit = "wont_fit"
	FitUnknown = "unknown"
)

Fit verdicts. FitUnknown means the node facts needed to judge are missing.

View Source
const CacheNote = "Each model keeps its weights in its own Docker volume, so the cache is listed per volume, not per file. " +
	"Last used comes from gateway traffic when a model has any, else from the model's last change. " +
	"Only the control plane's own host is inspected; remote nodes are not listed yet."

CacheNote states what the cache listing can and cannot see.

View Source
const FitNote = "Fit figures are estimates: weights plus a flat overhead for the KV cache and compute buffers. " +
	"Real usage depends on context length, batch size, engine and driver."

FitNote states the limits of every fit number.

View Source
const FitNoteVRAM = "This is an estimate, not a guarantee: weights are sized from the model name and quantization (exact when the Hugging Face file sizes are known), " +
	"the KV cache is approximated from the parameter count and context length, and engine overhead is a flat allowance. " +
	"Real usage depends on the engine version, batch size and driver."

FitNoteVRAM states the limits of the per-node VRAM check.

View Source
const LocalNodeName = "local"

LocalNodeName labels the control plane's own host in GPU listings.

View Source
const UsageNote = "Tokens are counted only for responses that carry a usage object: non-streaming responses, and streams " +
	"opened with stream_options.include_usage. Other requests are counted as requests only, and nothing is estimated. " +
	"Figures lag the gateway by up to one flush interval."

UsageNote explains the limits of the token counts.

Variables

View Source
var (
	ErrInvalid            = errors.New("models: invalid request")
	ErrSecretsUnavailable = errors.New("models: no secrets master key is configured")
	ErrNodeNotFound       = errors.New("models: node not found")
)

Errors returned by Service, distinguishable by callers to pick an HTTP status.

View Source
var ErrKeyExists = errors.New("models: a key with this name already exists")

ErrKeyExists is returned when a live key of the model already has the name.

View Source
var ErrKeyNotFound = errors.New("models: key not found")

ErrKeyNotFound is returned when a model has no such key.

Functions

func AllowedRoutes

func AllowedRoutes(engine string) []string

AllowedRoutes lists the "METHOD path" pairs the gateway forwards for an engine; a trailing slash marks a prefix.

func CacheUnusedDays

func CacheUnusedDays() int

CacheUnusedDays is APP_MODEL_CACHE_UNUSED_DAYS (default 30).

func Command

func Command(m Spec, gpus int) []string

Command returns the engine container's command line. gpus is the resolved number of GPUs the container will see.

func ContainerPrefix

func ContainerPrefix(prefix, name string) string

ContainerPrefix is the name prefix shared by every container of model name, across config revisions.

func ControllerName

func ControllerName(name string) string

ControllerName is the reconcile_status name for model name.

func DefaultIdleTTL

func DefaultIdleTTL() time.Duration

DefaultIdleTTL reads APP_MODEL_IDLE_TTL.

func EngineMetricsInterval

func EngineMetricsInterval() time.Duration

EngineMetricsInterval reads APP_MODEL_ENGINE_METRICS_INTERVAL.

func EngineNames

func EngineNames() []string

EngineNames lists supported engines in stable order.

func Env

func Env(m Spec, hfToken string) map[string]string

Env returns the engine container's environment. hfToken may be empty.

func EstimateWeightBytes

func EstimateWeightBytes(engine, ref, quant string) (int64, bool)

EstimateWeightBytes sizes a model's weights from its name and quantization alone.

func HashAPIKey

func HashAPIKey(plaintext string) string

HashAPIKey returns the SHA-256 hex digest stored for a key.

func IdleTTL

func IdleTTL(m store.Model) time.Duration

IdleTTL is how long an on-demand model may go unused before its engine stops: its own setting, else the platform default.

func KeyMatches

func KeyMatches(plaintext, storedHash string) bool

KeyMatches reports whether plaintext hashes to storedHash, in constant time.

func KeyRotationGrace

func KeyRotationGrace() time.Duration

KeyRotationGrace returns the grace window used when a rotation names none.

func MaxUsageWindow

func MaxUsageWindow() time.Duration

MaxUsageWindow is the longest window Usage serves: the retention, or a year when retention is unlimited.

func ModelClaim

func ModelClaim(m store.Model) gpu.Claim

ModelClaim is the GPU reservation of a model.

func ModelClaimName

func ModelClaimName(name string) string

ModelClaimName is the reservation label of a model.

func NewAPIKey

func NewAPIKey() (plaintext, hash, prefix string, err error)

NewAPIKey returns a fresh plaintext key, its SHA-256 hex hash, and a short non-secret prefix for display. The plaintext is shown once.

func NewKeyID

func NewKeyID() (string, error)

NewKeyID returns a random identifier for a virtual key.

func ParseHFRepo

func ParseHFRepo(in string) (repo, quant string, ok bool)

ParseHFRepo splits a repo reference into "owner/name" and an optional quant, accepting huggingface.co and hf.co URL prefixes.

func ParseParamsBillions

func ParseParamsBillions(ref string) (float64, bool)

ParseParamsBillions extracts the parameter count (in billions) from a model reference such as "llama3.1:8b" or "org/Mixtral-8x7B-GGUF". MoE references count every expert, since all of them stay resident.

func QuantName

func QuantName(path string) string

QuantName extracts the quantization label from a GGUF file path, or "" when there is none or the file is not a weight file.

func ResidencyActive

func ResidencyActive(m store.Model, now time.Time) bool

ResidencyActive reports whether an on-demand model should have its engine running at now: it was used or woken within its idle TTL.

func ServiceClaim

func ServiceClaim(svc store.DesiredService) (gpu.Claim, bool)

ServiceClaim is the GPU reservation of an app, ok false when it asks for none.

func ServiceClaimName

func ServiceClaimName(name string) string

ServiceClaimName is the reservation label of an app.

func ShmBytes

func ShmBytes(engine string) int64

ShmBytes is the /dev/shm size the engine needs (vLLM tensor parallelism exchanges tensors through shared memory). 0 keeps Docker's default.

func ValidateAllowPaths

func ValidateAllowPaths(engine string, paths []string) (string, bool)

ValidateAllowPaths reports the first entry that is not a path the engine's gateway allowlist forwards.

func VolumeName

func VolumeName(prefix, name string) string

VolumeName is the persistent model-cache volume of model name.

Types

type CacheBackend

type CacheBackend interface {
	ListVolumesByPrefix(ctx context.Context, prefix string) ([]docker.NamedVolume, error)
	RemoveVolume(ctx context.Context, name string) error
}

CacheBackend is the Docker surface the cache manager needs.

type CacheEntry

type CacheEntry struct {
	Volume         string     `json:"volume"`
	Model          string     `json:"model,omitempty"`
	Engine         string     `json:"engine,omitempty"`
	ModelRef       string     `json:"model_ref,omitempty"`
	SizeBytes      *int64     `json:"size_bytes"`
	LastUsedAt     *time.Time `json:"last_used_at"`
	LastUsedSource string     `json:"last_used_source"`
	UnusedDays     int        `json:"unused_days"`
	Unused         bool       `json:"unused"`
	InUse          bool       `json:"in_use"`
	Configured     bool       `json:"configured"`
	// DuplicateOf names the volume holding the same weights that is
	// counted in UniqueBytes instead of this one.
	DuplicateOf string `json:"duplicate_of,omitempty"`
	Prunable    bool   `json:"prunable"`
	KeepReason  string `json:"keep_reason,omitempty"`
}

CacheEntry is one cached weights volume.

type CacheNode

type CacheNode struct {
	NodeID           string       `json:"node_id"`
	Name             string       `json:"name"`
	IsLocal          bool         `json:"is_local"`
	Supported        bool         `json:"supported"`
	Message          string       `json:"message,omitempty"`
	Entries          []CacheEntry `json:"entries"`
	TotalBytes       int64        `json:"total_bytes"`
	UniqueBytes      int64        `json:"unique_bytes"`
	ReclaimableBytes int64        `json:"reclaimable_bytes"`
	DiskFreeBytes    *int64       `json:"disk_free_bytes"`
}

CacheNode is one node's cache.

type CachePruneResult

type CachePruneResult struct {
	DryRun         bool         `json:"dry_run"`
	Candidates     []CacheEntry `json:"candidates"`
	Removed        []string     `json:"removed"`
	Skipped        []CacheSkip  `json:"skipped"`
	ReclaimedBytes int64        `json:"reclaimed_bytes"`
}

CachePruneResult reports a prune. With DryRun set nothing was removed and Candidates is what a real run would remove.

type CacheReport

type CacheReport struct {
	UnusedDays int         `json:"unused_days"`
	Nodes      []CacheNode `json:"nodes"`
	Note       string      `json:"note"`
}

CacheReport lists every node's model cache.

type CacheSkip

type CacheSkip struct {
	Volume string `json:"volume"`
	Reason string `json:"reason"`
}

CacheSkip is a volume a prune left alone.

type Controller

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

Controller converges one model row to a running engine container.

func New

func New(name string, st Store, nodes Nodes, rt docker.Runtime, prober Prober, opts ...Option) *Controller

New builds the Controller for model name.

func (*Controller) Name

func (c *Controller) Name() string

Name implements reconcile.Controller.

func (*Controller) Reconcile

func (c *Controller) Reconcile(ctx context.Context) (reconcile.Result, error)

Reconcile implements reconcile.Controller.

type CreateInput

type CreateInput struct {
	Spec    Spec
	NodeID  string
	Domain  string
	HFToken string
	// Residency is "always" (default) or "on_demand". IdleTTL 0 uses the
	// platform default.
	Residency string
	IdleTTL   time.Duration
	// SwapGroup is empty (no group) or a name shared by other models on
	// the same node/GPU; see store.Model.SwapGroup.
	SwapGroup string
}

CreateInput is a request to deploy a model.

type CreateKeyInput

type CreateKeyInput struct {
	Name      string
	CreatedBy string
	ExpiresAt *time.Time
	Limits    KeyLimits
}

CreateKeyInput is a request for a new virtual key.

type Created

type Created struct {
	Model  store.Model
	APIKey string
}

Created is the result of Create; APIKey is the plaintext, shown once.

type CreatedKey

type CreatedKey struct {
	KeyView
	Plaintext string
}

CreatedKey is a new key; Plaintext is shown once and never stored.

type DiskFactsFunc

type DiskFactsFunc func(ctx context.Context, nodeID string) (free, total int64, ok bool)

DiskFactsFunc reports free and total bytes of the disk holding a node's model cache. nodeID is "" for the control plane host. ok is false when the disk cannot be measured.

type Engine

type Engine struct {
	Name         string
	DefaultImage string
	Port         int
	// CachePath is where the engine keeps downloaded weights inside the
	// container; it is backed by a persistent volume.
	CachePath string
	// RefHelp explains the model reference format for error messages.
	RefHelp string
	// contains filtered or unexported fields
}

Engine describes how one inference engine runs as a container.

func EngineFor

func EngineFor(name string) (Engine, bool)

EngineFor returns the named engine.

type EngineHealth

type EngineHealth struct {
	State   string   `json:"state"`
	Summary string   `json:"summary"`
	Reasons []string `json:"reasons"`
}

EngineHealth is a one-line reading of the latest samples.

type EngineMetricPoint

type EngineMetricPoint struct {
	T time.Time `json:"t"`
	V float64   `json:"v"`
}

EngineMetricPoint is one stored reading.

type EngineMetricSeries

type EngineMetricSeries struct {
	ID        string              `json:"id"`
	Label     string              `json:"label"`
	Unit      string              `json:"unit"`
	Supported bool                `json:"supported"`
	Latest    *float64            `json:"latest"`
	Points    []EngineMetricPoint `json:"points"`
}

EngineMetricSeries is one metric over the window. Supported is false when the model's engine cannot expose it.

type EngineMetricsCollector

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

EngineMetricsCollector scrapes each running engine's metrics endpoint and writes the readings to the telemetry store. It reaches engines the same way the readiness prober does.

func NewEngineMetricsCollector

func NewEngineMetricsCollector(st EngineMetricsStore, sink SampleWriter, client *http.Client, logger *slog.Logger) *EngineMetricsCollector

NewEngineMetricsCollector builds a collector. client may be nil.

func (*EngineMetricsCollector) Collect

func (c *EngineMetricsCollector) Collect(ctx context.Context, now time.Time)

Collect scrapes every model once and writes the resulting samples.

func (*EngineMetricsCollector) Run

func (c *EngineMetricsCollector) Run(ctx context.Context, interval time.Duration)

Run collects every interval until ctx ends.

type EngineMetricsReader

type EngineMetricsReader interface {
	Query(ctx context.Context, resourceID, metric string, from, to time.Time) ([]telemetry.Sample, error)
}

EngineMetricsReader reads stored samples. *telemetry.DB satisfies it.

type EngineMetricsReport

type EngineMetricsReport struct {
	Model      string               `json:"model"`
	Engine     string               `json:"engine"`
	From       time.Time            `json:"from"`
	To         time.Time            `json:"to"`
	Collecting bool                 `json:"collecting"`
	Note       string               `json:"note"`
	Health     EngineHealth         `json:"health"`
	Series     []EngineMetricSeries `json:"series"`
}

EngineMetricsReport is a model's engine metrics over a window.

type EngineMetricsStore

type EngineMetricsStore interface {
	ListModels(ctx context.Context) ([]store.Model, error)
}

EngineMetricsStore is the model listing the collector needs.

type FitConfig

type FitConfig struct {
	// OverheadPercent is added to weight bytes for KV cache and buffers.
	OverheadPercent float64
	// FitPercent is the share of free VRAM a model may use to count as
	// "fits"; above it (up to 100%) it is "tight".
	FitPercent float64
	// DiskHeadroomPercent is extra free disk required beyond the download.
	DiskHeadroomPercent float64
}

FitConfig holds the estimation knobs.

func LoadFitConfig

func LoadFitConfig() FitConfig

LoadFitConfig reads APP_MODEL_FIT_OVERHEAD_PERCENT, APP_MODEL_FIT_PERCENT and APP_MODEL_DISK_HEADROOM_PERCENT.

func (FitConfig) Check

func (c FitConfig) Check(p FitParams, in FitInput) FitDetail

Check estimates whether in fits in its GPUs' free VRAM.

func (FitConfig) DiskOK

func (c FitConfig) DiskOK(bytes, freeDisk int64) bool

DiskOK reports whether downloading bytes leaves the configured headroom. freeDisk < 0 means unknown, which counts as OK (the caller reports it).

func (FitConfig) FitVerdict

func (c FitConfig) FitVerdict(weightBytes, freeVRAMBytes int64) string

FitVerdict judges weightBytes against free VRAM. freeVRAMBytes < 0 means unknown.

func (FitConfig) MarkFits

func (c FitConfig) MarkFits(quants []Quant, freeVRAMBytes, freeDiskBytes int64) (name, reason string)

MarkFits sets Fit on every quant and Recommended on the best one, and returns the recommended name with a one-line reason. It picks the largest quantized variant that fits VRAM and disk, then the largest that is tight. With no VRAM facts it falls back to the conventional default.

type FitDetail

type FitDetail struct {
	Verdict        string   `json:"verdict"`
	WeightsSource  string   `json:"weights_source"`
	WeightsBytes   int64    `json:"weights_bytes"`
	KVBytes        int64    `json:"kv_bytes"`
	OverheadBytes  int64    `json:"overhead_bytes"`
	NeedBytes      int64    `json:"need_bytes"`
	FreeBytes      int64    `json:"free_bytes"`
	ContextTokens  int      `json:"context_tokens"`
	ContextAssumed bool     `json:"context_assumed"`
	Arithmetic     string   `json:"arithmetic"`
	Reason         string   `json:"reason,omitempty"`
	Suggestions    []string `json:"suggestions"`
}

FitDetail is the arithmetic behind a verdict.

type FitInput

type FitInput struct {
	Engine        string
	ModelRef      string
	Quantization  string
	ContextLength int
	// WeightsBytes is the exact download size when known; 0 means estimate.
	WeightsBytes int64
	// GPUs is how many GPUs the model spreads over.
	GPUs int
	// FreeBytes is the total free VRAM across those GPUs; MinFreeBytes and
	// MinTotalBytes describe the tightest single GPU.
	FreeBytes     int64
	MinFreeBytes  int64
	MinTotalBytes int64
}

FitInput describes one model against one set of GPUs.

type FitParams

type FitParams struct {
	// GPUOverheadMiB is reserved per GPU for the CUDA context and buffers.
	GPUOverheadMiB int64
	// VLLMExtraMiB is added per GPU for vLLM's CUDA graphs and torch context.
	VLLMExtraMiB int64
	// DefaultContext is assumed when a model sets no context length.
	DefaultContext int
	// VLLMUtilization is the share of each GPU vLLM pre-allocates.
	VLLMUtilization float64
	// KVKiBPerToken overrides the parameter-count heuristic when positive.
	KVKiBPerToken float64
}

FitParams are the VRAM estimation knobs, all environment driven.

func LoadFitParams

func LoadFitParams() FitParams

LoadFitParams reads APP_MODEL_FIT_GPU_OVERHEAD_MIB, APP_MODEL_FIT_VLLM_EXTRA_MIB, APP_MODEL_FIT_DEFAULT_CONTEXT, APP_MODEL_VLLM_GPU_UTILIZATION and APP_MODEL_FIT_KV_KIB_PER_TOKEN.

type FitReport

type FitReport struct {
	Model string    `json:"model,omitempty"`
	Nodes []NodeFit `json:"nodes"`
	Note  string    `json:"note"`
}

FitReport ranks nodes for a model, best first.

type FitRequest

type FitRequest struct {
	Engine        string
	ModelRef      string
	Quantization  string
	ContextLength int
	GPUCount      int
	GPUDeviceIDs  []string
	// WeightsBytes is the exact size from a preflight, 0 to estimate.
	WeightsBytes int64
	// NodeID limits the check to one node; nil checks every GPU node.
	NodeID *string
}

FitRequest asks whether a model fits on GPU nodes.

type GPUNode

type GPUNode struct {
	NodeID     string
	Name       string
	IsLocal    bool
	Info       gpu.Info
	UpdatedAt  time.Time
	ModelCount int
	// PlacementID is the node ID as services and models record it: "" for
	// the control plane's own host.
	PlacementID string
	Schedulable bool
	Online      bool
	Claims      []gpu.Claim
}

GPUNode is one node's GPU snapshot plus the models placed on it.

func (GPUNode) Eligible

func (n GPUNode) Eligible() bool

Eligible reports whether new workloads may be placed on the node.

func (GPUNode) Ledger

func (n GPUNode) Ledger(exclude string) gpu.Ledger

Ledger returns the node's reservations, leaving out the claim named exclude so a workload can be re-checked against its own node.

type Gateway

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

Gateway authenticates OpenAI-compatible requests addressed to a model's host with one of the model's virtual API keys and reverse proxies them to the engine, enforcing the key's limits and metering its usage. Only an allowlist of inference and listing routes is forwarded, so engine admin APIs (Ollama pull and delete, vLLM LoRA loading) are never exposed. Request size, generation length, concurrency and upstream timeouts are bounded by GatewayLimits.

func NewGateway

func NewGateway(st GatewayStore, hosts *HostResolver, logger *slog.Logger) *Gateway

NewGateway builds a Gateway. hosts maps a model to the hostnames it is served on.

func (*Gateway) Handle

func (g *Gateway) Handle(w http.ResponseWriter, r *http.Request) bool

Handle serves r when its Host belongs to a model, returning true. It returns false without touching w for every other host.

func (*Gateway) InFlight

func (g *Gateway) InFlight() map[string]int

InFlight returns the running request count per key id.

func (*Gateway) Invalidate

func (g *Gateway) Invalidate()

Invalidate makes the next request reload models and keys, so a revoked key stops working at once instead of after the cache TTL.

func (*Gateway) Middleware

func (g *Gateway) Middleware(next http.Handler) http.Handler

Middleware wraps next so requests for model hosts are handled by the gateway.

func (*Gateway) SetLimits

func (g *Gateway) SetLimits(l GatewayLimits)

SetLimits replaces the request limits. Call it before serving.

func (*Gateway) SetWakeHook

func (g *Gateway) SetWakeHook(fn func())

SetWakeHook registers a function called (repeatedly, cheaply) while a request waits for a model to wake, typically the reconciler's Nudge.

func (*Gateway) StartMetering

func (g *Gateway) StartMetering(ctx context.Context, st UsageStore)

StartMetering flushes usage to st every flush interval until ctx ends.

type GatewayLimits

type GatewayLimits struct {
	MaxBodyBytes  int64
	MaxN          int
	MaxTokens     int
	MaxInflight   int
	RetryAfter    time.Duration
	DialTimeout   time.Duration
	HeaderTimeout time.Duration
	IdleTimeout   time.Duration
	// WakeWait bounds how long a request to a sleeping on-demand model is
	// held while its engine loads; zero fails fast with Retry-After.
	WakeWait       time.Duration
	WakeRetryAfter time.Duration
	// TouchInterval throttles how often gateway activity is written.
	TouchInterval time.Duration
}

GatewayLimits bounds what one request may cost the engine. The limits are global: they apply to every model.

func DefaultGatewayLimits

func DefaultGatewayLimits() GatewayLimits

DefaultGatewayLimits are the limits used when no environment override is set.

func LoadGatewayLimits

func LoadGatewayLimits() GatewayLimits

LoadGatewayLimits reads the limits from the environment, falling back to the defaults for unset or unparsable values.

func (GatewayLimits) Summary

func (l GatewayLimits) Summary() GatewayLimitsSummary

Summary returns the limits as shown to operators.

type GatewayLimitsSummary

type GatewayLimitsSummary struct {
	MaxBodyBytes           int64 `json:"max_body_bytes"`
	MaxN                   int   `json:"max_n"`
	MaxTokens              int   `json:"max_tokens"`
	MaxInflight            int   `json:"max_inflight_requests"`
	ResponseHeaderTimeoutS int   `json:"response_header_timeout_seconds"`
	StreamIdleTimeoutS     int   `json:"stream_idle_timeout_seconds"`
}

GatewayLimitsSummary is the read-only view of the limits shown on the model resource. A zero value means the limit is disabled.

type GatewayStore

type GatewayStore interface {
	ListModels(ctx context.Context) ([]store.Model, error)
	ListActiveModelKeys(ctx context.Context) ([]store.ModelKey, error)
}

GatewayStore is the store surface the gateway reads.

type HFClient

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

HFClient queries the Hub's public metadata API. It refuses internal addresses and never logs or returns the token it is given.

func NewHFClient

func NewHFClient(cfg HFConfig, httpClient *http.Client, logger *slog.Logger) *HFClient

NewHFClient builds a client. httpClient nil uses the SSRF-guarded client.

func (*HFClient) CacheTTL

func (c *HFClient) CacheTTL() time.Duration

CacheTTL is how long Repo answers are reused.

func (*HFClient) Repo

func (c *HFClient) Repo(ctx context.Context, repo, token string) (r *HFRepo, cached bool, err error)

Repo returns the repository's metadata. Errors are *HFError. cached is true when the answer came from the short-lived cache.

type HFConfig

type HFConfig struct {
	BaseURL          string
	Timeout          time.Duration
	CacheTTL         time.Duration
	MaxResponseBytes int64
	CacheEntries     int
}

HFConfig tunes the Hugging Face Hub client.

func LoadHFConfig

func LoadHFConfig() HFConfig

LoadHFConfig reads APP_HF_BASE_URL, APP_HF_TIMEOUT, APP_HF_CACHE_TTL and APP_HF_MAX_RESPONSE_BYTES, falling back to defaults on missing or bad values.

type HFError

type HFError struct {
	Status     string
	Message    string
	RetryAfter time.Duration
}

HFError carries a non-success Hub outcome.

func (*HFError) Error

func (e *HFError) Error() string

type HFFile

type HFFile struct {
	Name  string `json:"name"`
	Bytes int64  `json:"bytes"`
}

HFFile is one file of a Hub repository.

type HFRepo

type HFRepo struct {
	ID      string
	Gated   string
	Private bool
	License string
	Files   []HFFile
	// Access is "granted", "denied" or "unknown" for a gated repo, and
	// "not_required" otherwise.
	Access string
}

HFRepo is the Hub metadata Preflight needs.

type HTTPProber

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

HTTPProber probes engines over their HTTP API and drives Ollama model pulls in the background so a reconcile pass never blocks on a download.

func NewHTTPProber

func NewHTTPProber() *HTTPProber

NewHTTPProber builds an HTTPProber.

func (*HTTPProber) Probe

func (p *HTTPProber) Probe(ctx context.Context, engine, dial, modelRef string) Status

Probe implements Prober.

type HostLister

type HostLister struct {
	Store GatewayStore
	Hosts *HostResolver
}

HostLister is what the ingress controller needs to route model hosts.

func (HostLister) ModelHosts

func (l HostLister) ModelHosts(ctx context.Context) ([]string, error)

ModelHosts returns every hostname of every live model.

type HostResolver

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

HostResolver computes the hostnames a model is served on: its configured domain, or the zero-config fallback derived from the control plane's public host.

func NewHostResolver

func NewHostResolver(publicHost string, fallback func(publicHost, label string) (string, bool)) *HostResolver

NewHostResolver builds a HostResolver. fallback may be nil (no fallback hostnames).

func (*HostResolver) BaseURL

func (h *HostResolver) BaseURL(m store.Model) string

BaseURL returns the OpenAI-compatible base URL for m, or empty when it has no reachable hostname.

func (*HostResolver) Hosts

func (h *HostResolver) Hosts(m store.Model) []string

Hosts returns the hostnames serving m.

type KeyLimits

type KeyLimits struct {
	RPM         int
	TPM         int
	TPD         int
	MaxParallel int
	AllowPaths  []string
	AllowModels []string
}

KeyLimits are the optional per-key limits. Zero means unlimited and empty allow lists mean anything the engine allowlist forwards.

type KeyStatus

type KeyStatus string

KeyStatus describes where a key is in its life.

const (
	KeyActive   KeyStatus = "active"
	KeyRotating KeyStatus = "rotating"
	KeyExpired  KeyStatus = "expired"
	KeyRevoked  KeyStatus = "revoked"
)

Key statuses.

type KeyUsage

type KeyUsage struct {
	KeyID     string `json:"key_id"`
	Name      string `json:"name"`
	KeyPrefix string `json:"key_prefix"`
	Status    string `json:"status"`
	InFlight  int    `json:"in_flight"`
	UsageTotals
}

KeyUsage is one key's share of the window.

type KeyView

type KeyView struct {
	store.ModelKey
	Status   KeyStatus
	InFlight int
}

KeyView is a key without its hash, with its derived status.

type MeterConfig

type MeterConfig struct {
	FlushInterval time.Duration
	BatchSize     int
	MaxBuffered   int
	Retention     time.Duration
	ScanBytes     int
}

MeterConfig bounds usage metering. A non-positive Retention keeps rows forever; a non-positive ScanBytes turns off token parsing.

func DefaultMeterConfig

func DefaultMeterConfig() MeterConfig

DefaultMeterConfig returns the metering defaults.

func LoadMeterConfig

func LoadMeterConfig() MeterConfig

LoadMeterConfig reads the metering config from the environment.

type NodeFit

type NodeFit struct {
	NodeID   string `json:"node_id"`
	Name     string `json:"name"`
	IsLocal  bool   `json:"is_local"`
	Eligible bool   `json:"eligible"`
	// Current marks the node a deployed model already runs on.
	Current    bool  `json:"current"`
	GPUs       int   `json:"gpus"`
	TotalBytes int64 `json:"total_bytes"`
	// ReservedBytes is VRAM estimated for other models placed here that are
	// not loaded yet, already subtracted from free.
	ReservedBytes int64 `json:"reserved_bytes"`
	FitDetail
}

NodeFit is the verdict for one node.

type NodeInfo

type NodeInfo struct {
	GPU gpu.Info
	// BindIP is the address the engine's port is published on.
	BindIP string
	// DialHost is the address the control plane reaches BindIP at. Empty
	// means the node is remote and not on the mesh.
	DialHost string
}

NodeInfo is what the controller needs to know about a model's node.

type Nodes

type Nodes interface {
	NodeInfo(ctx context.Context, nodeID string) (NodeInfo, error)
}

Nodes resolves a model's node. nodeID "" is the local node.

type Option

type Option func(*Controller)

Option configures a Controller.

func WithClock

func WithClock(now func() time.Time) Option

WithClock overrides the clock used for idle decisions.

func WithContainerPrefix

func WithContainerPrefix(p string) Option

WithContainerPrefix sets the container and volume name prefix (typically brand.ShortName).

func WithImages

func WithImages(images map[string]string) Option

WithImages overrides engine images by engine name.

func WithSecrets

func WithSecrets(s Secrets) Option

WithSecrets enables resolving the model's HuggingFace token and deleting its secrets on teardown. Without it, a model with a token set stays blocked.

type Phase

type Phase string

Phase is how far a model engine has got.

const (
	PhaseUnreachable Phase = "unreachable"
	PhaseDownloading Phase = "downloading"
	PhaseLoading     Phase = "loading"
	PhaseReady       Phase = "ready"
	PhaseFailed      Phase = "failed"
)

Model engine phases.

type PreflightDisk

type PreflightDisk struct {
	Status        string `json:"status"`
	RequiredBytes int64  `json:"required_bytes"`
	FreeBytes     *int64 `json:"free_bytes"`
	Message       string `json:"message"`
}

PreflightDisk is the disk check for the selected download.

type PreflightFile

type PreflightFile struct {
	Name  string `json:"name"`
	Bytes int64  `json:"bytes"`
}

PreflightFile is one repository file.

type PreflightInput

type PreflightInput struct {
	// Repo is "owner/name", optionally ":quant", or a huggingface.co URL.
	Repo   string
	Engine string
	File   string
	Quant  string
	NodeID string
	// GPUCount is how many GPUs the model will use; 0 or less means all.
	GPUCount int
	// Token is used for this request only and never stored or logged.
	Token string
}

PreflightInput is a request to check a repository before deploying.

type PreflightNode

type PreflightNode struct {
	NodeID         string `json:"node_id"`
	GPUPresent     bool   `json:"gpu_present"`
	VRAMTotalBytes *int64 `json:"vram_total_bytes"`
	VRAMFreeBytes  *int64 `json:"vram_free_bytes"`
	DiskFreeBytes  *int64 `json:"disk_free_bytes"`
	DiskTotalBytes *int64 `json:"disk_total_bytes"`
}

PreflightNode is the target node's facts. Nil numbers are unknown.

type PreflightResult

type PreflightResult struct {
	Repo               string              `json:"repo"`
	Status             string              `json:"status"`
	Exists             bool                `json:"exists"`
	Message            string              `json:"message"`
	NextStep           string              `json:"next_step,omitempty"`
	RetryAfterSeconds  int                 `json:"retry_after_seconds,omitempty"`
	Gated              string              `json:"gated,omitempty"`
	Access             string              `json:"access,omitempty"`
	Private            bool                `json:"private"`
	License            string              `json:"license,omitempty"`
	TotalBytes         int64               `json:"total_bytes"`
	FileCount          int                 `json:"file_count"`
	Files              []PreflightFile     `json:"files"`
	FilesTruncated     bool                `json:"files_truncated"`
	HasGGUF            bool                `json:"has_gguf"`
	HasSafetensors     bool                `json:"has_safetensors"`
	CompatibleEngines  []string            `json:"compatible_engines"`
	EngineHint         string              `json:"engine_hint"`
	Quants             []Quant             `json:"quants"`
	RecommendedQuant   string              `json:"recommended_quant,omitempty"`
	RecommendationNote string              `json:"recommendation_note,omitempty"`
	Selected           *PreflightSelection `json:"selected,omitempty"`
	Node               PreflightNode       `json:"node"`
	Disk               PreflightDisk       `json:"disk"`
	Warnings           []string            `json:"warnings"`
	EstimateNote       string              `json:"estimate_note"`
	Cached             bool                `json:"cached"`
}

PreflightResult is the outcome of Preflight. It always describes the repository as far as the Hub allowed, with Status saying how far that was.

type PreflightSelection

type PreflightSelection struct {
	Label string `json:"label"`
	Bytes int64  `json:"bytes"`
	Fit   string `json:"fit"`
}

PreflightSelection is what a deploy would download.

type Prober

type Prober interface {
	Probe(ctx context.Context, engine, dial, modelRef string) Status
}

Prober reports whether a running engine has loaded its model.

type Quant

type Quant struct {
	Name        string   `json:"name"`
	Bytes       int64    `json:"bytes"`
	Files       []string `json:"files"`
	Fit         string   `json:"fit"`
	Recommended bool     `json:"recommended"`
}

Quant is one GGUF quantization of a repository: all shards of one variant summed.

func DetectQuants

func DetectQuants(files []HFFile) []Quant

DetectQuants groups GGUF files by quantization, smallest first. Split shards of one variant are summed.

type SampleWriter

type SampleWriter interface {
	WriteSamples(ctx context.Context, samples []telemetry.Sample) error
}

SampleWriter persists telemetry samples.

type SecretWriter

type SecretWriter interface {
	SetValue(ctx context.Context, serviceName, envKey, plaintext string) error
	DeleteAll(ctx context.Context, serviceName string) error
}

SecretWriter stores the HuggingFace token.

type Secrets

type Secrets interface {
	Resolve(ctx context.Context, serviceName, envKey string) (string, error)
	DeleteAll(ctx context.Context, serviceName string) error
}

Secrets is the narrow secrets surface the controller needs.

type Service

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

Service implements model management for the API, CLI and MCP surfaces.

func NewService

func NewService(st ServiceStore, secrets SecretWriter, hosts *HostResolver, localNodeID string) *Service

NewService builds a Service. secrets may be nil (HuggingFace tokens are then rejected). localNodeID identifies the control plane's own node so its GPU snapshot is found under the local key.

func (*Service) CacheEnabled

func (s *Service) CacheEnabled() bool

CacheEnabled reports whether the cache manager is available.

func (*Service) CacheList

func (s *Service) CacheList(ctx context.Context) (CacheReport, error)

CacheList reports model weight volumes with size, last use and whether each is safe to prune.

func (*Service) CachePrune

func (s *Service) CachePrune(ctx context.Context, volumes []string, dryRun bool) (CachePruneResult, error)

CachePrune removes prunable volumes: not mounted, not owned by any configured model, and unused for CacheUnusedDays. volumes narrows the candidates; empty means all. With dryRun nothing is removed.

func (*Service) Create

func (s *Service) Create(ctx context.Context, in CreateInput) (Created, error)

Create validates and stores a new model, returning its one-time API key.

func (*Service) CreateKey

func (s *Service) CreateKey(ctx context.Context, model string, in CreateKeyInput) (CreatedKey, error)

CreateKey adds a named key to a model and returns its plaintext once.

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, name string) error

Delete tombstones the model; its controller removes the container and row.

func (*Service) EngineMetrics

func (s *Service) EngineMetrics(ctx context.Context, name string, window time.Duration) (EngineMetricsReport, error)

EngineMetrics returns the model's engine metrics over window.

func (*Service) FitCheck

func (s *Service) FitCheck(ctx context.Context, req FitRequest) (FitReport, error)

FitCheck rates a model against GPU nodes.

func (*Service) GPUNodes

func (s *Service) GPUNodes(ctx context.Context) ([]GPUNode, error)

GPUNodes lists every node that has reported a GPU snapshot, the local host first.

func (*Service) Get

func (s *Service) Get(ctx context.Context, name string) (View, error)

Get returns one model with status.

func (*Service) List

func (s *Service) List(ctx context.Context) ([]View, error)

List returns every model with status.

func (*Service) ListKeys

func (s *Service) ListKeys(ctx context.Context, model string) ([]KeyView, error)

ListKeys returns every key of a model, revoked ones included.

func (*Service) ModelFit

func (s *Service) ModelFit(ctx context.Context, name string) (FitReport, error)

ModelFit rates a deployed model against every GPU node, marking its own.

func (*Service) NodeGPU

func (s *Service) NodeGPU(ctx context.Context, nodeID string) (info gpu.Info, known bool, err error)

NodeGPU returns the GPU snapshot of nodeID ("" or the local node ID is the control plane's host). known is false when the node has not reported yet.

func (*Service) Preflight

func (s *Service) Preflight(ctx context.Context, in PreflightInput) (PreflightResult, error)

Preflight checks a Hugging Face repository against a node before a model is created. Hub failures come back as a Status, not an error.

func (*Service) PreflightEnabled

func (s *Service) PreflightEnabled() bool

PreflightEnabled reports whether Preflight can run.

func (*Service) Restart

func (s *Service) Restart(ctx context.Context, name string) error

Restart recreates the model's container.

func (*Service) RevokeKey

func (s *Service) RevokeKey(ctx context.Context, model, id string) error

RevokeKey stops a key from working at once.

func (*Service) RotateKey

func (s *Service) RotateKey(ctx context.Context, name string) (string, error)

RotateKey replaces the model's "default" key at once, with no grace.

func (*Service) RotateKeyByID

func (s *Service) RotateKeyByID(ctx context.Context, model, id, actor string, grace *time.Duration) (CreatedKey, error)

RotateKeyByID issues a replacement for a key with the same name, limits and expiry. The old key keeps working for grace (KeyRotationGrace when nil, no grace when zero) and is then dead.

func (*Service) SetCacheBackend

func (s *Service) SetCacheBackend(b CacheBackend, prefix string)

SetCacheBackend enables the cache manager. prefix is the container and volume name prefix the model controller uses.

func (*Service) SetDiskFacts

func (s *Service) SetDiskFacts(fn DiskFactsFunc)

SetDiskFacts registers the source of node disk facts.

func (*Service) SetEngineMetricsReader

func (s *Service) SetEngineMetricsReader(r EngineMetricsReader)

SetEngineMetricsReader enables EngineMetrics. Call once at startup.

func (*Service) SetHFToken

func (s *Service) SetHFToken(ctx context.Context, name, token string) error

SetHFToken stores a new HuggingFace token and restarts the model so it takes effect.

func (*Service) SetHuggingFace

func (s *Service) SetHuggingFace(c *HFClient, fit FitConfig)

SetHuggingFace enables Preflight. Call once at startup.

func (*Service) SetKeyChangeHook

func (s *Service) SetKeyChangeHook(fn func())

SetKeyChangeHook registers fn to run after any key is created, revoked or rotated, so the gateway can drop its cached key list.

func (*Service) SetLiveStats

func (s *Service) SetLiveStats(fn func() map[string]int)

SetLiveStats registers a source of running request counts per key id.

func (*Service) SetLocalNodeID

func (s *Service) SetLocalNodeID(id string)

SetLocalNodeID tells the service which node ID is the control plane's own host. Call once at startup before serving requests.

func (*Service) SetResidency

func (s *Service) SetResidency(ctx context.Context, name, residency string, idleTTL time.Duration) error

SetResidency changes a model's residency mode and idle TTL (0 keeps the platform default). Switching to on-demand counts as activity.

func (*Service) SetSwapGroup

func (s *Service) SetSwapGroup(ctx context.Context, name, group string) error

SetSwapGroup changes a model's swap group. Empty clears it.

func (*Service) Sleep

func (s *Service) Sleep(ctx context.Context, name string) error

Sleep marks an on-demand model idle so its engine stops on the next reconcile pass.

func (*Service) UnplacedWorkloads

func (s *Service) UnplacedWorkloads(ctx context.Context) ([]Unplaced, error)

UnplacedWorkloads lists GPU apps and models whose own node cannot serve them and for which no other eligible GPU node has enough free GPUs.

func (*Service) Usage

func (s *Service) Usage(ctx context.Context, model string, window time.Duration) (UsageReport, error)

Usage reports a model's usage over the last window, hourly and per key.

func (*Service) Wake

func (s *Service) Wake(ctx context.Context, name string) error

Wake marks an on-demand model active so its engine starts now.

type ServiceStore

type ServiceStore interface {
	SaveModel(ctx context.Context, m store.Model) error
	GetModel(ctx context.Context, name string) (*store.Model, error)
	ListModels(ctx context.Context) ([]store.Model, error)
	DeleteModel(ctx context.Context, name string) error
	MarkModelDeleting(ctx context.Context, name string) error
	RotateModelAPIKey(ctx context.Context, name, hash, prefix string) error
	ListModelKeys(ctx context.Context, model string) ([]store.ModelKey, error)
	GetModelKey(ctx context.Context, model, id string) (*store.ModelKey, error)
	CreateModelKey(ctx context.Context, k store.ModelKey) error
	RevokeModelKey(ctx context.Context, model, id string, now time.Time) error
	RotateModelKey(ctx context.Context, model, oldID string, next store.ModelKey, graceUntil *time.Time, now time.Time) error
	ListModelUsage(ctx context.Context, model string, from, to time.Time) ([]store.ModelUsage, error)
	RestartModel(ctx context.Context, name string) error
	SetModelHFTokenSet(ctx context.Context, name string, set bool) error
	SetModelResidency(ctx context.Context, name, residency string, idleTTLSeconds int, now time.Time) error
	TouchModel(ctx context.Context, name string, at time.Time) error
	SleepModel(ctx context.Context, name string) error
	SetModelSwapGroup(ctx context.Context, name, group string) error
	ListModelsInSwapGroup(ctx context.Context, group string) ([]store.Model, error)
	GetConditions(ctx context.Context, controllerName string) ([]reconcile.Condition, error)
	GetConditionsForControllers(ctx context.Context, controllerNames []string) (map[string][]reconcile.Condition, error)
	GetNode(ctx context.Context, id string) (*store.Node, error)
	GetNodeGPU(ctx context.Context, nodeID string) (store.NodeGPU, bool, error)
	ListNodes(ctx context.Context) ([]store.Node, error)
	ListNodeGPUs(ctx context.Context) (map[string]store.NodeGPU, error)
	ListDesiredServices(ctx context.Context) ([]store.DesiredService, error)
}

ServiceStore is the store surface Service uses. *store.DB satisfies it.

type Spec

type Spec struct {
	Name          string
	Engine        string
	ModelRef      string
	GPUCount      int
	GPUDeviceIDs  []string
	ContextLength int
	Quantization  string
}

Spec is the validated user input for a model.

func SpecFromModel

func SpecFromModel(m *store.Model) Spec

SpecFromModel converts a stored model into its Spec.

func (Spec) Validate

func (s Spec) Validate() error

Validate checks s against its engine's rules.

type Status

type Status struct {
	Phase  Phase
	Detail string
}

Status is one probe result.

type Store

type Store interface {
	GetModel(ctx context.Context, name string) (*store.Model, error)
	SetModelEndpoint(ctx context.Context, name, dial string) error
	SetModelResidencyState(ctx context.Context, name, state string) error
	DeleteModel(ctx context.Context, name string) error
	// ListModelsInSwapGroup backs swap group eviction (residency.go's
	// waitForGPUWithSwap): finding a resident sibling to stop before
	// waking a model that would otherwise not fit.
	ListModelsInSwapGroup(ctx context.Context, group string) ([]store.Model, error)
}

Store is the narrow store surface the controller needs.

type Unplaced

type Unplaced struct {
	Kind   string
	Name   string
	NodeID string
	Reason string
}

Unplaced is a GPU workload no reported node can host right now.

type UsagePoint

type UsagePoint struct {
	Hour time.Time `json:"hour"`
	UsageTotals
}

UsagePoint is one hour of usage across all keys.

type UsageReport

type UsageReport struct {
	Model    string       `json:"model"`
	From     time.Time    `json:"from"`
	To       time.Time    `json:"to"`
	Totals   UsageTotals  `json:"totals"`
	Series   []UsagePoint `json:"series"`
	Keys     []KeyUsage   `json:"keys"`
	InFlight int          `json:"in_flight"`
	Note     string       `json:"note"`
}

UsageReport is a model's gateway usage over a window.

type UsageStore

type UsageStore interface {
	AddModelUsage(ctx context.Context, rows []store.ModelUsage) error
	TouchModelKeys(ctx context.Context, used map[string]time.Time) error
	PruneModelUsage(ctx context.Context, before time.Time) (int64, error)
}

UsageStore is the store surface the meter flushes to.

type UsageTotals

type UsageTotals struct {
	Requests      int64 `json:"requests"`
	Status2xx     int64 `json:"status_2xx"`
	Status4xx     int64 `json:"status_4xx"`
	Status5xx     int64 `json:"status_5xx"`
	RateLimited   int64 `json:"rate_limited"`
	UsageRequests int64 `json:"usage_requests"`
	InputTokens   int64 `json:"input_tokens"`
	OutputTokens  int64 `json:"output_tokens"`
	BytesOut      int64 `json:"bytes_out"`
	AvgDurationMs int64 `json:"avg_duration_ms"`
	AvgTTFTMs     int64 `json:"avg_ttft_ms"`
	// contains filtered or unexported fields
}

UsageTotals sums gateway usage over a set of hourly rows.

type View

type View struct {
	Model   store.Model
	Ready   bool
	Reason  string
	Message string
	BaseURL string
	// SharesGPUWith is every other model in the same non-empty
	// SwapGroup on the same node, excluding this one.
	SharesGPUWith []string
}

View is a model with its reconcile status and endpoint.

type WakeStore

type WakeStore interface {
	GetModel(ctx context.Context, name string) (*store.Model, error)
	TouchModel(ctx context.Context, name string, at time.Time) error
}

WakeStore is the optional store surface that lets the gateway wake and keep alive on-demand models. *store.DB satisfies it; a store without it leaves on-demand models unreachable while asleep.

Jump to

Keyboard shortcuts

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