6 releases (breaking)
| 0.5.0 | Apr 5, 2026 |
|---|---|
| 0.4.0 | Apr 5, 2026 |
| 0.3.0 | Oct 14, 2024 |
| 0.2.0 | Oct 6, 2024 |
| 0.1.1 | Oct 6, 2024 |
#344 in Procedural macros
64KB
1.5K
SLoC
gradio_macro
A macro that generates type-safe API client code for Gradio Rust crate endpoints at compile time.
Usage
Add the crates to your project:
[dependencies]
gradio_macro = "0.4"
gradio = "0.3"
Then use the macro in your code:
use gradio_macro::gradio_api;
use std::fs;
/// Define the API client using the macro
#[gradio_api(url = "hf-audio/whisper-large-v3-turbo", option = "async")]
pub struct WhisperLarge;
#[tokio::main]
async fn main() {
println!("Whisper Large V3 turbo");
// Instantiate the API client
let whisper = WhisperLarge::new().await.unwrap();
// Call the API's predict method.
// `task` is optional (default: "transcribe"), so a builder is generated:
let result = whisper.predict("wavs/english.wav").call().await.unwrap();
// Handle the result
let result = result[0].clone().as_value().unwrap();
// Save the result to a file
std::fs::write("result.txt", format!("{}", result)).expect("Can't write to file");
println!("result written to result.txt");
}
This example demonstrates how to define an asynchronous API client using the gradio_api macro to interact with the hf-audio/whisper-large-v3-turbo Gradio model.
Macro parameters
| Parameter | Required | Description |
|---|---|---|
url |
✅ | HuggingFace space identifier or full Gradio URL |
option |
✅ | "sync" or "async" |
hf_token |
❌ | HuggingFace API token |
auth_username |
❌ | HuggingFace username (pair with auth_password) |
auth_password |
❌ | HuggingFace password (pair with auth_username) |
Explanation
The macro generates the WhisperLarge struct and all its methods automatically from the live Gradio API spec:
- Each named API endpoint becomes a method on the struct.
- Endpoints with optional parameters (those with API-level defaults) generate a builder:
Endpoints with only mandatory parameters are called directly.whisper.predict("audio.wav") // mandatory params only .with_task(WhisperLargePredictTask::Translate) // optional setter (typed enum) .call().await? // execute Literal[...]Python types become typed Rust enums (e.g.WhisperLargePredictTask::Transcribe), providing compile-time safety instead of runtime string validation.- Parameter types are derived from the full Gradio API spec (
f64forfloat,i64forint,boolforbool,impl Into<std::path::PathBuf>for file inputs,impl Into<String>for strings). - A
_backgroundvariant of every direct method (orcall_background()on a builder) returns a streamingPredictionStreamhandle instead of blocking. - Every generated method is documented with parameter names, types, descriptions and return-value information taken directly from the Gradio API spec – your IDE will show this information in hover tooltips.
API caching
The macro spec from the Gradio server is cached in .gradio_cache/<url>.json in your project root.
Subsequent builds load the spec from the cache without making any network request, so VS Code / rust-analyzer will not hang.
Populating and refreshing the cache
Enable the update_cache feature to fetch fresh specs from the network and write them to .gradio_cache/:
# First-time setup or cache refresh:
cargo build --features gradio_macro/update_cache
# For private spaces, pass a token via the environment:
HF_TOKEN=hf_... cargo build --features gradio_macro/update_cache
Without this feature, the macro only reads the local cache. If no cache is present the build fails with a clear error message pointing at this command. If the cache is older than 7 days a warning is printed.
Committing the cache
You may commit the .gradio_cache/ directory to version control for fully reproducible, offline-capable builds. To always fetch a fresh spec instead, add .gradio_cache/ to your .gitignore.
Building CLI tools with gradio_cli
gradio_cli turns a Gradio API spec into a fully-featured clap CLI in a single attribute:
use clap::Parser;
use gradio_macro::gradio_cli;
#[gradio_cli(url = "hf-audio/whisper-large-v3-turbo", option = "async")]
pub struct WhisperCli;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = WhisperCli::parse();
let result = cli.run().await?;
for output in &result {
println!("{}", output.clone().as_value()?);
}
Ok(())
}
Each named endpoint becomes a subcommand, each parameter a --long flag:
$ cargo run -- --help
Gradio API client for hf-audio/whisper-large-v3-turbo
Usage: whisper_cli <COMMAND>
Commands:
predict Calls the `/predict` Gradio endpoint
predict1 Calls the `/predict_1` Gradio endpoint
predict2 Calls the `/predict_2` Gradio endpoint
help Print this message or the help of the given subcommand(s)
$ cargo run -- predict --help
Usage: whisper_cli predict [OPTIONS] --inputs <INPUTS>
Options:
--inputs <INPUTS> parameter_1 (filepath)
--task <TASK> Task [default: transcribe] [possible values: transcribe, translate]
-h, --help Print help
Literal[...] Python types are automatically mapped to clap possible_values, giving
built-in validation and shell completions for free. When used via gradio_api they
become typed Rust enums for compile-time safety.
How it works
The #[gradio_api(...)] and #[gradio_cli(...)] attribute macros call the gradio Rust crate at compile time to introspect the target Gradio space and generate a bespoke client struct or CLI struct.
Limitations
- Prediction outputs are
Vec<gradio::PredictionOutput>(dynamically typed). Extract values with.as_value()or.as_file(). - Complex input types (lists, dicts, etc.) fall back to
impl gradio::serde::Serialize.
Credits
Big Thanks to Jacob Lin for the gradio-rs crate and assistance.
Dependencies
~10–19MB
~315K SLoC