Model reference · open weights
fibo-scene-analyzer is an open-weight language model from briaai. fibo-scene-analyzer-gguf (GGUF) weighs 21.5 GB; the smallest configuration that runs it is 2× RTX 3060 12 GB.
For self-hosting, compare this build's requirements below with the GPU you plan to rent.
What it is
| Released by | briaai |
|---|---|
| Released | 2026-09-10 |
| Parameters | 36.0B |
| VRAM | 21.5 GB for the weights |
What it runs on
How much memory each request adds isn't estimated yet for this architecture. The weights need at least the cards below, plus room for the context.
| Card | Weights alone |
|---|---|
| RTX 3060 12 GB … RTX 4060 Ti 16 GB 2 smaller cards | does not fit |
| RTX 3090 24 GB | tight |
| RTX 4090 24 GB | tight |
| RTX 5090 32 GB | fits |
| L40S 48 GB | fits |
| A100 80 GB | fits |
| H100 80 GB | fits |
| RTX PRO 6000 Blackwell 96 GB | fits |
| DGX Spark (GB10) 128 GB unified | fits |
| H200 141 GB | fits |
| B200 180 GB | fits |
| 2× RTX 3060 12 GB split by layers (llama.cpp) | tight |
| 2× RTX 4060 Ti 16 GB split by layers (llama.cpp) | fits |
| 2× RTX 4090 24 GB split by layers (llama.cpp) | fits |
| 2× RTX 3090 24 GB split by layers (llama.cpp) | fits |
Builds
| Build | Params | Precision | Weights | Smallest setup |
|---|---|---|---|---|
| fibo-scene-analyzer ↗ | 36.0B | BF16 | 71.9 GB | A100 80 GB |
| fibo-scene-analyzer-gguf (above) ↗ 2 builds: Q4_K_M 21.5 GB … Q8_0 36.9 GB |
GGUF | 21.5 GB | 2× RTX 3060 12 GB |
From the model card
FIBO Scene Analyzer [dev] was developed to cover a wide range of image understanding tasks using Bria's scene description format. A scene description holds a general description of the image (type, style, lighting, composition, color palette and more) and a tree of objects. Each object has a name, a description, its geometry (bounding boxes, polygon masks, body keypoints), its colors, its relationships to other objects and fields for its kind: people, animals, text and other objects.
The same model also does grounding (detection, masks, and body keypoints for a named target, or for all objects), OCR with line boxes, and text-to-description tasks: it expands a short prompt to a full scene description, and it refines or edits a scene description from an instruction.
We built FIBO Scene Analyzer from Qwen3.6-35B-A3B via multi-stage SFT on a custom synthetic dataset, then GRPO reinforcement learning with task-specific rewards, then a final short SFT stage. For synthetic data, we developed a 12-step workflow that combines computer vision tools, general and specialist models to extract all possible structured information from the images.
| Task | Input | Prompt text | Answer |
|---|---|---|---|
caption | image | `` | SceneDescription |
detect | image, optional target | `` or TARGET | SceneObjectList: names, kinds, boxes |
mask | image, optional target | `` or TARGET | as detect, with polygon masks |
keypoints | image, optional target | `` or TARGET | people with boxes and named keypoints |
ocr | image | `` | text objects: language, lines, line boxes |
describe | image, object name | NAME | one object with all its fields |
expand | prompt, aspect ratio | \nAR\nPROMPT | SceneDescription of a new image |
expand_object | object name, optional scene description | NAME, or with \nSCENE_JSON after the name | one object with all its fields |
refine | instruction, scene description JSON | INSTRUCTION\nSCENE_JSON | the changed SceneDescription |
edit | 1-5 images, instruction | \nAR\nINSTRUCTION | SceneDescription of the edited image |
AR is the width divided by the height, rounded to two decimals.
With a scene description (scene_contexts in generate()), expand_object describes
the object so that it fits the scene, with relationships to the objects of the scene. The
scene must not contain the object itself.
SCENE_JSON is compacted JSON with coordinates and colors as
tokens. prompt_json() in scene_analyzer.py writes a SceneDescription in this form, also
after post_process().
For the grounding tasks, a named target that is not in the image gives an empty list.
Without a target, detect and mask return every object; clothing, footwear and
accessories are separate targets named "ITEM on PERSON".
| Detail level | Content |
|---|---|
general | the general block only, without objects |
short | a flat list of objects, with name, kind, description, location, position, relative size and text lines |
long | as short, plus colors, details, relationships and the fields of each kind |
full | the object tree with bounding boxes, relative distance, and body keypoints |
full_mask | as full, with a polygon mask for most of the objects |
expand, refine and edit accept general, short, long and full.
expand_object accepts short, long, full and full_mask.
Download the code files of this repository, then:
from PIL import Image
from scene_analyzer import SceneAnalyzerModel, SceneAnalyzerTask, DetailLevel
model = SceneAnalyzerModel("briaai/fibo-scene-analyzer") # Transformers, device_map="auto"
image = Image.open("photo.jpg").convert("RGB")
[description] = model.generate([image], SceneAnalyzerTask.CAPTION, detail_level=DetailLevel.FULL, num_samples=3)
description.post_process() # coordinate and color tokens to numbers
print(description.general.description)
for object in description.objects or []:
print(object.kind, object.name, object.bounding_boxes)
[people] = model.generate([image], SceneAnalyzerTask.DETECT, text_inputs=["person"])
[text] = model.generate([image], SceneAnalyzerTask.OCR)
To render an answer as an HTML page with the geometry drawn on the image:
from caption_visualizer import CaptionVisualizer
CaptionVisualizer().save("description.html", image, description)
To make it easier to work with the model and get the best results, we provide harness classes
based on the Pydantic scene description format.
The three harnesses have the same SceneAnalyzerModel.generate() interface and the same
task logic; only the engine differs.
| File | Engine | Use it for |
|---|---|---|
scene_analyzer.py | Hugging Face Transformers | the smallest set of dependencies |
scene_analyzer_vllm.py | vLLM, in the same process | batch processing; the output is constrained to the schema |
scene_analyzer_server.py | an OpenAI-compatible server | a model served separately (vLLM, SGLang) |
What each harness does:
ValueError.num_samples answers and returns the best valid one. A scene description
with the most objects wins; for grounding tasks, the most confident answer wins.
An input without a valid answer is sampled again (retries), and
None is returned if all attempts fail.num_iterations, it runs revision rounds: the model sees its answer and adds the
objects that it missed. This works for `` and the whole-image grounding tasks.from scene_analyzer_vllm import SceneAnalyzerModel
model = SceneAnalyzerModel("briaai/fibo-scene-analyzer", gpu_memory_utilization=0.9)
descriptions = model.generate(images, SceneAnQuoted from the model card on Hugging Face. The full card is behind the Hugging Face link above.