first commit
Some checks failed
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled

This commit is contained in:
2026-07-23 02:38:05 +03:00
commit 8757bec8ac
335 changed files with 61527 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
"""Подсчёт токенов для чанкера и плагина `QwenLocal`."""
import logging
from typing import Any
logger = logging.getLogger(__name__)
class QwenTokenCounter:
"""Подсчёт токенов токенизатором модели Qwen2.5-3B-Instruct.
Загрузка `tokenizers.Tokenizer` — ленивая (при первом вызове), чтобы
инстанцирование плагина в API-процессе не тянуло за собой файл
токенизатора. Если файл отсутствует или повреждён — используется
эвристический фолбэк `len(text) // 3`, чтобы пайплайн не падал из-за
отсутствия токенизатора (например, в dev-окружении без volume модели).
"""
def __init__(self, tokenizer_path: str | None = None) -> None:
self._tokenizer_path = tokenizer_path
self._tokenizer: Any | None = None
self._load_attempted = False
def _ensure_loaded(self) -> None:
"""Загрузить токенизатор один раз (синглтон на инстанс counter'а)."""
if self._load_attempted:
return
self._load_attempted = True
if not self._tokenizer_path:
logger.warning("Путь к токенизатору не задан, использую эвристику len(text) // 3")
return
try:
from tokenizers import Tokenizer
self._tokenizer = Tokenizer.from_file(self._tokenizer_path)
except Exception:
logger.warning(
"Не удалось загрузить токенизатор из %s, использую эвристику len(text) // 3",
self._tokenizer_path,
)
self._tokenizer = None
def __call__(self, text: str) -> int:
"""Вернуть число токенов в тексте (или эвристическую оценку)."""
self._ensure_loaded()
if self._tokenizer is not None:
encoded: int = len(self._tokenizer.encode(text).ids)
return encoded
return len(text) // 3