// Package ocr is majordomo's canonical document text-recognition surface. // Like imagegen/audio/videogen/musicgen, it is a deliberately separate leaf // contract from the llm package (ADR-0023, following the ADR-0016→0022 // lineage: functional options, zero values = backend default, bytes-only // I/O, Raw escape hatch). OCR is not chat-vision: it targets dedicated // detection+recognition models (Surya style) that return exact per-page, // per-line text rather than a model's paraphrase. // // The first implementation is provider/llamaswap, which posts the document // to a Surya shim through the /upstream passthrough; the shim rasterizes // PDFs itself, so Document may be an image (png/jpg/webp) or a PDF. package ocr import "context" // Request is a text-recognition request. Zero values mean "backend default". type Request struct { // Document is the encoded document to recognize: an image (png/jpg/webp) // or a PDF. Required. Carried as bytes, never a URL. Document []byte // MIME is the document MIME type (e.g. "image/png", "application/pdf"); // "" = let the backend sniff it. MIME string // Filename is the multipart filename hint some backends key their format // detection on; "" derives one from MIME ("document.pdf") or falls back // to "document". Filename string // Languages are ISO-639 hints for the recognizer (e.g. "en", "de"); // nil = backend default (auto/multilingual). Languages []string // MaxPages caps how many pages of a multi-page document are recognized; // 0 = backend default (all pages, up to the backend's own ceiling). MaxPages int } // Page is the recognized text of one page. type Page struct { // Number is the 1-based page number. Number int // Text is the page's recognized text. Text string } // Result is the canonical text-recognition result. type Result struct { // Text is the full recognized text, pages joined in order. Text string // Pages are the per-page results in page order. Pages []Page // Raw is the provider-native response object (e.g. the per-line // bbox/confidence/layout detail), an escape hatch for provider-specific // fields. May be nil; never required for normal use. Raw any } // Option mutates a Request before it is sent. Options passed to Recognize are // applied to a copy of the request, so a Request value can be reused. type Option func(*Request) // WithLanguages sets the recognizer language hints. func WithLanguages(langs ...string) Option { return func(r *Request) { r.Languages = langs } } // WithMaxPages caps how many pages are recognized. func WithMaxPages(n int) Option { return func(r *Request) { r.MaxPages = n } } // Apply returns a copy of the request with all options applied. Providers // call this once at the top of Recognize. func (r Request) Apply(opts ...Option) Request { for _, opt := range opts { opt(&r) } return r } // Model recognizes text in documents. type Model interface { // Recognize extracts the document's text, page by page. Recognize(ctx context.Context, req Request, opts ...Option) (*Result, error) } // ModelOption configures a Model at construction time. Reserved for future // per-model settings. type ModelOption func(*ModelConfig) // ModelConfig carries per-model construction settings. type ModelConfig struct{} // ApplyModelOptions folds options into a config. func ApplyModelOptions(opts []ModelOption) ModelConfig { var cfg ModelConfig for _, opt := range opts { opt(&cfg) } return cfg } // Provider mints OCR models bound to one backend. type Provider interface { // Name is the registry identifier for the provider. Name() string // OCRModel returns a Model bound to the given id (passed through to the // backend verbatim; no catalog validation). OCRModel(id string, opts ...ModelOption) (Model, error) }