Skip to content

feat(voice): add speech_id to assistant message metrics - #6787

Open
hassannaftabb wants to merge 1 commit into
livekit:mainfrom
hassannaftabb:fix/metrics-report-speech-id
Open

feat(voice): add speech_id to assistant message metrics#6787
hassannaftabb wants to merge 1 commit into
livekit:mainfrom
hassannaftabb:fix/metrics-report-speech-id

Conversation

@hassannaftabb

Copy link
Copy Markdown

Closes #4387.

Problem

TTSMetrics carries a speech_id, and the llm_node / tts_node spans set lk.speech_id, but the assistant ChatMessage those describe carries no such id. metrics_collected events are not part of SessionReport, so joining a stored message to its trace or to the per-component metrics of the same turn takes external bookkeeping. One commenter on #4387 keeps an item.id -> speech_id map by hand.

Change

MetricsReport gains an optional speech_id, populated in the three paths that store an assistant message:

  • session.say (_tts_task_impl)
  • the reply pipeline (_pipeline_reply_task_impl)
  • realtime generation (_realtime_generation_task_impl)

This follows the provider_request_ids precedent: a new key on the existing TypedDict, so no existing field changes.

_early_assistant_metrics is left alone on purpose — it only feeds console rendering and never reaches a stored message.

One correction to the issue's framing

#4387 asks for this so tts_node_ttfb - TTSMetrics.ttfb gives sentence-tokenizer overhead. That subtraction no longer measures anything. tts_node_ttfb now anchors on the text handed to the TTS provider, so it reads the same as TTSMetrics.ttfb: both came out at 0.19998 for the same turn on the fake harness. The LLM-to-TTS buffering the reporter wanted is already exposed as llm_node_ttfs.

The id still looks worth having for the other reason, joining a persisted message to its lk.speech_id span, so I've written it up that way. Close this if you'd rather not add the field.

Tests

All three failed before the change:

  • test_assistant_metrics_share_speech_id_with_tts_metrics — pipeline path; asserts the message's id matches the one on the tts_metrics event from the same run
  • test_say_assistant_metrics_carry_speech_idsession.say path
  • an added assertion on test_realtime_response_id_is_available_on_assistant_message — realtime path

pytest --unit gives 1520 passed with no new failures against main. ruff check, ruff format --check, and mypy --platform linux -p livekit.agents are clean.

TTSMetrics and the llm_node/tts_node spans both carry a speech_id, but the
assistant ChatMessage they describe did not, so a stored message could not be
joined to its trace or to the metrics_collected events of the same turn.

Populate speech_id on the assistant metrics in all three paths that store an
assistant message: session.say, the reply pipeline, and realtime generation.
Follows the provider_request_ids precedent: an optional key on the existing
MetricsReport TypedDict, so no existing field changes.

Closes livekit#4387
@hassannaftabb
hassannaftabb requested a review from a team as a code owner August 11, 2026 11:00
@CLAassistant

CLAassistant commented Aug 11, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

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.

Cannot correlate TTSMetrics.ttfb with ChatMessage.metrics.tts_node_ttfb

2 participants