RFC: manifest-driven module architecture to stop per-model interface churn #1189
msluszniak
started this conversation in
Ideas
Replies: 1 comment
-
|
cc: @barhanc maybe this will not decrease number of modified / changed files exactly, but will definitely improve flow, so we don't change common base files anymore and adding new models will be easier and healthier for the lib itself. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
RFC: manifest-driven module architecture to stop per-model interface churn
Why now
We have 17 modules across CV and NLP. Every new model touches ~20 files across 7 trees, and the rate at which model-specific quirks leak into shared family interfaces is going up. Three recent PRs illustrate the trend:
src/modules/,src/hooks/,src/types/,src/constants/,src/index.ts, native models,RnExecutorchInstaller.cpp,JsiConversions.h, docs, and the example app.ObjectDetectionarg list grew from 7 to 8, draggingBaseInstanceSegmentation.{h,cpp}and every integration test along with it — even though instance segmentation has nothing to do with BlazeFace.This isn't a per-PR problem. The architecture makes it the path of least resistance.
What's actually wrong
Three compounding issues:
ObjectDetectionOptions.inputSizeis accepted for RF-DETR and SSDLite but ignored — the type lies. LLMcapabilitiesare baked into load args. Instance-segmentationapplyNMSis in the constructor. Every quirk surfaces in the shared type.generateFromString(input, threshold, iouThreshold, classIndices, methodName, ...). Adding a field churns C++ signatures, every test fixture, andJsiConversions.h(currently 702 lines).modelRegistry.ts,modelUrls.ts, and an in-moduleModelConfigsconst. No single source of truth.What good looks like
A new model should be:
Proposed direction
Five pieces, each independently mergeable.
1. Declarative model manifest
One TS object per model, the single source of truth:
The quirk lives in the model file. No shared interface grows.
2. Generic family module, options derived from the manifest
OptionsOf<F, M>is computed from the manifest. IfMdeclaresvariants: { inputSize: […] }, the type includesinputSize?: 384 | 512 | 640. If it doesn't, the field doesn't exist. The compiler enforces "no quirky options for models that don't support them."3. Uniform JSI bridge
Replace 17
global.load<X>globals + N positional-arggenerate*methods with two operations:All payloads are
jsi::Objectwith named fields. Each module has typedConfig/Payloadstructs plus aparseConfig(jsi::Object)helper. Adding a field = touch one struct + the parser. No positional signatures, ever.4. Co-located feature folders
A new model becomes: one TS file in
models/, optionally one C++ postprocessor pair, optionally a docs page. Zero touches tosrc/index.ts(barrel re-exports the folder),RnExecutorchInstaller.cpp(static registration),JsiConversions.h(generic payload), or other models.5. Composites for multi-stage pipelines
The composite family runner wires stage outputs to stage inputs per a declarative schema. New pipeline architectures (ControlNet, multi-decoder LLMs) become new compositions, not new modules.
What this fixes
OptionsOf<M>defineCompositejsi::Objectpayloadsrc/index.tsgrowing per modelexport * from './features/<x>'forward_${inputSize}string-template dispatchvariantsis declarativeOptionsOf<F, M>shapemakeUseFamily(family), ~1 line eachMigration plan (not a big-bang rewrite)
rne.load/invokenext to the existing globals. No user-facing change.src/features/object-detection/alongside the existing module; the old export becomes a deprecated shim that delegates.forward_${size}smell), then NLP, then audio + OCR (composites).RnExecutorchInstaller.cppswitch, per-family globals) once all families are migrated.src/index.tsto barrel-of-features when no consumer-facing import path needs to change.Each step is independently shippable. Reversible up to step 4.
Known risks
OptionsOf<F, M>needs careful conditional types. Mitigate withsatisfies ModelDefinition<F>so errors surface at definition, not at call sites.KEEPrules or per-feature anchor TUs. Verify on Hermes + iOS release builds early.What I'd like input on
Beta Was this translation helpful? Give feedback.
All reactions