mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-06 12:30:29 +08:00
added requirements to push package
This commit is contained in:
parent
0c2c45c50b
commit
c22fdbb36a
193
.idea/workspace.xml
generated
193
.idea/workspace.xml
generated
@ -2,15 +2,12 @@
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="fd73cd66-e80f-470e-a2ec-e220d3b6b864" name="Default Changelist" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/Emotional Detector.ipynb" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Test Notebook.ipynb" beforeDir="false" afterPath="$PROJECT_DIR$/Test Notebook.ipynb" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/css/draw-a-digit.css" beforeDir="false" afterPath="$PROJECT_DIR$/css/draw-a-digit.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/inputs.py" beforeDir="false" afterPath="$PROJECT_DIR$/inputs.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/js/dropzone.js" beforeDir="false" afterPath="$PROJECT_DIR$/js/dropzone.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/js/image-upload-input.js" beforeDir="false" afterPath="$PROJECT_DIR$/js/image-upload-input.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/preprocessing_utils.py" beforeDir="false" afterPath="$PROJECT_DIR$/preprocessing_utils.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/templates/image_upload_input.html" beforeDir="false" afterPath="$PROJECT_DIR$/templates/image_upload_input.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/templates/tmp_html.html" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/gradio.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/inputs.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/networking.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/outputs.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/preprocessing_utils.py" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/script.py" beforeDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
@ -83,7 +80,7 @@
|
||||
<entry key="html" value="4" />
|
||||
<entry key="ipynb" value="1" />
|
||||
<entry key="js" value="5" />
|
||||
<entry key="py" value="11" />
|
||||
<entry key="py" value="18" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.types.open">
|
||||
@ -93,17 +90,17 @@
|
||||
<entry key="IPNB" value="1" />
|
||||
<entry key="JavaScript" value="5" />
|
||||
<entry key="PLAIN_TEXT" value="1" />
|
||||
<entry key="Python" value="11" />
|
||||
<entry key="Python" value="18" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.extensions.edit">
|
||||
<counts>
|
||||
<entry key="css" value="11" />
|
||||
<entry key="dummy" value="10" />
|
||||
<entry key="dummy" value="19" />
|
||||
<entry key="gitignore" value="2" />
|
||||
<entry key="html" value="112" />
|
||||
<entry key="js" value="272" />
|
||||
<entry key="py" value="4059" />
|
||||
<entry key="py" value="4194" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.types.edit">
|
||||
@ -111,54 +108,66 @@
|
||||
<entry key="CSS" value="11" />
|
||||
<entry key="HTML" value="112" />
|
||||
<entry key="JavaScript" value="272" />
|
||||
<entry key="PLAIN_TEXT" value="12" />
|
||||
<entry key="Python" value="4059" />
|
||||
<entry key="PLAIN_TEXT" value="21" />
|
||||
<entry key="Python" value="4194" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
</session>
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/css/draw-a-digit.css">
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/setup.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1225">
|
||||
<caret line="96" column="15" selection-start-line="96" selection-start-column="15" selection-end-line="96" selection-end-column="15" />
|
||||
<state relative-caret-position="525">
|
||||
<caret line="21" column="17" selection-start-line="21" selection-start-column="17" selection-end-line="21" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/.gitignore">
|
||||
<entry file="file://$PROJECT_DIR$/gradio/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="175">
|
||||
<caret line="7" selection-start-line="7" selection-end-line="7" />
|
||||
<caret line="7" column="19" selection-start-line="7" selection-start-column="19" selection-end-line="7" selection-end-column="19" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/preprocessing_utils.py">
|
||||
<entry file="file://$PROJECT_DIR$/gradio/inputs.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="336">
|
||||
<caret line="16" column="31" selection-start-line="16" selection-start-column="31" selection-end-line="16" selection-end-column="31" />
|
||||
<state relative-caret-position="125">
|
||||
<caret line="5" column="19" selection-start-line="5" selection-start-column="19" selection-end-line="5" selection-end-column="19" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/gradio.py">
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/gradio/networking.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="647">
|
||||
<caret line="130" column="13" selection-start-line="130" selection-start-column="13" selection-end-line="130" selection-end-column="13" />
|
||||
<state relative-caret-position="150">
|
||||
<caret line="6" column="11" selection-start-line="6" selection-start-column="5" selection-end-line="6" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/gradio/outputs.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<folding>
|
||||
<element signature="e#0#14#0" expanded="true" />
|
||||
<marker date="1550563754843" expanded="true" signature="1905:2502" ph="..." />
|
||||
<element signature="e#0#35#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/gradio/preprocessing_utils.py">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/js/all-io.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
@ -168,41 +177,6 @@
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/networking.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="486">
|
||||
<caret line="39" selection-start-line="32" selection-end-line="39" />
|
||||
<folding>
|
||||
<element signature="e#0#17#0" expanded="true" />
|
||||
<marker date="1550562739002" expanded="true" signature="754:937" ph="..." />
|
||||
<marker date="1550562739002" expanded="true" signature="2659:2661" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/inputs.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="50">
|
||||
<caret line="2" column="21" selection-start-line="2" selection-start-column="21" selection-end-line="2" selection-end-column="21" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/outputs.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1350">
|
||||
<caret line="60" selection-start-line="60" selection-end-line="60" />
|
||||
<folding>
|
||||
<element signature="e#0#35#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/templates/webcam_input.html">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
@ -223,9 +197,6 @@
|
||||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>clear</find>
|
||||
<find>ctx</find>
|
||||
<find>clear-b</find>
|
||||
<find>css/</find>
|
||||
<find>communica</find>
|
||||
<find>communicate</find>
|
||||
@ -253,6 +224,9 @@
|
||||
<find>6002</find>
|
||||
<find>INITIAL_WEBSOCKET_PORT</find>
|
||||
<find>print(</find>
|
||||
<find>inputs.</find>
|
||||
<find>subprocess</find>
|
||||
<find>psutil</find>
|
||||
</findStrings>
|
||||
<replaceStrings>
|
||||
<replace>400</replace>
|
||||
@ -296,6 +270,9 @@
|
||||
<option value="$PROJECT_DIR$/networking.py" />
|
||||
<option value="$PROJECT_DIR$/js/all-io.js" />
|
||||
<option value="$PROJECT_DIR$/gradio.py" />
|
||||
<option value="$PROJECT_DIR$/gradio/__init__.py" />
|
||||
<option value="$PROJECT_DIR$/gradio/inputs.py" />
|
||||
<option value="$PROJECT_DIR$/setup.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
@ -335,7 +312,7 @@
|
||||
<path>
|
||||
<item name="gradio" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="gradio" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="js" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="gradio" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="gradio" type="b2602c69:ProjectViewProjectNode" />
|
||||
@ -388,7 +365,7 @@
|
||||
<frame x="-6" y="-6" width="1513" height="1013" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.25360826" />
|
||||
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.25360826" />
|
||||
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||
<window_info id="Favorites" order="2" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Message" order="0" />
|
||||
@ -519,13 +496,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.gitignore">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="175">
|
||||
<caret line="7" selection-start-line="7" selection-end-line="7" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/js/webcam-input.js">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="300">
|
||||
@ -533,13 +503,6 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/css/draw-a-digit.css">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1225">
|
||||
<caret line="96" column="15" selection-start-line="96" selection-start-column="15" selection-end-line="96" selection-end-column="15" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/preprocessing_utils.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="336">
|
||||
@ -577,8 +540,6 @@
|
||||
<caret line="39" selection-start-line="32" selection-end-line="39" />
|
||||
<folding>
|
||||
<element signature="e#0#17#0" expanded="true" />
|
||||
<marker date="1550562739002" expanded="true" signature="754:937" ph="..." />
|
||||
<marker date="1550562739002" expanded="true" signature="2659:2661" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@ -600,13 +561,69 @@
|
||||
<entry file="file://$PROJECT_DIR$/gradio.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="647">
|
||||
<caret line="130" column="13" selection-start-line="130" selection-start-column="13" selection-end-line="130" selection-end-column="13" />
|
||||
<caret line="130" column="21" selection-start-line="130" selection-start-column="21" selection-end-line="130" selection-end-column="21" />
|
||||
<folding>
|
||||
<element signature="e#0#14#0" expanded="true" />
|
||||
<marker date="1550563754843" expanded="true" signature="1905:2502" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/gradio/script.py">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/gradio/inputs.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="125">
|
||||
<caret line="5" column="19" selection-start-line="5" selection-start-column="19" selection-end-line="5" selection-end-column="19" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.gitignore">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="175">
|
||||
<caret line="7" selection-start-line="7" selection-end-line="7" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/css/draw-a-digit.css">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1225">
|
||||
<caret line="96" column="15" selection-start-line="96" selection-start-column="15" selection-end-line="96" selection-end-column="15" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/gradio/networking.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="150">
|
||||
<caret line="6" column="11" selection-start-line="6" selection-start-column="5" selection-end-line="6" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/gradio/outputs.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<folding>
|
||||
<element signature="e#0#35#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/gradio/preprocessing_utils.py">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/gradio/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="175">
|
||||
<caret line="7" column="19" selection-start-line="7" selection-start-column="19" selection-end-line="7" selection-end-column="19" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/setup.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="525">
|
||||
<caret line="21" column="17" selection-start-line="21" selection-start-column="17" selection-end-line="21" selection-end-column="17" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
@ -3,9 +3,9 @@ import websockets
|
||||
import nest_asyncio
|
||||
import webbrowser
|
||||
from bs4 import BeautifulSoup
|
||||
import inputs
|
||||
import outputs
|
||||
import networking
|
||||
from gradio import inputs
|
||||
from gradio import outputs
|
||||
from gradio import networking
|
||||
|
||||
nest_asyncio.apply()
|
||||
|
@ -3,7 +3,7 @@ import base64
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
import numpy as np
|
||||
import preprocessing_utils
|
||||
from gradio import preprocessing_utils
|
||||
|
||||
class AbstractInput(ABC):
|
||||
"""
|
BIN
dist/gradio-0.1.0-py3-none-any.whl
vendored
Normal file
BIN
dist/gradio-0.1.0-py3-none-any.whl
vendored
Normal file
Binary file not shown.
BIN
dist/gradio-0.1.0.tar.gz
vendored
Normal file
BIN
dist/gradio-0.1.0.tar.gz
vendored
Normal file
Binary file not shown.
11
gradio.egg-info/PKG-INFO
Normal file
11
gradio.egg-info/PKG-INFO
Normal file
@ -0,0 +1,11 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: gradio
|
||||
Version: 0.1.0
|
||||
Summary: Python library for easily interacting with trained machine learning models
|
||||
Home-page: https://github.com/abidlabs/gradio
|
||||
Author: Abubakar Abid
|
||||
Author-email: a12d@stanford.edu
|
||||
License: UNKNOWN
|
||||
Description: UNKNOWN
|
||||
Keywords: machine learning,visualization,reproducibility
|
||||
Platform: UNKNOWN
|
12
gradio.egg-info/SOURCES.txt
Normal file
12
gradio.egg-info/SOURCES.txt
Normal file
@ -0,0 +1,12 @@
|
||||
README.md
|
||||
setup.py
|
||||
gradio/__init__.py
|
||||
gradio/inputs.py
|
||||
gradio/networking.py
|
||||
gradio/outputs.py
|
||||
gradio/preprocessing_utils.py
|
||||
gradio.egg-info/PKG-INFO
|
||||
gradio.egg-info/SOURCES.txt
|
||||
gradio.egg-info/dependency_links.txt
|
||||
gradio.egg-info/requires.txt
|
||||
gradio.egg-info/top_level.txt
|
1
gradio.egg-info/dependency_links.txt
Normal file
1
gradio.egg-info/dependency_links.txt
Normal file
@ -0,0 +1 @@
|
||||
|
6
gradio.egg-info/requires.txt
Normal file
6
gradio.egg-info/requires.txt
Normal file
@ -0,0 +1,6 @@
|
||||
numpy
|
||||
websockets
|
||||
nest_asyncio
|
||||
beautifulsoup4Pillow
|
||||
requests
|
||||
psutil
|
1
gradio.egg-info/top_level.txt
Normal file
1
gradio.egg-info/top_level.txt
Normal file
@ -0,0 +1 @@
|
||||
gradio
|
131
gradio/__init__.py
Normal file
131
gradio/__init__.py
Normal file
@ -0,0 +1,131 @@
|
||||
import asyncio
|
||||
import websockets
|
||||
import nest_asyncio
|
||||
import webbrowser
|
||||
from bs4 import BeautifulSoup
|
||||
from gradio import inputs
|
||||
from gradio import outputs
|
||||
from gradio import networking
|
||||
|
||||
nest_asyncio.apply()
|
||||
|
||||
LOCALHOST_IP = '127.0.0.1'
|
||||
INITIAL_WEBSOCKET_PORT = 9200
|
||||
TRY_NUM_PORTS = 100
|
||||
|
||||
|
||||
class Interface():
|
||||
"""
|
||||
"""
|
||||
build_template_path = 'templates/tmp_html.html'
|
||||
|
||||
def __init__(self, input, output, model, model_type, preprocessing_fn=None, postprocessing_fn=None):
|
||||
"""
|
||||
:param model_type: what kind of trained model, can be 'keras' or 'sklearn'.
|
||||
:param model_obj: the model object, such as a sklearn classifier or keras model.
|
||||
:param model_params: additional model parameters.
|
||||
"""
|
||||
self.input_interface = inputs.registry[input](preprocessing_fn)
|
||||
self.output_interface = outputs.registry[output](postprocessing_fn)
|
||||
self.model_type = model_type
|
||||
self.model_obj = model
|
||||
|
||||
def _build_template(self):
|
||||
input_template_path = self.input_interface._get_template_path()
|
||||
output_template_path = self.output_interface._get_template_path()
|
||||
input_page = open(input_template_path)
|
||||
output_page = open(output_template_path)
|
||||
input_soup = BeautifulSoup(input_page.read(), features="html.parser")
|
||||
output_soup = BeautifulSoup(output_page.read(), features="html.parser")
|
||||
|
||||
all_io_url = 'templates/all_io.html'
|
||||
all_io_page = open(all_io_url)
|
||||
all_io_soup = BeautifulSoup(all_io_page.read(), features="html.parser")
|
||||
input_tag = all_io_soup.find("div", {"id": "input"})
|
||||
output_tag = all_io_soup.find("div", {"id": "output"})
|
||||
|
||||
input_tag.replace_with(input_soup)
|
||||
output_tag.replace_with(output_soup)
|
||||
|
||||
f = open(self.build_template_path, "w")
|
||||
f.write(str(all_io_soup.prettify))
|
||||
return self.build_template_path
|
||||
|
||||
def _set_socket_url_in_js(self, socket_url):
|
||||
with open('js/all-io.js') as fin:
|
||||
lines = fin.readlines()
|
||||
lines[0] = 'var NGROK_URL = "{}"\n'.format(socket_url.replace('http', 'ws'))
|
||||
|
||||
with open('js/all-io.js', 'w') as fout:
|
||||
for line in lines:
|
||||
fout.write(line)
|
||||
|
||||
def _set_socket_port_in_js(self, socket_port):
|
||||
with open('js/all-io.js') as fin:
|
||||
lines = fin.readlines()
|
||||
lines[1] = 'var SOCKET_PORT = {}\n'.format(socket_port)
|
||||
|
||||
with open('js/all-io.js', 'w') as fout:
|
||||
for line in lines:
|
||||
fout.write(line)
|
||||
|
||||
def predict(self, array):
|
||||
if self.model_type=='sklearn':
|
||||
return self.model_obj.predict(array)
|
||||
elif self.model_type=='keras':
|
||||
return self.model_obj.predict(array)
|
||||
elif self.model_type=='func':
|
||||
return self.model_obj(array)
|
||||
else:
|
||||
raise ValueError('model_type must be one of: "sklearn" or "keras" or "func".')
|
||||
|
||||
async def communicate(self, websocket, path):
|
||||
"""
|
||||
Method that defines how this interface communicates with the websocket.
|
||||
:param websocket: a Websocket object used to communicate with the interface frontend
|
||||
:param path: ignored
|
||||
"""
|
||||
while True:
|
||||
try:
|
||||
msg = await websocket.recv()
|
||||
processed_input = self.input_interface._pre_process(msg)
|
||||
prediction = self.predict(processed_input)
|
||||
processed_output = self.output_interface._post_process(prediction)
|
||||
await websocket.send(str(processed_output))
|
||||
except websockets.exceptions.ConnectionClosed:
|
||||
pass
|
||||
|
||||
def launch(self, share_link=True):
|
||||
"""
|
||||
Standard method shared by interfaces that launches a websocket at a specified IP address.
|
||||
"""
|
||||
networking.kill_processes([4040, 4041])
|
||||
server_port = networking.start_simple_server()
|
||||
path_to_server = 'http://localhost:{}/'.format(server_port)
|
||||
path_to_template = self._build_template()
|
||||
|
||||
ports_in_use = networking.get_ports_in_use()
|
||||
for i in range(TRY_NUM_PORTS):
|
||||
if not ((INITIAL_WEBSOCKET_PORT + i) in ports_in_use):
|
||||
break
|
||||
else:
|
||||
raise OSError("All ports from {} to {} are in use. Please close a port.".format(
|
||||
INITIAL_WEBSOCKET_PORT, INITIAL_WEBSOCKET_PORT + TRY_NUM_PORTS))
|
||||
|
||||
start_server = websockets.serve(self.communicate, LOCALHOST_IP, INITIAL_WEBSOCKET_PORT + i)
|
||||
self._set_socket_port_in_js(INITIAL_WEBSOCKET_PORT + i)
|
||||
|
||||
if share_link:
|
||||
site_ngrok_url = networking.setup_ngrok(server_port)
|
||||
socket_ngrok_url = networking.setup_ngrok(INITIAL_WEBSOCKET_PORT, api_url=networking.NGROK_TUNNELS_API_URL2)
|
||||
self._set_socket_url_in_js(socket_ngrok_url)
|
||||
print("NOTE: Gradio is in beta stage, please report all bugs to: a12d@stanford.edu")
|
||||
print("Model available locally at: {}".format(path_to_server + path_to_template))
|
||||
print("Model available publicly for 8 hours at: {}".format(site_ngrok_url + '/' + path_to_template))
|
||||
asyncio.get_event_loop().run_until_complete(start_server)
|
||||
try:
|
||||
asyncio.get_event_loop().run_forever()
|
||||
except RuntimeError: # Runtime errors are thrown in jupyter notebooks because of async.
|
||||
pass
|
||||
|
||||
webbrowser.open(path_to_server + path_to_template)
|
94
gradio/inputs.py
Normal file
94
gradio/inputs.py
Normal file
@ -0,0 +1,94 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import base64
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
import numpy as np
|
||||
from gradio import preprocessing_utils
|
||||
|
||||
class AbstractInput(ABC):
|
||||
"""
|
||||
An abstract class for defining the methods that all gradio inputs should have.
|
||||
When this is subclassed, it is automatically added to the registry
|
||||
"""
|
||||
|
||||
def __init__(self, preprocessing_fn=None):
|
||||
if preprocessing_fn is not None:
|
||||
self._pre_process = preprocessing_fn
|
||||
super().__init__()
|
||||
|
||||
@abstractmethod
|
||||
def _get_template_path(self):
|
||||
"""
|
||||
All interfaces should define a method that returns the path to its template.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def _pre_process(self):
|
||||
"""
|
||||
All interfaces should define a method that returns the path to its template.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Sketchpad(AbstractInput):
|
||||
|
||||
def _get_template_path(self):
|
||||
return 'templates/sketchpad_input.html'
|
||||
|
||||
def _pre_process(self, imgstring):
|
||||
"""
|
||||
"""
|
||||
content = imgstring.split(';')[1]
|
||||
image_encoded = content.split(',')[1]
|
||||
body = base64.decodebytes(image_encoded.encode('utf-8'))
|
||||
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
|
||||
im = preprocessing_utils.resize_and_crop(im, (28, 28))
|
||||
array = np.array(im).flatten().reshape(1, 28, 28, 1)
|
||||
return array
|
||||
|
||||
|
||||
class Webcam(AbstractInput):
|
||||
|
||||
def _get_template_path(self):
|
||||
return 'templates/webcam_input.html'
|
||||
|
||||
def _pre_process(self, imgstring):
|
||||
"""
|
||||
"""
|
||||
content = imgstring.split(';')[1]
|
||||
image_encoded = content.split(',')[1]
|
||||
body = base64.decodebytes(image_encoded.encode('utf-8'))
|
||||
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
|
||||
im = preprocessing_utils.resize_and_crop(im, (48, 48))
|
||||
array = np.array(im).flatten().reshape(1, 48, 48, 1)
|
||||
return array
|
||||
|
||||
class Textbox(AbstractInput):
|
||||
|
||||
def _get_template_path(self):
|
||||
return 'templates/textbox_input.html'
|
||||
|
||||
def _pre_process(self, text):
|
||||
"""
|
||||
"""
|
||||
return text
|
||||
|
||||
class ImageUpload(AbstractInput):
|
||||
|
||||
def _get_template_path(self):
|
||||
return 'templates/image_upload_input.html'
|
||||
|
||||
def _pre_process(self, imgstring):
|
||||
"""
|
||||
"""
|
||||
content = imgstring.split(';')[1]
|
||||
image_encoded = content.split(',')[1]
|
||||
body = base64.decodebytes(image_encoded.encode('utf-8'))
|
||||
im = Image.open(BytesIO(base64.b64decode(image_encoded))).convert('L')
|
||||
im = preprocessing_utils.resize_and_crop(im, (48, 48))
|
||||
array = np.array(im).flatten().reshape(1, 48, 48, 1)
|
||||
return array
|
||||
|
||||
|
||||
registry = {cls.__name__.lower(): cls for cls in AbstractInput.__subclasses__()}
|
76
gradio/networking.py
Normal file
76
gradio/networking.py
Normal file
@ -0,0 +1,76 @@
|
||||
import subprocess
|
||||
import requests
|
||||
import zipfile
|
||||
import io
|
||||
import sys
|
||||
import os
|
||||
from psutil import process_iter, AccessDenied
|
||||
from signal import SIGTERM # or SIGKILL
|
||||
|
||||
INITIAL_PORT_VALUE = 7860
|
||||
TRY_NUM_PORTS = 100
|
||||
LOCALHOST_PREFIX = 'localhost:'
|
||||
NGROK_TUNNELS_API_URL = "http://localhost:4040/api/tunnels" # TODO(this should be captured from output)
|
||||
NGROK_TUNNELS_API_URL2 = "http://localhost:4041/api/tunnels" # TODO(this should be captured from output)
|
||||
|
||||
NGROK_ZIP_URLS = {
|
||||
"linux": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip",
|
||||
"darwin": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip",
|
||||
"win32": "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-windows-amd64.zip",
|
||||
}
|
||||
|
||||
|
||||
def get_ports_in_use():
|
||||
ports_in_use = []
|
||||
for proc in process_iter():
|
||||
for conns in proc.connections(kind='inet'):
|
||||
ports_in_use.append(conns.laddr.port)
|
||||
return ports_in_use
|
||||
|
||||
|
||||
def start_simple_server():
|
||||
# TODO(abidlabs): increment port number until free port is found
|
||||
ports_in_use = get_ports_in_use()
|
||||
for i in range(TRY_NUM_PORTS):
|
||||
if not((INITIAL_PORT_VALUE + i) in ports_in_use):
|
||||
break
|
||||
else:
|
||||
raise OSError("All ports from {} to {} are in use. Please close a port.".format(
|
||||
INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS))
|
||||
subprocess.Popen(['python', '-m', 'http.server', str(INITIAL_PORT_VALUE + i)])
|
||||
return INITIAL_PORT_VALUE + i
|
||||
|
||||
|
||||
def download_ngrok():
|
||||
try:
|
||||
zip_file_url = NGROK_ZIP_URLS[sys.platform]
|
||||
except KeyError:
|
||||
print("Sorry, we don't currently support your operating system, please leave us a note on GitHub, and we'll look into it!")
|
||||
return
|
||||
|
||||
r = requests.get(zip_file_url)
|
||||
z = zipfile.ZipFile(io.BytesIO(r.content))
|
||||
z.extractall()
|
||||
|
||||
|
||||
def setup_ngrok(local_port, api_url=NGROK_TUNNELS_API_URL):
|
||||
if not(os.path.isfile('ngrok.exe')):
|
||||
download_ngrok()
|
||||
subprocess.Popen(['ngrok', 'http', str(local_port)])
|
||||
r = requests.get(api_url)
|
||||
for tunnel in r.json()['tunnels']:
|
||||
if LOCALHOST_PREFIX + str(local_port) in tunnel['config']['addr']:
|
||||
return tunnel['public_url']
|
||||
raise RuntimeError("Not able to retrieve ngrok public URL")
|
||||
|
||||
|
||||
def kill_processes(process_ids):
|
||||
for proc in process_iter():
|
||||
for conns in proc.connections(kind='inet'):
|
||||
if conns.laddr.port in process_ids:
|
||||
try:
|
||||
proc.send_signal(SIGTERM) # or SIGKILL
|
||||
except AccessDenied:
|
||||
print("Unable to kill process running on port {}, please kill manually.".format(conns.laddr.port))
|
||||
|
||||
|
63
gradio/outputs.py
Normal file
63
gradio/outputs.py
Normal file
@ -0,0 +1,63 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import numpy as np
|
||||
|
||||
class AbstractOutput(ABC):
|
||||
"""
|
||||
An abstract class for defining the methods that all gradio inputs should have.
|
||||
When this is subclassed, it is automatically added to the registry
|
||||
"""
|
||||
|
||||
def __init__(self, postprocessing_fn=None):
|
||||
"""
|
||||
"""
|
||||
if postprocessing_fn is not None:
|
||||
self._post_process = postprocessing_fn
|
||||
super().__init__()
|
||||
|
||||
@abstractmethod
|
||||
def _get_template_path(self):
|
||||
"""
|
||||
All interfaces should define a method that returns the path to its template.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def _post_process(self):
|
||||
"""
|
||||
All interfaces should define a method that returns the path to its template.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Class(AbstractOutput):
|
||||
|
||||
def _get_template_path(self):
|
||||
return 'templates/class_output.html'
|
||||
|
||||
def _post_process(self, prediction):
|
||||
"""
|
||||
"""
|
||||
if isinstance(prediction, np.ndarray):
|
||||
prediction = prediction.squeeze()
|
||||
if prediction.size == 1:
|
||||
return prediction
|
||||
else:
|
||||
return prediction.argmax()
|
||||
elif isinstance(prediction, str):
|
||||
return prediction
|
||||
else:
|
||||
raise ValueError("Unable to post-process model prediction.")
|
||||
|
||||
|
||||
class Textbox(AbstractOutput):
|
||||
|
||||
def _get_template_path(self):
|
||||
return 'templates/textbox_output.html'
|
||||
|
||||
def _post_process(self, prediction):
|
||||
"""
|
||||
"""
|
||||
return prediction
|
||||
|
||||
|
||||
registry = {cls.__name__.lower(): cls for cls in AbstractOutput.__subclasses__()}
|
53
gradio/preprocessing_utils.py
Normal file
53
gradio/preprocessing_utils.py
Normal file
@ -0,0 +1,53 @@
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def resize_and_crop(img, size, crop_type='top'):
|
||||
"""
|
||||
Resize and crop an image to fit the specified size.
|
||||
args:
|
||||
img_path: path for the image to resize.
|
||||
modified_path: path to store the modified image.
|
||||
size: `(width, height)` tuple.
|
||||
crop_type: can be 'top', 'middle' or 'bottom', depending on this
|
||||
value, the image will cropped getting the 'top/left', 'midle' or
|
||||
'bottom/rigth' of the image to fit the size.
|
||||
raises:
|
||||
Exception: if can not open the file in img_path of there is problems
|
||||
to save the image.
|
||||
ValueError: if an invalid `crop_type` is provided.
|
||||
"""
|
||||
# Get current and desired ratio for the images
|
||||
img_ratio = img.size[0] / float(img.size[1])
|
||||
ratio = size[0] / float(size[1])
|
||||
# The image is scaled/cropped vertically or horizontally depending on the ratio
|
||||
if ratio > img_ratio:
|
||||
img = img.resize((size[0], size[0] * img.size[1] / img.size[0]),
|
||||
Image.ANTIALIAS)
|
||||
# Crop in the top, middle or bottom
|
||||
if crop_type == 'top':
|
||||
box = (0, 0, img.size[0], size[1])
|
||||
elif crop_type == 'middle':
|
||||
box = (0, (img.size[1] - size[1]) / 2, img.size[0], (img.size[1] + size[1]) / 2)
|
||||
elif crop_type == 'bottom':
|
||||
box = (0, img.size[1] - size[1], img.size[0], img.size[1])
|
||||
else:
|
||||
raise ValueError('ERROR: invalid value for crop_type')
|
||||
img = img.crop(box)
|
||||
elif ratio < img_ratio:
|
||||
img = img.resize((size[1] * img.size[0] // img.size[1], size[1]),
|
||||
Image.ANTIALIAS)
|
||||
# Crop in the top, middle or bottom
|
||||
if crop_type == 'top':
|
||||
box = (0, 0, size[0], img.size[1])
|
||||
elif crop_type == 'middle':
|
||||
box = ((img.size[0] - size[0]) / 2, 0, (img.size[0] + size[0]) / 2, img.size[1])
|
||||
elif crop_type == 'bottom':
|
||||
box = (img.size[0] - size[0], 0, img.size[0], img.size[1])
|
||||
else:
|
||||
raise ValueError('ERROR: invalid value for crop_type')
|
||||
img = img.crop(box)
|
||||
else:
|
||||
img = img.resize((size[0], size[1]),
|
||||
Image.ANTIALIAS)
|
||||
# If the scale is the same, we do not need to crop
|
||||
return img
|
12
script.py
12
script.py
@ -1,12 +0,0 @@
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
sketchpad_url = 'templates/sketchpad_input.html'
|
||||
all_io_url = 'templates/all_io.html'
|
||||
sketchpad_page = open(sketchpad_url)
|
||||
all_io_page = open(all_io_url)
|
||||
sketchpad_soup = BeautifulSoup(sketchpad_page.read())
|
||||
all_io_soup = BeautifulSoup(all_io_page.read())
|
||||
input_tag = all_io_soup.find("div", {"id": "input"})
|
||||
input_tag.replace_with(sketchpad_soup)
|
||||
f = open("templates/tmp_html.html", "w")
|
||||
f.write(str(all_io_soup.prettify))
|
24
setup.py
Normal file
24
setup.py
Normal file
@ -0,0 +1,24 @@
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name = 'gradio',
|
||||
version = '0.1.0',
|
||||
description = 'Python library for easily interacting with trained machine learning models',
|
||||
author = 'Abubakar Abid',
|
||||
author_email = 'a12d@stanford.edu',
|
||||
url = 'https://github.com/abidlabs/gradio',
|
||||
packages=['gradio'],
|
||||
keywords = ['machine learning', 'visualization', 'reproducibility'],
|
||||
install_requires=[
|
||||
'numpy',
|
||||
'websockets',
|
||||
'nest_asyncio',
|
||||
'beautifulsoup4'
|
||||
'Pillow',
|
||||
'requests',
|
||||
'psutil',
|
||||
],
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user