This commit is contained in:
Ali Abid 2020-07-07 07:27:14 -07:00
commit c9edbb3eb8
18 changed files with 150 additions and 444 deletions

View File

@ -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/")

View File

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

View File

@ -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`.

View File

@ -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]

View File

@ -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()

View File

@ -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()

View File

@ -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):
"""

View File

@ -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 {

View File

@ -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.",

View File

@ -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> &nbsp; <br>
model = tf.keras.Sequential() <br>
# Define your model, as you ordinarily do <br>
# Train your model, as you ordinarily do <br> &nbsp; <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>&nbsp;<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 &nbsp;
<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 &nbsp;
<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>

View File

@ -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',

View File

@ -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__':

View File

@ -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
View 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