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 ID | Quality | Speed | Price | Best For |
|---|---|---|---|---|
| flux-pro-1.1 | Excellent | Medium | $0.055/image | Professional work |
| flux-pro | Excellent | Medium | $0.05/image | High quality |
| flux-dev | Very Good | Fast | $0.025/image | Development |
| flux-schnell | Good | Very Fast | $0.003/image | Rapid 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
-
Prompt Engineering
- Be detailed and specific
- Include style, mood, lighting
- Mention technical details (lens, lighting, etc)
- FLUX understands complex descriptions
-
Model Selection
- Use flux-pro-1.1 for final production
- Use flux-dev for development/testing
- Use flux-schnell for rapid prototyping
-
Quality Optimization
- FLUX needs fewer iterations than SD
- Prompts can be more natural/conversational
- Text in images works reliably
-
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.