This commit is contained in:
dawoodkhan82 2021-06-14 16:30:38 -04:00
commit bc69139099
19 changed files with 341 additions and 90 deletions

View File

@ -11,7 +11,7 @@ def sentiment_analysis(text):
del scores["compound"]
return scores
iface = gr.Interface(sentiment_analysis, "textbox", "label", allow_screenshot=False, allow_flagging=False)
iface = gr.Interface(sentiment_analysis, "textbox", "label", interpretation="default")
iface.test_launch()
if __name__ == "__main__":

View File

@ -85,7 +85,6 @@ iface = gr.Interface(
["third", True, 30, ["Child"], 20, "S"],
],
interpretation="default",
live=True
)
if __name__ == "__main__":

View File

@ -65,6 +65,8 @@ export class GradioInterface extends React.Component {
this.clear = this.clear.bind(this);
this.submit = this.submit.bind(this);
this.flag = this.flag.bind(this);
this.interpret = this.interpret.bind(this);
this.removeInterpret = this.removeInterpret.bind(this);
this.handleExampleChange = this.handleExampleChange.bind(this);
this.state = this.get_default_state();
this.state["examples_page"] = 0;
@ -82,6 +84,7 @@ export class GradioInterface extends React.Component {
state["submitting"] = false;
state["error"] = false;
state["complete"] = false;
state["interpretation"] = null;
state["just_flagged"] = false;
state["has_changed"] = false;
state["example_id"] = null;
@ -99,13 +102,13 @@ export class GradioInterface extends React.Component {
input_state[i] = this.state[i];
}
this.setState({ "submitting": true, "has_changed": false, "error": false });
this.props.fn(input_state, "predict").then((output) => {
this.props.fn(input_state, "predict").then(output => {
let index_start = this.props.input_components.length;
for (let [i, value] of output["data"].entries()) {
this.setState({ [index_start + i]: value });
}
this.setState({ "submitting": false, "complete": true });
if (this.state.has_changed) {
if (this.props.live && this.state.has_changed) {
this.submit();
}
}).catch(e => {
@ -133,6 +136,31 @@ export class GradioInterface extends React.Component {
}, 1000)
this.props.fn(component_state, "flag");
}
interpret() {
if (!this.state.complete) {
return;
}
let input_state = [];
for (let i = 0; i < this.props.input_components.length; i++) {
if (this.state[i] === null) {
return;
}
input_state[i] = this.state[i];
}
this.setState({ "submitting": true, "has_changed": false, "error": false });
this.props.fn(input_state, "interpret").then(output => {
this.setState({ "interpretation": output["interpretation_scores"], "submitting": false })
}).catch(e => {
console.error(e);
this.setState({
"error": true,
"submitting": false
});
});
}
removeInterpret() {
this.setState({ "interpretation": null });
}
handleChange(_id, value) {
let state_change = { [_id]: value, "has_changed": true };
if (this.props.live && !(this.state.submitting)) {
@ -176,7 +204,7 @@ export class GradioInterface extends React.Component {
return (
<div className="component" key={index}>
<div className="panel_header">{component.label}</div>
<Component {...component} handleChange={this.handleChange.bind(this, index)} value={this.state[index]} />
<Component {...component} handleChange={this.handleChange.bind(this, index)} value={this.state[index]} interpretation={this.state["interpretation"] === null ? null : this.state["interpretation"][index]} />
</div>);
})}
</div>
@ -203,21 +231,13 @@ export class GradioInterface extends React.Component {
</div>
<div className="panel_buttons">
{this.props.allow_interpretation ?
<button className="panel_button">Interpret</button> : false
(this.state.interpretation === null ?
<button className={classNames("panel_button", { "disabled": this.state.complete === false })} onClick={this.interpret}>Interpret</button> :
<button className="panel_button" onClick={this.removeInterpret}>Hide</button>)
: false
}
{this.props.allow_screenshot ?
<div className="screenshot_set">
<button className="panel_button left_panel_button">Screenshot</button>
<button className="panel_button right_panel_button">GIF</button>
{this.state.screenshot_mode ?
<div className="screenshot_logo">
<img src="/static/img/logo_inline.png" alt="Gradio" />
<button className='record_stop'>
<div className='record_square'></div>
</button>
</div>
: false}
</div>
<button className="panel_button hidden">Screenshot</button>
: false}
{this.props.allow_flagging ?
<button className={classNames("panel_button", { "disabled": this.state.complete === false })}

View File

@ -1,6 +1,7 @@
import React from 'react';
import { DataURLComponentExample } from '../component_example';
import AudioReactRecorder, { RecordState } from 'audio-react-recorder'
import { getSaliencyColor } from '../utils';
class AudioInput extends React.Component {
constructor(props) {
@ -46,6 +47,13 @@ class AudioInput extends React.Component {
<audio controls key={this.key}>
<source src={this.props.value}></source>
</audio>
{this.props.interpretation === null ? false :
<div class="interpret_range">
{this.props.interpretation.map(value =>
<div style={{ 'background-color': getSaliencyColor(value) }}>
</div>
)}
</div>}
</div>);
} else {
if (this.props.source === "microphone") {
@ -59,7 +67,7 @@ class AudioInput extends React.Component {
} else if (this.props.source === "upload") {
let no_action = (evt) => {
evt.preventDefault();
evt.stopPropagation();
evt.stopPropagation();
}
return (
<div className="input_image" onDrag={no_action} onDragStart={no_action} onDragEnd={no_action} onDragOver={no_action} onDragEnter={no_action} onDragLeave={no_action} onDrop={no_action} >

View File

@ -1,6 +1,7 @@
import React from 'react';
import ComponentExample from '../component_example';
import classNames from "classnames";
import { getSaliencyColor } from '../utils';
class CheckboxInput extends React.Component {
constructor(props) {
@ -15,12 +16,23 @@ class CheckboxInput extends React.Component {
<div className={classNames("checkbox_item", {
"selected": this.props.value
})} onClick={this.handleChange}>
<div className="checkbox">
<svg className="check" viewBox="-10 -10 20 20">
<line x1="-7.5" y1="0" x2="-2.5" y2="5"></line>
<line x1="-2.5" y1="5" x2="7.5" y2="-7.5"></line>
</svg>
</div>
{this.props.interpretation === null ?
<div className="checkbox">
<svg className="check" viewBox="-10 -10 20 20">
<line x1="-7.5" y1="0" x2="-2.5" y2="5"></line>
<line x1="-2.5" y1="5" x2="7.5" y2="-7.5"></line>
</svg>
</div>
:
<div class="interpretation">
<div class="interpretation_box" style={{ "backgroundColor": getSaliencyColor(this.props.interpretation[0]) }}></div>
<div class="interpretation_box" style={{ "backgroundColor": getSaliencyColor(this.props.interpretation[1]) }}>
<svg className="interpret_check" viewBox="-10 -10 20 20">
<line x1="-7.5" y1="0" x2="-2.5" y2="5"></line>
<line x1="-2.5" y1="5" x2="7.5" y2="-7.5"></line>
</svg>
</div>
</div>}
</div>
</div>)
}
@ -32,4 +44,4 @@ class CheckboxInputExample extends ComponentExample {
}
}
export {CheckboxInput, CheckboxInputExample};
export { CheckboxInput, CheckboxInputExample };

View File

@ -1,6 +1,7 @@
import React from 'react';
import ComponentExample from '../component_example';
import classNames from "classnames";
import { getSaliencyColor } from '../utils';
class CheckboxGroupInput extends React.Component {
constructor(props) {
@ -17,21 +18,32 @@ class CheckboxGroupInput extends React.Component {
this.props.handleChange(all_selected);
}
render() {
return (<div className="input_checkbox_group">
{this.props.choices.map((item, index) => {
return <div className={classNames("checkbox_item", {
"selected": this.props.value.includes(item)
})} onClick={this.handleChange.bind(this, item)} key={index}>
return (<div className="input_checkbox_group">
{this.props.choices.map((item, index) => {
return <div className={classNames("checkbox_item", {
"selected": this.props.value.includes(item)
})} onClick={this.handleChange.bind(this, item)} key={index}>
{this.props.interpretation === null ?
<div className="checkbox">
<svg className="check" viewBox="-10 -10 20 20">
<line x1="-7.5" y1="0" x2="-2.5" y2="5"></line>
<line x1="-2.5" y1="5" x2="7.5" y2="-7.5"></line>
</svg>
</div>
{item}
</div>
})}
</div>)
:
<div class="interpretation">
<div class="interpretation_box" style={{ "backgroundColor": getSaliencyColor(this.props.interpretation[index][0]) }}></div>
<div class="interpretation_box" style={{ "backgroundColor": getSaliencyColor(this.props.interpretation[index][1]) }}>
<svg className="interpret_check" viewBox="-10 -10 20 20">
<line x1="-7.5" y1="0" x2="-2.5" y2="5"></line>
<line x1="-2.5" y1="5" x2="7.5" y2="-7.5"></line>
</svg>
</div>
</div>}
{item}
</div>
})}
</div>)
}
}
@ -41,4 +53,4 @@ class CheckboxGroupInputExample extends ComponentExample {
}
}
export {CheckboxGroupInput, CheckboxGroupInputExample};
export { CheckboxGroupInput, CheckboxGroupInputExample };

View File

@ -1,6 +1,7 @@
import React from 'react';
import ComponentExample from '../component_example';
import classNames from "classnames";
import { getSaliencyColor } from '../utils';
class DropdownInput extends React.Component {
constructor(props) {
@ -12,21 +13,28 @@ class DropdownInput extends React.Component {
}
render() {
return (<div className="input_dropdown">
<div className="dropdown inline-block relative">
<button className="selector ">
<span className="current">{this.props.value}</span>
<svg className="caret" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /> </svg>
</button>
<ul className="dropdown_menu">
{this.props.choices.map((item, index) => {
return <li className={classNames("dropdown_item", {
"selected": item === this.props.value
})} onClick={this.handleChange.bind(this, item)} key={index}>
{item}
</li>
})}
</ul>
</div>
{this.props.interpretation === null ?
<div className="dropdown inline-block relative">
<button className="selector ">
<span className="current">{this.props.value}</span>
<svg className="caret" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" /> </svg>
</button>
<ul className="dropdown_menu">
{this.props.choices.map((item, index) => {
return <li className={classNames("dropdown_item", {
"selected": item === this.props.value
})} onClick={this.handleChange.bind(this, item)} key={index}>
{item}
</li>
})}
</ul>
</div>
:
<div class="interpretation">
{this.props.interpretation.map((value, index) =>
<div class="interpretation_box" key={index} style={{ "backgroundColor": getSaliencyColor(value) }}>{this.props.choices[index]}</div>
)}
</div>}
</div>)
}
}
@ -37,4 +45,4 @@ class DropdownInputExample extends ComponentExample {
}
}
export {DropdownInput, DropdownInputExample};
export { DropdownInput, DropdownInputExample };

View File

@ -2,6 +2,7 @@ import React from 'react';
import { DataURLComponentExample } from '../component_example';
import Webcam from "react-webcam";
import { SketchField, Tools } from '../../vendor/ReactSketch';
import { getObjectFitSize, paintSaliency } from '../utils';
class ImageInput extends React.Component {
constructor(props) {
@ -9,11 +10,13 @@ class ImageInput extends React.Component {
this.handleChange = this.handleChange.bind(this);
this.uploader = React.createRef();
this.openFileUpload = this.openFileUpload.bind(this);
this.onImgLoad = this.onImgLoad.bind(this);
this.load_preview_from_files = this.load_preview_from_files.bind(this);
this.load_preview_from_upload = this.load_preview_from_upload.bind(this);
this.load_preview_from_drop = this.load_preview_from_drop.bind(this);
this.snapshot = this.snapshot.bind(this);
this.getSketch = this.getSketch.bind(this);
this.imgRef = React.createRef();
this.webcamRef = React.createRef();
this.sketchRef = React.createRef();
this.sketchKey = 0;
@ -32,17 +35,39 @@ class ImageInput extends React.Component {
let imageSrc = this.sketchRef.current.toDataURL();
this.handleChange(imageSrc);
}
onImgLoad({target:img}) {
this.setState({dimensions:{height:img.offsetHeight,
width:img.offsetWidth}});
}
render() {
let no_action = (evt) => {
evt.preventDefault();
evt.stopPropagation();
}
if (this.props.value !== null && this.props.source !== "canvas") {
let interpretation = false;
if (this.props.interpretation !== null) {
let img = this.imgRef.current;
let size = getObjectFitSize(true, img.width, img.height, img.naturalWidth, img.naturalHeight);
if (this.props.shape) {
size = getObjectFitSize(true, size.width, size.height, this.props.shape[0], this.props.shape[1])
}
let width = size.width;
let height = size.height;
let canvas = document.createElement("canvas")
canvas.setAttribute("height", height);
canvas.setAttribute("width", width);
paintSaliency(this.props.interpretation, canvas.getContext("2d"), width, height);
interpretation = (<div class="interpretation">
<img src={canvas.toDataURL()}></img>
</div>)
}
return (
<div className="input_image">
<div className="image_preview_holder">
<img className="image_preview" alt="" src={this.props.value} />
<img ref={this.imgRef} onLoad={this.onImgLoad} className="image_preview" alt="" src={this.props.value} />
</div>
{interpretation}
</div>)
} else {
if (this.props.source === "upload") {

View File

@ -1,5 +1,6 @@
import React from 'react';
import ComponentExample from '../component_example';
import { getSaliencyColor } from '../utils';
class NumberInput extends React.Component {
constructor(props) {
@ -14,7 +15,16 @@ class NumberInput extends React.Component {
}
}
render() {
return <input type="text" className="input_number" onChange={this.handleChange} value={this.props.value === null ? "" : this.props.value}></input>
return <div className="input_number">
{this.props.interpretation === null ?
<input type="text" onChange={this.handleChange} value={this.props.value === null ? "" : this.props.value}></input>
:
<div class="interpretation">
{this.props.interpretation.map((value, index) =>
<div class="interpretation_box" key={index} style={{ "backgroundColor": getSaliencyColor(value[1]) }}>{value[0]}</div>
)}
</div>}
</div>
}
}
@ -25,4 +35,4 @@ class NumberInputExample extends ComponentExample {
}
}
export {NumberInput, NumberInputExample};
export { NumberInput, NumberInputExample };

View File

@ -1,6 +1,7 @@
import React from 'react';
import ComponentExample from '../component_example';
import classNames from "classnames";
import { getSaliencyColor } from '../utils';
class RadioInput extends React.Component {
constructor(props) {
@ -11,16 +12,21 @@ class RadioInput extends React.Component {
this.props.handleChange(selected_item);
}
render() {
return (<div className="input_radio">
{this.props.choices.map((item, index) => {
return <div className={classNames("radio_item", {
return (<div className="input_radio">
{this.props.choices.map((item, index) => {
return <div key={index}>
<div className={classNames("radio_item", {
"selected": item === this.props.value
})} onClick={this.handleChange.bind(this, item)} key={index}>
<div className="radio_circle"></div>
})} onClick={this.handleChange.bind(this, item)}>
{this.props.interpretation === null ?
<div className="radio_circle"></div> :
<div className="radio_circle" style={{"backgroundColor": getSaliencyColor(this.props.interpretation[index])}}></div>
}
{item}
</div>
})}
</div>)
</div>
})}
</div>)
}
}
@ -30,4 +36,4 @@ class RadioInputExample extends ComponentExample {
}
}
export {RadioInput, RadioInputExample};
export { RadioInput, RadioInputExample };

View File

@ -1,5 +1,6 @@
import React from 'react';
import ComponentExample from '../component_example';
import { getSaliencyColor } from '../utils';
class SliderInput extends React.Component {
constructor(props) {
@ -10,10 +11,20 @@ class SliderInput extends React.Component {
this.props.handleChange(parseFloat(evt.target.value));
}
render() {
return (<div className="input_slider">
<input type="range" className="range" onChange={this.handleChange} value={this.props.value} min={this.props.minimum} max={this.props.maximum} step={this.props.step}></input>
<div className="value">{this.props.value}</div>
</div>)
return (<div className="input_slider">
{this.props.interpretation === null ?
<>
<input type="range" className="range" onChange={this.handleChange} value={this.props.value} min={this.props.minimum} max={this.props.maximum} step={this.props.step}></input>
<div className="value">{this.props.value}</div>
</>
:
<div class="interpret_range">
{this.props.interpretation.map(value =>
<div style={{ 'background-color': getSaliencyColor(value) }}>
</div>
)}
</div>}
</div>)
}
}
@ -23,4 +34,4 @@ class SliderInputExample extends ComponentExample {
}
}
export {SliderInput, SliderInputExample};
export { SliderInput, SliderInputExample };

View File

@ -1,5 +1,6 @@
import React from 'react';
import ComponentExample from '../component_example';
import { getSaliencyColor } from '../utils';
class TextboxInput extends React.Component {
constructor(props) {
@ -10,15 +11,25 @@ class TextboxInput extends React.Component {
this.props.handleChange(evt.target.value);
}
render() {
if (this.props.lines > 1) {
if (this.props.interpretation !== null) {
return (
<div>
<textarea className="input_text" value={this.props.value || ""} onChange={this.handleChange}>
<div className="input_text">
<div class="interpretation">
{this.props.interpretation.map((item, index) => <div class="interpretation_box" key={index} style={{ "backgroundColor": getSaliencyColor(item[1]) }}>{item[0]}</div>)}
</div>
</div>
)
} else if (this.props.lines > 1) {
return (
<div className="input_text">
<textarea value={this.props.value || ""} onChange={this.handleChange}>
</textarea>
</div>
)
} else {
return <input type="text" className="input_text" onChange={this.handleChange} value={this.props.value || ""}></input>
return (<div className="input_text">
<input type="text" onChange={this.handleChange} value={this.props.value || ""}></input>
</div>)
}
}
}
@ -29,4 +40,4 @@ class TextboxInputExample extends ComponentExample {
}
}
export {TextboxInput, TextboxInputExample};
export { TextboxInput, TextboxInputExample };

View File

@ -7,4 +7,69 @@ export function prettyBytes(bytes) {
}
let unit = units[i];
return bytes.toFixed(1) + " " + unit;
}
}
export function getSaliencyColor(value) {
if (value < 0) {
var color = [52, 152, 219];
} else {
var color = [231, 76, 60];
}
return colorToString(interpolate(Math.abs(value), [255, 255, 255], color));
}
function interpolate(val, rgb1, rgb2) {
if (val > 1) {
val = 1;
}
val = Math.sqrt(val);
var rgb = [0, 0, 0];
var i;
for (i = 0; i < 3; i++) {
rgb[i] = Math.round(rgb1[i] * (1.0 - val) + rgb2[i] * val);
}
return rgb;
}
function colorToString(rgb) {
return "rgb(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ")";
}
export function getObjectFitSize(contains /* true = contain, false = cover */, containerWidth, containerHeight, width, height) {
var doRatio = width / height;
var cRatio = containerWidth / containerHeight;
var targetWidth = 0;
var targetHeight = 0;
var test = contains ? (doRatio > cRatio) : (doRatio < cRatio);
if (test) {
targetWidth = containerWidth;
targetHeight = targetWidth / doRatio;
} else {
targetHeight = containerHeight;
targetWidth = targetHeight * doRatio;
}
return {
width: targetWidth,
height: targetHeight,
x: (containerWidth - targetWidth) / 2,
y: (containerHeight - targetHeight) / 2
};
}
export function paintSaliency(data, ctx, width, height) {
var cell_width = width / data[0].length
var cell_height = height / data.length
var r = 0
data.forEach(function(row) {
var c = 0
row.forEach(function(cell) {
ctx.fillStyle = getSaliencyColor(cell);
ctx.fillRect(c * cell_width, r * cell_height, cell_width, cell_height);
c++;
})
r++;
})
}

View File

@ -35,7 +35,7 @@
@apply mb-1 uppercase text-sm font-semibold;
}
.panel_button {
@apply flex-grow p-3 rounded bg-gray-50 hover:bg-gray-100 transition font-semibold focus:outline-none;
@apply flex-1 p-3 rounded bg-gray-50 hover:bg-gray-100 transition font-semibold focus:outline-none;
}
.panel_button.disabled {
@apply text-gray-400 cursor-not-allowed;
@ -92,17 +92,32 @@
}
}
/* Input Components */
textarea.input_text {
@apply w-full bg-white border-gray-400 rounded box-border p-1 resize-none;
}
input.input_text {
@apply w-full bg-white border-gray-400 rounded box-border p-1;
}
.input_text {
textarea {
@apply w-full bg-white border-gray-400 rounded box-border p-1 resize-none;
}
input {
@apply w-full bg-white border-gray-400 rounded box-border p-1;
}
.interpretation {
.interpretation_box {
@apply inline-block whitespace-pre-wrap;
}
}
}
.input_number {
@apply w-full bg-white border-gray-400 rounded box-border p-1;
input {
@apply w-full bg-white border-gray-400 rounded box-border p-1;
}
.interpretation {
@apply flex h-6;
.interpretation_box {
@apply flex-grow;
}
}
}
.input_image {
@apply w-full h-80;
@apply w-full h-80 relative;
.upload_zone {
@apply border-8 border-gray-300 border-dashed w-full h-full flex justify-center items-center text-3xl text-gray-400 text-center cursor-pointer leading-10;
}
@ -119,6 +134,9 @@
.snapshot {
@apply absolute bottom-0 w-full bg-white bg-opacity-90 py-3 font-bold text-lg text-center;
}
.interpretation {
@apply w-full h-full absolute top-0 left-0 flex justify-center items-center opacity-90 hover:opacity-20 transition;
}
}
.input_image_example {
@apply h-24;
@ -163,6 +181,20 @@
stroke-width: 4;
stroke-linecap: round;
}
.interpretation {
@apply flex;
.interpretation_box {
@apply flex-grow h-4 w-4;
}
.interpret_check {
@apply w-full h-full;
}
.interpret_check line {
stroke: gray;
stroke-width: 4;
stroke-linecap: round;
}
}
}
.input_checkbox {
@apply flex flex-wrap gap-2;
@ -189,6 +221,20 @@
stroke-width: 4;
stroke-linecap: round;
}
.interpretation {
@apply flex;
.interpretation_box {
@apply flex-grow h-4 w-4;
}
.interpret_check {
@apply w-full h-full;
}
.interpret_check line {
stroke: gray;
stroke-width: 4;
stroke-linecap: round;
}
}
}
.input_dropdown {
@apply inline-block relative;
@ -216,6 +262,9 @@
:hover .dropdown_menu {
@apply block;
}
.interpretation_box {
@apply p-1;
}
}
.input_slider {
@apply text-center;
@ -232,6 +281,12 @@
.value {
@apply inline-block mx-auto mt-1 px-2 py-0.5 bg-gray-200 rounded text-gray-700;
}
.interpret_range {
@apply flex h-6;
div {
@apply flex-grow;
}
}
}
.input_audio {
.audio-react-recorder {
@ -246,6 +301,12 @@
audio {
@apply w-full border-2 border-gray-300 rounded;
}
.interpret_range {
@apply flex h-4;
div {
@apply flex-grow h-full;
}
}
}
.input_video {
@apply w-full h-80;

View File

@ -86,13 +86,13 @@
}
}
/* Input Components */
textarea.input_text {
.input_text textarea {
@apply w-full p-3 border rounded-lg shadow-inner outline-none focus:ring-1 focus:ring-inset focus:ring-indigo-200 focus:shadow-inner placeholder-gray-400;
}
input.input_text {
.input_text input {
@apply w-full p-3 border rounded-lg shadow-inner outline-none focus:ring-1 focus:ring-inset focus:ring-indigo-200 focus:shadow-inner placeholder-gray-400;
}
.input_number {
.input_number input {
@apply w-full p-3 border rounded-lg shadow-inner outline-none focus:ring-1 focus:ring-inset focus:ring-indigo-200 focus:shadow-inner placeholder-gray-400;
}
.input_image {

View File

@ -33,6 +33,8 @@ gradio/frontend/static/bundle.js.LICENSE.txt
gradio/frontend/static/bundle.js.map
gradio/frontend/static/css/main.20be28ac.css
gradio/frontend/static/css/main.20be28ac.css.map
gradio/frontend/static/css/main.2b64a968.css
gradio/frontend/static/css/main.2b64a968.css.map
gradio/frontend/static/css/main.380e3222.css
gradio/frontend/static/css/main.380e3222.css.map
gradio/frontend/static/css/main.4aea80f8.css

View File

@ -1,17 +1,17 @@
{
"files": {
"main.css": "/static/css/main.4aea80f8.css",
"main.css": "/static/css/main.2b64a968.css",
"main.js": "/static/bundle.js",
"main.js.map": "/static/bundle.js.map",
"index.html": "/index.html",
"static/bundle.css.map": "/static/bundle.css.map",
"static/bundle.js.LICENSE.txt": "/static/bundle.js.LICENSE.txt",
"static/css/main.4aea80f8.css.map": "/static/css/main.4aea80f8.css.map",
"static/css/main.2b64a968.css.map": "/static/css/main.2b64a968.css.map",
"static/media/logo_loading.e93acd82.jpg": "/static/media/logo_loading.e93acd82.jpg"
},
"entrypoints": [
"static/bundle.css",
"static/css/main.4aea80f8.css",
"static/css/main.2b64a968.css",
"static/bundle.js"
]
}

View File

@ -8,4 +8,4 @@
window.config = {{ config|tojson }};
} catch (e) {
window.config = {};
}</script><title>Gradio</title><link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet"><link href="static/bundle.css" rel="stylesheet"><link href="static/css/main.4aea80f8.css" rel="stylesheet"></head><body><div id="root"></div><script src="static/bundle.js"></script></body></html>
}</script><title>Gradio</title><link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet"><link href="static/bundle.css" rel="stylesheet"><link href="static/css/main.2b64a968.css" rel="stylesheet"></head><body><div id="root"></div><script src="static/bundle.js"></script></body></html>

View File

@ -258,6 +258,7 @@ class Number(InputComponent):
return self
def get_interpretation_neighbors(self, x):
x = float(x)
neighbors = []
if self.interpretation_delta_type == "percent":
delta = 1.0 * self.interpretation_delta * x / 100