This commit is contained in:
Ali Abid 2021-10-18 18:34:34 +00:00
commit 5b0bdf4171
14 changed files with 92 additions and 314 deletions

View File

@ -1,4 +1,6 @@
version: 2
version: 2.1
orbs:
codecov: codecov/codecov@3.1.1
jobs:
build:
docker:
@ -15,7 +17,7 @@ jobs:
. venv/bin/activate
pip install --upgrade pip
pip install -r gradio.egg-info/requires.txt
pip install selenium==4.0.0a6.post2
pip install selenium==4.0.0a6.post2 coverage
- run:
command: |
chromedriver --version
@ -30,7 +32,10 @@ jobs:
- run:
command: |
. venv/bin/activate
python3 -m unittest
coverage run -m unittest
coverage xml
- codecov/upload:
file: 'coverage.xml'
- store_artifacts:
path: /home/circleci/project/test/tmp
destination: screenshots

2
.gitignore vendored
View File

@ -7,6 +7,8 @@ gradio.egg-info/*
*.pyc
staticfiles
.env
.coverage
coverage.xml
*.sqlite3
.idea/*
*.ipynb

View File

@ -1,4 +1,6 @@
[![CircleCI](https://circleci.com/gh/gradio-app/gradio.svg?style=svg)](https://circleci.com/gh/gradio-app/gradio) [![PyPI version](https://badge.fury.io/py/gradio.svg)](https://badge.fury.io/py/gradio)
[![CircleCI](https://circleci.com/gh/gradio-app/gradio.svg?style=svg)](https://circleci.com/gh/gradio-app/gradio) [![PyPI version](https://badge.fury.io/py/gradio.svg)](https://badge.fury.io/py/gradio) [![codecov](https://codecov.io/gh/gradio-app/gradio/branch/master/graph/badge.svg?token=NNVPX9KEGS)](https://codecov.io/gh/gradio-app/gradio) [![PyPI - Downloads](https://img.shields.io/pypi/dm/gradio)](https://pypi.org/project/gradio/) [![Twitter Follow](https://img.shields.io/twitter/follow/gradio.svg?style=social&label=Follow)](https://twitter.com/gradio)
# Welcome to Gradio

View File

@ -1,5 +1,6 @@
from gradio.interface import * # This makes it possible to import `Interface` as `gradio.Interface`.
from gradio.networking import get_state, set_state
from gradio.mix import *
import pkg_resources
current_pkg_version = pkg_resources.require("gradio")[0].version

View File

@ -1,58 +0,0 @@
import numpy as np
SMALL_CONST = 1e-10
class PCA:
"""
Credit: https://www.python-engineer.com/courses/mlfromscratch/11_pca/
"""
def __init__(self, n_components, random_state):
self.n_components = n_components
self.components = None
self.mean = None
self.random_state = random_state
def fit(self, X):
np.random.seed(self.random_state)
self.mean = np.mean(X, axis=0)
X = X - self.mean
cov = np.cov(X.T)
eigenvalues, eigenvectors = np.linalg.eig(cov)
eigenvectors = eigenvectors.T
idxs = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idxs]
eigenvectors = eigenvectors[idxs]
self.components = np.real(eigenvectors[0:self.n_components])
def transform(self, X):
X = X - self.mean
return np.dot(X, self.components.T)
def fit_transform(self, X):
self.fit(X)
return self.transform(X)
def calculate_similarity(embedding1, embedding2):
"""
Scores the similarity between two embeddings by taking the cosine similarity
"""
e1, e2 = np.array(embedding1), np.array(embedding2)
cosine_similarity = np.dot(e1, e2) / (np.linalg.norm(e1) * np.linalg.norm(e2) + SMALL_CONST)
return cosine_similarity
def fit_pca_to_embeddings(embeddings):
"""
Computes 2D tsne embeddings from a list of higher-dimensional embeddings
"""
pca_model = PCA(n_components=2, random_state=0)
embeddings = np.array(embeddings)
embeddings_2D = pca_model.fit_transform(embeddings)
return pca_model, [{'x': e[0], 'y': e[1]} for e in embeddings_2D.tolist()]
def transform_with_pca(pca_model, embeddings):
"""
Computes 2D tsne embeddings from a list of higher-dimensional embeddings
"""
embeddings_2D = pca_model.transform(embeddings)
return [{'x': e[0], 'y': e[1]} for e in embeddings_2D.tolist()]

View File

@ -168,55 +168,6 @@ def get_huggingface_interface(model_name, api_key, alias):
return interface_info
def get_gradio_interface(model_name, api_key, alias):
model_info = requests.get("https://gradio.app/get_config/{}".format(model_name)).json()
config_info = json.loads(model_info["config"])
api_url = "{}/api/predict/".format(model_info["url"])
headers = {
'authority': model_info["url"],
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="90", "Microsoft Edge";v="90"',
'accept': 'application/json, text/javascript, */*; q=0.01',
'sec-ch-ua-mobile': '?1',
'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Mobile Safari/537.36 Edg/90.0.818.56',
'content-type': 'application/json; charset=UTF-8',
'origin': 'https://gradio.app',
'sec-fetch-site': 'cross-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://gradio.app/',
'accept-language': 'en-US,en;q=0.9',
}
def query_gradio_api(*input):
payload = pipeline['preprocess'](*input)
data = json.dumps(payload)
response = requests.post(api_url, headers=headers, data=data)
result = json.loads(response.content.decode("utf-8"))
output = pipeline['postprocess'](result)
return output
if alias is None:
query_gradio_api.__name__ = model_name
else:
query_gradio_api.__name__ = alias
pipeline = {
'inputs': [inp[0] for inp in config_info["input_components"]],
'outputs': [out[0] for out in config_info["output_components"]],
'preprocess': lambda x: {"data": [x]},
'postprocess': lambda r: r["data"][0],
}
interface_info = {
'fn': query_gradio_api,
'inputs': pipeline['inputs'],
'outputs': pipeline['outputs'],
'title': model_name,
}
return interface_info
def load_interface(name, src=None, api_key=None, alias=None):
if src is None:
tokens = name.split("/")
@ -244,7 +195,6 @@ def interface_params_from_config(config_dict):
del config_dict[key]
return config_dict
def get_spaces_interface(model_name, api_key, alias):
iframe_url = "https://huggingface.co/gradioiframe/{}/+".format(model_name)
api_url = "https://huggingface.co/gradioiframe/{}/api/predict/".format(model_name)
@ -264,16 +214,18 @@ def get_spaces_interface(model_name, api_key, alias):
if len(interface_info["outputs"])==1: # if the fn is supposed to return a single value, pop it
output = output[0]
return output
interface_info["fn"] = fn
if alias is not None:
interface_info["title"] = alias
if alias is None:
fn.__name__ = model_name
else:
fn.__name__ = alias
interface_info["fn"] = fn
return interface_info
repos = {
# for each repo, we have a method that returns the Interface given the model name & optionally an api_key
"huggingface": get_huggingface_interface,
"gradio": get_gradio_interface,
"spaces": get_spaces_interface,
}

