Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exposing examples as a component for Blocks #1639

Merged
merged 26 commits into from
Jul 6, 2022
Merged

Exposing examples as a component for Blocks #1639

merged 26 commits into from
Jul 6, 2022

Conversation

abidlabs
Copy link
Member

@abidlabs abidlabs commented Jun 26, 2022

We now have gr.Examples() as a component that can be used within Blocks. See example: demo\blocks_inputs\run.py

Usage:

  • Case 1: Only inputs is provided, in which case clicking on the examples will populate the inputs components
with blocks:
....
    with gr.Row() 
        textbox = gr.Textbox()
        examples = gr.Examples(examples=examples, inputs=textbox)
        ....

    button.click(predict, textbox, label)
....
  • Case 2: Both inputs and outputs as well as the prediction fn is provided (required for cache_examples=True), in which case, if the examples are cached, clicking on the examples will populate the inputs components and the output components.
with blocks:
....
    with gr.Row() 
        textbox = gr.Textbox()
        examples = gr.Examples(examples=examples, inputs=textbox, outputs=label, fn=predict, cache_examples=True)
        ....

    button.click(predict, textbox, label)
....

This approach is more wordy than the one proposed by @radames in #1156 but I think more logical since it ties the examples clearly to the input (and potentially the output components). Open to feedback here.

Original API proposed by @radames:

with blocks:
....
    with gr.Row() 
        examples = gr.Examples(examples=examples, cache_examples=False)

    button.click(predict, inputs, outputs, examples)
....
  • Problem: in this approach, what would happen if multiple event triggers are passed the same examples?

Closes: #1156

Note: This PR also does a lot of other cleanups in the Interface class. A lot of the bloat is removed because we now only accept single functions in the fn parameter of Interface. I've tested a bunch of demos and they work fine, but would appreciate a careful review to make sure I didn't miss anything!

@abidlabs abidlabs requested a review from radames July 1, 2022 04:51
@abidlabs abidlabs requested a review from aliabid94 July 1, 2022 19:20
@radames radames marked this pull request as ready for review July 1, 2022 21:39
@radames
Copy link
Contributor

radames commented Jul 1, 2022

hi @abidlabs ,

Your proposal approach looks good to me. It's also enables users to create multiple examples for different predict functions on the same screen, right? For example, this Space has two sections, and would benefit of separated examples for each step.

with blocks:
....
    with gr.Row() 
        textbox = gr.Textbox()
        outbox =  gr.Textbox()
        examples = gr.Examples(examples=examples, inputs=textbox, outputs=outbox, fn=predict, cache_examples=True)
        ....
    with gr.Row() 
        data = gr.DataFrame()
        examples2 = gr.Examples(examples=examples2, inputs=outbox, outputs=data, fn=predict2, cache_examples=True)
        ....

    button.click(predict, textbox, label)
.... 

@abidlabs abidlabs marked this pull request as draft July 4, 2022 14:24
@abidlabs abidlabs changed the title Exposing examples as a component for Blocks [WIP] Exposing examples as a component for Blocks Jul 4, 2022
@abidlabs
Copy link
Member Author

abidlabs commented Jul 4, 2022

Yes, that is now possible @radames. See example here: demo\blocks_inputs\run.py

@abidlabs abidlabs marked this pull request as ready for review July 4, 2022 21:43
Copy link
Collaborator

@freddyaboulton freddyaboulton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abidlabs This is awesome! Taking a closer look now but one thing that stood out to me is that we're giving lots of power to the user and that increases the chance of misusing examples. I wonder if we should invest some time in making sure incorrect combinations of parameters are caught and informative error messages are displayed.

For example,

  • when you set cache_examples to True but don't provide a fn you get a TypeError: 'NoneType' object is not callable error.
    gr.Examples(
        examples=[os.path.join(os.path.dirname(__file__), "lion.jpg")],
        inputs=im,
        outputs=im_2,
        cache_examples=True)
  • when you provide inputs, fn but not outputs and cache_examples is True:
    gr.Examples(
        examples=[os.path.join(os.path.dirname(__file__), "lion.jpg")],
        inputs=im,
        fn=mirror,
        cache_examples=True)
  • If the size of the examples list doesn't match the api of the fn you get a IndexError: list index out of range
    gr.Examples([["hi"], ["hello", "Eve"]], [txt, txt_2], txt_3, combine, cache_examples=True)
  • There's a weird bug when examples is None that I commented below.

Some of these may be rare cases and not worth catching in the library but some may be worth guiding the user on. Curious what your thoughts on the matter are.

gradio/examples.py Outdated Show resolved Hide resolved
gradio/examples.py Outdated Show resolved Hide resolved
self.cache_interface_examples()

def load_example(example_id):
processed_examples = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The examples don't change during the lifetime of the app. I think we can compute processed_examples once and avoid a bunch of repetitive work?

gradio/mix.py Outdated Show resolved Hide resolved
@abidlabs
Copy link
Member Author

abidlabs commented Jul 5, 2022

This is awesome @freddyaboulton! Agree with you about catching and throwing errors. Will add those in and fix up Series.

@abidlabs
Copy link
Member Author

abidlabs commented Jul 5, 2022

Series should be fixed now, thanks for the suggestion @freddyaboulton!

Copy link
Collaborator

@freddyaboulton freddyaboulton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abidlabs Thank you for making the changes! This looks good to me. Just a minor comment on the parameter validation logic you added.

"list, where each sublist represents a set of inputs."
)

if cache_examples and (fn is None or outputs is None):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't work as expected since outputs gets wrapped into a list so passing None will get converted to [None] which is not None. I think we should move this up to before outputs gets wrapped into a list or change the check to outputs[0] is None.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good catch thanks!

@abidlabs abidlabs merged commit a1c3916 into main Jul 6, 2022
@abidlabs abidlabs deleted the examples branch July 6, 2022 18:23
@abidlabs
Copy link
Member Author

abidlabs commented Jul 6, 2022

Thanks for the thorough feedback @freddyaboulton!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Blocks] Expose Examples as Block Component
3 participants