feat: media expansion surfaces — edit mask, upscale, background removal, interpolation, diarization, meshgen (ADR-0020)
- imagegen.EditRequest.Mask -> sd-server img2img inpainting (white=repaint) - imagegen.Upscaler + BackgroundRemover, videogen.Interpolator, audio.DiarizationModel: new optional provider-minted surfaces - NEW meshgen leaf package (image->3D, glb/stl/obj) - provider/llamaswap: all five via the /upstream/<model>/<path> passthrough (upstreamPath helper, shared one-file multipart builder); binary success bodies validated (non-image, non-video, JSON-mesh rejection); diarization pins output=json (vtt/srt drop speaker labels) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
// Package meshgen is majordomo's canonical image-to-3D surface. Like
|
||||
// imagegen/audio/videogen, it is a deliberately separate leaf contract from
|
||||
// the llm package: mesh generation shares none of the chat machinery, so it
|
||||
// gets its own small Provider/Model interfaces (ADR-0020, following the
|
||||
// ADR-0016→0019 lineage: functional options, zero values = backend default,
|
||||
// bytes-only I/O, Raw escape hatch).
|
||||
//
|
||||
// The first implementation is provider/llamaswap, which targets a
|
||||
// Hunyuan3D-2.1-style api_server reached through the /upstream passthrough.
|
||||
// The surface is image-to-3D only: text-to-3D is the composition
|
||||
// imagegen.Generate → meshgen.Generate, owned by the caller.
|
||||
package meshgen
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gitea.stevedudenhoeffer.com/steve/majordomo/llm"
|
||||
)
|
||||
|
||||
// Image is the conditioning input (bytes + MIME), aliased to llm.ImagePart so
|
||||
// chat- or imagegen-sourced images feed mesh generation without conversion.
|
||||
type Image = llm.ImagePart
|
||||
|
||||
// Mesh is one generated 3D asset: raw encoded bytes plus its format.
|
||||
type Mesh struct {
|
||||
// Data is the encoded mesh (binary GLB/STL/OBJ container).
|
||||
Data []byte
|
||||
|
||||
// Format is the lowercase container name ("glb", "stl", "obj").
|
||||
Format string
|
||||
|
||||
// MIME is the corresponding MIME type, e.g. "model/gltf-binary",
|
||||
// "model/stl".
|
||||
MIME string
|
||||
}
|
||||
|
||||
// Request is an image-to-3D generation request. Zero values mean "backend
|
||||
// default".
|
||||
type Request struct {
|
||||
// Image is the source image the mesh is reconstructed from. Required.
|
||||
Image Image
|
||||
|
||||
// Format is the requested output container ("glb", "stl", "obj");
|
||||
// "" = backend default (glb).
|
||||
Format string
|
||||
|
||||
// Texture asks the backend to also synthesize surface textures. Much
|
||||
// slower and much more VRAM-hungry than shape-only on the reference
|
||||
// backend; leave false for print-pipeline geometry.
|
||||
Texture bool
|
||||
|
||||
// RemoveBackground lets the backend cut the subject out first; nil =
|
||||
// backend default (true on Hunyuan3D). Set explicitly to false when the
|
||||
// input is already a clean cutout.
|
||||
RemoveBackground *bool
|
||||
|
||||
// OctreeResolution is the shape-decoder grid resolution; 0 = backend
|
||||
// default.
|
||||
OctreeResolution int
|
||||
|
||||
// Steps is the number of diffusion steps; nil = backend default.
|
||||
Steps *int
|
||||
|
||||
// GuidanceScale is the guidance strength; nil = backend default.
|
||||
GuidanceScale *float64
|
||||
|
||||
// Seed fixes the RNG seed for reproducible output; nil = backend default.
|
||||
Seed *int64
|
||||
|
||||
// FaceCount caps the output mesh's face count; 0 = backend default.
|
||||
FaceCount int
|
||||
}
|
||||
|
||||
// Result is the canonical mesh-generation result.
|
||||
type Result struct {
|
||||
// Mesh is the generated asset.
|
||||
Mesh Mesh
|
||||
|
||||
// Raw is the provider-native response object. May be nil.
|
||||
Raw any
|
||||
}
|
||||
|
||||
// Option mutates a Request before it is sent. Options passed to Generate are
|
||||
// applied to a copy of the request, so a Request value can be reused.
|
||||
type Option func(*Request)
|
||||
|
||||
// WithFormat sets the output container ("glb", "stl", "obj").
|
||||
func WithFormat(f string) Option { return func(r *Request) { r.Format = f } }
|
||||
|
||||
// WithTexture enables texture synthesis.
|
||||
func WithTexture() Option { return func(r *Request) { r.Texture = true } }
|
||||
|
||||
// WithRemoveBackground sets the backend's background-removal preprocessing.
|
||||
func WithRemoveBackground(v bool) Option {
|
||||
return func(r *Request) { r.RemoveBackground = &v }
|
||||
}
|
||||
|
||||
// WithOctreeResolution sets the shape-decoder grid resolution.
|
||||
func WithOctreeResolution(n int) Option { return func(r *Request) { r.OctreeResolution = n } }
|
||||
|
||||
// WithSteps overrides the number of diffusion steps.
|
||||
func WithSteps(n int) Option { return func(r *Request) { r.Steps = &n } }
|
||||
|
||||
// WithGuidanceScale overrides the guidance strength.
|
||||
func WithGuidanceScale(s float64) Option { return func(r *Request) { r.GuidanceScale = &s } }
|
||||
|
||||
// WithSeed fixes the RNG seed.
|
||||
func WithSeed(seed int64) Option { return func(r *Request) { r.Seed = &seed } }
|
||||
|
||||
// WithFaceCount caps the output mesh's face count.
|
||||
func WithFaceCount(n int) Option { return func(r *Request) { r.FaceCount = n } }
|
||||
|
||||
// Apply returns a copy of the request with all options applied. Providers
|
||||
// call this once at the top of Generate.
|
||||
func (r Request) Apply(opts ...Option) Request {
|
||||
for _, opt := range opts {
|
||||
opt(&r)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Model generates 3D meshes from images.
|
||||
type Model interface {
|
||||
// Generate reconstructs a mesh from the request's image.
|
||||
Generate(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 mesh models bound to one backend.
|
||||
type Provider interface {
|
||||
// Name is the registry identifier for the provider.
|
||||
Name() string
|
||||
|
||||
// MeshModel returns a Model bound to the given id (passed through to the
|
||||
// backend verbatim; no catalog validation).
|
||||
MeshModel(id string, opts ...ModelOption) (Model, error)
|
||||
}
|
||||
Reference in New Issue
Block a user