View File

@ -69,16 +69,6 @@ class InputComponent(Component):
'''
pass
def embed(self, x):
"""
Return a default embedding for the *preprocessed* input to the interface. Used to compute similar inputs.
x (Any): Input to interface
Returns:
(List[Float]): An embedding vector as a list or numpy array of floats
"""
pass
class Textbox(InputComponent):
"""
Component creates a textbox for user to enter input. Provides a string as an argument to the wrapped function.
@ -196,28 +186,6 @@ class Textbox(InputComponent):
result.append((self.interpretation_separator, 0))
return result
def _embed_text(self, text):
"""
Figures out a "reasonable" embedding for any particular text. Did it this way to avoid loading any
external machine learning models, which would be slow and require additional dependencies.
"""
top_english_words = ['find', 'new', 'work', 'part', 'take', 'get', 'place', 'made', 'live', 'where', 'after', 'back', 'little', 'only', 'round', 'man', 'year', 'came', 'show', 'every', 'good', 'me', 'give', 'our', 'under', 'name', 'very', 'through', 'just', 'form', 'sentence', 'great', 'think', 'say', 'help', 'low', 'line', 'differ', 'turn', 'cause', 'much', 'mean', 'before', 'move', 'right', 'boy', 'old', 'too', 'same', 'tell', 'does', 'set', 'three', 'want', 'air', 'well', 'also', 'play', 'small', 'end', 'put', 'home', 'read', 'hand', 'port', 'large', 'spell', 'add', 'even', 'land', 'here', 'must', 'big', 'high', 'such', 'follow', 'act', 'why', 'ask', 'men', 'change', 'went', 'light', 'kind', 'off', 'need', 'house', 'picture', 'try', 'us', 'again', 'animal', 'point', 'mother', 'world', 'near', 'build', 'self', 'earth', 'father', 'head', 'stand', 'own', 'page', 'should', 'country', 'found', 'answer', 'school', 'grow', 'study', 'still', 'learn', 'plant', 'cover', 'food', 'sun', 'four', 'between', 'state', 'keep', 'eye', 'never', 'last', 'let', 'thought', 'city', 'tree', 'cross', 'farm', 'hard', 'start', 'might', 'story', 'saw', 'far', 'sea', 'draw', 'left', 'late', 'run', 'don\'t', 'while', 'press', 'close', 'night', 'real', 'life', 'few', 'north', 'open', 'seem', 'together', 'next', 'white', 'children', 'begin', 'got', 'walk', 'example', 'ease', 'paper', 'group', 'always', 'music', 'those', 'both', 'mark', 'often', 'letter', 'until', 'mile', 'river', 'car', 'feet', 'care', 'second', 'book', 'carry', 'took', 'science', 'eat', 'room', 'friend', 'began', 'idea', 'fish', 'mountain', 'stop', 'once', 'base', 'hear', 'horse', 'cut', 'sure', 'watch', 'color', 'face', 'wood', 'main', 'enough', 'plain', 'girl', 'usual', 'young', 'ready', 'above', 'ever', 'red', 'list', 'though', 'feel', 'talk', 'bird', 'soon', 'body', 'dog', 'family', 'direct', 'pose', 'leave', 'song', 'measure', 'door', 'product', 'black', 'short', 'numeral', 'class', 'wind', 'question', 'happen', 'complete', 'ship', 'area', 'half', 'rock', 'order', 'fire', 'south', 'problem', 'piece', 'told', 'knew', 'pass', 'since', 'top', 'whole', 'king', 'space', 'heard', 'best', 'hour', 'better', 'true', 'during', 'hundred', 'five', 'remember', 'step', 'early', 'hold', 'west', 'ground', 'interest', 'reach', 'fast', 'verb', 'sing', 'listen', 'six', 'table', 'travel', 'less', 'morning', 'ten', 'simple', 'several', 'vowel', 'toward', 'war', 'lay', 'against', 'pattern', 'slow', 'center', 'love', 'person', 'money', 'serve', 'appear', 'road', 'map', 'rain', 'rule', 'govern', 'pull', 'cold', 'notice', 'voice', 'unit', 'power', 'town', 'fine', 'certain', 'fly', 'fall', 'lead', 'cry', 'dark', 'machine', 'note', 'wait', 'plan', 'figure', 'star', 'box', 'noun', 'field', 'rest', 'correct', 'able', 'pound', 'done', 'beauty', 'drive', 'stood', 'contain', 'front', 'teach', 'week', 'final', 'gave', 'green', 'oh', 'quick', 'develop', 'ocean', 'warm', 'free', 'minute', 'strong', 'special', 'mind', 'behind', 'clear', 'tail', 'produce', 'fact', 'street', 'inch', 'multiply', 'nothing', 'course', 'stay', 'wheel', 'full', 'force', 'blue', 'object', 'decide', 'surface', 'deep', 'moon', 'island', 'foot', 'system', 'busy', 'test', 'record', 'boat', 'common', 'gold', 'possible', 'plane', 'stead', 'dry', 'wonder', 'laugh', 'thousand', 'ago', 'ran', 'check', 'game', 'shape', 'equate', 'hot', 'miss', 'brought', 'heat', 'snow', 'tire', 'bring', 'yes', 'distant', 'fill', 'east', 'paint', 'language', 'among', 'grand', 'ball', 'yet', 'wave', 'drop', 'heart', 'am', 'present', 'heavy', 'dance', 'engine', 'position', 'arm', 'wide', 'sail', 'material', 'size', 'vary', 'settle', 'speak', 'weight', 'general', 'ice', 'matter', 'circle', 'pair', 'include', 'divide', 'syllable', 'felt', 'perhaps', 'pick', 'sudden', 'count', 'square', 'reason', 'length', 'represent', 'art', 'subject', 'region', 'energy', 'hunt', 'probable', 'bed', 'brother', 'egg', 'ride', 'cell', 'believe', 'fraction', 'forest', 'sit', 'race', 'window', 'store', 'summer', 'train', 'sleep', 'prove', 'lone', 'leg',
'exercise', 'wall', 'catch', 'mount', 'wish', 'sky', 'board', 'joy', 'winter', 'sat', 'written', 'wild', 'instrument', 'kept', 'glass', 'grass', 'cow', 'job', 'edge', 'sign', 'visit', 'past', 'soft', 'fun', 'bright', 'gas', 'weather', 'month', 'million', 'bear', 'finish', 'happy', 'hope', 'flower', 'clothe', 'strange', 'gone', 'jump', 'baby', 'eight', 'village', 'meet', 'root', 'buy', 'raise', 'solve', 'metal', 'whether', 'push', 'seven', 'paragraph', 'third', 'shall', 'held', 'hair', 'describe', 'cook', 'floor', 'either', 'result', 'burn', 'hill', 'safe', 'cat', 'century', 'consider', 'type', 'law', 'bit', 'coast', 'copy', 'phrase', 'silent', 'tall', 'sand', 'soil', 'roll', 'temperature', 'finger', 'industry', 'value', 'fight', 'lie', 'beat', 'excite', 'natural', 'view', 'sense', 'ear', 'else', 'quite', 'broke', 'case', 'middle', 'kill', 'son', 'lake', 'moment', 'scale', 'loud', 'spring', 'observe', 'child', 'straight', 'consonant', 'nation', 'dictionary', 'milk', 'speed', 'method', 'organ', 'pay', 'age', 'section', 'dress', 'cloud', 'surprise', 'quiet', 'stone', 'tiny', 'climb', 'cool', 'design', 'poor', 'lot', 'experiment', 'bottom', 'key', 'iron', 'single', 'stick', 'flat', 'twenty', 'skin', 'smile', 'crease', 'hole', 'trade', 'melody', 'trip', 'office', 'receive', 'row', 'mouth', 'exact', 'symbol', 'die', 'least', 'trouble', 'shout', 'except', 'wrote', 'seed', 'tone', 'join', 'suggest', 'clean', 'break', 'lady', 'yard', 'rise', 'bad', 'blow', 'oil', 'blood', 'touch', 'grew', 'cent', 'mix', 'team', 'wire', 'cost', 'lost', 'brown', 'wear', 'garden', 'equal', 'sent', 'choose', 'fell', 'fit', 'flow', 'fair', 'bank', 'collect', 'save', 'control', 'decimal', 'gentle', 'woman', 'captain', 'practice', 'separate', 'difficult', 'doctor', 'please', 'protect', 'noon', 'whose', 'locate', 'ring', 'character', 'insect', 'caught', 'period', 'indicate', 'radio', 'spoke', 'atom', 'human', 'history', 'effect', 'electric', 'expect', 'crop', 'modern', 'element', 'hit', 'student', 'corner', 'party', 'supply', 'bone', 'rail', 'imagine', 'provide', 'agree', 'thus', 'capital', 'won\'t', 'chair', 'danger', 'fruit', 'rich', 'thick', 'soldier', 'process', 'operate', 'guess', 'necessary', 'sharp', 'wing', 'create', 'neighbor', 'wash', 'bat', 'rather', 'crowd', 'corn', 'compare', 'poem', 'string', 'bell', 'depend', 'meat', 'rub', 'tube', 'famous', 'dollar', 'stream', 'fear', 'sight', 'thin', 'triangle', 'planet', 'hurry', 'chief', 'colony', 'clock', 'mine', 'tie', 'enter', 'major', 'fresh', 'search', 'send', 'yellow', 'gun', 'allow', 'print', 'dead', 'spot', 'desert', 'suit', 'current', 'lift', 'rose', 'continue', 'block', 'chart', 'hat', 'sell', 'success', 'company', 'subtract', 'event', 'particular', 'deal', 'swim', 'term', 'opposite', 'wife', 'shoe', 'shoulder', 'spread', 'arrange', 'camp', 'invent', 'cotton', 'born', 'determine', 'quart', 'nine', 'truck', 'noise', 'level', 'chance', 'gather', 'shop', 'stretch', 'throw', 'shine', 'property', 'column', 'molecule', 'select', 'wrong', 'gray', 'repeat', 'require', 'broad', 'prepare', 'salt', 'nose', 'plural', 'anger', 'claim', 'continent', 'oxygen', 'sugar', 'death', 'pretty', 'skill', 'women', 'season', 'solution', 'magnet', 'silver', 'thank', 'branch', 'match', 'suffix', 'especially', 'fig', 'afraid', 'huge', 'sister', 'steel', 'discuss', 'forward', 'similar', 'guide', 'experience', 'score', 'apple', 'bought', 'led', 'pitch', 'coat', 'mass', 'card', 'band', 'rope', 'slip', 'win', 'dream', 'evening', 'condition', 'feed', 'tool', 'total', 'basic', 'smell', 'valley', 'nor', 'double', 'seat', 'arrive', 'master', 'track', 'parent', 'shore', 'division', 'sheet', 'substance', 'favor', 'connect', 'post', 'spend', 'chord', 'fat', 'glad', 'original', 'share', 'station', 'dad', 'bread', 'charge', 'proper', 'bar', 'offer', 'segment', 'slave', 'duck', 'instant', 'market', 'degree', 'populate', 'chick', 'dear', 'enemy', 'reply', 'drink', 'occur', 'support', 'speech', 'nature', 'range', 'steam', 'motion', 'path', 'liquid', 'log', 'meant', 'quotient', 'teeth', 'shell', 'neck']
words = text.split(' ')
return np.array([w in words for w in top_english_words])
def embed(self, x):
"""
Embeds an arbitrary text based on word frequency
"""
if self.type == "str":
return self._embed_text(x)
elif self.type == "number":
return [float(x)]
else:
raise ValueError("Unknown type: " + str(self.type) +
". Please choose from: 'str', 'number'.")
class Number(InputComponent):
"""
@ -298,9 +266,6 @@ class Number(InputComponent):
interpretation.insert(int(len(interpretation) / 2), [x, None])
return interpretation
def embed(self, x):
return [float(x)]
class Slider(InputComponent):
"""
@ -371,9 +336,6 @@ class Slider(InputComponent):
"""
return scores
def embed(self, x):
return [float(x)]
class Checkbox(InputComponent):
"""
@ -431,9 +393,6 @@ class Checkbox(InputComponent):
else:
return None, scores[0]
def embed(self, x):
return [float(x)]
class CheckboxGroup(InputComponent):
"""
@ -504,21 +463,6 @@ class CheckboxGroup(InputComponent):
final_scores.append(score_set)
return final_scores
@classmethod
def get_shortcut_implementations(cls):
return {
"checkboxgroup": {},
}
def embed(self, x):
if self.type == "value":
return [float(choice in x) for choice in self.choices]
elif self.type == "index":
return [float(index in x) for index in range(len(self.choices))]
else:
raise ValueError("Unknown type: " + str(self.type) +
". Please choose from: 'value', 'index'.")
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (List[str]])
@ -586,21 +530,6 @@ class Radio(InputComponent):
scores.insert(self.choices.index(x), None)
return scores
@classmethod
def get_shortcut_implementations(cls):
return {
"radio": {},
}
def embed(self, x):
if self.type == "value":
return [float(choice == x) for choice in self.choices]
elif self.type == "index":
return [float(index == x) for index in range(len(self.choices))]
else:
raise ValueError("Unknown type: " + str(self.type) +
". Please choose from: 'value', 'index'.")
class Dropdown(InputComponent):
"""
@ -659,22 +588,6 @@ class Dropdown(InputComponent):
scores.insert(self.choices.index(x), None)
return scores
@classmethod
def get_shortcut_implementations(cls):
return {
"dropdown": {},
}
def embed(self, x):
if self.type == "value":
return [float(choice == x) for choice in self.choices]
elif self.type == "index":
return [float(index == x) for index in range(len(self.choices))]
else:
raise ValueError("Unknown type: " + str(self.type) +
". Please choose from: 'value', 'index'.")
class Image(InputComponent):
"""
Component creates an image upload box with editing capabilities.
@ -690,7 +603,7 @@ class Image(InputComponent):
invert_colors (bool): whether to invert the image as a preprocessing step.
source (str): Source of image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "canvas" defaults to a white image that can be edited and drawn upon with tools.
tool (str): Tools used for editing. "editor" allows a full screen editor, "select" provides a cropping and zoom tool.
type (str): Type of value to be returned by component. "numpy" returns a numpy array with shape (width, height, 3) and values from 0 to 255, "pil" returns a PIL image object, "file" returns a temporary file object whose path can be retrieved by file_obj.name.
type (str): Type of value to be returned by component. "numpy" returns a numpy array with shape (width, height, 3) and values from 0 to 255, "pil" returns a PIL image object, "file" returns a temporary file object whose path can be retrieved by file_obj.name, "base64" leaves as a base64 string.
label (str): component name in interface.
optional (bool): If True, the interface can be submitted with no uploaded image, in which case the input value is None.
'''
@ -725,7 +638,7 @@ class Image(InputComponent):
}
def preprocess(self, x):
if x is None:
if x is None or self.type == "base64":
return x
im = processing_utils.decode_base64_to_image(x)
fmt = im.format
@ -840,20 +753,6 @@ class Image(InputComponent):
output_scores = (output_scores - min_val) / (max_val - min_val)
return output_scores.tolist()
def embed(self, x):
shape = (100, 100) if self.shape is None else self.shape
if self.type == "pil":
im = x
elif self.type == "numpy":
im = PIL.Image.fromarray(x)
elif self.type == "file":
im = PIL.Image.open(x)
else:
raise ValueError("Unknown type: " + str(self.type) +
". Please choose from: 'numpy', 'pil', 'file'.")
im = processing_utils.resize_and_crop(im, (shape[0], shape[1]))
return np.asarray(im).flatten()
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (str) path to image file
@ -1127,9 +1026,6 @@ class File(InputComponent):
else:
return [process_single_file(f) for f in x]
def embed(self, x):
raise NotImplementedError("File doesn't currently support embeddings")
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (str) path to file
@ -1209,10 +1105,6 @@ class Dataframe(InputComponent):
raise ValueError("Unknown type: " + str(self.type) +
". Please choose from: 'pandas', 'numpy', 'array'.")
def embed(self, x):
raise NotImplementedError(
"DataFrame doesn't currently support embeddings")
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (List[List[Union[str, float]]]) 2D array
@ -1268,10 +1160,6 @@ class Timeseries(InputComponent):
dataframe = dataframe.loc[dataframe[self.x or 0] <= x["range"][1]]
return dataframe
def embed(self, x):
raise NotImplementedError(
"DataFrame doesn't currently support embeddings")
def save_flagged(self, dir, label, data, encryption_key):
"""
Returns: (List[List[Union[str, float]]]) 2D array
@ -1289,9 +1177,12 @@ def get_input_instance(iface):
return shortcut[0](**shortcut[1])
elif isinstance(iface, dict): # a dict with `name` as the input component type and other keys as parameters
name = iface.pop('name')
component, params = InputComponent.get_all_shortcut_implementations()[name]
params.update(**iface)
return component(**params)
for component in InputComponent.__subclasses__():
if component.__name__.lower() == name:
break
else:
raise ValueError("No such InputComponent: {}".format(name))
return component(**iface)
elif isinstance(iface, InputComponent):
return iface
else:

View File

@ -71,7 +71,7 @@ class Interface:
title=None, description=None, article=None, thumbnail=None,
css=None, server_port=None, server_name=networking.LOCALHOST_NAME, height=500, width=900,
allow_screenshot=True, allow_flagging=True, flagging_options=None, encrypt=False,
show_tips=False, embedding=None, flagging_dir="flagged", analytics_enabled=True, enable_queue=False):
show_tips=False, flagging_dir="flagged", analytics_enabled=True, enable_queue=False):
"""
Parameters:
fn (Callable): the function to wrap an interface around.
@ -177,7 +177,6 @@ class Interface:
self.share = None
self.share_url = None
self.local_url = None
self.embedding = embedding
self.show_tips = show_tips
self.requires_permissions = any(
[component.requires_permissions for component in self.input_components])
@ -190,7 +189,6 @@ class Interface:
'capture_session': capture_session,
'ip_address': ip_address,
'interpretation': interpretation,
'embedding': embedding,
'allow_flagging': allow_flagging,
'allow_screenshot': allow_screenshot,
'custom_css': self.css is not None,
@ -217,8 +215,11 @@ class Interface:
except (requests.ConnectionError, requests.exceptions.ReadTimeout):
pass # do not push analytics if no network
def __call__(self, params_per_function):
return self.predict[0](params_per_function)
def __call__(self, *params):
output = [p(*params) for p in self.predict]
if len(output) == 1:
return output.pop() # if there's only one output, then don't return as list
return output
def __str__(self):
return self.__repr__()
@ -259,7 +260,6 @@ class Interface:
"allow_flagging": self.allow_flagging,
"flagging_options": self.flagging_options,
"allow_interpretation": self.interpretation is not None,
"allow_embedding": self.embedding is not None,
"queue": self.enable_queue
}
try:
@ -604,7 +604,6 @@ class Interface:
try:
from IPython.display import IFrame, display
# Embed the remote interface page if on google colab; otherwise, embed the local page.
print(strings.en["INLINE_DISPLAY_BELOW"])
if share:
while not networking.url_ok(share_url):
time.sleep(1)

