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

Properly close session in AsyncInferenceClient #2496

Merged
merged 3 commits into from
Sep 2, 2024

Conversation

Wauplin
Copy link
Contributor

@Wauplin Wauplin commented Aug 30, 2024

Close #2493.

This PR adds the possibility to properly close sessions from a AsyncInferenceClient object using either close or a context manager:

import asyncio

from huggingface_hub import AsyncInferenceClient

model = ...  # NOTE: I'm using a self-hosted TGI instance

async def run():
    client = AsyncInferenceClient(model)
    answer_stream = await client.text_generation(
        "Between emacs and vim, the best editor is",
        stream=True,
    )
    await client.close()

asyncio.run(run())

or a context manager:

async with AsyncInferenceClient():
    for token in await client.text_generation(
        "Between emacs and vim, the best editor is",
        stream=True,
    ):
        break  # no one wants the answer

If some sessions are still opened when a client is being deleted, a warning is emitted to the user to tell them how to properly handle things.

Thanks @tomjorquera for the very well described issue which helped a lot building this PR :)

@Wauplin Wauplin requested a review from LysandreJik August 30, 2024 14:30
@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Copy link
Member

@LysandreJik LysandreJik left a comment

Choose a reason for hiding this comment

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

Awesome, thanks @Wauplin!

Comment on lines +343 to +350
def __del__(self):
if len(self._sessions) > 0:
warnings.warn(
"Deleting 'AsyncInferenceClient' client but some sessions are still open. "
"This can happen if you've stopped streaming data from the server before the stream was complete. "
"To close the client properly, you must call `await client.close()` "
"or use an async context (e.g. `async with AsyncInferenceClient(): ...`."
)
Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity, shouldn't this just close the session as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well well well...

I got a hard time getting to make it work. The thing is that you don't know when __del__ is called by Python's garbage collector. Since self.close is an async function, you need an active event loop to make the close method run -which is not guaranteed. I first tried some hacks but gave up given the complexity compared to having a proper close method or using an async context manager.

This answer on stackoverflow also convinced me of doing things like this.

@Wauplin
Copy link
Contributor Author

Wauplin commented Sep 2, 2024

Thanks for the review!

@Wauplin Wauplin merged commit b189401 into main Sep 2, 2024
19 checks passed
@Wauplin Wauplin deleted the 2493-properly-close-session-in-async-client branch September 2, 2024 09:30
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.

AsyncInferenceClient not closing connection properly when answer stream is not entierly consumed
3 participants