This commit is contained in:
Ali Abid 2020-07-08 11:17:07 -07:00
parent db2b65764d
commit 1e752997e3
13 changed files with 108 additions and 93 deletions

View File

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

View File

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

View File

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

View File

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

View 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")
},
});
}
};

View File

@ -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)
}
this.target.css("height", "auto");
},
output: function(data) {
this.target.find(".output_text").text(data);

BIN
dist/gradio-0.9.9.1-py3.7.egg vendored Normal file

Binary file not shown.

View File

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

View File

@ -4,4 +4,3 @@ paramiko
scipy
IPython
scikit-image
analytics

View File

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

View File

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

View File

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

View File

@ -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)
}
this.target.css("height", "auto");
},
output: function(data) {
this.target.find(".output_text").text(data);