mirror of
https://github.com/gradio-app/gradio.git
synced 2025-02-11 11:19:58 +08:00
merge
This commit is contained in:
commit
246cdc46d5
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,3 +18,4 @@ __pycache__/
|
||||
*$py.class
|
||||
demo/models/*
|
||||
dist/*
|
||||
*.h5
|
||||
|
223
README.md
223
README.md
@ -4,14 +4,157 @@
|
||||
|
||||
<img src="https://i.ibb.co/GHRk2JP/header-2.png" alt="drawing" width="1000"/>
|
||||
|
||||
At Gradio, we often try to understand what inputs that a model is particularly sensitive to. To help facilitate this, we've developed and open-sourced `gradio`, a python library that allows you to easily create input and output interfaces over trained models to make it easy for you to "play around" with your model in your browser by dragging-and-dropping in your own images (or pasting your own text, recording your own voice, etc.) and seeing what the model outputs. We are working on making creating a shareable, public link to your model so you can share the interface with others (e.g. your client, your advisor, or your dad), who can use the model without writing any code.
|
||||
At Gradio, we often try to understand what inputs a model is particularly sensitive to. To help facilitate this, we've developed and open-sourced `gradio`, a python library that allows you to quickly create input and output interfaces over trained models to make it easy for you to "play around" with your model in your browser by dragging-and-dropping in your own images (or pasting your own text, recording your own voice, etc.) and seeing what the model outputs. `gradio` can also generate a share link which allows anyone, anywhere to use the interface as the model continues to run on your machine.
|
||||
|
||||
Gradio is useful for:
|
||||
* Creating demos of your machine learning code for clients / collaborators / users
|
||||
* Getting feedback on model performance from users
|
||||
* Debugging your model interactively during development
|
||||
|
||||
For more details, see the accompanying paper: ["Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild"](https://arxiv.org/pdf/1906.02569.pdf), *ICML HILL 2019*, and please use the citation below.
|
||||
To get a sense of `gradio`, take a look at a few of these examples, and find more on our website: www.gradio.app.
|
||||
|
||||
## Installation
|
||||
```
|
||||
pip install gradio
|
||||
```
|
||||
(you may need to replace `pip` with `pip3` if you're running `python3`).
|
||||
|
||||
## Usage
|
||||
|
||||
Gradio is very easy to use with your existing code. Here are a few working examples:
|
||||
|
||||
### 0. Hello World [![alt text](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/18ODkJvyxHutTN0P5APWyGFO_xwNcgHDZ?usp=sharing)
|
||||
|
||||
Let's start with a basic function (no machine learning yet!) that greets an input name. We'll wrap the function with a `Text` to `Text` interface.
|
||||
|
||||
```python
|
||||
import gradio as gr
|
||||
|
||||
def greet(name):
|
||||
return "Hello " + name + "!"
|
||||
|
||||
gr.Interface(fn=greet, inputs="text", outputs="text").launch()
|
||||
```
|
||||
|
||||
The core Interface class is initialized with three parameters:
|
||||
|
||||
- `fn`: the function to wrap
|
||||
- `inputs`: the name of the input interface
|
||||
- `outputs`: the name of the output interface
|
||||
|
||||
Calling the `launch()` function of the `Interface` object produces the interface shown in image below. Click on the screenshot to go the live interface in our getting started page.
|
||||
|
||||
<a href="https://gradio.app/getting_started#interface_4">
|
||||
<p align="center">
|
||||
<img src="https://i.ibb.co/Z8p7gLZ/hello-world.png" alt="drawing"/>
|
||||
</p>
|
||||
</a>
|
||||
|
||||
### 1. Inception Net [![alt text](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1c6gQiW88wKBwWq96nqEwuQ1Kyt5LejiU?usp=sharing)
|
||||
|
||||
Now, let's do a machine learning example. We're going to wrap an
|
||||
interface around the InceptionV3 image classifier, which we'll load
|
||||
using Tensorflow! Since this is an image classification model, we will use the `Image` input interface.
|
||||
We'll output a dictionary of labels and their corresponding confidence scores with the `Label` output
|
||||
interface. (The original Inception Net architecture [can be found here](https://arxiv.org/abs/1409.4842))
|
||||
|
||||
```python
|
||||
import gradio as gr
|
||||
import tensorflow as tf
|
||||
import numpy as np
|
||||
import requests
|
||||
|
||||
inception_net = tf.keras.applications.InceptionV3() # load the model
|
||||
|
||||
# Download human-readable labels for ImageNet.
|
||||
response = requests.get("https://git.io/JJkYN")
|
||||
labels = response.text.split("\n")
|
||||
|
||||
def classify_image(inp):
|
||||
inp = inp.reshape((-1, 299, 299, 3))
|
||||
inp = tf.keras.applications.inception_v3.preprocess_input(inp)
|
||||
prediction = inception_net.predict(inp).flatten()
|
||||
return {labels[i]: float(prediction[i]) for i in range(1000)}
|
||||
|
||||
image = gr.inputs.Image(shape=(299, 299, 3))
|
||||
label = gr.outputs.Label(num_top_classes=3)
|
||||
|
||||
gr.Interface(fn=classify_image, inputs=image, outputs=label).launch()
|
||||
```
|
||||
This code will produce the interface below. The interface gives you a way to test
|
||||
Inception Net by dragging and dropping images, and also allows you to use naturally modify the input image using image editing tools that
|
||||
appear when you click EDIT. Notice here we provided actual `gradio.inputs` and `gradio.outputs` objects to the Interface
|
||||
function instead of using string shortcuts. This lets us use built-in preprocessing (e.g. image resizing)
|
||||
and postprocessing (e.g. choosing the number of labels to display) provided by these
|
||||
interfaces.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://i.ibb.co/BtRNc62/inception-net.png" alt="drawing"/>
|
||||
</p>
|
||||
|
||||
You can supply your own model instead of the pretrained model above, as well as use different kinds of models or functions. Here's a list of the interfaces we currently support, along with their preprocessing / postprocessing parameters:
|
||||
|
||||
**Input Interfaces**:
|
||||
- `Sketchpad(shape=(28, 28), invert_colors=True, flatten=False, scale=1/255, shift=0, dtype='float64')`
|
||||
- `Webcam(image_width=224, image_height=224, num_channels=3, label=None)`
|
||||
- `Textbox(lines=1, placeholder=None, label=None, numeric=False)`
|
||||
- `Radio(choices, label=None)`
|
||||
- `Dropdown(choices, label=None)`
|
||||
- `CheckboxGroup(choices, label=None)`
|
||||
- `Slider(minimum=0, maximum=100, default=None, label=None)`
|
||||
- `Image(shape=(224, 224, 3), image_mode='RGB', scale=1/127.5, shift=-1, label=None)`
|
||||
- `Microphone()`
|
||||
|
||||
**Output Interfaces**:
|
||||
- `Label(num_top_classes=None, label=None)`
|
||||
- `KeyValues(label=None)`
|
||||
- `Textbox(lines=1, placeholder=None, label=None)`
|
||||
- `Image(label=None, plot=False)`
|
||||
|
||||
Interfaces can also be combined together, for multiple-input or multiple-output models.
|
||||
|
||||
### 2. Real-Time MNIST [![alt text](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1LXJqwdkZNkt1J_yfLWQ3FLxbG2cAF8p4?usp=sharing)
|
||||
|
||||
Let's wrap a fun `Sketchpad`-to-`Label` UI around MNIST. For this example, we'll take advantage of the `live`
|
||||
feature in the library. Set `live=True` inside `Interface()`> to have it run continuous predictions.
|
||||
We've abstracted the model training from the code below, but you can see the full code on the colab link.
|
||||
|
||||
```python
|
||||
import tensorflow as tf
|
||||
import gradio as gr
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
urlretrieve("https://gr-models.s3-us-west-2.amazonaws.com/mnist-model.h5","mnist-model.h5")
|
||||
model = tf.keras.models.load_model("mnist-model.h5")
|
||||
|
||||
def recognize_digit(inp):
|
||||
prediction = model.predict(inp.reshape(1, 28, 28, 1)).tolist()[0]
|
||||
return {str(i): prediction[i] for i in range(10)}
|
||||
|
||||
sketchpad = gr.inputs.Sketchpad()
|
||||
label = gr.outputs.Label(num_top_classes=3)
|
||||
|
||||
gr.Interface(fn=recognize_digit, inputs=sketchpad,
|
||||
outputs=label, live=True).launch()
|
||||
```
|
||||
|
||||
This code will produce the interface below.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://i.ibb.co/9n2mGgk/mnist-live.png" alt="drawing"/>
|
||||
</p>
|
||||
|
||||
## Contributing:
|
||||
If you would like to contribute and your contribution is small, you can directly open a pull request (PR). If you would like to contribute a larger feature, we recommend first creating an issue with a proposed design for discussion. Please see our contributing guidelines for more info.
|
||||
|
||||
## License:
|
||||
Gradio is licensed under the Apache License 2.0
|
||||
|
||||
## See more:
|
||||
|
||||
You can find many more examples (like GPT-2, model comparison, multiple inputs, and numerical interfaces) as well as more info on usage on our website: www.gradio.app
|
||||
|
||||
See, also, the accompanying paper: ["Gradio: Hassle-Free Sharing and Testing of ML Models in the Wild"](https://arxiv.org/pdf/1906.02569.pdf), *ICML HILL 2019*, and please use the citation below.
|
||||
|
||||
```
|
||||
@article{abid2019gradio,
|
||||
@ -22,80 +165,4 @@ year={2019}
|
||||
}
|
||||
```
|
||||
|
||||
To get a sense of `gradio`, take a look at the at the `examples` and `demo` folders, or read on below! And be sure to visit the gradio website: www.gradio.app.
|
||||
|
||||
## Installation
|
||||
```
|
||||
pip install gradio
|
||||
```
|
||||
(you may need to replace `pip` with `pip3` if you're running `python3`).
|
||||
|
||||
## Usage
|
||||
|
||||
Gradio is very easy to use with your existing code. Here's a working example:
|
||||
|
||||
|
||||
```python
|
||||
import gradio
|
||||
import tensorflow as tf
|
||||
from imagenetlabels import idx_to_labels
|
||||
|
||||
def classify_image(inp):
|
||||
inp = inp.reshape((1, 224, 224, 3))
|
||||
prediction = mobile_net.predict(inp).flatten()
|
||||
return {idx_to_labels[i].split(',')[0]: float(prediction[i]) for i in range(1000)}
|
||||
|
||||
imagein = gradio.inputs.Image(shape=(224, 224, 3))
|
||||
label = gradio.outputs.Label(num_top_classes=3)
|
||||
|
||||
gr.Interface(classify_image, imagein, label, capture_session=True).launch();
|
||||
```
|
||||
|
||||
![alt text](https://i.ibb.co/nM97z2B/image-interface.png)
|
||||
|
||||
|
||||
You can supply your own model instead of the pretrained model above, as well as use different kinds of models or functions. Changing the `input` and `output` parameters in the `Interface` face object allow you to create different interfaces, depending on the needs of your model. Take a look at the python notebooks for more examples. The currently supported interfaces are as follows:
|
||||
|
||||
**Input interfaces**:
|
||||
* Sketchpad
|
||||
* ImageUplaod
|
||||
* Webcam
|
||||
* Textbox
|
||||
|
||||
**Output interfaces**:
|
||||
* Label
|
||||
* Textbox
|
||||
|
||||
## Screenshots
|
||||
|
||||
Here are a few screenshots that show examples of gradio interfaces
|
||||
|
||||
#### MNIST Digit Recognition (Input: Sketchpad, Output: Label)
|
||||
|
||||
```python
|
||||
sketchpad = Sketchpad()
|
||||
label = Label(num_top_classes=4)
|
||||
|
||||
gradio.Interface(predict, sketchpad, label).launch();
|
||||
```
|
||||
|
||||
![alt text](https://i.ibb.co/CV8Kk3D/sketchpad-interface.png)
|
||||
|
||||
#### Human DNA Variant Effect Prediction (Input: Textbox, Output: Label)
|
||||
|
||||
```python
|
||||
gradio.Interface(predict, 'textbox', 'label').launch()
|
||||
```
|
||||
|
||||
![alt text](https://i.ibb.co/C7GXDDQ/label-interface.png)
|
||||
|
||||
### Contributing:
|
||||
If you would like to contribute and your contribution is small, you can directly open a pull request (PR). If you would like to contribute a larger feature, we recommend first creating an issue with a proposed design for discussion. Please see our contributing guidelines for more info.
|
||||
|
||||
### License:
|
||||
Gradio is licensed under the Apache License 2.0
|
||||
|
||||
### See more:
|
||||
Find more info on usage here: www.gradio.app.
|
||||
|
||||
|
||||
|
@ -40,12 +40,6 @@ class AbstractInput(ABC):
|
||||
"""
|
||||
return {"label": self.label}
|
||||
|
||||
def sample_inputs(self):
|
||||
"""
|
||||
An interface can optionally implement a method that sends a list of sample inputs for inference.
|
||||
"""
|
||||
return []
|
||||
|
||||
def preprocess(self, inp):
|
||||
"""
|
||||
By default, no pre-processing is applied to text.
|
||||
@ -67,17 +61,12 @@ class AbstractInput(ABC):
|
||||
|
||||
|
||||
class Sketchpad(AbstractInput):
|
||||
def __init__(self, cast_to="numpy", shape=(28, 28), invert_colors=True,
|
||||
flatten=False, scale=1/255, shift=0,
|
||||
dtype='float64', sample_inputs=None, label=None):
|
||||
def __init__(self, shape=(28, 28), invert_colors=True,
|
||||
flatten=False, label=None):
|
||||
self.image_width = shape[0]
|
||||
self.image_height = shape[1]
|
||||
self.invert_colors = invert_colors
|
||||
self.flatten = flatten
|
||||
self.scale = scale
|
||||
self.shift = shift
|
||||
self.dtype = dtype
|
||||
self.sample_inputs = sample_inputs
|
||||
super().__init__(label)
|
||||
|
||||
@classmethod
|
||||
@ -101,8 +90,6 @@ class Sketchpad(AbstractInput):
|
||||
array = np.array(im).flatten().reshape(1, self.image_width * self.image_height)
|
||||
else:
|
||||
array = np.array(im).flatten().reshape(1, self.image_width, self.image_height)
|
||||
array = array * self.scale + self.shift
|
||||
array = array.astype(self.dtype)
|
||||
return array
|
||||
|
||||
def process_example(self, example):
|
||||
@ -136,8 +123,7 @@ class Webcam(AbstractInput):
|
||||
|
||||
|
||||
class Textbox(AbstractInput):
|
||||
def __init__(self, sample_inputs=None, lines=1, placeholder=None, default=None, label=None, numeric=False):
|
||||
self.sample_inputs = sample_inputs
|
||||
def __init__(self, lines=1, placeholder=None, default=None, numeric=False, label=None):
|
||||
self.lines = lines
|
||||
self.placeholder = placeholder
|
||||
self.default = default
|
||||
@ -227,7 +213,7 @@ class Slider(AbstractInput):
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
"checkbox": {},
|
||||
"slider": {},
|
||||
}
|
||||
|
||||
|
||||
@ -243,8 +229,7 @@ class Checkbox(AbstractInput):
|
||||
|
||||
|
||||
class Image(AbstractInput):
|
||||
def __init__(self, cast_to=None, shape=(224, 224), image_mode='RGB', label=None):
|
||||
self.cast_to = cast_to
|
||||
def __init__(self, shape=(224, 224), image_mode='RGB', label=None):
|
||||
self.image_width = shape[0]
|
||||
self.image_height = shape[1]
|
||||
self.image_mode = image_mode
|
||||
@ -264,29 +249,10 @@ class Image(AbstractInput):
|
||||
**super().get_template_context()
|
||||
}
|
||||
|
||||
def cast_to_base64(self, inp):
|
||||
return inp
|
||||
|
||||
def cast_to_im(self, inp):
|
||||
return preprocessing_utils.decode_base64_to_image(inp)
|
||||
|
||||
def cast_to_numpy(self, inp):
|
||||
im = self.cast_to_im(inp)
|
||||
arr = np.array(im).flatten()
|
||||
return arr
|
||||
|
||||
def preprocess(self, inp):
|
||||
"""
|
||||
Default preprocessing method for is to convert the picture to black and white and resize to be 48x48
|
||||
"""
|
||||
cast_to_type = {
|
||||
"base64": self.cast_to_base64,
|
||||
"numpy": self.cast_to_numpy,
|
||||
"pillow": self.cast_to_im
|
||||
}
|
||||
if self.cast_to:
|
||||
return cast_to_type[self.cast_to](inp)
|
||||
|
||||
im = preprocessing_utils.decode_base64_to_image(inp)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
@ -303,6 +269,8 @@ class Image(AbstractInput):
|
||||
|
||||
|
||||
class Microphone(AbstractInput):
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
def preprocess(self, inp):
|
||||
"""
|
||||
|
@ -19,9 +19,15 @@ import inspect
|
||||
from IPython import get_ipython
|
||||
import sys
|
||||
import weakref
|
||||
import analytics
|
||||
import socket
|
||||
|
||||
|
||||
PKG_VERSION_URL = "https://gradio.app/api/pkg-version"
|
||||
analytics.write_key = "uxIFddIEuuUcFLf9VgH2teTEtPlWdkNy"
|
||||
analytics_url = 'https://api.gradio.app/'
|
||||
hostname = socket.gethostname()
|
||||
ip_address = socket.gethostbyname(hostname)
|
||||
|
||||
|
||||
class Interface:
|
||||
@ -89,6 +95,21 @@ class Interface:
|
||||
self.simple_server = None
|
||||
Interface.instances.add(self)
|
||||
|
||||
data = {'fn': fn,
|
||||
'inputs': inputs,
|
||||
'outputs': outputs,
|
||||
'saliency': saliency,
|
||||
'live': live,
|
||||
'capture_session': capture_session,
|
||||
'host_name': hostname,
|
||||
'ip_address': ip_address
|
||||
}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-initiated-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("gradio-initiated-analytics/ Connection Error")
|
||||
|
||||
def get_config_file(self):
|
||||
config = {
|
||||
"input_interfaces": [
|
||||
@ -184,6 +205,12 @@ class Interface:
|
||||
processed_input = self.input_interface.preprocess(msg)
|
||||
prediction = self.predict(processed_input)
|
||||
except Exception as e:
|
||||
data = {'error': e}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("gradio-error-analytics/ Connection Error")
|
||||
if self.verbose:
|
||||
print("\n----------")
|
||||
print(
|
||||
@ -194,6 +221,12 @@ class Interface:
|
||||
try:
|
||||
_ = self.output_interface.postprocess(prediction)
|
||||
except Exception as e:
|
||||
data = {'error': e}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("gradio-error-analytics/ Connection Error")
|
||||
if self.verbose:
|
||||
print("\n----------")
|
||||
print(
|
||||
@ -250,6 +283,12 @@ class Interface:
|
||||
is_colab = True
|
||||
print("Google colab notebook detected.")
|
||||
except NameError:
|
||||
data = {'error': 'NameError in launch method'}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("Connection Error")
|
||||
pass
|
||||
|
||||
try:
|
||||
@ -278,6 +317,12 @@ class Interface:
|
||||
share_url = networking.setup_tunnel(server_port)
|
||||
print("Running on External URL:", share_url)
|
||||
except RuntimeError:
|
||||
data = {'error': 'RuntimeError in launch method'}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("Connection Error")
|
||||
share_url = None
|
||||
if self.verbose:
|
||||
print(strings.en["NGROK_NO_INTERNET"])
|
||||
@ -343,6 +388,19 @@ class Interface:
|
||||
sys.stdout.flush()
|
||||
time.sleep(0.1)
|
||||
|
||||
launch_method = 'browser' if inbrowser else 'inline'
|
||||
data = {'launch_method': launch_method,
|
||||
'is_google_colab': is_colab,
|
||||
'is_sharing_on': share,
|
||||
'share_url': share_url,
|
||||
'host_name': hostname,
|
||||
'ip_address': ip_address
|
||||
}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-hosted-launched-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("Connection Error")
|
||||
return httpd, path_to_local_server, share_url
|
||||
|
||||
@classmethod
|
||||
|
@ -14,7 +14,7 @@ from gradio.tunneling import create_tunnel
|
||||
import urllib.request
|
||||
from shutil import copyfile
|
||||
import requests
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
INITIAL_PORT_VALUE = (
|
||||
@ -117,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")
|
||||
@ -134,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()
|
||||
@ -198,12 +196,13 @@ def serve_files_in_background(interface, port, directory_to_serve=None, server_n
|
||||
|
||||
# Now loop forever
|
||||
def serve_forever():
|
||||
# try:
|
||||
try:
|
||||
while True:
|
||||
# sys.stdout.flush()
|
||||
sys.stdout.flush()
|
||||
httpd.serve_forever()
|
||||
# except (KeyboardInterrupt, OSError):
|
||||
# httpd.server_close()
|
||||
except (KeyboardInterrupt, OSError):
|
||||
httpd.shutdown()
|
||||
httpd.server_close()
|
||||
|
||||
thread = threading.Thread(target=serve_forever, daemon=False)
|
||||
thread.start()
|
||||
@ -215,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()
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@ import json
|
||||
from gradio import preprocessing_utils
|
||||
import datetime
|
||||
import operator
|
||||
from numbers import Number
|
||||
|
||||
# Where to find the static resources associated with each template.
|
||||
BASE_OUTPUT_INTERFACE_JS_PATH = 'static/js/interfaces/output/{}.js'
|
||||
@ -53,7 +54,7 @@ class Label(AbstractOutput):
|
||||
super().__init__(label)
|
||||
|
||||
def postprocess(self, prediction):
|
||||
if isinstance(prediction, str):
|
||||
if isinstance(prediction, str) or isinstance(prediction, Number):
|
||||
return {"label": prediction}
|
||||
elif isinstance(prediction, dict):
|
||||
sorted_pred = sorted(
|
||||
@ -104,15 +105,11 @@ class KeyValues(AbstractOutput):
|
||||
|
||||
|
||||
class Textbox(AbstractOutput):
|
||||
def __init__(self, lines=1, placeholder=None, label=None):
|
||||
self.lines = lines
|
||||
self.placeholder = placeholder
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
def get_template_context(self):
|
||||
return {
|
||||
"lines": self.lines,
|
||||
"placeholder": self.placeholder,
|
||||
**super().get_template_context()
|
||||
}
|
||||
|
||||
@ -121,7 +118,6 @@ class Textbox(AbstractOutput):
|
||||
return {
|
||||
"text": {},
|
||||
"number": {},
|
||||
"textbox": {"lines": 7}
|
||||
}
|
||||
|
||||
def postprocess(self, prediction):
|
||||
@ -133,7 +129,7 @@ class Textbox(AbstractOutput):
|
||||
|
||||
|
||||
class Image(AbstractOutput):
|
||||
def __init__(self, label=None, plot=False):
|
||||
def __init__(self, plot=False, label=None):
|
||||
self.plot = plot
|
||||
super().__init__(label)
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
.output_text {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
outline: none;
|
||||
@ -8,4 +7,6 @@
|
||||
border: solid 1px black;
|
||||
box-sizing: border-box;
|
||||
padding: 4px;
|
||||
min-height: 30px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
@ -47,7 +47,11 @@ var io_master_template = {
|
||||
}
|
||||
|
||||
if (this.config.live) {
|
||||
this.gather();
|
||||
var io = this;
|
||||
var refresh_lag = this.config.refresh_lag || 0;
|
||||
window.setTimeout(function() {
|
||||
io.gather();
|
||||
}, refresh_lag);
|
||||
} else {
|
||||
this.target.find(".loading").addClass("invisible");
|
||||
this.target.find(".output_interface").removeClass("invisible");
|
||||
|
73
build/lib/gradio/static/js/all_io.js.bak
Normal file
73
build/lib/gradio/static/js/all_io.js.bak
Normal file
@ -0,0 +1,73 @@
|
||||
var io_master_template = {
|
||||
gather: function() {
|
||||
this.clear();
|
||||
for (let iface of this.input_interfaces) {
|
||||
iface.submit();
|
||||
}
|
||||
},
|
||||
clear: function() {
|
||||
this.last_input = new Array(this.input_interfaces.length);
|
||||
this.input_count = 0;
|
||||
},
|
||||
input: function(interface_id, data) {
|
||||
this.last_input[interface_id] = data;
|
||||
this.input_count += 1;
|
||||
if (this.input_count == this.input_interfaces.length) {
|
||||
this.submit();
|
||||
}
|
||||
},
|
||||
submit: function() {
|
||||
let io = this;
|
||||
if (!this.config.live) {
|
||||
this.target.find(".loading").removeClass("invisible");
|
||||
this.target.find(".loading_in_progress").show();
|
||||
this.target.find(".loading_failed").hide();
|
||||
this.target.find(".output_interface").addClass("invisible");
|
||||
this.target.find(".output_interfaces .panel_header").addClass("invisible");
|
||||
}
|
||||
this.fn(this.last_input).then((output) => {
|
||||
io.output(output);
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
this.target.find(".loading_in_progress").hide();
|
||||
this.target.find(".loading_failed").show();
|
||||
})
|
||||
},
|
||||
output: function(data) {
|
||||
this.last_output = data["data"];
|
||||
|
||||
for (let i = 0; i < this.output_interfaces.length; i++) {
|
||||
this.output_interfaces[i].output(data["data"][i]);
|
||||
}
|
||||
if (data["durations"]) {
|
||||
let 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 {
|
||||
this.target.find(".loading").addClass("invisible");
|
||||
this.target.find(".output_interface").removeClass("invisible");
|
||||
this.target.find(".output_interfaces .panel_header").removeClass("invisible");
|
||||
}
|
||||
},
|
||||
flag: function(message) {
|
||||
var post_data = {
|
||||
'data': {
|
||||
'input_data' : toStringIfObject(this.last_input) ,
|
||||
'output_data' : toStringIfObject(this.last_output),
|
||||
'message' : message
|
||||
}
|
||||
}
|
||||
$.ajax({type: "POST",
|
||||
url: "/api/flag/",
|
||||
data: JSON.stringify(post_data),
|
||||
success: function(output){
|
||||
console.log("Flagging successful")
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
@ -1,13 +1,7 @@
|
||||
const textbox_output = {
|
||||
html: `<textarea readonly class="output_text"></textarea>`,
|
||||
html: `<div class="output_text"></div>`,
|
||||
init: function(opts) {
|
||||
if (opts.lines) {
|
||||
this.target.find(".output_text").attr("rows", opts.lines).css("height", "auto");
|
||||
this.target.css("height", "auto");
|
||||
}
|
||||
if (opts.placeholder) {
|
||||
this.target.find(".output_text").attr("placeholder", opts.placeholder)
|
||||
}
|
||||
},
|
||||
output: function(data) {
|
||||
this.target.find(".output_text").text(data);
|
||||
|
@ -31,7 +31,7 @@
|
||||
<a href="https://gradio.app"><img src="../static/img/logo_inline.png" /></a>
|
||||
</nav>
|
||||
<div id="share" class="invisible">
|
||||
Live at <a id="share-link"></a>.
|
||||
Live at <a id="share-link" target="_blank"></a>.
|
||||
<button id="share-copy">Copy Link</button>
|
||||
</div>
|
||||
<div class="container">
|
||||
@ -40,7 +40,7 @@
|
||||
</div>
|
||||
<div id="interface_target" class="container"></div>
|
||||
<div id="examples" class="container invisible">
|
||||
<h3>Examples</h3>
|
||||
<h3>Examples <small>(click to load)</small></h3>
|
||||
<table>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# In[2]:
|
||||
|
||||
|
||||
# installing transformers
|
||||
# !pip install -q git+https://github.com/huggingface/transformers.git
|
||||
# !pip install -q tensorflow==2.1
|
||||
|
||||
|
||||
# In[12]:
|
||||
|
||||
|
||||
import tensorflow as tf
|
||||
from transformers import TFGPT2LMHeadModel, GPT2Tokenizer
|
||||
import gradio
|
||||
|
||||
|
||||
# In[4]:
|
||||
|
||||
|
||||
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
|
||||
|
||||
# add the EOS token as PAD token to avoid warnings
|
||||
model = TFGPT2LMHeadModel.from_pretrained("gpt2", pad_token_id=tokenizer.eos_token_id)
|
||||
|
||||
|
||||
# In[15]:
|
||||
|
||||
|
||||
def predict(inp):
|
||||
input_ids = tokenizer.encode(inp, return_tensors='tf')
|
||||
beam_output = model.generate(input_ids, max_length=49, num_beams=5, no_repeat_ngram_size=2, early_stopping=True)
|
||||
output = tokenizer.decode(beam_output[0], skip_special_tokens=True, clean_up_tokenization_spaces=True)
|
||||
return ".".join(output.split(".")[:-1]) + "."
|
||||
|
||||
# In[18]:
|
||||
|
||||
|
||||
gradio.Interface(predict,"textbox","textbox").launch(inbrowser=True)
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import gradio as gr
|
||||
from time import sleep
|
||||
|
||||
|
||||
def answer_question(quantity, animal, place, activity_list, morning, etc):
|
||||
return f"""The {quantity} {animal}s went to the {place} where they {" and ".join(activity_list)} until the {"morning" if morning else "night"}""", "OK"
|
||||
@ -15,8 +15,8 @@ gr.Interface(answer_question,
|
||||
gr.inputs.Textbox(default="What else?"),
|
||||
],
|
||||
[
|
||||
gr.outputs.Textbox(lines=8),
|
||||
gr.outputs.Textbox(lines=1),
|
||||
gr.outputs.Textbox(),
|
||||
gr.outputs.Textbox(),
|
||||
],
|
||||
examples=[
|
||||
[2, "cat", "park", ["ran", "swam"], True],
|
||||
|
@ -3,44 +3,22 @@ import gradio
|
||||
import os
|
||||
from tensorflow.keras.layers import *
|
||||
import gradio as gr
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
(x_train, y_train),(x_test, y_test) = tf.keras.datasets.mnist.load_data()
|
||||
x_train, x_test = x_train.reshape(-1,784) / 255.0, x_test.reshape(-1,784) / 255.0
|
||||
|
||||
def get_trained_model(n):
|
||||
model = tf.keras.models.Sequential()
|
||||
model.add(Reshape((28, 28, 1), input_shape=(784,)))
|
||||
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu'))
|
||||
model.add(Conv2D(64, (3, 3), activation='relu'))
|
||||
model.add(MaxPooling2D(pool_size=(2, 2)))
|
||||
model.add(Dropout(0.25))
|
||||
model.add(Flatten())
|
||||
model.add(Dense(128, activation='relu'))
|
||||
model.add(Dropout(0.5))
|
||||
model.add(Dense(10, activation='softmax'))
|
||||
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
|
||||
model.fit(x_train[:n], y_train[:n], epochs=2)
|
||||
print(model.evaluate(x_test, y_test))
|
||||
return model
|
||||
urlretrieve("https://gr-models.s3-us-west-2.amazonaws.com/mnist-model.h5","mnist-model.h5")
|
||||
model = tf.keras.models.load_model("mnist-model.h5")
|
||||
|
||||
if not os.path.exists("models/mnist.h5"):
|
||||
model = get_trained_model(n=50000)
|
||||
model.save('models/mnist.h5')
|
||||
else:
|
||||
model = tf.keras.models.load_model('models/mnist.h5')
|
||||
|
||||
graph = tf.get_default_graph()
|
||||
sess = tf.keras.backend.get_session()
|
||||
|
||||
def recognize_digit(image):
|
||||
with graph.as_default():
|
||||
with sess.as_default():
|
||||
prediction = model.predict(image).tolist()[0]
|
||||
return {str(i): prediction[i] for i in range(10)}
|
||||
|
||||
|
||||
gr.Interface(
|
||||
recognize_digit,
|
||||
gradio.inputs.Sketchpad(flatten=True),
|
||||
gradio.outputs.Label(num_top_classes=3),
|
||||
live=True
|
||||
live=True,
|
||||
capture_session=True,
|
||||
).launch()
|
@ -2,6 +2,7 @@ import gradio as gr
|
||||
import numpy as np
|
||||
from time import time
|
||||
|
||||
|
||||
def flip(image):
|
||||
start = time()
|
||||
return image, {
|
||||
@ -9,6 +10,7 @@ def flip(image):
|
||||
"2": 0.8
|
||||
}
|
||||
|
||||
|
||||
def flip2(image):
|
||||
start = time()
|
||||
return np.fliplr(image), time() - start
|
||||
|
@ -3,6 +3,7 @@ import random
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
|
||||
def plot_forecast(final_year, companies, noise, show_legend, point_style):
|
||||
start_year = 2020
|
||||
x = np.arange(start_year, final_year + 1)
|
||||
@ -17,6 +18,7 @@ def plot_forecast(final_year, companies, noise, show_legend, point_style):
|
||||
plt.legend(companies)
|
||||
return plt
|
||||
|
||||
|
||||
gr.Interface(plot_forecast,
|
||||
[
|
||||
gr.inputs.Radio([2025, 2030, 2035, 2040],
|
||||
|
@ -1,177 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
# In[9]:
|
||||
|
||||
|
||||
import tensorflow as tf
|
||||
import sys
|
||||
import gradio
|
||||
from tensorflow.keras.layers import *
|
||||
from tensorflow.keras.datasets import imdb
|
||||
import json
|
||||
from tensorflow.keras import backend as K
|
||||
import numpy as np
|
||||
|
||||
|
||||
# In[2]:
|
||||
|
||||
|
||||
top_words = 5000 # Only keep the 5,000 most frequent words
|
||||
max_word_length = 500 # The maximum length of the review should be 500 words (trim/pad otherwise)
|
||||
|
||||
# (X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words);
|
||||
# # save np.load
|
||||
np_load_old = np.load
|
||||
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)
|
||||
|
||||
# # # call load_data with allow_pickle implicitly set to true
|
||||
(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words=top_words);
|
||||
|
||||
# # restore np.load for future normal usage
|
||||
np.load = np_load_old
|
||||
|
||||
X_train = tf.keras.preprocessing.sequence.pad_sequences(X_train, maxlen=max_word_length)
|
||||
X_test = tf.keras.preprocessing.sequence.pad_sequences(X_test, maxlen=max_word_length)
|
||||
|
||||
|
||||
def get_trained_model(n):
|
||||
model = tf.keras.models.Sequential()
|
||||
model.add(Embedding(top_words, 32, input_length=max_word_length))
|
||||
model.add(Dropout(0.2))
|
||||
model.add(Conv1D(250, 3, padding='valid', activation='relu', strides=1))
|
||||
model.add(GlobalMaxPooling1D())
|
||||
model.add(Dense(250))
|
||||
model.add(Dropout(0.2))
|
||||
model.add(Activation('relu'))
|
||||
model.add(Dense(1))
|
||||
model.add(Activation('sigmoid'))
|
||||
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
|
||||
model.fit(X_train[:n], y_train[:n], epochs=1, batch_size=128)
|
||||
print(model.evaluate(X_test[:n], y_test[:n]))
|
||||
return model
|
||||
|
||||
|
||||
# In[3]:
|
||||
|
||||
|
||||
model = get_trained_model(n=1000) #25000
|
||||
|
||||
|
||||
# In[4]:
|
||||
|
||||
|
||||
graph = tf.get_default_graph()
|
||||
sess = tf.keras.backend.get_session()
|
||||
|
||||
|
||||
# In[5]:
|
||||
|
||||
|
||||
NUM_SPECIAL_TOKENS = 3
|
||||
PAD_TOKEN = 0
|
||||
START_TOKEN = 1
|
||||
UNK_TOKEN = 2
|
||||
|
||||
word_to_id = tf.keras.datasets.imdb.get_word_index()
|
||||
word_to_id = {k: (v + NUM_SPECIAL_TOKENS) for k, v in word_to_id.items()}
|
||||
|
||||
id_to_word = {value: key for key, value in word_to_id.items()}
|
||||
id_to_word[PAD_TOKEN] = "" # Padding tokens are converted to empty strings.
|
||||
id_to_word[START_TOKEN] = "" # Start tokens are converted to empty strings.
|
||||
id_to_word[UNK_TOKEN] = "UNK" # <UNK> tokens are converted to "UNK".
|
||||
|
||||
|
||||
def decode_vector_to_text(vector):
|
||||
text = " ".join(id_to_word[id] for id in vector if id >= 2)
|
||||
return text
|
||||
|
||||
|
||||
def encode_text_to_vector(text, max_word_length=500, top_words=5000):
|
||||
text_vector = text.split(" ")
|
||||
encoded_vector = [
|
||||
word_to_id.get(element, UNK_TOKEN) if word_to_id.get(element, UNK_TOKEN) < top_words else UNK_TOKEN for element
|
||||
in text_vector]
|
||||
encoded_vector = [START_TOKEN] + encoded_vector
|
||||
if len(encoded_vector) < max_word_length:
|
||||
encoded_vector = (max_word_length - len(encoded_vector)) * [PAD_TOKEN] + encoded_vector
|
||||
else:
|
||||
encoded_vector = encoded_vector[:max_word_length]
|
||||
return encoded_vector
|
||||
|
||||
|
||||
def preprocessing(text):
|
||||
new = encode_text_to_vector(text)
|
||||
return tf.keras.preprocessing.sequence.pad_sequences([new], maxlen=max_word_length)
|
||||
|
||||
|
||||
def postprocessing(pred):
|
||||
return {
|
||||
"Positive review": f"{pred[0][0]}",
|
||||
"Negative review": f"{1-pred[0][0]}"
|
||||
}
|
||||
|
||||
def predict(inp):
|
||||
inp = preprocessing(inp)
|
||||
with graph.as_default():
|
||||
with sess.as_default():
|
||||
prediction = model.predict(inp)
|
||||
prediction = postprocessing(prediction)
|
||||
return prediction
|
||||
|
||||
|
||||
def saliency(input, output):
|
||||
with graph.as_default():
|
||||
with sess.as_default():
|
||||
processed_input = preprocessing(input)
|
||||
processed_output = output
|
||||
|
||||
output = 0 if float(output["Positive review"]) > 0.5 else 1
|
||||
input_tensors = [model.layers[0].input, K.learning_phase()]
|
||||
saliency_input = model.layers[1].input
|
||||
saliency_output = model.layers[-1].output[:, output]
|
||||
gradients = model.optimizer.get_gradients(saliency_output, saliency_input)
|
||||
compute_gradients = K.function(inputs=input_tensors, outputs=gradients)
|
||||
saliency_graph = compute_gradients(processed_input.reshape(1, 500))[0]
|
||||
|
||||
saliency_graph = saliency_graph.reshape(500, 32)
|
||||
|
||||
saliency_graph = np.abs(saliency_graph).sum(axis=1)
|
||||
normalized_saliency = (saliency_graph - saliency_graph.min()) / (saliency_graph.max() - saliency_graph.min())
|
||||
|
||||
start_idx = np.where(processed_input[0] == START_TOKEN)[0][0]
|
||||
heat_map = []
|
||||
counter = 0
|
||||
words = input.split(" ")
|
||||
for i in range(start_idx + 1, 500):
|
||||
heat_map.extend([normalized_saliency[i]] * len(words[counter]))
|
||||
heat_map.append(0) # zero saliency value assigned to the spaces between words
|
||||
counter += 1
|
||||
return np.array(heat_map)
|
||||
|
||||
|
||||
# In[6]:
|
||||
|
||||
|
||||
textbox = gradio.inputs.Textbox()
|
||||
label = gradio.outputs.Label()
|
||||
interface = gradio.Interface(inputs=textbox, outputs=label, fn=predict, saliency=saliency)
|
||||
|
||||
|
||||
# In[8]:
|
||||
|
||||
|
||||
interface.launch(inbrowser=True, share=False)
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# In[ ]:
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: gradio
|
||||
Version: 0.9.8
|
||||
Version: 0.9.9.3
|
||||
Summary: Python library for easily interacting with trained machine learning models
|
||||
Home-page: https://github.com/gradio-app/gradio-UI
|
||||
Author: Abubakar Abid
|
||||
|
@ -50,6 +50,7 @@ gradio/static/img/vendor/icon-b.svg
|
||||
gradio/static/img/vendor/icon-c.svg
|
||||
gradio/static/img/vendor/icon-d.svg
|
||||
gradio/static/js/all_io.js
|
||||
gradio/static/js/all_io.js.bak
|
||||
gradio/static/js/gradio.js
|
||||
gradio/static/js/utils.js
|
||||
gradio/static/js/interfaces/input/checkbox.js
|
||||
|
@ -4,3 +4,4 @@ paramiko
|
||||
scipy
|
||||
IPython
|
||||
scikit-image
|
||||
analytics-python
|
||||
|
@ -40,12 +40,6 @@ class AbstractInput(ABC):
|
||||
"""
|
||||
return {"label": self.label}
|
||||
|
||||
def sample_inputs(self):
|
||||
"""
|
||||
An interface can optionally implement a method that sends a list of sample inputs for inference.
|
||||
"""
|
||||
return []
|
||||
|
||||
def preprocess(self, inp):
|
||||
"""
|
||||
By default, no pre-processing is applied to text.
|
||||
@ -67,17 +61,12 @@ class AbstractInput(ABC):
|
||||
|
||||
|
||||
class Sketchpad(AbstractInput):
|
||||
def __init__(self, cast_to="numpy", shape=(28, 28), invert_colors=True,
|
||||
flatten=False, scale=1/255, shift=0,
|
||||
dtype='float64', sample_inputs=None, label=None):
|
||||
def __init__(self, shape=(28, 28), invert_colors=True,
|
||||
flatten=False, label=None):
|
||||
self.image_width = shape[0]
|
||||
self.image_height = shape[1]
|
||||
self.invert_colors = invert_colors
|
||||
self.flatten = flatten
|
||||
self.scale = scale
|
||||
self.shift = shift
|
||||
self.dtype = dtype
|
||||
self.sample_inputs = sample_inputs
|
||||
super().__init__(label)
|
||||
|
||||
@classmethod
|
||||
@ -101,8 +90,6 @@ class Sketchpad(AbstractInput):
|
||||
array = np.array(im).flatten().reshape(1, self.image_width * self.image_height)
|
||||
else:
|
||||
array = np.array(im).flatten().reshape(1, self.image_width, self.image_height)
|
||||
array = array * self.scale + self.shift
|
||||
array = array.astype(self.dtype)
|
||||
return array
|
||||
|
||||
def process_example(self, example):
|
||||
@ -136,8 +123,7 @@ class Webcam(AbstractInput):
|
||||
|
||||
|
||||
class Textbox(AbstractInput):
|
||||
def __init__(self, sample_inputs=None, lines=1, placeholder=None, default=None, label=None, numeric=False):
|
||||
self.sample_inputs = sample_inputs
|
||||
def __init__(self, lines=1, placeholder=None, default=None, numeric=False, label=None):
|
||||
self.lines = lines
|
||||
self.placeholder = placeholder
|
||||
self.default = default
|
||||
@ -227,7 +213,7 @@ class Slider(AbstractInput):
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
"checkbox": {},
|
||||
"slider": {},
|
||||
}
|
||||
|
||||
|
||||
@ -283,6 +269,8 @@ class Image(AbstractInput):
|
||||
|
||||
|
||||
class Microphone(AbstractInput):
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
def preprocess(self, inp):
|
||||
"""
|
||||
|
@ -19,9 +19,15 @@ import inspect
|
||||
from IPython import get_ipython
|
||||
import sys
|
||||
import weakref
|
||||
import analytics
|
||||
import socket
|
||||
|
||||
|
||||
PKG_VERSION_URL = "https://gradio.app/api/pkg-version"
|
||||
analytics.write_key = "uxIFddIEuuUcFLf9VgH2teTEtPlWdkNy"
|
||||
analytics_url = 'https://api.gradio.app/'
|
||||
hostname = socket.gethostname()
|
||||
ip_address = socket.gethostbyname(hostname)
|
||||
|
||||
|
||||
class Interface:
|
||||
@ -89,6 +95,21 @@ class Interface:
|
||||
self.simple_server = None
|
||||
Interface.instances.add(self)
|
||||
|
||||
data = {'fn': fn,
|
||||
'inputs': inputs,
|
||||
'outputs': outputs,
|
||||
'saliency': saliency,
|
||||
'live': live,
|
||||
'capture_session': capture_session,
|
||||
'host_name': hostname,
|
||||
'ip_address': ip_address
|
||||
}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-initiated-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("gradio-initiated-analytics/ Connection Error")
|
||||
|
||||
def get_config_file(self):
|
||||
config = {
|
||||
"input_interfaces": [
|
||||
@ -184,6 +205,12 @@ class Interface:
|
||||
processed_input = self.input_interface.preprocess(msg)
|
||||
prediction = self.predict(processed_input)
|
||||
except Exception as e:
|
||||
data = {'error': e}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("gradio-error-analytics/ Connection Error")
|
||||
if self.verbose:
|
||||
print("\n----------")
|
||||
print(
|
||||
@ -194,6 +221,12 @@ class Interface:
|
||||
try:
|
||||
_ = self.output_interface.postprocess(prediction)
|
||||
except Exception as e:
|
||||
data = {'error': e}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("gradio-error-analytics/ Connection Error")
|
||||
if self.verbose:
|
||||
print("\n----------")
|
||||
print(
|
||||
@ -250,6 +283,12 @@ class Interface:
|
||||
is_colab = True
|
||||
print("Google colab notebook detected.")
|
||||
except NameError:
|
||||
data = {'error': 'NameError in launch method'}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("Connection Error")
|
||||
pass
|
||||
|
||||
try:
|
||||
@ -278,6 +317,12 @@ class Interface:
|
||||
share_url = networking.setup_tunnel(server_port)
|
||||
print("Running on External URL:", share_url)
|
||||
except RuntimeError:
|
||||
data = {'error': 'RuntimeError in launch method'}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-error-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("Connection Error")
|
||||
share_url = None
|
||||
if self.verbose:
|
||||
print(strings.en["NGROK_NO_INTERNET"])
|
||||
@ -343,6 +388,19 @@ class Interface:
|
||||
sys.stdout.flush()
|
||||
time.sleep(0.1)
|
||||
|
||||
launch_method = 'browser' if inbrowser else 'inline'
|
||||
data = {'launch_method': launch_method,
|
||||
'is_google_colab': is_colab,
|
||||
'is_sharing_on': share,
|
||||
'share_url': share_url,
|
||||
'host_name': hostname,
|
||||
'ip_address': ip_address
|
||||
}
|
||||
try:
|
||||
requests.post(analytics_url + 'gradio-hosted-launched-analytics/',
|
||||
data=data)
|
||||
except requests.ConnectionError:
|
||||
print("Connection Error")
|
||||
return httpd, path_to_local_server, share_url
|
||||
|
||||
@classmethod
|
||||
|
@ -10,6 +10,7 @@ import json
|
||||
from gradio import preprocessing_utils
|
||||
import datetime
|
||||
import operator
|
||||
from numbers import Number
|
||||
|
||||
# Where to find the static resources associated with each template.
|
||||
BASE_OUTPUT_INTERFACE_JS_PATH = 'static/js/interfaces/output/{}.js'
|
||||
@ -53,8 +54,8 @@ class Label(AbstractOutput):
|
||||
super().__init__(label)
|
||||
|
||||
def postprocess(self, prediction):
|
||||
if isinstance(prediction, str):
|
||||
return {"label": prediction}
|
||||
if isinstance(prediction, str) or isinstance(prediction, Number):
|
||||
return {"label": str(prediction)}
|
||||
elif isinstance(prediction, dict):
|
||||
sorted_pred = sorted(
|
||||
prediction.items(),
|
||||
@ -104,15 +105,11 @@ class KeyValues(AbstractOutput):
|
||||
|
||||
|
||||
class Textbox(AbstractOutput):
|
||||
def __init__(self, lines=1, placeholder=None, label=None):
|
||||
self.lines = lines
|
||||
self.placeholder = placeholder
|
||||
def __init__(self, label=None):
|
||||
super().__init__(label)
|
||||
|
||||
def get_template_context(self):
|
||||
return {
|
||||
"lines": self.lines,
|
||||
"placeholder": self.placeholder,
|
||||
**super().get_template_context()
|
||||
}
|
||||
|
||||
@ -121,7 +118,6 @@ class Textbox(AbstractOutput):
|
||||
return {
|
||||
"text": {},
|
||||
"number": {},
|
||||
"textbox": {"lines": 7}
|
||||
}
|
||||
|
||||
def postprocess(self, prediction):
|
||||
@ -133,7 +129,7 @@ class Textbox(AbstractOutput):
|
||||
|
||||
|
||||
class Image(AbstractOutput):
|
||||
def __init__(self, label=None, plot=False):
|
||||
def __init__(self, plot=False, label=None):
|
||||
self.plot = plot
|
||||
super().__init__(label)
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
.output_text {
|
||||
resize: none;
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
outline: none;
|
||||
@ -8,4 +7,6 @@
|
||||
border: solid 1px black;
|
||||
box-sizing: border-box;
|
||||
padding: 4px;
|
||||
min-height: 30px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
@ -47,7 +47,11 @@ var io_master_template = {
|
||||
}
|
||||
|
||||
if (this.config.live) {
|
||||
this.gather();
|
||||
var io = this;
|
||||
var refresh_lag = this.config.refresh_lag || 0;
|
||||
window.setTimeout(function() {
|
||||
io.gather();
|
||||
}, refresh_lag);
|
||||
} else {
|
||||
this.target.find(".loading").addClass("invisible");
|
||||
this.target.find(".output_interface").removeClass("invisible");
|
||||
|
73
gradio/static/js/all_io.js.bak
Normal file
73
gradio/static/js/all_io.js.bak
Normal file
@ -0,0 +1,73 @@
|
||||
var io_master_template = {
|
||||
gather: function() {
|
||||
this.clear();
|
||||
for (let iface of this.input_interfaces) {
|
||||
iface.submit();
|
||||
}
|
||||
},
|
||||
clear: function() {
|
||||
this.last_input = new Array(this.input_interfaces.length);
|
||||
this.input_count = 0;
|
||||
},
|
||||
input: function(interface_id, data) {
|
||||
this.last_input[interface_id] = data;
|
||||
this.input_count += 1;
|
||||
if (this.input_count == this.input_interfaces.length) {
|
||||
this.submit();
|
||||
}
|
||||
},
|
||||
submit: function() {
|
||||
let io = this;
|
||||
if (!this.config.live) {
|
||||
this.target.find(".loading").removeClass("invisible");
|
||||
this.target.find(".loading_in_progress").show();
|
||||
this.target.find(".loading_failed").hide();
|
||||
this.target.find(".output_interface").addClass("invisible");
|
||||
this.target.find(".output_interfaces .panel_header").addClass("invisible");
|
||||
}
|
||||
this.fn(this.last_input).then((output) => {
|
||||
io.output(output);
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
this.target.find(".loading_in_progress").hide();
|
||||
this.target.find(".loading_failed").show();
|
||||
})
|
||||
},
|
||||
output: function(data) {
|
||||
this.last_output = data["data"];
|
||||
|
||||
for (let i = 0; i < this.output_interfaces.length; i++) {
|
||||
this.output_interfaces[i].output(data["data"][i]);
|
||||
}
|
||||
if (data["durations"]) {
|
||||
let 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 {
|
||||
this.target.find(".loading").addClass("invisible");
|
||||
this.target.find(".output_interface").removeClass("invisible");
|
||||
this.target.find(".output_interfaces .panel_header").removeClass("invisible");
|
||||
}
|
||||
},
|
||||
flag: function(message) {
|
||||
var post_data = {
|
||||
'data': {
|
||||
'input_data' : toStringIfObject(this.last_input) ,
|
||||
'output_data' : toStringIfObject(this.last_output),
|
||||
'message' : message
|
||||
}
|
||||
}
|
||||
$.ajax({type: "POST",
|
||||
url: "/api/flag/",
|
||||
data: JSON.stringify(post_data),
|
||||
success: function(output){
|
||||
console.log("Flagging successful")
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
@ -1,13 +1,7 @@
|
||||
const textbox_output = {
|
||||
html: `<textarea readonly class="output_text"></textarea>`,
|
||||
html: `<div class="output_text"></div>`,
|
||||
init: function(opts) {
|
||||
if (opts.lines) {
|
||||
this.target.find(".output_text").attr("rows", opts.lines).css("height", "auto");
|
||||
this.target.css("height", "auto");
|
||||
}
|
||||
if (opts.placeholder) {
|
||||
this.target.find(".output_text").attr("placeholder", opts.placeholder)
|
||||
}
|
||||
},
|
||||
output: function(data) {
|
||||
this.target.find(".output_text").text(data);
|
||||
|
@ -31,7 +31,7 @@
|
||||
<a href="https://gradio.app"><img src="../static/img/logo_inline.png" /></a>
|
||||
</nav>
|
||||
<div id="share" class="invisible">
|
||||
Live at <a id="share-link"></a>.
|
||||
Live at <a id="share-link" target="_blank"></a>.
|
||||
<button id="share-copy">Copy Link</button>
|
||||
</div>
|
||||
<div class="container">
|
||||
@ -40,7 +40,7 @@
|
||||
</div>
|
||||
<div id="interface_target" class="container"></div>
|
||||
<div id="examples" class="container invisible">
|
||||
<h3>Examples</h3>
|
||||
<h3>Examples <small>(click to load)</small></h3>
|
||||
<table>
|
||||
</table>
|
||||
</div>
|
||||
|
3
setup.py
3
setup.py
@ -5,7 +5,7 @@ except ImportError:
|
||||
|
||||
setup(
|
||||
name='gradio',
|
||||
version='0.9.8',
|
||||
version='0.9.9.3',
|
||||
include_package_data=True,
|
||||
description='Python library for easily interacting with trained machine learning models',
|
||||
author='Abubakar Abid',
|
||||
@ -20,5 +20,6 @@ setup(
|
||||
'scipy',
|
||||
'IPython',
|
||||
'scikit-image',
|
||||
'analytics-python',
|
||||
],
|
||||
)
|
||||
|
@ -7,13 +7,13 @@ 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='TexT', fn=lambda x: x)
|
||||
self.assertIsInstance(io.input_interfaces[0], gradio.inputs.Sketchpad)
|
||||
self.assertIsInstance(io.output_interfaces[0], gradio.outputs.Textbox)
|
||||
|
||||
def test_input_interface_is_instance(self):
|
||||
inp = gradio.inputs.Image()
|
||||
io = gr.Interface(inputs=inp, outputs='textBOX', fn=lambda x: x)
|
||||
io = gr.Interface(inputs=inp, outputs='teXT', fn=lambda x: x)
|
||||
self.assertEqual(io.input_interfaces[0], inp)
|
||||
|
||||
def test_output_interface_is_instance(self):
|
||||
@ -24,7 +24,7 @@ class TestInterface(unittest.TestCase):
|
||||
def test_prediction(self):
|
||||
def model(x):
|
||||
return 2*x
|
||||
io = gr.Interface(inputs='textbox', outputs='textBOX', fn=model)
|
||||
io = gr.Interface(inputs='textbox', outputs='TEXT', fn=model)
|
||||
self.assertEqual(io.predict[0](11), 22)
|
||||
|
||||
|
||||
|
0
upload_to_pypi.sh
Normal file → Executable file
0
upload_to_pypi.sh
Normal file → Executable file
Loading…
Reference in New Issue
Block a user