View File

@ -1,9 +1,9 @@
"""
Ways to transform interfaces to produce new interfaces
"""
from gradio.interface import Interface
import gradio
class Parallel(Interface):
class Parallel(gradio.Interface):
"""
Creates a new Interface consisting of multiple models in parallel
Parameters:
@ -30,7 +30,7 @@ class Parallel(Interface):
super().__init__(**kwargs)
class Series(Interface):
class Series(gradio.Interface):
"""
Creates a new Interface from multiple models in series (the output of one is fed as the input to the next)
Parameters:

View File

@ -20,7 +20,6 @@ import requests
import sys
import csv
import logging
from gradio.embeddings import calculate_similarity, fit_pca_to_embeddings, transform_with_pca
from gradio.tunneling import create_tunnel
from gradio import encryptor
from gradio import queue
@ -208,66 +207,6 @@ def log_feature_analytics(feature):
pass # do not push analytics if no network
@app.route("/api/score_similarity/", methods=["POST"])
@login_check
def score_similarity():
raw_input = request.json["data"]
preprocessed_input = [input_interface.preprocess(raw_input[i])
for i, input_interface in enumerate(app.interface.input_components)]
input_embedding = app.interface.embed(preprocessed_input)
scores = list()
for example in app.interface.examples:
preprocessed_example = [iface.preprocess(iface.preprocess_example(example))
for iface, example in zip(app.interface.input_components, example)]
example_embedding = app.interface.embed(preprocessed_example)
scores.append(calculate_similarity(input_embedding, example_embedding))
log_feature_analytics('score_similarity')
return jsonify({"data": scores})
@app.route("/api/view_embeddings/", methods=["POST"])
@login_check
def view_embeddings():
sample_embedding = []
if "data" in request.json:
raw_input = request.json["data"]
preprocessed_input = [input_interface.preprocess(raw_input[i])
for i, input_interface in enumerate(app.interface.input_components)]
sample_embedding.append(app.interface.embed(preprocessed_input))
example_embeddings = []
for example in app.interface.examples:
preprocessed_example = [iface.preprocess(iface.preprocess_example(example))
for iface, example in zip(app.interface.input_components, example)]
example_embedding = app.interface.embed(preprocessed_example)
example_embeddings.append(example_embedding)
pca_model, embeddings_2d = fit_pca_to_embeddings(
sample_embedding + example_embeddings)
sample_embedding_2d = embeddings_2d[:len(sample_embedding)]
example_embeddings_2d = embeddings_2d[len(sample_embedding):]
app.pca_model = pca_model
log_feature_analytics('view_embeddings')
return jsonify({"sample_embedding_2d": sample_embedding_2d, "example_embeddings_2d": example_embeddings_2d})
@app.route("/api/update_embeddings/", methods=["POST"])
@login_check
def update_embeddings():
sample_embedding, sample_embedding_2d = [], []
if "data" in request.json:
raw_input = request.json["data"]
preprocessed_input = [input_interface.preprocess(raw_input[i])
for i, input_interface in enumerate(app.interface.input_components)]
sample_embedding.append(app.interface.embed(preprocessed_input))
sample_embedding_2d = transform_with_pca(
app.pca_model, sample_embedding)
return jsonify({"sample_embedding_2d": sample_embedding_2d})
def flag_data(input_data, output_data, flag_option=None, flag_index=None, username=None):
flag_path = os.path.join(app.cwd, app.interface.flagging_dir)
log_fp = "{}/log.csv".format(flag_path)

