vocalguard-backend / backend /analyze_transcripts.py
Tawhid Bin Omar
backend update
8829ab0
Raw
History Blame Contribute Delete
9.31 kB
"""
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()