Files
wehub-resource-sync 770d92cb1f
Lint / lint (push) Has been cancelled
Build Docs / Deploy Docs (push) Has been cancelled
Windows CI / Windows (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:23:58 +08:00

265 lines
11 KiB
Python

"""Command line entrypoint of serve."""
import dataclasses
import json
from io import StringIO
from typing import Literal, Optional
from mlc_llm.interface.help import HELP
from mlc_llm.interface.serve import serve
from mlc_llm.support import argparse
from mlc_llm.support.argparse import ArgumentParser
@dataclasses.dataclass
class EngineConfigOverride:
"""Arguments for overriding engine config."""
# Overrides for EngineConfig (runtime)
max_num_sequence: Optional[int] = None
max_total_seq_length: Optional[int] = None
prefill_chunk_size: Optional[int] = None
max_history_size: Optional[int] = None
gpu_memory_utilization: Optional[float] = None
spec_draft_length: Optional[int] = None
spec_tree_width: Optional[int] = None
prefix_cache_mode: Optional[Literal["disable", "radix"]] = None
prefix_cache_max_num_recycling_seqs: Optional[int] = None
prefill_mode: Optional[Literal["chunked", "hybrid"]] = None
context_window_size: Optional[int] = None
sliding_window_size: Optional[int] = None
attention_sink_size: Optional[int] = None
tensor_parallel_shards: Optional[int] = None
pipeline_parallel_stages: Optional[int] = None
opt: Optional[str] = None
def __repr__(self) -> str:
out = StringIO()
print(f"max_num_sequence={self.max_num_sequence}", file=out, end="")
print(f";max_total_seq_length={self.max_total_seq_length}", file=out, end="")
print(f";prefill_chunk_size={self.prefill_chunk_size}", file=out, end="")
print(f";max_history_size={self.max_history_size}", file=out, end="")
print(f";gpu_memory_utilization={self.gpu_memory_utilization}", file=out, end="")
print(f";spec_draft_length={self.spec_draft_length}", file=out, end="")
print(f";spec_tree_width={self.spec_tree_width}", file=out, end="")
print(f";prefix_cache_mode={self.prefix_cache_mode}", file=out, end="")
print(
f";prefix_cache_max_num_recycling_seqs={self.prefix_cache_max_num_recycling_seqs}",
file=out,
end="",
)
print(f";prefill_mode={self.prefill_mode}", file=out, end="")
print(f";context_window_size={self.context_window_size}", file=out, end="")
print(f";sliding_window_size={self.sliding_window_size}", file=out, end="")
print(f";attention_sink_size={self.attention_sink_size}", file=out, end="")
print(f";tensor_parallel_shards={self.tensor_parallel_shards}", file=out, end="")
print(
f";pipeline_parallel_stages={self.pipeline_parallel_stages}",
file=out,
end="",
)
print(f";opt={self.opt}", file=out, end="")
return out.getvalue().rstrip()
@staticmethod
def from_str(source: str) -> "EngineConfigOverride":
"""Parse engine config override values from a string."""
parser = argparse.ArgumentParser(description="Engine config override values")
parser.add_argument("--max_num_sequence", type=int, default=None)
parser.add_argument("--max_total_seq_length", type=int, default=None)
parser.add_argument("--prefill_chunk_size", type=int, default=None)
parser.add_argument("--max_history_size", type=int, default=None)
parser.add_argument("--gpu_memory_utilization", type=float, default=None)
parser.add_argument("--spec_draft_length", type=int, default=None)
parser.add_argument("--spec_tree_width", type=int, default=None)
parser.add_argument("--prefix_cache_mode", type=str, default="radix")
parser.add_argument("--prefix_cache_max_num_recycling_seqs", type=int, default=None)
parser.add_argument("--prefill_mode", type=str, default="hybrid")
parser.add_argument("--context_window_size", type=int, default=None)
parser.add_argument("--sliding_window_size", type=int, default=None)
parser.add_argument("--attention_sink_size", type=int, default=None)
parser.add_argument("--tensor_parallel_shards", type=int, default=None)
parser.add_argument("--pipeline_parallel_stages", type=int, default=None)
parser.add_argument("--opt", type=str, default=None)
results = parser.parse_args([f"--{i}" for i in source.split(";") if i])
return EngineConfigOverride(
max_num_sequence=results.max_num_sequence,
max_total_seq_length=results.max_total_seq_length,
prefill_chunk_size=results.prefill_chunk_size,
max_history_size=results.max_history_size,
gpu_memory_utilization=results.gpu_memory_utilization,
spec_draft_length=results.spec_draft_length,
spec_tree_width=results.spec_tree_width,
prefix_cache_mode=results.prefix_cache_mode,
prefix_cache_max_num_recycling_seqs=results.prefix_cache_max_num_recycling_seqs,
prefill_mode=results.prefill_mode,
context_window_size=results.context_window_size,
sliding_window_size=results.sliding_window_size,
attention_sink_size=results.attention_sink_size,
tensor_parallel_shards=results.tensor_parallel_shards,
pipeline_parallel_stages=results.pipeline_parallel_stages,
opt=results.opt,
)
def main(argv):
"""Parse command line arguments and call `mlc_llm.interface.serve`."""
parser = ArgumentParser("MLC LLM Serve CLI")
parser.add_argument(
"model",
type=str,
help=HELP["model"] + " (required)",
)
parser.add_argument(
"--device",
type=str,
default="auto",
help=HELP["device_deploy"] + ' (default: "%(default)s")',
)
parser.add_argument(
"--model-lib",
type=str,
default=None,
help=HELP["model_lib"] + ' (default: "%(default)s")',
)
parser.add_argument(
"--mode",
type=str,
choices=["local", "interactive", "server"],
default="local",
help=HELP["mode_serve"] + ' (default: "%(default)s")',
)
parser.add_argument(
"--enable-debug",
action="store_true",
help="whether we enable debug end points and debug config when accepting requests",
)
parser.add_argument(
"--additional-models", type=str, nargs="*", help=HELP["additional_models_serve"]
)
parser.add_argument(
"--embedding-model",
type=str,
default=None,
help="Path to the embedding model weight directory (enables /v1/embeddings endpoint)",
)
parser.add_argument(
"--embedding-model-lib",
type=str,
default=None,
help="Path to the compiled embedding model library (.so/.dylib file)",
)
parser.add_argument(
"--speculative-mode",
type=str,
choices=["disable", "small_draft", "eagle", "medusa"],
default="disable",
help=HELP["speculative_mode_serve"] + ' (default: "%(default)s")',
)
parser.add_argument(
"--prefix-cache-mode",
type=str,
choices=["disable", "radix"],
default="radix",
help=HELP["prefix_cache_mode_serve"] + ' (default: "%(default)s")',
)
parser.add_argument(
"--prefill-mode",
type=str,
choices=["hybrid", "chunked"],
default="hybrid",
help=HELP["prefill_mode"] + ' (default: "%(default)s")',
)
parser.add_argument(
"--overrides",
type=EngineConfigOverride.from_str,
default="",
help=HELP["overrides_serve"],
)
parser.add_argument("--enable-tracing", action="store_true", help=HELP["enable_tracing_serve"])
parser.add_argument(
"--host",
type=str,
default="127.0.0.1",
help="host name" + ' (default: "%(default)s")',
)
parser.add_argument(
"--port",
type=int,
default=8000,
help="port" + ' (default: "%(default)s")',
)
parser.add_argument("--allow-credentials", action="store_true", help="allow credentials")
parser.add_argument(
"--allow-origins",
type=json.loads,
default=["*"],
help="allowed origins" + ' (default: "%(default)s")',
)
parser.add_argument(
"--allow-methods",
type=json.loads,
default=["*"],
help="allowed methods" + ' (default: "%(default)s")',
)
parser.add_argument(
"--allow-headers",
type=json.loads,
default=["*"],
help="allowed headers" + ' (default: "%(default)s")',
)
parser.add_argument(
"--api-key",
type=str,
default=None,
help="API key for authentication. If not provided, authentication is disabled.",
)
parsed = parser.parse_args(argv)
additional_models = []
if parsed.additional_models is not None:
for additional_model in parsed.additional_models:
splits = additional_model.split(",", maxsplit=1)
if len(splits) == 2:
additional_models.append((splits[0], splits[1]))
else:
additional_models.append(splits[0])
serve(
model=parsed.model,
device=parsed.device,
model_lib=parsed.model_lib,
mode=parsed.mode,
enable_debug=parsed.enable_debug,
additional_models=additional_models,
embedding_model=parsed.embedding_model,
embedding_model_lib=parsed.embedding_model_lib,
tensor_parallel_shards=parsed.overrides.tensor_parallel_shards,
pipeline_parallel_stages=parsed.overrides.pipeline_parallel_stages,
opt=parsed.overrides.opt,
speculative_mode=parsed.speculative_mode,
prefix_cache_mode=parsed.prefix_cache_mode,
max_num_sequence=parsed.overrides.max_num_sequence,
max_total_sequence_length=parsed.overrides.max_total_seq_length,
max_single_sequence_length=parsed.overrides.context_window_size,
prefill_chunk_size=parsed.overrides.prefill_chunk_size,
sliding_window_size=parsed.overrides.sliding_window_size,
attention_sink_size=parsed.overrides.attention_sink_size,
max_history_size=parsed.overrides.max_history_size,
gpu_memory_utilization=parsed.overrides.gpu_memory_utilization,
spec_draft_length=parsed.overrides.spec_draft_length,
spec_tree_width=parsed.overrides.spec_tree_width,
prefix_cache_max_num_recycling_seqs=parsed.overrides.prefix_cache_max_num_recycling_seqs,
prefill_mode=parsed.prefill_mode,
enable_tracing=parsed.enable_tracing,
host=parsed.host,
port=parsed.port,
allow_credentials=parsed.allow_credentials,
allow_origins=parsed.allow_origins,
allow_methods=parsed.allow_methods,
allow_headers=parsed.allow_headers,
api_key=parsed.api_key,
)