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

Allow gr.Request to work with ZeroGPU #9148

Merged
merged 8 commits into from
Aug 19, 2024
Merged

Allow gr.Request to work with ZeroGPU #9148

merged 8 commits into from
Aug 19, 2024

Conversation

abidlabs
Copy link
Member

@abidlabs abidlabs commented Aug 19, 2024

Closes: #8844. So the underlying issue is that the fastapi.Request class is not pickleable. Making it pickleable is tricky because it contains lots of attributes that are custom classes, which themselves are not serializeable. So what I've done here is extract the main attributes that we mention in our docs are users are likely using and ensured that they are preserved when the gr.Request object is picked and unpickled. I've added unit tests to confirm this. @hysts, quick favor -- if you have a chance to test on ZeroGPU directly, that'd be awesome.

@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Aug 19, 2024

🪼 branch checks and previews

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

@abidlabs abidlabs marked this pull request as ready for review August 19, 2024 20:41
@gradio-pr-bot
Copy link
Collaborator

gradio-pr-bot commented Aug 19, 2024

🦄 change detected

This Pull Request includes changes to the following packages.

Package Version
gradio patch
  • Maintainers can select this checkbox to manually select packages to update.

With the following changelog entry.

Allow gr.Request to work with ZeroGPU

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.

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.

The approach looks good but I'm worried that not all the attributes from the base request will be copied over. Maybe we can also copy url and state?

https://www.starlette.io/requests/

@@ -177,6 +181,23 @@ def __getattr__(self, name):
) from ke
return self.dict_to_obj(obj)

def __getstate__(self) -> dict[str, Any]:
self.kwargs.update(
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should probably set request.request when its unpickled, no?

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 don't think so. There's no additional value in setting it since if its not set, the attributes that a user fetches from gr.Request are served from self.kwargs instead of self.request, which is what we want. That's the logic here:

    def __getattr__(self, name: str):
        if self.request:
            return self.dict_to_obj(getattr(self.request, name))
        else:
            try:
                obj = self.kwargs[name]
            except KeyError as ke:
                raise AttributeError(
                    f"'Request' object has no attribute '{name}'"
                ) from ke
            return self.dict_to_obj(obj)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok I meant it more so that the api of a Request object in ZeroGPU is the same as outside ZeroGPU. Like someone used to doing request.request.client.host would get an error in ZeroGPU. Not sure if that's common though so we can keep as is.

@abidlabs
Copy link
Member Author

abidlabs commented Aug 19, 2024

The approach looks good but I'm worried that not all the attributes from the base request will be copied over. Maybe we can also copy url and state?

Good idea, I'll add url, state (if pickleable), path_params, and cookies

(Btw I tried a more generic approach of just serializing all the attributes of fastapi.request but I couldn't get it to work because some of the attributes are just unusual data structure)

@abidlabs
Copy link
Member Author

Ok added a few more attributes, which I think should cover the vast majority of cases. Will merge after CI runs, thanks @freddyaboulton.

@abidlabs abidlabs enabled auto-merge (squash) August 19, 2024 21:49
@abidlabs abidlabs disabled auto-merge August 19, 2024 21:57
@abidlabs abidlabs merged commit 8715f10 into main Aug 19, 2024
20 checks passed
@abidlabs abidlabs deleted the pickle branch August 19, 2024 22:02
@hysts
Copy link
Collaborator

hysts commented Aug 20, 2024

@hysts, quick favor -- if you have a chance to test on ZeroGPU directly, that'd be awesome.

Sorry, looks like I came here a bit too late.
I confirmed that this PR fixes the error on ZeroGPU with the following sample code just in case. (I used the wheel in #9072 as there doesn't seem to be a link to a pre-built wheel of this PR for some reason.)

import gradio as gr
import spaces


@spaces.GPU
def fn(request: gr.Request):
    print(request)


with gr.Blocks() as demo:
    btn = gr.Button()
    btn.click(fn=fn)
demo.queue().launch()

@abidlabs
Copy link
Member Author

abidlabs commented Aug 20, 2024

Wonderful thanks for confirming @hysts! Btw you don't need demo.queue() anymore -- queueing is enabled by default

@hysts
Copy link
Collaborator

hysts commented Aug 20, 2024

Btw you don't need demo.queue() anymore -- queueing is enabled by default

Ah, good to know. I remember seeing that discussion (before version 4?), but I wasn't sure how it was actually implemented because I also remember seeing discussions about enabling it by default on Spaces or on ZeroGPU Spaces in a bit different contexts, and I've just been using the old code. Thanks for the info!

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.

Get error on adding gr.Request to queue and ZeroGpu
4 participants