Model Library
Browse and deploy state-of-the-art AI models through the DEVUP Gateway.
Browse and deploy state-of-the-art AI models through the DEVUP Gateway.
FIBO 1.5 is a distilled release of Bria's JSON-native text-to-image model: the same 8-billion-parameter architecture and the same structured control, generating in four to six inference steps instead of fifty. The base model was trained entirely on long structured JSON captions rather than free-form text, which is what gives it disentangled control — change the camera angle without disturbing the lighting, adjust the lighting without touching the composition. That also makes it strict about input: it expects a structured prompt and does not work well with a sentence. Trained exclusively on licensed data, it is built for production pipelines where reproducibility and provenance matter more than creative surprise.

A distilled release of Bria's JSON-native text-to-image model. Same architecture, same control, roughly a tenth of the inference steps.
The most important thing on this page, because getting it wrong produces poor output rather than an error.
FIBO was trained exclusively on structured prompts and does not work well with free-form text. That is Bria's own guidance, stated plainly. A sentence like "a product shot of a coffee bag on concrete" will produce something — it will just be markedly worse than what the model can do.
The expected input is a structured JSON description naming visual parameters explicitly: lighting, camera, composition, colour, depth of field. The model was trained on captions of roughly a thousand words in that form, and that is the shape it understands.
If you have a sentence and want the model's quality, run it through a conversion step first. Bria publishes dedicated prompt-to-JSON models for exactly this, and any capable vision-language model can do the job — it expands a short intent into a full structured schema, filling in the parameters you did not specify.
The practical consequence: plan for a two-stage pipeline. Intent in, structure out, image after. Skipping the middle stage is the single most common way to get disappointing results from this model.
Two post-training stages, applied to the existing model.
DMD stage — distillation into a 4–6 step model with no classifier-free guidance.
DMD-R stage — refinement of the distilled student to improve realism and texture.
Everything else is identical. The 8B diffusion transformer, the text encoder, the conditioning architecture, the autoencoder, and the structured-prompt interface are unchanged. Weight layout and control behaviour are the same as the base model.
That matters if you are migrating: your prompts, your schemas, and your expectations about how attributes interact all carry over. What changes is that generation takes four to six steps where the base model takes around fifty — and that classifier-free guidance is gone, so the guidance-scale parameter no longer applies.
Worth understanding before writing a schema, because it explains what the model can and cannot do.
Conventional text-to-image models learn from short captions written by humans or scraped from the web. In that data, visual attributes are entangled: "vintage" moves colour, grain, contrast, and lighting together, because they moved together in the captions. You cannot request one without the others, and you cannot change one without the rest shifting.
FIBO was trained on captions where those attributes are named separately. The result is native disentanglement: setting a camera angle changes the camera angle. It does not also warm the palette or alter the mood.
Two things follow.
Iterative refinement works. Fix the lighting, approve it, then adjust composition — and the lighting you approved survives. On an entangled model each change is a fresh roll.
The same input reproduces the same output. With a fixed seed and a fixed schema, the image regenerates identically. An approved asset can be recreated from its blueprint months later.
The reason enterprise teams choose this family, and it has nothing to do with output quality.
FIBO is trained only on rights-cleared, licensed material. For a company shipping generated imagery in a product, an advertisement, or a publication, that provenance answers a question most image models leave open.
Licensing of the training data and licensing of the weights are separate questions. The published weights carry their own terms, which may restrict commercial use independently of how cleanly the model was trained. Read the licence attached to your specific deployment before building a commercial product on it.
| Component | |
|---|---|
| Type | Diffusion transformer, flow matching |
| Parameters | 8B |
| Text encoder | SmolLM3-3B |
| Conditioning | DimFusion — built for long-caption training |
| Autoencoder | Wan 2.2 VAE |
| Inference steps | 4–6 |
| Classifier-free guidance | Removed in this release |
DimFusion is the piece that makes the whole approach viable. Conditioning on a thousand-word caption is expensive with conventional architectures; this one was designed for it, which is why the structured-prompt paradigm is practical rather than theoretical.
| Model ID | Bria/fibo-1.5 |
| Parameters | 8B |
| Input | Structured JSON prompt |
| Output | Image |
| Inference steps | 4–6 |
| Guidance scale | Not applicable — CFG removed |
| Free-form text | Not supported — convert to structure first |
| Determinism | Same schema and seed reproduce the same image |
| Training data | Fully licensed |
| Endpoint | /v1/images/generations |
| Capability | Value |
|---|---|
input_types | text — structured JSON |
output_types | image |
structured_prompt | Required |
freeform_prompt | Not supported |
negative_prompt | Supported |
seed | Supported — reproducible |
aspect_ratios | Multiple |
deterministic | Yes, for a fixed schema and seed |
endpoint | /v1/images/generations |
requires_prompt | Yes — structured prompt required |
Endpoint: POST https://api.devupai.com/v1/images/generations
The response returns a signed URL in data[0].url alongside a _devup object carrying the request
cost and your remaining balance.
The URL is valid for five minutes. Fetch the image within that window.
The input the model actually expects.
import os
import json
import requests
from pathlib import Path
DEVUP_API_KEY = os.environ["DEVUP_API_KEY"]
GENERATE = "https://api.devupai.com/v1/images/generations"
blueprint = {
"scene": {
"subject": "a matte black coffee bag, standing upright, centred",
"setting": "pale concrete surface, plain background",
"additional_objects": "none",
},
"camera": {
"angle": "eye_level",
"distance": "medium",
"focal_length": "50mm",
"depth_of_field": "shallow",
},
"lighting": {
"source": "single softbox",
"direction": "upper_left",
"quality": "soft",
"color_temperature": "neutral",
"shadow": "short, falling lower right",
},
"color": {
"palette": "monochrome with warm neutral background",
"saturation": "low",
},
"style": {
"aesthetic": "editorial product photography",
"grain": "none",
},
}
def generate(schema: dict, *, seed: int | None = None, **extra) -> bytes:
"""Generate an image from a structured prompt."""
payload = {"model": "Bria/fibo-1.5", "prompt": json.dumps(schema), **extra}
if seed is not None:
payload["seed"] = seed
response = requests.post(
GENERATE,
headers={
"Authorization": f"Bearer {DEVUP_API_KEY}",
"Content-Type": "application/json",
},
json=payload,
timeout=300,
)
response.raise_for_status()
result = response.json()
spend = result.get("_devup", {})
print(f"{spend.get('cost_dzd')} DZD · balance {spend.get('balance_dzd')}")
# The URL is valid for five minutes.
return requests.get(result["data"][0]["url"], timeout=120).content
Path("coffee_bag.png").write_bytes(generate(blueprint, seed=42))Field names above are illustrative. Consult the current schema reference before building around specific keys — the structure the model was trained on is the structure that works.
The capability disentanglement provides, and the reason to use this model at all.
import copy
SEED = 42
variants = {
"low_angle": {"camera": {"angle": "low_angle"}},
"high_angle": {"camera": {"angle": "high_angle"}},
"close": {"camera": {"distance": "close"}},
}
for name, override in variants.items():
schema = copy.deepcopy(blueprint)
for section, fields in override.items():
schema[section].update(fields)
Path(f"bag_{name}.png").write_bytes(generate(schema, seed=SEED))Same seed, same schema, one field changed. The lighting, palette, subject, and setting hold across all three renders — so the comparison isolates the camera angle rather than showing you three different photographs.
On an entangled model this experiment does not work. The sampler moves, the attributes move together, and you cannot attribute the difference to your change.
The first stage of the pipeline, and the one most often skipped.
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DEVUP_API_KEY"],
base_url="https://api.devupai.com/v1",
)
SCHEMA_INSTRUCTION = (
"Convert the user's image request into a structured JSON prompt. "
"Name lighting, camera, composition, colour, and style explicitly. "
"Fill in professional defaults for anything the user did not specify, "
"and state 'none' rather than omitting a field. Reply with JSON only."
)
def to_schema(intent: str) -> dict:
"""Expand a short intent into a structured prompt."""
response = client.chat.completions.create(
model="<a capable model in your catalogue>",
messages=[
{"role": "system", "content": SCHEMA_INSTRUCTION},
{"role": "user", "content": intent},
],
max_tokens=2048,
temperature=0,
)
return json.loads(response.choices[0].message.content)
schema = to_schema("a moody product shot of a leather notebook on a desk")
Path("notebook.png").write_bytes(generate(schema, seed=7))temperature: 0 on the conversion step is deliberate. The whole point of this model is
reproducibility, and a non-deterministic translation stage reintroduces exactly the variance you
chose the model to avoid. Better still: run the conversion once, store the schema, and generate from
the stored version thereafter.
Path("clean_plate.png").write_bytes(
generate(
blueprint,
seed=42,
negative_prompt="text, watermark, logo, people, motion blur, visible seams",
)
)import { writeFile } from "node:fs/promises";
const blueprint = {
scene: { subject: "a matte black coffee bag, standing upright, centred", setting: "pale concrete surface" },
camera: { angle: "eye_level", focal_length: "50mm", depth_of_field: "shallow" },
lighting: { source: "single softbox", direction: "upper_left", quality: "soft" },
};
const response = await fetch("https://api.devupai.com/v1/images/generations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DEVUP_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "Bria/fibo-1.5",
prompt: JSON.stringify(blueprint),
seed: 42,
}),
signal: AbortSignal.timeout(300_000),
});
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`);
}
const result = await response.json();
// The URL is valid for five minutes.
const image = await fetch(result.data[0].url);
await writeFile("coffee_bag.png", Buffer.from(await image.arrayBuffer()));Store schemas, not prompts. The structured blueprint is the reproducible artefact. With the seed, it regenerates the image exactly. A sentence does not.
Version them. A schema is text; it belongs in your repository alongside the code that uses it, with a history you can read.
Convert once, reuse thereafter. The sentence-to-schema step is where non-determinism lives. Run it once, review the result, and treat the schema as the source of truth.
Pin the seed while iterating. Any difference in output is then attributable to the field you changed rather than to sampling.
Change one field at a time. Disentangled control is only useful if exercised one dimension at a time. Rewriting the whole schema between attempts throws away the advantage.
Build a library of partial schemas. A brand's lighting setup, a standard camera configuration, a house palette — composable fragments that guarantee consistency across a catalogue.
Do not pass a guidance scale. Classifier-free guidance was removed in this release.
Automated pipelines. Code produces JSON naturally and needs the output to be predictable. This is the model's home ground.
Agent-driven generation. An agent adjusting one visual attribute at a time needs a control surface where one adjustment does not disturb the rest.
Brand-consistent catalogues. Shared schema fragments guarantee that two hundred product shots share lighting, framing, and palette exactly rather than approximately.
Enterprise content with provenance requirements. The licensed training data is the reason, and for some organisations it is the only reason that matters.
Anything needing an audit trail. A schema records what was specified; a sentence records only what someone typed.
Less suited to open-ended creative exploration, where the looseness of a conventional model is a feature, and where writing a thousand-word schema to get one image is the wrong economics.