From c027fa3318d244711e5967d26e5c19e31fd2e359 Mon Sep 17 00:00:00 2001 From: turboderp <11859846+turboderp@users.noreply.github.com> Date: Wed, 15 Jul 2026 03:09:13 +0200 Subject: [PATCH] Sampling: Remove sampling parameters not supported by exllamav3, warn when unsupported args given with request, wire in already-supported min_tokens and token_healing --- backends/exllamav3/model.py | 2 + common/sampling.py | 66 ++++++++++++++++++++++------- sampler_overrides/sample_preset.yml | 12 ------ 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/backends/exllamav3/model.py b/backends/exllamav3/model.py index ce0f3c0..e94bcba 100644 --- a/backends/exllamav3/model.py +++ b/backends/exllamav3/model.py @@ -1192,6 +1192,8 @@ class ExllamaV3Container: sampler=sampler, input_ids=input_ids, max_new_tokens=max_tokens, + min_new_tokens=unwrap(params.min_tokens, 0), + token_healing=unwrap(params.token_healing, False), stop_conditions=stop_conditions, banned_strings=params.banned_strings, embeddings=mm_embeddings_content, diff --git a/common/sampling.py b/common/sampling.py index a665b7d..cc29280 100644 --- a/common/sampling.py +++ b/common/sampling.py @@ -19,6 +19,28 @@ from typing import Dict, List, Optional, Union from common.utils import filter_none_values, unwrap +# Params that are accepted for API compatibility but not implemented by the +# exllamav3 backend, mapped to the neutral value that leaves them inactive. +# Requests that activate any of these get a warning and the param is ignored. +UNSUPPORTED_PARAMS = { + "ban_eos_token": False, + "banned_tokens": [], + "allowed_tokens": [], + "smoothing_factor": 0.0, + "top_a": 0.0, + "tfs": 1.0, + "typical": 1.0, + "skew": 0.0, + "xtc_probability": 0.0, + "dry_multiplier": 0.0, + "mirostat_mode": 0, + "logit_bias": None, + "temp_exponent": 1.0, + "regex_pattern": None, + "grammar_string": None, +} + + # Common class for sampler params class BaseSamplerRequest(BaseModel): """Common class for sampler params that are used in APIs""" @@ -212,10 +234,6 @@ class BaseSamplerRequest(BaseModel): examples=[{"1": 10, "2": 50}], ) - negative_prompt: Optional[str] = Field( - default_factory=lambda: get_default_sampler_value("negative_prompt") - ) - json_schema: Optional[object] = Field( default_factory=lambda: get_default_sampler_value("json_schema"), ) @@ -228,17 +246,6 @@ class BaseSamplerRequest(BaseModel): default_factory=lambda: get_default_sampler_value("grammar_string"), ) - speculative_ngram: Optional[bool] = Field( - default_factory=lambda: get_default_sampler_value("speculative_ngram"), - ) - - cfg_scale: Optional[float] = Field( - default_factory=lambda: get_default_sampler_value("cfg_scale", 1.0), - validation_alias=AliasChoices("cfg_scale", "guidance_scale"), - description="Aliases: guidance_scale", - examples=[1.0], - ) - max_temp: Optional[float] = Field( default_factory=lambda: get_default_sampler_value("max_temp", 1.0), validation_alias=AliasChoices("max_temp", "dynatemp_high"), @@ -356,8 +363,33 @@ class BaseSamplerRequest(BaseModel): if self.min_tokens and self.max_tokens and self.min_tokens > self.max_tokens: raise ValidationError("min tokens cannot be more then max tokens") + self.warn_unsupported_params() + return self + def warn_unsupported_params(self): + """Warn when the request activates params the backend doesn't implement.""" + + active = [ + name + for name, neutral in UNSUPPORTED_PARAMS.items() + if getattr(self, name) and getattr(self, name) != neutral + ] + + # Dynamic temperature is only in effect when the bounds differ + if ( + self.min_temp is not None + and self.max_temp is not None + and self.min_temp != self.max_temp + ): + active.append("min_temp/max_temp") + + if active: + xlogger.warning( + "Ignoring sampler params not supported by the exllamav3 backend: " + + ", ".join(active) + ) + class SamplerOverridesContainer(BaseModel): selected_preset: Optional[str] = None @@ -431,6 +463,10 @@ def apply_forced_sampler_overrides(params: BaseSamplerRequest): params.top_logprobs = params.logprobs for var, value in overrides_container.overrides.items(): + if var not in BaseSamplerRequest.model_fields: + xlogger.warning(f'Skipping unknown sampler override key "{var}"') + continue + override = deepcopy(value.get("override")) original_value = getattr(params, var, None) diff --git a/sampler_overrides/sample_preset.yml b/sampler_overrides/sample_preset.yml index 98b20d3..eb18a17 100644 --- a/sampler_overrides/sample_preset.yml +++ b/sampler_overrides/sample_preset.yml @@ -25,10 +25,6 @@ banned_strings: token_healing: override: false force: false -speculative_ngram: - override: false - force: false - # Commented out because the default is dynamically scaled #generate_window: #override: 512 @@ -149,14 +145,6 @@ allowed_tokens: force: false additive: false -# MARK: CFG scale -cfg_scale: - override: 1.0 - force: false -negative_prompt: - override: - force: false - # MARK: Adaptive-P adaptive_target: override: 1.0