VGL — Visual Generation Language
VGL turns a text prompt, or images plus a prompt, into a structured JSON description of a scene: objects, background, lighting, aesthetics, camera, and text. The result is a typed Pydantic model that an image model like FIBO takes as its prompt.
Install
pip install bria-vgl
The default LLM is Gemini through Google AI Studio. For other providers, install the extra:
pip install 'bria-vgl[vertex]' # Gemini on Vertex AI
pip install 'bria-vgl[bedrock]' # Claude on AWS Bedrock
Authenticate
| Provider | llm= |
Set |
|---|---|---|
| Google AI Studio (default) | gemini/gemini-3.5-flash-lite |
GEMINI_API_KEY (get one) |
| Vertex AI | vertex_ai/gemini-3.5-flash-lite |
VERTEXAI_PROJECT, VERTEXAI_LOCATION, GOOGLE_APPLICATION_CREDENTIALS (a service account JSON) |
| AWS Bedrock | e.g. bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0 |
the usual AWS credentials and AWS_REGION_NAME |
llm takes any litellm model id, but the prompts are tuned for Gemini.
Quickstart
Create a scene from a prompt
import bria_vgl
from bria_vgl.dialects.thales import Generate
scene = bria_vgl.create(Generate(prompt="a red fox in snow at dusk"))
print(scene.short_description)
print(scene.model_dump_json(indent=2, exclude_none=True))
Create a scene inspired by an image
The image is a visual reference only. The VGL describes the scene the prompt asks for, not the image.
import bria_vgl
from bria_vgl.dialects.thales import Inspire
scene = bria_vgl.create(Inspire(prompt="the same fox, at the beach", image=fox))
Describe an image
No prompt: the VGL describes the image itself.
from bria_vgl.dialects.thales import Caption
scene = bria_vgl.create(Caption(image=fox))
Refine a VGL
No image: the prompt changes an existing VGL, and the fields it doesn't affect are kept.
from bria_vgl.dialects.thales import Generate, Refine
scene = bria_vgl.create(Generate(prompt="a cosy living room"))
night = bria_vgl.modify(Refine(prompt="make it night", input_vgl=scene))
Edit from images
from PIL import Image
from bria_vgl.dialects.thales import EditImages
room = Image.open("room.jpg")
lamp = Image.open("lamp.jpg")
scene = bria_vgl.modify(EditImages(prompt="make it night", images=[room]))
scene = bria_vgl.modify(EditImages(prompt="put the lamp from <image_2> in <image_1>", images=[room, lamp]))
print(scene.edit_instruction)
Up to 4 images. The prompt refers to them as <image_1> to <image_4>, in list order.
Edit a masked area
from bria_vgl.dialects.thales import EditImageWithMask
mask = Image.open("mask.png") # white is the area to change; same size as the image
scene = bria_vgl.modify(EditImageWithMask(prompt="replace it with a cat", image=room, mask=mask))
Edit with the image's VGL
If you have the VGL that an image was generated from, pass it as input_image_vgl. The edit then keeps everything the prompt doesn't change, rather than re-describing the image from scratch. vgl doesn't check that it matches the image.
scene = bria_vgl.create(Generate(prompt="a cosy living room"))
image = ... # generate the image from `scene` with FIBO
night = bria_vgl.modify(EditImages(prompt="make it night", images=[image], input_image_vgl=scene))
Runnable versions are in examples/.
Options
bria_vgl.create(payload, llm="vertex_ai/gemini-3.5-flash-lite", seed=7, style_preset_prompt="Muted film colours, soft grain.")
bria_vgl.modify(payload, llm=..., seed=...)
llm: the litellm model id; see Authenticate.seed: makes a call repeatable, on models that accept one.style_preset_prompt: style guidelines added to the system prompt. Applies tocreateonly;modifyignores it.
create also takes overrides for the payload's defaults. Each is optional, and leaving it out keeps the default:
system_prompt: replaces the system prompt.{llm_input_schema}and{style_preset_block}in it are still filled.final_prompt: replaces the final (user) prompt. Its placeholders, such as{user_prompt}, are still filled.input_schema: the field guide filled into{llm_input_schema}.response_schema: the JSON schema the model must follow, in Gemini's format. Extra keys in the reply are dropped from the VGL.thinking_level: abria_vgl.ThinkingLevelor its string,"minimal","low","medium"or"high", on Gemini 3+. Anything else, or a level on an older Gemini, raisesValueErrorbefore the call. By default thinking is as low as the model allows.temperatureandmax_output_tokens: thinking tokens count againstmax_output_tokens, so raise it with a high thinking level.
bria-vgl logs under the bria_vgl logger hierarchy (bria_vgl.gateway, bria_vgl.prompting, …). Configure it the standard way — e.g. logging.getLogger("bria_vgl").setLevel(logging.INFO) and attach your own handler; add a logging.Filter if you need to inject contextual fields.
A Gemini call that keeps failing (3 attempts) or hits a rate limit (429, not retried) moves to gemini-3.1-flash-lite on the same provider.
Errors
Everything bria-vgl raises inherits from bria_vgl.exceptions.VGLError, except a bad payload, which raises pydantic.ValidationError before any LLM call. The classes below all live in bria_vgl.exceptions.
| Error | Means |
|---|---|
AuthenticationError |
the provider rejected your credentials, e.g. a missing or wrong API key |
RateLimitError |
the provider returned 429 (quota exhausted), on the Gemini fallback too |
LLMError |
any other provider failure, after retries and the fallback |
InvalidResponseError |
the model's reply isn't a valid VGL |
MaxTokensError |
the model ran out of output tokens mid-reply |
PromptNotFoundError |
a bundled prompt is missing; a packaging fault, please report it |
Dialects
A dialect is a small variant of VGL, with its own model, payloads, and prompts. The payload you import decides the dialect. vgl ships the Thales dialect: no aesthetic scores, and every edit states its change in edit_instruction.
More
- Best practices: how images are prepared, masks, and getting consistent results.
- Contributing
Metadata
Release files for bria-vgl 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| bria_vgl-0.8.0.tar.gz | 33.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bria_vgl-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 99.4 kB
Release files / bria_vgl-0.8.0.tar.gz
| Download URL | bria_vgl-0.8.0.tar.gz |
|---|---|
| Size | 33.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00827ec42e64bbca502eec725fc9db76253e8e7bcffeaccd73ed617c216b349f
|
|
BLAKE2b-256 checksum How to use checksums |
21b831173958be966a6f99ab30b5b9f17e5250a8432501609cb618cccbe7d41c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / bria_vgl-0.8.0-py3-none-any.whl
| Download URL | bria_vgl-0.8.0-py3-none-any.whl |
|---|---|
| Size | 65.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ad1f65f56864aa46465951d9f32fd01bbd21efb5978076436ac557a285197e8d
|
|
BLAKE2b-256 checksum How to use checksums |
8ac91b94ef618d50173f6aec9bd7186fec1d0e282a230ed0ef49581bd78546f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for bria-vgl 0.8.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.