Add a guide on how to use apps like functions (#1799)

* Add examples for series and parallel

* Create demo + guide

* More formatting

* Change name of guide

* Fix typo

* Use english to german as example instead

* Expand phrase a bit
This commit is contained in:
Freddy Boulton 2022-07-19 17:43:53 -04:00 committed by GitHub
parent 106934fe70
commit 3f9ec2c345
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 144 additions and 15 deletions

View File

@ -0,0 +1,25 @@
import gradio as gr
from transformers import pipeline
pipe = pipeline("translation", model="t5-base")
def translate(text):
return pipe(text)[0]["translation_text"]
with gr.Blocks() as demo:
with gr.Row():
with gr.Column():
english = gr.Textbox(label="English text")
translate_btn = gr.Button(value="Translate")
with gr.Column():
german = gr.Textbox(label="German Text")
translate_btn.click(translate, inputs=english, outputs=german)
examples = gr.Examples(examples=["I went to the supermarket yesterday.", "Helen is a good swimmer."],
inputs=[english])
if __name__ == "__main__":
demo.launch()

View File

@ -0,0 +1,27 @@
import gradio as gr
from transformers import pipeline
english_translator = gr.Blocks.load(name="spaces/freddyaboulton/english-translator")
english_generator = pipeline("text-generation", model="distilgpt2")
def generate_text(text):
english_text = english_generator(text)[0]["generated_text"]
german_text = english_translator(english_text)
return english_text, german_text
with gr.Blocks() as demo:
with gr.Row():
with gr.Column():
seed = gr.Text(label="Input Phrase")
with gr.Column():
english = gr.Text(label="Generated English Text")
german = gr.Text(label="Generated German Text")
btn = gr.Button("Generate")
btn.click(generate_text, inputs=[seed], outputs=[english, german])
gr.Examples(["My name is Clara and I am"], inputs=[seed])
if __name__ == "__main__":
demo.launch()

View File

@ -230,7 +230,7 @@ def skip() -> dict:
return update()
@document()
@document("load")
class Blocks(BlockContext):
"""
Blocks is Gradio's low-level API that allows you to create more custom web
@ -262,7 +262,7 @@ class Blocks(BlockContext):
btn.click(fn=update, inputs=inp, outputs=out)
demo.launch()
Demos: blocks_hello, blocks_flipper, blocks_speech_text_length
Demos: blocks_hello, blocks_flipper, blocks_speech_text_length, generate_english_german
"""
def __init__(
@ -686,21 +686,19 @@ class Blocks(BlockContext):
For reverse compatibility reasons, this is both a class method and an instance
method, the two of which, confusingly, do two completely different things.
Class method: loads a demo from a Hugging Face Spaces repo and creates it locally
Parameters:
name (str): the name of the model (e.g. "gpt2"), can include the `src` as prefix (e.g. "models/gpt2")
src (str | None): the source of the model: `models` or `spaces` (or empty if source is provided as a prefix in `name`)
api_key (str | None): optional api key for use with Hugging Face Hub
alias (str | None): optional string used as the name of the loaded model instead of the default name
type (str): the type of the Blocks, either a standard `blocks` or `column`
Returns: Blocks instance
Instance method: adds an event for when the demo loads in the browser.
Class method: loads a demo from a Hugging Face Spaces repo and creates it locally and returns a block instance.
Instance method: adds an event for when the demo loads in the browser and returns None.
Parameters:
fn: Callable function
inputs: input list
outputs: output list
Returns: None
name: Class Method - the name of the model (e.g. "gpt2"), can include the `src` as prefix (e.g. "models/gpt2")
src: Class Method - the source of the model: `models` or `spaces` (or empty if source is provided as a prefix in `name`)
api_key: Class Method - optional api key for use with Hugging Face Hub
alias: Class Method - optional string used as the name of the loaded model instead of the default name
fn: Instance Method - Callable function
inputs: Instance Method - input list
outputs: Instance Method - output list
"""
if isinstance(self_or_cls, type):
if name is None:

View File

@ -0,0 +1,77 @@
<script type="module" src="https://gradio.s3-us-west-2.amazonaws.com/3.0.24/gradio.js"></script>
# Using Gradio Blocks Like Functions
Tags: TRANSLATION, HUB, SPACES
Docs: Blocks
**Prerequisite**: This Guide builds on the Blocks Introduction. Make sure to [read that guide first](/introduction_to_blocks).
## Introduction
Did you know that apart from being a full-stack machine learning demo, a Gradio Blocks app is also a regular-old python function!?
This means that if you have a gradio Blocks (or Interface) app called `demo`, you can use `demo` like you would any python function.
So doing something like `output = demo("Hello", "friend")` will run the first event defined in `demo` on the inputs "Hello" and "friend" and store it
in the variable `output`.
If I put you to sleep 🥱, please bear with me! By using apps like functions, you can seamlessly compose Gradio apps.
The following section will show how.
## Treating spaces like functions
Let's say we have the following demo that translates english text to german text.
$code_english_translator
I already went ahead and hosted it in Hugging Face spaces at [freddyaboulton/english-to-german](https://huggingface.co/spaces/freddyaboulton/english-to-german).
You can see the demo below as well:
<gradio-app space="freddyaboulton/english-to-german"> </gradio-app>
Now, let's say you have an app that generates english text, but you wanted to additionally generate german text.
You could either:
1. Copy the source code of my english-to-german translation and paste it in your app.
2. Load my english-to-german translation in your app and treat it like a normal python function.
Option 1 technically always works, but it often introduces unwanted complexity.
Option 2 lets you borrow the functionality you want without tightly coupling our apps.
All you have to do is call the `Blocks.load` class method in your source file.
After that, you can use my translation app like a regular python function!
The following code snippet and demo shows how to use `Blocks.load`.
Note that the variable `english_translator` is my english to german app, but its used in `generate_text` like a regular function.
$code_generate_english_german
<gradio-app space="freddyaboulton/generate-english-german"> </gradio-app>
## How to control which function in the app to use
If the app you are loading defines more than one function, you can specify which function to use with the `fn_index` parameter.
Imagine my app also defined an english to spanish translation function. In order to use it in our text generation app,
we would use the following code:
```python
english_generator(text, fn_index=1)[0]["generated_text"]
```
Functions in gradio spaces are zero-indexed, so since the spanish translator would be the second function in my space,
you would use index 1.
## Parting Remarks
We showed how treating a Blocks app like a regular python helps you compose functionality across different apps.
Any Blocks app can be treated like a function, but a powerful pattern is to `load` an app hosted on
[Hugging Face Spaces](https://huggingface.co/spaces) prior to treating it like a function in your own app.
You can also load models hosted on the [Hugging Face Model Hub](https://huggingface.co/models) - see the [Using Hugging Face Integrations](/using_hugging_face_integrations) guide for an example.
### Happy building! ⚒️

View File

@ -112,6 +112,8 @@ The code above generates the following demo.
As you can see, the demo looks the same, but it uses a webcam input instead of user-uploaded images.
You can learn more about this feature, and how to use it with the new Blocks API in the [Using Gradio Blocks Like Functions guide](/using_blocks_like_functions)
## Using multiple Spaces
Sometimes a single model inference will not be enough: you might want to call multiple models by piping them (using the output of model A as the input of model B). `Series` can achieve this. Other times, you might want to run two models in parallel to compare them. `Parallel` can do this!