gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
31.99k stars 2.38k forks source link

Mounting Gradio in an already running FastAPI application causes the queue to not work. #8839

Open oubeichen opened 1 month ago

oubeichen commented 1 month ago

Describe the bug

My project is developed using FastAPI. I need to load some asynchronous operations (such as reading configuration and database) after FastAPI starts, specifically during the startup event of the lifespan. (Since the codes are synchronous when uvicorn starts the app, it’s inconvenient to use asyncio.)

After these operations, I mount Gradio. I managed to open the Gradio page, but found that the interactions get no response.

Later, I found these: https://github.com/gradio-app/gradio/issues/6718 https://github.com/gradio-app/gradio/pull/6759

However, these only address the issues when FastAPI uses lifespan, not the problems arising when using mount_gradio_app while already in lifespan.

Does anyone have any good suggestions? Thanks.

Have you searched existing issues? 🔎

Reproduction

test.py

import contextlib
from typing import Any, AsyncContextManager

import gradio as gr
import uvicorn
from fastapi import FastAPI

def sample_chat(*args: Any, **kwargs: Any) -> str:
    return "this is a example output"

async def mount_gradio(app: FastAPI) -> None:
    # do some asynchronous operations
    ...

    io = gr.ChatInterface(sample_chat)
    gr.mount_gradio_app(app, io, path="/gradio")

@contextlib.asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncContextManager[Any]:
    await mount_gradio(app)
    yield

def get_app() -> FastAPI:
    # do some configurations
    app = FastAPI(lifespan=lifespan)
    return app

def main() -> None:
    uvicorn.run(
        "test:get_app",  # base on the file name
        factory=True,
    )

if __name__ == "__main__":
    main()

Screenshot

image image

Logs

No response

System Info

Gradio Environment Information:
------------------------------
Operating System: Darwin
gradio version: 4.38.1
gradio_client version: 1.1.0

------------------------------------------------
gradio dependencies in your environment:

aiofiles: 23.2.1
altair: 5.3.0
fastapi: 0.111.1
ffmpy: 0.3.2
gradio-client==1.1.0 is not installed.
httpx: 0.27.0
huggingface-hub: 0.23.5
importlib-resources: 6.4.0
jinja2: 3.1.4
markupsafe: 2.1.5
matplotlib: 3.9.1
numpy: 2.0.0
orjson: 3.10.6
packaging: 24.1
pandas: 2.2.2
pillow: 10.4.0
pydantic: 2.8.2
pydub: 0.25.1
python-multipart: 0.0.9
pyyaml: 6.0.1
ruff: 0.5.2
semantic-version: 2.10.0
tomlkit==0.12.0 is not installed.
typer: 0.12.3
typing-extensions: 4.12.2
urllib3: 2.2.2
uvicorn: 0.30.1
authlib; extra == 'oauth' is not installed.
itsdangerous; extra == 'oauth' is not installed.

gradio_client dependencies in your environment:

fsspec: 2024.6.1
httpx: 0.27.0
huggingface-hub: 0.23.5
packaging: 24.1
typing-extensions: 4.12.2
websockets: 11.0.3

Severity

Blocking usage of gradio

freddyaboulton commented 1 month ago

Hi @oubeichen - does mounting gradio in get_app instead of in the context manager fix the issue?

oubeichen commented 1 month ago

Hi @oubeichen - does mounting gradio in get_app instead of in the context manager fix the issue?

Mounting a fixed interface of Gradio in get_app works. However, get_app is a synchronous method, but I need to use asynchronous methods in mount_gradio to read from the database/settings and dynamically change the Gradio interface.