The following is the previous README, retained for context. Its commands and performance claims have not been independently validated against a frozen test set; use the root README for the current quick start.
A comprehensive implementation for fraud and scam detection using advanced Natural Language Processing techniques. What began as a pure classification playground (LogReg โ BERT โ DistilBERT) has evolved into a full-stack pipeline where every model can both detect and explain fraud attempts. Today we ship lightweight LoRA-tuned LLMs (Phi-3.5, Gemma-2, Qwen2.5, BART Joint) that deliver production-ready multiclass predictions and evidence-backed contextual reasoning in one pass.
๐ GitHub Repository: https://github.com/RockENZO/NLP-Cyber-Harm-Detection.git
๐ Hugging Face Space (Demo): https://huggingface.co/spaces/RockENZ0/fraud-detection-ai
This project implements advanced models for detecting fraudulent content (scams, phishing, spam) in text data using state-of-the-art transformer architectures. The project evolved through multiple phases:
Initial implementation focused on pure classification using transformer models to detect fraud types with high accuracy.
Comprehensive analysis of reasoning-capable LLMs (GPT-2, FLAN-T5 variants) for post-hoc fraud explanation generation, with performance benchmarking and quality assessment.
Developed a unified, text-to-text approach using FLAN-T5 that produces both the class label and a concise explanation in a single generation. This works directly with your existing CSV (final_fraud_detection_dataset.csv) that has text and detailed_category columns. If your dataset also has rationale fields such as explanation or rationale, the trainer will use them; otherwise, it auto-synthesizes short label-specific explanations.
State-of-the-art custom architecture combining classification and rich contextual reasoning in a single unified model with superior performance.
Fine-tuned lightweight instruction-following LLMs (2B-3.8B parameters) that provide TRUE contextual reasoning with deep fraud analysis, not template-based responses. Achieves 94-96% classification accuracy while generating coherent, multi-paragraph explanations citing specific fraud indicators.
BREAKTHROUGH: Fine-tuned lightweight LLMs (Phi-3.5, Qwen2.5, Gemma-2) that provide genuine reasoning instead of templates:
Classification: reward_scam
Confidence: 96%
Detailed Analysis:
This message presents as: "Congratulations! You've won a $1000 Amazon gift card..."
Fraud Indicators Identified:
1. **Unsolicited Prize Announcement**: Claims winning without prior participation
2. **Unrealistic Reward Value**: $1000 gift card without legitimate context
3. **Urgency Pressure**: "Click now" creates time pressure to bypass thinking
Threat Tactics:
- **Urgency Manipulation (HIGH)**: Employs time-pressure tactics to bypass
critical thinking and force hasty decisions without proper verification.
- **Reward Deception**: Uses unsolicited prize claims to create excitement
and lower recipient's guard against potential fraud.
Request Pattern Analysis:
The message directs recipients to click external links, a common vector for
phishing attacks and malware distribution. Legitimate organizations rarely
require link-based verification for prize claims.
Risk Assessment: CRITICAL
Recommended Actions:
1. Do not click any links or download attachments
2. Do not provide any personal or financial information
3. Verify sender authenticity through official channels
4. Report as reward scam to appropriate authorities
# 1. Prepare high-quality reasoning dataset
python scripts/prepare_reasoning_data.py \
--csv_path final_fraud_detection_dataset.csv \
--output_path training_data/fraud_reasoning.jsonl \
--format_type multi_task
# 2. Fine-tune Phi-3.5-mini (2-3 hours on Kaggle T4)
python scripts/train_reasoning_llm.py \
--model_name microsoft/Phi-3.5-mini-instruct \
--training_data training_data/fraud_reasoning.jsonl \
--output_dir models/phi-3.5-fraud-reasoning \
--use_4bit --use_lora
# 3. Run inference
python demos/reasoning_llm_demo.py \
--model_path models/phi-3.5-fraud-reasoning \
--interactive
docs/advanced_reasoning_llm_guide.mddocs/kaggle_training_guide.mdscripts/train_reasoning_llm.pydemos/reasoning_llm_demo.pyNEWEST: The project now features a state-of-the-art BART joint model (unified-bart-joint-enhanced) that combines classification and contextual reasoning in a single unified architecture:
BartForJointClassificationAndGeneration with dual heads:
| Available checkpoints: 5,482 | 10,964 | 16,446 | 21,928 |
training/unified-bart-joint-enhanced-reasoning.ipynb - Training pipeline for joint modeldemos/test-unified-bart-joint-enhanced.ipynb - Comprehensive testing and evaluation notebookmodels/unified-bart-joint-enhanced/ - Trained model with 4 checkpointsInput: "Congratulations! You've won a $1000 gift card. Click here to claim now!"
Predicted: reward_scam
Confidence: 0.987 (98.7%)
Enhanced Reasoning: The message contains typical reward scam indicators including
unsolicited prize announcement, urgency ("claim now"), request for immediate action
via suspicious link, and promises of high-value rewards without prior participation.
These are classic tactics used to lure victims into providing personal information
or making fraudulent payments.
The notebook demos/test-unified-bart-joint-enhanced.ipynb is fully Kaggle-compatible:
unified-bart-joint-enhanced folder as a Kaggle DatasetNEW: The project now includes a production-ready DistilBERT model with significant advantages:
The DistilBERT model is trained for multiclass classification, providing granular fraud type detection rather than just binary fraud/legitimate classification.
โโโ README.md # This comprehensive documentation
โโโ requirements.txt # Python dependencies
โโโ final_fraud_detection_dataset.csv # Training dataset (Git LFS)
โโโ models/ # Saved trained models
โ โโโ bert_model/ # Trained BERT model files
โ โโโ bert_tokenizer/ # BERT tokenizer files
โ โโโ distilbert_model/ # Trained DistilBERT model files
โ โโโ distilbert_tokenizer/ # DistilBERT tokenizer files
โ โโโ unified-bart-joint-enhanced/ # BART joint classification + reasoning model
โ โ โโโ config.json # Model configuration
โ โ โโโ model.safetensors # Trained model weights (final, 21,928 steps)
โ โ โโโ generation_config.json # Generation parameters (beam=4, length_penalty=1.0)
โ โ โโโ tokenizer files # BART tokenizer (merges.txt, vocab.json, etc.)
โ โ โโโ checkpoint-5482/ # Early checkpoint (epoch 1)
โ โ โโโ checkpoint-10964/ # Mid-training checkpoint (epoch 2)
โ โ โโโ checkpoint-16446/ # Late-training checkpoint (epoch 3)
โ โ โโโ checkpoint-21928/ # Final checkpoint (epoch 4)
โ โโโ flan-t5-base/ # FLAN-T5 model files
โ โโโ unified-flan-t5-small/ # Unified FLAN-T5 model
โโโ training/ # Training scripts and notebooks
โ โโโ baseline_fraud_detection.py # Traditional ML baseline models
โ โโโ bert_fraud_detection.py # BERT-based classifier
โ โโโ fraud_detection_baseline.ipynb # Interactive Jupyter notebook
โ โโโ kaggle_fraud_detection.ipynb # Kaggle-optimized training notebook
โ โโโ unified-bart-joint-enhanced-reasoning.ipynb # BART joint model training
โ โโโ unified_t5_fraud_kaggle.ipynb # FLAN-T5 training notebook
โ โโโ unified_t5_fraud.py # FLAN-T5 training script
โโโ demos/ # Demo and testing tools
โ โโโ fraud_detection_demo.py # Full-featured demo script
โ โโโ fraud_detection_demo.ipynb # Interactive demo notebook
โ โโโ quick_demo.py # Quick verification script
โ โโโ test-unified-bart-joint-enhanced.ipynb # BART joint model testing (Kaggle-ready)
โ โโโ unified_flan_t5_demo.ipynb # FLAN-T5 demo notebook
โ โโโ unified_reasoning_demo.py # Unified reasoning demo script
โโโ reasoning/ # AI-powered reasoning pipeline
โ โโโ GPT2_Fraud_Reasoning.ipynb # GPT2-based reasoning analysis
โ โโโ KaggleLLMsReasoning.ipynb # Local reasoning notebook
โโโ docs/ # Documentation
โ โโโ nlp_terms_explanation.md # NLP concepts explanation
โโโ runs/ # Training run outputs and analysis results
โ โโโ fraud_analysis_results_20250916_155231.csv
โ โโโ fraud-detection-kaggle-training-bert-run.ipynb
โ โโโ gpt2_fraud_analysis_20250917_034015.csv
โ โโโ LLMsReasoningResultVisualization.ipynb
โ โโโ MultipleLLMsReasoning(small-models).ipynb
โ โโโ LLMsStats/ # LLM performance comparison charts
โ โโโ llm_category_heatmap.png
โ โโโ llm_comparison_table.csv
โ โโโ llm_performance_comparison.png
โ โโโ llm_quality_radar.png
โ โโโ llm_size_performance.png
โ โโโ llm_speed_quality_scatter.png
โ โโโ llm_model_size_comparison.png # Model size vs performance charts
โ โโโ llm_speed_quality_bubble.png # Speed vs quality bubble chart
โโโ .gitattributes # Git LFS configuration
โโโ .gitignore # Git ignore rules
โโโ .git/ # Git repository
Test the enhanced BART model with classification + contextual reasoning:
pip install torch transformers pandas numpy matplotlib seaborn jupyter
# Open the comprehensive testing notebook
jupyter notebook demos/test-unified-bart-joint-enhanced.ipynb
The notebook includes:
models/unified-bart-joint-enhanced/ as a Kaggle Datasetdemos/test-unified-bart-joint-enhanced.ipynb to KaggleIf you have already trained BERT/DistilBERT models:
pip install torch transformers pandas numpy matplotlib seaborn jupyter
python demos/quick_demo.py
jupyter notebook demos/fraud_detection_demo.ipynb
python demos/fraud_detection_demo.py
# Upload KaggleGPTReasoning.ipynb to Kaggle
# Enable GPU accelerator
# Run all cells for fraud detection + AI explanations
# Download results - no API costs
๐ LLM Performance Analysis: Check runs/LLMsStats/ for performance comparisons.
pip install -r requirements.txt
python training/baseline_fraud_detection.py
python training/bert_fraud_detection.py
final_fraud_detection_dataset.csv to Kaggletraining/fraud-detection-kaggle-training-bert-run.ipynbNote: The dataset is stored with Git LFS due to its size (~158MB). Clone with git lfs pull to download the full dataset. Large model files like model.zip are excluded from git to keep the repository size manageable.
The runs/LLMsStats/ directory contains LLM model analysis for fraud reasoning tasks.
training/baseline_fraud_detection.py)training/bert_fraud_detection.py)training/kaggle_fraud_detection.ipynb)training/unified-bart-joint-enhanced-reasoning.ipynb)BartForJointClassificationAndGeneration - Custom dual-head model
demos/test-unified-bart-joint-enhanced.ipynb)training/unified_t5_fraud.py)label: phishing | reason: asks for login via suspicious linkruns/fraud-detection-kaggle-training-bert-run.ipynb)reasoning/)reasoning/KaggleGPTReasoning.ipynb for local reasoning analysis

