Skip to main content

Black Forest Labs Provider

Black Forest Labs (founded by Stable Diffusion creators) provides FLUX models - the next generation of image synthesis with exceptional quality and prompt adherence.

Setup​

Installation​

import (
"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/bfl"
)

Configuration​

provider := bfl.New(bfl.Config{
APIKey: os.Getenv("BFL_API_KEY"),
})

model, err := provider.ImageModel("flux-pro-1.1")

Get API Key​

export BFL_API_KEY=...

Available Models​

FLUX Models​

Model IDQualitySpeedPriceBest For
flux-pro-1.1ExcellentMedium$0.055/imageProfessional work
flux-proExcellentMedium$0.05/imageHigh quality
flux-devVery GoodFast$0.025/imageDevelopment
flux-schnellGoodVery Fast$0.003/imageRapid iteration

Provider-Specific Features​

Exceptional Quality​

FLUX models produce photorealistic and artistically sophisticated images:

result, err := ai.GenerateImage(ctx, ai.GenerateImageOptions{
Model: model,
Prompt: "A photorealistic portrait of an elderly person with expressive eyes",
Size: "1024x1024",
})

Perfect Text Rendering​

FLUX excels at text in images:

result, err := ai.GenerateImage(ctx, ai.GenerateImageOptions{
Model: model,
Prompt: "A storefront sign that says 'Coffee & Code' in elegant typography",
})

Advanced Prompt Understanding​

Complex, nuanced prompts work well:

result, err := ai.GenerateImage(ctx, ai.GenerateImageOptions{
Model: model,
Prompt: "A cyberpunk street scene at night, neon reflections on wet pavement, " +
"shallow depth of field, cinematic composition, blade runner aesthetic",
})

Examples​

Basic Image Generation​

package main

import (
"context"
"fmt"
"log"
"os"

"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/bfl"
)

func main() {
provider := bfl.New(bfl.Config{
APIKey: os.Getenv("BFL_API_KEY"),
})

model, err := provider.ImageModel("flux-pro-1.1")
if err != nil {
log.Fatal(err)
}

result, err := ai.GenerateImage(context.Background(), ai.GenerateImageOptions{
Model: model,
Prompt: "A majestic dragon perched on a mountain peak at sunrise",
Size: "1024x1024",
})
if err != nil {
log.Fatal(err)
}

os.WriteFile("dragon.png", result.Images[0].Data, 0644)
fmt.Println("Image saved to dragon.png")
}

Professional Photography​

result, err := ai.GenerateImage(ctx, ai.GenerateImageOptions{
Model: model,
Prompt: "Professional product photography: luxury watch on marble surface, " +
"soft studio lighting, shallow depth of field, 85mm lens, f/1.4",
Size: "1024x1024",
})

Fill Models​

flux-pro-1.0-fill uses Black Forest Labs' fill request format. Pass the source image through Files; the provider maps it to the image request field required by the upstream API.

model, _ := bflProvider.ImageModel("flux-pro-1.0-fill")

result, err := model.DoGenerate(ctx, &provider.ImageGenerateOptions{
Prompt: "replace the background with a studio wall",
Files: []provider.ImageFile{{
Data: imageBytes,
MediaType: "image/png",
}},
})

Artistic Styles​

styles := []string{
"oil painting, impressionist style",
"watercolor, loose brushstrokes",
"digital art, concept art style",
"pencil sketch, detailed cross-hatching",
}

basePrompt := "A serene forest path"

for i, style := range styles {
prompt := fmt.Sprintf("%s, %s", basePrompt, style)
result, err := ai.GenerateImage(ctx, ai.GenerateImageOptions{
Model: model,
Prompt: prompt,
})
if err != nil {
continue
}

filename := fmt.Sprintf("forest_%d.png", i)
os.WriteFile(filename, result.Images[0].Data, 0644)
}

Video Generation (FLUX 3)​

provider.VideoModel(modelID) (e.g. "flux-video") generates a single video per call (MaxVideosPerCall() == 1) — FLUX 3 video does not accept a custom frame rate or seed:

videoModel, err := provider.VideoModel("flux-video")
if err != nil {
log.Fatal(err)
}

result, err := ai.GenerateVideo(ctx, ai.GenerateVideoOptions{
Model: videoModel,
Prompt: ai.VideoPrompt{Text: "A time-lapse of clouds over a mountain range"},
})
if err != nil {
log.Fatal(err)
}

for _, video := range result.Videos {
fmt.Println(video.URL)
}

VideoModel also implements provider.VideoModelStarter / VideoModelStatusChecker, so it works with ai.ExperimentalStartVideo / ai.ExperimentalGetVideoStatus.

Workflow Serialization​

BFL image and video models can cross a workflow boundary with provider.SerializeImageModel / DeserializeImageModel and provider.SerializeVideoModel / DeserializeVideoModel. See Provider Serialization for the mechanism.

Best Practices​

  1. Prompt Engineering

    • Be detailed and specific
    • Include style, mood, lighting
    • Mention technical details (lens, lighting, etc)
    • FLUX understands complex descriptions
  2. Model Selection

    • Use flux-pro-1.1 for final production
    • Use flux-dev for development/testing
    • Use flux-schnell for rapid prototyping
  3. Quality Optimization

    • FLUX needs fewer iterations than SD
    • Prompts can be more natural/conversational
    • Text in images works reliably
  4. Cost Management

    • Use schnell for experimentation
    • Switch to pro for finals
    • Batch similar requests

Rate Limits & Pricing​

Rate Limits​

Varies by plan - check dashboard.

Cost Comparison​

func compareFLUXCosts(imageCount int) {
models := map[string]float64{
"flux-pro-1.1": 0.055,
"flux-pro": 0.05,
"flux-dev": 0.025,
"flux-schnell": 0.003,
}

for model, price := range models {
total := price * float64(imageCount)
fmt.Printf("%s: $%.2f\n", model, total)
}
}

See Also​

Provider options are parsed once when the request body is built. Polling and result retrieval reuse the generated request state, matching the TypeScript provider behavior for single-parse option semantics.