router

package
v0.2.0 Latest Latest
Warning

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

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

Documentation

Overview

Package router maps client-facing model aliases to configured providers and implements ai.Service.

Clients choose aliases from ai.models ("smart", "fast", "image", "embed"); an empty alias selects the default of the requested kind (ai.default_model, ai.default_image_model, ai.default_embedding_model). "provider/model-id" is accepted only when ai.allow_raw_models is true (and the model id must look like one: no empty, "." or ".." path segments, no query or whitespace characters). The router validates and normalises requests (role:"system" messages are hoisted into the system prompt, consecutive same-role turns are merged, images are checked), applies the max_tokens caps, prepends ai.system_prompt, applies per-alias effort, bounds every upstream call with ai.request_timeout (streaming and image generation: at least 10 minutes) and reports the alias as the response model.

Limits on max_tokens: the cap is ai.max_tokens, lowered by a per-alias max_tokens when that is smaller (an alias cannot exceed the global cap; raise ai.max_tokens for long-output aliases and give the others their own lower caps); a request without max_tokens gets min(4096, cap). An alias's effort overrides the request's. When an upstream reports no token usage, the router fills in an estimate (about four bytes per token, a flat cost per image) so per-user token limits cannot be bypassed.

Image URLs of the calling site's own content (site-relative upload URLs such as /__backyard/files/{id}/{name}, and absolute URLs of the site's origin) are loaded through the request's ai.ImageResolver, when the HTTP layer supplies one, and sent as inline bytes; without a resolver site-relative URLs are rejected.

Untrusted input is contained: image URLs that a provider needs as inline bytes are downloaded by an SSRF-guarded fetcher within a per-request byte budget (MaxRemoteImageBytes, shared with images loaded through the resolver); end-user ids are replaced by keyed opaque ids (Options.UserIDKey) before they reach a provider; generated images get their media type from their content, and non-raster formats are refused.

Index

Constants

View Source
const (
	KindChat      = "chat"
	KindImage     = "image"
	KindEmbedding = "embedding"
)

Model kinds.

View Source
const (
	// MaxImageBytes is the largest inline image accepted in a chat message.
	MaxImageBytes = 20 << 20
	// MaxImagesPerRequest bounds the number of images in one chat request.
	MaxImagesPerRequest = 50
	// MaxImageCount bounds ImageRequest.N.
	MaxImageCount = 10
	// MaxImagePromptChars bounds ImageRequest.Prompt.
	MaxImagePromptChars = 32000
	// MaxEmbedInputs bounds the number of strings in one embedding request.
	MaxEmbedInputs = 2048
	// MaxEmbedBytes bounds the total size of an embedding request's input.
	MaxEmbedBytes = 8 << 20
	// MaxRemoteImageBytes bounds the total size of the image URLs one chat
	// request makes Backyard load: the site's own uploads (through the
	// request's ai.ImageResolver) and downloads for providers that need
	// inline bytes (Bedrock, Gemini, Claude on Vertex AI/Bedrock, Ollama and
	// other self-hosted OpenAI-compatible servers).
	MaxRemoteImageBytes = 64 << 20
)

Request limits enforced before calling a provider.

Variables

This section is empty.

Functions

func New

func New(ctx context.Context, cfg config.AIConfig, opts Options) (ai.Service, error)

New builds providers from cfg.Providers and validates cfg.Models. When AI is disabled it returns a Service whose Enabled() is false and whose methods return ai.ErrDisabled.

Only providers referenced by a model alias are built (all of them when allow_raw_models is set; failures of unreferenced providers are then logged and the provider is skipped). Construction does no network I/O: cloud credentials (Vertex AI, Bedrock Mantle, Entra ID) are discovered on first use.

Types

type Options

type Options struct {
	HTTPClient *http.Client // used by HTTP-based providers (tests inject fakes)
	Logger     *slog.Logger
	// Providers are prebuilt providers by key. They take precedence over
	// building a provider from cfg.Providers and may also add keys that are
	// not in cfg.Providers (tests, embedding Backyard with custom providers).
	Providers map[string]ai.Provider
	// UserIDKey keys the hash that turns end-user ids (emails) into the
	// opaque ids sent to providers for abuse monitoring (ai.KeyedUserID).
	// Pass the server secret so providers cannot confirm a guessed email;
	// when empty an unkeyed hash (ai.OpaqueUserID) is used.
	UserIDKey []byte
}

Options are optional dependencies.

type Router

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

Router implements ai.Service. It is immutable after New and safe for concurrent use.

func (*Router) Chat

func (r *Router) Chat(ctx context.Context, alias string, req ai.ChatRequest) (*ai.ChatResponse, error)

Chat implements ai.Service.

func (*Router) ChatStream

func (r *Router) ChatStream(ctx context.Context, alias string, req ai.ChatRequest, onDelta func(string) error) (*ai.ChatResponse, error)

ChatStream implements ai.Service.

func (*Router) Embed

func (r *Router) Embed(ctx context.Context, alias string, req ai.EmbedRequest) (*ai.EmbedResponse, string, error)

Embed implements ai.Service.

func (*Router) Enabled

func (r *Router) Enabled() bool

Enabled implements ai.Service.

func (*Router) Image

func (r *Router) Image(ctx context.Context, alias string, req ai.ImageRequest) (*ai.ImageResponse, string, error)

Image implements ai.Service.

func (*Router) Models

func (r *Router) Models() (string, []ai.ModelInfo)

Models implements ai.Service.

Jump to

Keyboard shortcuts

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