File size: 3,566 Bytes
8c85b97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import json
from datetime import datetime
from typing import Dict, Any, List
from langchain_openai import ChatOpenAI
from langchain_core.messages import SystemMessage, HumanMessage
from src.config.settings import Config

class MetadataExtractor:
    """
    Service to extract intelligent metadata from meeting transcripts using an LLM.
    Extracts: Title, Summary, Date, and Speaker Identities.
    """
    
    def __init__(self):
        # Use a cost-effective model for metadata extraction if possible
        # defaulting to the configured model
        self.llm = ChatOpenAI(
            model=Config.METADATA_MODEL,
            temperature=0, # Deterministic output
            openai_api_key=Config.OPENAI_API_KEY
        )
    
    def extract_metadata(self, transcript_text: str) -> Dict[str, Any]:
        """
        Analyze transcript to extract title, summary, date, and speaker mapping.
        """
        # Truncate transcript if too long to avoid token limits (e.g., first 15k chars)
        # usually enough for context
        analysis_text = transcript_text[:15000]
        
        system_prompt = """You are a Metadata Extraction Expert. Analyze the provided meeting transcript and extract the following information in JSON format:

1. "title": A concise, meaningful title for the meeting (e.g., "Q3 Marketing Strategy Review").
2. "summary": A brief 2-3 sentence summary of the meeting.
3. "meeting_date": The date the meeting likely took place, if mentioned (format: YYYY-MM-DD). If not explicitly mentioned, return null.
4. "speaker_mapping": A dictionary mapping generic speaker labels (SPEAKER_00, SPEAKER_01) to likely real names based on introductions or context. If unknown, leave empty.

Example Output:
{
    "title": "Project Alpha Kickoff",
    "summary": "The team discussed the timeline for Project Alpha. John assigned tasks to Sarah and Mike.",
    "meeting_date": "2023-10-12",
    "speaker_mapping": {
        "SPEAKER_00": "John Smith",
        "SPEAKER_01": "Sarah Jones"
    }
}
"""
        
        try:
            response = self.llm.invoke([
                SystemMessage(content=system_prompt),
                HumanMessage(content=f"Transcript:\n{analysis_text}")
            ])
            
            # Parse JSON from response
            content = response.content.strip()
            if "```json" in content:
                content = content.split("```json")[1].split("```")[0].strip()
            elif "```" in content:
                content = content.split("```")[1].split("```")[0].strip()
                
            metadata = json.loads(content)
            return metadata
            
        except Exception as e:
            print(f"Error extracting metadata: {e}")
            # Return safe defaults
            return {
                "title": "Untitled Meeting",
                "summary": "No summary available.",
                "meeting_date": None,
                "speaker_mapping": {}
            }

    def apply_speaker_mapping(self, transcript: str, mapping: Dict[str, str]) -> str:
        """
        Replace generic speaker labels with identified names in the transcript.
        """
        if not mapping:
            return transcript
            
        updated_transcript = transcript
        for generic, real_name in mapping.items():
            # Replace "SPEAKER_00" with "John Smith"
            # We handle common variations in formatting
            updated_transcript = updated_transcript.replace(generic, real_name)
            
        return updated_transcript