Repository: huggingface/transformers
Pull request: fix async client for transformers chat

# What does this PR do?

This PR fixes the async client for transformers chat. There were some error due to the latest version of `huggingface-hub` since we migrated to httpx and i'm not sure why the previous code actually worked ... 

### Traceback 
```
Traceback (most recent call last): File "/admin/home/marc/miniconda3/envs/test/bin/transformers", line 8, in <module> sys.exit(main()) File "/admin/home/marc/transformers/src/transformers/commands/transformers_cli.py", line 48, in main service.run() File "/admin/home/marc/transformers/src/transformers/commands/chat.py", line 665, in run asyncio.run(self._inner_run()) File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/asyncio/runners.py", line 44, in run return loop.run_until_complete(main) File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete return future.result() File "/admin/home/marc/transformers/src/transformers/commands/chat.py", line 747, in _inner_run model_output = await interface.stream_output(stream) File "/admin/home/marc/transformers/src/transformers/commands/chat.py", line 134, in stream_output async for token in await stream: File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/site-packages/huggingface_hub/inference/_generated/_async_client.py", line 956, in chat_completion data = await self._inner_post(request_parameters, stream=stream) File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/site-packages/huggingface_hub/inference/_generated/_async_client.py", line 282, in _inner_post response = await self.exit_stack.enter_async_context( File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/contextlib.py", line 619, in enter_async_context result = await _cm_type.__aenter__(cm) File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/contextlib.py", line 199, in __aenter__ return await anext(self.gen) File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/site-packages/httpx/_client.py", line 1583, in stream response = await self.send( File "/admin/home/marc/miniconda3/envs/test/lib/python3.10/site-packages/httpx/_client.py", line 1616, in send raise RuntimeError("Cannot send a request, as the client has been closed.") RuntimeError: Cannot send a request, as the client has been closed.
```

Changed files:
filename: src/transformers/commands/chat.py
patch: @@ -687,7 +687,6 @@ async def _inner_run(self):
 
         model = self.args.model_name_or_path + "@" + self.args.model_revision
         host = "http://localhost" if self.args.host == "localhost" else self.args.host
-        client = AsyncInferenceClient(f"{host}:{self.args.port}")
 
         args = self.args
         if args.examples_path is None:
@@ -710,48 +709,47 @@ async def _inner_run(self):
 
         # Starts the session with a minimal help message at the top, so that a user doesn't get stuck
         interface.print_help(minimal=True)
-        while True:
-            try:
-                user_input = interface.input()
-
-                # User commands
-                if user_input.startswith("!"):
-                    # `!exit` is special, it breaks the loop
-                    if user_input == "!exit":
-                        break
-                    else:
-                        chat, valid_command, generation_config, model_kwargs = self.handle_non_exit_user_commands(
-                            user_input=user_input,
-                            args=args,
-                            interface=interface,
-                            examples=examples,
-                            generation_config=generation_config,
-                            model_kwargs=model_kwargs,
-                            chat=chat,
-                        )
-                    # `!example` sends a user message to the model
-                    if not valid_command or not user_input.startswith("!example"):
-                        continue
-                else:
-                    chat.append({"role": "user", "content": user_input})
-
-                stream = client.chat_completion(
-                    chat,
-                    stream=True,
-                    extra_body={
-                        "generation_config": generation_config.to_json_string(),
-                        "model": model,
-                    },
-                )
 
-                model_output = await interface.stream_output(stream)
+        async with AsyncInferenceClient(f"{host}:{self.args.port}") as client:
+            while True:
+                try:
+                    user_input = interface.input()
+
+                    # User commands
+                    if user_input.startswith("!"):
+                        # `!exit` is special, it breaks the loop
+                        if user_input == "!exit":
+                            break
+                        else:
+                            chat, valid_command, generation_config, model_kwargs = self.handle_non_exit_user_commands(
+                                user_input=user_input,
+                                args=args,
+                                interface=interface,
+                                examples=examples,
+                                generation_config=generation_config,
+                                model_kwargs=model_kwargs,
+                                chat=chat,
+                            )
+                        # `!example` sends a user message to the model
+                        if not valid_command or not user_input.startswith("!example"):
+                            continue
+                    else:
+                        chat.append({"role": "user", "content": user_input})
+
+                    stream = client.chat_completion(
+                        chat,
+                        stream=True,
+                        extra_body={
+                            "generation_config": generation_config.to_json_string(),
+                            "model": model,
+                        },
+                    )
 
-                chat.append({"role": "assistant", "content": model_output})
+                    model_output = await interface.stream_output(stream)
 
-            except KeyboardInterrupt:
-                break
-            finally:
-                await client.close()
+                    chat.append({"role": "assistant", "content": model_output})
+                except KeyboardInterrupt:
+                    break
 
 
 if __name__ == "__main__":