Once you have a trained model, use these tools to test and demonstrate fraud detection capabilities:
demos/fraud_detection_demo.ipynbdemos/fraud_detection_demo.pydemos/quick_demo.pyYour trained model can detect these 9 classes:
from demos.reasoning_llm_demo import FraudReasoningDetector
# Load fine-tuned model
detector = FraudReasoningDetector(
model_path="models/phi-3.5-fraud-reasoning",
base_model_name="microsoft/Phi-3.5-mini-instruct"
)
# Analyze message with detailed reasoning
result = detector.analyze("Congratulations! You won $1000. Click here now!")
print(f"Classification: {result['classification']}")
print(f"Confidence: {result['confidence']:.1%}")
print(f"Risk Level: {result['risk_level']}")
print(f"\nReasoning:\n{result['reasoning']}")
# Interactive mode
!python demos/reasoning_llm_demo.py \
--model_path models/phi-3.5-fraud-reasoning \
--interactive
Output Example:
Classification: reward_scam
Confidence: 96%
Risk Level: CRITICAL
Fraud Indicators:
1. Unsolicited Prize Announcement: Claims winning without participation
2. Unrealistic Reward Value: $1000 without legitimate context
3. Urgency Pressure: "Click now" creates time pressure
Threat Tactics:
- Urgency Manipulation (HIGH): Bypasses critical thinking through pressure
- Reward Deception: Uses prize claims to lower guard
Risk Assessment: CRITICAL
Recommended Actions:
1. Do not click any links or download attachments
2. Report as reward scam to authorities
# Load the enhanced BART joint model
from pathlib import Path
from transformers import AutoTokenizer, AutoConfig
import torch
# Load model and tokenizer
MODEL_DIR = Path('models/unified-bart-joint-enhanced')
tokenizer = AutoTokenizer.from_pretrained(str(MODEL_DIR))
config = AutoConfig.from_pretrained(str(MODEL_DIR))
joint_model = BartForJointClassificationAndGeneration.from_pretrained(str(MODEL_DIR), config=config)
joint_model.eval()
# Single prediction with reasoning
def predict_with_reasoning(text):
instruction = (
'Analyze this message and classify it into one of these categories: '
'job_scam, legitimate, phishing, popup_scam, refund_scam, reward_scam, '
'sms_spam, ssn_scam, tech_support_scam. '
'Then explain your reasoning by identifying specific suspicious elements.\n\n'
f'Message: {text}'
)
inputs = tokenizer([instruction], return_tensors='pt', truncation=True, max_length=256)
with torch.no_grad():
# Get classification
enc_out = joint_model.model.encoder(**inputs, return_dict=True)
pooled = joint_model.pooled_encoder(enc_out.last_hidden_state, inputs['attention_mask'])
cls_logits = joint_model.classifier(pooled)
pred_label = ID2LABEL[cls_logits.argmax(-1).item()]
confidence = torch.softmax(cls_logits, dim=-1).max().item()
# Generate reasoning
gen_ids = joint_model.generate(
**inputs,
max_new_tokens=128,
num_beams=4,
length_penalty=1.0,
no_repeat_ngram_size=3,
early_stopping=True
)
reasoning = tokenizer.decode(gen_ids[0], skip_special_tokens=True)
return {
'label': pred_label,
'confidence': confidence,
'reasoning': reasoning
}
# Example usage
result = predict_with_reasoning("Congratulations! You've won $1000. Click to claim now!")
print(f"๐ฏ Predicted: {result['label']}")
print(f"๐ Confidence: {result['confidence']:.3f}")
print(f"๐ก Reasoning: {result['reasoning']}")
Output Example:
๐ฏ Predicted: reward_scam
๐ Confidence: 0.987
๐ก Reasoning: The message contains typical reward scam indicators including unsolicited
prize announcement, urgency ("claim now"), request for immediate action via suspicious
link, and promises of high-value rewards without prior participation. These are classic
tactics used to lure victims into providing personal information or making fraudulent payments.
from demos.fraud_detection_demo import FraudDetectionDemo
demo = FraudDetectionDemo()
result = demo.predict_single("Your account has been compromised! Click here now!")
print(f"Prediction: {result['predicted_class']}")
print(f"Confidence: {result['confidence']:.4f}")
print(f"Is Fraud: {result['is_fraud']}")
texts = [
"Meeting at 3 PM tomorrow",
"URGENT: Verify your SSN now!",
"You won $10,000! Send fee to claim"
]
results = demo.predict_batch(texts)
for result in results:
print(f"{result['predicted_class']}: {result['text']}")
# In demos/fraud_detection_demo.ipynb
your_text = "Your Netflix subscription has expired. Update your payment method to continue watching."
result = predict_fraud(your_text)
display_prediction(result)
See demos/test-unified-bart-joint-enhanced.ipynb for comprehensive testing including:
Based on training results and baseline implementations:
| Model Type | Expected Accuracy | F1-Score | Reasoning Quality | Speed | Notes |
|---|---|---|---|---|---|
| Simple Rule-Based | 60-70% | 0.6-0.7 | โ None | Fast | Quick prototype |
| TF-IDF + LogReg | 80-90% | 0.8-0.9 | โ None | Fast | Good baseline |
| TF-IDF + SVM | 80-90% | 0.8-0.9 | โ None | Fast | Robust to noise |
| BERT Fine-tuned | 90-95% | 0.9-0.95 | โ None | Medium | Best classification only |
| DistilBERT Fine-tuned | 89-94% | 0.89-0.94 | โ None | Fast | 60% faster, 97% of BERT |
| FLAN-T5 Unified | 85-90% | 0.85-0.90 | โ ๏ธ Template | Medium | Short template reasons |
| BART Joint Enhanced | 91-93% | 0.91-0.93 | โ ๏ธ Template | Medium | Template-based explanations |
| Phi-3.5-mini (3.8B) | 94-96% | 0.94-0.96 | โ TRUE | Fast | ๐ BEST: Real reasoning โญ |
| Qwen2.5-3B | 93-95% | 0.93-0.95 | โ TRUE | Fast | Superior reasoning quality |
| Gemma-2-2b | 91-93% | 0.91-0.93 | โ TRUE | Very Fast | Most efficient |
| Mistral-7B | 94-97% | 0.94-0.97 | โ TRUE | Medium | Maximum quality |
Modern Reasoning LLMs (Phi-3.5, Qwen2.5) represent the next generation:
Comparison: Template-Based vs True Reasoning
| Aspect | BART/FLAN-T5 | Phi-3.5/Qwen2.5 |
|---|---|---|
| Classification | 91-93% | 94-96% โจ |
| Reasoning Type | Templates | Contextual โจ |
| Explanation Length | 1-2 sentences | Multi-paragraph โจ |
| Coherence | 6/10 | 9/10 โจ |
| Fraud Indicators | Generic | Specific โจ |
| Evidence-Based | โ No | โ Yes โจ |
| Training Time | 2-4 hours | 2-3 hours |
| Inference Speed | Fast | Fast-Medium |
BART/FLAN-T5 Output:
Classification: reward_scam
Reasoning: "Contains credential-stealing cues (links/requests for login)."
โ Generic, template-based, minimal insight
Phi-3.5 Output:
Classification: reward_scam (96% confidence)
Fraud Indicators Identified:
1. Unsolicited Prize Announcement: Claims winning without participation
2. Unrealistic Reward Value: $1000 without legitimate context
3. Urgency Pressure: "Click now" creates time pressure
Threat Tactics:
- Urgency Manipulation (HIGH): Bypasses critical thinking
- Reward Deception: Lowers guard through fake prizes
Request Pattern Analysis:
Directs to external links, common phishing vector. Legitimate
organizations don't require link-based prize verification.
Risk Assessment: CRITICAL
โ Deep analysis, specific indicators, actionable insights
models/bert_model/ and models/bert_tokenizer/ exist (for BERT)models/distilbert_model/ and models/distilbert_tokenizer/ exist (for DistilBERT)models/unified-bart-joint-enhanced/ exists (for BART joint model)pip install torch transformers pandas numpy matplotlib seabornpredict_batch()FraudDetectionDemo class as a starting point for applications# In training/baseline_fraud_detection.py
vectorizer = TfidfVectorizer(
max_features=5000, # Vocabulary size
stop_words='english', # Remove common words
ngram_range=(1, 2) # Use unigrams and bigrams
)
# In training/bert_fraud_detection.py
classifier = BERTFraudClassifier(
model_name='bert-base-uncased', # Or 'distilbert-base-uncased' for faster training
max_length=128, # Maximum sequence length
num_classes=2 # Binary classification
)
# In training/kaggle_fraud_detection.ipynb
model = DistilBertForSequenceClassification.from_pretrained(
'distilbert-base-uncased',
num_labels=10 # Multiclass classification (9 fraud types + legitimate)
)
batch_size = 16 # Can use larger batches due to lower memory usage
max_length = 128 # Maximum sequence length
epochs = 3 # Faster training allows more epochs
learning_rate = 2e-5 # DistilBERT learning rate
# In runs/fraud-detection-kaggle-training-bert-run.ipynb
batch_size = 16 # Adjust based on GPU memory
max_length = 128 # Maximum sequence length
epochs = 3 # Training epochs
learning_rate = 2e-5 # BERT learning rate
LOGISTIC_REGRESSION:
Accuracy: 0.889
F1-Score: 0.889
AUC Score: 0.944
SVM:
Accuracy: 0.889
F1-Score: 0.889
AUC Score: 0.944
BERT Evaluation Results:
precision recall f1-score support
normal 0.92 0.92 0.92 38
fraud 0.92 0.92 0.92 37
accuracy 0.92 75
macro avg 0.92 0.92 0.92 75
weighted avg 0.92 0.92 0.92 75
DistilBERT Multiclass Evaluation Results:
precision recall f1-score support
job_scam 0.89 0.94 0.91 32
legitimate 0.95 0.91 0.93 45
phishing 0.92 0.90 0.91 41
popup_scam 0.88 0.92 0.90 38
refund_scam 0.91 0.88 0.89 34
reward_scam 0.90 0.93 0.91 36
sms_spam 0.93 0.89 0.91 43
ssn_scam 0.87 0.91 0.89 35
tech_support_scam 0.94 0.89 0.91 37
accuracy 0.91 341
macro avg 0.91 0.91 0.91 341
weighted avg 0.91 0.91 0.91 341
๐ DistilBERT Overall Metrics:
Accuracy: 0.9120
F1-Score (Macro): 0.9088
F1-Score (Weighted): 0.9115
data = pd.DataFrame({
'message': ['text content here', ...],
'label': ['fraud', 'normal', ...]
})
# Add sentiment analysis
from textblob import TextBlob
def add_sentiment_features(text):
blob = TextBlob(text)
return {
'polarity': blob.sentiment.polarity,
'subjectivity': blob.sentiment.subjectivity
}
def custom_preprocess(text):
# Add domain-specific preprocessing
text = remove_urls(text)
text = normalize_currency(text)
return text
# Combine multiple models
def ensemble_predict(text):
lr_pred = lr_model.predict_proba(text)[0][1]
svm_pred = svm_model.predict_proba(text)[0][1]
bert_pred = bert_model.predict(text)['probabilities']['fraud']
# Weighted average
final_score = 0.3 * lr_pred + 0.3 * svm_pred + 0.4 * bert_pred
return 'fraud' if final_score > 0.5 else 'normal'
# Production-ready integration using the demo class
from demos.fraud_detection_demo import FraudDetectionDemo
detector = FraudDetectionDemo()
# Single prediction
result = detector.predict_single(user_message)
if result['is_fraud'] and result['confidence'] > 0.8:
alert_user(result['predicted_class'])
from flask import Flask, request, jsonify
from demos.fraud_detection_demo import FraudDetectionDemo
app = Flask(__name__)
detector = FraudDetectionDemo()
@app.route('/predict', methods=['POST'])
def predict():
text = request.json['text']
result = detector.predict_single(text)
return jsonify({
'prediction': result['predicted_class'],
'is_fraud': result['is_fraud'],
'confidence': result['confidence']
})
import streamlit as st
from demos.fraud_detection_demo import FraudDetectionDemo
st.title("๐ก๏ธ Fraud Detection System")
detector = FraudDetectionDemo()
text_input = st.text_area("Enter message to analyze:")
if st.button("Analyze"):
result = detector.predict_single(text_input)
if result['is_fraud']:
st.error(f"๐จ FRAUD DETECTED: {result['predicted_class']}")
else:
st.success("โ
Message appears legitimate")
st.write(f"Confidence: {result['confidence']:.2%}")
# Show probability distribution
st.bar_chart(result['all_probabilities'])
The models are evaluated using:
For fraud detection, Recall is often most important (donโt miss actual fraud).
Based on analysis of existing projects including:
training/baseline_fraud_detection.py - Traditional ML modelstraining/bert_fraud_detection.py - BERT training scriptruns/fraud-detection-kaggle-training-bert-run.ipynb - Kaggle BERT training notebookdemos/fraud_detection_demo.ipynb - Interactive demo notebookdemos/fraud_detection_demo.py - Full demo scriptdemos/quick_demo.py - Quick verificationmodels/bert_model/ - Trained BERT modelmodels/bert_tokenizer/ - BERT tokenizermodels/distilbert_model/ - Trained DistilBERT model (60% faster)models/distilbert_tokenizer/ - DistilBERT tokenizermodels/unified-bart-joint-enhanced/ - BART joint model (classification + reasoning) โญ LATESTmodels/unified-flan-t5-small/ - FLAN-T5 unified modelmodels/flan-t5-base/ - FLAN-T5 base modelmodels/model.zip - Compressed model bundle (excluded from git)# Test BART joint model (LATEST)
jupyter notebook demos/test-unified-bart-joint-enhanced.ipynb
# Quick test traditional models
python demos/quick_demo.py
# Interactive demo
jupyter notebook demos/fraud_detection_demo.ipynb
# Full demo
python demos/fraud_detection_demo.py
# Train from scratch
python training/baseline_fraud_detection.py
BartForJointClassificationAndGeneration custom architecturedemos/test-unified-bart-joint-enhanced.ipynb)Note: This is a baseline implementation. For production use, consider: