Gradio 代理与 MCP 黑客马拉松
获奖者Gradio 代理与 MCP 黑客马拉松
获奖者核心 `gradio` 库是一个 Python 库。但由于 Python 能够与外部进程交互,你也可以使用 `gradio` 为其他语言编写的程序创建用户界面。通过使用 Python 的 `subprocess` 模块,你可以调用用 C++、Rust 或几乎任何其他语言编写的程序,从而使 `gradio` 成为非 Python 应用程序的灵活 UI 层。
在本文中,我们将通过 Python 的 `subprocess` 模块调用用 C++ 和 Rust 编写的代码,来讲解如何将 `gradio` 与 C++ 和 Rust 集成。我们还将讨论如何与 R 配合使用 Gradio,这甚至更简单,这要归功于 reticulate R 包,它使得在 R 中安装和导入 Python 模块成为可能。
让我们从一个简单的示例开始,将 C++ 程序集成到 Gradio 应用中。假设我们有以下 C++ 程序,用于两个数字相加:
// add.cpp
#include <iostream>
int main() {
double a, b;
std::cin >> a >> b;
std::cout << a + b << std::endl;
return 0;
}
该程序从标准输入读取两个数字,将它们相加,然后输出结果。
我们可以使用 Python 的 `subprocess` 模块围绕这个 C++ 程序构建 Gradio 界面。下面是相应的 Python 代码:
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()
在这里,`subprocess.Popen` 用于执行编译后的 C++ 程序 (`add`),传递输入值,并捕获输出。你可以通过运行以下命令编译 C++ 程序:
g++ -o add add.cpp
这个例子展示了使用 `subprocess` 从 Python 调用 C++ 并围绕它构建 Gradio 界面是多么容易。
现在,我们来看另一个例子:调用 Rust 程序来对图像应用深褐色滤镜。Rust 代码可能如下所示:
// 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]);
}
这个 Rust 程序对图像应用深褐色滤镜。它接受两个命令行参数:输入图像路径和输出图像路径。你可以使用以下命令编译此程序:
cargo build --release
现在,我们可以从 Python 调用此 Rust 程序,并使用 Gradio 构建界面:
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()
在这里,当用户上传图像并点击提交时,Gradio 会调用 Rust 二进制文件 (`sepia`) 来处理图像,并将经过深褐色滤镜处理的输出返回给 Gradio。
此设置展示了如何将用 Rust 编写的性能关键或专用代码集成到 Gradio 界面中。
由于 `reticulate` 包,将 Gradio 与 R 集成特别简单,它允许你在 R 中直接运行 Python 代码。让我们来看一个在 R 中使用 Gradio 的例子。
安装
首先,你需要在 R 中安装 `reticulate` 包:
install.packages("reticulate")
安装后,你可以使用该包直接从 R 脚本内部运行 Gradio。
library(reticulate)
py_install("gradio", pip = TRUE)
gr <- import("gradio") # import gradio as gr
构建 Gradio 应用程序
安装并导入 gradio 后,我们现在可以访问 gradio 的应用程序构建方法。让我们为一个返回问候语的 R 函数构建一个简单的应用程序:
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))
感谢 @IfeanyiIdiaye 为此部分做出的贡献。你可以在这里查看更多示例,包括使用 Gradio Blocks 在 R 中构建机器学习应用程序。