first git
CI / ruff (push) Waiting to run
CI / mypy (push) Waiting to run
CI / pytest (push) Waiting to run
CI / package (push) Waiting to run
CI / Install smoke (${{ matrix.label }}) (linux, ubuntu-latest) (push) Blocked by required conditions
CI / Install smoke (${{ matrix.label }}) (macos-arm64, macos-14) (push) Blocked by required conditions
CI / ruff (push) Waiting to run
CI / mypy (push) Waiting to run
CI / pytest (push) Waiting to run
CI / package (push) Waiting to run
CI / Install smoke (${{ matrix.label }}) (linux, ubuntu-latest) (push) Blocked by required conditions
CI / Install smoke (${{ matrix.label }}) (macos-arm64, macos-14) (push) Blocked by required conditions
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
from speech_to_speech.arguments_classes.responses_api_language_model_arguments import (
|
||||
ResponsesApiLanguageModelHandlerArguments,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ChatCompletionsLanguageModelHandlerArguments(ResponsesApiLanguageModelHandlerArguments):
|
||||
"""Arguments for the ``chat-completions`` LLM backend.
|
||||
|
||||
Inherits the OpenAI-compatible connection fields from the Responses-API
|
||||
arguments (``responses_api_base_url`` / ``responses_api_api_key`` /
|
||||
``responses_api_stream`` / ``responses_api_disable_thinking``) so the same
|
||||
CLI flags and launcher env vars drive both backends, and adds the
|
||||
Chat-Completions-only ``reasoning_effort`` knob.
|
||||
"""
|
||||
|
||||
responses_api_reasoning_effort: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "Provider-specific reasoning level sent as extra_body={'reasoning_effort': <value>} on the "
|
||||
"Chat Completions request. Use to disable reasoning on providers where "
|
||||
"chat_template_kwargs.enable_thinking is ignored (e.g. 'none' / 'low'). When unset, falls back to "
|
||||
"the disable_thinking behaviour (chat_template_kwargs.enable_thinking=false). Default is None."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class ChatTTSHandlerArguments:
|
||||
chat_tts_stream: bool = field(
|
||||
default=True,
|
||||
metadata={"help": "The tts mode is stream Default is 'stream'."},
|
||||
)
|
||||
chat_tts_device: str = field(
|
||||
default="cuda",
|
||||
metadata={"help": "The device to be used for speech synthesis. Default is 'cuda'."},
|
||||
)
|
||||
chat_tts_chunk_size: int = field(
|
||||
default=512,
|
||||
metadata={
|
||||
"help": "Sets the size of the audio data chunk processed per cycle, balancing playback latency and CPU load.. Default is 512。."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class FacebookMMSTTSHandlerArguments:
|
||||
facebook_mms_model_name: str = field(
|
||||
default="facebook/mms-tts-eng",
|
||||
metadata={"help": "The model name to use. Default is 'facebook/mms-tts-eng'."},
|
||||
)
|
||||
tts_language: str = field(
|
||||
default="en",
|
||||
metadata={"help": "The language code for the TTS model. Default is 'en' for English."},
|
||||
)
|
||||
facebook_mms_device: str = field(
|
||||
default="cuda",
|
||||
metadata={"help": "The device to use for the TTS model. Default is 'cuda'."},
|
||||
)
|
||||
facebook_mms_torch_dtype: str = field(
|
||||
default="float32",
|
||||
metadata={"help": "The torch data type to use for the TTS model. Default is 'float32'."},
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class FasterWhisperSTTHandlerArguments:
|
||||
faster_whisper_stt_model_name: str = field(
|
||||
default="tiny.en",
|
||||
metadata={
|
||||
"help": (
|
||||
"The pretrained Faster Whisper model to use.\n"
|
||||
" One of ('tiny', 'tiny.en', 'base', 'base.en', 'small', 'small.en', "
|
||||
"'distil-small.en', 'medium', 'medium.en', 'distil-medium.en', 'large-v1', 'large-v2', "
|
||||
"'large-v3', 'large', 'distil-large-v2', 'distil-large-v3').\n"
|
||||
" Default is 'small'."
|
||||
)
|
||||
},
|
||||
)
|
||||
faster_whisper_stt_device: str = field(
|
||||
default="auto",
|
||||
metadata={
|
||||
"help": """The device type on which the model will run.
|
||||
One of ('cpu', 'cuda', 'auto').
|
||||
Default is 'auto'."""
|
||||
},
|
||||
)
|
||||
faster_whisper_stt_compute_type: str = field(
|
||||
default="auto",
|
||||
metadata={
|
||||
"help": """The data type to use for computation.
|
||||
One of ('default', 'auto', 'int8', 'int8_float32', 'int8_float16', 'int8_bfloat16', 'int16', 'float16', 'float32', 'bfloat16')
|
||||
Default is 'auto'.
|
||||
Refer to 'https://opennmt.net/CTranslate2/quantization.html#quantize-on-model-loading'"""
|
||||
},
|
||||
)
|
||||
faster_whisper_stt_gen_max_new_tokens: int = field(
|
||||
default=128,
|
||||
metadata={"help": "The maximum number of new tokens to generate. Default is 128."},
|
||||
)
|
||||
faster_whisper_stt_gen_beam_size: int = field(
|
||||
default=1,
|
||||
metadata={"help": "The number of beams for beam search. Default is 1, implying greedy decoding."},
|
||||
)
|
||||
faster_whisper_stt_gen_return_timestamps: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Whether to return timestamps with transcriptions. Default is False."},
|
||||
)
|
||||
faster_whisper_stt_gen_task: str = field(
|
||||
default="transcribe",
|
||||
metadata={"help": "The task to perform, typically 'transcribe' for transcription. Default is 'transcribe'."},
|
||||
)
|
||||
faster_whisper_stt_gen_language: str = field(
|
||||
default="en",
|
||||
metadata={"help": "The language of the speech to transcribe. Default is 'en' for English."},
|
||||
)
|
||||
@@ -0,0 +1,38 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class KokoroTTSHandlerArguments:
|
||||
kokoro_model_name: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "The Kokoro TTS model to use. Auto-selects based on device: 'mlx-community/Kokoro-82M-bf16' for MPS, 'hexgrad/Kokoro-82M' for CUDA/CPU."
|
||||
},
|
||||
)
|
||||
kokoro_device: str = field(
|
||||
default="auto",
|
||||
metadata={
|
||||
"help": "The device to run Kokoro TTS on. Options: 'auto', 'cuda', 'cpu', 'mps'. Default is 'auto' (MPS on Mac, CUDA on GPU systems)."
|
||||
},
|
||||
)
|
||||
kokoro_voice: str = field(
|
||||
default="bm_fable",
|
||||
metadata={
|
||||
"help": "The voice to use for synthesis. See VOICES.md in the Kokoro repo for options. Default is 'bm_fable' (British male)."
|
||||
},
|
||||
)
|
||||
kokoro_lang_code: str = field(
|
||||
default="b",
|
||||
metadata={
|
||||
"help": "Language code: 'a' for American English, 'b' for British English, 'j' for Japanese, etc. Default is 'b'."
|
||||
},
|
||||
)
|
||||
kokoro_speed: float = field(
|
||||
default=1.0,
|
||||
metadata={"help": "Speech speed multiplier. Values > 1.0 speed up, < 1.0 slow down. Default is 1.0."},
|
||||
)
|
||||
kokoro_blocksize: int = field(
|
||||
default=512,
|
||||
metadata={"help": "The audio chunk size in samples for streaming output. Default is 512."},
|
||||
)
|
||||
@@ -0,0 +1,43 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from speech_to_speech.arguments_classes.language_model_base_arguments import LanguageModelBaseArguments
|
||||
|
||||
|
||||
@dataclass
|
||||
class LanguageModelHandlerArguments(LanguageModelBaseArguments):
|
||||
llm_device: str = field(
|
||||
default="cuda",
|
||||
metadata={"help": "The device type on which the model will run. Default is 'cuda' for GPU acceleration."},
|
||||
)
|
||||
llm_torch_dtype: str = field(
|
||||
default="float16",
|
||||
metadata={
|
||||
"help": "The PyTorch data type for the model and input tensors. One of `float32` (full-precision), `float16` or `bfloat16` (both half-precision)."
|
||||
},
|
||||
)
|
||||
llm_gen_max_new_tokens: int = field(
|
||||
default=1024,
|
||||
metadata={"help": "Maximum number of new tokens to generate in a single completion. Default is 1024."},
|
||||
)
|
||||
llm_gen_min_new_tokens: int = field(
|
||||
default=0,
|
||||
metadata={"help": "Minimum number of new tokens to generate in a single completion. Default is 0."},
|
||||
)
|
||||
llm_gen_temperature: float = field(
|
||||
default=0.0,
|
||||
metadata={
|
||||
"help": "Controls the randomness of the output. Set to 0.0 for deterministic (repeatable) outputs. Default is 0.0."
|
||||
},
|
||||
)
|
||||
llm_gen_do_sample: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Whether to use sampling; set this to False for deterministic outputs. Default is False."},
|
||||
)
|
||||
llm_is_vlm: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": "Set to True when using a Vision Language Model (VLM) that accepts image inputs. "
|
||||
"Loads AutoProcessor + AutoModelForImageTextToText instead of the default text-only model. "
|
||||
"Default is False."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,46 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class LanguageModelBaseArguments:
|
||||
model_name: str = field(
|
||||
default="Qwen/Qwen3-4B-Instruct-2507",
|
||||
metadata={"help": "The pretrained language model to use."},
|
||||
)
|
||||
user_role: str = field(
|
||||
default="user",
|
||||
metadata={"help": "Role assigned to the user in the chat context. Default is 'user'."},
|
||||
)
|
||||
init_chat_role: str = field(
|
||||
default="system",
|
||||
metadata={"help": "Initial role for setting up the chat context. Default is 'system'."},
|
||||
)
|
||||
init_chat_prompt: str = field(
|
||||
default="You are a helpful and friendly AI assistant. You are polite, respectful, and aim to provide concise responses of less than 20 words.",
|
||||
metadata={"help": "The initial chat prompt to establish context for the language model."},
|
||||
)
|
||||
chat_size: int = field(
|
||||
default=30,
|
||||
metadata={"help": "Number of interactions assistant-user to keep for the chat."},
|
||||
)
|
||||
stream_batch_sentences: int = field(
|
||||
default=3,
|
||||
metadata={
|
||||
"help": "Number of sentences to accumulate before yielding a batch during streaming. "
|
||||
"Set to 1 for sentence-by-sentence streaming. Default is 3."
|
||||
},
|
||||
)
|
||||
enable_lang_prompt: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": "When True, append a user message instructing the model to reply in the detected/selected "
|
||||
"language (e.g. 'Please reply to my message in French.'). Default is False."
|
||||
},
|
||||
)
|
||||
compact_history: bool = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"help": "When True, summarize older turns in the background once the chat exceeds chat_size, "
|
||||
"instead of synchronously evicting them. Adds an extra LLM call per compaction. Default is True."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class MLXAudioWhisperSTTHandlerArguments:
|
||||
mlx_audio_whisper_model_name: str = field(
|
||||
default="mlx-community/whisper-large-v3-turbo",
|
||||
metadata={
|
||||
"help": "The pretrained MLX Audio Whisper model to use. Default is 'mlx-community/whisper-large-v3-turbo'."
|
||||
},
|
||||
)
|
||||
mlx_audio_whisper_gen_kwargs: dict = field(
|
||||
default_factory=dict,
|
||||
metadata={"help": "Additional generation kwargs to pass to the model. Default is an empty dict."},
|
||||
)
|
||||
@@ -0,0 +1,72 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Literal, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class ModuleArguments:
|
||||
device: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={"help": "If specified, overrides the device for all handlers."},
|
||||
)
|
||||
mode: Optional[Literal["local", "socket", "websocket", "realtime"]] = field(
|
||||
default="realtime",
|
||||
metadata={
|
||||
"help": "The mode to run the pipeline in. Either 'local', 'socket', 'websocket', or 'realtime'. Default is 'realtime'."
|
||||
},
|
||||
)
|
||||
local_mac_optimal_settings: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": "If specified, sets the optimal settings for Mac OS. Sets Parakeet TDT for STT, MLX LM for language model, and Qwen3-TTS for TTS, with MPS device and local mode."
|
||||
},
|
||||
)
|
||||
stt: Optional[
|
||||
Literal["whisper", "whisper-mlx", "mlx-audio-whisper", "faster-whisper", "parakeet-tdt", "paraformer"]
|
||||
] = field(
|
||||
default="parakeet-tdt",
|
||||
metadata={
|
||||
"help": "The STT to use. Either 'whisper', 'whisper-mlx', 'mlx-audio-whisper', 'faster-whisper', 'parakeet-tdt', or 'paraformer'. Default is 'parakeet-tdt'."
|
||||
},
|
||||
)
|
||||
llm_backend: Optional[Literal["transformers", "mlx-lm", "responses-api", "chat-completions"]] = field(
|
||||
default="responses-api",
|
||||
metadata={
|
||||
"help": "The LLM backend to use. Either 'transformers', 'mlx-lm', 'responses-api', or "
|
||||
"'chat-completions' (OpenAI-compatible /v1/chat/completions). Default is 'responses-api'."
|
||||
},
|
||||
)
|
||||
tts: Optional[Literal["chatTTS", "facebookMMS", "pocket", "kokoro", "qwen3"]] = field(
|
||||
default="qwen3",
|
||||
metadata={
|
||||
"help": "The TTS to use. Either 'chatTTS', 'facebookMMS', 'pocket', 'kokoro', or 'qwen3'. Default is 'qwen3'."
|
||||
},
|
||||
)
|
||||
log_level: str = field(
|
||||
default="info",
|
||||
metadata={"help": "Provide logging level. Example --log_level debug, default=info."},
|
||||
)
|
||||
enable_live_transcription: bool = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"help": "Enable live transcription display while user is speaking (works with parakeet-tdt). Default is true."
|
||||
},
|
||||
)
|
||||
live_transcription_update_interval: float = field(
|
||||
default=0.5,
|
||||
metadata={"help": "Update interval for live transcription in seconds (default: 0.5s = 500ms)"},
|
||||
)
|
||||
live_transcription_min_silence_ms: int = field(
|
||||
default=500,
|
||||
metadata={
|
||||
"help": "Minimum silence duration (ms) before ending speech when live transcription is enabled (default: 500ms)"
|
||||
},
|
||||
)
|
||||
num_pipelines: int = field(
|
||||
default=1,
|
||||
metadata={
|
||||
"help": "Number of isolated realtime pipelines in the pool. One uvicorn server listens on "
|
||||
"--ws_port and routes each incoming websocket to the next free pipeline (each has its own "
|
||||
"VAD/STT/LM/TTS handlers and conversation state). Max concurrent websocket sessions equals "
|
||||
"num_pipelines; further connections are rejected. Only valid for --mode realtime. Default is 1."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class ParaformerSTTHandlerArguments:
|
||||
paraformer_stt_model_name: str = field(
|
||||
default="paraformer-zh",
|
||||
metadata={
|
||||
"help": "The pretrained model to use. Default is 'paraformer-zh'. Can be choose from https://github.com/modelscope/FunASR"
|
||||
},
|
||||
)
|
||||
paraformer_stt_device: str = field(
|
||||
default="cuda",
|
||||
metadata={"help": "The device type on which the model will run. Default is 'cuda' for GPU acceleration."},
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class ParakeetTDTSTTHandlerArguments:
|
||||
"""
|
||||
Arguments for the Parakeet TDT Speech-to-Text handler.
|
||||
|
||||
Parakeet TDT 0.6B v3 is a 600M parameter multilingual ASR model from NVIDIA.
|
||||
- On MPS (Apple Silicon): Uses mlx-audio with mlx-community/parakeet-tdt-0.6b-v3
|
||||
- On CUDA/CPU: Uses nano-parakeet (pure PyTorch) with nvidia/parakeet-tdt-0.6b-v3
|
||||
"""
|
||||
|
||||
parakeet_tdt_model_name: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "The Parakeet TDT model to use. Defaults to 'mlx-community/parakeet-tdt-0.6b-v3' "
|
||||
"for MPS or 'nvidia/parakeet-tdt-0.6b-v3' for CUDA/CPU."
|
||||
},
|
||||
)
|
||||
parakeet_tdt_device: str = field(
|
||||
default="auto",
|
||||
metadata={
|
||||
"help": "Device to run the model on. 'auto' will use MPS on macOS and CUDA otherwise. "
|
||||
"Options: 'auto', 'cuda', 'mps', 'cpu'. Default is 'auto'."
|
||||
},
|
||||
)
|
||||
parakeet_tdt_compute_type: str = field(
|
||||
default="float16",
|
||||
metadata={"help": "Compute type for the model. Options: 'float16', 'float32'. Default is 'float16'."},
|
||||
)
|
||||
parakeet_tdt_language: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "Target language code for transcription. If not specified, the model will "
|
||||
"auto-detect the language. Supports 25 European languages."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class PocketTTSHandlerArguments:
|
||||
pocket_tts_device: str = field(
|
||||
default="cpu",
|
||||
metadata={
|
||||
"help": "The device type on which the Pocket TTS model will run. Options: 'cpu', 'cuda', 'mps'. Default is 'cpu'."
|
||||
},
|
||||
)
|
||||
pocket_tts_voice: str = field(
|
||||
default="jean",
|
||||
metadata={
|
||||
"help": "Voice to use for Pocket TTS. Can be a preset name ('alba', 'marius', 'javert', 'jean', 'fantine', 'cosette', 'eponine', 'azelma'), a local audio file path, or a HuggingFace path like 'hf://kyutai/tts-voices/...'. Default is 'jean'."
|
||||
},
|
||||
)
|
||||
pocket_tts_sample_rate: int = field(
|
||||
default=16000,
|
||||
metadata={
|
||||
"help": "Output sample rate in Hz for Pocket TTS. Pocket TTS uses 24kHz internally but will be resampled to this rate to match the audio output. Default is 16000 to match the pipeline's audio streamer."
|
||||
},
|
||||
)
|
||||
pocket_tts_blocksize: int = field(
|
||||
default=512,
|
||||
metadata={"help": "Size of audio blocks to yield for streaming in Pocket TTS. Default is 512."},
|
||||
)
|
||||
pocket_tts_max_tokens: int = field(
|
||||
default=50,
|
||||
metadata={"help": "Maximum number of tokens to generate per sentence in Pocket TTS. Default is 50."},
|
||||
)
|
||||
@@ -0,0 +1,100 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Literal, Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class Qwen3TTSHandlerArguments:
|
||||
qwen3_tts_model_name: str = field(
|
||||
default="Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice",
|
||||
metadata={
|
||||
"help": "The Qwen3-TTS model to use (HuggingFace Hub ID or local path). Default is 'Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice'. On Apple Silicon, Qwen/* model IDs are auto-mapped to the corresponding mlx-community/* model when possible, defaulting to the 6bit MLX variant unless the model name already pins a specific suffix."
|
||||
},
|
||||
)
|
||||
qwen3_tts_device: str = field(
|
||||
default="cuda",
|
||||
metadata={
|
||||
"help": "Preferred device for Qwen3-TTS. Options: 'cuda', 'cpu', 'mps', 'auto'. Default is 'cuda'. On Apple Silicon the mlx-audio backend is selected automatically."
|
||||
},
|
||||
)
|
||||
qwen3_tts_dtype: str = field(
|
||||
default="auto",
|
||||
metadata={
|
||||
"help": "Data type for inference. Options: 'auto', 'float16', 'bfloat16', 'float32'. Default is 'auto'."
|
||||
},
|
||||
)
|
||||
qwen3_tts_attn_implementation: str = field(
|
||||
default="eager",
|
||||
metadata={
|
||||
"help": "Attention implementation. Options: 'eager', 'flash_attention_2', 'sdpa'. Use 'eager' on Jetson. Default is 'eager'."
|
||||
},
|
||||
)
|
||||
qwen3_tts_backend: Literal["ggml", "torch"] = field(
|
||||
default="ggml",
|
||||
metadata={
|
||||
"help": "faster-qwen3-tts backend on non-macOS platforms. Options: 'ggml' or 'torch'. Default is 'ggml'. On Apple Silicon, mlx-audio is selected automatically and this option is ignored."
|
||||
},
|
||||
)
|
||||
qwen3_tts_ref_audio: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "Optional path to reference audio file for voice cloning. Leave unset when using a CustomVoice model."
|
||||
},
|
||||
)
|
||||
qwen3_tts_ref_text: str = field(
|
||||
default="I'm confused why some people have super short timelines, yet at the same time are bullish on scaling up reinforcement learning atop LLMs. If we're actually close to a human-like learner, then this whole approach of training on verifiable outcomes.",
|
||||
metadata={"help": "Transcription of the reference audio for voice cloning."},
|
||||
)
|
||||
qwen3_tts_speaker: Optional[str] = field(
|
||||
default="Aiden",
|
||||
metadata={
|
||||
"help": "Speaker name for CustomVoice models. Default is 'Aiden'. If not provided, the first supported speaker is used when available."
|
||||
},
|
||||
)
|
||||
qwen3_tts_instruct: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={"help": "Instruction text for VoiceDesign models (optional, required for voice design)."},
|
||||
)
|
||||
qwen3_tts_xvec_only: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": "Use x-vector only voice cloning mode (recommended for cleaner starts and language switching). Default is False."
|
||||
},
|
||||
)
|
||||
qwen3_tts_parity_mode: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Disable CUDA-graph streaming path and use parity mode for stability. Default is False."},
|
||||
)
|
||||
qwen3_tts_non_streaming_mode: Optional[bool] = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"help": "Optional override for Qwen3-TTS text prefill behavior. Default is true, which pre-fills the full target text before decode on faster-qwen3-tts. Currently ignored on Apple Silicon because mlx-audio does not expose this yet."
|
||||
},
|
||||
)
|
||||
qwen3_tts_mlx_quantization: Optional[str] = field(
|
||||
default="6bit",
|
||||
metadata={
|
||||
"help": "Optional MLX quantization override on Apple Silicon. Supported values: 'bf16', '4bit', '6bit', '8bit'. Default is '6bit'."
|
||||
},
|
||||
)
|
||||
qwen3_tts_language: str = field(
|
||||
default="auto",
|
||||
metadata={"help": "Target language for synthesis. Default is 'auto'."},
|
||||
)
|
||||
qwen3_tts_streaming_chunk_size: Optional[int] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "Codec steps per streaming chunk. If unset, the handler uses a backend-specific default: 8 on faster-qwen3-tts and 4 on mlx-audio."
|
||||
},
|
||||
)
|
||||
qwen3_tts_max_new_tokens: int = field(
|
||||
default=1536,
|
||||
metadata={
|
||||
"help": "Upper cap for Qwen3-TTS codec tokens. The handler estimates a per-utterance budget from the text and clamps it to this ceiling (~12 tokens per second of audio). Raise this above 1536 if you want to allow longer utterances."
|
||||
},
|
||||
)
|
||||
qwen3_tts_blocksize: int = field(
|
||||
default=512,
|
||||
metadata={
|
||||
"help": "Audio chunk size in samples for streaming output. Must match LocalAudioStreamer blocksize. Default is 512."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,92 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class RAGArguments:
|
||||
"""Argomenti CLI per il sottosistema RAG server-side."""
|
||||
|
||||
rag_enabled: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": (
|
||||
"Abilita il retrieval RAG server-side: ogni turno utente viene usato come query "
|
||||
"per la knowledge base locale, e i top-k chunk vengono iniettati nel prompt "
|
||||
"prima dell'LLM. Default: False."
|
||||
)
|
||||
},
|
||||
)
|
||||
rag_kb_path: str = field(
|
||||
default="./kb",
|
||||
metadata={
|
||||
"help": (
|
||||
"Percorso cartella knowledge base. Contiene file .md/.txt (auto-chunkizzati), "
|
||||
"file .jsonl pre-chunkizzati, l'indice _index.npz e _chunks.jsonl. Default: ./kb"
|
||||
)
|
||||
},
|
||||
)
|
||||
rag_embedding_model: str = field(
|
||||
default="paraphrase-multilingual-MiniLM-L12-v2",
|
||||
metadata={
|
||||
"help": (
|
||||
"Modello sentence-transformers per l'embedding. "
|
||||
"'paraphrase-multilingual-MiniLM-L12-v2' supporta spagnolo e 50+ lingue, "
|
||||
"veloce e leggero. Per spagnolo puro puoi usare 'hiiamsid/sentence_similarity_spanish_es'."
|
||||
)
|
||||
},
|
||||
)
|
||||
rag_device: str = field(
|
||||
default="auto",
|
||||
metadata={
|
||||
"help": "Device per embedding: 'auto' (usa CUDA se disponibile), 'cuda', 'cpu', 'mps'. Default: auto"
|
||||
},
|
||||
)
|
||||
rag_top_k: int = field(
|
||||
default=3,
|
||||
metadata={"help": "Numero massimo di chunk da recuperare per query. Default: 3"},
|
||||
)
|
||||
rag_threshold: float = field(
|
||||
default=0.25,
|
||||
metadata={
|
||||
"help": (
|
||||
"Soglia minima coseno-similarità per considerare un chunk rilevante. "
|
||||
"Range [0,1]; valori più alti = meno falsi positivi. Default: 0.25"
|
||||
)
|
||||
},
|
||||
)
|
||||
rag_chunk_size: int = field(
|
||||
default=512,
|
||||
metadata={"help": "Dimensione massima in caratteri per ogni chunk (solo file md/txt). Default: 512"},
|
||||
)
|
||||
rag_chunk_overlap: int = field(
|
||||
default=64,
|
||||
metadata={"help": "Overlap in caratteri tra chunk consecutivi. Default: 64"},
|
||||
)
|
||||
rag_force_rebuild: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": "Se True, ricostruisce sempre l'indice da zero anche se esiste _index.npz. Default: False"
|
||||
},
|
||||
)
|
||||
rag_language: str = field(
|
||||
default="es",
|
||||
metadata={
|
||||
"help": (
|
||||
"Lingua per il prompt injection header (intestazione blocchi RAG). "
|
||||
"Valori: 'es' (spagnolo), 'it' (italiano), 'en' (inglese). Default: es"
|
||||
)
|
||||
},
|
||||
)
|
||||
rag_embedding_batch_size: int = field(
|
||||
default=32,
|
||||
metadata={"help": "Batch size per l'embedding durante l'indicizzazione. Default: 32"},
|
||||
)
|
||||
rag_inject_as: str = field(
|
||||
default="system",
|
||||
metadata={
|
||||
"help": (
|
||||
"Dove iniettare i risultati retrieval: 'system' (system message, consigliato) "
|
||||
"oppure 'user' (accodato all'ultimo messaggio utente). Default: system"
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,34 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
from speech_to_speech.arguments_classes.language_model_base_arguments import LanguageModelBaseArguments
|
||||
|
||||
|
||||
@dataclass
|
||||
class ResponsesApiLanguageModelHandlerArguments(LanguageModelBaseArguments):
|
||||
model_name: str = field(
|
||||
default="gpt-5.4-mini",
|
||||
metadata={"help": "The model to use with the OpenAI-compatible API. Default is 'gpt-5.4-mini'."},
|
||||
)
|
||||
responses_api_api_key: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={"help": "API key used to authenticate access to the OpenAI-compatible API. Default is None."},
|
||||
)
|
||||
responses_api_base_url: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={"help": "Base URL for the OpenAI-compatible API endpoint. Default is None (uses OpenAI)."},
|
||||
)
|
||||
responses_api_stream: bool = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"help": "The stream parameter typically indicates whether data should be transmitted in a continuous flow rather"
|
||||
" than in a single, complete response, often used for handling large or real-time data.Default is True"
|
||||
},
|
||||
)
|
||||
responses_api_disable_thinking: bool = field(
|
||||
default=True,
|
||||
metadata={
|
||||
"help": "Disable provider-side thinking/reasoning when supported by the OpenAI-compatible backend. "
|
||||
"For Together Qwen3.5 models this sends chat_template_kwargs.enable_thinking=false."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class SocketReceiverArguments:
|
||||
recv_host: str = field(
|
||||
default="localhost",
|
||||
metadata={
|
||||
"help": "The host IP ddress for the socket connection. Default is '0.0.0.0' which binds to all "
|
||||
"available interfaces on the host machine."
|
||||
},
|
||||
)
|
||||
recv_port: int = field(
|
||||
default=12345,
|
||||
metadata={"help": "The port number on which the socket server listens. Default is 12346."},
|
||||
)
|
||||
chunk_size: int = field(
|
||||
default=1024,
|
||||
metadata={"help": "The size of each data chunk to be sent or received over the socket. Default is 1024 bytes."},
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class SocketSenderArguments:
|
||||
send_host: str = field(
|
||||
default="localhost",
|
||||
metadata={
|
||||
"help": "The host IP address for the socket connection. Default is '0.0.0.0' which binds to all "
|
||||
"available interfaces on the host machine."
|
||||
},
|
||||
)
|
||||
send_port: int = field(
|
||||
default=12346,
|
||||
metadata={"help": "The port number on which the socket server listens. Default is 12346."},
|
||||
)
|
||||
@@ -0,0 +1,81 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class VADHandlerArguments:
|
||||
thresh: float = field(
|
||||
default=0.6,
|
||||
metadata={
|
||||
"help": "The threshold value for voice activity detection (VAD). Values typically range from 0 to 1, with higher values requiring higher confidence in speech detection."
|
||||
},
|
||||
)
|
||||
sample_rate: int = field(
|
||||
default=16000,
|
||||
metadata={
|
||||
"help": "The sample rate of the audio in Hertz. Default is 16000 Hz, which is a common setting for voice audio."
|
||||
},
|
||||
)
|
||||
min_silence_ms: int = field(
|
||||
default=64,
|
||||
metadata={
|
||||
"help": "Minimum length of silence intervals to be used for segmenting speech. Measured in milliseconds. Default is 64 ms."
|
||||
},
|
||||
)
|
||||
min_speech_ms: int = field(
|
||||
default=384,
|
||||
metadata={
|
||||
"help": "Minimum length of speech segments to be considered valid speech. Measured in milliseconds. Default is 384 ms."
|
||||
},
|
||||
)
|
||||
min_speech_continuation_ms: int = field(
|
||||
default=192,
|
||||
metadata={
|
||||
"help": "Hysteresis threshold (ms of active speech) for accepting speech that continues a reopenable turn (soft-ended, uncommitted, within the reopen window). Set to 0 to disable the split and use min_speech_ms. Clamped to [100, min_speech_ms]. New turns and barge-ins always require min_speech_ms. Default and recommended: 192 with min_speech_ms 384."
|
||||
},
|
||||
)
|
||||
max_speech_ms: float = field(
|
||||
default=float("inf"),
|
||||
metadata={
|
||||
"help": "Maximum length of continuous speech before forcing a split. Default is infinite, allowing for uninterrupted speech segments."
|
||||
},
|
||||
)
|
||||
speech_pad_ms: int = field(
|
||||
default=500,
|
||||
metadata={
|
||||
"help": "Amount of audio retained before VAD triggers and prepended to detected speech segments. Once speech is detected, audio continues to be kept until VAD declares the segment done. Measured in milliseconds. Default is 500 ms."
|
||||
},
|
||||
)
|
||||
audio_enhancement: bool = field(
|
||||
default=False,
|
||||
metadata={
|
||||
"help": "improves sound quality by applying techniques like noise reduction, equalization, and echo cancellation. Default is False."
|
||||
},
|
||||
)
|
||||
enable_realtime_transcription: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Enable progressive audio release for live transcription during speech. Default is False."},
|
||||
)
|
||||
realtime_processing_pause: float = field(
|
||||
default=0.5,
|
||||
metadata={
|
||||
"help": "Interval (in seconds) for releasing progressive audio chunks during speech. Default is 0.5s."
|
||||
},
|
||||
)
|
||||
speculative_reopen_ms: int = field(
|
||||
default=1000,
|
||||
metadata={
|
||||
"help": "In realtime mode, keep a soft-ended turn reopenable for this many milliseconds unless a response commits it."
|
||||
},
|
||||
)
|
||||
unanswered_reopen_ms: int = field(
|
||||
default=7000,
|
||||
metadata={
|
||||
"help": "Sanity cap (ms) for reopening a soft-ended speculative turn that has not yet been answered by any assistant output. While a turn is uncommitted, resumed speech within this window reopens the same turn instead of starting a new one. Has no effect below speculative_reopen_ms."
|
||||
},
|
||||
)
|
||||
short_segment_merge_ms: int = field(
|
||||
default=0,
|
||||
metadata={
|
||||
"help": "When greater than 0, adjacent VAD segments below min_speech_ms are held and stitched for this many milliseconds before being discarded. Fragments shorter than 100 ms of active speech are never held. Useful with very low min_silence_ms values."
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class WebSocketStreamerArguments:
|
||||
ws_host: str = field(
|
||||
default="0.0.0.0",
|
||||
metadata={
|
||||
"help": "The host IP address for the WebSocket server. Default is '0.0.0.0' which binds to all "
|
||||
"available interfaces on the host machine."
|
||||
},
|
||||
)
|
||||
ws_port: int = field(
|
||||
default=8765,
|
||||
metadata={"help": "The port number on which the WebSocket server listens. Default is 8765."},
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class WhisperSTTHandlerArguments:
|
||||
stt_model_name: str = field(
|
||||
default="distil-whisper/distil-large-v3",
|
||||
metadata={"help": "The pretrained Whisper model to use. Default is 'distil-whisper/distil-large-v3'."},
|
||||
)
|
||||
stt_device: str = field(
|
||||
default="cuda",
|
||||
metadata={"help": "The device type on which the model will run. Default is 'cuda' for GPU acceleration."},
|
||||
)
|
||||
stt_torch_dtype: str = field(
|
||||
default="float16",
|
||||
metadata={
|
||||
"help": "The PyTorch data type for the model and input tensors. One of `float32` (full-precision), `float16` or `bfloat16` (both half-precision)."
|
||||
},
|
||||
)
|
||||
stt_compile_mode: Optional[str] = field(
|
||||
default=None,
|
||||
metadata={
|
||||
"help": "Compile mode for torch compile. Either 'default', 'reduce-overhead' and 'max-autotune'. Default is None (no compilation)"
|
||||
},
|
||||
)
|
||||
stt_gen_max_new_tokens: int = field(
|
||||
default=128,
|
||||
metadata={"help": "The maximum number of new tokens to generate. Default is 128."},
|
||||
)
|
||||
stt_gen_num_beams: int = field(
|
||||
default=1,
|
||||
metadata={"help": "The number of beams for beam search. Default is 1, implying greedy decoding."},
|
||||
)
|
||||
stt_gen_return_timestamps: bool = field(
|
||||
default=False,
|
||||
metadata={"help": "Whether to return timestamps with transcriptions. Default is False."},
|
||||
)
|
||||
stt_gen_task: str = field(
|
||||
default="transcribe",
|
||||
metadata={"help": "The task to perform, typically 'transcribe' for transcription. Default is 'transcribe'."},
|
||||
)
|
||||
language: Optional[str] = field(
|
||||
default="en",
|
||||
metadata={
|
||||
"help": """The language for the conversation.
|
||||
Choose between 'en' (english), 'fr' (french), 'es' (spanish),
|
||||
'zh' (chinese), 'ko' (korean), 'ja' (japanese), 'hi' (hindi) or 'None'.
|
||||
If using 'auto', the language is automatically detected and can
|
||||
change during the conversation. Default is 'en'."""
|
||||
},
|
||||
)
|
||||
Reference in New Issue
Block a user