feat: wave-3 image + document surfaces — segmentation, colorize, face restore, ocr (ADR-0023)
- imagegen.Segmenter/SegmentationProvider: prompted mask via POST /upstream/<id>/v1/segment (file, prompt[, threshold], output=mask); white = prompted region, EditRequest.Mask polarity. - imagegen.Colorizer/ColorizeProvider: POST /upstream/<id>/v1/colorize. - imagegen.FaceRestorer/FaceRestoreProvider: POST /upstream/<id>/v1/restore_faces (upscale 1|2). - New ocr leaf package (Request/Page/Result, Recognize) + llamaswap OCRModel: POST /upstream/<id>/v1/ocr (file[, langs, max_pages]), tolerant per-page decode (join lines when page text absent), Raw escape hatch. - httptest contract tests per surface; ADR-0023; ADR index backfilled (0020-0022 rows were missing). Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
+114
@@ -0,0 +1,114 @@
|
||||
// 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)
|
||||
}
|
||||
Reference in New Issue
Block a user