From 5742a34df180a6c17409f1eb038b7409429905d0 Mon Sep 17 00:00:00 2001 From: Tai An Date: Fri, 24 Jul 2026 00:22:30 -0700 Subject: [PATCH] docs(sampling): clarify that sampler override presets resolve from the CWD (#419) The sampler override preset name is turned into the relative path `sampler_overrides/.yml`, so it is resolved against the process's current working directory rather than the TabbyAPI install directory. Nothing said that, and the "Make sure it's located in the sampler_overrides folder" error did not say which sampler_overrides folder was searched, so launching TabbyAPI from another directory looked like a missing-file bug. - Hoist the lookup directory into a documented SAMPLER_OVERRIDES_DIR constant shared by overrides_from_file() and get_all_presets(). - Report the resolved path and the current working directory in the not-found error. - Say in the docstrings, the config description, config_sample.yml, and the docs that the value is a preset name (not a path) resolved relative to the launch directory. No behaviour change. --- common/config_models.py | 4 +++- common/sampling.py | 33 ++++++++++++++++++++++++++------- config_sample.yml | 2 +- docs/02.-Server-options.md | 2 +- docs/08.-Sampler-Overrides.md | 5 +++++ 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/common/config_models.py b/common/config_models.py index 178e23be..1bfc3f3c 100644 --- a/common/config_models.py +++ b/common/config_models.py @@ -462,7 +462,9 @@ class SamplingConfig(BaseConfigModel): None, description=( "Select a sampler override preset (default: None).\n" - "Find this in the sampler-overrides folder.\n" + "This is a preset name, not a path: TabbyAPI reads " + "sampler_overrides/.yml relative to the directory it is " + "launched from.\n" "This overrides default fallbacks for sampler values " "that are passed to the API.\n" "NOTE: safe_defaults preset provides a fallback for frontends " diff --git a/common/sampling.py b/common/sampling.py index 94533642..7bee5a43 100644 --- a/common/sampling.py +++ b/common/sampling.py @@ -19,6 +19,11 @@ from common.utils import filter_none_values, unwrap +# Directory that sampler override presets are looked up in. This is a relative +# path, so it resolves against the current working directory (where TabbyAPI +# was launched from) rather than the directory TabbyAPI is installed in. +SAMPLER_OVERRIDES_DIR = pathlib.Path("sampler_overrides") + # 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. @@ -408,9 +413,16 @@ def overrides_from_dict(new_overrides: dict): async def overrides_from_file(preset_name: str): - """Fetches an override preset from a file""" + """ + Fetches an override preset from a file. + + The preset name is not a path: it is looked up as + `sampler_overrides/.yml` relative to the current working + directory, so TabbyAPI has to be launched from the directory that holds + the `sampler_overrides` folder. + """ - preset_path = pathlib.Path(f"sampler_overrides/{preset_name}.yml") + preset_path = SAMPLER_OVERRIDES_DIR / f"{preset_name}.yml" if preset_path.exists(): overrides_container.selected_preset = preset_path.stem async with aiofiles.open(preset_path, "r", encoding="utf8") as raw_preset: @@ -424,18 +436,25 @@ async def overrides_from_file(preset_name: str): xlogger.info("Applied sampler overrides from file.", {"preset": preset}) else: error_message = ( - f'Sampler override file named "{preset_name}" was not found. ' - + "Make sure it's located in the sampler_overrides folder." + f'Sampler override file named "{preset_name}" was not found at ' + f"{preset_path.resolve()}. Presets are read from the " + f'"{SAMPLER_OVERRIDES_DIR}" folder relative to the current working ' + f"directory ({pathlib.Path.cwd()}), so make sure the file is there " + "and that TabbyAPI is launched from that directory." ) raise FileNotFoundError(error_message) def get_all_presets(): - """Fetches all sampler override presets from the overrides directory""" + """ + Fetches all sampler override presets from the overrides directory. + + Uses the same lookup as `overrides_from_file`: the `sampler_overrides` + folder relative to the current working directory. + """ - override_directory = pathlib.Path("sampler_overrides") - preset_files = [file.stem for file in override_directory.glob("*.yml")] + preset_files = [file.stem for file in SAMPLER_OVERRIDES_DIR.glob("*.yml")] return preset_files diff --git a/config_sample.yml b/config_sample.yml index 601e90fb..aec0b690 100644 --- a/config_sample.yml +++ b/config_sample.yml @@ -256,7 +256,7 @@ draft_model: # Options for Sampling sampling: # Select a sampler override preset (default: None). - # Find this in the sampler-overrides folder. + # This is a preset name, not a path: TabbyAPI reads sampler_overrides/.yml relative to the directory it is launched from. # This overrides default fallbacks for sampler values that are passed to the API. # NOTE: safe_defaults is noob friendly and provides fallbacks for frontends that don't send sampling parameters. # Remove this for any advanced usage. diff --git a/docs/02.-Server-options.md b/docs/02.-Server-options.md index ef6ace7c..cde364a5 100644 --- a/docs/02.-Server-options.md +++ b/docs/02.-Server-options.md @@ -39,7 +39,7 @@ Note: This block is for sampling overrides, not samplers themselves. | Config Option | Type (Default) | Description | | --------------- | -------------- | ------------------------------------------------------------------------- | -| override_preset | String (None) | Startup the given sampler override preset in the sampler_overrides folder | +| override_preset | String (None) | Startup the given sampler override preset. This is a preset name, not a path: it is read from `sampler_overrides/.yml` relative to the directory TabbyAPI is launched from | ### Developer Options diff --git a/docs/08.-Sampler-Overrides.md b/docs/08.-Sampler-Overrides.md index 89258e46..755dbbb1 100644 --- a/docs/08.-Sampler-Overrides.md +++ b/docs/08.-Sampler-Overrides.md @@ -7,6 +7,11 @@ Sampler overrides is tabbyAPI's flexible proxy for adding or forcing sampler val All supported samplers are located in `sampler_overrides/sample_preset.yml`. +> [!IMPORTANT] +> `sampler_overrides` is a **relative** path. TabbyAPI resolves it against the current working directory — the directory you launch TabbyAPI from — not against the directory TabbyAPI is installed in. If you start TabbyAPI from somewhere else, it will look for `sampler_overrides` there and report that the preset was not found. +> +> The value you configure is a preset *name*, not a file path: a preset named `my_preset` is read from `sampler_overrides/my_preset.yml`. + > [!NOTE] > Sampler overrides can also be switched at runtime via the `/v1/sampling/override` endpoint set. Please read the [API docs](https://theroyallab.github.io/tabbyAPI/#operation/list_sampler_overrides_v1_sampling_override_list_get) for more information.