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

Allows updating the dataset of a gr.Examples #8745

Merged
merged 45 commits into from
Jul 15, 2024
Merged

Allows updating the dataset of a gr.Examples #8745

merged 45 commits into from
Jul 15, 2024

Conversation

abidlabs
Copy link
Member

@abidlabs abidlabs commented Jul 11, 2024

Allows modifying the samples of a .dataset of a gr.Examples, adds an example in the docs

import gradio as gr

def update_examples(country):
    if country == "USA":
        return gr.Dataset(samples=[["Chicago"], ["Little Rock"], ["San Francisco"]])
    else:
        return gr.Dataset(samples=[["Islamabad"], ["Karachi"], ["Lahore"]])

with gr.Blocks() as demo:
    dropdown = gr.Dropdown(label="Country", choices=["USA", "Pakistan"], value="USA")
    textbox = gr.Textbox()
    examples = gr.Examples([["Chicago"], ["Little Rock"], ["San Francisco"]], textbox)
    dropdown.change(update_examples, dropdown, examples.dataset)
    
demo.launch()

Closes: #5042
Closes: #8325

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Jul 11, 2024

🪼 branch checks and previews

Name Status URL
Spaces ready! Spaces preview
Website ready! Website preview
Storybook ready! Storybook preview
🦄 Changes detected! Details

Install Gradio from this PR

pip install https://gradio-builds.s3.amazonaws.com/841609e09800025ab90da92e5fc4ab5c51f4d346/gradio-4.38.1-py3-none-any.whl

Install Gradio Python Client from this PR

pip install "gradio-client @ git+https://github.com/gradio-app/gradio@841609e09800025ab90da92e5fc4ab5c51f4d346#subdirectory=client/python"

Install Gradio JS Client from this PR

npm install https://gradio-builds.s3.amazonaws.com/841609e09800025ab90da92e5fc4ab5c51f4d346/gradio-client-1.3.0.tgz

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Jul 11, 2024

🦄 change detected

This Pull Request includes changes to the following packages.

Package Version
@gradio/dataframe minor
gradio minor
website minor
  • Maintainers can select this checkbox to manually select packages to update.

With the following changelog entry.

Allows updating the dataset of a gr.Examples

Maintainers or the PR author can modify the PR title to modify this entry.

Something isn't right?

  • Maintainers can change the version label to modify the version bump.
  • If the bot has failed to detect any changes, or if this pull request needs to update multiple packages to different versions or requires a more comprehensive changelog entry, maintainers can update the changelog file directly.

@abidlabs abidlabs added the v: patch A change that requires a patch release label Jul 11, 2024
@abidlabs abidlabs marked this pull request as ready for review July 11, 2024 15:26
@freddyaboulton
Copy link
Collaborator

@abidlabs I tried the following demo and ran into the following issues

  • caching examples does not work. Clicking on anything but the first example raises an error. Something like ValueError: [[[1, 2, 4, 1, 7, 5, 6, 0, 7, 5], [7, 2, 6, 0, 0, 2, 2, 1, 6, 2], [1, 6, 8, 7, 9, 1, 5, 1, 5, 5], [9, 9, 8, 3, 0, 1, 8, 8, 5, 4], [3, 9, 8, 8, 7, 7, 5, 3, 0, 7]]] is not in list

  • If I set cache_examples=False, updating the examples via the button does not work as expected. The example preview does not update (uses the original example preview) but if I click on the example the right value gets shown in the UI

ort numpy as np

import gradio as gr


def transpose(matrix):
    return matrix.T


with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            input_matrix = gr.Dataframe(type="numpy", datatype="number", row_count=5, col_count=3)
        with gr.Column():
            output_matrix = gr.Dataframe(type="numpy", datatype="number", row_count=3, col_count=5)
    button = gr.Button("Transpose")
    button.click(transpose, input_matrix, output_matrix)
    dataset = gr.Examples(fn=transpose,
                          examples=[[np.random.randint(0, 10, (3, 10)).tolist()],
                                    [np.random.randint(0, 10, (10, 3)).tolist()],
                                    [np.random.randint(0, 10, (10, 10)).tolist()]],
                          inputs=input_matrix,
                          outputs=output_matrix,
                          cache_examples=False)
    update_examples = gr.Button("Update Examples")
    update_examples.click(lambda: gr.Dataset(samples=[
        [np.zeros((3, 3)).tolist()],
        [np.ones((2, 2)).tolist()]]), None, [dataset.dataset])


if __name__ == "__main__":
    demo.launch()

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

Thanks @freddyaboulton for catching these issues, will debug

@abidlabs abidlabs added v: minor A change that requires a minor release and removed v: patch A change that requires a patch release labels Jul 11, 2024
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 Thanks for making the fixes! I'm running into two issues and maybe it's the same underlying issue but have not figured it out yet.

The first - the examples preview still is not updating for me in the matrix transpose demo I linked above.

The second - having trouble updating an examples dataset of images. Right now, I'm getting ValueError: Cannot process this value as an Image, it is of type: <class 'dict'> but even if we fix that issue, I'm worried that files will not be moved to the cache since the init logic does not run if a component is returned from an event listener?

