mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-06 10:25:17 +08:00
Merge branch 'master' of https://github.com/gradio-app/gradio-UI
This commit is contained in:
commit
c9edbb3eb8
@ -14,6 +14,8 @@ from gradio.tunneling import create_tunnel
|
||||
import urllib.request
|
||||
from shutil import copyfile
|
||||
import requests
|
||||
import os
|
||||
|
||||
|
||||
INITIAL_PORT_VALUE = (
|
||||
7860
|
||||
@ -21,7 +23,7 @@ INITIAL_PORT_VALUE = (
|
||||
TRY_NUM_PORTS = (
|
||||
100
|
||||
) # Number of ports to try before giving up and throwing an exception.
|
||||
LOCALHOST_NAME = "127.0.0.1"
|
||||
LOCALHOST_NAME = os.getenv('GRADIO_SERVER_NAME', "127.0.0.1")
|
||||
GRADIO_API_SERVER = "https://api.gradio.app/v1/tunnel-request"
|
||||
|
||||
STATIC_TEMPLATE_LIB = pkg_resources.resource_filename("gradio", "templates/")
|
||||
|
@ -42,6 +42,7 @@ class AbstractOutput(ABC):
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
class Label(AbstractOutput):
|
||||
def __init__(self, num_top_classes=None, label=None):
|
||||
self.num_top_classes = num_top_classes
|
||||
|
BIN
dist/gradio-0.9.6-py3.7.egg
vendored
BIN
dist/gradio-0.9.6-py3.7.egg
vendored
Binary file not shown.
BIN
dist/gradio-0.9.7-py3-none-any.whl
vendored
BIN
dist/gradio-0.9.7-py3-none-any.whl
vendored
Binary file not shown.
BIN
dist/gradio-0.9.7.tar.gz
vendored
BIN
dist/gradio-0.9.7.tar.gz
vendored
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: gradio
|
||||
Version: 0.9.7
|
||||
Version: 0.9.8
|
||||
Summary: Python library for easily interacting with trained machine learning models
|
||||
Home-page: https://github.com/gradio-app/gradio-UI
|
||||
Author: Abubakar Abid
|
||||
|
@ -1 +1 @@
|
||||
from gradio.interface import Interface # This makes it possible to import `Interface` as `gradio.Interface`.
|
||||
from gradio.interface import * # This makes it possible to import `Interface` as `gradio.Interface`.
|
||||
|
@ -67,7 +67,7 @@ class AbstractInput(ABC):
|
||||
|
||||
|
||||
class Sketchpad(AbstractInput):
|
||||
def __init__(self, cast_to="numpy", shape=(28, 28), invert_colors=True,
|
||||
def __init__(self, shape=(28, 28), invert_colors=True,
|
||||
flatten=False, scale=1/255, shift=0,
|
||||
dtype='float64', sample_inputs=None, label=None):
|
||||
self.image_width = shape[0]
|
||||
|
@ -17,6 +17,8 @@ import random
|
||||
import time
|
||||
import inspect
|
||||
from IPython import get_ipython
|
||||
import sys
|
||||
import weakref
|
||||
|
||||
|
||||
PKG_VERSION_URL = "https://gradio.app/api/pkg-version"
|
||||
@ -27,6 +29,7 @@ class Interface:
|
||||
The Interface class represents a general input/output interface for a machine learning model. During construction,
|
||||
the appropriate inputs and outputs
|
||||
"""
|
||||
instances = weakref.WeakSet()
|
||||
|
||||
def __init__(self, fn, inputs, outputs, saliency=None, verbose=False, examples=None,
|
||||
live=False, show_input=True, show_output=True,
|
||||
@ -82,6 +85,9 @@ class Interface:
|
||||
self.description = description
|
||||
self.thumbnail = thumbnail
|
||||
self.examples = examples
|
||||
self.server_port = None
|
||||
self.simple_server = None
|
||||
Interface.instances.add(self)
|
||||
|
||||
def get_config_file(self):
|
||||
config = {
|
||||
@ -204,7 +210,12 @@ class Interface:
|
||||
return
|
||||
raise RuntimeError("Validation did not pass")
|
||||
|
||||
def launch(self, inline=None, inbrowser=None, share=False, validate=True):
|
||||
def close(self):
|
||||
if self.simple_server and not(self.simple_server.fileno() == -1): # checks to see if server is running
|
||||
print("Closing Gradio server on port {}...".format(self.server_port))
|
||||
networking.close_server(self.simple_server)
|
||||
|
||||
def launch(self, inline=None, inbrowser=None, share=False, validate=True, debug=False):
|
||||
"""
|
||||
Standard method shared by interfaces that creates the interface and sets up a websocket to communicate with it.
|
||||
:param inline: boolean. If True, then a gradio interface is created inline (e.g. in jupyter or colab notebook)
|
||||
@ -223,22 +234,13 @@ class Interface:
|
||||
except (ImportError, AttributeError): # If they are using TF >= 2.0 or don't have TF, just ignore this.
|
||||
pass
|
||||
|
||||
# If an existing interface is running with this instance, close it.
|
||||
if self.status == "RUNNING":
|
||||
if self.verbose:
|
||||
print("Closing existing server...")
|
||||
if self.simple_server is not None:
|
||||
try:
|
||||
networking.close_server(self.simple_server)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
output_directory = tempfile.mkdtemp()
|
||||
# Set up a port to serve the directory containing the static files with interface.
|
||||
server_port, httpd = networking.start_simple_server(self, output_directory, self.server_name)
|
||||
path_to_local_server = "http://{}:{}/".format(self.server_name, server_port)
|
||||
networking.build_template(output_directory)
|
||||
|
||||
self.server_port = server_port
|
||||
self.status = "RUNNING"
|
||||
self.simple_server = httpd
|
||||
|
||||
@ -247,6 +249,7 @@ class Interface:
|
||||
from_ipynb = get_ipython()
|
||||
if "google.colab" in str(from_ipynb):
|
||||
is_colab = True
|
||||
print("Google colab notebook detected.")
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
@ -264,11 +267,17 @@ class Interface:
|
||||
|
||||
if not is_colab:
|
||||
print(strings.en["RUNNING_LOCALLY"].format(path_to_local_server))
|
||||
else:
|
||||
if debug:
|
||||
print("This cell will run indefinitely so that you can see errors and logs. To turn off, "
|
||||
"set debug=False in launch().")
|
||||
else:
|
||||
print("To show errors in colab notebook, set debug=True in launch()")
|
||||
|
||||
if share:
|
||||
try:
|
||||
share_url = networking.setup_tunnel(server_port)
|
||||
print("External URL:", share_url)
|
||||
print("Running on External URL:", share_url)
|
||||
except RuntimeError:
|
||||
share_url = None
|
||||
if self.verbose:
|
||||
@ -330,4 +339,18 @@ class Interface:
|
||||
|
||||
networking.set_config(config, output_directory)
|
||||
|
||||
if debug:
|
||||
while True:
|
||||
sys.stdout.flush()
|
||||
time.sleep(0.1)
|
||||
|
||||
return httpd, path_to_local_server, share_url
|
||||
|
||||
@classmethod
|
||||
def get_instances(cls):
|
||||
return list(Interface.instances) #Returns list of all current instances
|
||||
|
||||
|
||||
def reset_all():
|
||||
for io in Interface.get_instances():
|
||||
io.close()
|
||||
|
@ -14,6 +14,8 @@ from gradio.tunneling import create_tunnel
|
||||
import urllib.request
|
||||
from shutil import copyfile
|
||||
import requests
|
||||
import sys
|
||||
|
||||
|
||||
INITIAL_PORT_VALUE = (
|
||||
7860
|
||||
@ -21,7 +23,7 @@ INITIAL_PORT_VALUE = (
|
||||
TRY_NUM_PORTS = (
|
||||
100
|
||||
) # Number of ports to try before giving up and throwing an exception.
|
||||
LOCALHOST_NAME = "127.0.0.1"
|
||||
LOCALHOST_NAME = os.getenv('GRADIO_SERVER_NAME', "127.0.0.1")
|
||||
GRADIO_API_SERVER = "https://api.gradio.app/v1/tunnel-request"
|
||||
|
||||
STATIC_TEMPLATE_LIB = pkg_resources.resource_filename("gradio", "templates/")
|
||||
@ -115,7 +117,6 @@ def get_first_available_port(initial, final):
|
||||
def serve_files_in_background(interface, port, directory_to_serve=None, server_name=LOCALHOST_NAME):
|
||||
class HTTPHandler(SimpleHTTPRequestHandler):
|
||||
"""This handler uses server.base_path instead of always using os.getcwd()"""
|
||||
|
||||
def _set_headers(self):
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "application/json")
|
||||
@ -132,7 +133,6 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
|
||||
def do_POST(self):
|
||||
# Read body of the request.
|
||||
|
||||
if self.path == "/api/predict/":
|
||||
# Make the prediction.
|
||||
self._set_headers()
|
||||
@ -196,12 +196,13 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
|
||||
# Now loop forever
|
||||
def serve_forever():
|
||||
# try:
|
||||
while True:
|
||||
# sys.stdout.flush()
|
||||
httpd.serve_forever()
|
||||
# except (KeyboardInterrupt, OSError):
|
||||
# httpd.server_close()
|
||||
try:
|
||||
while True:
|
||||
sys.stdout.flush()
|
||||
httpd.serve_forever()
|
||||
except (KeyboardInterrupt, OSError):
|
||||
httpd.shutdown()
|
||||
httpd.server_close()
|
||||
|
||||
thread = threading.Thread(target=serve_forever, daemon=False)
|
||||
thread.start()
|
||||
@ -213,13 +214,11 @@ def start_simple_server(interface, directory_to_serve=None, server_name=None):
|
||||
port = get_first_available_port(
|
||||
INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS
|
||||
)
|
||||
httpd = serve_files_in_background(
|
||||
interface, port, directory_to_serve, server_name)
|
||||
httpd = serve_files_in_background(interface, port, directory_to_serve, server_name)
|
||||
return port, httpd
|
||||
|
||||
|
||||
def close_server(server):
|
||||
server.shutdown()
|
||||
server.server_close()
|
||||
|
||||
|
||||
|
@ -42,7 +42,12 @@ class AbstractOutput(ABC):
|
||||
"""
|
||||
return {}
|
||||
|
||||
|
||||
class Label(AbstractOutput):
|
||||
LABEL_KEY = "label"
|
||||
CONFIDENCE_KEY = "confidence"
|
||||
CONFIDENCES_KEY = "confidences"
|
||||
|
||||
def __init__(self, num_top_classes=None, label=None):
|
||||
self.num_top_classes = num_top_classes
|
||||
super().__init__(label)
|
||||
@ -59,16 +64,19 @@ class Label(AbstractOutput):
|
||||
if self.num_top_classes is not None:
|
||||
sorted_pred = sorted_pred[:self.num_top_classes]
|
||||
return {
|
||||
"label": sorted_pred[0][0],
|
||||
"confidences": [
|
||||
self.LABEL_KEY: sorted_pred[0][0],
|
||||
self.CONFIDENCES_KEY: [
|
||||
{
|
||||
"label": pred[0],
|
||||
"confidence" : pred[1]
|
||||
self.LABEL_KEY: pred[0],
|
||||
self.CONFIDENCE_KEY: pred[1]
|
||||
} for pred in sorted_pred
|
||||
]
|
||||
}
|
||||
elif isinstance(prediction, int) or isinstance(prediction, float):
|
||||
return {self.LABEL_KEY: str(prediction)}
|
||||
else:
|
||||
raise ValueError("Function output should be string or dict")
|
||||
raise ValueError("The `Label` output interface expects one of: a string label, or an int label, a "
|
||||
"float label, or a dictionary whose keys are labels and values are confidences.")
|
||||
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
@ -81,6 +89,13 @@ class KeyValues(AbstractOutput):
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
def postprocess(self, prediction):
|
||||
if isinstance(prediction, dict):
|
||||
return prediction
|
||||
else:
|
||||
raise ValueError("The `KeyValues` output interface expects an output that is a dictionary whose keys are "
|
||||
"labels and values are corresponding values.")
|
||||
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
@ -110,9 +125,11 @@ class Textbox(AbstractOutput):
|
||||
}
|
||||
|
||||
def postprocess(self, prediction):
|
||||
"""
|
||||
"""
|
||||
return prediction
|
||||
if isinstance(prediction, str) or isinstance(prediction, int) or isinstance(prediction, float):
|
||||
return str(prediction)
|
||||
else:
|
||||
raise ValueError("The `Textbox` output interface expects an output that is one of: a string, or"
|
||||
"an int/float that can be converted to a string.")
|
||||
|
||||
|
||||
class Image(AbstractOutput):
|
||||
@ -131,9 +148,16 @@ class Image(AbstractOutput):
|
||||
"""
|
||||
"""
|
||||
if self.plot:
|
||||
return preprocessing_utils.encode_plot_to_base64(prediction)
|
||||
try:
|
||||
return preprocessing_utils.encode_plot_to_base64(prediction)
|
||||
except:
|
||||
raise ValueError("The `Image` output interface expects a `matplotlib.pyplot` object"
|
||||
"if plt=True.")
|
||||
else:
|
||||
return preprocessing_utils.encode_array_to_base64(prediction)
|
||||
try:
|
||||
return preprocessing_utils.encode_array_to_base64(prediction)
|
||||
except:
|
||||
raise ValueError("The `Image` output interface (with plt=False) expects a numpy array.")
|
||||
|
||||
def rebuild_flagged(self, dir, msg):
|
||||
"""
|
||||
|
@ -38,8 +38,22 @@ var io_master_template = {
|
||||
|
||||
for (let i = 0; i < this.output_interfaces.length; i++) {
|
||||
this.output_interfaces[i].output(data["data"][i]);
|
||||
// this.output_interfaces[i].target.parent().find(`.loading_time[interface="${i}"]`).text("Latency: " + ((data["durations"][i])).toFixed(2) + "s");
|
||||
}
|
||||
|
||||
let ratio;
|
||||
if (data["durations"].length === 1) {
|
||||
this.output_interfaces[0].target.parent().find(`.loading_time[interface="${this.output_interfaces.length - 1}"]`).text("Latency: " + ((data["durations"][0])).toFixed(2) + "s");
|
||||
} else if (this.output_interfaces.length === data["durations"].length) {
|
||||
for (let i = 0; i < this.output_interfaces.length; i++) {
|
||||
this.output_interfaces[i].target.parent().find(`.loading_time[interface="${i}"]`).text("Latency: " + ((data["durations"][i])).toFixed(2) + "s");
|
||||
}
|
||||
} else {
|
||||
ratio = this.output_interfaces.length / data["durations"].length;
|
||||
for (let i = 0; i < this.output_interfaces.length; i = i + ratio) {
|
||||
this.output_interfaces[i].target.parent().find(`.loading_time[interface="${i + ratio - 1}"]`).text("Latency: " + ((data["durations"][i / ratio])).toFixed(2) + "s");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.config.live) {
|
||||
this.gather();
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
en = {
|
||||
"BETA_MESSAGE": "NOTE: Gradio is in beta stage, please report all bugs to: gradio.app@gmail.com",
|
||||
"RUNNING_LOCALLY": "Model is running locally at: {}",
|
||||
"RUNNING_LOCALLY": "Running locally at: {}",
|
||||
"NGROK_NO_INTERNET": "Unable to create public link for interface, please check internet connection or try "
|
||||
"restarting python interpreter.",
|
||||
"COLAB_NO_LOCAL": "Cannot display local interface on google colab, public link created.",
|
||||
|
331
index.html
331
index.html
@ -1,331 +0,0 @@
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<!--<link rel="icon" href="../../../../favicon.ico">-->
|
||||
|
||||
<title>Gradio: An Interactive Demo for Your Trained ML Model</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="css/index.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-md navbar-light fixed-top" style="background-color: #e3f2fd">
|
||||
<a class="navbar-brand" href="#" style="font-weight:bold">Gradio</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<!--<li class="nav-item active">-->
|
||||
<!--<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>-->
|
||||
<!--</li>-->
|
||||
<!--<li class="nav-item">-->
|
||||
<!--<a class="nav-link disabled" href="#">Disabled</a>-->
|
||||
<!--</li>-->
|
||||
<!--<li class="nav-item dropdown">-->
|
||||
<!--<a class="nav-link dropdown-toggle" href="http://example.com" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a>-->
|
||||
<!--<div class="dropdown-menu" aria-labelledby="dropdown01">-->
|
||||
<!--<a class="dropdown-item" href="#">Action</a>-->
|
||||
<!--<a class="dropdown-item" href="#">Another action</a>-->
|
||||
<!--<a class="dropdown-item" href="#">Something else here</a>-->
|
||||
<!--</div>-->
|
||||
<!--</li>-->
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<!--<li class="nav-item">-->
|
||||
<!--<a class="nav-link" href="#">Help</a>-->
|
||||
<!--</li>-->
|
||||
<li class="nav-item " style="font-weight:500; font-decoration:none">
|
||||
<a class="nav-link" href="http://www.siliconprep.com"><em>A Silicon Prep Tool</em></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<!--<header>-->
|
||||
<!--<div class="collapse bg-dark" id="navbarHeader">-->
|
||||
<!--<div class="container">-->
|
||||
<!--<div class="row">-->
|
||||
<!--<div class="col-sm-8 col-md-7 py-4">-->
|
||||
<!--<h4 class="text-white">About</h4>-->
|
||||
<!--<p class="text-muted">Add some information about the album below, the author, or any other background context. Make it a few sentences long so folks can pick up some informative tidbits. Then, link them off to some social networking sites or contact information.</p>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="col-sm-4 offset-md-1 py-4">-->
|
||||
<!--<h4 class="text-white">Contact</h4>-->
|
||||
<!--<ul class="list-unstyled">-->
|
||||
<!--<li><a href="#" class="text-white">Follow on Twitter</a></li>-->
|
||||
<!--<li><a href="#" class="text-white">Like on Facebook</a></li>-->
|
||||
<!--<li><a href="#" class="text-white">Email me</a></li>-->
|
||||
<!--</ul>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="navbar navbar-dark bg-dark shadow-sm">-->
|
||||
<!--<div class="container d-flex justify-content-between">-->
|
||||
<!--<a href="#" class="navbar-brand d-flex align-items-center">-->
|
||||
<!--<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg>-->
|
||||
<!--<strong>Album</strong>-->
|
||||
<!--</a>-->
|
||||
<!--<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">-->
|
||||
<!--<span class="navbar-toggler-icon"></span>-->
|
||||
<!--</button>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</header>-->
|
||||
|
||||
<main role="main">
|
||||
|
||||
<section class="jumbotron text-center">
|
||||
<div class="container">
|
||||
<h1 class="jumbotron-heading">Gradio</h1>
|
||||
<p class="lead text-muted" style="font-weight:400 !important">Put a beautiful interactive demo layer over your trained ML model.</p>
|
||||
<p>
|
||||
<a href="#" class="btn btn-lg btn-pink my-2">Get started</a>
|
||||
<a href="#" class="btn btn-lg btn-primary my-2">See examples</a>
|
||||
<a href="#" class="btn btn-lg btn-secondary my-2">Github</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="album py-5 bg-light">
|
||||
<div class="container">
|
||||
<h1>Getting started</h1>
|
||||
<p>
|
||||
Gradio (gradient input-output) is a python library that allows you to easily transform your trained model into a webpage that easily allows you to interface with it. This allows you to:
|
||||
<ul>
|
||||
<li>Show off the model to others</li>
|
||||
<li>Identify response to unusual behavior</li>
|
||||
<li>Encourage fairness and reproducibility of your model</li>
|
||||
</ul>
|
||||
Gradio is designed to be very simple to use. For example, in just 2 lines of Python code, you can create a sketchpad that allows you write digits and see whether your MNIST model can correctly identify them.
|
||||
</p>
|
||||
|
||||
<h4> Installation </h4>
|
||||
<p> Gradio is a standard python library, so install it from your terminal like this:
|
||||
<div class="codebox">
|
||||
<code>
|
||||
pip install gradio
|
||||
</code>
|
||||
</div>
|
||||
</p>
|
||||
<h4> Usage </h4>
|
||||
<p> To use gradio in your code, simply import it, and then launch the appropriate interface
|
||||
<div class="codebox">
|
||||
<code>
|
||||
import gradio <br>
|
||||
import tensorflow as tf <br> <br>
|
||||
|
||||
model = tf.keras.Sequential() <br>
|
||||
# Define your model, as you ordinarily do <br>
|
||||
# Train your model, as you ordinarily do <br> <br>
|
||||
|
||||
gradio.interfaces.Sketchpad(model=model, model_type='keras').launch()
|
||||
</code>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
This will open a new browser window which will allow you to draw into a "sketchpad". Behind the scenes, gradio transforms the user drawing into a numeric array and passes it into your model for your prediction.
|
||||
Then, gradio will fetch the result and show it to the user. Like this:
|
||||
<br> <br>
|
||||
Currently, the following <code>model_type</code> are supported:
|
||||
<ul>
|
||||
<li>Keras models</li>
|
||||
<li>Sklearn models</li>
|
||||
<li>Arbitrary python functions</li>
|
||||
</ul>
|
||||
|
||||
See the gallery of interfaces below to see what kind of interfaces can be supported. Contribute your own interfaces by visiting our GitHub page.
|
||||
|
||||
<hr>
|
||||
<h1>Gallery of Interfaces</h1>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<img class="card-img-top" src="img/draw-a-digit.png" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<p class="card-text"><strong>Draw a Digit</strong>: allow users to draw their own digits to test MNIST-type models.</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="location.href='templates/draw_a_digit.html';">View</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="location.href='https://github.com/abidlabs/gradiome/blob/master/templates/draw_a_digit.html';">Source</button>
|
||||
</div>
|
||||
<small class="text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<img class="card-img-top" src="img/placeholder.png" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<p class="card-text"><strong>Emotion Detector</strong>: allow users to make emotions through their webcam and detect their emotion with your model.</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="location.href='templates/emotion_detector.html';">View</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>
|
||||
</div>
|
||||
<small class="text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<img class="card-img-top" src="img/placeholder.png" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<p class="card-text"><strong>Automated Author</strong>: use an RNN to generate a sequence of words beginning the words that the user has supplied</p>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>
|
||||
</div>
|
||||
<small class="text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div class="col-md-4">-->
|
||||
<!--<div class="card mb-4 shadow-sm">-->
|
||||
<!--<img class="card-img-top" src="img/placeholder.png" alt="Card image cap">-->
|
||||
<!--<div class="card-body">-->
|
||||
<!--<p class="card-text"><strong>Image Blender</strong>: use an GAN to generate a sequence of images imputed between two images that the user has supplied.</p>-->
|
||||
<!--<div class="d-flex justify-content-between align-items-center">-->
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">View</button>-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>-->
|
||||
<!--</div>-->
|
||||
<!--<small class="text-muted"></small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="col-md-4">-->
|
||||
<!--<div class="card mb-4 shadow-sm">-->
|
||||
<!--<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="Card image cap">-->
|
||||
<!--<div class="card-body">-->
|
||||
<!--<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>-->
|
||||
<!--<div class="d-flex justify-content-between align-items-center">-->
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">View</button>-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>-->
|
||||
<!--</div>-->
|
||||
<!--<small class="text-muted">9 mins</small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="col-md-4">-->
|
||||
<!--<div class="card mb-4 shadow-sm">-->
|
||||
<!--<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="Card image cap">-->
|
||||
<!--<div class="card-body">-->
|
||||
<!--<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>-->
|
||||
<!--<div class="d-flex justify-content-between align-items-center">-->
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">View</button>-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>-->
|
||||
<!--</div>-->
|
||||
<!--<small class="text-muted">9 mins</small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
<!--<div class="col-md-4">-->
|
||||
<!--<div class="card mb-4 shadow-sm">-->
|
||||
<!--<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="Card image cap">-->
|
||||
<!--<div class="card-body">-->
|
||||
<!--<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>-->
|
||||
<!--<div class="d-flex justify-content-between align-items-center">-->
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">View</button>-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>-->
|
||||
<!--</div>-->
|
||||
<!--<small class="text-muted">9 mins</small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="col-md-4">-->
|
||||
<!--<div class="card mb-4 shadow-sm">-->
|
||||
<!--<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="Card image cap">-->
|
||||
<!--<div class="card-body">-->
|
||||
<!--<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>-->
|
||||
<!--<div class="d-flex justify-content-between align-items-center">-->
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">View</button>-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>-->
|
||||
<!--</div>-->
|
||||
<!--<small class="text-muted">9 mins</small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--<div class="col-md-4">-->
|
||||
<!--<div class="card mb-4 shadow-sm">-->
|
||||
<!--<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="Card image cap">-->
|
||||
<!--<div class="card-body">-->
|
||||
<!--<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>-->
|
||||
<!--<div class="d-flex justify-content-between align-items-center">-->
|
||||
<!--<div class="btn-group">-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">View</button>-->
|
||||
<!--<button type="button" class="btn btn-sm btn-outline-secondary">Source</button>-->
|
||||
<!--</div>-->
|
||||
<!--<small class="text-muted">9 mins</small>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
<!--</div>-->
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<div class="container" >
|
||||
<span class="text-muted">
|
||||
|
||||
<!-- Add font awesome icons -->
|
||||
Gradio is open-source, help make it better
|
||||
<a href="https://github.com/abidlabs/gradiome" target="_blank" class="fa fa-github"></a>
|
||||
|
||||
</span>
|
||||
|
||||
<span class="text-muted pull-right">
|
||||
|
||||
<!-- Add font awesome icons -->
|
||||
Found this useful? Kindly spread the word
|
||||
<a href="https://www.facebook.com/sharer/sharer.php?u=www.siliconprep.com" target="_blank" class="fa fa-facebook"></a>
|
||||
<a href="https://twitter.com/home?status=Check%20out%20Gradio%20tool%20at%20www.siliconprep.com" target="_blank" class="fa fa-twitter"></a>
|
||||
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<!--<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>-->
|
||||
<!--<script src="../../assets/js/vendor/popper.min.js"></script>-->
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
<!--<script src="../../assets/js/vendor/holder.min.js"></script>-->
|
||||
</body>
|
||||
</html>
|
2
setup.py
2
setup.py
@ -5,7 +5,7 @@ except ImportError:
|
||||
|
||||
setup(
|
||||
name='gradio',
|
||||
version='0.9.7',
|
||||
version='0.9.8',
|
||||
include_package_data=True,
|
||||
description='Python library for easily interacting with trained machine learning models',
|
||||
author='Abubakar Abid',
|
||||
|
@ -7,8 +7,7 @@ import gradio.outputs
|
||||
|
||||
class TestInterface(unittest.TestCase):
|
||||
def test_input_output_mapping(self):
|
||||
io = gr.Interface(inputs='SketCHPad', outputs='textBOX', fn=lambda
|
||||
x: x)
|
||||
io = gr.Interface(inputs='SketCHPad', outputs='textBOX', fn=lambda x: x)
|
||||
self.assertIsInstance(io.input_interfaces[0], gradio.inputs.Sketchpad)
|
||||
self.assertIsInstance(io.output_interfaces[0], gradio.outputs.Textbox)
|
||||
|
||||
@ -18,52 +17,15 @@ class TestInterface(unittest.TestCase):
|
||||
self.assertEqual(io.input_interfaces[0], inp)
|
||||
|
||||
def test_output_interface_is_instance(self):
|
||||
# out = gradio.outputs.Label(show_confidences=False)
|
||||
out = gradio.outputs.Label()
|
||||
io = gr.Interface(inputs='SketCHPad', outputs=out, fn=lambda x: x)
|
||||
self.assertEqual(io.output_interfaces[0], out)
|
||||
|
||||
def test_keras_model(self):
|
||||
try:
|
||||
import tensorflow as tf
|
||||
except:
|
||||
raise unittest.SkipTest("Need tensorflow installed to do keras-based tests")
|
||||
inputs = tf.keras.Input(shape=(3,))
|
||||
x = tf.keras.layers.Dense(4, activation=tf.nn.relu)(inputs)
|
||||
outputs = tf.keras.layers.Dense(5, activation=tf.nn.softmax)(x)
|
||||
model = tf.keras.Model(inputs=inputs, outputs=outputs)
|
||||
io = gr.Interface(inputs='SketCHPad', outputs='textBOX', fn=model)
|
||||
# pred = io.predict(np.ones(shape=(1, 3), ))
|
||||
# self.assertEqual(pred.shape, (1, 5))
|
||||
|
||||
def test_func_model(self):
|
||||
def test_prediction(self):
|
||||
def model(x):
|
||||
return 2*x
|
||||
io = gr.Interface(inputs='SketCHPad', outputs='textBOX', fn=model)
|
||||
# pred = io.predict(np.ones(shape=(1, 3)))
|
||||
# self.assertEqual(pred.shape, (1, 3))
|
||||
|
||||
def test_pytorch_model(self):
|
||||
try:
|
||||
import torch
|
||||
except:
|
||||
raise unittest.SkipTest("Need torch installed to do pytorch-based tests")
|
||||
|
||||
class TwoLayerNet(torch.nn.Module):
|
||||
def __init__(self):
|
||||
super(TwoLayerNet, self).__init__()
|
||||
self.linear1 = torch.nn.Linear(3, 4)
|
||||
self.linear2 = torch.nn.Linear(4, 5)
|
||||
|
||||
def forward(self, x):
|
||||
h_relu = torch.nn.functional.relu(self.linear1(x))
|
||||
y_pred = self.linear2(h_relu)
|
||||
return y_pred
|
||||
|
||||
model = TwoLayerNet()
|
||||
io = gr.Interface(inputs='SketCHPad', outputs='textBOX', fn=model)
|
||||
# pred = io.predict(np.ones(shape=(1, 3), dtype=np.float32))
|
||||
# self.assertEqual(pred.shape, (1, 5))
|
||||
io = gr.Interface(inputs='textbox', outputs='textBOX', fn=model)
|
||||
self.assertEqual(io.predict[0](11), 22)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -14,37 +14,39 @@ class TestLabel(unittest.TestCase):
|
||||
path = outputs.BASE_OUTPUT_INTERFACE_JS_PATH.format(out.__class__.__name__.lower())
|
||||
self.assertTrue(os.path.exists(os.path.join(PACKAGE_NAME, path)))
|
||||
|
||||
# def test_postprocessing_string(self):
|
||||
# string = 'happy'
|
||||
# out = outputs.Label()
|
||||
# label = json.loads(out.postprocess(string))
|
||||
# self.assertDictEqual(label, {outputs.Label.LABEL_KEY: string})
|
||||
#
|
||||
# def test_postprocessing_1D_array(self):
|
||||
# array = np.array([0.1, 0.2, 0, 0.7, 0])
|
||||
# true_label = {outputs.Label.LABEL_KEY: 3,
|
||||
# outputs.Label.CONFIDENCES_KEY: [
|
||||
# {outputs.Label.LABEL_KEY: 3, outputs.Label.CONFIDENCE_KEY: 0.7},
|
||||
# {outputs.Label.LABEL_KEY: 1, outputs.Label.CONFIDENCE_KEY: 0.2},
|
||||
# {outputs.Label.LABEL_KEY: 0, outputs.Label.CONFIDENCE_KEY: 0.1},
|
||||
# ]}
|
||||
# out = outputs.Label()
|
||||
# label = json.loads(out.postprocess(array))
|
||||
# self.assertDictEqual(label, true_label)
|
||||
def test_postprocessing_string(self):
|
||||
string = 'happy'
|
||||
out = outputs.Label()
|
||||
label = out.postprocess(string)
|
||||
self.assertDictEqual(label, {outputs.Label.LABEL_KEY: string})
|
||||
|
||||
# def test_postprocessing_1D_array_no_confidences(self):
|
||||
# array = np.array([0.1, 0.2, 0, 0.7, 0])
|
||||
# true_label = {outputs.Label.LABEL_KEY: 3}
|
||||
# out = outputs.Label(show_confidences=False)
|
||||
# label = json.loads(out.postprocess(array))
|
||||
# self.assertDictEqual(label, true_label)
|
||||
#
|
||||
# def test_postprocessing_int(self):
|
||||
# true_label_array = np.array([[[3]]])
|
||||
# true_label = {outputs.Label.LABEL_KEY: 3}
|
||||
# out = outputs.Label()
|
||||
# label = json.loads(out.postprocess(true_label_array))
|
||||
# self.assertDictEqual(label, true_label)
|
||||
def test_postprocessing_dict(self):
|
||||
orig_label = {
|
||||
3: 0.7,
|
||||
1: 0.2,
|
||||
0: 0.1
|
||||
}
|
||||
true_label = {outputs.Label.LABEL_KEY: 3,
|
||||
outputs.Label.CONFIDENCES_KEY: [
|
||||
{outputs.Label.LABEL_KEY: 3, outputs.Label.CONFIDENCE_KEY: 0.7},
|
||||
{outputs.Label.LABEL_KEY: 1, outputs.Label.CONFIDENCE_KEY: 0.2},
|
||||
{outputs.Label.LABEL_KEY: 0, outputs.Label.CONFIDENCE_KEY: 0.1},
|
||||
]}
|
||||
out = outputs.Label()
|
||||
label = out.postprocess(orig_label)
|
||||
self.assertDictEqual(label, true_label)
|
||||
|
||||
def test_postprocessing_array(self):
|
||||
array = np.array([0.1, 0.2, 0, 0.7, 0])
|
||||
out = outputs.Label()
|
||||
self.assertRaises(ValueError, out.postprocess, array)
|
||||
|
||||
def test_postprocessing_int(self):
|
||||
label = 3
|
||||
true_label = {outputs.Label.LABEL_KEY: '3'}
|
||||
out = outputs.Label()
|
||||
label = out.postprocess(label)
|
||||
self.assertDictEqual(label, true_label)
|
||||
|
||||
|
||||
class TestTextbox(unittest.TestCase):
|
||||
|
10
upload_to_pypi.sh
Normal file
10
upload_to_pypi.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Before running this, go to setup.py and update the version # of the library
|
||||
|
||||
echo "Make sure to update the version number in setup.py!!!"
|
||||
rm dist/*
|
||||
python setup.py sdist bdist_wheel
|
||||
python -m twine upload dist/*
|
||||
git add -A
|
||||
git commit -m "updated PyPi version"
|
||||
git push origin master
|
Loading…
Reference in New Issue
Block a user