View File

@ -568,13 +568,6 @@ class Carousel(OutputComponent):
**super().get_template_context()
}
@classmethod
def get_shortcut_implementations(cls):
return {
"carousel": {},
}
def postprocess(self, y):
if isinstance(y, list):
if len(y) != 0 and not isinstance(y[0], list):
@ -605,9 +598,12 @@ def get_output_instance(iface):
return shortcut[0](**shortcut[1])
elif isinstance(iface, dict): # a dict with `name` as the output component type and other keys as parameters
name = iface.pop('name')
component, params = OutputComponent.get_all_shortcut_implementations()[name]
params.update(**iface)
return component(**params)
for component in OutputComponent.__subclasses__():
if component.__name__.lower() == name:
break
else:
raise ValueError("No such OutputComponent: {}".format(name))
return component(**iface)
elif isinstance(iface, OutputComponent):
return iface
else:

38
test/test_external.py Normal file
View File

@ -0,0 +1,38 @@
import unittest
import gradio as gr
class TestHuggingFaceModels(unittest.TestCase):
def test_gpt2(self):
interface_info = gr.external.get_huggingface_interface("gpt2", api_key=None, alias=None)
self.assertEqual(interface_info["fn"].__name__, "gpt2")
self.assertIsInstance(interface_info["inputs"], gr.inputs.Textbox)
self.assertIsInstance(interface_info["outputs"], gr.outputs.Textbox)
def test_distilbert_classification(self):
interface_info = gr.external.get_huggingface_interface("distilbert-base-uncased-finetuned-sst-2-english", api_key=None, alias="sentiment_classifier")
self.assertEqual(interface_info["fn"].__name__, "sentiment_classifier")
self.assertIsInstance(interface_info["inputs"], gr.inputs.Textbox)
self.assertIsInstance(interface_info["outputs"], gr.outputs.Label)
class TestHuggingFaceSpaces(unittest.TestCase):
def test_english_to_spanish(self):
interface_info = gr.external.get_spaces_interface("abidlabs/english_to_spanish", api_key=None, alias=None)
self.assertIsInstance(interface_info["inputs"][0], gr.inputs.Textbox)
self.assertIsInstance(interface_info["outputs"][0], gr.outputs.Textbox)
class TestLoadInterface(unittest.TestCase):
def test_english_to_spanish(self):
interface_info = gr.external.load_interface("spaces/abidlabs/english_to_spanish")
self.assertIsInstance(interface_info["inputs"][0], gr.inputs.Textbox)
self.assertIsInstance(interface_info["outputs"][0], gr.outputs.Textbox)
def test_distilbert_classification(self):
interface_info = gr.external.load_interface("distilbert-base-uncased-finetuned-sst-2-english", src="huggingface", alias="sentiment_classifier")
self.assertEqual(interface_info["fn"].__name__, "sentiment_classifier")
self.assertIsInstance(interface_info["inputs"], gr.inputs.Textbox)
self.assertIsInstance(interface_info["outputs"], gr.outputs.Label)
if __name__ == '__main__':
unittest.main()

