Repository navigation
Conversation
Make RoutingInterface.route_request a coroutine with an optional
request_json parameter, and give every router that signature, including
PriorityRouter and LoadAwareRouter, which arrived after the original
branch. Both dispatch sites in request.py then await the router directly:
route_general_request and the failover loop drop their isinstance chains,
and proxy_multipart_request makes one awaited call that passes {}.
The DisaggregatedPrefill* handler dispatch in route_general_request stays,
because those routers go to different request handlers.
Rebased from vllm-project#1023.
Fixes vllm-project#1022
Co-authored-by: Mohith Gajjela <109003762+Mohith26@users.noreply.github.com>
Signed-off-by: Christopher Krah <48338417+chrikrah@users.noreply.github.com>
Add test_route_request_signature.py, which checks that every router's route_request is a coroutine function with an optional request_json, and that both dispatch sites in request.py await it. Update the round-robin, auth-header and multipart request-stats tests, whose fake routers called route_request synchronously. Co-authored-by: Mohith Gajjela <109003762+Mohith26@users.noreply.github.com> Signed-off-by: Christopher Krah <48338417+chrikrah@users.noreply.github.com>
There was a problem hiding this comment.
Code Review
This pull request standardizes the route_request signature across all routers to be asynchronous and accept an optional request_json parameter, simplifying call sites by removing complex isinstance dispatch guards. Feedback was provided regarding a potential KeyError in PrefixAwareRouter when request_json is empty or missing the prompt key.
| if request_json is None: | ||
| request_json = {} |
There was a problem hiding this comment.
If request_json is None or an empty dictionary (such as the {} passed during multipart/form-data requests), PrefixAwareRouter will raise a KeyError: 'prompt' at line 934 because it directly accesses request_json["prompt"] when "messages" is not present. \n\nTo prevent this runtime crash, we should ensure that request_json always contains at least an empty string for "prompt" if neither "prompt" nor "messages" is specified.
if request_json is None:\n request_json = {\"prompt\": \"\"}\n elif \"prompt\" not in request_json and \"messages\" not in request_json:\n request_json = {**request_json, \"prompt\": \"\"}
Mohith26's #1023 on main
7b1164d: every router'sroute_requestbecomes async withrequest_json: Optional[Dict] = None, and the three dispatch sites inrequest.pystop type-sniffing. Fixes #1022.Since the original base,
PriorityRouterandLoadAwareRouterarrived and get the same signature here, and the three-way isinstance chain #1021 put on the multipart call collapses to one awaited call passing{}. TheDisaggregatedPrefill*handler dispatch stays, since those routers use different handlers.Cost: an out-of-tree router with a sync
route_requestbreaks on the first request, withTypeError: object str can't be used in 'await' expression. The fake router intest_request_stats.pyfrom #1115 hit that and is now async. Once this lands I would close my #1095, whoseisinstanceaddition becomes dead code. #929 by nejch and #950 by guba-elleschr make the same async change, both before #1023, and #1020 patches the multipart call alone. All three are open, and this series covers each.On #1095 I said I would keep Mohith Gajjela as author, but the new routers and the #1021 chain meant rewriting his commits, so he is credited in a
Co-authored-by:trailer on both commits. The second extends his signature tests to the two new routers and checks thatrequest_jsondefaults toNone.-swhen doinggit commit[Bugfix],[Feat], and[CI].[Router], the prefix [Router] Standardize route_request signature across all routers #1023 used.@Shaoting-Feng, you asked on #1095 for someone to pick #1023 up, and this is that rebase as its own pull request. If Mohith26 comes back, should it fold into his branch instead?