Skip to content

AGT-2182: Add adaptive interruption handling and dynamic endpointing#4771

Merged
chenghao-mou merged 52 commits intomainfrom
chenghaomou/v1.5.0
Mar 19, 2026
Merged

AGT-2182: Add adaptive interruption handling and dynamic endpointing#4771
chenghao-mou merged 52 commits intomainfrom
chenghaomou/v1.5.0

Conversation

@chenghao-mou
Copy link
Member

No description provided.

@chenghao-mou chenghao-mou requested a review from a team February 9, 2026 12:01
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

chenghao-mou and others added 3 commits February 23, 2026 10:23
Co-authored-by: Théo Monnom <theo.monnom@outlook.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Théo Monnom <theo.8bits@gmail.com>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@chenghao-mou chenghao-mou changed the title AGT-2182: Add inference bargein and examples AGT-2182: Add adaptive interruption handling and dynamic endpotining Feb 26, 2026
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 4 new potential issues.

View 50 additional findings in Devin Review.

Open in Devin Review

Comment on lines +20 to +23
_logger_class = logging.getLoggerClass()
logging.setLoggerClass(Logger)
logger: Logger = logging.getLogger("livekit.agents") # type: ignore[assignment]
logging.setLoggerClass(_logger_class)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 logging.setLoggerClass globally mutates the logging module, affecting all loggers created concurrently

In log.py, the code temporarily sets the global logger class to Logger via logging.setLoggerClass(Logger), creates the livekit.agents logger, then restores the original class. This is not thread-safe: any logger created by another thread between lines 21 and 23 will inadvertently be a Logger instance. Additionally, any child loggers of livekit.agents created later (e.g., logging.getLogger("livekit.agents.voice")) will use the standard logging.Logger class and won't have the trace() or dev() methods, leading to AttributeError if those methods are ever called on a child logger.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +166 to +175
def serialize_model(self, handler: SerializerFunctionWrapHandler) -> Any:
# remove numpy arrays from the model dump
copy = self.model_copy(deep=True)
data = copy.speech_input, copy.probabilities
copy.speech_input, copy.probabilities = None, None
try:
serialized = handler(copy)
finally:
copy.speech_input, copy.probabilities = data
return serialized
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 OverlappingSpeechEvent.serialize_model corrupts original object's speech_input and probabilities on exception

In interruption.py:166-175, the serialize_model method makes a deep copy but then destructures it incorrectly. It saves data = copy.speech_input, copy.probabilities, sets the copy's fields to None, serializes, then restores from data. However, if handler(copy) raises an exception, the finally block restores the copy's fields — not the original's — so there's no actual corruption of self. But more importantly, model_copy(deep=True) on a Pydantic model containing numpy arrays may fail or produce unexpected results since numpy arrays aren't standard Pydantic-serializable types. The real issue is that data captures (copy.speech_input, copy.probabilities) as a tuple but the restore line copy.speech_input, copy.probabilities = data unpacks it back — this is fine syntactically but the entire deep copy + restore pattern is unnecessary since the copy is never used after the function returns.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +558 to +559
input_tokens=self._input_tokens,
output_tokens=self._output_tokens,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 TTS streaming metrics report cumulative _input_tokens/_output_tokens for every segment instead of per-segment

In tts.py, SynthesizeStream._set_token_usage sets instance-level self._input_tokens and self._output_tokens (lines 447-449). These values are then emitted in the TTSMetrics for every segment produced by _emit_metrics (line 558-559). If a TTS provider calls _set_token_usage once with cumulative totals, every subsequent segment's metrics will duplicate those same token counts, inflating the totals in ModelUsageCollector.collect() (usage.py:213-214) which sums them. Unlike characters_count which is per-segment (derived from len(text)), the token counts are not reset between segments.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@kath0la kath0la changed the title AGT-2182: Add adaptive interruption handling and dynamic endpotining AGT-2182: Add adaptive interruption handling and dynamic endpointing Mar 16, 2026
theomonnom and others added 8 commits March 17, 2026 21:55
… metrics_collected (#5124)

Co-authored-by: Chenghao Mou <chenghao.mou@livekit.io>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Théo Monnom <theo.monnom@outlook.com>
Co-authored-by: David Zhao <dz@livekit.io>
Copy link
Member

@theomonnom theomonnom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ship it! 🚀🚀

@chenghao-mou chenghao-mou merged commit 494766a into main Mar 19, 2026
19 of 21 checks passed
@chenghao-mou chenghao-mou deleted the chenghaomou/v1.5.0 branch March 19, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants