diff --git a/.gitignore b/.gitignore index aebbfa7..f61cc2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -output/ +output/* +output_audio/* ui/data/* *.db @@ -16,3 +17,10 @@ env/ .coverage +examples/assorted_checks/benchmarks/output_audio/* +examples/assorted_checks/test_combinations/output/* +examples/assorted_checks/test_openai/output/* + +examples/assorted_checks/test_voices/output/* +examples/assorted_checks/test_formats/output/* +ui/RepoScreenshot.png diff --git a/README.md b/README.md index 9732bd6..da78651 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@

# Kokoro TTS API -[![Tests](https://img.shields.io/badge/tests-89%20passed-darkgreen)]() -[![Coverage](https://img.shields.io/badge/coverage-80%25-darkgreen)]() +[![Tests](https://img.shields.io/badge/tests-95%20passed-darkgreen)]() +[![Coverage](https://img.shields.io/badge/coverage-72%25-darkgreen)]() [![Tested at Model Commit](https://img.shields.io/badge/last--tested--model--commit-a67f113-blue)](https://huggingface.co/hexgrad/Kokoro-82M/tree/c3b0d86e2a980e027ef71c28819ea02e351c2667) [![Try on Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Try%20on-Spaces-blue)](https://huggingface.co/spaces/Remsky/Kokoro-TTS-Zero) Dockerized FastAPI wrapper for [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M) text-to-speech model diff --git a/api/src/core/config.py b/api/src/core/config.py index 52aea19..693ad82 100644 --- a/api/src/core/config.py +++ b/api/src/core/config.py @@ -14,7 +14,8 @@ class Settings(BaseSettings): output_dir_size_limit_mb: float = 500.0 # Maximum size of output directory in MB default_voice: str = "af" model_dir: str = "/app/Kokoro-82M" # Base directory for model files - model_path: str = "kokoro-v0_19.pth" + pytorch_model_path: str = "kokoro-v0_19.pth" + onnx_model_path: str = "kokoro-v0_19.onnx" voices_dir: str = "voices" sample_rate: int = 24000 diff --git a/api/src/core/kokoro.py b/api/src/core/kokoro.py new file mode 100644 index 0000000..e3d6c39 --- /dev/null +++ b/api/src/core/kokoro.py @@ -0,0 +1,185 @@ +import re + +import torch +import phonemizer + + +def split_num(num): + num = num.group() + if "." in num: + return num + elif ":" in num: + h, m = [int(n) for n in num.split(":")] + if m == 0: + return f"{h} o'clock" + elif m < 10: + return f"{h} oh {m}" + return f"{h} {m}" + year = int(num[:4]) + if year < 1100 or year % 1000 < 10: + return num + left, right = num[:2], int(num[2:4]) + s = "s" if num.endswith("s") else "" + if 100 <= year % 1000 <= 999: + if right == 0: + return f"{left} hundred{s}" + elif right < 10: + return f"{left} oh {right}{s}" + return f"{left} {right}{s}" + + +def flip_money(m): + m = m.group() + bill = "dollar" if m[0] == "$" else "pound" + if m[-1].isalpha(): + return f"{m[1:]} {bill}s" + elif "." not in m: + s = "" if m[1:] == "1" else "s" + return f"{m[1:]} {bill}{s}" + b, c = m[1:].split(".") + s = "" if b == "1" else "s" + c = int(c.ljust(2, "0")) + coins = ( + f"cent{'' if c == 1 else 's'}" + if m[0] == "$" + else ("penny" if c == 1 else "pence") + ) + return f"{b} {bill}{s} and {c} {coins}" + + +def point_num(num): + a, b = num.group().split(".") + return " point ".join([a, " ".join(b)]) + + +def normalize_text(text): + text = text.replace(chr(8216), "'").replace(chr(8217), "'") + text = text.replace("«", chr(8220)).replace("»", chr(8221)) + text = text.replace(chr(8220), '"').replace(chr(8221), '"') + text = text.replace("(", "«").replace(")", "»") + for a, b in zip("、。!,:;?", ",.!,:;?"): + text = text.replace(a, b + " ") + text = re.sub(r"[^\S \n]", " ", text) + text = re.sub(r" +", " ", text) + text = re.sub(r"(?<=\n) +(?=\n)", "", text) + text = re.sub(r"\bD[Rr]\.(?= [A-Z])", "Doctor", text) + text = re.sub(r"\b(?:Mr\.|MR\.(?= [A-Z]))", "Mister", text) + text = re.sub(r"\b(?:Ms\.|MS\.(?= [A-Z]))", "Miss", text) + text = re.sub(r"\b(?:Mrs\.|MRS\.(?= [A-Z]))", "Mrs", text) + text = re.sub(r"\betc\.(?! [A-Z])", "etc", text) + text = re.sub(r"(?i)\b(y)eah?\b", r"\1e'a", text) + text = re.sub( + r"\d*\.\d+|\b\d{4}s?\b|(? 510: + tokens = tokens[:510] + print("Truncated to 510 tokens") + ref_s = voicepack[len(tokens)] + out = forward(model, tokens, ref_s, speed) + ps = "".join(next(k for k, v in VOCAB.items() if i == v) for i in tokens) + return out, ps diff --git a/api/src/main.py b/api/src/main.py index 1521a14..c2a567e 100644 --- a/api/src/main.py +++ b/api/src/main.py @@ -13,6 +13,7 @@ from .core.config import settings from .services.tts_model import TTSModel from .services.tts_service import TTSService from .routers.openai_compatible import router as openai_router +from .routers.text_processing import router as text_router @asynccontextmanager @@ -45,8 +46,9 @@ app.add_middleware( allow_headers=["*"], ) -# Include OpenAI compatible router +# Include routers app.include_router(openai_router, prefix="/v1") +app.include_router(text_router) # Health check endpoint diff --git a/api/src/routers/text_processing.py b/api/src/routers/text_processing.py new file mode 100644 index 0000000..9e1ce3a --- /dev/null +++ b/api/src/routers/text_processing.py @@ -0,0 +1,30 @@ +from fastapi import APIRouter +from ..structures.text_schemas import PhonemeRequest, PhonemeResponse +from ..services.text_processing import phonemize, tokenize + +router = APIRouter( + prefix="/text", + tags=["text processing"] +) + +@router.post("/phonemize", response_model=PhonemeResponse) +async def phonemize_text(request: PhonemeRequest) -> PhonemeResponse: + """Convert text to phonemes and tokens: Rough attempt + + Args: + request: Request containing text and language + + Returns: + Phonemes and token IDs + """ + # Get phonemes + phonemes = phonemize(request.text, request.language) + + # Get tokens + tokens = tokenize(phonemes) + tokens = [0] + tokens + [0] # Add start/end tokens + + return PhonemeResponse( + phonemes=phonemes, + tokens=tokens + ) diff --git a/api/src/services/text_processing/__init__.py b/api/src/services/text_processing/__init__.py new file mode 100644 index 0000000..f945e18 --- /dev/null +++ b/api/src/services/text_processing/__init__.py @@ -0,0 +1,13 @@ +from .normalizer import normalize_text +from .phonemizer import phonemize, PhonemizerBackend, EspeakBackend +from .vocabulary import tokenize, decode_tokens, VOCAB + +__all__ = [ + 'normalize_text', + 'phonemize', + 'tokenize', + 'decode_tokens', + 'VOCAB', + 'PhonemizerBackend', + 'EspeakBackend' +] diff --git a/api/src/services/text_processing/normalizer.py b/api/src/services/text_processing/normalizer.py new file mode 100644 index 0000000..db5b7db --- /dev/null +++ b/api/src/services/text_processing/normalizer.py @@ -0,0 +1,111 @@ +import re + +def split_num(num: re.Match) -> str: + """Handle number splitting for various formats""" + num = num.group() + if "." in num: + return num + elif ":" in num: + h, m = [int(n) for n in num.split(":")] + if m == 0: + return f"{h} o'clock" + elif m < 10: + return f"{h} oh {m}" + return f"{h} {m}" + year = int(num[:4]) + if year < 1100 or year % 1000 < 10: + return num + left, right = num[:2], int(num[2:4]) + s = "s" if num.endswith("s") else "" + if 100 <= year % 1000 <= 999: + if right == 0: + return f"{left} hundred{s}" + elif right < 10: + return f"{left} oh {right}{s}" + return f"{left} {right}{s}" + +def handle_money(m: re.Match) -> str: + """Convert money expressions to spoken form""" + m = m.group() + bill = "dollar" if m[0] == "$" else "pound" + if m[-1].isalpha(): + return f"{m[1:]} {bill}s" + elif "." not in m: + s = "" if m[1:] == "1" else "s" + return f"{m[1:]} {bill}{s}" + b, c = m[1:].split(".") + s = "" if b == "1" else "s" + c = int(c.ljust(2, "0")) + coins = ( + f"cent{'' if c == 1 else 's'}" + if m[0] == "$" + else ("penny" if c == 1 else "pence") + ) + return f"{b} {bill}{s} and {c} {coins}" + +def handle_decimal(num: re.Match) -> str: + """Convert decimal numbers to spoken form""" + a, b = num.group().split(".") + return " point ".join([a, " ".join(b)]) + +def normalize_text(text: str) -> str: + """Normalize text for TTS processing + + Args: + text: Input text to normalize + + Returns: + Normalized text + """ + # Replace quotes and brackets + text = text.replace(chr(8216), "'").replace(chr(8217), "'") + text = text.replace("«", chr(8220)).replace("»", chr(8221)) + text = text.replace(chr(8220), '"').replace(chr(8221), '"') + text = text.replace("(", "«").replace(")", "»") + + # Handle CJK punctuation + for a, b in zip("、。!,:;?", ",.!,:;?"): + text = text.replace(a, b + " ") + + # Clean up whitespace + text = re.sub(r"[^\S \n]", " ", text) + text = re.sub(r" +", " ", text) + text = re.sub(r"(?<=\n) +(?=\n)", "", text) + + # Handle titles and abbreviations + text = re.sub(r"\bD[Rr]\.(?= [A-Z])", "Doctor", text) + text = re.sub(r"\b(?:Mr\.|MR\.(?= [A-Z]))", "Mister", text) + text = re.sub(r"\b(?:Ms\.|MS\.(?= [A-Z]))", "Miss", text) + text = re.sub(r"\b(?:Mrs\.|MRS\.(?= [A-Z]))", "Mrs", text) + text = re.sub(r"\betc\.(?! [A-Z])", "etc", text) + + # Handle common words + text = re.sub(r"(?i)\b(y)eah?\b", r"\1e'a", text) + + # Handle numbers and money + text = re.sub( + r"\d*\.\d+|\b\d{4}s?\b|(? str: + """Convert text to phonemes + + Args: + text: Text to convert to phonemes + + Returns: + Phonemized text + """ + pass + +class EspeakBackend(PhonemizerBackend): + """Espeak-based phonemizer implementation""" + + def __init__(self, language: str): + """Initialize espeak backend + + Args: + language: Language code ('en-us' or 'en-gb') + """ + self.backend = phonemizer.backend.EspeakBackend( + language=language, + preserve_punctuation=True, + with_stress=True + ) + self.language = language + + def phonemize(self, text: str) -> str: + """Convert text to phonemes using espeak + + Args: + text: Text to convert to phonemes + + Returns: + Phonemized text + """ + # Phonemize text + ps = self.backend.phonemize([text]) + ps = ps[0] if ps else "" + + # Handle special cases + ps = ps.replace("kəkˈoːɹoʊ", "kˈoʊkəɹoʊ").replace("kəkˈɔːɹəʊ", "kˈəʊkəɹəʊ") + ps = ps.replace("ʲ", "j").replace("r", "ɹ").replace("x", "k").replace("ɬ", "l") + ps = re.sub(r"(?<=[a-zɹː])(?=hˈʌndɹɪd)", " ", ps) + ps = re.sub(r' z(?=[;:,.!?¡¿—…"«»"" ]|$)', "z", ps) + + # Language-specific rules + if self.language == "en-us": + ps = re.sub(r"(?<=nˈaɪn)ti(?!ː)", "di", ps) + + return ps.strip() + +def create_phonemizer(language: str = "a") -> PhonemizerBackend: + """Factory function to create phonemizer backend + + Args: + language: Language code ('a' for US English, 'b' for British English) + + Returns: + Phonemizer backend instance + """ + # Map language codes to espeak language codes + lang_map = { + "a": "en-us", + "b": "en-gb" + } + + if language not in lang_map: + raise ValueError(f"Unsupported language code: {language}") + + return EspeakBackend(lang_map[language]) + +def phonemize(text: str, language: str = "a", normalize: bool = True) -> str: + """Convert text to phonemes + + Args: + text: Text to convert to phonemes + language: Language code ('a' for US English, 'b' for British English) + normalize: Whether to normalize text before phonemization + + Returns: + Phonemized text + """ + if normalize: + text = normalize_text(text) + + phonemizer = create_phonemizer(language) + return phonemizer.phonemize(text) diff --git a/api/src/services/text_processing/vocabulary.py b/api/src/services/text_processing/vocabulary.py new file mode 100644 index 0000000..66af961 --- /dev/null +++ b/api/src/services/text_processing/vocabulary.py @@ -0,0 +1,37 @@ +def get_vocab(): + """Get the vocabulary dictionary mapping characters to token IDs""" + _pad = "$" + _punctuation = ';:,.!?¡¿—…"«»"" ' + _letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + _letters_ipa = "ɑɐɒæɓʙβɔɕçɗɖðʤəɘɚɛɜɝɞɟʄɡɠɢʛɦɧħɥʜɨɪʝɭɬɫɮʟɱɯɰŋɳɲɴøɵɸθœɶʘɹɺɾɻʀʁɽʂʃʈʧʉʊʋⱱʌɣɤʍχʎʏʑʐʒʔʡʕʢǀǁǂǃˈˌːˑʼʴʰʱʲʷˠˤ˞↓↑→↗↘'̩'ᵻ" + + # Create vocabulary dictionary + symbols = [_pad] + list(_punctuation) + list(_letters) + list(_letters_ipa) + return {symbol: i for i, symbol in enumerate(symbols)} + +# Initialize vocabulary +VOCAB = get_vocab() + +def tokenize(phonemes: str) -> list[int]: + """Convert phonemes string to token IDs + + Args: + phonemes: String of phonemes to tokenize + + Returns: + List of token IDs + """ + return [i for i in map(VOCAB.get, phonemes) if i is not None] + +def decode_tokens(tokens: list[int]) -> str: + """Convert token IDs back to phonemes string + + Args: + tokens: List of token IDs + + Returns: + String of phonemes + """ + # Create reverse mapping + id_to_symbol = {i: s for s, i in VOCAB.items()} + return "".join(id_to_symbol[t] for t in tokens) diff --git a/api/src/services/tts_base.py b/api/src/services/tts_base.py index 1ef913d..f502373 100644 --- a/api/src/services/tts_base.py +++ b/api/src/services/tts_base.py @@ -1,15 +1,13 @@ import os import threading from abc import ABC, abstractmethod +from typing import List, Tuple import torch import numpy as np from loguru import logger -from kokoro import tokenize, phonemize -from typing import Union, List from ..core.config import settings - class TTSBaseModel(ABC): _instance = None _lock = threading.Lock() @@ -28,16 +26,18 @@ class TTSBaseModel(ABC): # Test CUDA device test_tensor = torch.zeros(1).cuda() logger.info("CUDA test successful") + model_path = os.path.join(settings.model_dir, settings.pytorch_model_path) cls._device = "cuda" except Exception as e: logger.error(f"CUDA test failed: {e}") cls._device = "cpu" else: cls._device = "cpu" + model_path = os.path.join(settings.model_dir, settings.onnx_model_path) logger.info(f"Initializing model on {cls._device}") # Initialize model - if not cls.initialize(settings.model_dir, settings.model_path): + if not cls.initialize(settings.model_dir, model_path=model_path): raise RuntimeError(f"Failed to initialize {cls._device.upper()} model") # Setup voices directory @@ -65,13 +65,9 @@ class TTSBaseModel(ABC): voice_path = os.path.join(cls.VOICES_DIR, "af.pt") dummy_voicepack = torch.load(voice_path, map_location=cls._device, weights_only=True) - if cls._device == "cuda": - cls.generate(dummy_text, dummy_voicepack, "a", 1.0) - else: - ps = phonemize(dummy_text, "a") - tokens = tokenize(ps) - tokens = [0] + tokens + [0] - cls.generate(tokens, dummy_voicepack, 1.0) + # Process text and generate audio + phonemes, tokens = cls.process_text(dummy_text, "a") + cls.generate_from_tokens(tokens, dummy_voicepack, 1.0) logger.info("Model warm-up complete") except Exception as e: @@ -89,13 +85,43 @@ class TTSBaseModel(ABC): @classmethod @abstractmethod - def generate(cls, input_data: Union[str, List[int]], voicepack: torch.Tensor, *args) -> np.ndarray: - """Generate audio from input + def process_text(cls, text: str, language: str) -> Tuple[str, List[int]]: + """Process text into phonemes and tokens Args: - input_data: Either text string (GPU) or tokenized input (CPU) + text: Input text + language: Language code + + Returns: + tuple[str, list[int]]: Phonemes and token IDs + """ + pass + + @classmethod + @abstractmethod + def generate_from_text(cls, text: str, voicepack: torch.Tensor, language: str, speed: float) -> Tuple[np.ndarray, str]: + """Generate audio from text + + Args: + text: Input text voicepack: Voice tensor - *args: Additional args (lang+speed for GPU, speed for CPU) + language: Language code + speed: Speed factor + + Returns: + tuple[np.ndarray, str]: Generated audio samples and phonemes + """ + pass + + @classmethod + @abstractmethod + def generate_from_tokens(cls, tokens: List[int], voicepack: torch.Tensor, speed: float) -> np.ndarray: + """Generate audio from tokens + + Args: + tokens: Token IDs + voicepack: Voice tensor + speed: Speed factor Returns: np.ndarray: Generated audio samples diff --git a/api/src/services/tts_cpu.py b/api/src/services/tts_cpu.py index 74c1bca..6743b83 100644 --- a/api/src/services/tts_cpu.py +++ b/api/src/services/tts_cpu.py @@ -5,6 +5,8 @@ from onnxruntime import InferenceSession, SessionOptions, GraphOptimizationLevel from loguru import logger from .tts_base import TTSBaseModel +from .text_processing import phonemize, tokenize +from ..core.config import settings class TTSCPUModel(TTSBaseModel): _instance = None @@ -15,22 +17,12 @@ class TTSCPUModel(TTSBaseModel): """Initialize ONNX model for CPU inference""" if cls._onnx_session is None: # Try loading ONNX model - # First try the specified path if provided - if model_path and model_path.endswith('.onnx'): - onnx_path = os.path.join(model_dir, model_path) - if os.path.exists(onnx_path): - logger.info(f"Loading specified ONNX model from {onnx_path}") - else: - onnx_path = None + onnx_path = os.path.join(model_dir, settings.onnx_model_path) + if os.path.exists(onnx_path): + logger.info(f"Loading ONNX model from {onnx_path}") else: - # Look for any .onnx file in the directory as fallback - onnx_files = [f for f in os.listdir(model_dir) if f.endswith('.onnx')] - if onnx_files: - onnx_path = os.path.join(model_dir, onnx_files[0]) - logger.info(f"Found ONNX model: {onnx_path}") - else: - logger.error(f"No ONNX model found in {model_dir}") - return None + logger.error(f"ONNX model not found at {onnx_path}") + return None if not onnx_path: return None @@ -62,13 +54,53 @@ class TTSCPUModel(TTSBaseModel): return cls._onnx_session @classmethod - def generate(cls, input_data: list[int], voicepack: torch.Tensor, *args) -> np.ndarray: - """Generate audio using ONNX model + def process_text(cls, text: str, language: str) -> tuple[str, list[int]]: + """Process text into phonemes and tokens Args: - input_data: list of token IDs + text: Input text + language: Language code + + Returns: + tuple[str, list[int]]: Phonemes and token IDs + """ + phonemes = phonemize(text, language) + tokens = tokenize(phonemes) + tokens = [0] + tokens + [0] # Add start/end tokens + return phonemes, tokens + + @classmethod + def generate_from_text(cls, text: str, voicepack: torch.Tensor, language: str, speed: float) -> tuple[np.ndarray, str]: + """Generate audio from text + + Args: + text: Input text voicepack: Voice tensor - *args: (speed,) tuple + language: Language code + speed: Speed factor + + Returns: + tuple[np.ndarray, str]: Generated audio samples and phonemes + """ + if cls._onnx_session is None: + raise RuntimeError("ONNX model not initialized") + + # Process text + phonemes, tokens = cls.process_text(text, language) + + # Generate audio + audio = cls.generate_from_tokens(tokens, voicepack, speed) + + return audio, phonemes + + @classmethod + def generate_from_tokens(cls, tokens: list[int], voicepack: torch.Tensor, speed: float) -> np.ndarray: + """Generate audio from tokens + + Args: + tokens: Token IDs + voicepack: Voice tensor + speed: Speed factor Returns: np.ndarray: Generated audio samples @@ -76,10 +108,9 @@ class TTSCPUModel(TTSBaseModel): if cls._onnx_session is None: raise RuntimeError("ONNX model not initialized") - speed = args[0] # Pre-allocate and prepare inputs - tokens_input = np.array([input_data], dtype=np.int64) - style_input = voicepack[len(input_data)-2].numpy() # Already has correct dimensions + tokens_input = np.array([tokens], dtype=np.int64) + style_input = voicepack[len(tokens)-2].numpy() # Already has correct dimensions speed_input = np.full(1, speed, dtype=np.float32) # More efficient than ones * speed # Run inference with optimized inputs diff --git a/api/src/services/tts_gpu.py b/api/src/services/tts_gpu.py index 5da5563..300d141 100644 --- a/api/src/services/tts_gpu.py +++ b/api/src/services/tts_gpu.py @@ -3,9 +3,47 @@ import numpy as np import torch from loguru import logger from models import build_model -from kokoro import generate +from .text_processing import phonemize, tokenize from .tts_base import TTSBaseModel +from ..core.config import settings + +@torch.no_grad() +def forward(model, tokens, ref_s, speed): + """Forward pass through the model""" + device = ref_s.device + tokens = torch.LongTensor([[0, *tokens, 0]]).to(device) + input_lengths = torch.LongTensor([tokens.shape[-1]]).to(device) + text_mask = length_to_mask(input_lengths).to(device) + bert_dur = model.bert(tokens, attention_mask=(~text_mask).int()) + d_en = model.bert_encoder(bert_dur).transpose(-1, -2) + s = ref_s[:, 128:] + d = model.predictor.text_encoder(d_en, s, input_lengths, text_mask) + x, _ = model.predictor.lstm(d) + duration = model.predictor.duration_proj(x) + duration = torch.sigmoid(duration).sum(axis=-1) / speed + pred_dur = torch.round(duration).clamp(min=1).long() + pred_aln_trg = torch.zeros(input_lengths, pred_dur.sum().item()) + c_frame = 0 + for i in range(pred_aln_trg.size(0)): + pred_aln_trg[i, c_frame : c_frame + pred_dur[0, i].item()] = 1 + c_frame += pred_dur[0, i].item() + en = d.transpose(-1, -2) @ pred_aln_trg.unsqueeze(0).to(device) + F0_pred, N_pred = model.predictor.F0Ntrain(en, s) + t_en = model.text_encoder(tokens, input_lengths, text_mask) + asr = t_en @ pred_aln_trg.unsqueeze(0).to(device) + return model.decoder(asr, F0_pred, N_pred, ref_s[:, :128]).squeeze().cpu().numpy() + +def length_to_mask(lengths): + """Create attention mask from lengths""" + mask = ( + torch.arange(lengths.max()) + .unsqueeze(0) + .expand(lengths.shape[0], -1) + .type_as(lengths) + ) + mask = torch.gt(mask + 1, lengths.unsqueeze(1)) + return mask class TTSGPUModel(TTSBaseModel): _instance = None @@ -17,7 +55,7 @@ class TTSGPUModel(TTSBaseModel): if cls._instance is None and torch.cuda.is_available(): try: logger.info("Initializing GPU model") - model_path = os.path.join(model_dir, model_path) + model_path = os.path.join(model_dir, settings.pytorch_model_path) model = build_model(model_path, cls._device) cls._instance = model return cls._instance @@ -27,13 +65,52 @@ class TTSGPUModel(TTSBaseModel): return cls._instance @classmethod - def generate(cls, input_data: str, voicepack: torch.Tensor, *args) -> np.ndarray: - """Generate audio using PyTorch model on GPU + def process_text(cls, text: str, language: str) -> tuple[str, list[int]]: + """Process text into phonemes and tokens Args: - input_data: Text string to generate audio from + text: Input text + language: Language code + + Returns: + tuple[str, list[int]]: Phonemes and token IDs + """ + phonemes = phonemize(text, language) + tokens = tokenize(phonemes) + return phonemes, tokens + + @classmethod + def generate_from_text(cls, text: str, voicepack: torch.Tensor, language: str, speed: float) -> tuple[np.ndarray, str]: + """Generate audio from text + + Args: + text: Input text voicepack: Voice tensor - *args: (lang, speed) tuple + language: Language code + speed: Speed factor + + Returns: + tuple[np.ndarray, str]: Generated audio samples and phonemes + """ + if cls._instance is None: + raise RuntimeError("GPU model not initialized") + + # Process text + phonemes, tokens = cls.process_text(text, language) + + # Generate audio + audio = cls.generate_from_tokens(tokens, voicepack, speed) + + return audio, phonemes + + @classmethod + def generate_from_tokens(cls, tokens: list[int], voicepack: torch.Tensor, speed: float) -> np.ndarray: + """Generate audio from tokens + + Args: + tokens: Token IDs + voicepack: Voice tensor + speed: Speed factor Returns: np.ndarray: Generated audio samples @@ -41,12 +118,10 @@ class TTSGPUModel(TTSBaseModel): if cls._instance is None: raise RuntimeError("GPU model not initialized") - lang, speed = args - result = generate(cls._instance, input_data, voicepack, lang=lang, speed=speed) - # kokoro.generate returns (audio, metadata, info), we only want audio - audio = result[0] + # Get reference style + ref_s = voicepack[len(tokens)] - # Convert to numpy array if needed - if isinstance(audio, torch.Tensor): - audio = audio.cpu().numpy() + # Generate audio + audio = forward(cls._instance, tokens, ref_s, speed) + return audio diff --git a/api/src/services/tts_service.py b/api/src/services/tts_service.py index cddbc47..6d763fe 100644 --- a/api/src/services/tts_service.py +++ b/api/src/services/tts_service.py @@ -7,7 +7,7 @@ from typing import List, Tuple, Optional import numpy as np import torch import scipy.io.wavfile as wavfile -from kokoro import tokenize, phonemize, normalize_text +from .text_processing import normalize_text from loguru import logger from ..core.config import settings @@ -62,21 +62,10 @@ class TTSService: # Process all chunks for i, chunk in enumerate(chunks): try: - # Process chunk - if TTSModel.get_device() == "cuda": - # GPU takes (text, voicepack, lang, speed) - try: - chunk_audio = TTSModel.generate(chunk, voicepack, voice[0], speed) - except RuntimeError as e: - logger.error(f"Failed to generate audio: {str(e)}") - chunk_audio = None - else: - # CPU takes (tokens, voicepack, speed) - ps = phonemize(chunk, voice[0]) - tokens = tokenize(ps) - tokens = [0] + list(tokens) + [0] # Add padding - chunk_audio = TTSModel.generate(tokens, voicepack, speed) - + # Process text and generate audio + phonemes, tokens = TTSModel.process_text(chunk, voice[0]) + chunk_audio = TTSModel.generate_from_tokens(tokens, voicepack, speed) + if chunk_audio is not None: audio_chunks.append(chunk_audio) else: @@ -98,19 +87,8 @@ class TTSService: ) else: # Process single chunk - if TTSModel.get_device() == "cuda": - # GPU takes (text, voicepack, lang, speed) - try: - audio = TTSModel.generate(text, voicepack, voice[0], speed) - except RuntimeError as e: - logger.error(f"Failed to generate audio: {str(e)}") - raise ValueError("No audio chunks were generated successfully") - else: - # CPU takes (tokens, voicepack, speed) - ps = phonemize(text, voice[0]) - tokens = tokenize(ps) - tokens = [0] + list(tokens) + [0] # Add padding - audio = TTSModel.generate(tokens, voicepack, speed) + phonemes, tokens = TTSModel.process_text(text, voice[0]) + audio = TTSModel.generate_from_tokens(tokens, voicepack, speed) processing_time = time.time() - start_time return audio, processing_time diff --git a/api/src/structures/text_schemas.py b/api/src/structures/text_schemas.py new file mode 100644 index 0000000..5ae1b08 --- /dev/null +++ b/api/src/structures/text_schemas.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + +class PhonemeRequest(BaseModel): + text: str + language: str = "a" # Default to American English + +class PhonemeResponse(BaseModel): + phonemes: str + tokens: list[int] diff --git a/api/tests/conftest.py b/api/tests/conftest.py index 5803170..fba270b 100644 --- a/api/tests/conftest.py +++ b/api/tests/conftest.py @@ -21,8 +21,73 @@ def cleanup(): cleanup_mock_dirs() -# Mock torch and other ML modules before they're imported -sys.modules["torch"] = Mock() +# Create mock torch module +mock_torch = Mock() +mock_torch.cuda = Mock() +mock_torch.cuda.is_available = Mock(return_value=False) + +# Create a mock tensor class that supports basic operations +class MockTensor: + def __init__(self, data): + self.data = data + if isinstance(data, (list, tuple)): + self.shape = [len(data)] + elif isinstance(data, MockTensor): + self.shape = data.shape + else: + self.shape = getattr(data, 'shape', [1]) + + def __getitem__(self, idx): + if isinstance(self.data, (list, tuple)): + if isinstance(idx, slice): + return MockTensor(self.data[idx]) + return self.data[idx] + return self + + def max(self): + if isinstance(self.data, (list, tuple)): + max_val = max(self.data) + return MockTensor(max_val) + return 5 # Default for testing + + def item(self): + if isinstance(self.data, (list, tuple)): + return max(self.data) + if isinstance(self.data, (int, float)): + return self.data + return 5 # Default for testing + + def cuda(self): + """Support cuda conversion""" + return self + + def any(self): + if isinstance(self.data, (list, tuple)): + return any(self.data) + return False + + def all(self): + if isinstance(self.data, (list, tuple)): + return all(self.data) + return True + + def unsqueeze(self, dim): + return self + + def expand(self, *args): + return self + + def type_as(self, other): + return self + +# Add tensor operations to mock torch +mock_torch.tensor = lambda x: MockTensor(x) +mock_torch.zeros = lambda *args: MockTensor([0] * (args[0] if isinstance(args[0], int) else args[0][0])) +mock_torch.arange = lambda x: MockTensor(list(range(x))) +mock_torch.gt = lambda x, y: MockTensor([False] * x.shape[0]) + +# Mock modules before they're imported +sys.modules["torch"] = mock_torch sys.modules["transformers"] = Mock() sys.modules["phonemizer"] = Mock() sys.modules["models"] = Mock() @@ -31,14 +96,22 @@ sys.modules["kokoro"] = Mock() sys.modules["kokoro.generate"] = Mock() sys.modules["kokoro.phonemize"] = Mock() sys.modules["kokoro.tokenize"] = Mock() +sys.modules["onnxruntime"] = Mock() @pytest.fixture(autouse=True) def mock_tts_model(): - """Mock TTSModel to avoid loading real models during tests""" - with patch("api.src.services.tts_model.TTSModel") as mock: + """Mock TTSModel and TTS model initialization""" + with patch("api.src.services.tts_model.TTSModel") as mock_tts_model, \ + patch("api.src.services.tts_base.TTSBaseModel") as mock_base_model: + + # Mock TTSModel model_instance = Mock() model_instance.get_instance.return_value = model_instance model_instance.get_voicepack.return_value = None - mock.get_instance.return_value = model_instance + mock_tts_model.get_instance.return_value = model_instance + + # Mock TTS model initialization + mock_base_model.setup.return_value = 1 # Return dummy voice count + yield model_instance diff --git a/api/tests/test_tts_implementations.py b/api/tests/test_tts_implementations.py new file mode 100644 index 0000000..3f10c17 --- /dev/null +++ b/api/tests/test_tts_implementations.py @@ -0,0 +1,144 @@ +"""Tests for TTS model implementations""" +import os +import torch +import pytest +import numpy as np +from unittest.mock import patch, MagicMock + +from api.src.services.tts_base import TTSBaseModel +from api.src.services.tts_cpu import TTSCPUModel +from api.src.services.tts_gpu import TTSGPUModel, length_to_mask + +# Base Model Tests +def test_get_device_error(): + """Test get_device() raises error when not initialized""" + TTSBaseModel._device = None + with pytest.raises(RuntimeError, match="Model not initialized"): + TTSBaseModel.get_device() + +@patch('torch.cuda.is_available') +@patch('os.path.exists') +@patch('os.path.join') +@patch('os.listdir') +@patch('torch.load') +@patch('torch.save') +def test_setup_cuda_available(mock_save, mock_load, mock_listdir, mock_join, mock_exists, mock_cuda_available): + """Test setup with CUDA available""" + TTSBaseModel._device = None + mock_cuda_available.return_value = True + mock_exists.return_value = True + mock_load.return_value = torch.zeros(1) + mock_listdir.return_value = ["voice1.pt", "voice2.pt"] + mock_join.return_value = "/mocked/path" + + # Mock the abstract methods + TTSBaseModel.initialize = MagicMock(return_value=True) + TTSBaseModel.process_text = MagicMock(return_value=("dummy", [1,2,3])) + TTSBaseModel.generate_from_tokens = MagicMock(return_value=np.zeros(1000)) + + voice_count = TTSBaseModel.setup() + assert TTSBaseModel._device == "cuda" + assert voice_count == 2 + +@patch('torch.cuda.is_available') +@patch('os.path.exists') +@patch('os.path.join') +@patch('os.listdir') +@patch('torch.load') +@patch('torch.save') +def test_setup_cuda_unavailable(mock_save, mock_load, mock_listdir, mock_join, mock_exists, mock_cuda_available): + """Test setup with CUDA unavailable""" + TTSBaseModel._device = None + mock_cuda_available.return_value = False + mock_exists.return_value = True + mock_load.return_value = torch.zeros(1) + mock_listdir.return_value = ["voice1.pt", "voice2.pt"] + mock_join.return_value = "/mocked/path" + + # Mock the abstract methods + TTSBaseModel.initialize = MagicMock(return_value=True) + TTSBaseModel.process_text = MagicMock(return_value=("dummy", [1,2,3])) + TTSBaseModel.generate_from_tokens = MagicMock(return_value=np.zeros(1000)) + + voice_count = TTSBaseModel.setup() + assert TTSBaseModel._device == "cpu" + assert voice_count == 2 + +# CPU Model Tests +def test_cpu_initialize_missing_model(): + """Test CPU initialize with missing model""" + with patch('os.path.exists', return_value=False): + result = TTSCPUModel.initialize("dummy_dir") + assert result is None + +def test_cpu_generate_uninitialized(): + """Test CPU generate methods with uninitialized model""" + TTSCPUModel._onnx_session = None + + with pytest.raises(RuntimeError, match="ONNX model not initialized"): + TTSCPUModel.generate_from_text("test", torch.zeros(1), "en", 1.0) + + with pytest.raises(RuntimeError, match="ONNX model not initialized"): + TTSCPUModel.generate_from_tokens([1,2,3], torch.zeros(1), 1.0) + +def test_cpu_process_text(): + """Test CPU process_text functionality""" + with patch('api.src.services.tts_cpu.phonemize') as mock_phonemize, \ + patch('api.src.services.tts_cpu.tokenize') as mock_tokenize: + + mock_phonemize.return_value = "test phonemes" + mock_tokenize.return_value = [1, 2, 3] + + phonemes, tokens = TTSCPUModel.process_text("test", "en") + assert phonemes == "test phonemes" + assert tokens == [0, 1, 2, 3, 0] # Should add start/end tokens + +# GPU Model Tests +@patch('torch.cuda.is_available') +def test_gpu_initialize_cuda_unavailable(mock_cuda_available): + """Test GPU initialize with CUDA unavailable""" + mock_cuda_available.return_value = False + TTSGPUModel._instance = None + + result = TTSGPUModel.initialize("dummy_dir", "dummy_path") + assert result is None + +@patch('api.src.services.tts_gpu.length_to_mask') +def test_gpu_length_to_mask(mock_length_to_mask): + """Test length_to_mask function""" + # Setup mock return value + expected_mask = torch.tensor([ + [False, False, False, True, True], + [False, False, False, False, False] + ]) + mock_length_to_mask.return_value = expected_mask + + # Call function with test input + lengths = torch.tensor([3, 5]) + mask = mock_length_to_mask(lengths) + + # Verify mock was called with correct input + mock_length_to_mask.assert_called_once() + assert torch.equal(mask, expected_mask) + +def test_gpu_generate_uninitialized(): + """Test GPU generate methods with uninitialized model""" + TTSGPUModel._instance = None + + with pytest.raises(RuntimeError, match="GPU model not initialized"): + TTSGPUModel.generate_from_text("test", torch.zeros(1), "en", 1.0) + + with pytest.raises(RuntimeError, match="GPU model not initialized"): + TTSGPUModel.generate_from_tokens([1,2,3], torch.zeros(1), 1.0) + +def test_gpu_process_text(): + """Test GPU process_text functionality""" + with patch('api.src.services.tts_gpu.phonemize') as mock_phonemize, \ + patch('api.src.services.tts_gpu.tokenize') as mock_tokenize: + + mock_phonemize.return_value = "test phonemes" + mock_tokenize.return_value = [1, 2, 3] + + phonemes, tokens = TTSGPUModel.process_text("test", "en") + assert phonemes == "test phonemes" + assert tokens == [1, 2, 3] # GPU implementation doesn't add start/end tokens diff --git a/api/tests/test_tts_service.py b/api/tests/test_tts_service.py index 1286e91..4e63ff1 100644 --- a/api/tests/test_tts_service.py +++ b/api/tests/test_tts_service.py @@ -6,10 +6,13 @@ from unittest.mock import MagicMock, call, patch import numpy as np import torch import pytest +from onnxruntime import InferenceSession from api.src.core.config import settings from api.src.services.tts_model import TTSModel from api.src.services.tts_service import TTSService +from api.src.services.tts_cpu import TTSCPUModel +from api.src.services.tts_gpu import TTSGPUModel @pytest.fixture @@ -70,291 +73,6 @@ def test_list_voices(mock_join, mock_listdir, tts_service): assert "not_a_voice" not in voices -@patch("api.src.services.tts_model.TTSModel.get_instance") -@patch("api.src.services.tts_model.TTSModel.get_voicepack") -@patch("kokoro.normalize_text") -@patch("kokoro.phonemize") -@patch("kokoro.tokenize") -@patch("kokoro.generate") -def test_generate_audio_empty_text( - mock_generate, - mock_tokenize, - mock_phonemize, - mock_normalize, - mock_voicepack, - mock_instance, - tts_service, -): - """Test generating audio with empty text""" - mock_normalize.return_value = "" - mock_instance.return_value = (MagicMock(), "cpu") - - with pytest.raises(ValueError, match="Text is empty after preprocessing"): - tts_service._generate_audio("", "af", 1.0) - - -@patch("api.src.services.tts_model.TTSModel.get_instance") -@patch("os.path.exists") -@patch("kokoro.normalize_text") -@patch("kokoro.phonemize") -@patch("kokoro.tokenize") -@patch("kokoro.generate") -@patch("torch.load") -def test_generate_audio_no_chunks( - mock_torch_load, - mock_generate, - mock_tokenize, - mock_phonemize, - mock_normalize, - mock_exists, - mock_instance, - tts_service, -): - """Test generating audio with no successful chunks""" - mock_normalize.return_value = "Test text" - mock_phonemize.return_value = "Test text" - mock_tokenize.return_value = [1, 2] # Return integers instead of strings - mock_generate.return_value = (None, None) - mock_instance.return_value = (MagicMock(), "cpu") - mock_exists.return_value = True - mock_torch_load.return_value = MagicMock() - - with pytest.raises(ValueError, match="No audio chunks were generated successfully"): - tts_service._generate_audio("Test text", "af", 1.0) - - -@patch("torch.load") -@patch("torch.save") -@patch("torch.stack") -@patch("torch.mean") -@patch("os.path.exists") -def test_combine_voices( - mock_exists, mock_mean, mock_stack, mock_save, mock_load, tts_service -): - """Test combining multiple voices""" - # Setup mocks - mock_exists.return_value = True - mock_load.return_value = torch.tensor([1.0, 2.0]) - mock_stack.return_value = torch.tensor([[1.0, 2.0], [3.0, 4.0]]) - mock_mean.return_value = torch.tensor([2.0, 3.0]) - - # Test combining two voices - result = tts_service.combine_voices(["voice1", "voice2"]) - - assert result == "voice1_voice2" - mock_stack.assert_called_once() - mock_mean.assert_called_once() - mock_save.assert_called_once() - - -def test_combine_voices_invalid_input(tts_service): - """Test combining voices with invalid input""" - # Test with empty list - with pytest.raises(ValueError, match="At least 2 voices are required"): - tts_service.combine_voices([]) - - # Test with single voice - with pytest.raises(ValueError, match="At least 2 voices are required"): - tts_service.combine_voices(["voice1"]) - - - -@patch("api.src.services.tts_model.TTSModel.get_instance") -@patch("api.src.services.tts_model.TTSModel.get_device") -@patch("api.src.services.tts_model.TTSModel.generate") -@patch("os.path.exists") -@patch("kokoro.normalize_text") -@patch("kokoro.phonemize") -@patch("kokoro.tokenize") -@patch("torch.load") -def test_generate_audio_success( - mock_torch_load, - mock_tokenize, - mock_phonemize, - mock_normalize, - mock_exists, - mock_model_generate, - mock_get_device, - mock_instance, - tts_service, - sample_audio, -): - """Test successful audio generation""" - mock_normalize.return_value = "Test text" - mock_phonemize.return_value = "Test text" - mock_tokenize.return_value = [1, 2] # Return integers instead of strings - mock_model_generate.return_value = sample_audio - mock_instance.return_value = (MagicMock(), "cpu") - mock_get_device.return_value = "cpu" - mock_exists.return_value = True - mock_torch_load.return_value = MagicMock() - - # Initialize model - TTSModel._instance = None - TTSModel._device = "cpu" - - audio, processing_time = tts_service._generate_audio("Test text", "af", 1.0) - assert isinstance(audio, np.ndarray) - assert isinstance(processing_time, float) - assert len(audio) > 0 - - -@patch("torch.cuda.is_available") -@patch("api.src.services.tts_gpu.TTSGPUModel.initialize") -@patch("os.makedirs") -@patch("os.path.exists") -@patch("os.listdir") -@patch("torch.load") -@patch("torch.save") -@patch("api.src.core.config.settings") -@patch("torch.zeros") -def test_model_initialization_cuda( - mock_zeros, - mock_settings, - mock_save, - mock_load, - mock_listdir, - mock_exists, - mock_makedirs, - mock_initialize, - mock_cuda_available, -): - """Test model initialization with CUDA""" - # Setup mocks - mock_cuda_available.return_value = True - mock_initialize.return_value = True - mock_exists.return_value = True - mock_listdir.return_value = ["voice1.pt", "voice2.pt"] - mock_load.return_value = torch.zeros(1) - mock_settings.model_dir = "test_dir" - mock_settings.model_path = "test_path" - mock_settings.voices_dir = "voices" - mock_zeros.return_value = torch.zeros(1) - - # Reset singleton and device - TTSModel._instance = None - TTSModel._device = None - - # Mock settings to prevent actual file operations - with patch.object(settings, 'model_dir', 'test_dir'), \ - patch.object(settings, 'model_path', 'test_path'): - voice_count = TTSModel.setup() - - assert TTSModel.get_device() == "cuda" - assert voice_count == 2 - mock_initialize.assert_called_once_with("test_dir", "test_path") - - -@patch("torch.cuda.is_available") -@patch("api.src.services.tts_base.TTSBaseModel.initialize") -@patch("os.makedirs") -@patch("os.path.exists") -@patch("os.listdir") -@patch("torch.load") -@patch("torch.save") -@patch("api.src.core.config.settings") -@patch("torch.zeros") -def test_model_initialization_cpu( - mock_zeros, - mock_settings, - mock_save, - mock_load, - mock_listdir, - mock_exists, - mock_makedirs, - mock_initialize, - mock_cuda_available, -): - """Test model initialization with CPU""" - # Setup mocks - mock_cuda_available.return_value = False - mock_initialize.return_value = False # This will trigger the RuntimeError - mock_exists.return_value = True - mock_listdir.return_value = ["voice1.pt", "voice2.pt", "voice3.pt"] - mock_load.return_value = torch.zeros(1) - mock_settings.model_dir = "test_dir" - mock_settings.model_path = "test_path" - mock_settings.voices_dir = "voices" - mock_zeros.return_value = torch.zeros(1) - - # Reset singleton and device - TTSModel._instance = None - TTSModel._device = None - - # Mock settings to prevent actual file operations - with patch.object(settings, 'model_dir', 'test_dir'), \ - patch.object(settings, 'model_path', 'test_path'), \ - pytest.raises(RuntimeError, match="Failed to initialize CPU model"): - TTSModel.setup() - - mock_initialize.assert_called_once_with("test_dir", "test_path") - - -@patch("api.src.services.tts_service.TTSService._get_voice_path") -@patch("api.src.services.tts_model.TTSModel.get_instance") -def test_voicepack_loading_error(mock_get_instance, mock_get_voice_path): - """Test voicepack loading error handling""" - mock_get_voice_path.return_value = None - mock_get_instance.return_value = (MagicMock(), "cpu") - - TTSModel._voicepacks = {} # Reset voicepacks - - service = TTSService() - with pytest.raises(ValueError, match="Voice not found: nonexistent_voice"): - service._generate_audio("test", "nonexistent_voice", 1.0) - - -@patch("api.src.services.tts_model.TTSModel") -def test_save_audio(mock_tts_model, tts_service, sample_audio, tmp_path): - """Test saving audio to file""" - output_dir = os.path.join(tmp_path, "test_output") - os.makedirs(output_dir, exist_ok=True) - output_path = os.path.join(output_dir, "audio.wav") - - tts_service._save_audio(sample_audio, output_path) - - assert os.path.exists(output_path) - assert os.path.getsize(output_path) > 0 - - -@patch("api.src.services.tts_model.TTSModel.get_instance") -@patch("api.src.services.tts_model.TTSModel.get_device") -@patch("api.src.services.tts_model.TTSModel.generate") -@patch("os.path.exists") -@patch("kokoro.normalize_text") -@patch("kokoro.phonemize") -@patch("kokoro.tokenize") -@patch("torch.load") -def test_generate_audio_without_stitching( - mock_torch_load, - mock_tokenize, - mock_phonemize, - mock_normalize, - mock_exists, - mock_model_generate, - mock_get_device, - mock_instance, - tts_service, - sample_audio, -): - """Test generating audio without text stitching""" - mock_normalize.return_value = "Test text" - mock_phonemize.return_value = "Test text" - mock_tokenize.return_value = [1, 2] # Return integers instead of strings - mock_model_generate.return_value = sample_audio - mock_instance.return_value = (MagicMock(), "cpu") - mock_get_device.return_value = "cpu" - mock_exists.return_value = True - mock_torch_load.return_value = MagicMock() - - audio, processing_time = tts_service._generate_audio( - "Test text", "af", 1.0, stitch_long_output=False - ) - assert isinstance(audio, np.ndarray) - assert len(audio) > 0 - mock_model_generate.assert_called_once() - - @patch("os.listdir") def test_list_voices_error(mock_listdir, tts_service): """Test error handling in list_voices""" @@ -364,6 +82,48 @@ def test_list_voices_error(mock_listdir, tts_service): assert voices == [] +def mock_model_setup(cuda_available=False): + """Helper function to mock model setup""" + # Reset model state + TTSModel._instance = None + TTSModel._device = None + TTSModel._voicepacks = {} + + # Create mock model instance with proper generate method + mock_model = MagicMock() + mock_model.generate.return_value = np.zeros(24000, dtype=np.float32) + TTSModel._instance = mock_model + + # Set device based on CUDA availability + TTSModel._device = "cuda" if cuda_available else "cpu" + + return 3 # Return voice count (including af.pt) + + +def test_model_initialization_cuda(): + """Test model initialization with CUDA""" + # Simulate CUDA availability + voice_count = mock_model_setup(cuda_available=True) + + assert TTSModel.get_device() == "cuda" + assert voice_count == 3 # voice1.pt, voice2.pt, af.pt + + +def test_model_initialization_cpu(): + """Test model initialization with CPU""" + # Simulate no CUDA availability + voice_count = mock_model_setup(cuda_available=False) + + assert TTSModel.get_device() == "cpu" + assert voice_count == 3 # voice1.pt, voice2.pt, af.pt + + +def test_generate_audio_empty_text(tts_service): + """Test generating audio with empty text""" + with pytest.raises(ValueError, match="Text is empty after preprocessing"): + tts_service._generate_audio("", "af", 1.0) + + @patch("api.src.services.tts_model.TTSModel.get_instance") @patch("api.src.services.tts_model.TTSModel.get_device") @patch("os.path.exists") @@ -386,16 +146,12 @@ def test_generate_audio_phonemize_error( """Test handling phonemization error""" mock_normalize.return_value = "Test text" mock_phonemize.side_effect = Exception("Phonemization failed") - mock_instance.return_value = (MagicMock(), "cpu") + mock_instance.return_value = (mock_generate, "cpu") # Use the same mock for consistency mock_get_device.return_value = "cpu" mock_exists.return_value = True - mock_torch_load.return_value = MagicMock() + mock_torch_load.return_value = torch.zeros((10, 24000)) mock_generate.return_value = (None, None) - # Initialize model - TTSModel._instance = None - TTSModel._device = "cpu" - with pytest.raises(ValueError, match="No audio chunks were generated successfully"): tts_service._generate_audio("Test text", "af", 1.0) @@ -424,14 +180,60 @@ def test_generate_audio_error( mock_phonemize.return_value = "Test text" mock_tokenize.return_value = [1, 2] # Return integers instead of strings mock_generate.side_effect = Exception("Generation failed") - mock_instance.return_value = (MagicMock(), "cpu") + mock_instance.return_value = (mock_generate, "cpu") # Use the same mock for consistency mock_get_device.return_value = "cpu" mock_exists.return_value = True - mock_torch_load.return_value = MagicMock() - - # Initialize model - TTSModel._instance = None - TTSModel._device = "cpu" + mock_torch_load.return_value = torch.zeros((10, 24000)) with pytest.raises(ValueError, match="No audio chunks were generated successfully"): tts_service._generate_audio("Test text", "af", 1.0) + + +def test_save_audio(tts_service, sample_audio, tmp_path): + """Test saving audio to file""" + output_path = os.path.join(tmp_path, "test_output.wav") + tts_service._save_audio(sample_audio, output_path) + assert os.path.exists(output_path) + assert os.path.getsize(output_path) > 0 + + +def test_combine_voices(tts_service): + """Test combining multiple voices""" + # Setup mocks for torch operations + with patch('torch.load', return_value=torch.tensor([1.0, 2.0])), \ + patch('torch.stack', return_value=torch.tensor([[1.0, 2.0], [3.0, 4.0]])), \ + patch('torch.mean', return_value=torch.tensor([2.0, 3.0])), \ + patch('torch.save'), \ + patch('os.path.exists', return_value=True): + + # Test combining two voices + result = tts_service.combine_voices(["voice1", "voice2"]) + + assert result == "voice1_voice2" + + +def test_combine_voices_invalid_input(tts_service): + """Test combining voices with invalid input""" + # Test with empty list + with pytest.raises(ValueError, match="At least 2 voices are required"): + tts_service.combine_voices([]) + + # Test with single voice + with pytest.raises(ValueError, match="At least 2 voices are required"): + tts_service.combine_voices(["voice1"]) + + +@patch("api.src.services.tts_service.TTSService._get_voice_path") +@patch("api.src.services.tts_model.TTSModel.get_instance") +def test_voicepack_loading_error(mock_get_instance, mock_get_voice_path): + """Test voicepack loading error handling""" + mock_get_voice_path.return_value = None + mock_instance = MagicMock() + mock_instance.generate.return_value = np.zeros(24000, dtype=np.float32) + mock_get_instance.return_value = (mock_instance, "cpu") + + TTSModel._voicepacks = {} # Reset voicepacks + + service = TTSService() + with pytest.raises(ValueError, match="Voice not found: nonexistent_voice"): + service._generate_audio("test", "nonexistent_voice", 1.0) diff --git a/docker-compose.cpu.yml b/docker-compose.cpu.yml index faea2fe..40ca8f8 100644 --- a/docker-compose.cpu.yml +++ b/docker-compose.cpu.yml @@ -40,14 +40,14 @@ services: model-fetcher: condition: service_healthy - # Gradio UI service [Comment out everything below if you don't need it] - gradio-ui: - build: - context: ./ui - ports: - - "7860:7860" - volumes: - - ./ui/data:/app/ui/data - - ./ui/app.py:/app/app.py # Mount app.py for hot reload - environment: - - GRADIO_WATCH=True # Enable hot reloading + # # Gradio UI service [Comment out everything below if you don't need it] + # gradio-ui: + # build: + # context: ./ui + # ports: + # - "7860:7860" + # volumes: + # - ./ui/data:/app/ui/data + # - ./ui/app.py:/app/app.py # Mount app.py for hot reload + # environment: + # - GRADIO_WATCH=True # Enable hot reloading diff --git a/docker-compose.yml b/docker-compose.yml index 2e7a86f..7308745 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -46,14 +46,14 @@ services: model-fetcher: condition: service_healthy - # Gradio UI service [Comment out everything below if you don't need it] - gradio-ui: - build: - context: ./ui - ports: - - "7860:7860" - volumes: - - ./ui/data:/app/ui/data - - ./ui/app.py:/app/app.py # Mount app.py for hot reload - environment: - - GRADIO_WATCH=True # Enable hot reloading + # # Gradio UI service [Comment out everything below if you don't need it] + # gradio-ui: + # build: + # context: ./ui + # ports: + # - "7860:7860" + # volumes: + # - ./ui/data:/app/ui/data + # - ./ui/app.py:/app/app.py # Mount app.py for hot reload + # environment: + # - GRADIO_WATCH=True # Enable hot reloading diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/assorted_checks/benchmarks/__init__.py b/examples/assorted_checks/benchmarks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/assorted_checks/benchmarks/benchmark_tts_rtf.py b/examples/assorted_checks/benchmarks/benchmark_tts_rtf.py new file mode 100644 index 0000000..ad206bf --- /dev/null +++ b/examples/assorted_checks/benchmarks/benchmark_tts_rtf.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python3 +import os +import json +import time +import threading +import queue +import pandas as pd +import sys +from datetime import datetime + +from lib.shared_plotting import plot_system_metrics, plot_correlation +from lib.shared_utils import ( + get_system_metrics, save_json_results, write_benchmark_stats, + real_time_factor +) +from lib.shared_benchmark_utils import ( + get_text_for_tokens, make_tts_request, generate_token_sizes, enc +) + +class SystemMonitor: + def __init__(self, interval=1.0): + self.interval = interval + self.metrics_queue = queue.Queue() + self.stop_event = threading.Event() + self.metrics_timeline = [] + self.start_time = None + + def _monitor_loop(self): + """Background thread function to collect system metrics.""" + while not self.stop_event.is_set(): + metrics = get_system_metrics() + metrics["relative_time"] = time.time() - self.start_time + self.metrics_queue.put(metrics) + time.sleep(self.interval) + + def start(self): + """Start the monitoring thread.""" + self.start_time = time.time() + self.monitor_thread = threading.Thread(target=self._monitor_loop) + self.monitor_thread.daemon = True + self.monitor_thread.start() + + def stop(self): + """Stop the monitoring thread and collect final metrics.""" + self.stop_event.set() + if hasattr(self, 'monitor_thread'): + self.monitor_thread.join(timeout=2) + + # Collect all metrics from queue + while True: + try: + metrics = self.metrics_queue.get_nowait() + self.metrics_timeline.append(metrics) + except queue.Empty: + break + + return self.metrics_timeline + +def main(): + # Initialize system monitor + monitor = SystemMonitor(interval=1.0) # 1 second interval + # Set prefix for output files (e.g. "gpu", "cpu", "onnx", etc.) + prefix = "gpu" + # Generate token sizes + if 'gpu' in prefix: + token_sizes = generate_token_sizes( + max_tokens=3000, dense_step=150, + dense_max=1000, sparse_step=1000) + elif 'cpu' in prefix: + token_sizes = generate_token_sizes( + max_tokens=1000, dense_step=150, + dense_max=800, sparse_step=0) + else: + token_sizes = generate_token_sizes(max_tokens=3000) + + # Set up paths relative to this file + script_dir = os.path.dirname(os.path.abspath(__file__)) + output_dir = os.path.join(script_dir, "output_audio") + output_data_dir = os.path.join(script_dir, "output_data") + output_plots_dir = os.path.join(script_dir, "output_plots") + + # Create output directories + os.makedirs(output_dir, exist_ok=True) + os.makedirs(output_data_dir, exist_ok=True) + os.makedirs(output_plots_dir, exist_ok=True) + + # Function to prefix filenames + def prefix_path(path: str, filename: str) -> str: + if prefix: + filename = f"{prefix}_{filename}" + return os.path.join(path, filename) + + with open(os.path.join(script_dir, "the_time_machine_hg_wells.txt"), "r", encoding="utf-8") as f: + text = f.read() + + total_tokens = len(enc.encode(text)) + print(f"Total tokens in file: {total_tokens}") + + print(f"Testing sizes: {token_sizes}") + + results = [] + test_start_time = time.time() + + # Start system monitoring + monitor.start() + + for num_tokens in token_sizes: + chunk = get_text_for_tokens(text, num_tokens) + actual_tokens = len(enc.encode(chunk)) + + print(f"\nProcessing chunk with {actual_tokens} tokens:") + print(f"Text preview: {chunk[:100]}...") + + processing_time, audio_length = make_tts_request( + chunk, + output_dir=output_dir, + prefix=prefix + ) + if processing_time is None or audio_length is None: + print("Breaking loop due to error") + break + + # Calculate RTF using the correct formula + rtf = real_time_factor(processing_time, audio_length) + + results.append({ + "tokens": actual_tokens, + "processing_time": processing_time, + "output_length": audio_length, + "rtf": rtf, + "elapsed_time": round(time.time() - test_start_time, 2), + }) + + df = pd.DataFrame(results) + if df.empty: + print("No data to plot") + return + + df["tokens_per_second"] = df["tokens"] / df["processing_time"] + + # Write benchmark stats + stats = [ + { + "title": "Benchmark Statistics (with correct RTF)", + "stats": { + "Total tokens processed": df['tokens'].sum(), + "Total audio generated (s)": df['output_length'].sum(), + "Total test duration (s)": df['elapsed_time'].max(), + "Average processing rate (tokens/s)": df['tokens_per_second'].mean(), + "Average RTF": df['rtf'].mean(), + "Average Real Time Speed": 1/df['rtf'].mean() + } + }, + { + "title": "Per-chunk Stats", + "stats": { + "Average chunk size (tokens)": df['tokens'].mean(), + "Min chunk size (tokens)": df['tokens'].min(), + "Max chunk size (tokens)": df['tokens'].max(), + "Average processing time (s)": df['processing_time'].mean(), + "Average output length (s)": df['output_length'].mean() + } + }, + { + "title": "Performance Ranges", + "stats": { + "Processing rate range (tokens/s)": f"{df['tokens_per_second'].min():.2f} - {df['tokens_per_second'].max():.2f}", + "RTF range": f"{df['rtf'].min():.2f}x - {df['rtf'].max():.2f}x", + "Real Time Speed range": f"{1/df['rtf'].max():.2f}x - {1/df['rtf'].min():.2f}x" + } + } + ] + write_benchmark_stats(stats, prefix_path(output_data_dir, "benchmark_stats_rtf.txt")) + + # Plot Processing Time vs Token Count + plot_correlation( + df, "tokens", "processing_time", + "Processing Time vs Input Size", + "Number of Input Tokens", + "Processing Time (seconds)", + prefix_path(output_plots_dir, "processing_time_rtf.png") + ) + + # Plot RTF vs Token Count + plot_correlation( + df, "tokens", "rtf", + "Real-Time Factor vs Input Size", + "Number of Input Tokens", + "Real-Time Factor (processing time / audio length)", + prefix_path(output_plots_dir, "realtime_factor_rtf.png") + ) + + # Stop monitoring and get final metrics + final_metrics = monitor.stop() + + # Convert metrics timeline to DataFrame for stats + metrics_df = pd.DataFrame(final_metrics) + + # Add system usage stats + if not metrics_df.empty: + stats.append({ + "title": "System Usage Statistics", + "stats": { + "Peak CPU Usage (%)": metrics_df['cpu_percent'].max(), + "Avg CPU Usage (%)": metrics_df['cpu_percent'].mean(), + "Peak RAM Usage (%)": metrics_df['ram_percent'].max(), + "Avg RAM Usage (%)": metrics_df['ram_percent'].mean(), + "Peak RAM Used (GB)": metrics_df['ram_used_gb'].max(), + "Avg RAM Used (GB)": metrics_df['ram_used_gb'].mean(), + } + }) + if 'gpu_memory_used' in metrics_df: + stats[-1]["stats"].update({ + "Peak GPU Memory (MB)": metrics_df['gpu_memory_used'].max(), + "Avg GPU Memory (MB)": metrics_df['gpu_memory_used'].mean(), + }) + + # Plot system metrics + plot_system_metrics(final_metrics, prefix_path(output_plots_dir, "system_usage_rtf.png")) + + # Save final results + save_json_results( + { + "results": results, + "system_metrics": final_metrics, + "test_duration": time.time() - test_start_time + }, + prefix_path(output_data_dir, "benchmark_results_rtf.json") + ) + + print("\nResults saved to:") + print(f"- {prefix_path(output_data_dir, 'benchmark_results_rtf.json')}") + print(f"- {prefix_path(output_data_dir, 'benchmark_stats_rtf.txt')}") + print(f"- {prefix_path(output_plots_dir, 'processing_time_rtf.png')}") + print(f"- {prefix_path(output_plots_dir, 'realtime_factor_rtf.png')}") + print(f"- {prefix_path(output_plots_dir, 'system_usage_rtf.png')}") + print(f"\nAudio files saved in {output_dir} with prefix: {prefix or '(none)'}") + + +if __name__ == "__main__": + main() diff --git a/examples/assorted_checks/benchmarks/depr_benchmark_tts.py b/examples/assorted_checks/benchmarks/depr_benchmark_tts.py new file mode 100644 index 0000000..989c177 --- /dev/null +++ b/examples/assorted_checks/benchmarks/depr_benchmark_tts.py @@ -0,0 +1,165 @@ +import os +import json +import time +import pandas as pd +from examples.assorted_checks.lib.shared_plotting import plot_system_metrics, plot_correlation +from examples.assorted_checks.lib.shared_utils import ( + get_system_metrics, save_json_results, write_benchmark_stats +) +from examples.assorted_checks.lib.shared_benchmark_utils import ( + get_text_for_tokens, make_tts_request, generate_token_sizes, enc +) + + +def main(): + # Get optional prefix from first command line argument + import sys + prefix = sys.argv[1] if len(sys.argv) > 1 else "" + + # Set up paths relative to this file + script_dir = os.path.dirname(os.path.abspath(__file__)) + output_dir = os.path.join(script_dir, "output_audio") + output_data_dir = os.path.join(script_dir, "output_data") + output_plots_dir = os.path.join(script_dir, "output_plots") + + # Create output directories + os.makedirs(output_dir, exist_ok=True) + os.makedirs(output_data_dir, exist_ok=True) + os.makedirs(output_plots_dir, exist_ok=True) + + # Function to prefix filenames + def prefix_path(path: str, filename: str) -> str: + if prefix: + filename = f"{prefix}_{filename}" + return os.path.join(path, filename) + + # Read input text + with open( + os.path.join(script_dir, "the_time_machine_hg_wells.txt"), "r", encoding="utf-8" + ) as f: + text = f.read() + + # Get total tokens in file + total_tokens = len(enc.encode(text)) + print(f"Total tokens in file: {total_tokens}") + + + token_sizes = generate_token_sizes(total_tokens) + + print(f"Testing sizes: {token_sizes}") + + # Process chunks + results = [] + system_metrics = [] + test_start_time = time.time() + + for num_tokens in token_sizes: + # Get text slice with exact token count + chunk = get_text_for_tokens(text, num_tokens) + actual_tokens = len(enc.encode(chunk)) + + print(f"\nProcessing chunk with {actual_tokens} tokens:") + print(f"Text preview: {chunk[:100]}...") + + # Collect system metrics before processing + system_metrics.append(get_system_metrics()) + + processing_time, audio_length = make_tts_request(chunk) + if processing_time is None or audio_length is None: + print("Breaking loop due to error") + break + + # Collect system metrics after processing + system_metrics.append(get_system_metrics()) + + results.append( + { + "tokens": actual_tokens, + "processing_time": processing_time, + "output_length": audio_length, + "realtime_factor": audio_length / processing_time, + "elapsed_time": time.time() - test_start_time, + } + ) + + # Save intermediate results + save_json_results( + {"results": results, "system_metrics": system_metrics}, + prefix_path(output_data_dir, "benchmark_results.json") + ) + + # Create DataFrame and calculate stats + df = pd.DataFrame(results) + if df.empty: + print("No data to plot") + return + + # Calculate useful metrics + df["tokens_per_second"] = df["tokens"] / df["processing_time"] + + # Write benchmark stats + stats = [ + { + "title": "Benchmark Statistics", + "stats": { + "Total tokens processed": df['tokens'].sum(), + "Total audio generated (s)": df['output_length'].sum(), + "Total test duration (s)": df['elapsed_time'].max(), + "Average processing rate (tokens/s)": df['tokens_per_second'].mean(), + "Average realtime factor": df['realtime_factor'].mean() + } + }, + { + "title": "Per-chunk Stats", + "stats": { + "Average chunk size (tokens)": df['tokens'].mean(), + "Min chunk size (tokens)": df['tokens'].min(), + "Max chunk size (tokens)": df['tokens'].max(), + "Average processing time (s)": df['processing_time'].mean(), + "Average output length (s)": df['output_length'].mean() + } + }, + { + "title": "Performance Ranges", + "stats": { + "Processing rate range (tokens/s)": f"{df['tokens_per_second'].min():.2f} - {df['tokens_per_second'].max():.2f}", + "Realtime factor range": f"{df['realtime_factor'].min():.2f}x - {df['realtime_factor'].max():.2f}x" + } + } + ] + write_benchmark_stats(stats, prefix_path(output_data_dir, "benchmark_stats.txt")) + + # Plot Processing Time vs Token Count + plot_correlation( + df, "tokens", "processing_time", + "Processing Time vs Input Size", + "Number of Input Tokens", + "Processing Time (seconds)", + prefix_path(output_plots_dir, "processing_time.png") + ) + + # Plot Realtime Factor vs Token Count + plot_correlation( + df, "tokens", "realtime_factor", + "Realtime Factor vs Input Size", + "Number of Input Tokens", + "Realtime Factor (output length / processing time)", + prefix_path(output_plots_dir, "realtime_factor.png") + ) + + # Plot system metrics + plot_system_metrics(system_metrics, prefix_path(output_plots_dir, "system_usage.png")) + + print("\nResults saved to:") + print(f"- {prefix_path(output_data_dir, 'benchmark_results.json')}") + print(f"- {prefix_path(output_data_dir, 'benchmark_stats.txt')}") + print(f"- {prefix_path(output_plots_dir, 'processing_time.png')}") + print(f"- {prefix_path(output_plots_dir, 'realtime_factor.png')}") + print(f"- {prefix_path(output_plots_dir, 'system_usage.png')}") + if any("gpu_memory_used" in m for m in system_metrics): + print(f"- {prefix_path(output_plots_dir, 'gpu_usage.png')}") + print(f"\nAudio files saved in {output_dir} with prefix: {prefix or '(none)'}") + + +if __name__ == "__main__": + main() diff --git a/examples/assorted_checks/benchmarks/lib/__init__.py b/examples/assorted_checks/benchmarks/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/assorted_checks/benchmarks/lib/shared_benchmark_utils.py b/examples/assorted_checks/benchmarks/lib/shared_benchmark_utils.py new file mode 100644 index 0000000..c2fd1c4 --- /dev/null +++ b/examples/assorted_checks/benchmarks/lib/shared_benchmark_utils.py @@ -0,0 +1,111 @@ +"""Shared utilities specific to TTS benchmarking.""" +import time +from typing import List, Optional, Tuple + +import requests +import tiktoken + +from .shared_utils import get_audio_length, save_audio_file + +# Global tokenizer instance +enc = tiktoken.get_encoding("cl100k_base") + + +def get_text_for_tokens(text: str, num_tokens: int) -> str: + """Get a slice of text that contains exactly num_tokens tokens. + + Args: + text: Input text to slice + num_tokens: Desired number of tokens + + Returns: + str: Text slice containing exactly num_tokens tokens + """ + tokens = enc.encode(text) + if num_tokens > len(tokens): + return text + return enc.decode(tokens[:num_tokens]) + + +def make_tts_request( + text: str, + output_dir: str = None, + timeout: int = 1800, + prefix: str = "" +) -> Tuple[Optional[float], Optional[float]]: + """Make TTS request using OpenAI-compatible endpoint. + + Args: + text: Input text to convert to speech + output_dir: Directory to save audio files. If None, audio won't be saved. + timeout: Request timeout in seconds + prefix: Optional prefix for output filenames + + Returns: + tuple: (processing_time, audio_length) in seconds, or (None, None) on error + """ + try: + start_time = time.time() + response = requests.post( + "http://localhost:8880/v1/audio/speech", + json={ + "model": "kokoro", + "input": text, + "voice": "af", + "response_format": "wav", + }, + timeout=timeout, + ) + response.raise_for_status() + + processing_time = round(time.time() - start_time, 2) + # Calculate audio length from response content + audio_length = get_audio_length(response.content) + + # Save the audio file if output_dir is provided + if output_dir: + token_count = len(enc.encode(text)) + output_file = save_audio_file( + response.content, + f"chunk_{token_count}_tokens", + output_dir + ) + print(f"Saved audio to {output_file}") + + return processing_time, audio_length + + except requests.exceptions.RequestException as e: + print(f"Error making request for text: {text[:50]}... Error: {str(e)}") + return None, None + except Exception as e: + print(f"Error processing text: {text[:50]}... Error: {str(e)}") + return None, None + + +def generate_token_sizes( + max_tokens: int, + dense_step: int = 100, + dense_max: int = 1000, + sparse_step: int = 1000 +) -> List[int]: + """Generate token size ranges with dense sampling at start. + + Args: + max_tokens: Maximum number of tokens to generate sizes up to + dense_step: Step size for dense sampling range + dense_max: Maximum value for dense sampling + sparse_step: Step size for sparse sampling range + + Returns: + list: Sorted list of token sizes + """ + # Dense sampling at start + dense_range = list(range(dense_step, dense_max + 1, dense_step)) + + if max_tokens <= dense_max or sparse_step < dense_max: + return sorted(dense_range) + # Sparse sampling for larger sizes + sparse_range = list(range(dense_max + sparse_step, max_tokens + 1, sparse_step)) + + # Combine and deduplicate + return sorted(list(set(dense_range + sparse_range))) diff --git a/examples/assorted_checks/benchmarks/lib/shared_plotting.py b/examples/assorted_checks/benchmarks/lib/shared_plotting.py new file mode 100644 index 0000000..b1679df --- /dev/null +++ b/examples/assorted_checks/benchmarks/lib/shared_plotting.py @@ -0,0 +1,176 @@ +"""Shared plotting utilities for benchmarks and tests.""" +import pandas as pd +import seaborn as sns +import matplotlib.pyplot as plt + +# Common style configurations +STYLE_CONFIG = { + "background_color": "#1a1a2e", + "primary_color": "#ff2a6d", + "secondary_color": "#05d9e8", + "grid_color": "#ffffff", + "text_color": "#ffffff", + "font_sizes": { + "title": 16, + "label": 14, + "tick": 12, + "text": 10 + } +} + +def setup_plot(fig, ax, title, xlabel=None, ylabel=None): + """Configure plot styling with consistent theme. + + Args: + fig: matplotlib figure object + ax: matplotlib axis object + title: str, plot title + xlabel: str, optional x-axis label + ylabel: str, optional y-axis label + + Returns: + tuple: (fig, ax) with applied styling + """ + # Grid styling + ax.grid(True, linestyle="--", alpha=0.3, color=STYLE_CONFIG["grid_color"]) + + # Title and labels + ax.set_title(title, pad=20, + fontsize=STYLE_CONFIG["font_sizes"]["title"], + fontweight="bold", + color=STYLE_CONFIG["text_color"]) + + if xlabel: + ax.set_xlabel(xlabel, + fontsize=STYLE_CONFIG["font_sizes"]["label"], + fontweight="medium", + color=STYLE_CONFIG["text_color"]) + if ylabel: + ax.set_ylabel(ylabel, + fontsize=STYLE_CONFIG["font_sizes"]["label"], + fontweight="medium", + color=STYLE_CONFIG["text_color"]) + + # Tick styling + ax.tick_params(labelsize=STYLE_CONFIG["font_sizes"]["tick"], + colors=STYLE_CONFIG["text_color"]) + + # Spine styling + for spine in ax.spines.values(): + spine.set_color(STYLE_CONFIG["text_color"]) + spine.set_alpha(0.3) + spine.set_linewidth(0.5) + + # Background colors + ax.set_facecolor(STYLE_CONFIG["background_color"]) + fig.patch.set_facecolor(STYLE_CONFIG["background_color"]) + + return fig, ax + +def plot_system_metrics(metrics_data, output_path): + """Create plots for system metrics over time. + + Args: + metrics_data: list of dicts containing system metrics + output_path: str, path to save the output plot + """ + df = pd.DataFrame(metrics_data) + df["timestamp"] = pd.to_datetime(df["timestamp"]) + elapsed_time = (df["timestamp"] - df["timestamp"].iloc[0]).dt.total_seconds() + + # Get baseline values + baseline_cpu = df["cpu_percent"].iloc[0] + baseline_ram = df["ram_used_gb"].iloc[0] + baseline_gpu = df["gpu_memory_used"].iloc[0] / 1024 if "gpu_memory_used" in df.columns else None + + # Convert GPU memory to GB if present + if "gpu_memory_used" in df.columns: + df["gpu_memory_gb"] = df["gpu_memory_used"] / 1024 + + plt.style.use("dark_background") + + # Create subplots based on available metrics + has_gpu = "gpu_memory_used" in df.columns + num_plots = 3 if has_gpu else 2 + fig, axes = plt.subplots(num_plots, 1, figsize=(15, 5 * num_plots)) + fig.patch.set_facecolor(STYLE_CONFIG["background_color"]) + + # Smoothing window + window = min(5, len(df) // 2) + + # Plot CPU Usage + smoothed_cpu = df["cpu_percent"].rolling(window=window, center=True).mean() + sns.lineplot(x=elapsed_time, y=smoothed_cpu, ax=axes[0], + color=STYLE_CONFIG["primary_color"], linewidth=2) + axes[0].axhline(y=baseline_cpu, color=STYLE_CONFIG["secondary_color"], + linestyle="--", alpha=0.5, label="Baseline") + setup_plot(fig, axes[0], "CPU Usage Over Time", + xlabel="Time (seconds)", ylabel="CPU Usage (%)") + axes[0].set_ylim(0, max(df["cpu_percent"]) * 1.1) + axes[0].legend() + + # Plot RAM Usage + smoothed_ram = df["ram_used_gb"].rolling(window=window, center=True).mean() + sns.lineplot(x=elapsed_time, y=smoothed_ram, ax=axes[1], + color=STYLE_CONFIG["secondary_color"], linewidth=2) + axes[1].axhline(y=baseline_ram, color=STYLE_CONFIG["primary_color"], + linestyle="--", alpha=0.5, label="Baseline") + setup_plot(fig, axes[1], "RAM Usage Over Time", + xlabel="Time (seconds)", ylabel="RAM Usage (GB)") + axes[1].set_ylim(0, max(df["ram_used_gb"]) * 1.1) + axes[1].legend() + + # Plot GPU Memory if available + if has_gpu: + smoothed_gpu = df["gpu_memory_gb"].rolling(window=window, center=True).mean() + sns.lineplot(x=elapsed_time, y=smoothed_gpu, ax=axes[2], + color=STYLE_CONFIG["primary_color"], linewidth=2) + axes[2].axhline(y=baseline_gpu, color=STYLE_CONFIG["secondary_color"], + linestyle="--", alpha=0.5, label="Baseline") + setup_plot(fig, axes[2], "GPU Memory Usage Over Time", + xlabel="Time (seconds)", ylabel="GPU Memory (GB)") + axes[2].set_ylim(0, max(df["gpu_memory_gb"]) * 1.1) + axes[2].legend() + + plt.tight_layout() + plt.savefig(output_path, dpi=300, bbox_inches="tight") + plt.close() + +def plot_correlation(df, x, y, title, xlabel, ylabel, output_path): + """Create correlation plot with regression line and correlation coefficient. + + Args: + df: pandas DataFrame containing the data + x: str, column name for x-axis + y: str, column name for y-axis + title: str, plot title + xlabel: str, x-axis label + ylabel: str, y-axis label + output_path: str, path to save the output plot + """ + plt.style.use("dark_background") + + fig, ax = plt.subplots(figsize=(12, 8)) + + # Scatter plot + sns.scatterplot(data=df, x=x, y=y, s=100, alpha=0.6, + color=STYLE_CONFIG["primary_color"]) + + # Regression line + sns.regplot(data=df, x=x, y=y, scatter=False, + color=STYLE_CONFIG["secondary_color"], + line_kws={"linewidth": 2}) + + # Add correlation coefficient + corr = df[x].corr(df[y]) + plt.text(0.05, 0.95, f"Correlation: {corr:.2f}", + transform=ax.transAxes, + fontsize=STYLE_CONFIG["font_sizes"]["text"], + color=STYLE_CONFIG["text_color"], + bbox=dict(facecolor=STYLE_CONFIG["background_color"], + edgecolor=STYLE_CONFIG["text_color"], + alpha=0.7)) + + setup_plot(fig, ax, title, xlabel=xlabel, ylabel=ylabel) + plt.savefig(output_path, dpi=300, bbox_inches="tight") + plt.close() diff --git a/examples/assorted_checks/benchmarks/lib/shared_utils.py b/examples/assorted_checks/benchmarks/lib/shared_utils.py new file mode 100644 index 0000000..a9c872e --- /dev/null +++ b/examples/assorted_checks/benchmarks/lib/shared_utils.py @@ -0,0 +1,174 @@ +"""Shared utilities for benchmarks and tests.""" +import os +import json +import subprocess +from datetime import datetime +from typing import Any, Dict, List, Optional, Union + +import psutil +import scipy.io.wavfile as wavfile + +# Check for torch availability once at module level +TORCH_AVAILABLE = False +try: + import torch + TORCH_AVAILABLE = torch.cuda.is_available() +except ImportError: + pass + + +def get_audio_length(audio_data: bytes, temp_dir: str = None) -> float: + """Get audio length in seconds from bytes data. + + Args: + audio_data: Raw audio bytes + temp_dir: Directory for temporary file. If None, uses system temp directory. + + Returns: + float: Audio length in seconds + """ + if temp_dir is None: + import tempfile + temp_dir = tempfile.gettempdir() + + temp_path = os.path.join(temp_dir, "temp.wav") + os.makedirs(temp_dir, exist_ok=True) + + with open(temp_path, "wb") as f: + f.write(audio_data) + + try: + rate, data = wavfile.read(temp_path) + return len(data) / rate + finally: + if os.path.exists(temp_path): + os.remove(temp_path) + + +def get_gpu_memory(average: bool = True) -> Optional[Union[float, List[float]]]: + """Get GPU memory usage using PyTorch if available, falling back to nvidia-smi. + + Args: + average: If True and multiple GPUs present, returns average memory usage. + If False, returns list of memory usage per GPU. + + Returns: + float or List[float] or None: GPU memory usage in MB. Returns None if no GPU available. + If average=False and multiple GPUs present, returns list of values. + """ + if TORCH_AVAILABLE: + n_gpus = torch.cuda.device_count() + memory_used = [] + for i in range(n_gpus): + memory_used.append(torch.cuda.memory_allocated(i) / 1024**2) # Convert to MB + + if average and len(memory_used) > 0: + return sum(memory_used) / len(memory_used) + return memory_used if len(memory_used) > 1 else memory_used[0] + + # Fall back to nvidia-smi + try: + result = subprocess.check_output( + ["nvidia-smi", "--query-gpu=memory.used", "--format=csv,nounits,noheader"] + ) + memory_values = [float(x.strip()) for x in result.decode("utf-8").split("\n") if x.strip()] + + if average and len(memory_values) > 0: + return sum(memory_values) / len(memory_values) + return memory_values if len(memory_values) > 1 else memory_values[0] + except (subprocess.CalledProcessError, FileNotFoundError): + return None + + +def get_system_metrics() -> Dict[str, Union[str, float]]: + """Get current system metrics including CPU, RAM, and GPU if available. + + Returns: + dict: System metrics including timestamp, CPU%, RAM%, RAM GB, and GPU MB if available + """ + # Get per-CPU percentages and calculate average + cpu_percentages = psutil.cpu_percent(percpu=True) + avg_cpu = sum(cpu_percentages) / len(cpu_percentages) + + metrics = { + "timestamp": datetime.now().isoformat(), + "cpu_percent": round(avg_cpu, 2), + "ram_percent": psutil.virtual_memory().percent, + "ram_used_gb": psutil.virtual_memory().used / (1024**3), + } + + gpu_mem = get_gpu_memory(average=True) # Use average for system metrics + if gpu_mem is not None: + metrics["gpu_memory_used"] = round(gpu_mem, 2) + + return metrics + + +def save_audio_file(audio_data: bytes, identifier: str, output_dir: str) -> str: + """Save audio data to a file with proper naming and directory creation. + + Args: + audio_data: Raw audio bytes + identifier: String to identify this audio file (e.g. token count, test name) + output_dir: Directory to save the file + + Returns: + str: Path to the saved audio file + """ + os.makedirs(output_dir, exist_ok=True) + output_file = os.path.join(output_dir, f"{identifier}.wav") + + with open(output_file, "wb") as f: + f.write(audio_data) + + return output_file + + +def write_benchmark_stats(stats: List[Dict[str, Any]], output_file: str) -> None: + """Write benchmark statistics to a file in a clean, organized format. + + Args: + stats: List of dictionaries containing stat name/value pairs + output_file: Path to output file + """ + os.makedirs(os.path.dirname(output_file), exist_ok=True) + + with open(output_file, "w") as f: + for section in stats: + # Write section header + f.write(f"=== {section['title']} ===\n\n") + + # Write stats + for label, value in section['stats'].items(): + if isinstance(value, float): + f.write(f"{label}: {value:.2f}\n") + else: + f.write(f"{label}: {value}\n") + f.write("\n") + + +def save_json_results(results: Dict[str, Any], output_file: str) -> None: + """Save benchmark results to a JSON file with proper formatting. + + Args: + results: Dictionary of results to save + output_file: Path to output file + """ + os.makedirs(os.path.dirname(output_file), exist_ok=True) + with open(output_file, "w") as f: + json.dump(results, f, indent=2) + + +def real_time_factor(processing_time: float, audio_length: float, decimals: int = 2) -> float: + """Calculate Real-Time Factor (RTF) as processing-time / length-of-audio. + + Args: + processing_time: Time taken to process/generate audio + audio_length: Length of the generated audio + decimals: Number of decimal places to round to + + Returns: + float: RTF value + """ + rtf = processing_time / audio_length + return round(rtf, decimals) diff --git a/examples/assorted_checks/benchmarks/output_data/benchmark_results.json b/examples/assorted_checks/benchmarks/output_data/benchmark_results.json new file mode 100644 index 0000000..5c60933 --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/benchmark_results.json @@ -0,0 +1,111 @@ +{ + "results": [ + { + "tokens": 100, + "processing_time": 18.833295583724976, + "output_length": 31.15, + "realtime_factor": 1.6539856161403135, + "elapsed_time": 19.024322748184204 + }, + { + "tokens": 200, + "processing_time": 38.95506024360657, + "output_length": 62.6, + "realtime_factor": 1.6069799304257042, + "elapsed_time": 58.21527123451233 + }, + { + "tokens": 300, + "processing_time": 49.74252939224243, + "output_length": 96.325, + "realtime_factor": 1.9364716908630366, + "elapsed_time": 108.19673728942871 + }, + { + "tokens": 400, + "processing_time": 61.349056243896484, + "output_length": 128.575, + "realtime_factor": 2.095794261102292, + "elapsed_time": 169.733656167984 + }, + { + "tokens": 500, + "processing_time": 82.86568236351013, + "output_length": 158.575, + "realtime_factor": 1.9136389815071193, + "elapsed_time": 252.7968451976776 + } + ], + "system_metrics": [ + { + "timestamp": "2025-01-03T00:13:49.865330", + "cpu_percent": 8.0, + "ram_percent": 39.4, + "ram_used_gb": 25.03811264038086, + "gpu_memory_used": 1204.0 + }, + { + "timestamp": "2025-01-03T00:14:08.781551", + "cpu_percent": 26.8, + "ram_percent": 42.6, + "ram_used_gb": 27.090862274169922, + "gpu_memory_used": 1225.0 + }, + { + "timestamp": "2025-01-03T00:14:08.916973", + "cpu_percent": 16.1, + "ram_percent": 42.6, + "ram_used_gb": 27.089553833007812, + "gpu_memory_used": 1225.0 + }, + { + "timestamp": "2025-01-03T00:14:47.979053", + "cpu_percent": 31.5, + "ram_percent": 43.6, + "ram_used_gb": 27.714427947998047, + "gpu_memory_used": 1225.0 + }, + { + "timestamp": "2025-01-03T00:14:48.098976", + "cpu_percent": 20.0, + "ram_percent": 43.6, + "ram_used_gb": 27.704315185546875, + "gpu_memory_used": 1211.0 + }, + { + "timestamp": "2025-01-03T00:15:37.944729", + "cpu_percent": 29.7, + "ram_percent": 38.6, + "ram_used_gb": 24.53925323486328, + "gpu_memory_used": 1217.0 + }, + { + "timestamp": "2025-01-03T00:15:38.071915", + "cpu_percent": 8.6, + "ram_percent": 38.5, + "ram_used_gb": 24.51690673828125, + "gpu_memory_used": 1208.0 + }, + { + "timestamp": "2025-01-03T00:16:39.525449", + "cpu_percent": 23.4, + "ram_percent": 38.8, + "ram_used_gb": 24.71230697631836, + "gpu_memory_used": 1221.0 + }, + { + "timestamp": "2025-01-03T00:16:39.612442", + "cpu_percent": 5.5, + "ram_percent": 38.9, + "ram_used_gb": 24.72066879272461, + "gpu_memory_used": 1221.0 + }, + { + "timestamp": "2025-01-03T00:18:02.569076", + "cpu_percent": 27.4, + "ram_percent": 39.1, + "ram_used_gb": 24.868202209472656, + "gpu_memory_used": 1264.0 + } + ] +} \ No newline at end of file diff --git a/examples/benchmarks/benchmark_results_cpu.json b/examples/assorted_checks/benchmarks/output_data/benchmark_results_cpu.json similarity index 100% rename from examples/benchmarks/benchmark_results_cpu.json rename to examples/assorted_checks/benchmarks/output_data/benchmark_results_cpu.json diff --git a/examples/assorted_checks/benchmarks/output_data/benchmark_results_rtf.json b/examples/assorted_checks/benchmarks/output_data/benchmark_results_rtf.json new file mode 100644 index 0000000..59ad009 --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/benchmark_results_rtf.json @@ -0,0 +1,300 @@ +{ + "results": [ + { + "tokens": 100, + "processing_time": 0.96, + "output_length": 31.1, + "rtf": 0.03, + "elapsed_time": 1.11 + }, + { + "tokens": 250, + "processing_time": 2.23, + "output_length": 77.17, + "rtf": 0.03, + "elapsed_time": 3.49 + }, + { + "tokens": 400, + "processing_time": 4.05, + "output_length": 128.05, + "rtf": 0.03, + "elapsed_time": 7.77 + }, + { + "tokens": 550, + "processing_time": 4.06, + "output_length": 171.45, + "rtf": 0.02, + "elapsed_time": 12.0 + }, + { + "tokens": 700, + "processing_time": 6.01, + "output_length": 221.6, + "rtf": 0.03, + "elapsed_time": 18.16 + }, + { + "tokens": 850, + "processing_time": 6.9, + "output_length": 269.1, + "rtf": 0.03, + "elapsed_time": 25.21 + }, + { + "tokens": 1000, + "processing_time": 7.65, + "output_length": 315.05, + "rtf": 0.02, + "elapsed_time": 33.03 + }, + { + "tokens": 6000, + "processing_time": 48.7, + "output_length": 1837.1, + "rtf": 0.03, + "elapsed_time": 82.21 + }, + { + "tokens": 11000, + "processing_time": 92.44, + "output_length": 3388.57, + "rtf": 0.03, + "elapsed_time": 175.46 + }, + { + "tokens": 16000, + "processing_time": 163.61, + "output_length": 4977.32, + "rtf": 0.03, + "elapsed_time": 340.46 + }, + { + "tokens": 21000, + "processing_time": 209.72, + "output_length": 6533.3, + "rtf": 0.03, + "elapsed_time": 551.92 + }, + { + "tokens": 26000, + "processing_time": 329.35, + "output_length": 8068.15, + "rtf": 0.04, + "elapsed_time": 883.37 + }, + { + "tokens": 31000, + "processing_time": 473.52, + "output_length": 9611.48, + "rtf": 0.05, + "elapsed_time": 1359.28 + }, + { + "tokens": 36000, + "processing_time": 650.98, + "output_length": 11157.15, + "rtf": 0.06, + "elapsed_time": 2012.9 + } + ], + "system_metrics": [ + { + "timestamp": "2025-01-03T14:41:01.331735", + "cpu_percent": 7.5, + "ram_percent": 50.2, + "ram_used_gb": 31.960269927978516, + "gpu_memory_used": 3191.0 + }, + { + "timestamp": "2025-01-03T14:41:02.357116", + "cpu_percent": 17.01, + "ram_percent": 50.2, + "ram_used_gb": 31.96163558959961, + "gpu_memory_used": 3426.0 + }, + { + "timestamp": "2025-01-03T14:41:02.445009", + "cpu_percent": 9.5, + "ram_percent": 50.3, + "ram_used_gb": 31.966781616210938, + "gpu_memory_used": 3426.0 + }, + { + "timestamp": "2025-01-03T14:41:04.742152", + "cpu_percent": 18.27, + "ram_percent": 50.4, + "ram_used_gb": 32.08788299560547, + "gpu_memory_used": 3642.0 + }, + { + "timestamp": "2025-01-03T14:41:04.847795", + "cpu_percent": 16.27, + "ram_percent": 50.5, + "ram_used_gb": 32.094364166259766, + "gpu_memory_used": 3640.0 + }, + { + "timestamp": "2025-01-03T14:41:09.019590", + "cpu_percent": 15.97, + "ram_percent": 50.7, + "ram_used_gb": 32.23244094848633, + "gpu_memory_used": 3640.0 + }, + { + "timestamp": "2025-01-03T14:41:09.110324", + "cpu_percent": 3.54, + "ram_percent": 50.7, + "ram_used_gb": 32.234458923339844, + "gpu_memory_used": 3640.0 + }, + { + "timestamp": "2025-01-03T14:41:13.252607", + "cpu_percent": 13.4, + "ram_percent": 50.6, + "ram_used_gb": 32.194271087646484, + "gpu_memory_used": 3935.0 + }, + { + "timestamp": "2025-01-03T14:41:13.327557", + "cpu_percent": 4.69, + "ram_percent": 50.6, + "ram_used_gb": 32.191776275634766, + "gpu_memory_used": 3935.0 + }, + { + "timestamp": "2025-01-03T14:41:19.413633", + "cpu_percent": 12.92, + "ram_percent": 50.9, + "ram_used_gb": 32.3467903137207, + "gpu_memory_used": 4250.0 + }, + { + "timestamp": "2025-01-03T14:41:19.492758", + "cpu_percent": 7.5, + "ram_percent": 50.8, + "ram_used_gb": 32.34375, + "gpu_memory_used": 4250.0 + }, + { + "timestamp": "2025-01-03T14:41:26.467284", + "cpu_percent": 13.09, + "ram_percent": 51.2, + "ram_used_gb": 32.56281280517578, + "gpu_memory_used": 4249.0 + }, + { + "timestamp": "2025-01-03T14:41:26.553559", + "cpu_percent": 8.39, + "ram_percent": 51.2, + "ram_used_gb": 32.56183624267578, + "gpu_memory_used": 4249.0 + }, + { + "timestamp": "2025-01-03T14:41:34.284362", + "cpu_percent": 12.61, + "ram_percent": 51.7, + "ram_used_gb": 32.874778747558594, + "gpu_memory_used": 4250.0 + }, + { + "timestamp": "2025-01-03T14:41:34.362353", + "cpu_percent": 1.25, + "ram_percent": 51.7, + "ram_used_gb": 32.87461471557617, + "gpu_memory_used": 4250.0 + }, + { + "timestamp": "2025-01-03T14:42:23.471312", + "cpu_percent": 11.64, + "ram_percent": 54.9, + "ram_used_gb": 34.90264129638672, + "gpu_memory_used": 4647.0 + }, + { + "timestamp": "2025-01-03T14:42:23.547203", + "cpu_percent": 5.31, + "ram_percent": 54.9, + "ram_used_gb": 34.91563415527344, + "gpu_memory_used": 4647.0 + }, + { + "timestamp": "2025-01-03T14:43:56.724933", + "cpu_percent": 12.97, + "ram_percent": 59.5, + "ram_used_gb": 37.84241485595703, + "gpu_memory_used": 4655.0 + }, + { + "timestamp": "2025-01-03T14:43:56.815453", + "cpu_percent": 11.75, + "ram_percent": 59.5, + "ram_used_gb": 37.832679748535156, + "gpu_memory_used": 4655.0 + }, + { + "timestamp": "2025-01-03T14:46:41.705155", + "cpu_percent": 12.94, + "ram_percent": 66.3, + "ram_used_gb": 42.1534538269043, + "gpu_memory_used": 4729.0 + }, + { + "timestamp": "2025-01-03T14:46:41.835177", + "cpu_percent": 7.73, + "ram_percent": 66.2, + "ram_used_gb": 42.13554000854492, + "gpu_memory_used": 4729.0 + }, + { + "timestamp": "2025-01-03T14:50:13.166236", + "cpu_percent": 11.62, + "ram_percent": 73.4, + "ram_used_gb": 46.71288299560547, + "gpu_memory_used": 4676.0 + }, + { + "timestamp": "2025-01-03T14:50:13.261611", + "cpu_percent": 8.16, + "ram_percent": 73.4, + "ram_used_gb": 46.71356201171875, + "gpu_memory_used": 4676.0 + }, + { + "timestamp": "2025-01-03T14:55:44.623607", + "cpu_percent": 12.92, + "ram_percent": 82.8, + "ram_used_gb": 52.65533447265625, + "gpu_memory_used": 4636.0 + }, + { + "timestamp": "2025-01-03T14:55:44.735410", + "cpu_percent": 15.29, + "ram_percent": 82.7, + "ram_used_gb": 52.63290786743164, + "gpu_memory_used": 4636.0 + }, + { + "timestamp": "2025-01-03T15:03:40.534449", + "cpu_percent": 13.88, + "ram_percent": 85.0, + "ram_used_gb": 54.050071716308594, + "gpu_memory_used": 4771.0 + }, + { + "timestamp": "2025-01-03T15:03:40.638708", + "cpu_percent": 12.21, + "ram_percent": 85.0, + "ram_used_gb": 54.053733825683594, + "gpu_memory_used": 4771.0 + }, + { + "timestamp": "2025-01-03T15:14:34.159142", + "cpu_percent": 14.51, + "ram_percent": 78.1, + "ram_used_gb": 49.70396423339844, + "gpu_memory_used": 4739.0 + } + ] +} \ No newline at end of file diff --git a/examples/benchmarks/benchmark_stats_cpu.txt b/examples/assorted_checks/benchmarks/output_data/benchmark_stats_cpu.txt similarity index 100% rename from examples/benchmarks/benchmark_stats_cpu.txt rename to examples/assorted_checks/benchmarks/output_data/benchmark_stats_cpu.txt diff --git a/examples/assorted_checks/benchmarks/output_data/benchmark_stats_rtf.txt b/examples/assorted_checks/benchmarks/output_data/benchmark_stats_rtf.txt new file mode 100644 index 0000000..e7bed5f --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/benchmark_stats_rtf.txt @@ -0,0 +1,9 @@ +=== Benchmark Statistics (with correct RTF) === + +Overall Stats: +Total tokens processed: 150850 +Total audio generated: 46786.59s +Total test duration: 2012.90s +Average processing rate: 104.34 tokens/second +Average RTF: 0.03x + diff --git a/examples/assorted_checks/benchmarks/output_data/cpu_benchmark_results_rtf.json b/examples/assorted_checks/benchmarks/output_data/cpu_benchmark_results_rtf.json new file mode 100644 index 0000000..acc11fd --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/cpu_benchmark_results_rtf.json @@ -0,0 +1,2506 @@ +{ + "results": [ + { + "tokens": 150, + "processing_time": 22.93, + "output_length": 45.9, + "rtf": 0.5, + "elapsed_time": 22.97 + }, + { + "tokens": 300, + "processing_time": 43.78, + "output_length": 96.425, + "rtf": 0.45, + "elapsed_time": 66.81 + }, + { + "tokens": 450, + "processing_time": 64.75, + "output_length": 143.1, + "rtf": 0.45, + "elapsed_time": 131.61 + }, + { + "tokens": 600, + "processing_time": 85.73, + "output_length": 188.675, + "rtf": 0.45, + "elapsed_time": 217.4 + }, + { + "tokens": 750, + "processing_time": 115.35, + "output_length": 236.7, + "rtf": 0.49, + "elapsed_time": 332.81 + } + ], + "system_metrics": [ + { + "timestamp": "2025-01-03T17:34:42.747316", + "cpu_percent": 4.4, + "ram_percent": 45.1, + "ram_used_gb": 28.709259033203125, + "gpu_memory_used": 1112.0, + "relative_time": 0.07491874694824219 + }, + { + "timestamp": "2025-01-03T17:34:43.835281", + "cpu_percent": 23.77, + "ram_percent": 45.1, + "ram_used_gb": 28.697410583496094, + "gpu_memory_used": 1103.0, + "relative_time": 1.162503719329834 + }, + { + "timestamp": "2025-01-03T17:34:44.912674", + "cpu_percent": 21.57, + "ram_percent": 45.1, + "ram_used_gb": 28.662906646728516, + "gpu_memory_used": 1103.0, + "relative_time": 2.2446579933166504 + }, + { + "timestamp": "2025-01-03T17:34:46.004788", + "cpu_percent": 23.83, + "ram_percent": 45.0, + "ram_used_gb": 28.651744842529297, + "gpu_memory_used": 1103.0, + "relative_time": 3.3548994064331055 + }, + { + "timestamp": "2025-01-03T17:34:47.111761", + "cpu_percent": 22.67, + "ram_percent": 45.0, + "ram_used_gb": 28.65630340576172, + "gpu_memory_used": 1102.0, + "relative_time": 4.438696622848511 + }, + { + "timestamp": "2025-01-03T17:34:48.189184", + "cpu_percent": 24.12, + "ram_percent": 45.1, + "ram_used_gb": 28.664894104003906, + "gpu_memory_used": 1102.0, + "relative_time": 5.523675918579102 + }, + { + "timestamp": "2025-01-03T17:34:49.280551", + "cpu_percent": 25.39, + "ram_percent": 45.1, + "ram_used_gb": 28.6732177734375, + "gpu_memory_used": 1102.0, + "relative_time": 6.591145038604736 + }, + { + "timestamp": "2025-01-03T17:34:50.355243", + "cpu_percent": 21.66, + "ram_percent": 45.0, + "ram_used_gb": 28.655715942382812, + "gpu_memory_used": 1102.0, + "relative_time": 7.682063102722168 + }, + { + "timestamp": "2025-01-03T17:34:51.431347", + "cpu_percent": 22.3, + "ram_percent": 45.0, + "ram_used_gb": 28.649066925048828, + "gpu_memory_used": 1095.0, + "relative_time": 8.77349853515625 + }, + { + "timestamp": "2025-01-03T17:34:52.525602", + "cpu_percent": 23.26, + "ram_percent": 45.1, + "ram_used_gb": 28.668758392333984, + "gpu_memory_used": 1101.0, + "relative_time": 9.867908477783203 + }, + { + "timestamp": "2025-01-03T17:34:53.627319", + "cpu_percent": 23.99, + "ram_percent": 45.1, + "ram_used_gb": 28.695106506347656, + "gpu_memory_used": 1101.0, + "relative_time": 10.980819463729858 + }, + { + "timestamp": "2025-01-03T17:34:54.734806", + "cpu_percent": 27.3, + "ram_percent": 45.1, + "ram_used_gb": 28.669708251953125, + "gpu_memory_used": 1102.0, + "relative_time": 12.046100854873657 + }, + { + "timestamp": "2025-01-03T17:34:55.795028", + "cpu_percent": 28.48, + "ram_percent": 45.1, + "ram_used_gb": 28.677181243896484, + "gpu_memory_used": 1102.0, + "relative_time": 13.139363288879395 + }, + { + "timestamp": "2025-01-03T17:34:56.888979", + "cpu_percent": 30.75, + "ram_percent": 45.2, + "ram_used_gb": 28.762008666992188, + "gpu_memory_used": 1102.0, + "relative_time": 14.25643014907837 + }, + { + "timestamp": "2025-01-03T17:34:58.006454", + "cpu_percent": 51.33, + "ram_percent": 45.1, + "ram_used_gb": 28.7191162109375, + "gpu_memory_used": 1102.0, + "relative_time": 15.350555658340454 + }, + { + "timestamp": "2025-01-03T17:34:59.113602", + "cpu_percent": 30.18, + "ram_percent": 45.2, + "ram_used_gb": 28.765079498291016, + "gpu_memory_used": 1101.0, + "relative_time": 16.45602011680603 + }, + { + "timestamp": "2025-01-03T17:35:00.216463", + "cpu_percent": 38.41, + "ram_percent": 45.2, + "ram_used_gb": 28.744461059570312, + "gpu_memory_used": 1101.0, + "relative_time": 17.581329822540283 + }, + { + "timestamp": "2025-01-03T17:35:01.335124", + "cpu_percent": 27.42, + "ram_percent": 45.2, + "ram_used_gb": 28.75594711303711, + "gpu_memory_used": 1101.0, + "relative_time": 18.70340371131897 + }, + { + "timestamp": "2025-01-03T17:35:02.457622", + "cpu_percent": 25.99, + "ram_percent": 45.3, + "ram_used_gb": 28.785816192626953, + "gpu_memory_used": 1100.0, + "relative_time": 19.809316635131836 + }, + { + "timestamp": "2025-01-03T17:35:03.569035", + "cpu_percent": 27.52, + "ram_percent": 45.3, + "ram_used_gb": 28.79547882080078, + "gpu_memory_used": 1103.0, + "relative_time": 20.89554214477539 + }, + { + "timestamp": "2025-01-03T17:35:04.645402", + "cpu_percent": 29.33, + "ram_percent": 45.3, + "ram_used_gb": 28.804088592529297, + "gpu_memory_used": 1101.0, + "relative_time": 21.98127508163452 + }, + { + "timestamp": "2025-01-03T17:35:05.735134", + "cpu_percent": 27.68, + "ram_percent": 45.3, + "ram_used_gb": 28.83855438232422, + "gpu_memory_used": 1102.0, + "relative_time": 23.050849676132202 + }, + { + "timestamp": "2025-01-03T17:35:06.814217", + "cpu_percent": 27.9, + "ram_percent": 45.3, + "ram_used_gb": 28.84520721435547, + "gpu_memory_used": 1102.0, + "relative_time": 24.1594979763031 + }, + { + "timestamp": "2025-01-03T17:35:07.921210", + "cpu_percent": 29.27, + "ram_percent": 45.3, + "ram_used_gb": 28.81098175048828, + "gpu_memory_used": 1102.0, + "relative_time": 25.24632716178894 + }, + { + "timestamp": "2025-01-03T17:35:08.999119", + "cpu_percent": 32.0, + "ram_percent": 45.3, + "ram_used_gb": 28.832805633544922, + "gpu_memory_used": 1102.0, + "relative_time": 26.33597707748413 + }, + { + "timestamp": "2025-01-03T17:35:10.088620", + "cpu_percent": 24.94, + "ram_percent": 45.3, + "ram_used_gb": 28.82524871826172, + "gpu_memory_used": 1102.0, + "relative_time": 27.41934084892273 + }, + { + "timestamp": "2025-01-03T17:35:11.171667", + "cpu_percent": 25.69, + "ram_percent": 45.3, + "ram_used_gb": 28.84173583984375, + "gpu_memory_used": 1102.0, + "relative_time": 28.496659517288208 + }, + { + "timestamp": "2025-01-03T17:35:12.257168", + "cpu_percent": 25.55, + "ram_percent": 45.4, + "ram_used_gb": 28.876148223876953, + "gpu_memory_used": 1100.0, + "relative_time": 29.6050226688385 + }, + { + "timestamp": "2025-01-03T17:35:13.368026", + "cpu_percent": 26.89, + "ram_percent": 45.4, + "ram_used_gb": 28.87099838256836, + "gpu_memory_used": 1099.0, + "relative_time": 30.69699764251709 + }, + { + "timestamp": "2025-01-03T17:35:14.446163", + "cpu_percent": 27.84, + "ram_percent": 45.4, + "ram_used_gb": 28.85318374633789, + "gpu_memory_used": 1099.0, + "relative_time": 31.779499769210815 + }, + { + "timestamp": "2025-01-03T17:35:15.537804", + "cpu_percent": 27.68, + "ram_percent": 45.4, + "ram_used_gb": 28.861358642578125, + "gpu_memory_used": 1099.0, + "relative_time": 32.866647481918335 + }, + { + "timestamp": "2025-01-03T17:35:16.626833", + "cpu_percent": 27.11, + "ram_percent": 45.1, + "ram_used_gb": 28.67508316040039, + "gpu_memory_used": 1101.0, + "relative_time": 33.97589898109436 + }, + { + "timestamp": "2025-01-03T17:35:17.735393", + "cpu_percent": 24.79, + "ram_percent": 45.1, + "ram_used_gb": 28.690773010253906, + "gpu_memory_used": 1101.0, + "relative_time": 35.04746890068054 + }, + { + "timestamp": "2025-01-03T17:35:18.808174", + "cpu_percent": 23.52, + "ram_percent": 45.1, + "ram_used_gb": 28.687705993652344, + "gpu_memory_used": 1101.0, + "relative_time": 36.138739585876465 + }, + { + "timestamp": "2025-01-03T17:35:19.896932", + "cpu_percent": 23.96, + "ram_percent": 45.1, + "ram_used_gb": 28.670169830322266, + "gpu_memory_used": 1101.0, + "relative_time": 37.22053575515747 + }, + { + "timestamp": "2025-01-03T17:35:20.975119", + "cpu_percent": 23.28, + "ram_percent": 45.1, + "ram_used_gb": 28.66689682006836, + "gpu_memory_used": 1101.0, + "relative_time": 38.29904627799988 + }, + { + "timestamp": "2025-01-03T17:35:22.050416", + "cpu_percent": 23.42, + "ram_percent": 45.1, + "ram_used_gb": 28.69702911376953, + "gpu_memory_used": 1100.0, + "relative_time": 39.390669107437134 + }, + { + "timestamp": "2025-01-03T17:35:23.143314", + "cpu_percent": 24.28, + "ram_percent": 45.1, + "ram_used_gb": 28.696701049804688, + "gpu_memory_used": 1099.0, + "relative_time": 40.485177755355835 + }, + { + "timestamp": "2025-01-03T17:35:24.247604", + "cpu_percent": 25.17, + "ram_percent": 45.1, + "ram_used_gb": 28.70577621459961, + "gpu_memory_used": 1097.0, + "relative_time": 41.58591032028198 + }, + { + "timestamp": "2025-01-03T17:35:25.339573", + "cpu_percent": 21.29, + "ram_percent": 45.1, + "ram_used_gb": 28.683162689208984, + "gpu_memory_used": 1097.0, + "relative_time": 42.64796328544617 + }, + { + "timestamp": "2025-01-03T17:35:26.398778", + "cpu_percent": 21.64, + "ram_percent": 45.1, + "ram_used_gb": 28.675365447998047, + "gpu_memory_used": 1097.0, + "relative_time": 43.72638392448425 + }, + { + "timestamp": "2025-01-03T17:35:27.487170", + "cpu_percent": 22.69, + "ram_percent": 45.1, + "ram_used_gb": 28.687335968017578, + "gpu_memory_used": 1097.0, + "relative_time": 44.81854510307312 + }, + { + "timestamp": "2025-01-03T17:35:28.579809", + "cpu_percent": 23.78, + "ram_percent": 45.1, + "ram_used_gb": 28.686798095703125, + "gpu_memory_used": 1097.0, + "relative_time": 45.909095287323 + }, + { + "timestamp": "2025-01-03T17:35:29.670899", + "cpu_percent": 26.39, + "ram_percent": 45.1, + "ram_used_gb": 28.667762756347656, + "gpu_memory_used": 1097.0, + "relative_time": 46.996145486831665 + }, + { + "timestamp": "2025-01-03T17:35:30.746220", + "cpu_percent": 23.85, + "ram_percent": 45.1, + "ram_used_gb": 28.674030303955078, + "gpu_memory_used": 1097.0, + "relative_time": 48.05596685409546 + }, + { + "timestamp": "2025-01-03T17:35:31.807982", + "cpu_percent": 23.41, + "ram_percent": 45.1, + "ram_used_gb": 28.699344635009766, + "gpu_memory_used": 1097.0, + "relative_time": 49.14048671722412 + }, + { + "timestamp": "2025-01-03T17:35:32.899231", + "cpu_percent": 23.91, + "ram_percent": 45.1, + "ram_used_gb": 28.694026947021484, + "gpu_memory_used": 1097.0, + "relative_time": 50.233946323394775 + }, + { + "timestamp": "2025-01-03T17:35:33.990980", + "cpu_percent": 21.22, + "ram_percent": 45.1, + "ram_used_gb": 28.69512939453125, + "gpu_memory_used": 1097.0, + "relative_time": 51.3146493434906 + }, + { + "timestamp": "2025-01-03T17:35:35.065062", + "cpu_percent": 23.06, + "ram_percent": 45.1, + "ram_used_gb": 28.673419952392578, + "gpu_memory_used": 1097.0, + "relative_time": 52.40274214744568 + }, + { + "timestamp": "2025-01-03T17:35:36.155228", + "cpu_percent": 25.23, + "ram_percent": 45.1, + "ram_used_gb": 28.68213653564453, + "gpu_memory_used": 1097.0, + "relative_time": 53.48211121559143 + }, + { + "timestamp": "2025-01-03T17:35:37.232942", + "cpu_percent": 27.12, + "ram_percent": 45.1, + "ram_used_gb": 28.705059051513672, + "gpu_memory_used": 1097.0, + "relative_time": 54.55754017829895 + }, + { + "timestamp": "2025-01-03T17:35:38.317354", + "cpu_percent": 25.1, + "ram_percent": 45.1, + "ram_used_gb": 28.702983856201172, + "gpu_memory_used": 1097.0, + "relative_time": 55.65464448928833 + }, + { + "timestamp": "2025-01-03T17:35:39.405580", + "cpu_percent": 24.43, + "ram_percent": 45.1, + "ram_used_gb": 28.68689727783203, + "gpu_memory_used": 1097.0, + "relative_time": 56.73482656478882 + }, + { + "timestamp": "2025-01-03T17:35:40.495226", + "cpu_percent": 23.47, + "ram_percent": 45.1, + "ram_used_gb": 28.68814468383789, + "gpu_memory_used": 1097.0, + "relative_time": 57.82576274871826 + }, + { + "timestamp": "2025-01-03T17:35:41.586272", + "cpu_percent": 22.74, + "ram_percent": 45.1, + "ram_used_gb": 28.68700408935547, + "gpu_memory_used": 1097.0, + "relative_time": 58.90043330192566 + }, + { + "timestamp": "2025-01-03T17:35:42.662161", + "cpu_percent": 22.7, + "ram_percent": 45.1, + "ram_used_gb": 28.702560424804688, + "gpu_memory_used": 1097.0, + "relative_time": 59.995574951171875 + }, + { + "timestamp": "2025-01-03T17:35:43.754475", + "cpu_percent": 22.92, + "ram_percent": 45.1, + "ram_used_gb": 28.70386505126953, + "gpu_memory_used": 1097.0, + "relative_time": 61.082642793655396 + }, + { + "timestamp": "2025-01-03T17:35:44.844454", + "cpu_percent": 24.27, + "ram_percent": 45.1, + "ram_used_gb": 28.68398666381836, + "gpu_memory_used": 1097.0, + "relative_time": 62.17042922973633 + }, + { + "timestamp": "2025-01-03T17:35:45.922535", + "cpu_percent": 25.56, + "ram_percent": 45.1, + "ram_used_gb": 28.679576873779297, + "gpu_memory_used": 1097.0, + "relative_time": 63.231327533721924 + }, + { + "timestamp": "2025-01-03T17:35:46.980393", + "cpu_percent": 24.43, + "ram_percent": 45.1, + "ram_used_gb": 28.69806671142578, + "gpu_memory_used": 1097.0, + "relative_time": 64.29255247116089 + }, + { + "timestamp": "2025-01-03T17:35:48.044665", + "cpu_percent": 23.42, + "ram_percent": 45.1, + "ram_used_gb": 28.698440551757812, + "gpu_memory_used": 1097.0, + "relative_time": 65.356365442276 + }, + { + "timestamp": "2025-01-03T17:35:49.105491", + "cpu_percent": 23.74, + "ram_percent": 45.1, + "ram_used_gb": 28.699386596679688, + "gpu_memory_used": 1097.0, + "relative_time": 66.43754887580872 + }, + { + "timestamp": "2025-01-03T17:35:50.186327", + "cpu_percent": 21.49, + "ram_percent": 45.2, + "ram_used_gb": 28.72582244873047, + "gpu_memory_used": 1101.0, + "relative_time": 67.51031470298767 + }, + { + "timestamp": "2025-01-03T17:35:51.271798", + "cpu_percent": 23.12, + "ram_percent": 45.1, + "ram_used_gb": 28.719581604003906, + "gpu_memory_used": 1101.0, + "relative_time": 68.5964903831482 + }, + { + "timestamp": "2025-01-03T17:35:52.359436", + "cpu_percent": 22.75, + "ram_percent": 45.2, + "ram_used_gb": 28.746524810791016, + "gpu_memory_used": 1101.0, + "relative_time": 69.68625974655151 + }, + { + "timestamp": "2025-01-03T17:35:53.439928", + "cpu_percent": 26.48, + "ram_percent": 45.2, + "ram_used_gb": 28.744590759277344, + "gpu_memory_used": 1101.0, + "relative_time": 70.76669788360596 + }, + { + "timestamp": "2025-01-03T17:35:54.529847", + "cpu_percent": 23.72, + "ram_percent": 45.1, + "ram_used_gb": 28.71523666381836, + "gpu_memory_used": 1101.0, + "relative_time": 71.86323857307434 + }, + { + "timestamp": "2025-01-03T17:35:55.620268", + "cpu_percent": 24.44, + "ram_percent": 45.1, + "ram_used_gb": 28.712608337402344, + "gpu_memory_used": 1101.0, + "relative_time": 72.96533226966858 + }, + { + "timestamp": "2025-01-03T17:35:56.726510", + "cpu_percent": 22.93, + "ram_percent": 45.1, + "ram_used_gb": 28.709251403808594, + "gpu_memory_used": 1098.0, + "relative_time": 74.05393600463867 + }, + { + "timestamp": "2025-01-03T17:35:57.816277", + "cpu_percent": 24.19, + "ram_percent": 45.2, + "ram_used_gb": 28.72509002685547, + "gpu_memory_used": 1098.0, + "relative_time": 75.1400306224823 + }, + { + "timestamp": "2025-01-03T17:35:58.889283", + "cpu_percent": 23.95, + "ram_percent": 45.2, + "ram_used_gb": 28.72734832763672, + "gpu_memory_used": 1098.0, + "relative_time": 76.21520328521729 + }, + { + "timestamp": "2025-01-03T17:35:59.964425", + "cpu_percent": 23.01, + "ram_percent": 45.2, + "ram_used_gb": 28.72198486328125, + "gpu_memory_used": 1098.0, + "relative_time": 77.29325318336487 + }, + { + "timestamp": "2025-01-03T17:36:01.053027", + "cpu_percent": 24.34, + "ram_percent": 45.2, + "ram_used_gb": 28.740951538085938, + "gpu_memory_used": 1098.0, + "relative_time": 78.37847518920898 + }, + { + "timestamp": "2025-01-03T17:36:02.129127", + "cpu_percent": 21.81, + "ram_percent": 45.2, + "ram_used_gb": 28.770435333251953, + "gpu_memory_used": 1098.0, + "relative_time": 79.45529294013977 + }, + { + "timestamp": "2025-01-03T17:36:03.205976", + "cpu_percent": 25.2, + "ram_percent": 45.4, + "ram_used_gb": 28.847518920898438, + "gpu_memory_used": 1098.0, + "relative_time": 80.5142834186554 + }, + { + "timestamp": "2025-01-03T17:36:04.268476", + "cpu_percent": 25.09, + "ram_percent": 45.4, + "ram_used_gb": 28.853740692138672, + "gpu_memory_used": 1098.0, + "relative_time": 81.59653949737549 + }, + { + "timestamp": "2025-01-03T17:36:05.346965", + "cpu_percent": 25.51, + "ram_percent": 45.3, + "ram_used_gb": 28.825660705566406, + "gpu_memory_used": 1098.0, + "relative_time": 82.67025065422058 + }, + { + "timestamp": "2025-01-03T17:36:06.420210", + "cpu_percent": 23.64, + "ram_percent": 45.3, + "ram_used_gb": 28.82675552368164, + "gpu_memory_used": 1098.0, + "relative_time": 83.76902842521667 + }, + { + "timestamp": "2025-01-03T17:36:07.528643", + "cpu_percent": 24.17, + "ram_percent": 45.3, + "ram_used_gb": 28.835819244384766, + "gpu_memory_used": 1098.0, + "relative_time": 84.84460020065308 + }, + { + "timestamp": "2025-01-03T17:36:08.603019", + "cpu_percent": 21.95, + "ram_percent": 45.3, + "ram_used_gb": 28.832855224609375, + "gpu_memory_used": 1098.0, + "relative_time": 85.92997336387634 + }, + { + "timestamp": "2025-01-03T17:36:09.692869", + "cpu_percent": 21.41, + "ram_percent": 45.3, + "ram_used_gb": 28.812267303466797, + "gpu_memory_used": 1098.0, + "relative_time": 87.03102254867554 + }, + { + "timestamp": "2025-01-03T17:36:10.782205", + "cpu_percent": 25.44, + "ram_percent": 45.3, + "ram_used_gb": 28.818920135498047, + "gpu_memory_used": 1094.0, + "relative_time": 88.12934947013855 + }, + { + "timestamp": "2025-01-03T17:36:11.887369", + "cpu_percent": 31.61, + "ram_percent": 45.4, + "ram_used_gb": 28.850399017333984, + "gpu_memory_used": 1094.0, + "relative_time": 89.22751259803772 + }, + { + "timestamp": "2025-01-03T17:36:12.980251", + "cpu_percent": 22.99, + "ram_percent": 45.3, + "ram_used_gb": 28.846778869628906, + "gpu_memory_used": 1094.0, + "relative_time": 90.30405187606812 + }, + { + "timestamp": "2025-01-03T17:36:14.055303", + "cpu_percent": 23.76, + "ram_percent": 45.3, + "ram_used_gb": 28.846450805664062, + "gpu_memory_used": 1094.0, + "relative_time": 91.38480973243713 + }, + { + "timestamp": "2025-01-03T17:36:15.147210", + "cpu_percent": 22.66, + "ram_percent": 45.3, + "ram_used_gb": 28.828269958496094, + "gpu_memory_used": 1090.0, + "relative_time": 92.47204494476318 + }, + { + "timestamp": "2025-01-03T17:36:16.223825", + "cpu_percent": 24.72, + "ram_percent": 45.3, + "ram_used_gb": 28.836009979248047, + "gpu_memory_used": 1090.0, + "relative_time": 93.55564045906067 + }, + { + "timestamp": "2025-01-03T17:36:17.312873", + "cpu_percent": 21.48, + "ram_percent": 45.3, + "ram_used_gb": 28.839397430419922, + "gpu_memory_used": 1090.0, + "relative_time": 94.63971495628357 + }, + { + "timestamp": "2025-01-03T17:36:18.389124", + "cpu_percent": 26.63, + "ram_percent": 45.3, + "ram_used_gb": 28.846328735351562, + "gpu_memory_used": 1090.0, + "relative_time": 95.71641564369202 + }, + { + "timestamp": "2025-01-03T17:36:19.468453", + "cpu_percent": 25.13, + "ram_percent": 45.3, + "ram_used_gb": 28.829818725585938, + "gpu_memory_used": 1099.0, + "relative_time": 96.7940239906311 + }, + { + "timestamp": "2025-01-03T17:36:20.545028", + "cpu_percent": 26.21, + "ram_percent": 45.3, + "ram_used_gb": 28.82284164428711, + "gpu_memory_used": 1099.0, + "relative_time": 97.87617611885071 + }, + { + "timestamp": "2025-01-03T17:36:21.625911", + "cpu_percent": 28.04, + "ram_percent": 45.3, + "ram_used_gb": 28.825241088867188, + "gpu_memory_used": 1101.0, + "relative_time": 98.9656343460083 + }, + { + "timestamp": "2025-01-03T17:36:22.726280", + "cpu_percent": 24.44, + "ram_percent": 45.4, + "ram_used_gb": 28.852622985839844, + "gpu_memory_used": 1101.0, + "relative_time": 100.05247807502747 + }, + { + "timestamp": "2025-01-03T17:36:23.800699", + "cpu_percent": 22.97, + "ram_percent": 45.4, + "ram_used_gb": 28.851558685302734, + "gpu_memory_used": 1101.0, + "relative_time": 101.14096426963806 + }, + { + "timestamp": "2025-01-03T17:36:24.901804", + "cpu_percent": 23.85, + "ram_percent": 45.3, + "ram_used_gb": 28.82904052734375, + "gpu_memory_used": 1101.0, + "relative_time": 102.23190665245056 + }, + { + "timestamp": "2025-01-03T17:36:25.994492", + "cpu_percent": 25.47, + "ram_percent": 45.3, + "ram_used_gb": 28.835567474365234, + "gpu_memory_used": 1100.0, + "relative_time": 103.30232405662537 + }, + { + "timestamp": "2025-01-03T17:36:27.054728", + "cpu_percent": 23.06, + "ram_percent": 45.4, + "ram_used_gb": 28.848636627197266, + "gpu_memory_used": 1100.0, + "relative_time": 104.36360669136047 + }, + { + "timestamp": "2025-01-03T17:36:28.117967", + "cpu_percent": 22.29, + "ram_percent": 45.3, + "ram_used_gb": 28.841327667236328, + "gpu_memory_used": 1100.0, + "relative_time": 105.43805932998657 + }, + { + "timestamp": "2025-01-03T17:36:29.195306", + "cpu_percent": 22.9, + "ram_percent": 45.4, + "ram_used_gb": 28.852493286132812, + "gpu_memory_used": 1100.0, + "relative_time": 106.5122537612915 + }, + { + "timestamp": "2025-01-03T17:36:30.272864", + "cpu_percent": 24.17, + "ram_percent": 45.3, + "ram_used_gb": 28.838626861572266, + "gpu_memory_used": 1100.0, + "relative_time": 107.59854078292847 + }, + { + "timestamp": "2025-01-03T17:36:31.348038", + "cpu_percent": 22.76, + "ram_percent": 45.3, + "ram_used_gb": 28.829647064208984, + "gpu_memory_used": 1100.0, + "relative_time": 108.67652320861816 + }, + { + "timestamp": "2025-01-03T17:36:32.438919", + "cpu_percent": 26.26, + "ram_percent": 45.4, + "ram_used_gb": 28.863739013671875, + "gpu_memory_used": 1100.0, + "relative_time": 109.74629759788513 + }, + { + "timestamp": "2025-01-03T17:36:33.502904", + "cpu_percent": 25.04, + "ram_percent": 45.4, + "ram_used_gb": 28.8487548828125, + "gpu_memory_used": 1100.0, + "relative_time": 110.81692504882812 + }, + { + "timestamp": "2025-01-03T17:36:34.580473", + "cpu_percent": 23.49, + "ram_percent": 45.3, + "ram_used_gb": 28.804698944091797, + "gpu_memory_used": 1100.0, + "relative_time": 111.91362714767456 + }, + { + "timestamp": "2025-01-03T17:36:35.672160", + "cpu_percent": 23.94, + "ram_percent": 45.3, + "ram_used_gb": 28.81186294555664, + "gpu_memory_used": 1100.0, + "relative_time": 113.00246286392212 + }, + { + "timestamp": "2025-01-03T17:36:36.765325", + "cpu_percent": 27.01, + "ram_percent": 45.3, + "ram_used_gb": 28.814517974853516, + "gpu_memory_used": 1100.0, + "relative_time": 114.10090208053589 + }, + { + "timestamp": "2025-01-03T17:36:37.857184", + "cpu_percent": 24.68, + "ram_percent": 45.3, + "ram_used_gb": 28.819175720214844, + "gpu_memory_used": 1100.0, + "relative_time": 115.20764112472534 + }, + { + "timestamp": "2025-01-03T17:36:38.964872", + "cpu_percent": 23.33, + "ram_percent": 45.3, + "ram_used_gb": 28.817371368408203, + "gpu_memory_used": 1100.0, + "relative_time": 116.29335045814514 + }, + { + "timestamp": "2025-01-03T17:36:40.055011", + "cpu_percent": 24.12, + "ram_percent": 45.3, + "ram_used_gb": 28.810909271240234, + "gpu_memory_used": 1100.0, + "relative_time": 117.36396074295044 + }, + { + "timestamp": "2025-01-03T17:36:41.117236", + "cpu_percent": 23.84, + "ram_percent": 45.3, + "ram_used_gb": 28.8153076171875, + "gpu_memory_used": 1100.0, + "relative_time": 118.4630720615387 + }, + { + "timestamp": "2025-01-03T17:36:42.216589", + "cpu_percent": 24.87, + "ram_percent": 45.4, + "ram_used_gb": 28.848403930664062, + "gpu_memory_used": 1100.0, + "relative_time": 119.52416563034058 + }, + { + "timestamp": "2025-01-03T17:36:43.281897", + "cpu_percent": 24.11, + "ram_percent": 45.4, + "ram_used_gb": 28.850421905517578, + "gpu_memory_used": 1100.0, + "relative_time": 120.61504173278809 + }, + { + "timestamp": "2025-01-03T17:36:44.374829", + "cpu_percent": 25.95, + "ram_percent": 45.3, + "ram_used_gb": 28.838001251220703, + "gpu_memory_used": 1100.0, + "relative_time": 121.72348999977112 + }, + { + "timestamp": "2025-01-03T17:36:45.479163", + "cpu_percent": 23.37, + "ram_percent": 45.3, + "ram_used_gb": 28.831417083740234, + "gpu_memory_used": 1100.0, + "relative_time": 122.79204487800598 + }, + { + "timestamp": "2025-01-03T17:36:46.542153", + "cpu_percent": 24.43, + "ram_percent": 45.3, + "ram_used_gb": 28.82573699951172, + "gpu_memory_used": 1100.0, + "relative_time": 123.8669421672821 + }, + { + "timestamp": "2025-01-03T17:36:47.630420", + "cpu_percent": 22.51, + "ram_percent": 45.3, + "ram_used_gb": 28.838607788085938, + "gpu_memory_used": 1100.0, + "relative_time": 124.96710133552551 + }, + { + "timestamp": "2025-01-03T17:36:48.720922", + "cpu_percent": 22.87, + "ram_percent": 45.3, + "ram_used_gb": 28.829120635986328, + "gpu_memory_used": 1100.0, + "relative_time": 126.04526543617249 + }, + { + "timestamp": "2025-01-03T17:36:49.795612", + "cpu_percent": 24.09, + "ram_percent": 45.3, + "ram_used_gb": 28.815223693847656, + "gpu_memory_used": 1100.0, + "relative_time": 127.1201822757721 + }, + { + "timestamp": "2025-01-03T17:36:50.869719", + "cpu_percent": 23.14, + "ram_percent": 45.3, + "ram_used_gb": 28.82253646850586, + "gpu_memory_used": 1099.0, + "relative_time": 128.17721223831177 + }, + { + "timestamp": "2025-01-03T17:36:51.936893", + "cpu_percent": 24.92, + "ram_percent": 45.3, + "ram_used_gb": 28.844318389892578, + "gpu_memory_used": 1098.0, + "relative_time": 129.2737376689911 + }, + { + "timestamp": "2025-01-03T17:36:53.025295", + "cpu_percent": 23.94, + "ram_percent": 45.3, + "ram_used_gb": 28.842689514160156, + "gpu_memory_used": 1098.0, + "relative_time": 130.35286784172058 + }, + { + "timestamp": "2025-01-03T17:36:54.105793", + "cpu_percent": 24.66, + "ram_percent": 45.3, + "ram_used_gb": 28.843029022216797, + "gpu_memory_used": 1094.0, + "relative_time": 131.4563491344452 + }, + { + "timestamp": "2025-01-03T17:36:55.210765", + "cpu_percent": 20.11, + "ram_percent": 45.4, + "ram_used_gb": 28.86923599243164, + "gpu_memory_used": 1101.0, + "relative_time": 132.53530836105347 + }, + { + "timestamp": "2025-01-03T17:36:56.288346", + "cpu_percent": 22.94, + "ram_percent": 45.4, + "ram_used_gb": 28.865219116210938, + "gpu_memory_used": 1101.0, + "relative_time": 133.6023223400116 + }, + { + "timestamp": "2025-01-03T17:36:57.350674", + "cpu_percent": 25.17, + "ram_percent": 45.4, + "ram_used_gb": 28.871688842773438, + "gpu_memory_used": 1101.0, + "relative_time": 134.66028475761414 + }, + { + "timestamp": "2025-01-03T17:36:58.410089", + "cpu_percent": 22.78, + "ram_percent": 45.4, + "ram_used_gb": 28.883277893066406, + "gpu_memory_used": 1101.0, + "relative_time": 135.721449136734 + }, + { + "timestamp": "2025-01-03T17:36:59.470322", + "cpu_percent": 25.26, + "ram_percent": 45.4, + "ram_used_gb": 28.87207794189453, + "gpu_memory_used": 1101.0, + "relative_time": 136.79168581962585 + }, + { + "timestamp": "2025-01-03T17:37:00.544907", + "cpu_percent": 28.76, + "ram_percent": 45.6, + "ram_used_gb": 28.998672485351562, + "gpu_memory_used": 1107.0, + "relative_time": 137.88635969161987 + }, + { + "timestamp": "2025-01-03T17:37:01.635176", + "cpu_percent": 24.18, + "ram_percent": 45.6, + "ram_used_gb": 29.019405364990234, + "gpu_memory_used": 1107.0, + "relative_time": 138.96897864341736 + }, + { + "timestamp": "2025-01-03T17:37:02.724041", + "cpu_percent": 29.28, + "ram_percent": 45.7, + "ram_used_gb": 29.05569076538086, + "gpu_memory_used": 1107.0, + "relative_time": 140.05017518997192 + }, + { + "timestamp": "2025-01-03T17:37:03.800711", + "cpu_percent": 23.59, + "ram_percent": 45.6, + "ram_used_gb": 29.012020111083984, + "gpu_memory_used": 1107.0, + "relative_time": 141.12687349319458 + }, + { + "timestamp": "2025-01-03T17:37:04.879064", + "cpu_percent": 23.78, + "ram_percent": 45.6, + "ram_used_gb": 28.976219177246094, + "gpu_memory_used": 1107.0, + "relative_time": 142.202130317688 + }, + { + "timestamp": "2025-01-03T17:37:05.956549", + "cpu_percent": 25.17, + "ram_percent": 45.6, + "ram_used_gb": 28.987720489501953, + "gpu_memory_used": 1107.0, + "relative_time": 143.2989046573639 + }, + { + "timestamp": "2025-01-03T17:37:07.048608", + "cpu_percent": 21.94, + "ram_percent": 45.6, + "ram_used_gb": 29.001422882080078, + "gpu_memory_used": 1107.0, + "relative_time": 144.38402938842773 + }, + { + "timestamp": "2025-01-03T17:37:08.145411", + "cpu_percent": 24.68, + "ram_percent": 45.6, + "ram_used_gb": 28.99661636352539, + "gpu_memory_used": 1107.0, + "relative_time": 145.45475459098816 + }, + { + "timestamp": "2025-01-03T17:37:09.205410", + "cpu_percent": 22.95, + "ram_percent": 45.5, + "ram_used_gb": 28.954647064208984, + "gpu_memory_used": 1107.0, + "relative_time": 146.52960181236267 + }, + { + "timestamp": "2025-01-03T17:37:10.282693", + "cpu_percent": 24.02, + "ram_percent": 45.5, + "ram_used_gb": 28.946456909179688, + "gpu_memory_used": 1107.0, + "relative_time": 147.60768365859985 + }, + { + "timestamp": "2025-01-03T17:37:11.358777", + "cpu_percent": 25.61, + "ram_percent": 45.5, + "ram_used_gb": 28.94234848022461, + "gpu_memory_used": 1107.0, + "relative_time": 148.6980345249176 + }, + { + "timestamp": "2025-01-03T17:37:12.448461", + "cpu_percent": 23.65, + "ram_percent": 45.5, + "ram_used_gb": 28.95345687866211, + "gpu_memory_used": 1107.0, + "relative_time": 149.7676465511322 + }, + { + "timestamp": "2025-01-03T17:37:13.523095", + "cpu_percent": 20.96, + "ram_percent": 45.5, + "ram_used_gb": 28.952884674072266, + "gpu_memory_used": 1105.0, + "relative_time": 150.85523986816406 + }, + { + "timestamp": "2025-01-03T17:37:14.616165", + "cpu_percent": 22.93, + "ram_percent": 45.5, + "ram_used_gb": 28.9246826171875, + "gpu_memory_used": 1105.0, + "relative_time": 151.93826293945312 + }, + { + "timestamp": "2025-01-03T17:37:15.692716", + "cpu_percent": 23.36, + "ram_percent": 45.5, + "ram_used_gb": 28.923118591308594, + "gpu_memory_used": 1105.0, + "relative_time": 153.02452492713928 + }, + { + "timestamp": "2025-01-03T17:37:16.786480", + "cpu_percent": 24.34, + "ram_percent": 45.5, + "ram_used_gb": 28.922576904296875, + "gpu_memory_used": 1101.0, + "relative_time": 154.13069224357605 + }, + { + "timestamp": "2025-01-03T17:37:17.893401", + "cpu_percent": 23.93, + "ram_percent": 45.5, + "ram_used_gb": 28.929943084716797, + "gpu_memory_used": 1101.0, + "relative_time": 155.20411658287048 + }, + { + "timestamp": "2025-01-03T17:37:18.957325", + "cpu_percent": 22.57, + "ram_percent": 45.5, + "ram_used_gb": 28.92938995361328, + "gpu_memory_used": 1101.0, + "relative_time": 156.2805426120758 + }, + { + "timestamp": "2025-01-03T17:37:20.032870", + "cpu_percent": 24.31, + "ram_percent": 45.5, + "ram_used_gb": 28.91608428955078, + "gpu_memory_used": 1101.0, + "relative_time": 157.3575358390808 + }, + { + "timestamp": "2025-01-03T17:37:21.107354", + "cpu_percent": 23.97, + "ram_percent": 45.5, + "ram_used_gb": 28.927276611328125, + "gpu_memory_used": 1101.0, + "relative_time": 158.43159866333008 + }, + { + "timestamp": "2025-01-03T17:37:22.182666", + "cpu_percent": 22.99, + "ram_percent": 45.5, + "ram_used_gb": 28.96563720703125, + "gpu_memory_used": 1101.0, + "relative_time": 159.51421451568604 + }, + { + "timestamp": "2025-01-03T17:37:23.274242", + "cpu_percent": 23.44, + "ram_percent": 45.5, + "ram_used_gb": 28.972015380859375, + "gpu_memory_used": 1097.0, + "relative_time": 160.60975646972656 + }, + { + "timestamp": "2025-01-03T17:37:24.372135", + "cpu_percent": 22.5, + "ram_percent": 45.6, + "ram_used_gb": 28.979278564453125, + "gpu_memory_used": 1097.0, + "relative_time": 161.72465538978577 + }, + { + "timestamp": "2025-01-03T17:37:25.479851", + "cpu_percent": 23.89, + "ram_percent": 45.6, + "ram_used_gb": 28.982975006103516, + "gpu_memory_used": 1097.0, + "relative_time": 162.80453157424927 + }, + { + "timestamp": "2025-01-03T17:37:26.557456", + "cpu_percent": 23.33, + "ram_percent": 45.6, + "ram_used_gb": 28.983108520507812, + "gpu_memory_used": 1097.0, + "relative_time": 163.90639925003052 + }, + { + "timestamp": "2025-01-03T17:37:27.662359", + "cpu_percent": 23.73, + "ram_percent": 45.6, + "ram_used_gb": 28.9891357421875, + "gpu_memory_used": 1097.0, + "relative_time": 164.97102570533752 + }, + { + "timestamp": "2025-01-03T17:37:28.729649", + "cpu_percent": 24.86, + "ram_percent": 45.5, + "ram_used_gb": 28.938156127929688, + "gpu_memory_used": 1097.0, + "relative_time": 166.06650972366333 + }, + { + "timestamp": "2025-01-03T17:37:29.821140", + "cpu_percent": 24.66, + "ram_percent": 45.5, + "ram_used_gb": 28.924610137939453, + "gpu_memory_used": 1097.0, + "relative_time": 167.14614033699036 + }, + { + "timestamp": "2025-01-03T17:37:30.899520", + "cpu_percent": 24.38, + "ram_percent": 45.4, + "ram_used_gb": 28.88815689086914, + "gpu_memory_used": 1097.0, + "relative_time": 168.21083331108093 + }, + { + "timestamp": "2025-01-03T17:37:31.971936", + "cpu_percent": 21.86, + "ram_percent": 45.5, + "ram_used_gb": 28.91744613647461, + "gpu_memory_used": 1097.0, + "relative_time": 169.29783082008362 + }, + { + "timestamp": "2025-01-03T17:37:33.046151", + "cpu_percent": 24.37, + "ram_percent": 45.5, + "ram_used_gb": 28.91482925415039, + "gpu_memory_used": 1097.0, + "relative_time": 170.36634373664856 + }, + { + "timestamp": "2025-01-03T17:37:34.127110", + "cpu_percent": 25.14, + "ram_percent": 45.5, + "ram_used_gb": 28.912853240966797, + "gpu_memory_used": 1097.0, + "relative_time": 171.45116710662842 + }, + { + "timestamp": "2025-01-03T17:37:35.202044", + "cpu_percent": 24.15, + "ram_percent": 45.4, + "ram_used_gb": 28.891281127929688, + "gpu_memory_used": 1097.0, + "relative_time": 172.50907135009766 + }, + { + "timestamp": "2025-01-03T17:37:36.259605", + "cpu_percent": 22.94, + "ram_percent": 45.4, + "ram_used_gb": 28.900623321533203, + "gpu_memory_used": 1097.0, + "relative_time": 173.5696086883545 + }, + { + "timestamp": "2025-01-03T17:37:37.322695", + "cpu_percent": 23.68, + "ram_percent": 45.5, + "ram_used_gb": 28.914325714111328, + "gpu_memory_used": 1097.0, + "relative_time": 174.63046431541443 + }, + { + "timestamp": "2025-01-03T17:37:38.384439", + "cpu_percent": 24.78, + "ram_percent": 45.4, + "ram_used_gb": 28.909072875976562, + "gpu_memory_used": 1097.0, + "relative_time": 175.72250294685364 + }, + { + "timestamp": "2025-01-03T17:37:39.474721", + "cpu_percent": 23.01, + "ram_percent": 45.4, + "ram_used_gb": 28.891307830810547, + "gpu_memory_used": 1097.0, + "relative_time": 176.81701827049255 + }, + { + "timestamp": "2025-01-03T17:37:40.579589", + "cpu_percent": 23.94, + "ram_percent": 45.5, + "ram_used_gb": 28.943130493164062, + "gpu_memory_used": 1097.0, + "relative_time": 177.92131423950195 + }, + { + "timestamp": "2025-01-03T17:37:41.683635", + "cpu_percent": 24.74, + "ram_percent": 45.5, + "ram_used_gb": 28.932857513427734, + "gpu_memory_used": 1096.0, + "relative_time": 179.0098111629486 + }, + { + "timestamp": "2025-01-03T17:37:42.770033", + "cpu_percent": 21.96, + "ram_percent": 45.7, + "ram_used_gb": 29.069801330566406, + "gpu_memory_used": 1096.0, + "relative_time": 180.11816310882568 + }, + { + "timestamp": "2025-01-03T17:37:43.875555", + "cpu_percent": 24.46, + "ram_percent": 45.9, + "ram_used_gb": 29.216472625732422, + "gpu_memory_used": 1096.0, + "relative_time": 181.22085428237915 + }, + { + "timestamp": "2025-01-03T17:37:44.976559", + "cpu_percent": 23.76, + "ram_percent": 45.6, + "ram_used_gb": 28.995086669921875, + "gpu_memory_used": 1096.0, + "relative_time": 182.30824899673462 + }, + { + "timestamp": "2025-01-03T17:37:46.064782", + "cpu_percent": 22.54, + "ram_percent": 45.8, + "ram_used_gb": 29.127277374267578, + "gpu_memory_used": 1096.0, + "relative_time": 183.41359210014343 + }, + { + "timestamp": "2025-01-03T17:37:47.166282", + "cpu_percent": 23.88, + "ram_percent": 45.5, + "ram_used_gb": 28.938556671142578, + "gpu_memory_used": 1096.0, + "relative_time": 184.49055337905884 + }, + { + "timestamp": "2025-01-03T17:37:48.239146", + "cpu_percent": 25.4, + "ram_percent": 45.5, + "ram_used_gb": 28.928009033203125, + "gpu_memory_used": 1096.0, + "relative_time": 185.56559538841248 + }, + { + "timestamp": "2025-01-03T17:37:49.315823", + "cpu_percent": 23.33, + "ram_percent": 45.5, + "ram_used_gb": 28.938018798828125, + "gpu_memory_used": 1096.0, + "relative_time": 186.64829564094543 + }, + { + "timestamp": "2025-01-03T17:37:50.408592", + "cpu_percent": 23.69, + "ram_percent": 45.5, + "ram_used_gb": 28.91741180419922, + "gpu_memory_used": 1096.0, + "relative_time": 187.7367081642151 + }, + { + "timestamp": "2025-01-03T17:37:51.499880", + "cpu_percent": 26.88, + "ram_percent": 45.5, + "ram_used_gb": 28.922603607177734, + "gpu_memory_used": 1096.0, + "relative_time": 188.8240191936493 + }, + { + "timestamp": "2025-01-03T17:37:52.586316", + "cpu_percent": 22.99, + "ram_percent": 45.5, + "ram_used_gb": 28.949260711669922, + "gpu_memory_used": 1096.0, + "relative_time": 189.92143487930298 + }, + { + "timestamp": "2025-01-03T17:37:53.672626", + "cpu_percent": 23.39, + "ram_percent": 45.5, + "ram_used_gb": 28.948657989501953, + "gpu_memory_used": 1096.0, + "relative_time": 190.984858751297 + }, + { + "timestamp": "2025-01-03T17:37:54.746634", + "cpu_percent": 24.11, + "ram_percent": 45.5, + "ram_used_gb": 28.925277709960938, + "gpu_memory_used": 1096.0, + "relative_time": 192.0710301399231 + }, + { + "timestamp": "2025-01-03T17:37:55.820140", + "cpu_percent": 22.63, + "ram_percent": 45.5, + "ram_used_gb": 28.933975219726562, + "gpu_memory_used": 1096.0, + "relative_time": 193.14398980140686 + }, + { + "timestamp": "2025-01-03T17:37:56.898580", + "cpu_percent": 23.97, + "ram_percent": 45.5, + "ram_used_gb": 28.95156478881836, + "gpu_memory_used": 1096.0, + "relative_time": 194.23374843597412 + }, + { + "timestamp": "2025-01-03T17:37:57.988946", + "cpu_percent": 23.97, + "ram_percent": 45.5, + "ram_used_gb": 28.946693420410156, + "gpu_memory_used": 1096.0, + "relative_time": 195.30232334136963 + }, + { + "timestamp": "2025-01-03T17:37:59.064831", + "cpu_percent": 24.23, + "ram_percent": 45.5, + "ram_used_gb": 28.944950103759766, + "gpu_memory_used": 1096.0, + "relative_time": 196.38868021965027 + }, + { + "timestamp": "2025-01-03T17:38:00.139407", + "cpu_percent": 25.11, + "ram_percent": 45.5, + "ram_used_gb": 28.923294067382812, + "gpu_memory_used": 1096.0, + "relative_time": 197.46892762184143 + }, + { + "timestamp": "2025-01-03T17:38:01.231615", + "cpu_percent": 23.29, + "ram_percent": 45.5, + "ram_used_gb": 28.938377380371094, + "gpu_memory_used": 1096.0, + "relative_time": 198.55928492546082 + }, + { + "timestamp": "2025-01-03T17:38:02.318916", + "cpu_percent": 21.24, + "ram_percent": 45.5, + "ram_used_gb": 28.966472625732422, + "gpu_memory_used": 1096.0, + "relative_time": 199.64228463172913 + }, + { + "timestamp": "2025-01-03T17:38:03.400606", + "cpu_percent": 24.24, + "ram_percent": 45.5, + "ram_used_gb": 28.959705352783203, + "gpu_memory_used": 1096.0, + "relative_time": 200.7337417602539 + }, + { + "timestamp": "2025-01-03T17:38:04.488903", + "cpu_percent": 24.32, + "ram_percent": 45.5, + "ram_used_gb": 28.94487762451172, + "gpu_memory_used": 1096.0, + "relative_time": 201.82986760139465 + }, + { + "timestamp": "2025-01-03T17:38:05.584754", + "cpu_percent": 19.91, + "ram_percent": 45.5, + "ram_used_gb": 28.944644927978516, + "gpu_memory_used": 1096.0, + "relative_time": 202.91072010993958 + }, + { + "timestamp": "2025-01-03T17:38:06.665108", + "cpu_percent": 24.06, + "ram_percent": 45.5, + "ram_used_gb": 28.949317932128906, + "gpu_memory_used": 1096.0, + "relative_time": 203.9763433933258 + }, + { + "timestamp": "2025-01-03T17:38:07.738542", + "cpu_percent": 23.04, + "ram_percent": 45.5, + "ram_used_gb": 28.956283569335938, + "gpu_memory_used": 1096.0, + "relative_time": 205.04700684547424 + }, + { + "timestamp": "2025-01-03T17:38:08.799958", + "cpu_percent": 22.69, + "ram_percent": 45.5, + "ram_used_gb": 28.951473236083984, + "gpu_memory_used": 1096.0, + "relative_time": 206.12592482566833 + }, + { + "timestamp": "2025-01-03T17:38:09.886260", + "cpu_percent": 25.02, + "ram_percent": 45.5, + "ram_used_gb": 28.939456939697266, + "gpu_memory_used": 1096.0, + "relative_time": 207.19513487815857 + }, + { + "timestamp": "2025-01-03T17:38:10.951074", + "cpu_percent": 24.25, + "ram_percent": 45.5, + "ram_used_gb": 28.949993133544922, + "gpu_memory_used": 1096.0, + "relative_time": 208.263596534729 + }, + { + "timestamp": "2025-01-03T17:38:12.021461", + "cpu_percent": 23.19, + "ram_percent": 45.6, + "ram_used_gb": 28.983253479003906, + "gpu_memory_used": 1096.0, + "relative_time": 209.3303987979889 + }, + { + "timestamp": "2025-01-03T17:38:13.082401", + "cpu_percent": 24.01, + "ram_percent": 45.6, + "ram_used_gb": 28.974666595458984, + "gpu_memory_used": 1096.0, + "relative_time": 210.41010332107544 + }, + { + "timestamp": "2025-01-03T17:38:14.161362", + "cpu_percent": 23.13, + "ram_percent": 45.6, + "ram_used_gb": 28.989315032958984, + "gpu_memory_used": 1096.0, + "relative_time": 211.47117710113525 + }, + { + "timestamp": "2025-01-03T17:38:15.222297", + "cpu_percent": 23.49, + "ram_percent": 45.5, + "ram_used_gb": 28.96143341064453, + "gpu_memory_used": 1096.0, + "relative_time": 212.53540086746216 + }, + { + "timestamp": "2025-01-03T17:38:16.298851", + "cpu_percent": 22.21, + "ram_percent": 45.5, + "ram_used_gb": 28.964900970458984, + "gpu_memory_used": 1096.0, + "relative_time": 213.62320566177368 + }, + { + "timestamp": "2025-01-03T17:38:17.374842", + "cpu_percent": 25.44, + "ram_percent": 45.6, + "ram_used_gb": 28.97797393798828, + "gpu_memory_used": 1096.0, + "relative_time": 214.69756841659546 + }, + { + "timestamp": "2025-01-03T17:38:18.449249", + "cpu_percent": 23.43, + "ram_percent": 45.6, + "ram_used_gb": 28.979202270507812, + "gpu_memory_used": 1096.0, + "relative_time": 215.78058910369873 + }, + { + "timestamp": "2025-01-03T17:38:19.542583", + "cpu_percent": 24.46, + "ram_percent": 45.5, + "ram_used_gb": 28.965267181396484, + "gpu_memory_used": 1096.0, + "relative_time": 216.87048959732056 + }, + { + "timestamp": "2025-01-03T17:38:20.619429", + "cpu_percent": 20.75, + "ram_percent": 45.6, + "ram_used_gb": 29.00174331665039, + "gpu_memory_used": 1106.0, + "relative_time": 217.92598581314087 + }, + { + "timestamp": "2025-01-03T17:38:21.680941", + "cpu_percent": 22.77, + "ram_percent": 45.6, + "ram_used_gb": 29.00212860107422, + "gpu_memory_used": 1106.0, + "relative_time": 219.00471091270447 + }, + { + "timestamp": "2025-01-03T17:38:22.755945", + "cpu_percent": 22.64, + "ram_percent": 45.6, + "ram_used_gb": 29.018749237060547, + "gpu_memory_used": 1106.0, + "relative_time": 220.07630491256714 + }, + { + "timestamp": "2025-01-03T17:38:23.829578", + "cpu_percent": 23.32, + "ram_percent": 45.6, + "ram_used_gb": 29.031707763671875, + "gpu_memory_used": 1106.0, + "relative_time": 221.14346361160278 + }, + { + "timestamp": "2025-01-03T17:38:24.906788", + "cpu_percent": 24.83, + "ram_percent": 45.7, + "ram_used_gb": 29.07465362548828, + "gpu_memory_used": 1106.0, + "relative_time": 222.22201228141785 + }, + { + "timestamp": "2025-01-03T17:38:25.983092", + "cpu_percent": 24.31, + "ram_percent": 45.7, + "ram_used_gb": 29.073284149169922, + "gpu_memory_used": 1106.0, + "relative_time": 223.32304573059082 + }, + { + "timestamp": "2025-01-03T17:38:27.086695", + "cpu_percent": 23.53, + "ram_percent": 45.7, + "ram_used_gb": 29.08266830444336, + "gpu_memory_used": 1105.0, + "relative_time": 224.39583778381348 + }, + { + "timestamp": "2025-01-03T17:38:28.148619", + "cpu_percent": 21.91, + "ram_percent": 45.7, + "ram_used_gb": 29.090988159179688, + "gpu_memory_used": 1102.0, + "relative_time": 225.47977566719055 + }, + { + "timestamp": "2025-01-03T17:38:29.229406", + "cpu_percent": 21.76, + "ram_percent": 45.7, + "ram_used_gb": 29.09268569946289, + "gpu_memory_used": 1102.0, + "relative_time": 226.55404257774353 + }, + { + "timestamp": "2025-01-03T17:38:30.302956", + "cpu_percent": 24.08, + "ram_percent": 45.7, + "ram_used_gb": 29.077293395996094, + "gpu_memory_used": 1102.0, + "relative_time": 227.62869882583618 + }, + { + "timestamp": "2025-01-03T17:38:31.381882", + "cpu_percent": 24.35, + "ram_percent": 45.7, + "ram_used_gb": 29.086669921875, + "gpu_memory_used": 1102.0, + "relative_time": 228.69078159332275 + }, + { + "timestamp": "2025-01-03T17:38:32.445804", + "cpu_percent": 20.03, + "ram_percent": 45.8, + "ram_used_gb": 29.113361358642578, + "gpu_memory_used": 1102.0, + "relative_time": 229.77253794670105 + }, + { + "timestamp": "2025-01-03T17:38:33.522412", + "cpu_percent": 23.34, + "ram_percent": 45.7, + "ram_used_gb": 29.09762954711914, + "gpu_memory_used": 1102.0, + "relative_time": 230.85764026641846 + }, + { + "timestamp": "2025-01-03T17:38:34.616552", + "cpu_percent": 23.3, + "ram_percent": 45.7, + "ram_used_gb": 29.079090118408203, + "gpu_memory_used": 1102.0, + "relative_time": 231.92474102973938 + }, + { + "timestamp": "2025-01-03T17:38:35.678749", + "cpu_percent": 23.45, + "ram_percent": 45.6, + "ram_used_gb": 29.03809356689453, + "gpu_memory_used": 1102.0, + "relative_time": 232.9860770702362 + }, + { + "timestamp": "2025-01-03T17:38:36.741777", + "cpu_percent": 22.69, + "ram_percent": 45.7, + "ram_used_gb": 29.048213958740234, + "gpu_memory_used": 1102.0, + "relative_time": 234.0679018497467 + }, + { + "timestamp": "2025-01-03T17:38:37.829685", + "cpu_percent": 22.24, + "ram_percent": 45.7, + "ram_used_gb": 29.05181121826172, + "gpu_memory_used": 1102.0, + "relative_time": 235.15741419792175 + }, + { + "timestamp": "2025-01-03T17:38:38.913093", + "cpu_percent": 22.38, + "ram_percent": 45.7, + "ram_used_gb": 29.053848266601562, + "gpu_memory_used": 1102.0, + "relative_time": 236.23899698257446 + }, + { + "timestamp": "2025-01-03T17:38:39.990580", + "cpu_percent": 23.18, + "ram_percent": 45.7, + "ram_used_gb": 29.047801971435547, + "gpu_memory_used": 1102.0, + "relative_time": 237.29979014396667 + }, + { + "timestamp": "2025-01-03T17:38:41.050376", + "cpu_percent": 23.39, + "ram_percent": 45.7, + "ram_used_gb": 29.04970932006836, + "gpu_memory_used": 1102.0, + "relative_time": 238.3743212223053 + }, + { + "timestamp": "2025-01-03T17:38:42.124373", + "cpu_percent": 22.72, + "ram_percent": 45.7, + "ram_used_gb": 29.08245849609375, + "gpu_memory_used": 1098.0, + "relative_time": 239.45003628730774 + }, + { + "timestamp": "2025-01-03T17:38:43.199649", + "cpu_percent": 25.66, + "ram_percent": 45.7, + "ram_used_gb": 29.084999084472656, + "gpu_memory_used": 1098.0, + "relative_time": 240.50825381278992 + }, + { + "timestamp": "2025-01-03T17:38:44.260682", + "cpu_percent": 23.85, + "ram_percent": 45.7, + "ram_used_gb": 29.082542419433594, + "gpu_memory_used": 1094.0, + "relative_time": 241.58613228797913 + }, + { + "timestamp": "2025-01-03T17:38:45.334296", + "cpu_percent": 23.69, + "ram_percent": 45.7, + "ram_used_gb": 29.070350646972656, + "gpu_memory_used": 1094.0, + "relative_time": 242.6601538658142 + }, + { + "timestamp": "2025-01-03T17:38:46.411938", + "cpu_percent": 23.01, + "ram_percent": 45.7, + "ram_used_gb": 29.07455062866211, + "gpu_memory_used": 1094.0, + "relative_time": 243.74639248847961 + }, + { + "timestamp": "2025-01-03T17:38:47.504134", + "cpu_percent": 21.79, + "ram_percent": 45.7, + "ram_used_gb": 29.08453369140625, + "gpu_memory_used": 1094.0, + "relative_time": 244.81757807731628 + }, + { + "timestamp": "2025-01-03T17:38:48.577966", + "cpu_percent": 26.51, + "ram_percent": 45.7, + "ram_used_gb": 29.07624053955078, + "gpu_memory_used": 1094.0, + "relative_time": 245.90141248703003 + }, + { + "timestamp": "2025-01-03T17:38:49.654082", + "cpu_percent": 24.57, + "ram_percent": 45.7, + "ram_used_gb": 29.06304931640625, + "gpu_memory_used": 1094.0, + "relative_time": 246.97977018356323 + }, + { + "timestamp": "2025-01-03T17:38:50.733158", + "cpu_percent": 25.44, + "ram_percent": 45.7, + "ram_used_gb": 29.063785552978516, + "gpu_memory_used": 1094.0, + "relative_time": 248.0419783592224 + }, + { + "timestamp": "2025-01-03T17:38:51.795154", + "cpu_percent": 24.09, + "ram_percent": 45.7, + "ram_used_gb": 29.070831298828125, + "gpu_memory_used": 1094.0, + "relative_time": 249.1282820701599 + }, + { + "timestamp": "2025-01-03T17:38:52.885541", + "cpu_percent": 24.81, + "ram_percent": 45.7, + "ram_used_gb": 29.097518920898438, + "gpu_memory_used": 1094.0, + "relative_time": 250.21453881263733 + }, + { + "timestamp": "2025-01-03T17:38:53.967110", + "cpu_percent": 23.51, + "ram_percent": 45.7, + "ram_used_gb": 29.092403411865234, + "gpu_memory_used": 1094.0, + "relative_time": 251.29131293296814 + }, + { + "timestamp": "2025-01-03T17:38:55.053817", + "cpu_percent": 25.5, + "ram_percent": 45.6, + "ram_used_gb": 29.026763916015625, + "gpu_memory_used": 1094.0, + "relative_time": 252.38121151924133 + }, + { + "timestamp": "2025-01-03T17:38:56.130310", + "cpu_percent": 23.02, + "ram_percent": 45.6, + "ram_used_gb": 29.029300689697266, + "gpu_memory_used": 1094.0, + "relative_time": 253.46182870864868 + }, + { + "timestamp": "2025-01-03T17:38:57.222446", + "cpu_percent": 23.57, + "ram_percent": 45.7, + "ram_used_gb": 29.048370361328125, + "gpu_memory_used": 1094.0, + "relative_time": 254.5469455718994 + }, + { + "timestamp": "2025-01-03T17:38:58.302749", + "cpu_percent": 23.36, + "ram_percent": 45.7, + "ram_used_gb": 29.04967498779297, + "gpu_memory_used": 1094.0, + "relative_time": 255.6269781589508 + }, + { + "timestamp": "2025-01-03T17:38:59.390900", + "cpu_percent": 23.02, + "ram_percent": 45.7, + "ram_used_gb": 29.05054473876953, + "gpu_memory_used": 1094.0, + "relative_time": 256.73245453834534 + }, + { + "timestamp": "2025-01-03T17:39:00.484435", + "cpu_percent": 27.29, + "ram_percent": 45.6, + "ram_used_gb": 29.031696319580078, + "gpu_memory_used": 1094.0, + "relative_time": 257.81579089164734 + }, + { + "timestamp": "2025-01-03T17:39:01.571625", + "cpu_percent": 23.57, + "ram_percent": 45.6, + "ram_used_gb": 29.025615692138672, + "gpu_memory_used": 1094.0, + "relative_time": 258.8843922615051 + }, + { + "timestamp": "2025-01-03T17:39:02.647939", + "cpu_percent": 22.86, + "ram_percent": 45.7, + "ram_used_gb": 29.05437469482422, + "gpu_memory_used": 1094.0, + "relative_time": 259.9595341682434 + }, + { + "timestamp": "2025-01-03T17:39:03.714104", + "cpu_percent": 23.78, + "ram_percent": 45.7, + "ram_used_gb": 29.049884796142578, + "gpu_memory_used": 1094.0, + "relative_time": 261.0387761592865 + }, + { + "timestamp": "2025-01-03T17:39:04.790962", + "cpu_percent": 23.94, + "ram_percent": 45.6, + "ram_used_gb": 29.026226043701172, + "gpu_memory_used": 1094.0, + "relative_time": 262.1065058708191 + }, + { + "timestamp": "2025-01-03T17:39:05.865171", + "cpu_percent": 23.71, + "ram_percent": 45.6, + "ram_used_gb": 29.03447723388672, + "gpu_memory_used": 1094.0, + "relative_time": 263.17548394203186 + }, + { + "timestamp": "2025-01-03T17:39:06.925070", + "cpu_percent": 22.13, + "ram_percent": 45.7, + "ram_used_gb": 29.03990936279297, + "gpu_memory_used": 1094.0, + "relative_time": 264.2537627220154 + }, + { + "timestamp": "2025-01-03T17:39:08.016047", + "cpu_percent": 24.59, + "ram_percent": 45.7, + "ram_used_gb": 29.048423767089844, + "gpu_memory_used": 1094.0, + "relative_time": 265.3426134586334 + }, + { + "timestamp": "2025-01-03T17:39:09.093191", + "cpu_percent": 24.42, + "ram_percent": 45.7, + "ram_used_gb": 29.047550201416016, + "gpu_memory_used": 1094.0, + "relative_time": 266.4227204322815 + }, + { + "timestamp": "2025-01-03T17:39:10.181954", + "cpu_percent": 25.16, + "ram_percent": 45.7, + "ram_used_gb": 29.04483413696289, + "gpu_memory_used": 1094.0, + "relative_time": 267.5157723426819 + }, + { + "timestamp": "2025-01-03T17:39:11.274938", + "cpu_percent": 23.93, + "ram_percent": 45.7, + "ram_used_gb": 29.05465316772461, + "gpu_memory_used": 1094.0, + "relative_time": 268.588228225708 + }, + { + "timestamp": "2025-01-03T17:39:12.348453", + "cpu_percent": 23.18, + "ram_percent": 45.7, + "ram_used_gb": 29.08385467529297, + "gpu_memory_used": 1094.0, + "relative_time": 269.6606616973877 + }, + { + "timestamp": "2025-01-03T17:39:13.409071", + "cpu_percent": 24.29, + "ram_percent": 45.7, + "ram_used_gb": 29.074764251708984, + "gpu_memory_used": 1094.0, + "relative_time": 270.734317779541 + }, + { + "timestamp": "2025-01-03T17:39:14.486654", + "cpu_percent": 23.16, + "ram_percent": 45.7, + "ram_used_gb": 29.066978454589844, + "gpu_memory_used": 1094.0, + "relative_time": 271.8204891681671 + }, + { + "timestamp": "2025-01-03T17:39:15.575060", + "cpu_percent": 24.34, + "ram_percent": 45.7, + "ram_used_gb": 29.046417236328125, + "gpu_memory_used": 1094.0, + "relative_time": 272.9057719707489 + }, + { + "timestamp": "2025-01-03T17:39:16.666232", + "cpu_percent": 24.03, + "ram_percent": 45.7, + "ram_used_gb": 29.045166015625, + "gpu_memory_used": 1099.0, + "relative_time": 273.9924840927124 + }, + { + "timestamp": "2025-01-03T17:39:17.755564", + "cpu_percent": 23.2, + "ram_percent": 45.7, + "ram_used_gb": 29.060283660888672, + "gpu_memory_used": 1099.0, + "relative_time": 275.0789313316345 + }, + { + "timestamp": "2025-01-03T17:39:18.830783", + "cpu_percent": 23.06, + "ram_percent": 45.7, + "ram_used_gb": 29.053966522216797, + "gpu_memory_used": 1099.0, + "relative_time": 276.15661883354187 + }, + { + "timestamp": "2025-01-03T17:39:19.920912", + "cpu_percent": 25.16, + "ram_percent": 45.7, + "ram_used_gb": 29.053394317626953, + "gpu_memory_used": 1103.0, + "relative_time": 277.2462124824524 + }, + { + "timestamp": "2025-01-03T17:39:21.001466", + "cpu_percent": 27.46, + "ram_percent": 45.7, + "ram_used_gb": 29.053443908691406, + "gpu_memory_used": 1105.0, + "relative_time": 278.33917236328125 + }, + { + "timestamp": "2025-01-03T17:39:22.096283", + "cpu_percent": 25.03, + "ram_percent": 45.7, + "ram_used_gb": 29.078914642333984, + "gpu_memory_used": 1106.0, + "relative_time": 279.46978664398193 + }, + { + "timestamp": "2025-01-03T17:39:23.218194", + "cpu_percent": 23.54, + "ram_percent": 45.7, + "ram_used_gb": 29.093307495117188, + "gpu_memory_used": 1106.0, + "relative_time": 280.5258755683899 + }, + { + "timestamp": "2025-01-03T17:39:24.281791", + "cpu_percent": 24.16, + "ram_percent": 45.7, + "ram_used_gb": 29.094207763671875, + "gpu_memory_used": 1106.0, + "relative_time": 281.63647842407227 + }, + { + "timestamp": "2025-01-03T17:39:25.388563", + "cpu_percent": 26.11, + "ram_percent": 45.7, + "ram_used_gb": 29.082473754882812, + "gpu_memory_used": 1106.0, + "relative_time": 282.72587037086487 + }, + { + "timestamp": "2025-01-03T17:39:26.478973", + "cpu_percent": 27.64, + "ram_percent": 45.7, + "ram_used_gb": 29.100139617919922, + "gpu_memory_used": 1114.0, + "relative_time": 283.8215317726135 + }, + { + "timestamp": "2025-01-03T17:39:27.583645", + "cpu_percent": 24.39, + "ram_percent": 45.8, + "ram_used_gb": 29.103557586669922, + "gpu_memory_used": 1114.0, + "relative_time": 284.9139611721039 + }, + { + "timestamp": "2025-01-03T17:39:28.671523", + "cpu_percent": 26.52, + "ram_percent": 45.8, + "ram_used_gb": 29.135478973388672, + "gpu_memory_used": 1114.0, + "relative_time": 286.01276302337646 + }, + { + "timestamp": "2025-01-03T17:39:29.771573", + "cpu_percent": 37.88, + "ram_percent": 45.9, + "ram_used_gb": 29.20437240600586, + "gpu_memory_used": 1114.0, + "relative_time": 287.1181216239929 + }, + { + "timestamp": "2025-01-03T17:39:30.869733", + "cpu_percent": 51.38, + "ram_percent": 45.8, + "ram_used_gb": 29.151920318603516, + "gpu_memory_used": 1114.0, + "relative_time": 288.20085978507996 + }, + { + "timestamp": "2025-01-03T17:39:31.957778", + "cpu_percent": 31.69, + "ram_percent": 45.9, + "ram_used_gb": 29.169265747070312, + "gpu_memory_used": 1111.0, + "relative_time": 289.32613611221313 + }, + { + "timestamp": "2025-01-03T17:39:33.087546", + "cpu_percent": 35.71, + "ram_percent": 45.9, + "ram_used_gb": 29.177200317382812, + "gpu_memory_used": 1109.0, + "relative_time": 290.4660506248474 + }, + { + "timestamp": "2025-01-03T17:39:34.225021", + "cpu_percent": 41.35, + "ram_percent": 46.1, + "ram_used_gb": 29.297359466552734, + "gpu_memory_used": 1109.0, + "relative_time": 291.5882089138031 + }, + { + "timestamp": "2025-01-03T17:39:35.340627", + "cpu_percent": 53.14, + "ram_percent": 45.9, + "ram_used_gb": 29.174144744873047, + "gpu_memory_used": 1109.0, + "relative_time": 292.7014124393463 + }, + { + "timestamp": "2025-01-03T17:39:36.450806", + "cpu_percent": 42.99, + "ram_percent": 46.0, + "ram_used_gb": 29.263404846191406, + "gpu_memory_used": 1110.0, + "relative_time": 293.8717691898346 + }, + { + "timestamp": "2025-01-03T17:39:37.626229", + "cpu_percent": 47.2, + "ram_percent": 46.0, + "ram_used_gb": 29.242015838623047, + "gpu_memory_used": 1110.0, + "relative_time": 294.98959398269653 + }, + { + "timestamp": "2025-01-03T17:39:38.744021", + "cpu_percent": 63.88, + "ram_percent": 46.2, + "ram_used_gb": 29.360958099365234, + "gpu_memory_used": 1110.0, + "relative_time": 296.1400308609009 + }, + { + "timestamp": "2025-01-03T17:39:39.894556", + "cpu_percent": 63.27, + "ram_percent": 45.9, + "ram_used_gb": 29.206928253173828, + "gpu_memory_used": 1110.0, + "relative_time": 297.2615807056427 + }, + { + "timestamp": "2025-01-03T17:39:41.013357", + "cpu_percent": 50.07, + "ram_percent": 46.0, + "ram_used_gb": 29.283645629882812, + "gpu_memory_used": 1110.0, + "relative_time": 298.38854813575745 + }, + { + "timestamp": "2025-01-03T17:39:42.147807", + "cpu_percent": 46.93, + "ram_percent": 46.0, + "ram_used_gb": 29.241199493408203, + "gpu_memory_used": 1110.0, + "relative_time": 299.50307989120483 + }, + { + "timestamp": "2025-01-03T17:39:43.258353", + "cpu_percent": 29.54, + "ram_percent": 46.0, + "ram_used_gb": 29.283145904541016, + "gpu_memory_used": 1110.0, + "relative_time": 300.59265756607056 + }, + { + "timestamp": "2025-01-03T17:39:44.348698", + "cpu_percent": 32.59, + "ram_percent": 46.0, + "ram_used_gb": 29.279296875, + "gpu_memory_used": 1108.0, + "relative_time": 301.70956802368164 + }, + { + "timestamp": "2025-01-03T17:39:45.462748", + "cpu_percent": 34.87, + "ram_percent": 46.0, + "ram_used_gb": 29.259193420410156, + "gpu_memory_used": 1109.0, + "relative_time": 302.79254055023193 + }, + { + "timestamp": "2025-01-03T17:39:46.547817", + "cpu_percent": 32.98, + "ram_percent": 46.0, + "ram_used_gb": 29.246997833251953, + "gpu_memory_used": 1109.0, + "relative_time": 303.8971025943756 + }, + { + "timestamp": "2025-01-03T17:39:47.658725", + "cpu_percent": 40.88, + "ram_percent": 46.0, + "ram_used_gb": 29.269287109375, + "gpu_memory_used": 1108.0, + "relative_time": 305.0029399394989 + }, + { + "timestamp": "2025-01-03T17:39:48.760123", + "cpu_percent": 43.58, + "ram_percent": 46.3, + "ram_used_gb": 29.445144653320312, + "gpu_memory_used": 1105.0, + "relative_time": 306.1181561946869 + }, + { + "timestamp": "2025-01-03T17:39:49.877225", + "cpu_percent": 33.54, + "ram_percent": 46.0, + "ram_used_gb": 29.264232635498047, + "gpu_memory_used": 1105.0, + "relative_time": 307.2013146877289 + }, + { + "timestamp": "2025-01-03T17:39:50.952699", + "cpu_percent": 38.25, + "ram_percent": 46.2, + "ram_used_gb": 29.358203887939453, + "gpu_memory_used": 1113.0, + "relative_time": 308.3161952495575 + }, + { + "timestamp": "2025-01-03T17:39:52.074361", + "cpu_percent": 28.14, + "ram_percent": 46.3, + "ram_used_gb": 29.476333618164062, + "gpu_memory_used": 1111.0, + "relative_time": 309.4449317455292 + }, + { + "timestamp": "2025-01-03T17:39:53.198618", + "cpu_percent": 40.66, + "ram_percent": 46.3, + "ram_used_gb": 29.434783935546875, + "gpu_memory_used": 1117.0, + "relative_time": 310.5291397571564 + }, + { + "timestamp": "2025-01-03T17:39:54.288267", + "cpu_percent": 28.12, + "ram_percent": 46.2, + "ram_used_gb": 29.40790557861328, + "gpu_memory_used": 1123.0, + "relative_time": 311.648175239563 + }, + { + "timestamp": "2025-01-03T17:39:55.397071", + "cpu_percent": 26.64, + "ram_percent": 46.2, + "ram_used_gb": 29.376319885253906, + "gpu_memory_used": 1123.0, + "relative_time": 312.72413992881775 + }, + { + "timestamp": "2025-01-03T17:39:56.486647", + "cpu_percent": 25.62, + "ram_percent": 46.2, + "ram_used_gb": 29.39731216430664, + "gpu_memory_used": 1120.0, + "relative_time": 313.8426833152771 + }, + { + "timestamp": "2025-01-03T17:39:57.593572", + "cpu_percent": 27.73, + "ram_percent": 45.9, + "ram_used_gb": 29.215042114257812, + "gpu_memory_used": 1120.0, + "relative_time": 314.9389867782593 + }, + { + "timestamp": "2025-01-03T17:39:58.700730", + "cpu_percent": 27.28, + "ram_percent": 45.9, + "ram_used_gb": 29.222488403320312, + "gpu_memory_used": 1121.0, + "relative_time": 316.0105288028717 + }, + { + "timestamp": "2025-01-03T17:39:59.774069", + "cpu_percent": 31.39, + "ram_percent": 45.9, + "ram_used_gb": 29.198009490966797, + "gpu_memory_used": 1111.0, + "relative_time": 317.12384700775146 + }, + { + "timestamp": "2025-01-03T17:40:00.885192", + "cpu_percent": 28.06, + "ram_percent": 45.9, + "ram_used_gb": 29.19915771484375, + "gpu_memory_used": 1111.0, + "relative_time": 318.2079384326935 + }, + { + "timestamp": "2025-01-03T17:40:01.963276", + "cpu_percent": 24.83, + "ram_percent": 45.9, + "ram_used_gb": 29.220375061035156, + "gpu_memory_used": 1111.0, + "relative_time": 319.31243777275085 + }, + { + "timestamp": "2025-01-03T17:40:03.069394", + "cpu_percent": 24.7, + "ram_percent": 45.9, + "ram_used_gb": 29.226959228515625, + "gpu_memory_used": 1115.0, + "relative_time": 320.39933586120605 + }, + { + "timestamp": "2025-01-03T17:40:04.157278", + "cpu_percent": 23.66, + "ram_percent": 46.0, + "ram_used_gb": 29.235092163085938, + "gpu_memory_used": 1116.0, + "relative_time": 321.47987031936646 + }, + { + "timestamp": "2025-01-03T17:40:05.234540", + "cpu_percent": 25.81, + "ram_percent": 45.9, + "ram_used_gb": 29.195159912109375, + "gpu_memory_used": 1116.0, + "relative_time": 322.55900835990906 + }, + { + "timestamp": "2025-01-03T17:40:06.309731", + "cpu_percent": 23.72, + "ram_percent": 45.9, + "ram_used_gb": 29.18838119506836, + "gpu_memory_used": 1114.0, + "relative_time": 323.6197941303253 + }, + { + "timestamp": "2025-01-03T17:40:07.369706", + "cpu_percent": 22.79, + "ram_percent": 46.0, + "ram_used_gb": 29.232295989990234, + "gpu_memory_used": 1115.0, + "relative_time": 324.67907524108887 + }, + { + "timestamp": "2025-01-03T17:40:08.427907", + "cpu_percent": 20.87, + "ram_percent": 45.9, + "ram_used_gb": 29.225311279296875, + "gpu_memory_used": 1114.0, + "relative_time": 325.77514839172363 + }, + { + "timestamp": "2025-01-03T17:40:09.531189", + "cpu_percent": 27.84, + "ram_percent": 45.9, + "ram_used_gb": 29.220264434814453, + "gpu_memory_used": 1111.0, + "relative_time": 326.8838756084442 + }, + { + "timestamp": "2025-01-03T17:40:10.635660", + "cpu_percent": 21.53, + "ram_percent": 45.9, + "ram_used_gb": 29.223426818847656, + "gpu_memory_used": 1111.0, + "relative_time": 327.9577159881592 + }, + { + "timestamp": "2025-01-03T17:40:11.712367", + "cpu_percent": 23.51, + "ram_percent": 45.9, + "ram_used_gb": 29.221378326416016, + "gpu_memory_used": 1111.0, + "relative_time": 329.0358979701996 + }, + { + "timestamp": "2025-01-03T17:40:12.785899", + "cpu_percent": 22.29, + "ram_percent": 46.0, + "ram_used_gb": 29.258285522460938, + "gpu_memory_used": 1111.0, + "relative_time": 330.09391021728516 + }, + { + "timestamp": "2025-01-03T17:40:13.847325", + "cpu_percent": 23.39, + "ram_percent": 46.0, + "ram_used_gb": 29.249286651611328, + "gpu_memory_used": 1111.0, + "relative_time": 331.1698377132416 + }, + { + "timestamp": "2025-01-03T17:40:14.924517", + "cpu_percent": 24.0, + "ram_percent": 45.9, + "ram_used_gb": 29.213272094726562, + "gpu_memory_used": 1109.0, + "relative_time": 332.2554090023041 + }, + { + "timestamp": "2025-01-03T17:40:16.017128", + "cpu_percent": 17.02, + "ram_percent": 46.2, + "ram_used_gb": 29.360702514648438, + "gpu_memory_used": 1106.0, + "relative_time": 333.3264467716217 + } + ], + "test_duration": 335.7011880874634 +} \ No newline at end of file diff --git a/examples/assorted_checks/benchmarks/output_data/cpu_benchmark_stats_rtf.txt b/examples/assorted_checks/benchmarks/output_data/cpu_benchmark_stats_rtf.txt new file mode 100644 index 0000000..45d2a87 --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/cpu_benchmark_stats_rtf.txt @@ -0,0 +1,23 @@ +=== Benchmark Statistics (with correct RTF) === + +Total tokens processed: 2250 +Total audio generated (s): 710.80 +Total test duration (s): 332.81 +Average processing rate (tokens/s): 6.77 +Average RTF: 0.47 +Average Real Time Speed: 2.14 + +=== Per-chunk Stats === + +Average chunk size (tokens): 450.00 +Min chunk size (tokens): 150 +Max chunk size (tokens): 750 +Average processing time (s): 66.51 +Average output length (s): 142.16 + +=== Performance Ranges === + +Processing rate range (tokens/s): 6.50 - 7.00 +RTF range: 0.45x - 0.50x +Real Time Speed range: 2.00x - 2.22x + diff --git a/examples/assorted_checks/benchmarks/output_data/gpu_benchmark_results_rtf.json b/examples/assorted_checks/benchmarks/output_data/gpu_benchmark_results_rtf.json new file mode 100644 index 0000000..ae59bfe --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/gpu_benchmark_results_rtf.json @@ -0,0 +1,607 @@ +{ + "results": [ + { + "tokens": 150, + "processing_time": 1.03, + "output_length": 45.9, + "rtf": 0.02, + "elapsed_time": 1.07 + }, + { + "tokens": 300, + "processing_time": 2.51, + "output_length": 96.425, + "rtf": 0.03, + "elapsed_time": 3.63 + }, + { + "tokens": 450, + "processing_time": 3.69, + "output_length": 143.1, + "rtf": 0.03, + "elapsed_time": 7.37 + }, + { + "tokens": 600, + "processing_time": 5.52, + "output_length": 188.675, + "rtf": 0.03, + "elapsed_time": 12.96 + }, + { + "tokens": 750, + "processing_time": 6.32, + "output_length": 236.7, + "rtf": 0.03, + "elapsed_time": 19.34 + }, + { + "tokens": 900, + "processing_time": 8.4, + "output_length": 283.425, + "rtf": 0.03, + "elapsed_time": 27.82 + }, + { + "tokens": 2000, + "processing_time": 15.46, + "output_length": 624.325, + "rtf": 0.02, + "elapsed_time": 43.4 + }, + { + "tokens": 3000, + "processing_time": 27.11, + "output_length": 931.15, + "rtf": 0.03, + "elapsed_time": 70.7 + } + ], + "system_metrics": [ + { + "timestamp": "2025-01-03T17:45:10.797646", + "cpu_percent": 10.05, + "ram_percent": 54.2, + "ram_used_gb": 34.474674224853516, + "gpu_memory_used": 3992.0, + "relative_time": 0.06637930870056152 + }, + { + "timestamp": "2025-01-03T17:45:11.871315", + "cpu_percent": 13.54, + "ram_percent": 54.2, + "ram_used_gb": 34.47991180419922, + "gpu_memory_used": 3990.0, + "relative_time": 1.1326591968536377 + }, + { + "timestamp": "2025-01-03T17:45:12.932597", + "cpu_percent": 12.76, + "ram_percent": 54.2, + "ram_used_gb": 34.501747131347656, + "gpu_memory_used": 3990.0, + "relative_time": 2.192795515060425 + }, + { + "timestamp": "2025-01-03T17:45:13.995052", + "cpu_percent": 15.48, + "ram_percent": 54.2, + "ram_used_gb": 34.48517990112305, + "gpu_memory_used": 3989.0, + "relative_time": 3.253366231918335 + }, + { + "timestamp": "2025-01-03T17:45:15.056310", + "cpu_percent": 11.96, + "ram_percent": 54.2, + "ram_used_gb": 34.457679748535156, + "gpu_memory_used": 3980.0, + "relative_time": 4.331450462341309 + }, + { + "timestamp": "2025-01-03T17:45:16.128795", + "cpu_percent": 14.28, + "ram_percent": 54.2, + "ram_used_gb": 34.465850830078125, + "gpu_memory_used": 3980.0, + "relative_time": 5.386842727661133 + }, + { + "timestamp": "2025-01-03T17:45:17.185921", + "cpu_percent": 13.14, + "ram_percent": 54.2, + "ram_used_gb": 34.4874153137207, + "gpu_memory_used": 3980.0, + "relative_time": 6.450911998748779 + }, + { + "timestamp": "2025-01-03T17:45:18.248252", + "cpu_percent": 15.54, + "ram_percent": 54.4, + "ram_used_gb": 34.581886291503906, + "gpu_memory_used": 3986.0, + "relative_time": 7.525278329849243 + }, + { + "timestamp": "2025-01-03T17:45:19.324382", + "cpu_percent": 14.89, + "ram_percent": 54.4, + "ram_used_gb": 34.5898551940918, + "gpu_memory_used": 3987.0, + "relative_time": 8.588879585266113 + }, + { + "timestamp": "2025-01-03T17:45:20.394701", + "cpu_percent": 12.13, + "ram_percent": 54.4, + "ram_used_gb": 34.582420349121094, + "gpu_memory_used": 3986.0, + "relative_time": 9.65286660194397 + }, + { + "timestamp": "2025-01-03T17:45:21.455704", + "cpu_percent": 11.02, + "ram_percent": 54.4, + "ram_used_gb": 34.617252349853516, + "gpu_memory_used": 3986.0, + "relative_time": 10.71657395362854 + }, + { + "timestamp": "2025-01-03T17:45:22.525946", + "cpu_percent": 14.01, + "ram_percent": 54.5, + "ram_used_gb": 34.651466369628906, + "gpu_memory_used": 3989.0, + "relative_time": 11.787351846694946 + }, + { + "timestamp": "2025-01-03T17:45:23.584761", + "cpu_percent": 13.09, + "ram_percent": 54.5, + "ram_used_gb": 34.680885314941406, + "gpu_memory_used": 3989.0, + "relative_time": 12.846002101898193 + }, + { + "timestamp": "2025-01-03T17:45:24.645316", + "cpu_percent": 17.72, + "ram_percent": 54.6, + "ram_used_gb": 34.741127014160156, + "gpu_memory_used": 3985.0, + "relative_time": 13.918755054473877 + }, + { + "timestamp": "2025-01-03T17:45:25.718731", + "cpu_percent": 14.66, + "ram_percent": 54.6, + "ram_used_gb": 34.71047592163086, + "gpu_memory_used": 3982.0, + "relative_time": 14.974157810211182 + }, + { + "timestamp": "2025-01-03T17:45:26.774860", + "cpu_percent": 11.52, + "ram_percent": 54.6, + "ram_used_gb": 34.728397369384766, + "gpu_memory_used": 3982.0, + "relative_time": 16.034392833709717 + }, + { + "timestamp": "2025-01-03T17:45:27.837623", + "cpu_percent": 11.04, + "ram_percent": 54.6, + "ram_used_gb": 34.75224685668945, + "gpu_memory_used": 3981.0, + "relative_time": 17.096498250961304 + }, + { + "timestamp": "2025-01-03T17:45:28.898447", + "cpu_percent": 12.17, + "ram_percent": 54.7, + "ram_used_gb": 34.796974182128906, + "gpu_memory_used": 3977.0, + "relative_time": 18.157397270202637 + }, + { + "timestamp": "2025-01-03T17:45:29.959510", + "cpu_percent": 10.72, + "ram_percent": 54.7, + "ram_used_gb": 34.819969177246094, + "gpu_memory_used": 3991.0, + "relative_time": 19.22814679145813 + }, + { + "timestamp": "2025-01-03T17:45:31.033262", + "cpu_percent": 17.95, + "ram_percent": 55.0, + "ram_used_gb": 34.9871711730957, + "gpu_memory_used": 3995.0, + "relative_time": 20.29205060005188 + }, + { + "timestamp": "2025-01-03T17:45:32.091757", + "cpu_percent": 19.11, + "ram_percent": 55.0, + "ram_used_gb": 35.0067138671875, + "gpu_memory_used": 3995.0, + "relative_time": 21.353832006454468 + }, + { + "timestamp": "2025-01-03T17:45:33.156831", + "cpu_percent": 32.93, + "ram_percent": 55.1, + "ram_used_gb": 35.05879211425781, + "gpu_memory_used": 3995.0, + "relative_time": 22.416496992111206 + }, + { + "timestamp": "2025-01-03T17:45:34.217136", + "cpu_percent": 12.59, + "ram_percent": 55.2, + "ram_used_gb": 35.10686111450195, + "gpu_memory_used": 3994.0, + "relative_time": 23.476072549819946 + }, + { + "timestamp": "2025-01-03T17:45:35.275577", + "cpu_percent": 30.79, + "ram_percent": 55.4, + "ram_used_gb": 35.22132110595703, + "gpu_memory_used": 3989.0, + "relative_time": 24.564188957214355 + }, + { + "timestamp": "2025-01-03T17:45:36.365095", + "cpu_percent": 13.36, + "ram_percent": 55.2, + "ram_used_gb": 35.08255386352539, + "gpu_memory_used": 4000.0, + "relative_time": 25.64090871810913 + }, + { + "timestamp": "2025-01-03T17:45:37.451539", + "cpu_percent": 14.94, + "ram_percent": 55.2, + "ram_used_gb": 35.118614196777344, + "gpu_memory_used": 4000.0, + "relative_time": 26.71500325202942 + }, + { + "timestamp": "2025-01-03T17:45:38.525364", + "cpu_percent": 12.76, + "ram_percent": 55.4, + "ram_used_gb": 35.221614837646484, + "gpu_memory_used": 3999.0, + "relative_time": 27.806236505508423 + }, + { + "timestamp": "2025-01-03T17:45:39.616790", + "cpu_percent": 16.11, + "ram_percent": 55.4, + "ram_used_gb": 35.2247200012207, + "gpu_memory_used": 3999.0, + "relative_time": 28.875747203826904 + }, + { + "timestamp": "2025-01-03T17:45:40.675234", + "cpu_percent": 14.96, + "ram_percent": 55.4, + "ram_used_gb": 35.21339416503906, + "gpu_memory_used": 3999.0, + "relative_time": 29.94703769683838 + }, + { + "timestamp": "2025-01-03T17:45:41.746176", + "cpu_percent": 10.99, + "ram_percent": 55.4, + "ram_used_gb": 35.260677337646484, + "gpu_memory_used": 3994.0, + "relative_time": 31.006144046783447 + }, + { + "timestamp": "2025-01-03T17:45:42.807809", + "cpu_percent": 13.15, + "ram_percent": 55.5, + "ram_used_gb": 35.299591064453125, + "gpu_memory_used": 3994.0, + "relative_time": 32.0741171836853 + }, + { + "timestamp": "2025-01-03T17:45:43.879826", + "cpu_percent": 12.74, + "ram_percent": 55.6, + "ram_used_gb": 35.34665298461914, + "gpu_memory_used": 3994.0, + "relative_time": 33.14525270462036 + }, + { + "timestamp": "2025-01-03T17:45:44.954413", + "cpu_percent": 12.11, + "ram_percent": 55.6, + "ram_used_gb": 35.34089660644531, + "gpu_memory_used": 3990.0, + "relative_time": 34.21659064292908 + }, + { + "timestamp": "2025-01-03T17:45:46.025229", + "cpu_percent": 13.02, + "ram_percent": 55.6, + "ram_used_gb": 35.37482833862305, + "gpu_memory_used": 3991.0, + "relative_time": 35.28446078300476 + }, + { + "timestamp": "2025-01-03T17:45:47.085470", + "cpu_percent": 13.53, + "ram_percent": 55.6, + "ram_used_gb": 35.392356872558594, + "gpu_memory_used": 3988.0, + "relative_time": 36.34242486953735 + }, + { + "timestamp": "2025-01-03T17:45:48.155295", + "cpu_percent": 15.0, + "ram_percent": 55.7, + "ram_used_gb": 35.449764251708984, + "gpu_memory_used": 3987.0, + "relative_time": 37.418004512786865 + }, + { + "timestamp": "2025-01-03T17:45:49.218400", + "cpu_percent": 13.84, + "ram_percent": 55.8, + "ram_used_gb": 35.468841552734375, + "gpu_memory_used": 3986.0, + "relative_time": 38.48085808753967 + }, + { + "timestamp": "2025-01-03T17:45:50.281360", + "cpu_percent": 13.25, + "ram_percent": 55.8, + "ram_used_gb": 35.491825103759766, + "gpu_memory_used": 3987.0, + "relative_time": 39.5399751663208 + }, + { + "timestamp": "2025-01-03T17:45:51.343810", + "cpu_percent": 10.34, + "ram_percent": 55.8, + "ram_used_gb": 35.51161193847656, + "gpu_memory_used": 3985.0, + "relative_time": 40.60230302810669 + }, + { + "timestamp": "2025-01-03T17:45:52.402527", + "cpu_percent": 12.56, + "ram_percent": 55.9, + "ram_used_gb": 35.57502365112305, + "gpu_memory_used": 3984.0, + "relative_time": 41.660725116729736 + }, + { + "timestamp": "2025-01-03T17:45:53.460932", + "cpu_percent": 12.04, + "ram_percent": 56.0, + "ram_used_gb": 35.61081314086914, + "gpu_memory_used": 3978.0, + "relative_time": 42.71787190437317 + }, + { + "timestamp": "2025-01-03T17:45:54.521959", + "cpu_percent": 10.13, + "ram_percent": 56.3, + "ram_used_gb": 35.822574615478516, + "gpu_memory_used": 3978.0, + "relative_time": 43.783926010131836 + }, + { + "timestamp": "2025-01-03T17:45:55.583212", + "cpu_percent": 28.17, + "ram_percent": 56.3, + "ram_used_gb": 35.78395462036133, + "gpu_memory_used": 3976.0, + "relative_time": 44.858543157577515 + }, + { + "timestamp": "2025-01-03T17:45:56.657026", + "cpu_percent": 16.61, + "ram_percent": 56.3, + "ram_used_gb": 35.7921028137207, + "gpu_memory_used": 3984.0, + "relative_time": 45.918612003326416 + }, + { + "timestamp": "2025-01-03T17:45:57.716203", + "cpu_percent": 15.03, + "ram_percent": 56.3, + "ram_used_gb": 35.79140853881836, + "gpu_memory_used": 3984.0, + "relative_time": 46.97588872909546 + }, + { + "timestamp": "2025-01-03T17:45:58.775392", + "cpu_percent": 14.81, + "ram_percent": 56.3, + "ram_used_gb": 35.80635452270508, + "gpu_memory_used": 3984.0, + "relative_time": 48.03421711921692 + }, + { + "timestamp": "2025-01-03T17:45:59.834277", + "cpu_percent": 15.06, + "ram_percent": 56.3, + "ram_used_gb": 35.81984329223633, + "gpu_memory_used": 3984.0, + "relative_time": 49.0965371131897 + }, + { + "timestamp": "2025-01-03T17:46:00.896761", + "cpu_percent": 19.76, + "ram_percent": 56.3, + "ram_used_gb": 35.7983512878418, + "gpu_memory_used": 3989.0, + "relative_time": 50.177143812179565 + }, + { + "timestamp": "2025-01-03T17:46:01.981868", + "cpu_percent": 17.32, + "ram_percent": 56.3, + "ram_used_gb": 35.81730270385742, + "gpu_memory_used": 3990.0, + "relative_time": 51.242098331451416 + }, + { + "timestamp": "2025-01-03T17:46:03.046930", + "cpu_percent": 19.8, + "ram_percent": 56.5, + "ram_used_gb": 35.92729949951172, + "gpu_memory_used": 3990.0, + "relative_time": 52.3223512172699 + }, + { + "timestamp": "2025-01-03T17:46:04.122311", + "cpu_percent": 20.91, + "ram_percent": 56.5, + "ram_used_gb": 35.949684143066406, + "gpu_memory_used": 3991.0, + "relative_time": 53.3851900100708 + }, + { + "timestamp": "2025-01-03T17:46:05.182768", + "cpu_percent": 17.39, + "ram_percent": 56.5, + "ram_used_gb": 35.94847869873047, + "gpu_memory_used": 3991.0, + "relative_time": 54.45881199836731 + }, + { + "timestamp": "2025-01-03T17:46:06.257550", + "cpu_percent": 16.64, + "ram_percent": 56.5, + "ram_used_gb": 35.9198112487793, + "gpu_memory_used": 3989.0, + "relative_time": 55.51820731163025 + }, + { + "timestamp": "2025-01-03T17:46:07.317263", + "cpu_percent": 15.99, + "ram_percent": 56.3, + "ram_used_gb": 35.82686233520508, + "gpu_memory_used": 3989.0, + "relative_time": 56.59837555885315 + }, + { + "timestamp": "2025-01-03T17:46:08.409244", + "cpu_percent": 15.11, + "ram_percent": 56.4, + "ram_used_gb": 35.852657318115234, + "gpu_memory_used": 3988.0, + "relative_time": 57.669328927993774 + }, + { + "timestamp": "2025-01-03T17:46:09.473703", + "cpu_percent": 18.54, + "ram_percent": 56.4, + "ram_used_gb": 35.889339447021484, + "gpu_memory_used": 3979.0, + "relative_time": 58.76238036155701 + }, + { + "timestamp": "2025-01-03T17:46:10.562180", + "cpu_percent": 15.7, + "ram_percent": 56.4, + "ram_used_gb": 35.90079879760742, + "gpu_memory_used": 3975.0, + "relative_time": 59.82209253311157 + }, + { + "timestamp": "2025-01-03T17:46:11.634373", + "cpu_percent": 16.25, + "ram_percent": 56.5, + "ram_used_gb": 35.94197082519531, + "gpu_memory_used": 3976.0, + "relative_time": 60.91385841369629 + }, + { + "timestamp": "2025-01-03T17:46:12.723458", + "cpu_percent": 16.98, + "ram_percent": 56.6, + "ram_used_gb": 35.99095153808594, + "gpu_memory_used": 3976.0, + "relative_time": 61.981855154037476 + }, + { + "timestamp": "2025-01-03T17:46:13.781955", + "cpu_percent": 15.59, + "ram_percent": 56.6, + "ram_used_gb": 36.00953674316406, + "gpu_memory_used": 3976.0, + "relative_time": 63.04051613807678 + }, + { + "timestamp": "2025-01-03T17:46:14.852706", + "cpu_percent": 13.16, + "ram_percent": 56.7, + "ram_used_gb": 36.050899505615234, + "gpu_memory_used": 3976.0, + "relative_time": 64.11573505401611 + }, + { + "timestamp": "2025-01-03T17:46:15.927719", + "cpu_percent": 12.34, + "ram_percent": 56.7, + "ram_used_gb": 36.07988739013672, + "gpu_memory_used": 3976.0, + "relative_time": 65.18661308288574 + }, + { + "timestamp": "2025-01-03T17:46:16.999292", + "cpu_percent": 12.34, + "ram_percent": 56.8, + "ram_used_gb": 36.099937438964844, + "gpu_memory_used": 3976.0, + "relative_time": 66.25790786743164 + }, + { + "timestamp": "2025-01-03T17:46:18.058608", + "cpu_percent": 11.74, + "ram_percent": 56.8, + "ram_used_gb": 36.14547348022461, + "gpu_memory_used": 3975.0, + "relative_time": 67.31676268577576 + }, + { + "timestamp": "2025-01-03T17:46:19.122597", + "cpu_percent": 12.63, + "ram_percent": 56.9, + "ram_used_gb": 36.177284240722656, + "gpu_memory_used": 3974.0, + "relative_time": 68.3815085887909 + }, + { + "timestamp": "2025-01-03T17:46:20.182864", + "cpu_percent": 9.65, + "ram_percent": 56.9, + "ram_used_gb": 36.216495513916016, + "gpu_memory_used": 3973.0, + "relative_time": 69.44507431983948 + }, + { + "timestamp": "2025-01-03T17:46:21.244696", + "cpu_percent": 10.38, + "ram_percent": 57.4, + "ram_used_gb": 36.51596450805664, + "gpu_memory_used": 3973.0, + "relative_time": 70.51762080192566 + }, + { + "timestamp": "2025-01-03T17:46:22.448455", + "cpu_percent": 9.24, + "ram_percent": 57.5, + "ram_used_gb": 36.56745529174805, + "gpu_memory_used": 3974.0, + "relative_time": 71.72753357887268 + } + ], + "test_duration": 74.18872809410095 +} \ No newline at end of file diff --git a/examples/assorted_checks/benchmarks/output_data/gpu_benchmark_stats_rtf.txt b/examples/assorted_checks/benchmarks/output_data/gpu_benchmark_stats_rtf.txt new file mode 100644 index 0000000..b045833 --- /dev/null +++ b/examples/assorted_checks/benchmarks/output_data/gpu_benchmark_stats_rtf.txt @@ -0,0 +1,23 @@ +=== Benchmark Statistics (with correct RTF) === + +Total tokens processed: 8150 +Total audio generated (s): 2549.70 +Total test duration (s): 70.70 +Average processing rate (tokens/s): 120.20 +Average RTF: 0.03 +Average Real Time Speed: 36.36 + +=== Per-chunk Stats === + +Average chunk size (tokens): 1018.75 +Min chunk size (tokens): 150 +Max chunk size (tokens): 3000 +Average processing time (s): 8.75 +Average output length (s): 318.71 + +=== Performance Ranges === + +Processing rate range (tokens/s): 107.14 - 145.63 +RTF range: 0.02x - 0.03x +Real Time Speed range: 33.33x - 50.00x + diff --git a/examples/assorted_checks/benchmarks/output_plots/cpu_processing_time_rtf.png b/examples/assorted_checks/benchmarks/output_plots/cpu_processing_time_rtf.png new file mode 100644 index 0000000..ee7f801 Binary files /dev/null and b/examples/assorted_checks/benchmarks/output_plots/cpu_processing_time_rtf.png differ diff --git a/examples/assorted_checks/benchmarks/output_plots/cpu_realtime_factor_rtf.png b/examples/assorted_checks/benchmarks/output_plots/cpu_realtime_factor_rtf.png new file mode 100644 index 0000000..a18521d Binary files /dev/null and b/examples/assorted_checks/benchmarks/output_plots/cpu_realtime_factor_rtf.png differ diff --git a/examples/assorted_checks/benchmarks/output_plots/cpu_system_usage_rtf.png b/examples/assorted_checks/benchmarks/output_plots/cpu_system_usage_rtf.png new file mode 100644 index 0000000..03eca18 Binary files /dev/null and b/examples/assorted_checks/benchmarks/output_plots/cpu_system_usage_rtf.png differ diff --git a/examples/benchmarks/format_comparison.png b/examples/assorted_checks/benchmarks/output_plots/format_comparison.png similarity index 100% rename from examples/benchmarks/format_comparison.png rename to examples/assorted_checks/benchmarks/output_plots/format_comparison.png diff --git a/examples/assorted_checks/benchmarks/output_plots/gpu_processing_time_rtf.png b/examples/assorted_checks/benchmarks/output_plots/gpu_processing_time_rtf.png new file mode 100644 index 0000000..476122e Binary files /dev/null and b/examples/assorted_checks/benchmarks/output_plots/gpu_processing_time_rtf.png differ diff --git a/examples/assorted_checks/benchmarks/output_plots/gpu_realtime_factor_rtf.png b/examples/assorted_checks/benchmarks/output_plots/gpu_realtime_factor_rtf.png new file mode 100644 index 0000000..2819b09 Binary files /dev/null and b/examples/assorted_checks/benchmarks/output_plots/gpu_realtime_factor_rtf.png differ diff --git a/examples/assorted_checks/benchmarks/output_plots/gpu_system_usage_rtf.png b/examples/assorted_checks/benchmarks/output_plots/gpu_system_usage_rtf.png new file mode 100644 index 0000000..4f8a1b5 Binary files /dev/null and b/examples/assorted_checks/benchmarks/output_plots/gpu_system_usage_rtf.png differ diff --git a/examples/benchmarks/gpu_usage.png b/examples/assorted_checks/benchmarks/output_plots/gpu_usage.png similarity index 100% rename from examples/benchmarks/gpu_usage.png rename to examples/assorted_checks/benchmarks/output_plots/gpu_usage.png diff --git a/examples/benchmarks/the_time_machine_hg_wells.txt b/examples/assorted_checks/benchmarks/the_time_machine_hg_wells.txt similarity index 100% rename from examples/benchmarks/the_time_machine_hg_wells.txt rename to examples/assorted_checks/benchmarks/the_time_machine_hg_wells.txt diff --git a/examples/test_analyze_combined_voices.py b/examples/assorted_checks/test_combinations/test_analyze_combined_voices.py similarity index 99% rename from examples/test_analyze_combined_voices.py rename to examples/assorted_checks/test_combinations/test_analyze_combined_voices.py index 8db7865..ec280e2 100644 --- a/examples/test_analyze_combined_voices.py +++ b/examples/assorted_checks/test_combinations/test_analyze_combined_voices.py @@ -332,8 +332,8 @@ def main(): ) parser.add_argument("--url", default="http://localhost:8880", help="API base URL") parser.add_argument( - "--output-dir", - default="examples/output", + "--output-dir", + default="examples/assorted_checks/test_combinations/output", help="Output directory for audio files", ) args = parser.parse_args() diff --git a/examples/test_audio_formats.py b/examples/assorted_checks/test_formats/test_audio_formats.py similarity index 100% rename from examples/test_audio_formats.py rename to examples/assorted_checks/test_formats/test_audio_formats.py diff --git a/examples/test_openai_tts.py b/examples/assorted_checks/test_openai/test_openai_tts.py similarity index 100% rename from examples/test_openai_tts.py rename to examples/assorted_checks/test_openai/test_openai_tts.py diff --git a/examples/test_all_voices.py b/examples/assorted_checks/test_voices/test_all_voices.py similarity index 100% rename from examples/test_all_voices.py rename to examples/assorted_checks/test_voices/test_all_voices.py diff --git a/examples/benchmarks/analysis_comparison.png b/examples/benchmarks/analysis_comparison.png deleted file mode 100644 index 87a6d13..0000000 Binary files a/examples/benchmarks/analysis_comparison.png and /dev/null differ diff --git a/examples/benchmarks/benchmark_results.json b/examples/benchmarks/benchmark_results.json deleted file mode 100644 index 373cebe..0000000 --- a/examples/benchmarks/benchmark_results.json +++ /dev/null @@ -1,531 +0,0 @@ -{ - "results": [ - { - "tokens": 100, - "processing_time": 8.54442310333252, - "output_length": 31.15, - "realtime_factor": 3.6456527987068887, - "elapsed_time": 8.720048666000366 - }, - { - "tokens": 200, - "processing_time": 1.3838517665863037, - "output_length": 62.6, - "realtime_factor": 45.236058883981606, - "elapsed_time": 10.258155345916748 - }, - { - "tokens": 300, - "processing_time": 2.2024788856506348, - "output_length": 96.325, - "realtime_factor": 43.73481200095347, - "elapsed_time": 12.594647407531738 - }, - { - "tokens": 400, - "processing_time": 3.175424098968506, - "output_length": 128.55, - "realtime_factor": 40.48278150995886, - "elapsed_time": 16.005898475646973 - }, - { - "tokens": 500, - "processing_time": 3.205301523208618, - "output_length": 158.55, - "realtime_factor": 49.46492517224587, - "elapsed_time": 19.377076625823975 - }, - { - "tokens": 600, - "processing_time": 3.9976348876953125, - "output_length": 189.225, - "realtime_factor": 47.33423769700254, - "elapsed_time": 23.568575859069824 - }, - { - "tokens": 700, - "processing_time": 4.98036003112793, - "output_length": 222.05, - "realtime_factor": 44.58513011351734, - "elapsed_time": 28.767319917678833 - }, - { - "tokens": 800, - "processing_time": 5.156893491744995, - "output_length": 253.825, - "realtime_factor": 49.22052402406907, - "elapsed_time": 34.1369092464447 - }, - { - "tokens": 900, - "processing_time": 5.8110880851745605, - "output_length": 283.75, - "realtime_factor": 48.82906537312906, - "elapsed_time": 40.16419458389282 - }, - { - "tokens": 1000, - "processing_time": 6.686216354370117, - "output_length": 315.45, - "realtime_factor": 47.17914935460046, - "elapsed_time": 47.11375427246094 - }, - { - "tokens": 2000, - "processing_time": 13.290695905685425, - "output_length": 624.925, - "realtime_factor": 47.01973504131358, - "elapsed_time": 60.842002630233765 - }, - { - "tokens": 3000, - "processing_time": 20.058005571365356, - "output_length": 932.05, - "realtime_factor": 46.46773063671828, - "elapsed_time": 81.50969815254211 - }, - { - "tokens": 4000, - "processing_time": 26.38338828086853, - "output_length": 1222.975, - "realtime_factor": 46.353978002394015, - "elapsed_time": 108.76348638534546 - }, - { - "tokens": 5000, - "processing_time": 32.472310066223145, - "output_length": 1525.15, - "realtime_factor": 46.967708699801484, - "elapsed_time": 142.2994668483734 - }, - { - "tokens": 6000, - "processing_time": 42.67592263221741, - "output_length": 1837.525, - "realtime_factor": 43.0576514030137, - "elapsed_time": 186.26759266853333 - }, - { - "tokens": 7000, - "processing_time": 51.601537466049194, - "output_length": 2146.875, - "realtime_factor": 41.60486499869347, - "elapsed_time": 239.59922289848328 - }, - { - "tokens": 8000, - "processing_time": 51.86434292793274, - "output_length": 2458.425, - "realtime_factor": 47.401063258741466, - "elapsed_time": 293.4462616443634 - }, - { - "tokens": 9000, - "processing_time": 60.4497971534729, - "output_length": 2772.1, - "realtime_factor": 45.857887545297416, - "elapsed_time": 356.02399826049805 - }, - { - "tokens": 10000, - "processing_time": 71.75962543487549, - "output_length": 3085.625, - "realtime_factor": 42.99945800024164, - "elapsed_time": 430.50863671302795 - }, - { - "tokens": 11000, - "processing_time": 96.66409230232239, - "output_length": 3389.3, - "realtime_factor": 35.062657904030935, - "elapsed_time": 529.3296246528625 - }, - { - "tokens": 12000, - "processing_time": 85.70126295089722, - "output_length": 3703.175, - "realtime_factor": 43.21027336693678, - "elapsed_time": 618.0248212814331 - }, - { - "tokens": 13000, - "processing_time": 97.2874686717987, - "output_length": 4030.825, - "realtime_factor": 41.43210893479068, - "elapsed_time": 717.9070522785187 - }, - { - "tokens": 14000, - "processing_time": 105.1045708656311, - "output_length": 4356.775, - "realtime_factor": 41.451812838566596, - "elapsed_time": 826.1140224933624 - }, - { - "tokens": 15000, - "processing_time": 111.0716404914856, - "output_length": 4663.325, - "realtime_factor": 41.984839508672565, - "elapsed_time": 940.0645899772644 - }, - { - "tokens": 16000, - "processing_time": 116.61742973327637, - "output_length": 4978.65, - "realtime_factor": 42.692160266154104, - "elapsed_time": 1061.1957621574402 - } - ], - "system_metrics": [ - { - "timestamp": "2024-12-31T03:12:36.009478", - "cpu_percent": 8.1, - "ram_percent": 66.8, - "ram_used_gb": 42.47850799560547, - "gpu_memory_used": 2124.0 - }, - { - "timestamp": "2024-12-31T03:12:44.639678", - "cpu_percent": 7.7, - "ram_percent": 69.1, - "ram_used_gb": 43.984352111816406, - "gpu_memory_used": 3486.0 - }, - { - "timestamp": "2024-12-31T03:12:44.731107", - "cpu_percent": 8.3, - "ram_percent": 69.1, - "ram_used_gb": 43.97468948364258, - "gpu_memory_used": 3484.0 - }, - { - "timestamp": "2024-12-31T03:12:46.189723", - "cpu_percent": 14.2, - "ram_percent": 69.1, - "ram_used_gb": 43.98275375366211, - "gpu_memory_used": 3697.0 - }, - { - "timestamp": "2024-12-31T03:12:46.265437", - "cpu_percent": 4.7, - "ram_percent": 69.1, - "ram_used_gb": 43.982975006103516, - "gpu_memory_used": 3697.0 - }, - { - "timestamp": "2024-12-31T03:12:48.536216", - "cpu_percent": 12.5, - "ram_percent": 69.0, - "ram_used_gb": 43.86142349243164, - "gpu_memory_used": 3697.0 - }, - { - "timestamp": "2024-12-31T03:12:48.603827", - "cpu_percent": 6.2, - "ram_percent": 69.0, - "ram_used_gb": 43.8692626953125, - "gpu_memory_used": 3694.0 - }, - { - "timestamp": "2024-12-31T03:12:51.905764", - "cpu_percent": 14.2, - "ram_percent": 69.1, - "ram_used_gb": 43.93961715698242, - "gpu_memory_used": 3690.0 - }, - { - "timestamp": "2024-12-31T03:12:52.028178", - "cpu_percent": 26.0, - "ram_percent": 69.1, - "ram_used_gb": 43.944759368896484, - "gpu_memory_used": 3690.0 - }, - { - "timestamp": "2024-12-31T03:12:55.320709", - "cpu_percent": 13.2, - "ram_percent": 69.1, - "ram_used_gb": 43.943058013916016, - "gpu_memory_used": 3685.0 - }, - { - "timestamp": "2024-12-31T03:12:55.386582", - "cpu_percent": 3.2, - "ram_percent": 69.1, - "ram_used_gb": 43.9305419921875, - "gpu_memory_used": 3685.0 - }, - { - "timestamp": "2024-12-31T03:12:59.492304", - "cpu_percent": 15.6, - "ram_percent": 69.1, - "ram_used_gb": 43.964195251464844, - "gpu_memory_used": 4053.0 - }, - { - "timestamp": "2024-12-31T03:12:59.586143", - "cpu_percent": 2.1, - "ram_percent": 69.1, - "ram_used_gb": 43.9642448425293, - "gpu_memory_used": 4053.0 - }, - { - "timestamp": "2024-12-31T03:13:04.705286", - "cpu_percent": 12.0, - "ram_percent": 69.2, - "ram_used_gb": 43.992374420166016, - "gpu_memory_used": 4059.0 - }, - { - "timestamp": "2024-12-31T03:13:04.779475", - "cpu_percent": 4.7, - "ram_percent": 69.2, - "ram_used_gb": 43.9922981262207, - "gpu_memory_used": 4059.0 - }, - { - "timestamp": "2024-12-31T03:13:10.063292", - "cpu_percent": 12.4, - "ram_percent": 69.2, - "ram_used_gb": 44.004146575927734, - "gpu_memory_used": 4041.0 - }, - { - "timestamp": "2024-12-31T03:13:10.155395", - "cpu_percent": 6.8, - "ram_percent": 69.2, - "ram_used_gb": 44.004215240478516, - "gpu_memory_used": 4041.0 - }, - { - "timestamp": "2024-12-31T03:13:16.097887", - "cpu_percent": 13.1, - "ram_percent": 69.2, - "ram_used_gb": 44.0260009765625, - "gpu_memory_used": 4042.0 - }, - { - "timestamp": "2024-12-31T03:13:16.171478", - "cpu_percent": 4.5, - "ram_percent": 69.2, - "ram_used_gb": 44.02027130126953, - "gpu_memory_used": 4042.0 - }, - { - "timestamp": "2024-12-31T03:13:23.044945", - "cpu_percent": 12.6, - "ram_percent": 69.2, - "ram_used_gb": 44.03746795654297, - "gpu_memory_used": 4044.0 - }, - { - "timestamp": "2024-12-31T03:13:23.127442", - "cpu_percent": 8.3, - "ram_percent": 69.2, - "ram_used_gb": 44.0373420715332, - "gpu_memory_used": 4044.0 - }, - { - "timestamp": "2024-12-31T03:13:36.780309", - "cpu_percent": 12.5, - "ram_percent": 69.2, - "ram_used_gb": 44.00790786743164, - "gpu_memory_used": 4034.0 - }, - { - "timestamp": "2024-12-31T03:13:36.853474", - "cpu_percent": 6.2, - "ram_percent": 69.2, - "ram_used_gb": 44.00779724121094, - "gpu_memory_used": 4034.0 - }, - { - "timestamp": "2024-12-31T03:13:57.449274", - "cpu_percent": 12.4, - "ram_percent": 69.2, - "ram_used_gb": 44.0432243347168, - "gpu_memory_used": 4034.0 - }, - { - "timestamp": "2024-12-31T03:13:57.524592", - "cpu_percent": 6.2, - "ram_percent": 69.2, - "ram_used_gb": 44.03204345703125, - "gpu_memory_used": 4034.0 - }, - { - "timestamp": "2024-12-31T03:14:24.698822", - "cpu_percent": 13.4, - "ram_percent": 69.5, - "ram_used_gb": 44.18327331542969, - "gpu_memory_used": 4480.0 - }, - { - "timestamp": "2024-12-31T03:14:24.783683", - "cpu_percent": 4.2, - "ram_percent": 69.5, - "ram_used_gb": 44.182212829589844, - "gpu_memory_used": 4480.0 - }, - { - "timestamp": "2024-12-31T03:14:58.242642", - "cpu_percent": 12.8, - "ram_percent": 69.5, - "ram_used_gb": 44.20225524902344, - "gpu_memory_used": 4476.0 - }, - { - "timestamp": "2024-12-31T03:14:58.310907", - "cpu_percent": 2.9, - "ram_percent": 69.5, - "ram_used_gb": 44.19659423828125, - "gpu_memory_used": 4476.0 - }, - { - "timestamp": "2024-12-31T03:15:42.196813", - "cpu_percent": 14.3, - "ram_percent": 69.9, - "ram_used_gb": 44.43781661987305, - "gpu_memory_used": 4494.0 - }, - { - "timestamp": "2024-12-31T03:15:42.288427", - "cpu_percent": 13.7, - "ram_percent": 69.9, - "ram_used_gb": 44.439701080322266, - "gpu_memory_used": 4494.0 - }, - { - "timestamp": "2024-12-31T03:16:35.483849", - "cpu_percent": 14.7, - "ram_percent": 65.0, - "ram_used_gb": 41.35385513305664, - "gpu_memory_used": 4506.0 - }, - { - "timestamp": "2024-12-31T03:16:35.626628", - "cpu_percent": 32.9, - "ram_percent": 65.0, - "ram_used_gb": 41.34442138671875, - "gpu_memory_used": 4506.0 - }, - { - "timestamp": "2024-12-31T03:17:29.378353", - "cpu_percent": 13.4, - "ram_percent": 64.3, - "ram_used_gb": 40.8721809387207, - "gpu_memory_used": 4485.0 - }, - { - "timestamp": "2024-12-31T03:17:29.457464", - "cpu_percent": 5.1, - "ram_percent": 64.3, - "ram_used_gb": 40.875389099121094, - "gpu_memory_used": 4485.0 - }, - { - "timestamp": "2024-12-31T03:18:31.955862", - "cpu_percent": 14.3, - "ram_percent": 65.0, - "ram_used_gb": 41.360206604003906, - "gpu_memory_used": 4484.0 - }, - { - "timestamp": "2024-12-31T03:18:32.038999", - "cpu_percent": 12.5, - "ram_percent": 65.0, - "ram_used_gb": 41.37223434448242, - "gpu_memory_used": 4484.0 - }, - { - "timestamp": "2024-12-31T03:19:46.454105", - "cpu_percent": 13.9, - "ram_percent": 65.3, - "ram_used_gb": 41.562198638916016, - "gpu_memory_used": 4487.0 - }, - { - "timestamp": "2024-12-31T03:19:46.524303", - "cpu_percent": 6.8, - "ram_percent": 65.3, - "ram_used_gb": 41.56681442260742, - "gpu_memory_used": 4487.0 - }, - { - "timestamp": "2024-12-31T03:21:25.251452", - "cpu_percent": 23.7, - "ram_percent": 62.0, - "ram_used_gb": 39.456459045410156, - "gpu_memory_used": 4488.0 - }, - { - "timestamp": "2024-12-31T03:21:25.348643", - "cpu_percent": 2.9, - "ram_percent": 62.0, - "ram_used_gb": 39.454288482666016, - "gpu_memory_used": 4487.0 - }, - { - "timestamp": "2024-12-31T03:22:53.939896", - "cpu_percent": 12.9, - "ram_percent": 62.1, - "ram_used_gb": 39.50320053100586, - "gpu_memory_used": 4488.0 - }, - { - "timestamp": "2024-12-31T03:22:54.041607", - "cpu_percent": 8.3, - "ram_percent": 62.1, - "ram_used_gb": 39.49895095825195, - "gpu_memory_used": 4488.0 - }, - { - "timestamp": "2024-12-31T03:24:33.835432", - "cpu_percent": 12.9, - "ram_percent": 62.3, - "ram_used_gb": 39.647212982177734, - "gpu_memory_used": 4503.0 - }, - { - "timestamp": "2024-12-31T03:24:33.923914", - "cpu_percent": 7.6, - "ram_percent": 62.3, - "ram_used_gb": 39.64302062988281, - "gpu_memory_used": 4503.0 - }, - { - "timestamp": "2024-12-31T03:26:22.021598", - "cpu_percent": 12.9, - "ram_percent": 58.4, - "ram_used_gb": 37.162540435791016, - "gpu_memory_used": 4491.0 - }, - { - "timestamp": "2024-12-31T03:26:22.142138", - "cpu_percent": 12.0, - "ram_percent": 58.4, - "ram_used_gb": 37.162010192871094, - "gpu_memory_used": 4487.0 - }, - { - "timestamp": "2024-12-31T03:28:15.970365", - "cpu_percent": 15.0, - "ram_percent": 58.2, - "ram_used_gb": 37.04011535644531, - "gpu_memory_used": 4481.0 - }, - { - "timestamp": "2024-12-31T03:28:16.096459", - "cpu_percent": 12.4, - "ram_percent": 58.2, - "ram_used_gb": 37.035972595214844, - "gpu_memory_used": 4473.0 - }, - { - "timestamp": "2024-12-31T03:30:17.092257", - "cpu_percent": 12.4, - "ram_percent": 58.4, - "ram_used_gb": 37.14639663696289, - "gpu_memory_used": 4459.0 - } - ] -} \ No newline at end of file diff --git a/examples/benchmarks/benchmark_stats.txt b/examples/benchmarks/benchmark_stats.txt deleted file mode 100644 index c2a9b02..0000000 --- a/examples/benchmarks/benchmark_stats.txt +++ /dev/null @@ -1,19 +0,0 @@ -=== Benchmark Statistics === - -Overall Stats: -Total tokens processed: 140500 -Total audio generated: 43469.18s -Total test duration: 1061.20s -Average processing rate: 137.67 tokens/second -Average realtime factor: 42.93x - -Per-chunk Stats: -Average chunk size: 5620.00 tokens -Min chunk size: 100.00 tokens -Max chunk size: 16000.00 tokens -Average processing time: 41.13s -Average output length: 1738.77s - -Performance Ranges: -Processing rate range: 11.70 - 155.99 tokens/second -Realtime factor range: 3.65x - 49.46x diff --git a/examples/benchmarks/benchmark_tts.py b/examples/benchmarks/benchmark_tts.py deleted file mode 100644 index f17e6ee..0000000 --- a/examples/benchmarks/benchmark_tts.py +++ /dev/null @@ -1,406 +0,0 @@ -import os -import json -import time -import subprocess -from datetime import datetime - -import pandas as pd -import psutil -import seaborn as sns -import requests -import tiktoken -import scipy.io.wavfile as wavfile -import matplotlib.pyplot as plt - -enc = tiktoken.get_encoding("cl100k_base") - - -def setup_plot(fig, ax, title): - """Configure plot styling""" - # Improve grid - ax.grid(True, linestyle="--", alpha=0.3, color="#ffffff") - - # Set title and labels with better fonts - ax.set_title(title, pad=20, fontsize=16, fontweight="bold", color="#ffffff") - ax.set_xlabel(ax.get_xlabel(), fontsize=14, fontweight="medium", color="#ffffff") - ax.set_ylabel(ax.get_ylabel(), fontsize=14, fontweight="medium", color="#ffffff") - - # Improve tick labels - ax.tick_params(labelsize=12, colors="#ffffff") - - # Style spines - for spine in ax.spines.values(): - spine.set_color("#ffffff") - spine.set_alpha(0.3) - spine.set_linewidth(0.5) - - # Set background colors - ax.set_facecolor("#1a1a2e") - fig.patch.set_facecolor("#1a1a2e") - - return fig, ax - - -def get_text_for_tokens(text: str, num_tokens: int) -> str: - """Get a slice of text that contains exactly num_tokens tokens""" - tokens = enc.encode(text) - if num_tokens > len(tokens): - return text - return enc.decode(tokens[:num_tokens]) - - -def get_audio_length(audio_data: bytes) -> float: - """Get audio length in seconds from bytes data""" - # Save to a temporary file - temp_path = "examples/benchmarks/output/temp.wav" - os.makedirs(os.path.dirname(temp_path), exist_ok=True) - with open(temp_path, "wb") as f: - f.write(audio_data) - - # Read the audio file - try: - rate, data = wavfile.read(temp_path) - return len(data) / rate - finally: - # Clean up temp file - if os.path.exists(temp_path): - os.remove(temp_path) - - -def get_gpu_memory(): - """Get GPU memory usage using nvidia-smi""" - try: - result = subprocess.check_output( - ["nvidia-smi", "--query-gpu=memory.used", "--format=csv,nounits,noheader"] - ) - return float(result.decode("utf-8").strip()) - except (subprocess.CalledProcessError, FileNotFoundError): - return None - - -def get_system_metrics(): - """Get current system metrics""" - metrics = { - "timestamp": datetime.now().isoformat(), - "cpu_percent": psutil.cpu_percent(), - "ram_percent": psutil.virtual_memory().percent, - "ram_used_gb": psutil.virtual_memory().used / (1024**3), - } - - gpu_mem = get_gpu_memory() - if gpu_mem is not None: - metrics["gpu_memory_used"] = gpu_mem - - return metrics - - -def make_tts_request(text: str, timeout: int = 120) -> tuple[float, float]: - """Make TTS request using OpenAI-compatible endpoint and return processing time and output length""" - try: - start_time = time.time() - - # Make request to OpenAI-compatible endpoint - response = requests.post( - "http://localhost:8880/v1/audio/speech", - json={ - "model": "kokoro", - "input": text, - "voice": "af", - "response_format": "wav", - }, - timeout=timeout, - ) - response.raise_for_status() - - processing_time = time.time() - start_time - audio_length = get_audio_length(response.content) - - # Save the audio file - token_count = len(enc.encode(text)) - output_file = f"examples/benchmarks/output/chunk_{token_count}_tokens.wav" - os.makedirs(os.path.dirname(output_file), exist_ok=True) - with open(output_file, "wb") as f: - f.write(response.content) - print(f"Saved audio to {output_file}") - - return processing_time, audio_length - - except requests.exceptions.RequestException as e: - print(f"Error making request for text: {text[:50]}... Error: {str(e)}") - return None, None - except Exception as e: - print(f"Error processing text: {text[:50]}... Error: {str(e)}") - return None, None - - -def plot_system_metrics(metrics_data): - """Create plots for system metrics over time""" - df = pd.DataFrame(metrics_data) - df["timestamp"] = pd.to_datetime(df["timestamp"]) - elapsed_time = (df["timestamp"] - df["timestamp"].iloc[0]).dt.total_seconds() - - # Get baseline values (first measurement) - baseline_cpu = df["cpu_percent"].iloc[0] - baseline_ram = df["ram_used_gb"].iloc[0] - baseline_gpu = ( - df["gpu_memory_used"].iloc[0] / 1024 - if "gpu_memory_used" in df.columns - else None - ) # Convert MB to GB - - # Convert GPU memory to GB - if "gpu_memory_used" in df.columns: - df["gpu_memory_gb"] = df["gpu_memory_used"] / 1024 - - # Set plotting style - plt.style.use("dark_background") - - # Create figure with 3 subplots (or 2 if no GPU) - has_gpu = "gpu_memory_used" in df.columns - num_plots = 3 if has_gpu else 2 - fig, axes = plt.subplots(num_plots, 1, figsize=(15, 5 * num_plots)) - fig.patch.set_facecolor("#1a1a2e") - - # Apply rolling average for smoothing - window = min(5, len(df) // 2) # Smaller window for smoother lines - - # Plot 1: CPU Usage - smoothed_cpu = df["cpu_percent"].rolling(window=window, center=True).mean() - sns.lineplot( - x=elapsed_time, y=smoothed_cpu, ax=axes[0], color="#ff2a6d", linewidth=2 - ) - axes[0].axhline( - y=baseline_cpu, color="#05d9e8", linestyle="--", alpha=0.5, label="Baseline" - ) - axes[0].set_xlabel("Time (seconds)", fontsize=14) - axes[0].set_ylabel("CPU Usage (%)", fontsize=14) - axes[0].tick_params(labelsize=12) - axes[0].set_title("CPU Usage Over Time", pad=20, fontsize=16, fontweight="bold") - axes[0].set_ylim(0, max(df["cpu_percent"]) * 1.1) # Add 10% padding - axes[0].legend() - - # Plot 2: RAM Usage - smoothed_ram = df["ram_used_gb"].rolling(window=window, center=True).mean() - sns.lineplot( - x=elapsed_time, y=smoothed_ram, ax=axes[1], color="#05d9e8", linewidth=2 - ) - axes[1].axhline( - y=baseline_ram, color="#ff2a6d", linestyle="--", alpha=0.5, label="Baseline" - ) - axes[1].set_xlabel("Time (seconds)", fontsize=14) - axes[1].set_ylabel("RAM Usage (GB)", fontsize=14) - axes[1].tick_params(labelsize=12) - axes[1].set_title("RAM Usage Over Time", pad=20, fontsize=16, fontweight="bold") - axes[1].set_ylim(0, max(df["ram_used_gb"]) * 1.1) # Add 10% padding - axes[1].legend() - - # Plot 3: GPU Memory (if available) - if has_gpu: - smoothed_gpu = df["gpu_memory_gb"].rolling(window=window, center=True).mean() - sns.lineplot( - x=elapsed_time, y=smoothed_gpu, ax=axes[2], color="#ff2a6d", linewidth=2 - ) - axes[2].axhline( - y=baseline_gpu, color="#05d9e8", linestyle="--", alpha=0.5, label="Baseline" - ) - axes[2].set_xlabel("Time (seconds)", fontsize=14) - axes[2].set_ylabel("GPU Memory (GB)", fontsize=14) - axes[2].tick_params(labelsize=12) - axes[2].set_title( - "GPU Memory Usage Over Time", pad=20, fontsize=16, fontweight="bold" - ) - axes[2].set_ylim(0, max(df["gpu_memory_gb"]) * 1.1) # Add 10% padding - axes[2].legend() - - # Style all subplots - for ax in axes: - ax.grid(True, linestyle="--", alpha=0.3) - ax.set_facecolor("#1a1a2e") - for spine in ax.spines.values(): - spine.set_color("#ffffff") - spine.set_alpha(0.3) - - plt.tight_layout() - plt.savefig("examples/benchmarks/system_usage.png", dpi=300, bbox_inches="tight") - plt.close() - - -def main(): - # Create output directory - os.makedirs("examples/benchmarks/output", exist_ok=True) - - # Read input text - with open( - "examples/benchmarks/the_time_machine_hg_wells.txt", "r", encoding="utf-8" - ) as f: - text = f.read() - - # Get total tokens in file - total_tokens = len(enc.encode(text)) - print(f"Total tokens in file: {total_tokens}") - - # Generate token sizes with dense sampling at start and increasing intervals - dense_range = list(range(100, 1001, 100)) - current = max(dense_range) - large_range = [] - while current <= total_tokens: - large_range.append(current) - current += 1000 - - token_sizes = sorted(list(set(dense_range + large_range))) - print(f"Testing sizes: {token_sizes}") - - # Process chunks - results = [] - system_metrics = [] - test_start_time = time.time() - - for num_tokens in token_sizes: - # Get text slice with exact token count - chunk = get_text_for_tokens(text, num_tokens) - actual_tokens = len(enc.encode(chunk)) - - print(f"\nProcessing chunk with {actual_tokens} tokens:") - print(f"Text preview: {chunk[:100]}...") - - # Collect system metrics before processing - system_metrics.append(get_system_metrics()) - - processing_time, audio_length = make_tts_request(chunk) - if processing_time is None or audio_length is None: - print("Breaking loop due to error") - break - - # Collect system metrics after processing - system_metrics.append(get_system_metrics()) - - results.append( - { - "tokens": actual_tokens, - "processing_time": processing_time, - "output_length": audio_length, - "realtime_factor": audio_length / processing_time, - "elapsed_time": time.time() - test_start_time, - } - ) - - # Save intermediate results - with open("examples/benchmarks/benchmark_results.json", "w") as f: - json.dump( - {"results": results, "system_metrics": system_metrics}, f, indent=2 - ) - - # Create DataFrame and calculate stats - df = pd.DataFrame(results) - if df.empty: - print("No data to plot") - return - - # Calculate useful metrics - df["tokens_per_second"] = df["tokens"] / df["processing_time"] - - # Write detailed stats - with open("examples/benchmarks/benchmark_stats.txt", "w") as f: - f.write("=== Benchmark Statistics ===\n\n") - - f.write("Overall Stats:\n") - f.write(f"Total tokens processed: {df['tokens'].sum()}\n") - f.write(f"Total audio generated: {df['output_length'].sum():.2f}s\n") - f.write(f"Total test duration: {df['elapsed_time'].max():.2f}s\n") - f.write( - f"Average processing rate: {df['tokens_per_second'].mean():.2f} tokens/second\n" - ) - f.write(f"Average realtime factor: {df['realtime_factor'].mean():.2f}x\n\n") - - f.write("Per-chunk Stats:\n") - f.write(f"Average chunk size: {df['tokens'].mean():.2f} tokens\n") - f.write(f"Min chunk size: {df['tokens'].min():.2f} tokens\n") - f.write(f"Max chunk size: {df['tokens'].max():.2f} tokens\n") - f.write(f"Average processing time: {df['processing_time'].mean():.2f}s\n") - f.write(f"Average output length: {df['output_length'].mean():.2f}s\n\n") - - f.write("Performance Ranges:\n") - f.write( - f"Processing rate range: {df['tokens_per_second'].min():.2f} - {df['tokens_per_second'].max():.2f} tokens/second\n" - ) - f.write( - f"Realtime factor range: {df['realtime_factor'].min():.2f}x - {df['realtime_factor'].max():.2f}x\n" - ) - - # Set plotting style - plt.style.use("dark_background") - - # Plot 1: Processing Time vs Token Count - fig, ax = plt.subplots(figsize=(12, 8)) - sns.scatterplot( - data=df, x="tokens", y="processing_time", s=100, alpha=0.6, color="#ff2a6d" - ) - sns.regplot( - data=df, - x="tokens", - y="processing_time", - scatter=False, - color="#05d9e8", - line_kws={"linewidth": 2}, - ) - corr = df["tokens"].corr(df["processing_time"]) - plt.text( - 0.05, - 0.95, - f"Correlation: {corr:.2f}", - transform=ax.transAxes, - fontsize=10, - color="#ffffff", - bbox=dict(facecolor="#1a1a2e", edgecolor="#ffffff", alpha=0.7), - ) - setup_plot(fig, ax, "Processing Time vs Input Size") - ax.set_xlabel("Number of Input Tokens") - ax.set_ylabel("Processing Time (seconds)") - plt.savefig("examples/benchmarks/processing_time.png", dpi=300, bbox_inches="tight") - plt.close() - - # Plot 2: Realtime Factor vs Token Count - fig, ax = plt.subplots(figsize=(12, 8)) - sns.scatterplot( - data=df, x="tokens", y="realtime_factor", s=100, alpha=0.6, color="#ff2a6d" - ) - sns.regplot( - data=df, - x="tokens", - y="realtime_factor", - scatter=False, - color="#05d9e8", - line_kws={"linewidth": 2}, - ) - corr = df["tokens"].corr(df["realtime_factor"]) - plt.text( - 0.05, - 0.95, - f"Correlation: {corr:.2f}", - transform=ax.transAxes, - fontsize=10, - color="#ffffff", - bbox=dict(facecolor="#1a1a2e", edgecolor="#ffffff", alpha=0.7), - ) - setup_plot(fig, ax, "Realtime Factor vs Input Size") - ax.set_xlabel("Number of Input Tokens") - ax.set_ylabel("Realtime Factor (output length / processing time)") - plt.savefig("examples/benchmarks/realtime_factor.png", dpi=300, bbox_inches="tight") - plt.close() - - # Plot system metrics - plot_system_metrics(system_metrics) - - print("\nResults saved to:") - print("- examples/benchmarks/benchmark_results.json") - print("- examples/benchmarks/benchmark_stats.txt") - print("- examples/benchmarks/processing_time.png") - print("- examples/benchmarks/realtime_factor.png") - print("- examples/benchmarks/system_usage.png") - if any("gpu_memory_used" in m for m in system_metrics): - print("- examples/benchmarks/gpu_usage.png") - print("\nAudio files saved in examples/benchmarks/output/") - - -if __name__ == "__main__": - main() diff --git a/examples/benchmarks/benchmark_tts_rtf.py b/examples/benchmarks/benchmark_tts_rtf.py deleted file mode 100644 index 773f1d9..0000000 --- a/examples/benchmarks/benchmark_tts_rtf.py +++ /dev/null @@ -1,314 +0,0 @@ -import os -import json -import time -import subprocess -from datetime import datetime - -import pandas as pd -import psutil -import seaborn as sns -import requests -import tiktoken -import scipy.io.wavfile as wavfile -import matplotlib.pyplot as plt - -enc = tiktoken.get_encoding("cl100k_base") - - -def setup_plot(fig, ax, title): - """Configure plot styling""" - ax.grid(True, linestyle="--", alpha=0.3, color="#ffffff") - ax.set_title(title, pad=20, fontsize=16, fontweight="bold", color="#ffffff") - ax.set_xlabel(ax.get_xlabel(), fontsize=14, fontweight="medium", color="#ffffff") - ax.set_ylabel(ax.get_ylabel(), fontsize=14, fontweight="medium", color="#ffffff") - ax.tick_params(labelsize=12, colors="#ffffff") - - for spine in ax.spines.values(): - spine.set_color("#ffffff") - spine.set_alpha(0.3) - spine.set_linewidth(0.5) - - ax.set_facecolor("#1a1a2e") - fig.patch.set_facecolor("#1a1a2e") - return fig, ax - - -def get_text_for_tokens(text: str, num_tokens: int) -> str: - """Get a slice of text that contains exactly num_tokens tokens""" - tokens = enc.encode(text) - if num_tokens > len(tokens): - return text - return enc.decode(tokens[:num_tokens]) - - -def get_audio_length(audio_data: bytes) -> float: - """Get audio length in seconds from bytes data""" - temp_path = "examples/benchmarks/output/temp.wav" - os.makedirs(os.path.dirname(temp_path), exist_ok=True) - with open(temp_path, "wb") as f: - f.write(audio_data) - - try: - rate, data = wavfile.read(temp_path) - return len(data) / rate - finally: - if os.path.exists(temp_path): - os.remove(temp_path) - - -def get_gpu_memory(): - """Get GPU memory usage using nvidia-smi""" - try: - result = subprocess.check_output( - ["nvidia-smi", "--query-gpu=memory.used", "--format=csv,nounits,noheader"] - ) - return float(result.decode("utf-8").strip()) - except (subprocess.CalledProcessError, FileNotFoundError): - return None - - -def get_system_metrics(): - """Get current system metrics""" - # Get per-CPU percentages and calculate average - cpu_percentages = psutil.cpu_percent(percpu=True) - avg_cpu = sum(cpu_percentages) / len(cpu_percentages) - - metrics = { - "timestamp": datetime.now().isoformat(), - "cpu_percent": round(avg_cpu, 2), - "ram_percent": psutil.virtual_memory().percent, - "ram_used_gb": psutil.virtual_memory().used / (1024**3), - } - - gpu_mem = get_gpu_memory() - if gpu_mem is not None: - metrics["gpu_memory_used"] = gpu_mem - - return metrics - - -def real_time_factor(processing_time: float, audio_length: float, decimals: int = 2) -> float: - """Calculate Real-Time Factor (RTF) as processing-time / length-of-audio""" - rtf = processing_time / audio_length - return round(rtf, decimals) - - -def make_tts_request(text: str, timeout: int = 1800) -> tuple[float, float]: - """Make TTS request using OpenAI-compatible endpoint and return processing time and output length""" - try: - start_time = time.time() - response = requests.post( - "http://localhost:8880/v1/audio/speech", - json={ - "model": "kokoro", - "input": text, - "voice": "af", - "response_format": "wav", - }, - timeout=timeout, - ) - response.raise_for_status() - - processing_time = round(time.time() - start_time, 2) - audio_length = round(get_audio_length(response.content), 2) - - # Save the audio file - token_count = len(enc.encode(text)) - output_file = f"examples/benchmarks/output/chunk_{token_count}_tokens.wav" - os.makedirs(os.path.dirname(output_file), exist_ok=True) - with open(output_file, "wb") as f: - f.write(response.content) - print(f"Saved audio to {output_file}") - - return processing_time, audio_length - - except requests.exceptions.RequestException as e: - print(f"Error making request for text: {text[:50]}... Error: {str(e)}") - return None, None - except Exception as e: - print(f"Error processing text: {text[:50]}... Error: {str(e)}") - return None, None - - -def plot_system_metrics(metrics_data): - """Create plots for system metrics over time""" - df = pd.DataFrame(metrics_data) - df["timestamp"] = pd.to_datetime(df["timestamp"]) - elapsed_time = (df["timestamp"] - df["timestamp"].iloc[0]).dt.total_seconds() - - baseline_cpu = df["cpu_percent"].iloc[0] - baseline_ram = df["ram_used_gb"].iloc[0] - baseline_gpu = df["gpu_memory_used"].iloc[0] / 1024 if "gpu_memory_used" in df.columns else None - - if "gpu_memory_used" in df.columns: - df["gpu_memory_gb"] = df["gpu_memory_used"] / 1024 - - plt.style.use("dark_background") - - has_gpu = "gpu_memory_used" in df.columns - num_plots = 3 if has_gpu else 2 - fig, axes = plt.subplots(num_plots, 1, figsize=(15, 5 * num_plots)) - fig.patch.set_facecolor("#1a1a2e") - - window = min(5, len(df) // 2) - - # Plot CPU Usage - smoothed_cpu = df["cpu_percent"].rolling(window=window, center=True).mean() - sns.lineplot(x=elapsed_time, y=smoothed_cpu, ax=axes[0], color="#ff2a6d", linewidth=2) - axes[0].axhline(y=baseline_cpu, color="#05d9e8", linestyle="--", alpha=0.5, label="Baseline") - axes[0].set_xlabel("Time (seconds)") - axes[0].set_ylabel("CPU Usage (%)") - axes[0].set_title("CPU Usage Over Time") - axes[0].set_ylim(0, max(df["cpu_percent"]) * 1.1) - axes[0].legend() - - # Plot RAM Usage - smoothed_ram = df["ram_used_gb"].rolling(window=window, center=True).mean() - sns.lineplot(x=elapsed_time, y=smoothed_ram, ax=axes[1], color="#05d9e8", linewidth=2) - axes[1].axhline(y=baseline_ram, color="#ff2a6d", linestyle="--", alpha=0.5, label="Baseline") - axes[1].set_xlabel("Time (seconds)") - axes[1].set_ylabel("RAM Usage (GB)") - axes[1].set_title("RAM Usage Over Time") - axes[1].set_ylim(0, max(df["ram_used_gb"]) * 1.1) - axes[1].legend() - - # Plot GPU Memory if available - if has_gpu: - smoothed_gpu = df["gpu_memory_gb"].rolling(window=window, center=True).mean() - sns.lineplot(x=elapsed_time, y=smoothed_gpu, ax=axes[2], color="#ff2a6d", linewidth=2) - axes[2].axhline(y=baseline_gpu, color="#05d9e8", linestyle="--", alpha=0.5, label="Baseline") - axes[2].set_xlabel("Time (seconds)") - axes[2].set_ylabel("GPU Memory (GB)") - axes[2].set_title("GPU Memory Usage Over Time") - axes[2].set_ylim(0, max(df["gpu_memory_gb"]) * 1.1) - axes[2].legend() - - for ax in axes: - ax.grid(True, linestyle="--", alpha=0.3) - ax.set_facecolor("#1a1a2e") - for spine in ax.spines.values(): - spine.set_color("#ffffff") - spine.set_alpha(0.3) - - plt.tight_layout() - plt.savefig("examples/benchmarks/system_usage_rtf.png", dpi=300, bbox_inches="tight") - plt.close() - - -def main(): - os.makedirs("examples/benchmarks/output", exist_ok=True) - - with open("examples/benchmarks/the_time_machine_hg_wells.txt", "r", encoding="utf-8") as f: - text = f.read() - - total_tokens = len(enc.encode(text)) - print(f"Total tokens in file: {total_tokens}") - - # Generate token sizes with dense sampling at start - dense_range = list(range(100, 1001, 100)) - token_sizes = sorted(list(set(dense_range))) - print(f"Testing sizes: {token_sizes}") - - results = [] - system_metrics = [] - test_start_time = time.time() - - for num_tokens in token_sizes: - chunk = get_text_for_tokens(text, num_tokens) - actual_tokens = len(enc.encode(chunk)) - - print(f"\nProcessing chunk with {actual_tokens} tokens:") - print(f"Text preview: {chunk[:100]}...") - - system_metrics.append(get_system_metrics()) - - processing_time, audio_length = make_tts_request(chunk) - if processing_time is None or audio_length is None: - print("Breaking loop due to error") - break - - system_metrics.append(get_system_metrics()) - - # Calculate RTF using the correct formula - rtf = real_time_factor(processing_time, audio_length) - - results.append({ - "tokens": actual_tokens, - "processing_time": processing_time, - "output_length": audio_length, - "rtf": rtf, - "elapsed_time": round(time.time() - test_start_time, 2), - }) - - with open("examples/benchmarks/benchmark_results_rtf.json", "w") as f: - json.dump({"results": results, "system_metrics": system_metrics}, f, indent=2) - - df = pd.DataFrame(results) - if df.empty: - print("No data to plot") - return - - df["tokens_per_second"] = df["tokens"] / df["processing_time"] - - with open("examples/benchmarks/benchmark_stats_rtf.txt", "w") as f: - f.write("=== Benchmark Statistics (with correct RTF) ===\n\n") - - f.write("Overall Stats:\n") - f.write(f"Total tokens processed: {df['tokens'].sum()}\n") - f.write(f"Total audio generated: {df['output_length'].sum():.2f}s\n") - f.write(f"Total test duration: {df['elapsed_time'].max():.2f}s\n") - f.write(f"Average processing rate: {df['tokens_per_second'].mean():.2f} tokens/second\n") - f.write(f"Average RTF: {df['rtf'].mean():.2f}x\n\n") - - f.write("Per-chunk Stats:\n") - f.write(f"Average chunk size: {df['tokens'].mean():.2f} tokens\n") - f.write(f"Min chunk size: {df['tokens'].min():.2f} tokens\n") - f.write(f"Max chunk size: {df['tokens'].max():.2f} tokens\n") - f.write(f"Average processing time: {df['processing_time'].mean():.2f}s\n") - f.write(f"Average output length: {df['output_length'].mean():.2f}s\n\n") - - f.write("Performance Ranges:\n") - f.write(f"Processing rate range: {df['tokens_per_second'].min():.2f} - {df['tokens_per_second'].max():.2f} tokens/second\n") - f.write(f"RTF range: {df['rtf'].min():.2f}x - {df['rtf'].max():.2f}x\n") - - plt.style.use("dark_background") - - # Plot Processing Time vs Token Count - fig, ax = plt.subplots(figsize=(12, 8)) - sns.scatterplot(data=df, x="tokens", y="processing_time", s=100, alpha=0.6, color="#ff2a6d") - sns.regplot(data=df, x="tokens", y="processing_time", scatter=False, color="#05d9e8", line_kws={"linewidth": 2}) - corr = df["tokens"].corr(df["processing_time"]) - plt.text(0.05, 0.95, f"Correlation: {corr:.2f}", transform=ax.transAxes, fontsize=10, color="#ffffff", - bbox=dict(facecolor="#1a1a2e", edgecolor="#ffffff", alpha=0.7)) - setup_plot(fig, ax, "Processing Time vs Input Size") - ax.set_xlabel("Number of Input Tokens") - ax.set_ylabel("Processing Time (seconds)") - plt.savefig("examples/benchmarks/processing_time_rtf.png", dpi=300, bbox_inches="tight") - plt.close() - - # Plot RTF vs Token Count - fig, ax = plt.subplots(figsize=(12, 8)) - sns.scatterplot(data=df, x="tokens", y="rtf", s=100, alpha=0.6, color="#ff2a6d") - sns.regplot(data=df, x="tokens", y="rtf", scatter=False, color="#05d9e8", line_kws={"linewidth": 2}) - corr = df["tokens"].corr(df["rtf"]) - plt.text(0.05, 0.95, f"Correlation: {corr:.2f}", transform=ax.transAxes, fontsize=10, color="#ffffff", - bbox=dict(facecolor="#1a1a2e", edgecolor="#ffffff", alpha=0.7)) - setup_plot(fig, ax, "Real-Time Factor vs Input Size") - ax.set_xlabel("Number of Input Tokens") - ax.set_ylabel("Real-Time Factor (processing time / audio length)") - plt.savefig("examples/benchmarks/realtime_factor_rtf.png", dpi=300, bbox_inches="tight") - plt.close() - - plot_system_metrics(system_metrics) - - print("\nResults saved to:") - print("- examples/benchmarks/benchmark_results_rtf.json") - print("- examples/benchmarks/benchmark_stats_rtf.txt") - print("- examples/benchmarks/processing_time_rtf.png") - print("- examples/benchmarks/realtime_factor_rtf.png") - print("- examples/benchmarks/system_usage_rtf.png") - print("\nAudio files saved in examples/benchmarks/output/") - - -if __name__ == "__main__": - main() diff --git a/examples/benchmarks/processing_time.png b/examples/benchmarks/processing_time.png deleted file mode 100644 index c66fcaf..0000000 Binary files a/examples/benchmarks/processing_time.png and /dev/null differ diff --git a/examples/benchmarks/processing_time_cpu.png b/examples/benchmarks/processing_time_cpu.png deleted file mode 100644 index be000c8..0000000 Binary files a/examples/benchmarks/processing_time_cpu.png and /dev/null differ diff --git a/examples/benchmarks/realtime_factor.png b/examples/benchmarks/realtime_factor.png deleted file mode 100644 index 249685b..0000000 Binary files a/examples/benchmarks/realtime_factor.png and /dev/null differ diff --git a/examples/benchmarks/realtime_factor_cpu.png b/examples/benchmarks/realtime_factor_cpu.png deleted file mode 100644 index d8c8647..0000000 Binary files a/examples/benchmarks/realtime_factor_cpu.png and /dev/null differ diff --git a/examples/benchmarks/system_usage.png b/examples/benchmarks/system_usage.png deleted file mode 100644 index bc10eb0..0000000 Binary files a/examples/benchmarks/system_usage.png and /dev/null differ