Gradio Agents & MCP Hackathon
WinnersGradio Agents & MCP Hackathon
WinnersThe core gradio library is a Python library. But you can also use gradio to create UIs around programs written in other languages, thanks to Python's ability to interface with external processes. Using Python's subprocess module, you can call programs written in C++, Rust, or virtually any other language, allowing gradio to become a flexible UI layer for non-Python applications.
In this post, we'll walk through how to integrate gradio with C++ and Rust, using Python's subprocess module to invoke code written in these languages. We'll also discuss how to use Gradio with R, which is even easier, thanks to the reticulate R package, which makes it possible to install and import Python modules in R.
Let’s start with a simple example of integrating a C++ program into a Gradio app. Suppose we have the following C++ program that adds two numbers:
// add.cpp
#include <iostream>
int main() {
double a, b;
std::cin >> a >> b;
std::cout << a + b << std::endl;
return 0;
}This program reads two numbers from standard input, adds them, and outputs the result.
We can build a Gradio interface around this C++ program using Python's subprocess module. Here’s the corresponding Python code:
import gradio as gr
import subprocess
def add_numbers(a, b):
process = subprocess.Popen(
['./add'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
output, error = process.communicate(input=f"{a} {b}\n".encode())
if error:
return f"Error: {error.decode()}"
return float(output.decode().strip())
demo = gr.Interface(
fn=add_numbers,
inputs=[gr.Number(label="Number 1"), gr.Number(label="Number 2")],
outputs=gr.Textbox(label="Result")
)
demo.launch()Here, subprocess.Popen is used to execute the compiled C++ program (add), pass the input values, and capture the output. You can compile the C++ program by running:
g++ -o add add.cppThis example shows how easy it is to call C++ from Python using subprocess and build a Gradio interface around it.
Now, let’s move to another example: calling a Rust program to apply a sepia filter to an image. The Rust code could look something like this:
// sepia.rs
extern crate image;
use image::{GenericImageView, ImageBuffer, Rgba};
fn sepia_filter(input: &str, output: &str) {
let img = image::open(input).unwrap();
let (width, height) = img.dimensions();
let mut img_buf = ImageBuffer::new(width, height);
for (x, y, pixel) in img.pixels() {
let (r, g, b, a) = (pixel[0] as f32, pixel[1] as f32, pixel[2] as f32, pixel[3]);
let tr = (0.393 * r + 0.769 * g + 0.189 * b).min(255.0);
let tg = (0.349 * r + 0.686 * g + 0.168 * b).min(255.0);
let tb = (0.272 * r + 0.534 * g + 0.131 * b).min(255.0);
img_buf.put_pixel(x, y, Rgba([tr as u8, tg as u8, tb as u8, a]));
}
img_buf.save(output).unwrap();
}
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 3 {
eprintln!("Usage: sepia <input_file> <output_file>");
return;
}
sepia_filter(&args[1], &args[2]);
}This Rust program applies a sepia filter to an image. It takes two command-line arguments: the input image path and the output image path. You can compile this program using:
cargo build --releaseNow, we can call this Rust program from Python and use Gradio to build the interface:
import gradio as gr
import subprocess
def apply_sepia(input_path):
output_path = "output.png"
process = subprocess.Popen(
['./target/release/sepia', input_path, output_path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
process.wait()
return output_path
demo = gr.Interface(
fn=apply_sepia,
inputs=gr.Image(type="filepath", label="Input Image"),
outputs=gr.Image(label="Sepia Image")
)
demo.launch()Here, when a user uploads an image and clicks submit, Gradio calls the Rust binary (sepia) to process the image, and returns the sepia-filtered output to Gradio.
This setup showcases how you can integrate performance-critical or specialized code written in Rust into a Gradio interface.
reticulate)Integrating Gradio with R is particularly straightforward thanks to the reticulate package, which allows you to run Python code directly in R. Let’s walk through an example of using Gradio in R.
Installation
First, you need to install the reticulate package in R:
install.packages("reticulate")Once installed, you can use the package to run Gradio directly from within an R script.
library(reticulate)
py_install("gradio", pip = TRUE)
gr <- import("gradio") # import gradio as grBuilding a Gradio Application
With gradio installed and imported, we now have access to gradio's app building methods. Let's build a simple app for an R function that returns a greeting
greeting <- \(name) paste("Hello", name)
app <- gr$Interface(
fn = greeting,
inputs = gr$Text(label = "Name"),
outputs = gr$Text(label = "Greeting"),
title = "Hello! 😃 👋"
)
app$launch(server_name = "localhost",
server_port = as.integer(3000))Credit to @IfeanyiIdiaye for contributing this section. You can see more examples here, including using Gradio Blocks to build a machine learning application in R.