Improved: Ultravox performance

This commit is contained in:
Kyle Gani
2025-04-25 13:12:08 +02:00
parent e763cd7bee
commit 49fbcc86ac

View File

@@ -71,7 +71,7 @@ class UltravoxModel:
stop_token_ids: Optional token IDs to stop generation stop_token_ids: Optional token IDs to stop generation
""" """
def __init__(self, model_name: str = "fixie-ai/ultravox-v0_4_1-llama-3_1-8b"): def __init__(self, model_name: str = "fixie-ai/ultravox-v0_5-llama-3_1-8b"):
self.model_name = model_name self.model_name = model_name
self._initialize_engine() self._initialize_engine()
self._initialize_tokenizer() self._initialize_tokenizer()
@@ -177,7 +177,7 @@ class UltravoxSTTService(AIService):
to generate text transcriptions. to generate text transcriptions.
Args: Args:
model_size: The Ultravox model to use (ModelSize enum or string) model_name: The Ultravox model to use (ModelSize enum or string)
hf_token: Hugging Face token for model access hf_token: Hugging Face token for model access
temperature: Sampling temperature for generation temperature: Sampling temperature for generation
max_tokens: Maximum tokens to generate max_tokens: Maximum tokens to generate
@@ -194,7 +194,7 @@ class UltravoxSTTService(AIService):
def __init__( def __init__(
self, self,
*, *,
model_size: str = "fixie-ai/ultravox-v0_4_1-llama-3_1-8b", model_name: str = "fixie-ai/ultravox-v0_5-llama-3_1-8b",
hf_token: Optional[str] = None, hf_token: Optional[str] = None,
temperature: float = 0.7, temperature: float = 0.7,
max_tokens: int = 100, max_tokens: int = 100,
@@ -211,7 +211,6 @@ class UltravoxSTTService(AIService):
logger.warning("No Hugging Face token provided. Model may not load correctly.") logger.warning("No Hugging Face token provided. Model may not load correctly.")
# Initialize model # Initialize model
model_name = model_size if isinstance(model_size, str) else model_size.value
self._model = UltravoxModel(model_name=model_name) self._model = UltravoxModel(model_name=model_name)
# Initialize service state # Initialize service state
@@ -219,9 +218,60 @@ class UltravoxSTTService(AIService):
self._temperature = temperature self._temperature = temperature
self._max_tokens = max_tokens self._max_tokens = max_tokens
self._connection_active = False self._connection_active = False
self._warm_up_duration_sec = 1
logger.info(f"Initialized UltravoxSTTService with model: {model_name}") logger.info(f"Initialized UltravoxSTTService with model: {model_name}")
async def warm_up_model(self):
"""Warm up the model with silent audio to improve first inference performance.
This method generates a short segment of silent audio and runs it through
the model to ensure the model is fully loaded and optimized for the first
real inference request.
"""
logger.info("Warming up Ultravox model with silent audio...")
# Generate silent audio at 16kHz sample rate
sample_rate = 16000
silent_audio = self._generate_silent_audio(sample_rate, self._warm_up_duration_sec)
try:
# Process the silent audio with the model
messages = [{"role": "user", "content": "<|audio|>\n"}]
warmup_generator = self._model.generate(
messages=messages,
temperature=self._temperature,
max_tokens=self._max_tokens,
audio=silent_audio,
)
# Consume the generator to actually run the inference
async for _ in warmup_generator:
pass
logger.info("Model warm-up completed successfully")
except Exception as e:
logger.warning(f"Model warm-up failed: {e}")
def _generate_silent_audio(self, sample_rate=16000, duration_sec=1.0):
"""Generate silent audio as a numpy array.
Args:
sample_rate: Sample rate in Hz
duration_sec: Duration of silence in seconds
Returns:
np.ndarray: Float32 array of zeros representing silent audio
"""
# Calculate number of samples
num_samples = int(sample_rate * duration_sec)
# Create silent audio as float32 in the [-1.0, 1.0] range
silent_audio = np.zeros(num_samples, dtype=np.float32)
logger.info(f"Generated {duration_sec}s of silent audio ({num_samples} samples)")
return silent_audio
def can_generate_metrics(self) -> bool: def can_generate_metrics(self) -> bool:
"""Indicates whether this service can generate metrics. """Indicates whether this service can generate metrics.
@@ -238,6 +288,9 @@ class UltravoxSTTService(AIService):
""" """
await super().start(frame) await super().start(frame)
self._connection_active = True self._connection_active = True
await self.warm_up_model()
logger.info("UltravoxSTTService started") logger.info("UltravoxSTTService started")
async def stop(self, frame: EndFrame): async def stop(self, frame: EndFrame):
@@ -350,17 +403,18 @@ class UltravoxSTTService(AIService):
if self._model: if self._model:
try: try:
logger.info("Generating text from audio using model...") logger.info("Generating text from audio using model...")
full_response = ""
# Start metrics tracking # Start metrics tracking
await self.start_ttfb_metrics() await self.start_ttfb_metrics()
await self.start_processing_metrics() await self.start_processing_metrics()
async for response in self.model.generate( yield LLMFullResponseStartFrame()
messages=[{"role": "user", "content": "<|audio|>\n"}],
temperature=self.temperature, async for response in self._model.generate(
max_tokens=self.max_tokens, messages=[{"role": "user", "content": "<|audio|>\n"}],
audio=audio_float32, temperature=self._temperature,
max_tokens=self._max_tokens,
audio=audio_float32,
): ):
# Stop TTFB metrics after first response # Stop TTFB metrics after first response
await self.stop_ttfb_metrics() await self.stop_ttfb_metrics()
@@ -370,18 +424,12 @@ class UltravoxSTTService(AIService):
delta = chunk["choices"][0]["delta"] delta = chunk["choices"][0]["delta"]
if "content" in delta: if "content" in delta:
new_text = delta["content"] new_text = delta["content"]
full_response += new_text if new_text:
yield LLMTextFrame(text=new_text.strip())
# Stop processing metrics after completion # Stop processing metrics after completion
await self.stop_processing_metrics() await self.stop_processing_metrics()
logger.info(f"Generated text: {full_response}")
# Create a transcription frame with the generated text
yield LLMFullResponseStartFrame()
text_frame = LLMTextFrame(text=full_response.strip())
yield text_frame
yield LLMFullResponseEndFrame() yield LLMFullResponseEndFrame()
except Exception as e: except Exception as e: