[Cleanup] IPC struct renames, better typing, and SenderWrapper removal (#29214)

This commit is contained in:
Lianmin Zheng
2026-06-24 17:25:24 -07:00
committed by GitHub
parent 563c3418a7
commit 6c839368e0
11 changed files with 357 additions and 344 deletions
+65 -33
View File
@@ -28,6 +28,7 @@ import uuid
from contextlib import asynccontextmanager
from http import HTTPStatus
from typing import (
Annotated,
Any,
AsyncGenerator,
AsyncIterator,
@@ -43,6 +44,7 @@ import requests
import uvicorn
import uvloop
from fastapi import (
Body,
Depends,
FastAPI,
File,
@@ -739,7 +741,9 @@ async def get_load():
# curl -s -X POST http://localhost:30000/set_internal_state -H "Content-Type: application/json" -d '{"server_args": {"pp_max_micro_batch_size": 8}}'
@app.api_route("/set_internal_state", methods=["POST", "PUT"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def set_internal_state(obj: SetInternalStateReq, request: Request):
async def set_internal_state(
obj: Annotated[SetInternalStateReq, Body()], request: Request
):
res = await _global_state.tokenizer_manager.set_internal_state(obj)
return res
@@ -950,7 +954,9 @@ async def clear_hicache_storage_backend():
# }'
@app.api_route("/hicache/storage-backend", methods=["PUT"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def attach_hicache_storage_backend(obj: AttachHiCacheStorageReqInput):
async def attach_hicache_storage_backend(
obj: Annotated[AttachHiCacheStorageReqInput, Body()],
):
"""Attach (enable) HiCache storage backend at runtime.
Only allowed when there are NO running / queued requests.
@@ -964,7 +970,7 @@ async def attach_hicache_storage_backend(obj: AttachHiCacheStorageReqInput):
hicache_storage_prefetch_policy=obj.hicache_storage_prefetch_policy,
hicache_write_policy=obj.hicache_write_policy,
)
msg = getattr(ret, "message", "")
msg = ret.message
return Response(
content=(
(
@@ -991,7 +997,7 @@ async def detach_hicache_storage_backend():
return _admin_api_key_missing_response()
ret = await _global_state.tokenizer_manager.detach_hicache_storage()
msg = getattr(ret, "message", "")
msg = ret.message
return Response(
content=(
(
@@ -1024,7 +1030,7 @@ async def hicache_storage_backend_status():
@app.api_route("/start_profile", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def start_profile_async(obj: Optional[ProfileReq] = None):
async def start_profile_async(obj: Annotated[Optional[ProfileReq], Body()] = None):
"""Start profiling."""
await _global_state.tokenizer_manager.start_profile(obj or ProfileReq())
return Response(
@@ -1102,7 +1108,9 @@ async def dump_expert_distribution_record_async():
@app.post("/update_weights_from_disk")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def update_weights_from_disk(obj: UpdateWeightFromDiskReqInput, request: Request):
async def update_weights_from_disk(
obj: Annotated[UpdateWeightFromDiskReqInput, Body()], request: Request
):
"""Update the weights from disk inplace without re-launching the server."""
(
success,
@@ -1130,7 +1138,8 @@ async def update_weights_from_disk(obj: UpdateWeightFromDiskReqInput, request: R
@app.post("/init_weights_send_group_for_remote_instance")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def init_weights_send_group_for_remote_instance(
obj: InitWeightsSendGroupForRemoteInstanceReqInput, request: Request
obj: Annotated[InitWeightsSendGroupForRemoteInstanceReqInput, Body()],
request: Request,
):
(
success,
@@ -1148,7 +1157,7 @@ async def init_weights_send_group_for_remote_instance(
@app.post("/send_weights_to_remote_instance")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def send_weights_to_remote_instance(
obj: SendWeightsToRemoteInstanceReqInput, request: Request
obj: Annotated[SendWeightsToRemoteInstanceReqInput, Body()], request: Request
):
(
success,
@@ -1204,7 +1213,7 @@ async def remote_instance_transfer_engine_info(rank: int = None):
@app.post("/init_weights_update_group")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def init_weights_update_group(
obj: InitWeightsUpdateGroupReqInput, request: Request
obj: Annotated[InitWeightsUpdateGroupReqInput, Body()], request: Request
):
"""Initialize the parameter update group."""
success, message = await _global_state.tokenizer_manager.init_weights_update_group(
@@ -1220,7 +1229,7 @@ async def init_weights_update_group(
@app.post("/destroy_weights_update_group")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def destroy_weights_update_group(
obj: DestroyWeightsUpdateGroupReqInput, request: Request
obj: Annotated[DestroyWeightsUpdateGroupReqInput, Body()], request: Request
):
"""Destroy the parameter update group."""
(
@@ -1236,7 +1245,7 @@ async def destroy_weights_update_group(
@app.post("/update_weights_from_tensor")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def update_weights_from_tensor(
obj: UpdateWeightsFromTensorReqInput, request: Request
obj: Annotated[UpdateWeightsFromTensorReqInput, Body()], request: Request
):
"""Update the weights from tensor inplace without re-launching the server.
Notes:
@@ -1258,7 +1267,7 @@ async def update_weights_from_tensor(
@app.post("/update_weights_from_distributed")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def update_weights_from_distributed(
obj: UpdateWeightsFromDistributedReqInput, request: Request
obj: Annotated[UpdateWeightsFromDistributedReqInput, Body()], request: Request
):
"""Update model parameter from distributed online."""
(
@@ -1277,7 +1286,9 @@ async def update_weights_from_distributed(
@app.post("/update_weights_from_ipc")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def update_weights_from_ipc(obj: UpdateWeightsFromIPCReqInput, request: Request):
async def update_weights_from_ipc(
obj: Annotated[UpdateWeightsFromIPCReqInput, Body()], request: Request
):
"""Update the weights from IPC (Inter-Process Communication) for checkpoint-engine integration."""
success, message = await _global_state.tokenizer_manager.update_weights_from_ipc(
obj, request
@@ -1294,7 +1305,9 @@ async def update_weights_from_ipc(obj: UpdateWeightsFromIPCReqInput, request: Re
@app.post("/update_weight_version")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def update_weight_version(obj: UpdateWeightVersionReqInput, request: Request):
async def update_weight_version(
obj: Annotated[UpdateWeightVersionReqInput, Body()], request: Request
):
"""Update the weight version. This operation requires no active requests."""
if obj.abort_all_requests:
_global_state.tokenizer_manager.abort_request(abort_all=True)
@@ -1325,7 +1338,9 @@ async def update_weight_version(obj: UpdateWeightVersionReqInput, request: Reque
@app.api_route("/get_weights_by_name", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def get_weights_by_name(obj: GetWeightsByNameReqInput, request: Request):
async def get_weights_by_name(
obj: Annotated[GetWeightsByNameReqInput, Body()], request: Request
):
"""Get model parameter by name."""
try:
ret = await _global_state.tokenizer_manager.get_weights_by_name(obj, request)
@@ -1340,7 +1355,7 @@ async def get_weights_by_name(obj: GetWeightsByNameReqInput, request: Request):
@app.api_route("/release_memory_occupation", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def release_memory_occupation(
obj: ReleaseMemoryOccupationReqInput, request: Request
obj: Annotated[ReleaseMemoryOccupationReqInput, Body()], request: Request
):
"""Release GPU memory occupation temporarily."""
try:
@@ -1352,7 +1367,7 @@ async def release_memory_occupation(
@app.api_route("/resume_memory_occupation", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def resume_memory_occupation(
obj: ResumeMemoryOccupationReqInput, request: Request
obj: Annotated[ResumeMemoryOccupationReqInput, Body()], request: Request
):
"""Resume GPU memory occupation."""
try:
@@ -1364,7 +1379,8 @@ async def resume_memory_occupation(
@app.api_route("/weights_checker", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def check_weights(
obj: Optional[CheckWeightsReqInput] = None, request: Request = None
obj: Annotated[Optional[CheckWeightsReqInput], Body()] = None,
request: Request = None,
):
if obj is None:
obj = CheckWeightsReqInput()
@@ -1381,7 +1397,7 @@ async def check_weights(
@app.api_route("/slow_down", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def slow_down(obj: SlowDownReqInput, request: Request):
async def slow_down(obj: Annotated[SlowDownReqInput, Body()], request: Request):
"""Slow down the system deliberately. Only for testing. Example scenario:
when we want to test performance of D in large-scale PD disaggregation and have no enough nodes for P,
we can use this to slow down D to let it have enough running sequences, and then disable slowdown
@@ -1395,7 +1411,9 @@ async def slow_down(obj: SlowDownReqInput, request: Request):
@app.api_route("/load_lora_adapter", methods=["POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def load_lora_adapter(obj: LoadLoRAAdapterReqInput, request: Request):
async def load_lora_adapter(
obj: Annotated[LoadLoRAAdapterReqInput, Body()], request: Request
):
"""Load a new LoRA adapter without re-launching the server."""
result = await _global_state.tokenizer_manager.load_lora_adapter(obj, request)
@@ -1413,7 +1431,7 @@ async def load_lora_adapter(obj: LoadLoRAAdapterReqInput, request: Request):
@app.api_route("/load_lora_adapter_from_tensors", methods=["POST"])
async def load_lora_adapter_from_tensors(
obj: LoadLoRAAdapterFromTensorsReqInput, request: Request
obj: Annotated[LoadLoRAAdapterFromTensorsReqInput, Body()], request: Request
):
"""Load a new LoRA adapter from tensors without re-launching the server."""
result = await _global_state.tokenizer_manager.load_lora_adapter_from_tensors(
@@ -1428,7 +1446,9 @@ async def load_lora_adapter_from_tensors(
@app.api_route("/unload_lora_adapter", methods=["POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def unload_lora_adapter(obj: UnloadLoRAAdapterReqInput, request: Request):
async def unload_lora_adapter(
obj: Annotated[UnloadLoRAAdapterReqInput, Body()], request: Request
):
"""Load a new LoRA adapter without re-launching the server."""
result = await _global_state.tokenizer_manager.unload_lora_adapter(obj, request)
@@ -1445,7 +1465,7 @@ async def unload_lora_adapter(obj: UnloadLoRAAdapterReqInput, request: Request):
@app.api_route("/open_session", methods=["GET", "POST"])
async def open_session(obj: OpenSessionReqInput, request: Request):
async def open_session(obj: Annotated[OpenSessionReqInput, Body()], request: Request):
"""Open a session, and return its unique session id."""
try:
session_id = await _global_state.tokenizer_manager.open_session(obj, request)
@@ -1459,7 +1479,7 @@ async def open_session(obj: OpenSessionReqInput, request: Request):
@app.api_route("/close_session", methods=["GET", "POST"])
async def close_session(obj: CloseSessionReqInput, request: Request):
async def close_session(obj: Annotated[CloseSessionReqInput, Body()], request: Request):
"""Close the session."""
try:
await _global_state.tokenizer_manager.close_session(obj, request)
@@ -1470,7 +1490,9 @@ async def close_session(obj: CloseSessionReqInput, request: Request):
@app.api_route("/configure_logging", methods=["GET", "POST"])
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def configure_logging(obj: ConfigureLoggingReq, request: Request):
async def configure_logging(
obj: Annotated[ConfigureLoggingReq, Body()], request: Request
):
"""Configure the request logging options."""
_global_state.tokenizer_manager.configure_logging(obj)
return Response(status_code=200)
@@ -1478,7 +1500,7 @@ async def configure_logging(obj: ConfigureLoggingReq, request: Request):
@app.post("/abort_request")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def abort_request(obj: AbortReq, request: Request):
async def abort_request(obj: Annotated[AbortReq, Body()], request: Request):
"""Abort a request."""
try:
_global_state.tokenizer_manager.abort_request(
@@ -1490,7 +1512,9 @@ async def abort_request(obj: AbortReq, request: Request):
@app.post("/parse_function_call")
async def parse_function_call_request(obj: ParseFunctionCallReq, request: Request):
async def parse_function_call_request(
obj: Annotated[ParseFunctionCallReq, Body()], request: Request
):
"""
A native API endpoint to parse function calls from a text.
"""
@@ -1512,7 +1536,9 @@ async def parse_function_call_request(obj: ParseFunctionCallReq, request: Reques
@app.post("/separate_reasoning")
async def separate_reasoning_request(obj: SeparateReasoningReqInput, request: Request):
async def separate_reasoning_request(
obj: Annotated[SeparateReasoningReqInput, Body()], request: Request
):
"""
A native API endpoint to separate reasoning from a text.
"""
@@ -1520,7 +1546,7 @@ async def separate_reasoning_request(obj: SeparateReasoningReqInput, request: Re
parser = ReasoningParser(model_type=obj.reasoning_parser, request=request)
# 2) Call the non-stream parsing method (non-stream)
if getattr(obj, "return_blocks", False):
if obj.return_blocks:
blocks = parser.parse_non_stream_blocks(obj.text)
reasoning_blocks = [b["text"] for b in blocks if b["type"] == "reasoning"]
text_blocks = [b["text"] for b in blocks if b["type"] == "text"]
@@ -1534,7 +1560,7 @@ async def separate_reasoning_request(obj: SeparateReasoningReqInput, request: Re
"reasoning_text": reasoning_text,
"text": normal_text,
}
if getattr(obj, "return_blocks", False):
if obj.return_blocks:
response_data["reasoning_blocks"] = reasoning_blocks
response_data["text_blocks"] = text_blocks
response_data["blocks"] = blocks
@@ -1544,7 +1570,9 @@ async def separate_reasoning_request(obj: SeparateReasoningReqInput, request: Re
@app.post("/pause_generation")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def pause_generation(obj: PauseGenerationReqInput, request: Request):
async def pause_generation(
obj: Annotated[PauseGenerationReqInput, Body()], request: Request
):
"""Pause generation."""
await _global_state.tokenizer_manager.pause_generation(obj)
return ORJSONResponse(
@@ -1555,7 +1583,9 @@ async def pause_generation(obj: PauseGenerationReqInput, request: Request):
@app.post("/continue_generation")
@auth_level(AuthLevel.ADMIN_OPTIONAL)
async def continue_generation(obj: ContinueGenerationReqInput, request: Request):
async def continue_generation(
obj: Annotated[ContinueGenerationReqInput, Body()], request: Request
):
"""Continue generation."""
await _global_state.tokenizer_manager.continue_generation(obj)
return ORJSONResponse(
@@ -1894,7 +1924,9 @@ async def sagemaker_chat_completions(
## Vertex AI API
@app.post(os.environ.get("AIP_PREDICT_ROUTE", "/vertex_generate"))
async def vertex_generate(vertex_req: VertexGenerateReqInput, raw_request: Request):
async def vertex_generate(
vertex_req: Annotated[VertexGenerateReqInput, Body()], raw_request: Request
):
if not vertex_req.instances:
return []
inputs = {}