Inference Providers documentation
Building an AI Image Editor with Gradio and Inference Providers
Building an AI Image Editor with Gradio and Inference Providers
In this guide, we’ll build an AI-powered image editor that lets users upload images and edit them using natural language prompts. This project demonstrates how to combine Inference Providers with image-to-image models like Qwen’s Image Edit and Black Forest Labs’ Flux Kontext.
Our app will:
- Accept image uploads through a web interface
- Process natural language prompts editing instructions like “Turn the cat into a tiger”
- Transform images using Qwen Image Edit or FLUX.1 Kontext
- Display results in a Gradio interface
TL;DR - this guide will show you how to build an AI image editor with Gradio and Inference Providers, just like this one.
Step 1: Set Up Authentication
Before we start coding, authenticate with Hugging Face using your token:
# Get your token from https://huggingface.co/settings/tokens export HF_TOKEN="your_token_here"
This guide assumes you have a Hugging Face account. If you don’t have one, you can create one for free at huggingface.co.
When you set this environment variable, it handles authentication automatically for all your inference calls. You can generate a token from your settings page.
Step 2: Project Setup
Create a new project directory and initialize it with uv:
mkdir image-editor-app cd image-editor-app uv init
This creates a basic project structure with a pyproject.toml
file. Now add the required dependencies:
uv add huggingface-hub>=0.34.4 gradio>=5.0.0 pillow>=11.3.0
The dependencies are now installed and ready to use! Also, uv
will maintain the pyproject.toml
file for you as you add dependencies.
We’re using
uv
because it’s a fast Python package manager that handles dependency resolution and virtual environment management automatically. It’s much faster than pip and provides better dependency resolution. If you’re not familiar withuv
, check it out here.
Step 3: Build the Core Image Editing Function
Now let’s create the main logic for our application - the image editing function that transforms images using AI.
Create main.py
then import the necessary libraries and instantiate the InferenceClient. We’re using the fal-ai
provider for fast image processing, but other providers like replicate
are also available.
import os import gradio as gr from huggingface_hub import InferenceClient import io # Initialize the client with fal-ai provider for fast image processing client = InferenceClient( provider="fal-ai", api_key=os.environ["HF_TOKEN"], )
Now let’s create the image editing function. This function takes an input image and a prompt, and returns an edited image. We also want to handle errors gracefully and return the original image if there’s an error, so our UI always shows something.
def edit_image(input_image, prompt): """ Edit an image using the given prompt. Args: input_image: PIL Image object from Gradio prompt: String prompt for image editing Returns: PIL Image object (edited image) """ if input_image is None: return None if not prompt or prompt.strip() == "": return input_image try: # Convert PIL Image to bytes img_bytes = io.BytesIO() input_image.save(img_bytes, format="PNG") img_bytes = img_bytes.getvalue() # Use the image_to_image method with Qwen's image editing model edited_image = client.image_to_image( img_bytes, prompt=prompt.strip(), model="Qwen/Qwen-Image-Edit", ) return edited_image except Exception as e: print(f"Error editing image: {e}") return input_image
We’re using the
fal-ai
provider with theQwen/Qwen-Image-Edit
model. The fal-ai provider offers fast inference times, perfect for interactive applications.However, you can experiment with different providers for various performance characteristics:
client = InferenceClient(provider="replicate", api_key=os.environ["HF_TOKEN"]) client = InferenceClient(provider="auto", api_key=os.environ["HF_TOKEN"]) # Automatic selection
Step 4: Create the Gradio Interface
Now let’s build a simple user-friendly interface using Gradio.
# Create the Gradio interface with gr.Blocks(title="Image Editor", theme=gr.themes.Soft()) as interface: gr.Markdown( """ # 🎨 AI Image Editor Upload an image and describe how you want to edit it using natural language! """ ) with gr.Row(): with gr.Column(): input_image = gr.Image(label="Upload Image", type="pil", height=400) prompt = gr.Textbox( label="Edit Prompt", placeholder="Describe how you want to edit the image...", lines=2, ) edit_btn = gr.Button("✨ Edit Image", variant="primary", size="lg") with gr.Column(): output_image = gr.Image(label="Edited Image", type="pil", height=400) # Example images and prompts with gr.Row(): gr.Examples( examples=[ ["cat.png", "Turn the cat into a tiger"], ["cat.png", "Make it look like a watercolor painting"], ["cat.png", "Change the background to a forest"], ], inputs=[input_image, prompt], outputs=output_image, fn=edit_image, cache_examples=False, ) # Event handlers edit_btn.click(fn=edit_image, inputs=[input_image, prompt], outputs=output_image) # Allow Enter key to trigger editing prompt.submit(fn=edit_image, inputs=[input_image, prompt], outputs=output_image)
In this app we’ll use some practical Gradio features to make a user-friendly app
- We’ll use blocks to create a two column layout with the image upload and the edited image.
- We’ll drop some markdown into to explain what the app does.
- And, we’ll use
gr.Examples
to show some example inputs to give the user some inspiration.
Finally, add the launch configuration at the end of main.py
:
if __name__ == "__main__": interface.launch( share=True, # Creates a public link server_name="0.0.0.0", # Allow external access server_port=7860, # Default Gradio port show_error=True, # Show errors in the interface )
Now run your application:
python main.py
Your app will launch locally at http://localhost:7860
and Gradio will also provide a public shareable link!
Complete Working Code
📋 Click to view the complete main.py file
import os import gradio as gr from huggingface_hub import InferenceClient from PIL import Image import io # Initialize the client client = InferenceClient( provider="fal-ai", api_key=os.environ["HF_TOKEN"], ) def edit_image(input_image, prompt): """ Edit an image using the given prompt. Args: input_image: PIL Image object from Gradio prompt: String prompt for image editing Returns: PIL Image object (edited image) """ if input_image is None: return None if not prompt or prompt.strip() == "": return input_image try: # Convert PIL Image to bytes img_bytes = io.BytesIO() input_image.save(img_bytes, format="PNG") img_bytes = img_bytes.getvalue() # Use the image_to_image method edited_image = client.image_to_image( img_bytes, prompt=prompt.strip(), model="Qwen/Qwen-Image-Edit", ) return edited_image except Exception as e: print(f"Error editing image: {e}") return input_image # Create Gradio interface with gr.Blocks(title="Image Editor", theme=gr.themes.Soft()) as interface: gr.Markdown( """ # 🎨 AI Image Editor Upload an image and describe how you want to edit it using natural language! """ ) with gr.Row(): with gr.Column(): input_image = gr.Image(label="Upload Image", type="pil", height=400) prompt = gr.Textbox( label="Edit Prompt", placeholder="Describe how you want to edit the image...", lines=2, ) edit_btn = gr.Button("✨ Edit Image", variant="primary", size="lg") with gr.Column(): output_image = gr.Image(label="Edited Image", type="pil", height=400) # Example images and prompts with gr.Row(): gr.Examples( examples=[ ["cat.png", "Turn the cat into a tiger"], ["cat.png", "Make it look like a watercolor painting"], ["cat.png", "Change the background to a forest"], ], inputs=[input_image, prompt], outputs=output_image, fn=edit_image, cache_examples=False, ) # Event handlers edit_btn.click(fn=edit_image, inputs=[input_image, prompt], outputs=output_image) # Allow Enter key to trigger editing prompt.submit(fn=edit_image, inputs=[input_image, prompt], outputs=output_image) if __name__ == "__main__": interface.launch( share=True, # Creates a public link server_name="0.0.0.0", # Allow external access server_port=7860, # Default Gradio port show_error=True, # Show errors in the interface )
Deploy on Hugging Face Spaces
Let’s deploy our app to Hugging Face Spaces.
First, we will export our dependencies to a requirements file.
uv export --format requirements-txt --output-file requirements.txt
This creates a requirements.txt
file with all your project dependencies and their exact versions from the lockfile.
The
uv export
command ensures that your Space will use the exact same dependency versions that you tested locally, preventing deployment issues caused by version mismatches.
Now you can deploy to Spaces:
- Create a new Space: Go to huggingface.co/new-space
- Choose Gradio SDK and make it public
- Upload your files: Upload
main.py
,requirements.txt
, and any example images - Add your token: In Space settings, add
HF_TOKEN
as a secret - Launch: Your app will be live at
https://huggingface.co/spaces/your-username/your-space-name
Next Steps
Congratulations! You’ve created a production-ready AI image editor. Now that you have a working image editor, here are some ideas to extend it:
- Batch processing: Edit multiple images at once
- Object removal: Remove unwanted objects from images
- Provider comparison: Benchmark different providers for your use case
Happy building! And remember to share your app with the community on the Hub.
Update on GitHub