Not every problem wants a chat box. Speech notes, product photos, surveillance clips, and support tickets each live in a different modality — a type of signal the model consumes or produces. Choosing the wrong modality pipeline wastes compute and creates awkward UX (forcing users to describe a screenshot in words when vision would suffice).
A modality is a channel of information: text, images, audio, video, tabular fields, sensor streams. Models are often unimodal (one channel in, one out) or multimodal (multiple channels, jointly).
Think of product shapes, not brand names:
| Family | Typical I/O | What they are good at | Common failure mode |
|---|---|---|---|
| Text / LLM | text → text | Reasoning over language, code, structured drafts | Weak on pixels/sound without tools |
| Image generation | text/noise → image | Concepts, layouts, variants | Text spelling, precise counts, brand fidelity |
| Image understanding | image → labels/captions/embeddings | Search, moderation, OCR assist | Fine print, rare objects without fine-tuning |
| Speech / audio | audio ↔ text or audio | Transcription, voice interfaces, SFX | Accents, overlap, domain jargon |
| Video | text/video → video or understanding | Short clips, summarization, detection over time | Cost, temporal consistency, long duration |
Multimodal systems usually:
You do not need one giant model for every demo. Many production stacks are pipelines: speech-to-text → LLM → text-to-speech, or image embedder → vector search → LLM for explanations. That is multimodal as a system even if each step is unimodal.
Keep architecture shapes in mind, not slogans:
Exact training recipes change yearly; the job each family does changes slowly. Design against the job.
Use this decision sketch:
Also separate understanding from generation. Classifying whether a photo shows a damaged package is different from generating a marketing image of a package. Same modality, different risk, latency, and evaluation.
A field-support app receives: a photo of an error screen, a voice note, and a short typed symptom.
| Approach | Pipeline | Pros | Cons |
|---|---|---|---|
| A. Text-only | User must type everything | Simple | Loses visual detail; high user effort |
| B. Stitched unimodal | ASR → OCR/caption → LLM | Clear ownership per step | Error compounds across stages |
| C. Multimodal model | Image + transcript → answer | Fewer handoffs | Harder to debug; vendor lock-in risk |
from dataclasses import dataclass
@dataclass
class Ticket:
text: str
image_bytes: bytes | None = None
audio_bytes: bytes | None = None
def choose_pipeline(ticket: Ticket) -> str:
has_image = ticket.image_bytes is not None
has_audio = ticket.audio_bytes is not None
if has_image and has_audio:
return "multimodal_or_asr_plus_vision_then_llm"
if has_image:
return "vision_caption_or_vqa_then_llm"
if has_audio:
return "asr_then_llm"
return "text_llm_with_optional_rag"
print(choose_pipeline(Ticket("app crashes on save")))
# text_llm_with_optional_rag
print(choose_pipeline(Ticket("see photo", image_bytes=b"...png")))
# vision_caption_or_vqa_then_llm
The function is deliberately boring: modality choice is a product decision before it is a model-zoo decision.
Extend the same idea into a tiny routing table you could paste into a design doc:
ROUTES = {
("text",): "llm_rag",
("image",): "vision_then_llm",
("audio",): "asr_then_llm",
("image", "audio"): "parallel_asr_vision_then_llm",
("video",): "keyframe_or_video_model_then_llm",
}
def route(*modalities: str) -> str:
key = tuple(sorted(set(modalities)))
return ROUTES.get(key, "clarify_inputs_with_user")
print(route("text"))
print(route("image", "audio"))
print(route("video"))
If clarify_inputs_with_user appears often in real traffic, your intake UX — not your model — is the bottleneck.
Match models to modalities — text, image, audio, video, or multimodal fusion — and prefer the simplest pipeline that keeps the user’s native signal intact.