Subh775's picture
Claude Opus 5.5
Add Gradio meeting summarizer app
0db4022
Raw History Blame Contribute Delete
3.98 kB
"""
Pydantic data models for the meeting intelligence pipeline.
"""
from __future__ import annotations
import uuid
from datetime import datetime
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
# ---------------------------------------------------------------------------
# Transcription
# ---------------------------------------------------------------------------
class TranscriptionSegment(BaseModel):
"""A single segment returned by Whisper."""
start: float
end: float
text: str
# ---------------------------------------------------------------------------
# Diarization
# ---------------------------------------------------------------------------
class DiarizationSegment(BaseModel):
"""A single speaker turn returned by pyannote."""
start: float
end: float
speaker: str
# ---------------------------------------------------------------------------
# Aligned (merged) segment
# ---------------------------------------------------------------------------
class AlignedSegment(BaseModel):
"""Transcript segment associated with a speaker."""
start: float
end: float
speaker: str
text: str
# ---------------------------------------------------------------------------
# Meeting Intelligence
# ---------------------------------------------------------------------------
class ActionItem(BaseModel):
task: str
owner: str = "Unassigned"
deadline: str = "Not specified"
priority: str = "Not specified"
class MeetingIntelligence(BaseModel):
executive_summary: str = ""
key_points: List[str] = Field(default_factory=list)
pain_points: List[str] = Field(default_factory=list)
decisions: List[str] = Field(default_factory=list)
action_items: List[ActionItem] = Field(default_factory=list)
recommendations: List[str] = Field(default_factory=list)
follow_ups: List[str] = Field(default_factory=list)
open_questions: List[str] = Field(default_factory=list)
# ---------------------------------------------------------------------------
# Meeting Record (top-level entity)
# ---------------------------------------------------------------------------
class MeetingRecord(BaseModel):
meeting_id: str = Field(default_factory=lambda: str(uuid.uuid4()))
filename: str = ""
created_at: datetime = Field(default_factory=datetime.now)
duration: float = 0.0
language: str = "en"
segments: List[AlignedSegment] = Field(default_factory=list)
intelligence: Optional[MeetingIntelligence] = None
speaker_map: Dict[str, str] = Field(default_factory=dict)
# -- helpers ----------------------------------------------------------
def get_speaker_label(self, original_label: str) -> str:
"""Return the user-assigned name for a speaker, or the original."""
return self.speaker_map.get(original_label, original_label)
def get_formatted_transcript(self) -> str:
"""Full transcript with timestamps and speaker labels."""
lines: list[str] = []
for seg in self.segments:
ts = f"[{format_time(seg.start)} - {format_time(seg.end)}]"
speaker = self.get_speaker_label(seg.speaker)
lines.append(f"{ts}\n{speaker}:\n{seg.text}\n")
return "\n".join(lines)
def get_plain_transcript(self) -> str:
"""Plain speaker: text transcript for LLM consumption."""
lines: list[str] = []
for seg in self.segments:
speaker = self.get_speaker_label(seg.speaker)
lines.append(f"{speaker}: {seg.text}")
return "\n".join(lines)
# ---------------------------------------------------------------------------
# Utilities
# ---------------------------------------------------------------------------
def format_time(seconds: float) -> str:
"""Convert seconds to HH:MM:SS."""
h = int(seconds // 3600)
m = int((seconds % 3600) // 60)
s = int(seconds % 60)
return f"{h:02d}:{m:02d}:{s:02d}"