Open abidlabs opened 1 year ago
Came up during https://github.com/gradio-app/gradio/issues/3271
Let's add a gist for how to have examples with updating samples
import gradio as gr
import random
samples = [["What is your name?"], ["Where are you from?"]]
def get_new_examples():
if random.random() > 0.5:
return [["What is your favorite food?"], ["How old are you?"]]
else:
return [["Where do you live?"]]
def update_examples():
global samples
samples = get_new_examples()
return gr.Dataset.update(samples=samples)
def print_samples():
global samples
return {"samples": samples}
def load_example(example_id):
global samples
return samples[example_id][0]
with gr.Blocks() as demo:
with gr.Row():
with gr.Column():
question = gr.Textbox(label="question")
examples = gr.Dataset(samples=samples, components=[question], type="index")
generate = gr.Button(value="Generate examples")
with gr.Column():
global_state = gr.JSON(value={"samples": samples}, label="global variable")
examples.click(load_example, inputs=[examples], outputs=[question])
generate.click(update_examples, inputs=None, outputs=[examples])
generate.click(print_samples, inputs=None, outputs=[global_state])
demo.launch()
Also, so we don't forget, here are the other three gists we have created so far
https://twitter.com/search?q=%23gradiogist&src=typed_query
Edit: Fixed problem below changing lambda x:x
to lambda x:x[0]
to extract the filepath out of the filepath in a list.
Is there an example for images? I am getting stuck on passing image from dataset click to another image component like how Interface examples parameter allows it.
Image has various types (filepath,numpy,PIL) and i suspect the types in my pipeline are not matching and I don't know how the conversion is happening behind the scenes, which part I have to do myself, which parts I can let gradio do by specifying the type, and which parts I can let gradio infer without even specify type parameter.
My Dataset has samples being a list of list of filepaths.
I try dataset.click(lambda x:x,inputs=dataset,outputs=image_component)
but get ValueError: Cannot process this value as an Image
. I tried setting image_component
to both filepaths (trying to make it work to receive dataset clicks) and PIL types (original working type for prediction before i tried to integrate dataset) but both don't work.
When image_component
is pil type, my debugger inline debug values shows y =['filepath.jpg']
in section below
def postprocess(
self, y: np.ndarray | _Image.Image | str | Path | None
) -> str | None:
"""
Parameters:
y: image as a numpy array, PIL Image, string/Path filepath, or string URL
Returns:
base64 url data
"""
if y is None:
return None
if isinstance(y, np.ndarray):
return processing_utils.encode_array_to_base64(y)
elif isinstance(y, _Image.Image):
return processing_utils.encode_pil_to_base64(y)
elif isinstance(y, (str, Path)):
return processing_utils.encode_url_or_file_to_base64(y)
else:
raise ValueError("Cannot process this value as an Image")
The convenience of gradio also what makes it hard to understand what types of data to provide in each parameter to make a data flow chain work. For example, Dataset docs component parameter shows List[IOComponent] | List[str]
but I can't search what is an IOComponent
.
Currently the docs show examples, but don't explain enough the Blocks API building process, though some parts like event listener types exist. The examples still require beginners significant effort to parse through if they don't have a mental model of how things work.
Personally I had difficulty finding answers to
def mirror_to_preview(*idx_and_list_of_images)
and does the hard work parsing instead of the more natural def mirror_to_preview(idx, list_of_images)
.gradio.XXX.style(···)
I'm hoping for 2 types of pages in the docs so users can reason for themselves for all components and event listeners.
Thinking process on building a dataflow and where to place them to keep code organized
Ways to shoot yourself when you use wrong types and error messages that follow (so users can look at errors and infer the cause, then read other docs to fix)
field1.change(fn=func, inputs=field1, outputs=field2)
field2.change(fn=func, inputs=field2, outputs=field3)
field3.change(fn=func, inputs=field3, outputs=field1)
The problem with this is : you get session conflicts.
An example of this can be seen here:
Description of the image: I have just pressed "Generate examples" on the right hand side. That works.
However on the left hand side, when pressing "What's your favorite food" you now also get "Where do live?" copied into the text box. That - I think - is clearly undesirable bahaviour for most use cases.
Hopefully there is a fix for this.
I believe the problem is solved if instead of using global samples, one puts the sample into Gradio State:
This works for me:
import random
import gradio as gr
def get_new_examples():
x = random.random()
if x > 0.5:
return [["What is your favorite food?"], ["How old are you?"], [f"{x}"]]
else:
return [["Where do you live?"], [f"{x}"]]
def update_examples(customer_examples_var):
samples = get_new_examples()
customer_examples_var = gr.State([samples])
try:
samples = customer_examples_var.constructor_args["value"][0]
print("abcd")
except:
samples = customer_examples_var[0]
print("efgh")
return {"samples": samples}, customer_examples_var, gr.Dataset(samples=samples)
def load_example(example_id, customer_examples_var):
try:
samples = customer_examples_var.constructor_args["value"][0]
print(1234)
except:
samples = customer_examples_var[0]
print(5678)
return samples[example_id][0], customer_examples_var
with gr.Blocks() as demo:
samples = [["What is your name?"], ["Where are you from?"]]
customer_examples_var = gr.State([samples])
with gr.Row():
with gr.Column():
question = gr.Textbox(label="question")
examples = gr.Dataset(samples=samples, components=[question], type="index")
generate = gr.Button(value="Generate examples")
with gr.Column():
global_state = gr.JSON(
value={"samples": customer_examples_var}, label="global variable"
)
examples.click(
load_example,
inputs=[examples, customer_examples_var],
outputs=[question, customer_examples_var],
)
generate.click(
update_examples,
inputs=[customer_examples_var],
outputs=[global_state, customer_examples_var, examples],
)
demo.launch()
This is a silghtly simplified version:
import random
import gradio as gr
def _extract_samples(customer_examples_var):
samples = customer_examples_var[0]
return samples
def get_new_examples():
x = random.random()
if x > 0.5:
return [["What is your favorite food?"], ["How old are you?"], [f"{x}"]]
else:
return [["Where do you live?"], [f"{x}"]]
def update_examples(customer_examples_var):
samples = get_new_examples()
customer_examples_var[0] = samples
return {"samples": samples}, customer_examples_var, gr.Dataset(samples=samples)
def load_example(example_id, customer_examples_var):
samples = _extract_samples(customer_examples_var)
return samples[example_id][0], customer_examples_var
with gr.Blocks() as demo:
samples = get_new_examples()
customer_examples_var = gr.State([samples])
with gr.Row():
with gr.Column():
question = gr.Textbox(label="question")
examples = gr.Dataset(samples=samples, components=[question], type="index")
generate = gr.Button(value="Generate examples")
with gr.Column():
global_state = gr.JSON(value={"samples": samples}, label="global variable")
examples.click(
load_example,
inputs=[examples, customer_examples_var],
outputs=[question, customer_examples_var],
)
generate.click(
update_examples,
inputs=[customer_examples_var],
outputs=[global_state, customer_examples_var, examples],
)
demo.launch()
We have been releasing occasional code snippets with the hastag #GradioGist on Twitter. This information could be useful to developers browsing the Gradio docs. We could add a section underneath the Guides called #GradioGists, where they would appear to developers who are searching the Guides
In addition to making them searchable (like the Guides), we may also want to structure them in a Q&A format, so that they index better on search engines where developers might ask these questions.