mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-18 10:44:33 +08:00
Merge branch 'master' of https://github.com/gradio-app/gradio
This commit is contained in:
commit
5b0bdf4171
@ -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
2
.gitignore
vendored
@ -7,6 +7,8 @@ gradio.egg-info/*
|
||||
*.pyc
|
||||
staticfiles
|
||||
.env
|
||||
.coverage
|
||||
coverage.xml
|
||||
*.sqlite3
|
||||
.idea/*
|
||||
*.ipynb
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()]
|
@ -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,
|
||||
}
|
||||
|
||||
|
125
gradio/inputs.py
125
gradio/inputs.py
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
38
test/test_external.py
Normal 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()
|
@ -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()
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user