mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-25 17:57:09 +00:00
🔊(summary) improve logging of speaker assign
Structure logging of speaker assignment in json format to help assess its performance.
This commit is contained in:
@@ -8,9 +8,10 @@ Multiple speakers can map to the same participant (e.g. two people sharing
|
|||||||
one microphone). A participant with no matching speaker gets no assignment.
|
one microphone). A participant with no matching speaker gets no assignment.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import asdict, dataclass, field, is_dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -318,6 +319,24 @@ def _build_speaker_timelines(transcription: Any) -> dict[str, list[Interval]]:
|
|||||||
return intervals
|
return intervals
|
||||||
|
|
||||||
|
|
||||||
|
def _json_default(obj: Any) -> Any:
|
||||||
|
"""Encode datetimes, dataclasses, and pydantic models for `json.dumps`.
|
||||||
|
|
||||||
|
Intended to be used for logging of `resolve_speaker_identities` (input
|
||||||
|
and computed variables)
|
||||||
|
"""
|
||||||
|
if isinstance(obj, datetime):
|
||||||
|
return obj.isoformat()
|
||||||
|
if is_dataclass(obj) and not isinstance(obj, type):
|
||||||
|
return asdict(obj)
|
||||||
|
if hasattr(obj, "segments") and hasattr(obj, "word_segments"):
|
||||||
|
return {"segments": obj.segments, "word_segments": obj.word_segments}
|
||||||
|
if hasattr(obj, "model_dump"):
|
||||||
|
return obj.model_dump(mode="json")
|
||||||
|
|
||||||
|
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
|
||||||
|
|
||||||
|
|
||||||
def resolve_speaker_identities(
|
def resolve_speaker_identities(
|
||||||
metadata: dict[str, Any],
|
metadata: dict[str, Any],
|
||||||
transcription: Any,
|
transcription: Any,
|
||||||
@@ -344,17 +363,6 @@ def resolve_speaker_identities(
|
|||||||
)
|
)
|
||||||
speaker_timelines = _build_speaker_timelines(transcription)
|
speaker_timelines = _build_speaker_timelines(transcription)
|
||||||
|
|
||||||
logger.debug(
|
|
||||||
"Assignment inputs: %d participants, %d speakers\n%s\n%s\n%s",
|
|
||||||
len(participant_timelines),
|
|
||||||
len(speaker_timelines),
|
|
||||||
participant_timelines,
|
|
||||||
speaker_timelines,
|
|
||||||
_format_timelines_debug(
|
|
||||||
participant_timelines, participant_names, speaker_timelines
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
result = AssignmentResult()
|
result = AssignmentResult()
|
||||||
|
|
||||||
for speaker, speaker_intervals in speaker_timelines.items():
|
for speaker, speaker_intervals in speaker_timelines.items():
|
||||||
@@ -397,4 +405,30 @@ def resolve_speaker_identities(
|
|||||||
overlap_threshold,
|
overlap_threshold,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"recording_start_datetime": recording_start_datetime.isoformat(),
|
||||||
|
"recording_end_datetime": recording_end_datetime.isoformat(),
|
||||||
|
"metadata": metadata,
|
||||||
|
"transcription": transcription,
|
||||||
|
},
|
||||||
|
"computed": {
|
||||||
|
"speaker_timelines": speaker_timelines,
|
||||||
|
"participant_timelines": participant_timelines,
|
||||||
|
"result": result,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default=_json_default,
|
||||||
|
indent=2,
|
||||||
|
ensure_ascii=False,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
_format_timelines_debug(
|
||||||
|
participant_timelines, participant_names, speaker_timelines
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user