mirror of
https://github.com/gradio-app/gradio.git
synced 2024-11-27 01:40:20 +08:00
Call fn by api_name when using Blocks.load (#2593)
* Updated implementation + test * Add changelog * Fix unit test
This commit is contained in:
parent
fa08e711fa
commit
4a51cec5b4
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,7 +1,20 @@
|
||||
# Upcoming Release
|
||||
|
||||
## New Features:
|
||||
No changes to highlight.
|
||||
|
||||
### Calling functions by api_name in loaded apps
|
||||
|
||||
When you load an upstream app with `gr.Blocks.load`, you can now specify which fn
|
||||
to call with the `api_name` parameter.
|
||||
|
||||
```python
|
||||
import gradio as gr
|
||||
english_translator = gr.Blocks.load(name="spaces/gradio/english-translator")
|
||||
german = english_translator("My name is Freddy", api_name='translate-to-german')
|
||||
```
|
||||
|
||||
The `api_name` parameter will take precendence over the `fn_index` parameter.
|
||||
|
||||
|
||||
## Bug Fixes:
|
||||
* Fixed bug where None could not be used for File,Model3D, and Audio examples by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2588](https://github.com/gradio-app/gradio/pull/2588)
|
||||
@ -17,7 +30,7 @@ No changes to highlight.
|
||||
No changes to highlight.
|
||||
|
||||
## Full Changelog:
|
||||
No changes to highlight.
|
||||
* Add `api_name` to `Blocks.__call__` by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2593](https://github.com/gradio-app/gradio/pull/2593)
|
||||
|
||||
## Contributors Shoutout:
|
||||
No changes to highlight.
|
||||
|
@ -17,7 +17,7 @@ with gr.Blocks() as demo:
|
||||
with gr.Column():
|
||||
german = gr.Textbox(label="German Text")
|
||||
|
||||
translate_btn.click(translate, inputs=english, outputs=german)
|
||||
translate_btn.click(translate, inputs=english, outputs=german, api_name="translate-to-german")
|
||||
examples = gr.Examples(examples=["I went to the supermarket yesterday.", "Helen is a good swimmer."],
|
||||
inputs=[english])
|
||||
|
||||
|
@ -2,7 +2,7 @@ import gradio as gr
|
||||
|
||||
from transformers import pipeline
|
||||
|
||||
english_translator = gr.Blocks.load(name="spaces/freddyaboulton/english-translator")
|
||||
english_translator = gr.Blocks.load(name="spaces/gradio/english-translator")
|
||||
english_generator = pipeline("text-generation", model="distilgpt2")
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@ from gradio.documentation import (
|
||||
document_component_api,
|
||||
set_documentation_group,
|
||||
)
|
||||
from gradio.exceptions import DuplicateBlockError
|
||||
from gradio.exceptions import DuplicateBlockError, InvalidApiName
|
||||
from gradio.utils import (
|
||||
check_function_inputs_match,
|
||||
component_or_layout_class,
|
||||
@ -734,7 +734,7 @@ class Blocks(BlockContext):
|
||||
|
||||
return True
|
||||
|
||||
def __call__(self, *inputs, fn_index: int = 0):
|
||||
def __call__(self, *inputs, fn_index: int = 0, api_name: str = None):
|
||||
"""
|
||||
Allows Blocks objects to be called as functions. Supply the parameters to the
|
||||
function as positional arguments. To choose which function to call, use the
|
||||
@ -743,7 +743,19 @@ class Blocks(BlockContext):
|
||||
Parameters:
|
||||
*inputs: the parameters to pass to the function
|
||||
fn_index: the index of the function to call (defaults to 0, which for Interfaces, is the default prediction function)
|
||||
api_name: The api_name of the dependency to call. Will take precedence over fn_index.
|
||||
"""
|
||||
if api_name is not None:
|
||||
fn_index = next(
|
||||
(
|
||||
i
|
||||
for i, d in enumerate(self.dependencies)
|
||||
if d.get("api_name") == api_name
|
||||
),
|
||||
None,
|
||||
)
|
||||
if fn_index is None:
|
||||
raise InvalidApiName(f"Cannot find a function with api_name {api_name}")
|
||||
if not (self.is_callable(fn_index)):
|
||||
raise ValueError(
|
||||
"This function is not callable because it is either stateful or is a generator. Please use the .launch() method instead to create an interactive user interface."
|
||||
|
@ -10,6 +10,10 @@ class TooManyRequestsError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidApiName(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message: str):
|
||||
self.message = message
|
||||
|
@ -25,7 +25,7 @@ $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>
|
||||
<gradio-app space="gradio/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.
|
||||
|
||||
@ -48,13 +48,29 @@ Note that the variable `english_translator` is my english to german app, but its
|
||||
|
||||
$code_generate_english_german
|
||||
|
||||
<gradio-app space="freddyaboulton/generate-english-german"> </gradio-app>
|
||||
<gradio-app space="gradio/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:
|
||||
If the app you are loading defines more than one function, you can specify which function to use
|
||||
with the `fn_index` and `api_name` parameters.
|
||||
|
||||
In the code for our english to german demo, you'll see the following line:
|
||||
|
||||
```python
|
||||
translate_btn.click(translate, inputs=english, outputs=german, api_name="translate-to-german")
|
||||
```
|
||||
|
||||
The `api_name` gives this function a unique name in our app. You can use this name to tell gradio which
|
||||
function in the upstream space you want to use:
|
||||
|
||||
```python
|
||||
english_generator(text, api_name="translate-to-german")[0]["generated_text"]
|
||||
```
|
||||
|
||||
You can also use 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"]
|
||||
|
@ -11,6 +11,7 @@ import pytest
|
||||
import gradio
|
||||
import gradio as gr
|
||||
from gradio import utils
|
||||
from gradio.exceptions import InvalidApiName
|
||||
from gradio.external import (
|
||||
TooManyRequestsError,
|
||||
cols_to_rows,
|
||||
@ -417,5 +418,22 @@ def test_respect_queue_when_load_from_config():
|
||||
assert interface("bob") == "foo"
|
||||
|
||||
|
||||
def test_raise_value_error_when_api_name_invalid():
|
||||
with pytest.raises(InvalidApiName):
|
||||
demo = gr.Blocks.load(name="spaces/gradio/hello_world")
|
||||
demo("freddy", api_name="route does not exist")
|
||||
|
||||
|
||||
def test_use_api_name_in_call_method():
|
||||
# Interface
|
||||
demo = gr.Blocks.load(name="spaces/gradio/hello_world")
|
||||
assert demo("freddy", api_name="predict") == "Hello freddy!"
|
||||
|
||||
# Blocks demo with multiple functions
|
||||
app = gr.Blocks.load(name="spaces/gradio/multiple-api-name-test")
|
||||
assert app(15, api_name="minus_one") == 14
|
||||
assert app(4, api_name="double") == 8
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user