""" Analyze Call Transcript Datasets to Improve Linguistic Features Datasets: 1. https://www.kaggle.com/datasets/mealss/call-transcripts-scam-determinations 2. https://www.kaggle.com/datasets/teeconnie/scam-and-non-scam-call-conversation-dataset This will help improve: 1. SCAM_TERMS vocabulary 2. SCAM_PHRASES contextual patterns 3. LTS scoring weights """ import os import pandas as pd from collections import Counter import re from dotenv import load_dotenv load_dotenv() def download_datasets(): """Download both transcript datasets""" datasets = [ "mealss/call-transcripts-scam-determinations", "teeconnie/scam-and-non-scam-call-conversation-dataset" ] download_path = os.path.join(os.path.dirname(__file__), "transcript_data") os.makedirs(download_path, exist_ok=True) for dataset_name in datasets: print(f"\nšŸ“„ Downloading {dataset_name}...") dataset_folder = dataset_name.split('/')[-1] dataset_path = os.path.join(download_path, dataset_folder) os.makedirs(dataset_path, exist_ok=True) os.system(f'kaggle datasets download -d {dataset_name} -p "{dataset_path}" --unzip') print("\nāœ… All downloads complete!") return download_path def analyze_transcripts(data_path): """Analyze transcripts from multiple datasets to find scam patterns""" # Find all CSV files in all subdirectories csv_files = [] for root, dirs, files in os.walk(data_path): for file in files: if file.endswith('.csv'): csv_files.append(os.path.join(root, file)) if not csv_files: print("āŒ No CSV files found") return print(f"\nšŸ“„ Found {len(csv_files)} CSV file(s)") # Combine all datasets all_scam_texts = [] all_legit_texts = [] total_scam = 0 total_legit = 0 for csv_file in csv_files: print(f"\nšŸ“Š Processing: {os.path.basename(csv_file)}") try: df = pd.read_csv(csv_file) print(f" Rows: {len(df)}") print(f" Columns: {list(df.columns)}") # Identify transcript and label columns transcript_col = None label_col = None for col in df.columns: col_lower = col.lower() if 'transcript' in col_lower or 'text' in col_lower or 'call' in col_lower or 'conversation' in col_lower or 'message' in col_lower: transcript_col = col if 'scam' in col_lower or 'label' in col_lower or 'fraud' in col_lower or 'determination' in col_lower or 'class' in col_lower: label_col = col if not transcript_col: print(" āš ļø Could not find transcript column, skipping...") continue if not label_col: print(" āš ļø Could not find label column, skipping...") continue print(f" Using: {transcript_col} (text) + {label_col} (label)") # Separate scam and legitimate scam_mask = df[label_col].astype(str).str.lower().str.contains('scam|fraud|1|yes|true|positive', na=False, regex=True) legit_mask = df[label_col].astype(str).str.lower().str.contains('legit|normal|0|no|false|negative', na=False, regex=True) scam_df = df[sall_scam_texts] legit_texts = ' '.join(all_legit_texts) print(f" Scam: {len(scam_df)}, Legitimate: {len(legit_df)}") # Collect texts all_scam_texts.extend(scam_df[transcript_col].astype(str).str.lower().tolist()) all_legit_texts.extend(legit_df[transcript_col].astype(str).str.lower().tolist()) total_scam += len(scam_df) total_legit += len(legit_df) except Exception as e: print(f" āš ļø Error processing file: {e}") continue print(f"\n\nšŸ“ˆ Combined Dataset Statistics:") print(f" Total Scam calls: {total_scam}") print(f" Total Legitimate calls: {total_legit}") print(f" Datasets processed: {len(csv_files)}") if total_scam == 0 or total_legit == 0: print("\nāŒ Not enough data to analyze") return # Analyze scam transcripts for common patterns print("\nšŸ” Analyzing scam call patterns...") scam_texts = ' '.join(scam_df[transcript_col].astype(str).str.lower()) legit_texts = ' '.join(legit_df[transcript_col].astype(str).str.lower()) # Extract common words in scam calls scam_words = re.findall(r'\b\w+\b', scam_texts) legit_words = re.findall(r'\b\w+\b', legit_texts) scam_counter = Counter(scam_words) legit_counter = Counter(legit_words) # Find words that appear much more in scam calls scam_specific = {} for word, count in scam_counter.items(): if len(word) > 3: # Skip short words scam_freq = count / len(scam_words) legit_freq = legit_counter.get(word, 0) / max(len(legit_words), 1) if scam_freq > legit_freq * 3: # 3x more common in scams scam_specific[word] = (count, scam_freq / (legit_freq + 0.0001)) # Sort by ratio sorted_scam_words = sorted(scam_specific.items(), key=lambda x: x[1][1], reverse=True)[:50] print("\nšŸŽÆ Top 50 Scam-Specific Words (not in current SCAM_TERMS):") print(" (Words appearing 3x+ more in scam calls)") # Load current SCAM_TERMS to avoid duplicates import processor current_terms = set() for category in processor.SCAM_TERMS.values(): current_terms.update(category) current_terms = {term.lower() for term in current_terms} new_terms = [] for word, (count, ratio) in sorted_scam_words: if word not in current_terms: new_terms.append((word, count, ratio)) print("\n Word (Count, Scam/Legit Ratio)") print(" " + "-" * 40) for word, count, ratio in new_terms[:30]: print(f" {word:20s} ({count:4d}, {ratio:.1f}x)") # Extract common phrases (2-4 words) print("\n\nšŸ” Analyzing common scam phrases...") scam_phrases = [] for text in all_scam_texts: text_lower = text.lower() # Extract 2-4 word phrases words = text_lower.split() for i in range(len(words) - 1): for length in [2, 3, 4]: if i + length <= len(words): phrase = ' '.join(words[i:i+length]) if len(phrase) > 10: # Skip very short phrases scam_phrases.append(phrase) phrase_counter = Counter(scam_phrases) # Load current SCAM_PHRASES current_phrases = {phrase.lower() for phrase in processor.SCAM_PHRASES} print("\nšŸŽÆ Top 30 New Scam Phrases (not in current SCAM_PHRASES):") print(" " + "-" * 50) new_phrases = [] for phrase, count in phrase_counter.most_common(100): if phrase not in current_phrases and count > 5: # Appears 5+ times new_phrases.append((phrase, count)) for phrase, count in new_phrases[:30]: print(f" [{count:3d}x] {phrase}") # Save suggestions output_file = os.path.join(os.path.dirname(__file__), "linguistic_improvements.txt") with open(output_file, 'w') as f: f.write("VocalGuard Linguistic Feature Improvements\n") f.write("=" * 60 + "\n\n") f.write("NEW SCAM TERMS TO ADD:\n") f.write("-" * 60 + "\n") for word, count, ratio in new_terms[:50]: f.write(f"{word} (appears {count}x, {ratio:.1f}x more in scams)\n") f.write("\n\nNEW SCAM PHRASES TO ADD:\n") f.write("-" * 60 + "\n") for phrase, count in new_phrases[:50]: f.write(f"[{count}x] {phrase}\n") f.write("\n\nRECOMMENDATIONS:\n") f.write("-" * 60 + "\n") f.write("1. Add the top 20-30 new terms to SCAM_TERMS in processor.py\n") f.write("2. Add the top 10-15 new phrases to SCAM_PHRASES\n") f.write("3. Test on validation set to ensure no false positives\n") f.write("4. Re-evaluate LTS scoring weights if needed\n") print(f"\n\nāœ… Analysis complete!") print(f" Results saved to: {output_file}") print(f"\nšŸ’” Next Steps:") print(f" 1. Review {output_file}") print(f" 2. Add relevant terms/phrases to processor.py") print(f" 3. Test improved model") return new_terms, new_phrases def main(): print("=" * 60) print("šŸ¤– VocalGuard - Multi-Dataset Transcript Analysis") print("Improving Linguistic Threat Detection") print("=" * 60) # Check if data already exists data_path = os.path.join(os.path.dirname(__file__), "transcript_data") if not os.path.exists(data_path) or len(os.listdir(data_path)) < 2: print("\nšŸ“„ Downloading both transcript datasets...") download_datasets() else: print(f"āœ… Transcript data exists: {data_path}") # Analyze analyze_transcripts(data_path) if __name__ == "__main__": main()