Spaces:
Running
Running
SilverElixir
Fix ttf EMA pollution, quota log, explicit url_context, dynamic freshness years, transcribe cap (A2-4, A2-10..A2-13)
453b05f Download lumen_model_speed.py from SilverElixir/Lumen: direct link, hf CLI and curl.
- Browser
- Download file 4.25 kB
-
https://huggingface.co/spaces/SilverElixir/Lumen/resolve/main/lumen_model_speed.py
- Command line
-
hf download hf://spaces/SilverElixir/Lumen/lumen_model_speed.py
-
curl -L -o lumen_model_speed.py https://huggingface.co/spaces/SilverElixir/Lumen/resolve/main/lumen_model_speed.py
4.25 kB
| """ | |
| lumen_model_speed.py — самокалибрующаяся оценка задержек моделей. | |
| Прод 17.09.2026: голова цепочки тормозила 96с, а роутер ставил её первой. Поэтому замер по факту + EMA, новичок с нейтрального приора. EMA только в памяти. | |
| """ | |
| from __future__ import annotations | |
| # Ключ provider:model_id — из lumen_typing_pace, чтобы не плодить два форматтера. | |
| from lumen_typing_pace import speed_key | |
| # Тот же компромисс стабильности/подстройки, что в typing_pace. | |
| _EMA_ALPHA = 0.3 | |
| # Приор нейтрален: новичок без замеров не взлетает в голову и не падает в хвост. | |
| _DEFAULT_TTF_SEC = 10.0 | |
| _DEFAULT_TOTAL_SEC = 25.0 | |
| # Границы-зажимы ДО усреднения (тот же приём, что clamp в record_observed_speed): | |
| # один выброс не должен утащить EMA в небеса или в пол. | |
| _MIN_TTF_SEC = 1.0 | |
| _MAX_TTF_SEC = 90.0 | |
| _MIN_TOTAL_SEC = 3.0 | |
| _MAX_TOTAL_SEC = 120.0 | |
| # Запас на разовое зависание первого куска, а не вечное ожидание. | |
| _TTF_ABANDON_MULT = 2.5 | |
| _latency_ema: dict[str, tuple[float, float]] = {} | |
| def expected_ttf_sec(key: str) -> float: | |
| """Ожидаемое время до первого куска — EMA или приор для новой модели.""" | |
| ttf = _latency_ema.get(key, (_DEFAULT_TTF_SEC, _DEFAULT_TOTAL_SEC))[0] | |
| return max(_MIN_TTF_SEC, min(_MAX_TTF_SEC, ttf)) | |
| def expected_total_sec(key: str) -> float: | |
| """Ожидаемое полное время ответа — EMA или приор для новой модели.""" | |
| total = _latency_ema.get(key, (_DEFAULT_TTF_SEC, _DEFAULT_TOTAL_SEC))[1] | |
| return max(_MIN_TOTAL_SEC, min(_MAX_TOTAL_SEC, total)) | |
| def record_response(key: str, *, total_sec: float, ttf_sec: float | None = None) -> None: | |
| """Учесть один УСПЕШНЫЙ ответ. Без ttf_sec (нестриминговый ответ первого куска | |
| не видел) ttf-EMA не трогаем: подстановка total завышала first_chunk_limit, | |
| и зависшая голова держалась дольше. Неположительные замеры игнорируются.""" | |
| if total_sec <= 0: | |
| return | |
| prev = _latency_ema.get(key) | |
| if ttf_sec is None or ttf_sec <= 0: | |
| obs_ttf = prev[0] if prev is not None else _DEFAULT_TTF_SEC | |
| else: | |
| obs_ttf = max(_MIN_TTF_SEC, min(_MAX_TTF_SEC, ttf_sec)) | |
| obs_total = max(_MIN_TOTAL_SEC, min(_MAX_TOTAL_SEC, total_sec)) | |
| if prev is None: | |
| _latency_ema[key] = (obs_ttf, obs_total) | |
| else: | |
| _latency_ema[key] = ( | |
| _EMA_ALPHA * obs_ttf + (1 - _EMA_ALPHA) * prev[0], | |
| _EMA_ALPHA * obs_total + (1 - _EMA_ALPHA) * prev[1], | |
| ) | |
| def first_chunk_limit_sec(key: str, floor_sec: float) -> float: | |
| """min — floor от холодного старта, max — EMA_ttf × множитель от разового зависания.""" | |
| return max(floor_sec, expected_ttf_sec(key) * _TTF_ABANDON_MULT) | |
| def reorder_route(route: list[tuple[str, str]]) -> list[tuple[str, str]]: | |
| """Переупорядочить маршрут по задержкам, не ломая архитектуру: блоки провайдеров на месте, внутри блока — по ожидаемому времени. Сортировка стабильная, новички сохраняют кураторский порядок.""" | |
| blocks: list[list[tuple[str, str]]] = [] | |
| block_index: dict[str, int] = {} | |
| for item in route: | |
| provider = item[0] | |
| if provider not in block_index: | |
| block_index[provider] = len(blocks) | |
| blocks.append([]) | |
| blocks[block_index[provider]].append(item) | |
| ordered: list[tuple[str, str]] = [] | |
| for block in blocks: | |
| ordered.extend(sorted(block, key=lambda item: expected_total_sec(speed_key(item[0], item[1])))) | |
| return ordered | |