mstar.model.multimodal#
Order-preserving multimodal prompt adapter.
Intake hands models an ordered list of PromptPart — the user’s text
and attachments as written — instead of a bag of per-modality lists.
prefill_plan() turns that into the ordered sequence of text spans and
attachments to prefill.
A model renders its prompt once with the tokenizer’s own placeholders where
the attachments belong, tokenizes it once, and reads the placement back with
find_media_spans() / split_around_spans(). One tokenizer call, so
no BPE merge is cut at a span boundary, and a model says only how its prompt
renders — never how to take one apart.
Prompt building and schedule building both call prefill_plan(), so they
cannot disagree about the spans; check_plan() fails the request if a
rendered prompt ever does.
Functions
|
Fail loudly when the layout and the attachments that arrived disagree. |
|
Fail loudly when the rendered prompt disagrees with the plan. |
|
Locate every placeholder run in |
|
Rebuild the parts for a layout, filling the text slots from |
|
Order the prefill segments for |
|
Return the text between the spans, in order, dropping empty pieces. |
Classes
|
A |
|
One element of a prompt, in request order. |
- class mstar.model.multimodal.MediaSpan(modality, index, start, stop)[source]#
Bases:
objectA
<|x_start|> pad* <|x_end|>run located in a tokenized prompt.Bounds are sentinel-inclusive: the modality walk emits those embeddings itself, alongside the encoder output.
- class mstar.model.multimodal.PromptPart(modality, text=None, index=0)[source]#
Bases:
objectOne element of a prompt, in request order.
indexis the position within its own modality’s list, so a media part addressestensors[f"{modality}_inputs"][index].
- mstar.model.multimodal.check_attachments(parts, counts)[source]#
Fail loudly when the layout and the attachments that arrived disagree.
check_plan()compares the plan against the prompt it rendered, but both sides come from the same parts — a layout claiming two images renders two placeholders and scans two spans whatever was uploaded. Only the caller knows how many attachments the request actually carried, so it checks here, at intake, where the failure can still be answered with a 400.- Parameters:
parts (list[PromptPart])
- Return type:
None
- mstar.model.multimodal.check_plan(plan, spans, n_text)[source]#
Fail loudly when the rendered prompt disagrees with the plan.
A mismatch means an attachment was dropped or reordered between intake and tokenization — the failure this adapter exists to prevent.
- Parameters:
plan (list[PromptPart])
n_text (int)
- Return type:
None
- mstar.model.multimodal.find_media_spans(input_ids, specs)[source]#
Locate every placeholder run in
input_ids, in token order.specsmaps a modality to its(start_id, pad_id, end_id)triple. Indices run per modality, so the nth image span addresses the nth image.
- mstar.model.multimodal.parts_from_modalities(input_modalities, texts=None)[source]#
Rebuild the parts for a layout, filling the text slots from
texts.input_modalitiesis one entry per part, in order, and is the layout every consumer plans from. Rebuilding from it beats carrying a second copy of the ordering that could drift. Unfilled text slots carryNone, which is enough to plan with.
- mstar.model.multimodal.prefill_plan(parts, *, leading_text=True)[source]#
Order the prefill segments for
parts.Adjacent text collapses into one segment: the rendered prompt puts it in one contiguous run. A trailing segment always exists — the template’s turn close — even with no user text there.
leading_textsays whether the template opens with one too; BAGEL’s generation prompt does not.Text segments are numbered in order, so
indexaddresses the model’s own list of spans, and each carries its text (Nonewhen only the template contributes it).- Parameters:
parts (list[PromptPart])
leading_text (bool)
- Return type:
- mstar.model.multimodal.split_around_spans(input_ids, spans)[source]#
Return the text between the spans, in order, dropping empty pieces.
Two adjacent attachments leave nothing between them, and a zero-length walk has nothing to embed.
prefill_plan()drops the same pieces.