The demo for the second point

import gradio as gr
import os


def image_mod(image):
    return image.rotate(45)

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            image = gr.Image(type="pil")
        with gr.Column():
            output_image = gr.Image()
    submit = gr.Button("Submit")
    submit.click(image_mod, [image], [output_image])
    examples = gr.Examples(examples=[os.path.join(os.path.dirname(__file__), "images/cheetah1.jpg"),
        os.path.join(os.path.dirname(__file__), "images/lion.jpg")],
        inputs=[image], outputs=[output_image], fn=image_mod)

    update = gr.Button("Update Examples")
    update.click(lambda: gr.Dataset(samples=[[os.path.join(os.path.dirname(__file__), "images/logo.png")],
                                             [os.path.join(os.path.dirname(__file__), "images/tower.jpg")]],
                                    components=[image]),
                None, [examples.dataset])

demo.launch()

(just a variation of the image_mod demo)

gradio/utils.py Outdated
def _is_equal(self, key1, key2):
try:
comparison = key1 == key2
if comparison in [True, False]:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe utils.deep_equal also works here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea!

gradio/components/dataset.py Show resolved Hide resolved
@abidlabs
Copy link
Member Author

Oof I'll take a look, thanks for reviewing again @freddyaboulton!

@abidlabs
Copy link
Member Author

The first - the examples preview still is not updating for me in the matrix transpose demo I linked above.

Whoops sorry forgot to push a file. You'll need to rebuild the frontend since the issue was with js/dataframe/Example.svelte

@@ -5,8 +5,7 @@
export let index: number;

let hovered = false;
let loaded_value: (string | number)[][] | string = value;
let loaded = Array.isArray(loaded_value);
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure why we added loaded_value. It has no effect except to make value non-reactive -- i.e. updating value won't update the component. The original PR suggests that this was needed to show dataframe examples correctly when they are file names, however, this is not needed as can be confirmed with a simple example:

import gradio as gr
import numpy as np

data = np.random.random((100,5))
np.savetxt('test.csv', data, fmt = '%.2f', delimiter=',', header = 'c1, c2, c3, c4, c5')

gr.Interface(lambda x:x, "dataframe", "dataframe", examples=["test.csv", "test.csv"]).launch()

Copy link
Collaborator

Choose a reason for hiding this comment

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

Lol no clue who would ever write that 🙈

