Skip to main content

Vision: Analyzing Images with AI

Send images to vision-capable models for analysis, description, and understanding. This example shows how to analyze an image from a URL using GPT-4o with high detail processing for better accuracy.

Image Generation: Generating Images with AI

Generate images from text prompts using OpenAI-compatible image generation models via the Go SDK.

Audio Understanding: Analyzing Audio with AI

If your chat application supports text input, you can add audio input and output-just include audio in the modalities array and use an audio model, like gpt-4o-audio-preview.

Audio Input to Model

Text-to-Speech: Converting Text to Audio

Convert text into natural-sounding speech using AI voice models. This example demonstrates generating an MP3 audio file from text using the “alloy” voice. The result is saved to a local file for playback.

Speech-to-Text: Transcribing Audio Files

Convert audio files into text using AI transcription models. This example shows how to transcribe an MP3 file using OpenAI’s Whisper model, with an optional context prompt to improve accuracy.

Advanced Vision Examples

Multiple Images

Send multiple images in a single request for comparison or analysis. This is useful for comparing products, analyzing changes over time, or understanding relationships between different visual elements.

Base64 Images

Process local images by encoding them as base64 data URLs. This approach is ideal when you need to analyze images stored locally on your system without uploading them to external URLs first.

Audio Configuration Options

Voice Selection for Speech Synthesis

OpenAI provides six distinct voice options, each with different characteristics. This example generates sample audio files for each voice so you can compare and choose the one that best fits your application.

Audio Formats

Generate audio in different formats depending on your use case. MP3 for general use, Opus for web streaming, AAC for mobile apps, and FLAC for high-quality audio applications.

Transcription Options

Language Specification

Improve transcription accuracy by specifying the source language. This is particularly helpful for non-English audio or when the audio contains technical terms or specific domain vocabulary.

Response Formats

Choose between simple text output or detailed JSON responses with timestamps. The verbose JSON format provides word-level and segment-level timing information, useful for creating subtitles or analyzing speech patterns.

Multimodal Embeddings

Bifrost supports multimodal embeddings — generating vector representations that capture text, images, audio, video, and documents together. The Input field on BifrostEmbeddingRequest is a []EmbeddingInputItem; each item’s Content is an EmbeddingContent, a slice of typed parts, and all the parts in one item produce one vector.
Exactly one modality field must be set per part, and a media part must set exactly one of Data or URL. ValidateEmbeddingInput runs before dispatch, so a malformed part fails before any plugin or provider sees it. EmbeddingParameters carries the request-level defaults: EncodingFormat, Dimensions, TaskType, Title, AutoTruncate, plus ExtraParams for provider-specific fields that are forwarded as-is.

Response fields

EmbeddingData gained three optional fields, set only when the provider needs them: EncodingFormat: "base64" works on every provider; where the model has no native base64 output Bifrost encodes the float vector as little-endian float32 base64.

Provider support

A part the target model cannot carry returns an InvalidRequestError naming the modality. Bifrost never drops a part silently. The per-model rules below are the same as on the HTTP gateway; see the gateway guide for the wire-level detail.

Text Embedding (all providers)

Gemini

gemini-embedding-2-preview accepts text, image, audio, video and file (PDF) parts in any combination in one item. gemini-embedding-001 is text-only.
  • Inline Data is sent as inlineData.
  • A URL is sent as fileData.fileUri, which the Gemini API only resolves for Files API URIs. Upload large media first, or send it inline. gs:// is rejected on the Gemini provider; use Vertex for Cloud Storage media.
  • Multiple items go out as one :batchEmbedContents call. TaskType and Title apply to every entry, and this is the only provider that honours per-item Params.
  • documentOcr and audioTrackExtraction go in ExtraParams["embedContentConfig"].
For PDFs, use the file part type with MIMEType: "application/pdf", and enable OCR through embedContentConfig:

Vertex AI

Vertex has three embedding APIs, and Bifrost picks the right one from the model name. Project and region come from the Vertex key configuration. multimodalembedding@001 returns a separate 1408-dimension vector per modality, all in the same embedding space. Image and video URLs must be gs://; inline base64 data URIs are also accepted.
Video is embedded as a sequence of segments. Set VideoConfig on the video part (IntervalSec minimum is 4 seconds) and each segment comes back as its own EmbeddingData with a VideoSegment:

Cohere

