Studio: enforce 60s minimum on idle auto-unload TTL (0 stays off) (#7185)
* Studio: enforce 60s minimum on idle auto-unload TTL (0 stays off) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Drop decorative section separator from idle TTL floor tests --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Han <danielhanchen@gmail.com> Co-authored-by: danielhanchen <unslothshared@gmail.com>
This commit is contained in:
parent
030524ae8e
commit
e9ef2ac60f
14 changed files with 125 additions and 32 deletions
|
|
@ -1609,11 +1609,11 @@ def test_env_idle_ttl_standalone_when_no_stored_value(monkeypatch):
|
|||
def test_stored_idle_value_overrides_env_and_stays_gated(monkeypatch):
|
||||
# An explicit stored value wins over the env default and remains gated on the
|
||||
# auto-switch toggle.
|
||||
store = {settings.AUTO_UNLOAD_IDLE_SETTING_KEY: 30}
|
||||
store = {settings.AUTO_UNLOAD_IDLE_SETTING_KEY: 90}
|
||||
monkeypatch.setattr(settings, "_cached_setting", lambda k, d = None: store.get(k, d))
|
||||
monkeypatch.setenv("UNSLOTH_MODEL_IDLE_TTL", "600")
|
||||
monkeypatch.setattr(settings, "get_openai_auto_switch_enabled", lambda: True)
|
||||
assert settings.get_auto_unload_idle_seconds() == 30 # stored wins, not env
|
||||
assert settings.get_auto_unload_idle_seconds() == 90 # stored wins, not env
|
||||
monkeypatch.setattr(settings, "get_openai_auto_switch_enabled", lambda: False)
|
||||
assert settings.get_auto_unload_idle_seconds() == 0 # explicit value still gated off
|
||||
|
||||
|
|
@ -3094,3 +3094,53 @@ def test_responses_stream_hint_matches_toggle_regardless_of_active_model(monkeyp
|
|||
monkeypatch, enabled = False, active_model_name = "unsloth/Llama-3.2-1B-Instruct"
|
||||
)
|
||||
assert "Model auto-switch" in non_gguf_loaded
|
||||
|
||||
|
||||
def test_setter_rejects_idle_below_floor(monkeypatch):
|
||||
import storage.studio_db as db
|
||||
|
||||
writes = []
|
||||
monkeypatch.setattr(db, "upsert_app_settings", lambda m: writes.append(dict(m)))
|
||||
settings._cache.clear()
|
||||
|
||||
with pytest.raises(ValueError, match = "at least 60"):
|
||||
settings.set_openai_auto_switch(True, 30)
|
||||
assert writes == [] # rejected before any persist
|
||||
# 0 (off) and >= 60 pass through unchanged.
|
||||
assert settings.set_openai_auto_switch(True, 0)[1] == 0
|
||||
assert settings.set_openai_auto_switch(True, 60)[1] == 60
|
||||
assert settings.set_openai_auto_switch(True, 3600)[1] == 3600
|
||||
|
||||
|
||||
def test_put_route_rejects_idle_below_floor():
|
||||
import routes.settings as settings_route
|
||||
from fastapi import HTTPException
|
||||
|
||||
payload = settings_route.OpenAIAutoSwitchPayload(enabled = True, auto_unload_idle_seconds = 30)
|
||||
with pytest.raises(HTTPException) as excinfo:
|
||||
settings_route.update_openai_auto_switch(payload, "tester")
|
||||
assert excinfo.value.status_code == 400
|
||||
|
||||
|
||||
def test_stored_legacy_idle_below_floor_is_clamped(monkeypatch):
|
||||
# Values persisted before the floor existed are raised to it on read, for
|
||||
# both the effective TTL and the value the settings UI displays.
|
||||
store = {settings.AUTO_UNLOAD_IDLE_SETTING_KEY: 5}
|
||||
monkeypatch.setattr(settings, "_cached_setting", lambda k, d = None: store.get(k, d))
|
||||
monkeypatch.setattr(settings, "get_openai_auto_switch_enabled", lambda: True)
|
||||
assert settings.get_auto_unload_idle_seconds() == 60
|
||||
assert settings.get_stored_auto_unload_idle_seconds() == 60
|
||||
store[settings.AUTO_UNLOAD_IDLE_SETTING_KEY] = 90
|
||||
assert settings.get_auto_unload_idle_seconds() == 90
|
||||
|
||||
|
||||
def test_env_idle_below_floor_is_clamped(monkeypatch):
|
||||
monkeypatch.setattr(settings, "_cached_setting", lambda k, d = None: d)
|
||||
monkeypatch.setenv(settings.MODEL_IDLE_TTL_ENV_VAR, "5")
|
||||
assert settings.get_auto_unload_idle_seconds() == 60
|
||||
monkeypatch.setenv(settings.MODEL_IDLE_TTL_ENV_VAR, "0")
|
||||
assert settings.get_auto_unload_idle_seconds() == 0
|
||||
monkeypatch.setenv(settings.MODEL_IDLE_TTL_ENV_VAR, "600")
|
||||
assert settings.get_auto_unload_idle_seconds() == 600
|
||||
monkeypatch.delenv(settings.MODEL_IDLE_TTL_ENV_VAR)
|
||||
assert settings.get_auto_unload_idle_seconds() == 0
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ Two settings, both off by default so existing API behavior is unchanged:
|
|||
names a downloaded local GGUF different from the loaded one transparently
|
||||
loads it before serving (llama-swap-style). Unknown names pass through.
|
||||
- ``openai_api_auto_unload_idle_seconds``: when > 0, the loaded GGUF is
|
||||
unloaded after this many idle seconds to free VRAM.
|
||||
unloaded after this many idle seconds to free VRAM. Enabled values have a
|
||||
60s floor (0 stays "off"): a tiny TTL tears the model down between turns of
|
||||
an active chat, forcing a full weight reload + prompt re-prefill per turn.
|
||||
|
||||
The idle TTL can also be set at startup via the ``UNSLOTH_MODEL_IDLE_TTL`` env
|
||||
var. Unlike the stored setting (which stays gated on auto-switch), the env value
|
||||
|
|
@ -33,6 +35,7 @@ MODEL_IDLE_TTL_ENV_VAR = "UNSLOTH_MODEL_IDLE_TTL"
|
|||
|
||||
DEFAULT_OPENAI_AUTO_SWITCH_ENABLED = False
|
||||
DEFAULT_AUTO_UNLOAD_IDLE_SECONDS = 0
|
||||
MIN_AUTO_UNLOAD_IDLE_SECONDS = 60
|
||||
|
||||
_CACHE_TTL_S = 2.0
|
||||
_cache_lock = threading.Lock()
|
||||
|
|
@ -58,6 +61,10 @@ def _coerce_int(value: Any) -> int | None:
|
|||
return None
|
||||
|
||||
|
||||
def _apply_idle_floor(seconds: int) -> int:
|
||||
return 0 if seconds <= 0 else max(MIN_AUTO_UNLOAD_IDLE_SECONDS, seconds)
|
||||
|
||||
|
||||
def _cached_setting(key: str, default: Any) -> Any:
|
||||
"""Read an app setting, memoized for _CACHE_TTL_S to spare the hot path."""
|
||||
now = time.monotonic()
|
||||
|
|
@ -91,12 +98,34 @@ def _stored_idle_seconds() -> Optional[int]:
|
|||
return _coerce_int(_cached_setting(AUTO_UNLOAD_IDLE_SETTING_KEY, None))
|
||||
|
||||
|
||||
_env_floor_warned = False
|
||||
|
||||
|
||||
def _env_idle_seconds() -> Optional[int]:
|
||||
"""UNSLOTH_MODEL_IDLE_TTL as a non-negative seconds value, or None if unset/invalid."""
|
||||
"""UNSLOTH_MODEL_IDLE_TTL as a non-negative seconds value, or None if unset/invalid.
|
||||
|
||||
Floored to MIN_AUTO_UNLOAD_IDLE_SECONDS here (with a one-time warning) since
|
||||
headless/container deploys have no UI to surface a validation error."""
|
||||
raw = os.environ.get(MODEL_IDLE_TTL_ENV_VAR)
|
||||
if raw is None or not raw.strip():
|
||||
return None
|
||||
return _coerce_int(raw)
|
||||
parsed = _coerce_int(raw)
|
||||
if parsed is None:
|
||||
return None
|
||||
floored = _apply_idle_floor(parsed)
|
||||
if floored != parsed:
|
||||
global _env_floor_warned
|
||||
if not _env_floor_warned:
|
||||
_env_floor_warned = True
|
||||
from loggers import get_logger
|
||||
get_logger(__name__).warning(
|
||||
"%s=%s is below the %ss minimum; using %ss",
|
||||
MODEL_IDLE_TTL_ENV_VAR,
|
||||
parsed,
|
||||
MIN_AUTO_UNLOAD_IDLE_SECONDS,
|
||||
floored,
|
||||
)
|
||||
return floored
|
||||
|
||||
|
||||
def get_stored_auto_unload_idle_seconds() -> int:
|
||||
|
|
@ -108,7 +137,9 @@ def get_stored_auto_unload_idle_seconds() -> int:
|
|||
"""
|
||||
stored = _stored_idle_seconds()
|
||||
if stored is not None:
|
||||
return stored
|
||||
# Floor legacy values persisted before the minimum existed, so the UI
|
||||
# displays the effective TTL and round-trips it cleanly.
|
||||
return _apply_idle_floor(stored)
|
||||
env = _env_idle_seconds()
|
||||
return env if env is not None else DEFAULT_AUTO_UNLOAD_IDLE_SECONDS
|
||||
|
||||
|
|
@ -118,8 +149,9 @@ def get_auto_unload_idle_seconds() -> int:
|
|||
stored = _stored_idle_seconds()
|
||||
if stored is not None:
|
||||
# An explicit UI/API value stays gated on auto-switch: off reports 0 so the
|
||||
# off state is identical to pre-feature.
|
||||
return stored if get_openai_auto_switch_enabled() else 0
|
||||
# off state is identical to pre-feature. Floored to cover values persisted
|
||||
# before the minimum existed.
|
||||
return _apply_idle_floor(stored) if get_openai_auto_switch_enabled() else 0
|
||||
# No stored value: UNSLOTH_MODEL_IDLE_TTL is a standalone startup default that
|
||||
# enables idle-unload even with auto-switch off (headless/container deploys).
|
||||
env = _env_idle_seconds()
|
||||
|
|
@ -136,6 +168,11 @@ def set_openai_auto_switch(enabled: Any, idle_seconds: Any) -> tuple[bool, int]:
|
|||
parsed_idle = _coerce_int(idle_seconds)
|
||||
if parsed_idle is None:
|
||||
raise ValueError("Auto-unload idle seconds must be a non-negative integer.")
|
||||
if 0 < parsed_idle < MIN_AUTO_UNLOAD_IDLE_SECONDS:
|
||||
raise ValueError(
|
||||
f"Auto-unload idle seconds must be 0 (off) or at least "
|
||||
f"{MIN_AUTO_UNLOAD_IDLE_SECONDS}."
|
||||
)
|
||||
from storage.studio_db import upsert_app_settings
|
||||
|
||||
upsert_app_settings(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ import {
|
|||
import { SettingsRow } from "./settings-row";
|
||||
import { SettingsSection } from "./settings-section";
|
||||
|
||||
// Mirrors MIN_AUTO_UNLOAD_IDLE_SECONDS in the backend settings store.
|
||||
const MIN_IDLE_SECONDS = 60;
|
||||
|
||||
export function ModelAutoSwitchSection() {
|
||||
const t = useT();
|
||||
const [settings, setSettings] = useState<OpenAIAutoSwitchSettings | null>(
|
||||
|
|
@ -45,13 +48,16 @@ export function ModelAutoSwitchSection() {
|
|||
};
|
||||
}, [t]);
|
||||
|
||||
// Parse the idle-seconds draft to a non-negative integer; empty/invalid -> null.
|
||||
// Parse the idle-seconds draft: 0 (off) or >= MIN_IDLE_SECONDS; else null.
|
||||
const parseIdleSeconds = (): number | null => {
|
||||
if (!draftIdleSeconds.trim()) {
|
||||
return null;
|
||||
}
|
||||
const parsed = Number(draftIdleSeconds);
|
||||
return Number.isInteger(parsed) && parsed >= 0 ? parsed : null;
|
||||
if (!Number.isInteger(parsed)) {
|
||||
return null;
|
||||
}
|
||||
return parsed === 0 || parsed >= MIN_IDLE_SECONDS ? parsed : null;
|
||||
};
|
||||
|
||||
const persist = async (
|
||||
|
|
|
|||
|
|
@ -155,14 +155,14 @@ export const ar = {
|
|||
"عندما يسمّي طلب متوافق مع OpenAI ملف GGUF مُنزّلاً مختلفًا، يتم تحميله قبل الخدمة. مُعطّل افتراضيًا؛ الأسماء غير المعروفة تُبقي على النموذج المُحمَّل.",
|
||||
idleUnload: "الإلغاء التلقائي عند الخمول",
|
||||
idleUnloadDescription:
|
||||
"إلغاء تحميل النموذج بعد هذا العدد من ثواني الخمول لتحرير الـ VRAM؛ الطلب التالي يعيد تحميله. القيمة 0 تُبقيه محمَّلاً.",
|
||||
"إلغاء تحميل النموذج بعد هذا العدد من ثواني الخمول لتحرير الـ VRAM؛ الطلب التالي يعيد تحميله. القيمة 0 تُبقيه محمَّلاً. الحد الأدنى 60 ثانية.",
|
||||
idleNeedsEnable:
|
||||
"فعّل تبديل النموذج حسب الطلب حتى يعاد تحميل النموذج غير المحمَّل عند الاستخدام التالي.",
|
||||
idleActiveViaEnv:
|
||||
"الإلغاء التلقائي عند الخمول مُفعَّل عبر متغير البيئة UNSLOTH_MODEL_IDLE_TTL.",
|
||||
loadError: "فشل تحميل إعدادات التبديل التلقائي للنموذج.",
|
||||
saveError: "فشل حفظ إعدادات التبديل التلقائي للنموذج.",
|
||||
idleError: "أدخل عددًا صحيحًا من الثواني (0 أو أكثر).",
|
||||
idleError: "أدخل 0 لإبقاء النموذج محمَّلاً، أو 60 ثانية على الأقل.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "مشاركة المعاينة",
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ export const de = {
|
|||
"Wenn eine OpenAI-kompatible Anfrage ein anderes heruntergeladenes GGUF nennt, wird dieses vor der Auslieferung geladen. Standardmäßig aus; unbekannte Namen liefern weiterhin das geladene Modell aus.",
|
||||
idleUnload: "Automatisches Entladen bei Inaktivität",
|
||||
idleUnloadDescription:
|
||||
"Entlädt das Modell nach dieser Anzahl inaktiver Sekunden, um VRAM freizugeben; die nächste Anfrage lädt es erneut. 0 hält es geladen.",
|
||||
"Entlädt das Modell nach dieser Anzahl inaktiver Sekunden, um VRAM freizugeben; die nächste Anfrage lädt es erneut. 0 hält es geladen. Minimum 60 Sekunden.",
|
||||
idleNeedsEnable:
|
||||
"Aktivieren Sie \"Modell je Anfrage wechseln\", damit ein entladenes Modell bei der nächsten Nutzung erneut geladen wird.",
|
||||
idleActiveViaEnv:
|
||||
|
|
@ -167,7 +167,7 @@ export const de = {
|
|||
"Einstellungen für automatischen Modellwechsel konnten nicht geladen werden.",
|
||||
saveError:
|
||||
"Einstellungen für automatischen Modellwechsel konnten nicht gespeichert werden.",
|
||||
idleError: "Geben Sie eine ganze Anzahl an Sekunden ein (0 oder mehr).",
|
||||
idleError: "Geben Sie 0 ein, um das Modell geladen zu halten, oder mindestens 60 Sekunden.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "Vorschau-Freigabe",
|
||||
|
|
|
|||
|
|
@ -224,14 +224,14 @@ export const en = {
|
|||
"When an OpenAI-compatible request names a different downloaded GGUF, load it before serving. Off by default; unknown names keep serving the loaded model.",
|
||||
idleUnload: "Idle auto-unload",
|
||||
idleUnloadDescription:
|
||||
"Unload the model after this many idle seconds to free VRAM; the next request reloads it. 0 keeps it loaded.",
|
||||
"Unload the model after this many idle seconds to free VRAM; the next request reloads it. 0 keeps it loaded. Minimum 60 seconds.",
|
||||
idleNeedsEnable:
|
||||
"Turn on Switch model by request so an unloaded model reloads on next use.",
|
||||
idleActiveViaEnv:
|
||||
"Idle auto-unload is active via the UNSLOTH_MODEL_IDLE_TTL environment variable.",
|
||||
loadError: "Failed to load model auto-switch settings.",
|
||||
saveError: "Failed to save model auto-switch settings.",
|
||||
idleError: "Enter a whole number of seconds (0 or more).",
|
||||
idleError: "Enter 0 to keep the model loaded, or at least 60 seconds.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "Preview sharing",
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ export const es = {
|
|||
"Cuando una solicitud compatible con OpenAI nombra un GGUF descargado distinto, se carga antes de responder. Desactivado por defecto; los nombres desconocidos siguen usando el modelo cargado.",
|
||||
idleUnload: "Descarga automática por inactividad",
|
||||
idleUnloadDescription:
|
||||
"Descarga el modelo tras este número de segundos inactivo para liberar VRAM; la siguiente solicitud lo recarga. 0 lo mantiene cargado.",
|
||||
"Descarga el modelo tras este número de segundos inactivo para liberar VRAM; la siguiente solicitud lo recarga. 0 lo mantiene cargado. Mínimo 60 segundos.",
|
||||
idleNeedsEnable:
|
||||
"Activa Cambiar de modelo según la solicitud para que un modelo descargado se recargue en el próximo uso.",
|
||||
idleActiveViaEnv:
|
||||
|
|
@ -166,7 +166,7 @@ export const es = {
|
|||
"No se pudo cargar la configuración de cambio automático de modelo.",
|
||||
saveError:
|
||||
"No se pudo guardar la configuración de cambio automático de modelo.",
|
||||
idleError: "Introduce un número entero de segundos (0 o más).",
|
||||
idleError: "Introduce 0 para mantener el modelo cargado, o al menos 60 segundos.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "Compartir vista previa",
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ export const fr = {
|
|||
"Lorsqu'une requête compatible OpenAI nomme un autre GGUF téléchargé, le charger avant de répondre. Désactivé par défaut ; les noms inconnus continuent de servir le modèle chargé.",
|
||||
idleUnload: "Déchargement automatique en cas d'inactivité",
|
||||
idleUnloadDescription:
|
||||
"Décharger le modèle après ce nombre de secondes d'inactivité pour libérer la VRAM ; la requête suivante le recharge. 0 le maintient chargé.",
|
||||
"Décharger le modèle après ce nombre de secondes d'inactivité pour libérer la VRAM ; la requête suivante le recharge. 0 le maintient chargé. Minimum 60 secondes.",
|
||||
idleNeedsEnable:
|
||||
"Activez Changer de modèle par requête pour qu'un modèle déchargé se recharge à la prochaine utilisation.",
|
||||
idleActiveViaEnv:
|
||||
|
|
@ -166,7 +166,7 @@ export const fr = {
|
|||
"Échec du chargement des paramètres de changement automatique de modèle.",
|
||||
saveError:
|
||||
"Échec de l'enregistrement des paramètres de changement automatique de modèle.",
|
||||
idleError: "Saisissez un nombre entier de secondes (0 ou plus).",
|
||||
idleError: "Saisissez 0 pour garder le modèle chargé, ou au moins 60 secondes.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "Partage de l'aperçu",
|
||||
|
|
|
|||
|
|
@ -154,14 +154,14 @@ export const hi = {
|
|||
"जब कोई OpenAI-संगत अनुरोध किसी अन्य डाउनलोड किए गए GGUF का नाम लेता है, तो सर्व करने से पहले उसे लोड करें। डिफ़ॉल्ट रूप से बंद; अज्ञात नाम लोड किए गए मॉडल को सर्व करते रहते हैं।",
|
||||
idleUnload: "निष्क्रिय ऑटो-अनलोड",
|
||||
idleUnloadDescription:
|
||||
"VRAM मुक्त करने के लिए इतने निष्क्रिय सेकंड के बाद मॉडल को अनलोड करें; अगला अनुरोध इसे फिर से लोड करता है। 0 इसे लोड रखता है।",
|
||||
"VRAM मुक्त करने के लिए इतने निष्क्रिय सेकंड के बाद मॉडल को अनलोड करें; अगला अनुरोध इसे फिर से लोड करता है। 0 इसे लोड रखता है। न्यूनतम 60 सेकंड।",
|
||||
idleNeedsEnable:
|
||||
"अनुरोध के अनुसार मॉडल बदलें चालू करें ताकि अनलोड किया गया मॉडल अगले उपयोग पर फिर से लोड हो।",
|
||||
idleActiveViaEnv:
|
||||
"निष्क्रिय ऑटो-अनलोड UNSLOTH_MODEL_IDLE_TTL एनवायरनमेंट वेरिएबल के माध्यम से सक्रिय है।",
|
||||
loadError: "मॉडल ऑटो-स्विच सेटिंग्स लोड करने में विफल।",
|
||||
saveError: "मॉडल ऑटो-स्विच सेटिंग्स सहेजने में विफल।",
|
||||
idleError: "सेकंड की पूरी संख्या दर्ज करें (0 या अधिक)।",
|
||||
idleError: "मॉडल को लोड रखने के लिए 0 दर्ज करें, या कम से कम 60 सेकंड।",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "पूर्वावलोकन साझाकरण",
|
||||
|
|
|
|||
|
|
@ -149,12 +149,12 @@ export const ja = {
|
|||
enable: "リクエストごとにモデルを切り替え",
|
||||
enableDescription: "OpenAI互換のリクエストが別のダウンロード済み GGUF を指定した場合、応答する前にそのモデルを読み込みます。デフォルトはオフです。不明な名前の場合は、読み込み済みのモデルで応答を続けます。",
|
||||
idleUnload: "アイドル時の自動アンロード",
|
||||
idleUnloadDescription: "指定した秒数だけアイドル状態が続くとモデルをアンロードして VRAM を解放します。次のリクエストで再読み込みされます。0 にすると読み込んだままにします。",
|
||||
idleUnloadDescription: "指定した秒数だけアイドル状態が続くとモデルをアンロードして VRAM を解放します。次のリクエストで再読み込みされます。0 にすると読み込んだままにします。最小 60 秒。",
|
||||
idleNeedsEnable: "アンロードされたモデルが次回使用時に再読み込みされるように、「リクエストごとにモデルを切り替え」をオンにしてください。",
|
||||
idleActiveViaEnv: "アイドル時の自動アンロードは UNSLOTH_MODEL_IDLE_TTL 環境変数によって有効になっています。",
|
||||
loadError: "モデル自動切り替え設定の読み込みに失敗しました。",
|
||||
saveError: "モデル自動切り替え設定の保存に失敗しました。",
|
||||
idleError: "秒数を整数(0 以上)で入力してください。",
|
||||
idleError: "モデルを読み込んだままにするには 0 を、それ以外は 60 秒以上を入力してください。",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "プレビュー共有",
|
||||
|
|
|
|||
|
|
@ -153,14 +153,14 @@ export const ko = {
|
|||
"OpenAI 호환 요청이 다운로드된 다른 GGUF를 지정하면, 응답하기 전에 해당 모델을 불러옵니다. 기본값은 꺼짐이며, 알 수 없는 이름은 불러온 모델을 계속 제공합니다.",
|
||||
idleUnload: "유휴 시 자동 해제",
|
||||
idleUnloadDescription:
|
||||
"지정한 유휴 시간(초)이 지나면 모델을 해제하여 VRAM을 확보합니다. 다음 요청 시 다시 불러옵니다. 0으로 설정하면 계속 로드된 상태로 유지됩니다.",
|
||||
"지정한 유휴 시간(초)이 지나면 모델을 해제하여 VRAM을 확보합니다. 다음 요청 시 다시 불러옵니다. 0으로 설정하면 계속 로드된 상태로 유지됩니다. 최소 60초입니다.",
|
||||
idleNeedsEnable:
|
||||
"해제된 모델이 다음 사용 시 다시 로드되도록 하려면 요청에 따라 모델 전환을 켜세요.",
|
||||
idleActiveViaEnv:
|
||||
"유휴 시 자동 해제가 UNSLOTH_MODEL_IDLE_TTL 환경 변수를 통해 활성화되어 있습니다.",
|
||||
loadError: "모델 자동 전환 설정을 불러오지 못했습니다.",
|
||||
saveError: "모델 자동 전환 설정을 저장하지 못했습니다.",
|
||||
idleError: "정수(초)를 입력하세요(0 이상).",
|
||||
idleError: "모델을 로드 상태로 유지하려면 0을, 그렇지 않으면 60초 이상을 입력하세요.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "미리보기 공유",
|
||||
|
|
|
|||
|
|
@ -157,14 +157,14 @@ export const ptBR = {
|
|||
"Quando uma requisição compatível com OpenAI nomear um GGUF baixado diferente, carrega-o antes de responder. Desativado por padrão; nomes desconhecidos continuam usando o modelo carregado.",
|
||||
idleUnload: "Descarregamento automático por inatividade",
|
||||
idleUnloadDescription:
|
||||
"Descarrega o modelo após esta quantidade de segundos de inatividade para liberar VRAM; a próxima requisição o recarrega. 0 mantém o modelo carregado.",
|
||||
"Descarrega o modelo após esta quantidade de segundos de inatividade para liberar VRAM; a próxima requisição o recarrega. 0 mantém o modelo carregado. Mínimo de 60 segundos.",
|
||||
idleNeedsEnable:
|
||||
"Ative Trocar de modelo por requisição para que um modelo descarregado seja recarregado no próximo uso.",
|
||||
idleActiveViaEnv:
|
||||
"O descarregamento automático por inatividade está ativo por meio da variável de ambiente UNSLOTH_MODEL_IDLE_TTL.",
|
||||
loadError: "Falha ao carregar as configurações de troca automática de modelo.",
|
||||
saveError: "Falha ao salvar as configurações de troca automática de modelo.",
|
||||
idleError: "Insira um número inteiro de segundos (0 ou mais).",
|
||||
idleError: "Insira 0 para manter o modelo carregado, ou pelo menos 60 segundos.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "Compartilhamento de pré-visualização",
|
||||
|
|
|
|||
|
|
@ -154,14 +154,14 @@ export const ru = {
|
|||
"Когда OpenAI-совместимый запрос указывает другую загруженную GGUF, загружать её перед обслуживанием. По умолчанию выключено; неизвестные имена продолжают обслуживать загруженную модель.",
|
||||
idleUnload: "Автовыгрузка при простое",
|
||||
idleUnloadDescription:
|
||||
"Выгружать модель после указанного числа секунд простоя, чтобы освободить VRAM; следующий запрос загрузит её снова. 0 оставляет модель загруженной.",
|
||||
"Выгружать модель после указанного числа секунд простоя, чтобы освободить VRAM; следующий запрос загрузит её снова. 0 оставляет модель загруженной. Минимум 60 секунд.",
|
||||
idleNeedsEnable:
|
||||
"Включите «Переключать модель по запросу», чтобы выгруженная модель загружалась при следующем использовании.",
|
||||
idleActiveViaEnv:
|
||||
"Автовыгрузка при простое активна через переменную окружения UNSLOTH_MODEL_IDLE_TTL.",
|
||||
loadError: "Не удалось загрузить настройки автопереключения модели.",
|
||||
saveError: "Не удалось сохранить настройки автопереключения модели.",
|
||||
idleError: "Введите целое число секунд (0 или больше).",
|
||||
idleError: "Введите 0, чтобы модель оставалась загруженной, или не менее 60 секунд.",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "Публикация предпросмотра",
|
||||
|
|
|
|||
|
|
@ -152,14 +152,14 @@ export const zhCN = {
|
|||
"当兼容 OpenAI 的请求指定了另一个已下载的 GGUF 时,先加载它再提供服务。默认关闭;未知名称将继续使用已加载的模型。",
|
||||
idleUnload: "空闲自动卸载",
|
||||
idleUnloadDescription:
|
||||
"空闲达到该秒数后卸载模型以释放 VRAM;下次请求会重新加载。设为 0 则保持加载。",
|
||||
"空闲达到该秒数后卸载模型以释放 VRAM;下次请求会重新加载。设为 0 则保持加载。最小 60 秒。",
|
||||
idleNeedsEnable:
|
||||
"开启“按请求切换模型”,以便已卸载的模型在下次使用时重新加载。",
|
||||
idleActiveViaEnv:
|
||||
"空闲自动卸载已通过 UNSLOTH_MODEL_IDLE_TTL 环境变量启用。",
|
||||
loadError: "加载模型自动切换设置失败。",
|
||||
saveError: "保存模型自动切换设置失败。",
|
||||
idleError: "请输入整数秒数(0 或以上)。",
|
||||
idleError: "输入 0 保持模型加载,或输入至少 60 秒。",
|
||||
},
|
||||
previewSharing: {
|
||||
sectionTitle: "预览分享",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue