Closed vzakharov closed 2 years ago
Hi @vzakharov thanks for the suggestion! cc @aliabid94 with regards to updating the Blocks API..
Just realized kwargs would make no sense (as how would you be able which key corresponds to which component?). A better way would be to pass a dict (perhaps named as _inputs), where keys are components themselves (and not just strings).
Looking into this!
I feel like being able to pass the input and output for events as dicts would be a game-changer for Gradio. Having to maintain an ever-changing and possibly amended list is.. cumbersome.
Just realized kwargs would make no sense (as how would you be able which key corresponds to which component?). A better way would be to pass a dict (perhaps named as _inputs), where keys are components themselves (and not just strings).
Can you elaborate on this? I'm trying to understand why you'd want to use the components as keys rather than a string set in the component, e.g. label, or a dedicated ID parameter.
I find using the components as keys very cumbersome, as it means the components have to be in scope for the event handler, more tightly coupling the event handlers to the interface. With string keys, the event handlers become plain functions which can be called anywhere with no knowledge of gradio, and the interface of the event handler can be more explicitly defined with keyword arguments.
According to: https://www.gradio.app/guides/blocks-and-event-listeners#function-return-list-vs-dict
Components as keys is trouble, I can't define the event function in another file
Look like event listener cannot bind outside with gr.Blocks
:
AttributeError: Cannot call xxxxxx outside of a gradio.Blocks context.
I tried pass components with State
, but it will give me error:
TypeError: The initial value of `gr.State` must be able to be deepcopied. The initial value of type <class 'dict'> cannot be deepcopied.
One possible workaround is manually call __enter__
and __exit__
on gr.Blocks
instead of using with
statement
Construct the block in middle and bind the event listener later
Updated:
My purpose is to partial update the value or status of component
https://www.gradio.app/guides/blocks-and-event-listeners#running-events-consecutively
I find it useful to Running Events Consecutively, don't use a dict for output, all functions return
or yield
using list, and split the event function with .then()
or .success()
Now I can have some function that only update the message, and don't mixed with other process:
def update_message():
return gr.Markdown("...")
<component>.<event>(
<func1>,
...
).success(
update_message,
outputs=[<text_component>]
).success(
<func2>,
...
)
Is your feature request related to a problem? Please describe.
When writing an event handler, I don’t always know in advance what kind of inputs it will need. For example, when generating music with OpenAI Jukebox, you need to obviously need to take “generation length” as an input, but you might also add other parameters down the line (artist name, lyrics, etc.)
Currently I have to add them one by one in a specific order and remember/follow that order throughout coding.
Describe the solution you'd like
It would be much easier if I just could pass a dict containing any parameters I might need as **kwargs to the event handler.
Additional context
As you’ve already implemented a similar approach for outputs (which can be returned as a dict rather than a list), it sounds like it would make sense to make the same possible for event handler arguments?