Cohere’s API has three mutually exclusive input fields, and Bifrost picks one from the content: texts[] when every item is a single text part, images[] when every item is a single image part, and inputs[] content blocks (Embed v4 only) for anything else, such as text and image in one item. Images must be inline: a data URI in URL or Data, or raw base64 in Data with MIMEType set. Cohere does not fetch remote URLs. input_type defaults to search_document. EncodingFormat maps to Cohere’s embedding_types; when Cohere returns several representations for one input, each is a separate EmbeddingData labelled with its EncodingFormat. Image tokens are reported in Usage.PromptTokensDetails.ImageTokens, not PromptTokens.

Bedrock

Bedrock embedding models are routed by family, each with its own wire format and constraints. Titan. amazon.titan-embed-image-v1 accepts one item with text and at most one image, inline in Data only (a URL is rejected). Dimensions (256, 384 or 1024) maps to embeddingConfig.outputEmbeddingLength. The text models amazon.titan-embed-text-v1 / v2:0 take one item per request; a batch is an InvalidRequestError rather than a collapsed vector.
Cohere on Bedrock. cohere.embed-* models follow the same texts[] / images[] / inputs[] selection as direct Cohere. Image-only requests go out as images[] with input_type defaulting to image, which both Embed v3 and v4 accept; mixed text + image items use inputs[] and need Embed v4. Amazon Nova. amazon.nova-2-multimodal-embeddings-v1:0 embeds text, image, audio or video, one modality per item and one item per request. Media comes from inline Data or an s3://bucket/key URL; any other URL is rejected. Nova needs a declared format per media part, derived from MIMEType or the S3 key’s extension (png, jpeg, webp, gif; mp3, wav, ogg; mp4, mov, mkv, webm, flv, mpeg, wmv, 3gp). TaskType maps to embeddingPurpose (GENERIC_INDEX default, GENERIC_RETRIEVAL, TEXT_RETRIEVAL, IMAGE_RETRIEVAL, VIDEO_RETRIEVAL, AUDIO_RETRIEVAL, DOCUMENT_RETRIEVAL, CLASSIFICATION, CLUSTERING), Dimensions is 256, 384, 1024 or 3072, and Nova’s own knobs ride in ExtraParams: truncationMode (END, START, NONE), detailLevel (STANDARD_IMAGE, DOCUMENT_IMAGE; image parts only) and embeddingMode (video only). Video returns one audio_video vector by default. With embeddingMode: "AUDIO_VIDEO_SEPARATE" one input returns an audio vector and a video vector:
Nova and Cohere-on-Bedrock report token usage only in a response header, which Bifrost reads into Usage.

OpenAI-compatible providers

OpenAI, Azure OpenAI, Mistral, Parasail and every other provider that speaks the OpenAI embeddings dialect accept text and tokens parts only, and the two cannot be mixed in one request. Only EncodingFormat and Dimensions are sent on the wire; TaskType, Title and AutoTruncate are not part of the OpenAI format and are not forwarded.

Per-Item Parameters

Leave Params nil on an item and it inherits the request-level defaults; set it and that item alone uses the override — a query embedded with RETRIEVAL_QUERY alongside documents embedded with RETRIEVAL_DOCUMENT, say.
An item that sets Params replaces the request-level params wholesale — the two are not merged field by field, so repeat any request-level value you still want (as Dimensions is repeated above). EmbeddingInputItem.EffectiveParams(defaults) returns the params an item will actually be sent with.
Only providers whose wire format has one parameter block per item can honour this — currently Gemini (:batchEmbedContents). Everything else returns a 400 naming the offending item index rather than silently ignoring the override.

Things to know

  • Token usage is uneven across multimodal models. Vertex multimodalembedding@001 returns a nil Usage, Titan image-only inputs report zero tokens, and Cohere image tokens live under PromptTokensDetails. Budgets and cost metered on PromptTokens do not see those inputs.
  • Semantic cache keys include TaskType, Title and AutoTruncate, so a RETRIEVAL_QUERY request is never served a cached RETRIEVAL_DOCUMENT vector.
  • Migrating from the old EmbeddingInput struct: &schemas.EmbeddingInput{Texts: []string{"hello"}} becomes []schemas.EmbeddingInputItem{{Content: schemas.EmbeddingContent{{Type: schemas.EmbeddingContentPartTypeText, Text: &text}}}}. The helpers EmbeddingInput(items).Texts() and .TokenIDs() flatten the new shape back to the old one when you only need the strings or token IDs.
Check the Supported Providers page for more information on multimodal capabilities supported by each provider.

Next Steps