"""
if payload is None:
return None
if self.type == "index":
return payload
elif self.type == "values":
return self.samples[payload]
return self.raw_samples[payload]
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a small breaking change, but almost certainly the right behavior. When you are using the Dataset as an input, it should send the original values of the samples, not after they have already been postprocessed (and e.g. truncated as in the case of the dataframe).

For example, in a demo like this:

import gradio as gr

with gr.Blocks() as demo:
    image = gr.Image(type="pil")
    textbox = gr.Textbox()
    dataset = gr.Dataset(samples=[["cat.jpg"], ["cat.jpg"]], components=[image], type="values")
    dataset.click(lambda x:(x[0], x[0]), dataset, [textbox, image])
    
demo.launch()

clicking on the dataset, will send a human-readable value into the textbox and a valid image into the image component

demo/image_mod/run.py Outdated Show resolved Hide resolved
@abidlabs
Copy link
Member Author

Thanks so much for the detailed review @freddyaboulton! I think I've addressed everything now and tested with some more complex demos everything is working on my end, so would appreciate another look.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated this demo instead of adding another demo because the original demo is quite simplistic and not referenced anywhere in the docs, and this way we don't have to add more images to the repo (I want to use local images instead of urls to make sure the test is not flaky)

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.

Thanks for making the changes @abidlabs ! Everything is working now- appreciate the e2e test as well!

@abidlabs
Copy link
Member Author

Thanks so much for consistently reviewing this @freddyaboulton sorry it took a few tries 😅

@abidlabs abidlabs merged commit 4030f28 into main Jul 15, 2024
8 checks passed
@abidlabs abidlabs deleted the dataset-update branch July 15, 2024 16:19
@pngwn pngwn mentioned this pull request Jul 14, 2024
@mridulsamaddar
Copy link

mridulsamaddar commented Jul 16, 2024

Allows modifying the samples of a .dataset of a gr.Examples, adds an example in the docs

import gradio as gr

def update_examples(country):
    if country == "USA":
        return gr.Dataset(samples=[["Chicago"], ["Little Rock"], ["San Francisco"]])
    else:
        return gr.Dataset(samples=[["Islamabad"], ["Karachi"], ["Lahore"]])

with gr.Blocks() as demo:
    dropdown = gr.Dropdown(label="Country", choices=["USA", "Pakistan"], value="USA")
    textbox = gr.Textbox()
    examples = gr.Examples([["Chicago"], ["Little Rock"], ["San Francisco"]], textbox)
    dropdown.change(update_examples, dropdown, examples.dataset)
    
demo.launch()

Closes: #5042 Closes: #8325

Allows modifying the samples of a .dataset of a gr.Examples, adds an example in the docs

import gradio as gr

def update_examples(country):
    if country == "USA":
        return gr.Dataset(samples=[["Chicago"], ["Little Rock"], ["San Francisco"]])
    else:
        return gr.Dataset(samples=[["Islamabad"], ["Karachi"], ["Lahore"]])

with gr.Blocks() as demo:
    dropdown = gr.Dropdown(label="Country", choices=["USA", "Pakistan"], value="USA")
    textbox = gr.Textbox()
    examples = gr.Examples([["Chicago"], ["Little Rock"], ["San Francisco"]], textbox)
    dropdown.change(update_examples, dropdown, examples.dataset)
    
demo.launch()

Closes: #5042 Closes: #8325

Enhanced Gradio chatbot code with the ability to update examples using a button and a dynamic dropdown feature, catering to users who seek interactive example updates and a dynamic selection experience.

import gradio as gr
import random
import time
from gradio.themes.base import Base
import time
import requests
import os
from pathlib import Path
import pandas as pd
import re




class Seafoam(Base):
    pass

seafoam = Seafoam()


markdown_documents = []
markdown_document_titles = []
examples_list = [['Please first write a query in the chat box']]

def update_document_markdown(choice):
    global markdown_documents, markdown_document_titles
    return markdown_documents[markdown_document_titles.index(choice)]

def load_example(index):
    global examples_list
    return examples_list[index][0]

def respond_query(message, toggle_value, db):
    global examples_list, updated_examples
    if message:
      data = {"inputs": message, "switch": toggle_value, "db": db, "query_rewriting": True}
      response = ["Option 1", "Option 2", "Option 3", "Option 4"] # Dummy Values Give your logic or your rest API to get your response
      examples_list = [[i] for i in response]
      updated_examples = gr.Dataset(samples = examples_list, components=[])
    else:
        examples_list = [['chat box is empty']]
        updated_examples = gr.Dataset(samples = examples_list, components=[])
    return updated_examples


def respond(message, toggle_value, db, chat_history):
    # Dummy Values Give your logic or your rest API to get your response
    _titles = ["title_1", "title_2", "title_3", "title_4"]
    _ids = [1,2,3,4]
    _articles = ["Doc_1", "Doc_2", "Doc_3", "Doc_4"]
  
    answer = "This is your answer"
    ground_source = "ground_source"
    source_article = "source_article"

    global markdown_document_titles, markdown_documents
    markdown_document_titles = _titles
    markdown_documents = _articles
    
    updated_document_selector = gr.update(choices = _titles, value = _titles[0])
  
    bot_message = answer
    chat_history.append((message, bot_message))

    return "", chat_history, ground_source, source_article, updated_document_selector


with gr.Blocks(theme=seafoam, fill_height=True) as demo:
    with gr.Tab("Oracle Retriver"):
        with gr.Row():
            with gr.Column(scale=0.6):
                ls1 =["L1", 
                      "L2", 
                      "L3",
                      "L4"]
                switch = gr.Dropdown(ls1, value="L1", label="Your Label", info="Your Info")
                chat_output = gr.Chatbot(label="Chatbot Response")
                chat_input = gr.Textbox(label="Ask a question:")
                chat_button = gr.Button("Submit", variant="primary")
                clear_button = gr.Button("Clear")

                with gr.Row():
                    with gr.Column(scale=0.8):
                        updated_examples = gr.Dataset(samples=examples_list, components= [chat_input], type="index")
                    with gr.Column(scale=0.2):
                        query_rewriting_button = gr.Button("Rewrite The Query")
                    

            with gr.Column(scale=0.5):
                ls2 =  ['D1','D2'] 
                db = gr.Dropdown(ls2, value = "D1", label="Your Label", info="Your Info")
                ground_source_md = gr.Markdown()
                source_article_md = gr.Markdown()

    with gr.Tab("Document View"):
        with gr.Row():
            with gr.Column(scale=0.8):
                document_markdown = gr.Markdown()

            with gr.Column(scale=0.2): 
                document_selector = gr.Dropdown(
                    choices=["Enter your query"],
                    value="Enter your query",
                    label="Select Document",
                    interactive=True
                )

    updated_examples.click(load_example, inputs=[updated_examples], outputs=[chat_input]) 

    document_selector.change(
        fn=update_document_markdown,
        inputs=[document_selector],
        outputs=[document_markdown]
    )
    
    chat_button.click(
        respond,
        inputs=[chat_input, switch, db, chat_output],
        outputs=[chat_input, chat_output, ground_source_md, source_article_md, document_selector]
    )

    query_rewriting_button.click(
        respond_query,
        inputs=[chat_input, switch, db],
        outputs=[updated_examples]
    )

    clear_button.click(
        lambda: ["", [], None, None, [["Cleared"]]], 
        inputs=[],
        outputs=[chat_input, chat_output, ground_source_md, source_article_md, updated_examples]
    )


if __name__ == "__main__":
    demo.launch(share=False, server_name="0.0.0.0")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v: minor A change that requires a minor release
Projects
None yet
4 participants