Instructions to use Agnes-AI/Agnes-2.5-Flash-Base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Agnes-AI/Agnes-2.5-Flash-Base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Agnes-AI/Agnes-2.5-Flash-Base", trust_remote_code=True)# Load model directly from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("Agnes-AI/Agnes-2.5-Flash-Base", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Agnes-AI/Agnes-2.5-Flash-Base with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Agnes-AI/Agnes-2.5-Flash-Base" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Agnes-AI/Agnes-2.5-Flash-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/Agnes-AI/Agnes-2.5-Flash-Base
- SGLang
How to use Agnes-AI/Agnes-2.5-Flash-Base with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "Agnes-AI/Agnes-2.5-Flash-Base" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Agnes-AI/Agnes-2.5-Flash-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "Agnes-AI/Agnes-2.5-Flash-Base" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Agnes-AI/Agnes-2.5-Flash-Base", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use Agnes-AI/Agnes-2.5-Flash-Base with Docker Model Runner:
docker model run hf.co/Agnes-AI/Agnes-2.5-Flash-Base
| from __future__ import annotations | |
| import json | |
| import logging | |
| import os | |
| from typing import TYPE_CHECKING, Optional | |
| if TYPE_CHECKING: | |
| from sglang.srt.server_args import ServerArgs | |
| logger = logging.getLogger(__name__) | |
| def _disable_overlap_schedule_for_cpu(server_args: ServerArgs) -> None: | |
| if server_args.device != "cpu" or server_args.disable_overlap_schedule: | |
| return | |
| server_args.disable_overlap_schedule = True | |
| logger.warning( | |
| "Overlap schedule is not implemented for speculative decoding on CPU." | |
| ) | |
| def _resolve_speculative_algorithm_alias( | |
| speculative_algorithm: Optional[str], | |
| speculative_draft_model_path: Optional[str], | |
| trust_remote_code: bool = False, | |
| kwargs: Optional[dict] = {}, | |
| ) -> Optional[str]: | |
| """Resolve CLI speculative algorithm; NEXTN/EAGLE may become FROZEN_KV_MTP for Gemma4 assistant drafts.""" | |
| is_gemma4_draft = False | |
| if speculative_draft_model_path: | |
| from sglang.srt.utils.hf_transformers_utils import get_config | |
| cfg = get_config( | |
| speculative_draft_model_path, trust_remote_code=trust_remote_code, **kwargs | |
| ) | |
| draft_archs = getattr(cfg, "architectures", None) or [] | |
| is_gemma4_draft = any( | |
| arch in ("Gemma4AssistantForCausalLM", "Gemma4UnifiedAssistantForCausalLM") | |
| for arch in draft_archs | |
| ) | |
| if speculative_algorithm == "EAGLE3" and is_gemma4_draft: | |
| raise ValueError( | |
| "Gemma4AssistantForCausalLM draft requires " | |
| "--speculative-algorithm NEXTN or EAGLE; EAGLE3 is " | |
| "not supported for this draft architecture." | |
| ) | |
| if speculative_algorithm == "NEXTN" or speculative_algorithm == "EAGLE": | |
| if is_gemma4_draft: | |
| logger.info( | |
| "Detected Gemma4AssistantForCausalLM draft; " | |
| f"promoting --speculative-algorithm {speculative_algorithm} to FROZEN_KV_MTP." | |
| ) | |
| return "FROZEN_KV_MTP" | |
| return "EAGLE" | |
| return speculative_algorithm | |
| def handle_speculative_decoding(server_args: ServerArgs) -> None: | |
| if ( | |
| server_args.speculative_draft_model_path is not None | |
| and server_args.speculative_draft_model_revision is None | |
| ): | |
| server_args.speculative_draft_model_revision = "main" | |
| # Moved to the resolution pipeline (arg_groups/overrides.py: | |
| # _speculative_moe_runner_default), invoked here at its legacy slot. | |
| from sglang.srt.arg_groups.overrides import ( | |
| _speculative_moe_runner_default, | |
| run_post_process_pass, | |
| ) | |
| run_post_process_pass(server_args, _speculative_moe_runner_default) | |
| if server_args.speculative_algorithm is not None: | |
| server_args.speculative_algorithm = server_args.speculative_algorithm.upper() | |
| # Removal notice for the retired env var; raw os.getenv on purpose -- the | |
| # Envs descriptor is gone. Drop this check after one release. | |
| if os.getenv("SGLANG_ENABLE_SPEC_V2") is not None: | |
| logger.warning( | |
| "SGLANG_ENABLE_SPEC_V2 has been removed: speculative decoding " | |
| "always runs the V2 worker. Use --disable-overlap-schedule to " | |
| "select the non-overlap (synchronous) path." | |
| ) | |
| kwargs = {} | |
| override_config_file = server_args.decrypted_draft_config_file | |
| if override_config_file and override_config_file.strip(): | |
| kwargs["_configuration_file"] = override_config_file.strip() | |
| server_args.speculative_algorithm = _resolve_speculative_algorithm_alias( | |
| server_args.speculative_algorithm, | |
| server_args.speculative_draft_model_path, | |
| trust_remote_code=server_args.trust_remote_code, | |
| kwargs=kwargs, | |
| ) | |
| # Validate --speculative-draft-window-size once, regardless of algorithm. | |
| # Consumed by DFLASH (compact draft KV cache) and Llama EAGLE-3 (drafter attention SWA). | |
| if server_args.speculative_draft_window_size is not None: | |
| window_size = int(server_args.speculative_draft_window_size) | |
| if window_size <= 0: | |
| raise ValueError( | |
| f"--speculative-draft-window-size must be positive, got {window_size}." | |
| ) | |
| server_args.speculative_draft_window_size = window_size | |
| if server_args.speculative_algorithm not in ("EAGLE3", "DFLASH"): | |
| logger.warning( | |
| "--speculative-draft-window-size has no effect with " | |
| "speculative_algorithm=%s (honored by Llama EAGLE-3 and DFLASH only).", | |
| server_args.speculative_algorithm, | |
| ) | |
| algo = None | |
| if server_args.speculative_algorithm is not None: | |
| from sglang.srt.speculative.spec_info import SpeculativeAlgorithm | |
| from sglang.srt.speculative.spec_registry import CustomSpecAlgo | |
| algo = SpeculativeAlgorithm.from_string(server_args.speculative_algorithm) | |
| # TODO: move the per-algorithm validation below into spec module hooks. | |
| if isinstance(algo, CustomSpecAlgo) and algo.validate_server_args is not None: | |
| algo.validate_server_args(server_args) | |
| if server_args.speculative_skip_dp_mlp_sync: | |
| assert server_args.speculative_algorithm == "EAGLE", ( | |
| "--speculative-skip-dp-mlp-sync is only supported with " | |
| f"speculative_algorithm == EAGLE, got {server_args.speculative_algorithm}." | |
| ) | |
| if server_args.speculative_adaptive: | |
| _maybe_disable_adaptive(server_args) | |
| if server_args.speculative_adaptive: | |
| _init_adaptive_speculative_params(server_args) | |
| if algo is not None: | |
| algo.handle_server_args(server_args) | |
| def _handle_dflash(server_args: ServerArgs) -> None: | |
| from sglang.srt.arg_groups.overrides import resolved_view | |
| if not server_args.device.startswith("cuda"): | |
| raise ValueError("DFLASH speculative decoding only supports CUDA device.") | |
| if resolved_view(server_args).enable_dp_attention: | |
| raise ValueError( | |
| "Currently DFLASH speculative decoding does not support dp attention." | |
| ) | |
| if server_args.pp_size != 1: | |
| raise ValueError( | |
| "Currently DFLASH speculative decoding only supports pp_size == 1." | |
| ) | |
| if server_args.speculative_draft_model_path is None: | |
| raise ValueError( | |
| "DFLASH speculative decoding requires setting --speculative-draft-model-path." | |
| ) | |
| # DFLASH does not use EAGLE-style `num_steps`/`topk`, but those fields still | |
| # affect generic scheduler/KV-cache accounting (buffer sizing, KV freeing, | |
| # RoPE reservation). Force them to 1 to avoid surprising memory behavior. | |
| # | |
| # For DFlash, the natural unit is `block_size` (verify window length). | |
| if server_args.speculative_num_steps is None: | |
| server_args.speculative_num_steps = 1 | |
| elif int(server_args.speculative_num_steps) != 1: | |
| logger.warning( | |
| "DFLASH only supports speculative_num_steps == 1; overriding speculative_num_steps=%s to 1.", | |
| server_args.speculative_num_steps, | |
| ) | |
| server_args.speculative_num_steps = 1 | |
| if server_args.speculative_eagle_topk is None: | |
| server_args.speculative_eagle_topk = 1 | |
| elif int(server_args.speculative_eagle_topk) != 1: | |
| logger.warning( | |
| "DFLASH only supports speculative_eagle_topk == 1; overriding speculative_eagle_topk=%s to 1.", | |
| server_args.speculative_eagle_topk, | |
| ) | |
| server_args.speculative_eagle_topk = 1 | |
| if server_args.speculative_dflash_block_size is not None: | |
| if int(server_args.speculative_dflash_block_size) <= 0: | |
| raise ValueError( | |
| "DFLASH requires --speculative-dflash-block-size to be positive, " | |
| f"got {server_args.speculative_dflash_block_size}." | |
| ) | |
| if server_args.speculative_num_draft_tokens is not None and int( | |
| server_args.speculative_num_draft_tokens | |
| ) != int(server_args.speculative_dflash_block_size): | |
| raise ValueError( | |
| "Both --speculative-num-draft-tokens and --speculative-dflash-block-size are set " | |
| "but they differ. For DFLASH they must match. " | |
| f"speculative_num_draft_tokens={server_args.speculative_num_draft_tokens}, " | |
| f"speculative_dflash_block_size={server_args.speculative_dflash_block_size}." | |
| ) | |
| server_args.speculative_num_draft_tokens = int( | |
| server_args.speculative_dflash_block_size | |
| ) | |
| if server_args.speculative_num_draft_tokens is None: | |
| from sglang.srt.speculative.dflash_utils import ( | |
| parse_dflash_draft_config, | |
| ) | |
| model_override_args = json.loads(server_args.json_model_override_args) | |
| inferred_block_size = None | |
| try: | |
| from sglang.srt.utils.hf_transformers_utils import get_config | |
| draft_hf_config = get_config( | |
| server_args.speculative_draft_model_path, | |
| trust_remote_code=server_args.trust_remote_code, | |
| revision=server_args.speculative_draft_model_revision, | |
| model_override_args=model_override_args, | |
| ) | |
| inferred_block_size = parse_dflash_draft_config( | |
| draft_hf_config=draft_hf_config | |
| ).resolve_block_size(default=None) | |
| except Exception as e: | |
| logger.warning( | |
| "Failed to infer DFLASH block_size from draft model config; " | |
| "defaulting speculative_num_draft_tokens to 16. Error: %s", | |
| e, | |
| ) | |
| if inferred_block_size is None: | |
| inferred_block_size = 16 | |
| logger.warning( | |
| "speculative_num_draft_tokens is not set; defaulting to %d for DFLASH.", | |
| inferred_block_size, | |
| ) | |
| server_args.speculative_num_draft_tokens = inferred_block_size | |
| if server_args.speculative_draft_window_size is not None: | |
| draft_tokens = int(server_args.speculative_num_draft_tokens) | |
| if server_args.speculative_draft_window_size < draft_tokens: | |
| raise ValueError( | |
| "--speculative-draft-window-size must be >= " | |
| "--speculative-num-draft-tokens (block_size). " | |
| f"window_size={server_args.speculative_draft_window_size}, block_size={draft_tokens}." | |
| ) | |
| _resolve_dflash_draft_attention_backend(server_args) | |
| if server_args.max_running_requests is None: | |
| server_args.max_running_requests = 48 | |
| logger.warning( | |
| "Max running requests is reset to 48 for speculative decoding. You can override this by explicitly setting --max-running-requests." | |
| ) | |
| if server_args.enable_mixed_chunk: | |
| server_args.enable_mixed_chunk = False | |
| logger.warning( | |
| "Mixed chunked prefill is disabled because of using dflash speculative decoding." | |
| ) | |
| def _target_checkpoint_bundles_dspark_draft(server_args: ServerArgs) -> bool: | |
| from sglang.srt.speculative.dspark_components.dspark_config import ( | |
| checkpoint_bundles_dspark_draft, | |
| ) | |
| return checkpoint_bundles_dspark_draft(server_args.get_model_config().hf_config) | |
| def _handle_dspark(server_args: ServerArgs) -> None: | |
| if not server_args.device.startswith("cuda"): | |
| raise ValueError("DSpark speculative decoding only supports CUDA device.") | |
| if server_args.enable_dp_attention: | |
| if not server_args.enable_dp_lm_head: | |
| raise ValueError("DSpark with dp attention requires --enable-dp-lm-head.") | |
| if server_args.moe_a2a_backend != "none": | |
| raise ValueError( | |
| "DSpark with dp attention only supports the built-in TP MoE " | |
| f"(moe_a2a_backend='none'), got {server_args.moe_a2a_backend!r}." | |
| ) | |
| if server_args.attn_cp_size > 1: | |
| raise ValueError( | |
| "DSpark with dp attention does not support context parallel " | |
| f"(attn_cp_size={server_args.attn_cp_size})." | |
| ) | |
| if ( | |
| server_args.speculative_moe_a2a_backend is not None | |
| and server_args.speculative_moe_a2a_backend != server_args.moe_a2a_backend | |
| ): | |
| raise ValueError( | |
| "DSpark ignores --speculative-moe-a2a-backend; with dp attention it " | |
| f"must match the target moe_a2a_backend={server_args.moe_a2a_backend!r} " | |
| f"(got {server_args.speculative_moe_a2a_backend!r})." | |
| ) | |
| if server_args.pp_size != 1: | |
| raise ValueError( | |
| "Currently DSpark speculative decoding only supports pp_size == 1." | |
| ) | |
| if server_args.speculative_draft_model_path is None: | |
| if _target_checkpoint_bundles_dspark_draft(server_args): | |
| server_args.speculative_draft_model_path = server_args.model_path | |
| server_args.speculative_draft_model_revision = server_args.revision | |
| logger.info( | |
| "DSpark draft weights are bundled in the target checkpoint; " | |
| "defaulting --speculative-draft-model-path to --model-path (%s).", | |
| server_args.model_path, | |
| ) | |
| else: | |
| raise ValueError( | |
| "DSpark dense speculative decoding requires setting " | |
| "--speculative-draft-model-path." | |
| ) | |
| if server_args.speculative_num_steps is None: | |
| server_args.speculative_num_steps = 1 | |
| elif int(server_args.speculative_num_steps) != 1: | |
| logger.warning( | |
| "DSpark only supports speculative_num_steps == 1; overriding speculative_num_steps=%s to 1.", | |
| server_args.speculative_num_steps, | |
| ) | |
| server_args.speculative_num_steps = 1 | |
| if server_args.speculative_eagle_topk is None: | |
| server_args.speculative_eagle_topk = 1 | |
| elif int(server_args.speculative_eagle_topk) != 1: | |
| logger.warning( | |
| "DSpark only supports speculative_eagle_topk == 1; overriding speculative_eagle_topk=%s to 1.", | |
| server_args.speculative_eagle_topk, | |
| ) | |
| server_args.speculative_eagle_topk = 1 | |
| gamma: Optional[int] = None | |
| if server_args.speculative_dspark_block_size is not None: | |
| if int(server_args.speculative_dspark_block_size) <= 0: | |
| raise ValueError( | |
| "DSpark requires --speculative-dspark-block-size to be positive, " | |
| f"got {server_args.speculative_dspark_block_size}." | |
| ) | |
| gamma = int(server_args.speculative_dspark_block_size) | |
| else: | |
| from sglang.srt.speculative.dspark_components.dspark_config import ( | |
| DEFAULT_DSPARK_GAMMA, | |
| read_draft_checkpoint_gamma, | |
| ) | |
| try: | |
| gamma = read_draft_checkpoint_gamma(server_args=server_args) | |
| except Exception as e: | |
| logger.warning( | |
| "Failed to read DSpark gamma from draft model config; " | |
| "cannot cross-check --speculative-num-draft-tokens. Error: %s", | |
| e, | |
| ) | |
| if gamma is None and server_args.speculative_num_draft_tokens is None: | |
| gamma = DEFAULT_DSPARK_GAMMA | |
| logger.warning( | |
| "DSpark gamma is not set; defaulting to %d.", | |
| gamma, | |
| ) | |
| if gamma is not None: | |
| verify_window = int(gamma) + 1 | |
| if ( | |
| server_args.speculative_num_draft_tokens is not None | |
| and int(server_args.speculative_num_draft_tokens) != verify_window | |
| ): | |
| raise ValueError( | |
| "DSpark speculative_num_draft_tokens must equal gamma + 1 " | |
| f"(= {verify_window} for gamma={gamma}), but got " | |
| f"speculative_num_draft_tokens={server_args.speculative_num_draft_tokens}." | |
| ) | |
| server_args.speculative_num_draft_tokens = verify_window | |
| if server_args.speculative_num_draft_tokens is None: | |
| raise ValueError( | |
| "DSpark could not resolve speculative_num_draft_tokens; set " | |
| "--speculative-dspark-block-size (= gamma)." | |
| ) | |
| if int(server_args.speculative_num_draft_tokens) < 2: | |
| raise ValueError( | |
| "DSpark speculative_num_draft_tokens must be >= 2 (= gamma + 1), " | |
| f"got {server_args.speculative_num_draft_tokens}." | |
| ) | |
| if server_args.max_running_requests is None: | |
| server_args.max_running_requests = 48 | |
| logger.warning( | |
| "Max running requests is reset to 48 for speculative decoding. You can override this by explicitly setting --max-running-requests." | |
| ) | |
| if server_args.enable_mixed_chunk: | |
| server_args.enable_mixed_chunk = False | |
| logger.warning( | |
| "Mixed chunked prefill is disabled because of using dspark speculative decoding." | |
| ) | |
| from sglang.srt.speculative.ragged_verify import ( | |
| RaggedVerifyMode, | |
| read_ragged_verify_mode, | |
| ) | |
| ragged_mode = read_ragged_verify_mode() | |
| if ( | |
| server_args.speculative_dspark_align_verify_tokens_to_graph_tier | |
| and ragged_mode is not RaggedVerifyMode.COMPACT | |
| ): | |
| logger.warning( | |
| "--speculative-dspark-align-verify-tokens-to-graph-tier only takes " | |
| "effect with SGLANG_RAGGED_VERIFY_MODE=compact (got %r); it will be " | |
| "a no-op.", | |
| ragged_mode.value, | |
| ) | |
| if ( | |
| server_args.speculative_dspark_sps_table_path | |
| and ragged_mode is RaggedVerifyMode.STATIC | |
| ): | |
| logger.warning( | |
| "--speculative-dspark-sps-table-path feeds the ragged-verify budget " | |
| "scheduler, which is off under SGLANG_RAGGED_VERIFY_MODE=static; it " | |
| "will be a no-op." | |
| ) | |
| def _resolve_dflash_draft_attention_backend(server_args: ServerArgs) -> None: | |
| """Resolve `speculative_draft_attention_backend` to a final, supported value. | |
| Consumed by ModelRunner's `is_draft_worker` override (one backend for all | |
| draft modes). | |
| """ | |
| from sglang.srt.utils import is_hip | |
| supported_draft_backends = ("flashinfer", "fa3", "fa4", "triton", "ascend") | |
| # Use triton on ROCm (no FlashInfer), flashinfer on CUDA. | |
| fallback_backend = "triton" if is_hip() else "flashinfer" | |
| draft_backend = server_args.speculative_draft_attention_backend | |
| if draft_backend is None: | |
| from sglang.srt.arg_groups.overrides import ( | |
| attention_backends_of, | |
| resolved_view, | |
| ) | |
| draft_backend, _ = attention_backends_of(resolved_view(server_args)) | |
| if draft_backend is None: | |
| draft_backend = fallback_backend | |
| elif draft_backend == "trtllm_mha": | |
| logger.warning( | |
| "DFLASH draft worker does not support 'trtllm_mha' because the " | |
| "draft path requires per-layer DFlash attention. Falling back to " | |
| "'%s'.", | |
| fallback_backend, | |
| ) | |
| draft_backend = fallback_backend | |
| elif draft_backend not in supported_draft_backends: | |
| logger.warning( | |
| "DFLASH draft worker only supports attention_backend in %s for now, " | |
| "but got %r. Falling back to '%s'.", | |
| supported_draft_backends, | |
| draft_backend, | |
| fallback_backend, | |
| ) | |
| draft_backend = fallback_backend | |
| # FIXME: avoid overriding server args directly; pass the resolved draft | |
| # backend to the draft worker explicitly instead. | |
| server_args.speculative_draft_attention_backend = draft_backend | |
| def _handle_frozen_kv_mtp(server_args: ServerArgs) -> None: | |
| if server_args.max_running_requests is None: | |
| server_args.max_running_requests = 48 | |
| logger.warning( | |
| "Max running requests is reset to 48 for speculative decoding. You can override this by explicitly setting --max-running-requests." | |
| ) | |
| if server_args.enable_mixed_chunk: | |
| server_args.enable_mixed_chunk = False | |
| logger.warning( | |
| "Mixed chunked prefill is disabled because of using " | |
| "Frozen-KV MTP speculative decoding." | |
| ) | |
| def _handle_eagle_family(server_args: ServerArgs) -> None: | |
| from sglang.srt.arg_groups.overrides import ( | |
| attention_backends_of, | |
| resolved_view, | |
| ) | |
| if ( | |
| server_args.speculative_algorithm == "STANDALONE" | |
| and resolved_view(server_args).enable_dp_attention | |
| ): | |
| # TODO: support dp attention for standalone speculative decoding | |
| raise ValueError( | |
| "Currently standalone speculative decoding does not support dp attention." | |
| ) | |
| if server_args.max_running_requests is None: | |
| server_args.max_running_requests = 48 | |
| logger.warning( | |
| "Max running requests is reset to 48 for speculative decoding. You can override this by explicitly setting --max-running-requests." | |
| ) | |
| _disable_overlap_schedule_for_cpu(server_args) | |
| if resolved_view(server_args).disable_overlap_schedule: | |
| logger.warning( | |
| "Non-overlap (synchronous) spec v2 is used for eagle/eagle3/standalone " | |
| "speculative decoding." | |
| ) | |
| if server_args.enable_mixed_chunk: | |
| server_args.enable_mixed_chunk = False | |
| logger.warning( | |
| "Mixed chunked prefill is disabled because of using " | |
| "eagle speculative decoding." | |
| ) | |
| model_arch = server_args.get_model_config().hf_config.architectures[0] | |
| if model_arch in [ | |
| "DeepseekV32ForCausalLM", | |
| "DeepseekV3ForCausalLM", | |
| "AgnesForCausalLM", | |
| "Glm4MoeForCausalLM", | |
| "Glm4MoeLiteForCausalLM", | |
| "GlmMoeDsaForCausalLM", | |
| "BailingMoeForCausalLM", | |
| "BailingMoeV2ForCausalLM", | |
| "BailingMoeV2_5ForCausalLM", | |
| "MistralLarge3ForCausalLM", | |
| "PixtralForConditionalGeneration", | |
| "HYV3ForCausalLM", | |
| ]: | |
| if server_args.speculative_draft_model_path is None: | |
| server_args.speculative_draft_model_path = server_args.model_path | |
| server_args.speculative_draft_model_revision = server_args.revision | |
| else: | |
| if model_arch not in [ | |
| "MistralLarge3ForCausalLM", | |
| "PixtralForConditionalGeneration", | |
| ]: | |
| logger.warning( | |
| "DeepSeek MTP does not require setting speculative_draft_model_path." | |
| ) | |
| if ( | |
| not server_args.speculative_adaptive | |
| and server_args.speculative_num_steps is None | |
| ): | |
| assert ( | |
| server_args.speculative_eagle_topk is None | |
| and server_args.speculative_num_draft_tokens is None | |
| ) | |
| ( | |
| server_args.speculative_num_steps, | |
| server_args.speculative_eagle_topk, | |
| server_args.speculative_num_draft_tokens, | |
| ) = _auto_choose_speculative_params(server_args, model_arch) | |
| if "trtllm_mha" in attention_backends_of(resolved_view(server_args)): | |
| if server_args.speculative_eagle_topk > 1: | |
| raise ValueError( | |
| "trtllm_mha backend only supports topk = 1 for speculative decoding." | |
| ) | |
| if server_args.speculative_use_rejection_sampling: | |
| # Resolved alias by now: NEXTN -> EAGLE, Gemma4 draft -> FROZEN_KV_MTP. | |
| # Only the EAGLE/EAGLE3 draft workers emit a target-vocab proposal that | |
| # the rejection-sampling kernel consumes; everything else (STANDALONE, | |
| # FROZEN_KV_MTP, NGRAM, DFLASH) is unsupported. | |
| if server_args.speculative_algorithm not in ("EAGLE", "EAGLE3"): | |
| raise NotImplementedError( | |
| "--speculative-use-rejection-sampling is only supported for " | |
| "EAGLE / EAGLE3 / NEXTN, not " | |
| f"speculative_algorithm={server_args.speculative_algorithm}." | |
| ) | |
| if server_args.speculative_eagle_topk != 1: | |
| raise ValueError( | |
| "--speculative-use-rejection-sampling requires --speculative-eagle-topk=1." | |
| ) | |
| if ( | |
| server_args.speculative_accept_threshold_single != 1.0 | |
| or server_args.speculative_accept_threshold_acc != 1.0 | |
| ): | |
| raise ValueError( | |
| "--speculative-use-rejection-sampling is incompatible with " | |
| "--speculative-accept-threshold-single / " | |
| "--speculative-accept-threshold-acc; rejection sampling ignores " | |
| "the accept thresholds." | |
| ) | |
| if server_args.enable_deterministic_inference: | |
| raise ValueError( | |
| "--speculative-use-rejection-sampling is incompatible with " | |
| "--enable-deterministic-inference; the sampling kernel draws " | |
| "coins from the global RNG and is not batch-invariant." | |
| ) | |
| from sglang.srt.arg_groups.overrides import resolved_view | |
| if ( | |
| resolved_view(server_args).enable_multi_layer_eagle | |
| and server_args.speculative_eagle_topk != 1 | |
| ): | |
| raise ValueError( | |
| "--speculative-use-rejection-sampling with multi-layer EAGLE " | |
| "(--enable-multi-layer-eagle) requires --speculative-eagle-topk 1; " | |
| "rejection sampling is only implemented for the linear (topk=1) chain." | |
| ) | |
| logger.info( | |
| "Rejection sampling is enabled for speculative decoding " | |
| "(speculative_use_rejection_sampling=True)." | |
| ) | |
| if ( | |
| server_args.speculative_eagle_topk == 1 | |
| and server_args.speculative_num_draft_tokens | |
| != server_args.speculative_num_steps + 1 | |
| ): | |
| logger.warning( | |
| "speculative_num_draft_tokens is adjusted to speculative_num_steps + 1 when speculative_eagle_topk == 1" | |
| ) | |
| server_args.speculative_num_draft_tokens = server_args.speculative_num_steps + 1 | |
| # topk > 1 + page_size > 1 needs the two-pass cascade draft-decode (shared prefix | |
| # pass + per-branch expand pass with prefix-tail dup). Only these backends implement | |
| # it; flashmla / trtllm_mla / cutlass_mla can't express the per-branch tree, so reject. | |
| _PAGE_TREE_SPEC_BACKENDS = ("flashinfer", "fa3", "triton") | |
| view = resolved_view(server_args) | |
| if ( | |
| server_args.speculative_eagle_topk > 1 | |
| and view.page_size > 1 | |
| and view.attention_backend not in _PAGE_TREE_SPEC_BACKENDS | |
| ): | |
| raise ValueError( | |
| f"speculative_eagle_topk > 1 with page_size > 1 is only supported on " | |
| f"{_PAGE_TREE_SPEC_BACKENDS}; got attention_backend=" | |
| f"{view.attention_backend!r}. Use page_size == 1 or one of those backends." | |
| ) | |
| def _handle_ngram(server_args: ServerArgs) -> None: | |
| if server_args.device not in ("cuda", "cpu"): | |
| raise ValueError( | |
| "Ngram speculative decoding only supports CUDA or CPU devices." | |
| ) | |
| _disable_overlap_schedule_for_cpu(server_args) | |
| if server_args.max_running_requests is None: | |
| server_args.max_running_requests = 48 | |
| logger.warning( | |
| "Max running requests is reset to 48 for speculative decoding. You can override this by explicitly setting --max-running-requests." | |
| ) | |
| server_args.enable_mixed_chunk = False | |
| server_args.speculative_eagle_topk = server_args.speculative_ngram_max_bfs_breadth | |
| if server_args.speculative_num_draft_tokens is None: | |
| server_args.speculative_num_draft_tokens = 12 | |
| logger.warning( | |
| "speculative_num_draft_tokens is set to 12 by default for ngram speculative decoding. " | |
| "You can override this by explicitly setting --speculative-num-draft-tokens." | |
| ) | |
| if server_args.speculative_num_steps is None: | |
| server_args.speculative_num_steps = ( | |
| server_args.speculative_num_draft_tokens | |
| // server_args.speculative_eagle_topk | |
| ) | |
| if server_args.speculative_ngram_external_corpus_path is not None: | |
| if server_args.speculative_ngram_external_sam_budget <= 0: | |
| raise ValueError( | |
| "--speculative-ngram-external-sam-budget must be positive when " | |
| "--speculative-ngram-external-corpus-path is set." | |
| ) | |
| if server_args.speculative_ngram_external_corpus_max_tokens <= 0: | |
| raise ValueError( | |
| "--speculative-ngram-external-corpus-max-tokens must be positive when " | |
| "--speculative-ngram-external-corpus-path is set." | |
| ) | |
| if ( | |
| server_args.speculative_ngram_external_sam_budget | |
| > server_args.speculative_num_draft_tokens - 1 | |
| ): | |
| raise ValueError( | |
| "speculative_ngram_external_sam_budget must be less than or equal to " | |
| f"speculative_num_draft_tokens - 1 ({server_args.speculative_num_draft_tokens - 1})." | |
| ) | |
| logger.warning( | |
| "The mixed chunked prefill are disabled because of " | |
| "using ngram speculative decoding." | |
| ) | |
| from sglang.srt.arg_groups.overrides import resolved_view | |
| view = resolved_view(server_args) | |
| if ( | |
| server_args.speculative_eagle_topk > 1 | |
| and view.page_size > 1 | |
| and view.attention_backend != "flashinfer" | |
| ): | |
| raise ValueError( | |
| f"speculative_eagle_topk({server_args.speculative_eagle_topk}) > 1 " | |
| f"with page_size({view.page_size}) > 1 is unstable " | |
| "and produces incorrect results for paged attention backends. " | |
| "This combination is only supported for the 'flashinfer' backend." | |
| ) | |
| if view.enable_dp_attention: | |
| # TODO: support dp attention for ngram speculative decoding | |
| raise ValueError( | |
| "Currently ngram speculative decoding does not support dp attention." | |
| ) | |
| def _maybe_disable_adaptive(server_args: ServerArgs) -> None: | |
| from sglang.srt.speculative.adaptive_spec_params import ( | |
| adaptive_unsupported_reason, | |
| ) | |
| reason = adaptive_unsupported_reason(server_args) | |
| if reason is not None: | |
| logger.warning( | |
| f"speculative_adaptive disabled: {reason}. " | |
| "Falling back to static speculative params." | |
| ) | |
| server_args.speculative_adaptive = False | |
| def _init_adaptive_speculative_params(server_args: ServerArgs) -> None: | |
| from sglang.srt.speculative.adaptive_spec_params import ( | |
| resolve_candidate_steps_from_config, | |
| ) | |
| candidate_steps = resolve_candidate_steps_from_config( | |
| cfg_path=server_args.speculative_adaptive_config, | |
| ) | |
| if server_args.speculative_eagle_topk is None: | |
| server_args.speculative_eagle_topk = 1 | |
| if server_args.speculative_num_steps is None: | |
| server_args.speculative_num_steps = candidate_steps[len(candidate_steps) // 2] | |
| if server_args.speculative_num_steps not in candidate_steps: | |
| raise ValueError( | |
| f"--speculative-num-steps={server_args.speculative_num_steps} " | |
| f"is not in the adaptive config candidate_steps {candidate_steps}. " | |
| "Pass one of those values." | |
| ) | |
| server_args.speculative_num_draft_tokens = server_args.speculative_num_steps + 1 | |
| def _auto_choose_speculative_params(server_args: ServerArgs, model_arch: str) -> tuple: | |
| """ | |
| Automatically choose the parameters for speculative decoding. | |
| You can tune them on your own models and prompts with scripts/playground/bench_speculative.py | |
| """ | |
| if server_args.speculative_algorithm == "STANDALONE": | |
| return (3, 1, 4) | |
| if model_arch in ["LlamaForCausalLM"]: | |
| return (5, 4, 8) | |
| elif model_arch in [ | |
| "DeepseekV32ForCausalLM", | |
| "DeepseekV3ForCausalLM", | |
| "DeepseekV2ForCausalLM", | |
| "GptOssForCausalLM", | |
| "Glm4MoeForCausalLM", | |
| "Glm4MoeLiteForCausalLM", | |
| "GlmMoeDsaForCausalLM", | |
| "BailingMoeForCausalLM", | |
| "BailingMoeV2ForCausalLM", | |
| "BailingMoeV2_5ForCausalLM", | |
| "MistralLarge3ForCausalLM", | |
| "PixtralForConditionalGeneration", | |
| "MiMoV2ForCausalLM", | |
| "MiMoV2FlashForCausalLM", | |
| ]: | |
| return (3, 1, 4) | |
| elif model_arch in ["Grok1ForCausalLM", "Grok1VForCausalLM"]: | |
| return (5, 4, 8) | |
| else: | |
| return (3, 1, 4) | |