The contradiction
For text generation, the crate has a deliberate two-layer design (documented in aimux-core/src/lib.rs):
generate_text() ──► LanguageModel::do_generate()
The user calls generate_text / stream_text (free functions).
For every other modality (embedding, image, speech, transcription, video, reranking, search), only the lower layer exists. EmbeddingModel::do_embed's own doc comment says:
Naming: the do_ prefix prevents accidental direct usage by users.
…but there is no embed() free function. Calling do_embed directly is the only way to use the model — the bindings themselves do exactly that (RFC-0008's examples call self.inner.do_embed(&opts)).
So the naming convention warns against the only usage that exists.
Consequences of the missing layer
- Anything the text path does between
generate_text() and do_generate() (recording setup, logging spans, and whatever cross-cutting behavior lands there in the future) has no home on the multimodal paths.
- There is no per-call surface for cross-cutting options on multimodal calls (e.g. text's user layer is where per-call behavior gets applied; multimodal callers talk straight to the provider trait).
- Third-party Rust users are pushed into an API that the docs describe as not-for-users.
The question
Is the absence of user-facing operation functions (embed(), generate_image(), …) an intentional deferral or an oversight?
- RFC-0007 explicitly deferred it for search ("Do not introduce a user API layer (a
search free function)… a user API can be proposed separately later") — so for search it reads as deliberate.
- RFC-0008 says multimodal bindings "reuse the
generate_text pattern", but its examples skip the middle layer and call do_embed directly — which reads more like the layer was dropped on the way than decided against.
If deferral: is it time to propose that layer? If oversight: should the do_ naming claim be softened until the layer exists, so the docs stop contradicting the only supported usage?
References
aimux-core/src/lib.rs — two-layer diagram for text
aimux-core/src/embedding_model.rs — do_embed doc comment
rfc/0007-search-model-trait.md §"Do not introduce a user API layer"
rfc/0008-multimodal-bindings.md — binding examples calling do_embed directly
The contradiction
For text generation, the crate has a deliberate two-layer design (documented in
aimux-core/src/lib.rs):For every other modality (embedding, image, speech, transcription, video, reranking, search), only the lower layer exists.
EmbeddingModel::do_embed's own doc comment says:…but there is no
embed()free function. Callingdo_embeddirectly is the only way to use the model — the bindings themselves do exactly that (RFC-0008's examples callself.inner.do_embed(&opts)).So the naming convention warns against the only usage that exists.
Consequences of the missing layer
generate_text()anddo_generate()(recording setup, logging spans, and whatever cross-cutting behavior lands there in the future) has no home on the multimodal paths.The question
Is the absence of user-facing operation functions (
embed(),generate_image(), …) an intentional deferral or an oversight?searchfree function)… a user API can be proposed separately later") — so for search it reads as deliberate.generate_textpattern", but its examples skip the middle layer and calldo_embeddirectly — which reads more like the layer was dropped on the way than decided against.If deferral: is it time to propose that layer? If oversight: should the
do_naming claim be softened until the layer exists, so the docs stop contradicting the only supported usage?References
aimux-core/src/lib.rs— two-layer diagram for textaimux-core/src/embedding_model.rs—do_embeddoc commentrfc/0007-search-model-trait.md§"Do not introduce a user API layer"rfc/0008-multimodal-bindings.md— binding examples callingdo_embeddirectly