View File

@ -1,3 +1,4 @@
from re import sub
import unittest
import gradio as gr
import PIL
@ -160,6 +161,11 @@ class TestSequential(unittest.TestCase):
iface = gr.Interface(get_last, "list", "text")
self.assertEqual(iface.process([x_data])[0], ["Sal"])
class TestNames(unittest.TestCase):
def test_no_duplicate_uncased_names(self): # this ensures that get_input_instance() works correctly when instantiating from components
subclasses = gr.inputs.InputComponent.__subclasses__()
unique_subclasses_uncased = set([s.__name__.lower() for s in subclasses])
self.assertEqual(len(subclasses), len(unique_subclasses_uncased))
if __name__ == '__main__':
unittest.main()

View File

@ -188,6 +188,11 @@ class TestDataframe(unittest.TestCase):
iface.process([[2, 3, 4]])[0][0],
{"data": [[True, False, True]]})
class TestNames(unittest.TestCase):
def test_no_duplicate_uncased_names(self): # this ensures that get_input_instance() works correctly when instantiating from components
subclasses = gr.outputs.OutputComponent.__subclasses__()
unique_subclasses_uncased = set([s.__name__.lower() for s in subclasses])
self.assertEqual(len(subclasses), len(unique_subclasses_uncased))
if __name__ == '__main__':
unittest.main()