mirror of
https://github.com/kvcache-ai/sglang.git
synced 2026-07-15 03:44:18 +00:00
160 lines
4.8 KiB
Python
160 lines
4.8 KiB
Python
import json
|
|
import os
|
|
import resource
|
|
from json import JSONDecodeError
|
|
from typing import Dict, List, Optional, Union
|
|
|
|
import requests
|
|
from tqdm.asyncio import tqdm
|
|
from transformers import (
|
|
AutoProcessor,
|
|
AutoTokenizer,
|
|
PreTrainedTokenizer,
|
|
PreTrainedTokenizerFast,
|
|
)
|
|
|
|
|
|
def remove_prefix(text: str, prefix: str) -> str:
|
|
return text[len(prefix) :] if text.startswith(prefix) else text
|
|
|
|
|
|
def remove_suffix(text: str, suffix: str) -> str:
|
|
return text[: -len(suffix)] if text.endswith(suffix) else text
|
|
|
|
|
|
def parse_custom_headers(header_list: List[str]) -> Dict[str, str]:
|
|
return {k: v for h in header_list for k, _, v in [h.partition("=")] if k and v}
|
|
|
|
|
|
def get_model(pretrained_model_name_or_path: str) -> str:
|
|
if os.getenv("SGLANG_USE_MODELSCOPE", "false").lower() == "true":
|
|
import huggingface_hub.constants
|
|
from modelscope import snapshot_download
|
|
|
|
model_path = snapshot_download(
|
|
model_id=pretrained_model_name_or_path,
|
|
local_files_only=huggingface_hub.constants.HF_HUB_OFFLINE,
|
|
ignore_file_pattern=[".*.pt", ".*.safetensors", ".*.bin"],
|
|
)
|
|
|
|
return model_path
|
|
return pretrained_model_name_or_path
|
|
|
|
|
|
def get_tokenizer(
|
|
pretrained_model_name_or_path: str,
|
|
) -> Union[PreTrainedTokenizer, PreTrainedTokenizerFast]:
|
|
assert (
|
|
pretrained_model_name_or_path is not None
|
|
and pretrained_model_name_or_path != ""
|
|
)
|
|
if pretrained_model_name_or_path.endswith(
|
|
".json"
|
|
) or pretrained_model_name_or_path.endswith(".model"):
|
|
from sglang.srt.utils.hf_transformers_utils import get_tokenizer
|
|
|
|
return get_tokenizer(pretrained_model_name_or_path)
|
|
|
|
if pretrained_model_name_or_path is not None and not os.path.exists(
|
|
pretrained_model_name_or_path
|
|
):
|
|
pretrained_model_name_or_path = get_model(pretrained_model_name_or_path)
|
|
return AutoTokenizer.from_pretrained(
|
|
pretrained_model_name_or_path, trust_remote_code=True
|
|
)
|
|
|
|
|
|
def get_processor(
|
|
pretrained_model_name_or_path: str,
|
|
) -> AutoProcessor:
|
|
assert (
|
|
pretrained_model_name_or_path is not None
|
|
and pretrained_model_name_or_path != ""
|
|
)
|
|
if pretrained_model_name_or_path.endswith(
|
|
".json"
|
|
) or pretrained_model_name_or_path.endswith(".model"):
|
|
from sglang.srt.utils.hf_transformers_utils import get_processor
|
|
|
|
return get_processor(pretrained_model_name_or_path)
|
|
|
|
if pretrained_model_name_or_path is not None and not os.path.exists(
|
|
pretrained_model_name_or_path
|
|
):
|
|
pretrained_model_name_or_path = get_model(pretrained_model_name_or_path)
|
|
return AutoProcessor.from_pretrained(
|
|
pretrained_model_name_or_path, trust_remote_code=True
|
|
)
|
|
|
|
|
|
def download_and_cache_hf_file(
|
|
repo_id: str,
|
|
filename: str,
|
|
repo_type: str = "dataset",
|
|
):
|
|
"""Download a file from Hugging Face and cache it locally."""
|
|
from huggingface_hub import hf_hub_download
|
|
|
|
return hf_hub_download(repo_id=repo_id, filename=filename, repo_type=repo_type)
|
|
|
|
|
|
def download_and_cache_file(url: str, filename: Optional[str] = None):
|
|
"""Read and cache a file from a url."""
|
|
if filename is None:
|
|
filename = os.path.join("/tmp", url.split("/")[-1])
|
|
|
|
# Check if the cache file already exists
|
|
if is_file_valid_json(filename):
|
|
return filename
|
|
|
|
print(f"Downloading from {url} to {filename}")
|
|
|
|
# Stream the response to show the progress bar
|
|
response = requests.get(url, stream=True)
|
|
response.raise_for_status() # Check for request errors
|
|
|
|
# Total size of the file in bytes
|
|
total_size = int(response.headers.get("content-length", 0))
|
|
chunk_size = 1024 # Download in chunks of 1KB
|
|
|
|
# Use tqdm to display the progress bar
|
|
with open(filename, "wb") as f, tqdm(
|
|
desc=filename,
|
|
total=total_size,
|
|
unit="B",
|
|
unit_scale=True,
|
|
unit_divisor=1024,
|
|
) as bar:
|
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
f.write(chunk)
|
|
bar.update(len(chunk))
|
|
|
|
return filename
|
|
|
|
|
|
def is_file_valid_json(path):
|
|
if not os.path.isfile(path):
|
|
return False
|
|
|
|
# TODO can fuse into the real file open later
|
|
try:
|
|
with open(path) as f:
|
|
json.load(f)
|
|
return True
|
|
except JSONDecodeError as e:
|
|
print(
|
|
f"{path} exists but json loading fails ({e=}), thus treat as invalid file"
|
|
)
|
|
return False
|
|
|
|
|
|
def set_ulimit(target_soft_limit=65535):
|
|
resource_type = resource.RLIMIT_NOFILE
|
|
current_soft, current_hard = resource.getrlimit(resource_type)
|
|
|
|
if current_soft < target_soft_limit:
|
|
try:
|
|
resource.setrlimit(resource_type, (target_soft_limit, current_hard))
|
|
except ValueError as e:
|
|
print(f"Fail to set RLIMIT_NOFILE: {e}")
|