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

Multipage #10433

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Multipage #10433

wants to merge 17 commits into from

Conversation

aliabid94
Copy link
Collaborator

@aliabid94 aliabid94 commented Jan 24, 2025

Closes: #2654

Implemented multipage. This is the syntax:

import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    ...

with demo.route("Test", "/test"):
    num = gr.Number()
    ....

demo.launch()

See demo/multipage/run.py below:

Recording 2025-01-24 at 08 04 25

Initially I had implemented separate routes as separate Blocks but then it got real messy with trying to unify the queue, Stateholder and other backend things across multiple Blocks, so now we just keep the configs separate for different pages but the Blocks is shared.

Did not yet implement shared state or components across pages, because it's still unclear what the intended behaviour should be, still need to discuss.

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Jan 24, 2025

🪼 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-pypi-previews.s3.amazonaws.com/0c10c409d744142f7463a583e97cb4755de016c5/gradio-5.13.1-py3-none-any.whl

Install Gradio Python Client from this PR

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

Install Gradio JS Client from this PR

npm install https://gradio-npm-previews.s3.amazonaws.com/0c10c409d744142f7463a583e97cb4755de016c5/gradio-client-1.10.0.tgz

Use Lite from this PR

<script type="module" src="https://gradio-lite-previews.s3.amazonaws.com/0c10c409d744142f7463a583e97cb4755de016c5/dist/lite.js""></script>

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Jan 24, 2025

🦄 change detected

This Pull Request includes changes to the following packages.

Package Version
@gradio/client minor
@gradio/core minor
@self/app minor
@self/spa minor
gradio minor
  • Maintainers can select this checkbox to manually select packages to update.

With the following changelog entry.

Multipage

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 requested review from hysts and yvrjsharma January 24, 2025 18:03
@abidlabs
Copy link
Member

I get this error when trying demo/multipage/run.py or the toy example above:

TypeError: document..inner_doc() takes 1 positional argument but 2 were given

@aliabid94
Copy link
Collaborator Author

I get this error when trying demo/multipage/run.py or the toy example above:

Whoops fixed

@abidlabs
Copy link
Member

Thanks @aliabid94, the demo is working for me now in regular mode.

  • However, SSR mode demo.launch(ssr_mode=True) is not working for me, which means it doesn't work by default on Spaces. The content for both of the pages loads together and cliking on the "Up" has no effect:
image

Btw without SSR, multipage does feel a bit slow on Spaces: https://huggingface.co/spaces/abidlabs/multipage

  • For the navbar UI, I suggest moving the links to the right (to be more compatible with gr.Sidebar and to potentially leave space in the left for a navbar brand image), removing the bullets, and using background shading to indicate the currently selected page.

gradio/routes.py Outdated
@@ -592,6 +609,7 @@ def api_info(request: fastapi.Request):
@app.get("/config", dependencies=[Depends(login_check)])
def get_config(request: fastapi.Request):
config = utils.safe_deepcopy(app.get_blocks().config)
# del config["page"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

do we need to remove this comment?

@hannahblair
Copy link
Collaborator

For the navbar UI, I suggest moving the links to the right (to be more compatible with gr.Sidebar and to potentially leave space in the left for a navbar brand image), removing the bullets, and using background shading to indicate the currently selected page.

I'm not sure I agree about moving the links to the right but I do like the background shading idea! I do think we need the nav links to stand out a bit more. I can also experiment a little bit myself.

Ali Abid and others added 2 commits January 27, 2025 22:37
@aliabid94
Copy link
Collaborator Author

SSR mode (and dev mode) now work @abidlabs

@abidlabs
Copy link
Member

I do think we need the nav links to stand out a bit more.

I agree! In terms of a visual heirarchy, if a gradio app has both pages and tabs, the page links in the navbar should be more prominent but right now, they are less prominent than the tabs

@abidlabs
Copy link
Member


## Multipage Apps

Your Gradio app can support multiple pages with the `gr.Blocks().route()` method.
Copy link
Member

Choose a reason for hiding this comment

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

I would suggest creating a separate guide for multipage apps where we discuss multipages in more depth including the fact that you can't share components, event listeners, otherwise you should use tabs, etc. Its likely we'll expand on multipages as well with dynamic routes and so on so worth having its own section imo and also for seo purposes.

@@ -1741,3 +1762,18 @@ async def new_lifespan(app: FastAPI):

app.mount(path, gradio_app)
return app


EXISTING_ROUTES = [
Copy link
Member

@abidlabs abidlabs Jan 28, 2025

Choose a reason for hiding this comment

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

note we have similar logic here, would be good to consolidate:

                if (
                    getattr(blocks, "node_process", None) is not None
                    and blocks.node_port is not None
                    and not path.startswith("/gradio_api")
                    and path not in ["/config", "/favicon.ico"]
                    and not path.startswith("/theme")
                    and not path.startswith("/svelte")
                    and not path.startswith("/static")
                    and not path.startswith("/login")
                    and not path.startswith("/logout")
                    and not path.startswith("/manifest.json")
                    and not path.startswith("/pwa_icon")
                ):

num = gr.Number()
...
"""
if path:
Copy link
Member

Choose a reason for hiding this comment

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

I would probably do some basic validation to ensure that the path does not contain invalid characters such as "?"

Copy link
Member

Choose a reason for hiding this comment

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

Also make sure that a user doesn't accidentally reuse the same route for multiple pages in their Gradio app

Copy link
Member

Choose a reason for hiding this comment

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

Currently, if you reuse the same path, something funny happens:

image

"""
if path:
path = path.strip("/")
if path in EXISTING_ROUTES:
Copy link
Member

Choose a reason for hiding this comment

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

Nit: EXISTING_ROUTES sounds like routes that are already part of their Gradio app, INTERNAL_ROUTES would probably be more suitable

@abidlabs
Copy link
Member

Nice that each page has "its own" view api page:

image

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

@aliabid94 this is working pretty well for me! Just a few minor points:

(1) We should probably handle a large number of long page titles better (the navbar needs a bigger redesign anyways as mentioned in the comments above):

image

(2) Perhaps we should add a parameter in Blocks.route() to allow people to exclude a page from the Navbar. Also, is there a way to rename the Home page?

(3) I feel like there are small indentation changes that might trip up users as they don't give informative errors. For example, this fails and the resulting Gradio app just hangs:

import gradio as gr

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    with demo.route("Test", "/test"):
        num = gr.Number()
    with demo.route("Test", "test2"):
        num = gr.Number()

demo.launch()

@abidlabs
Copy link
Member

Actually noticing some issues with further testing. For example, all of the modals appear twice when triggered. Initially I thought it was that all events were getting triggered twice but its just the modals:

image
import gradio as gr

def check():
    gr.Info("Hello")
    return 

with gr.Blocks() as demo:
    name = gr.Textbox(label="Name")
    num = gr.Number()
    demo.load(check, None, None) 

    demo.load(lambda x:x+1, num, num)
    btn = gr.Button()
    btn.click(lambda x:x+1, num, num)

demo.launch()

aliabid94 and others added 4 commits January 28, 2025 13:10
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
@aliabid94
Copy link
Collaborator Author

Screenshot 2025-01-28 at 2 04 08 PM made the navbar a little more prominent, though feel free to suggest something else entirely @hannahblair

@abidlabs
Copy link
Member

Rendering slightly different for me, just wondering is the gray outline intentional?

image

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.

Support multiple pages in a gradio app
4 participants