apertus-swiss-transparency / examples /ultimate_transparency_demo.py
Markus Clauss DIRU Vetsuisse
Initial commit - Apertus Swiss AI Transparency Dashboard
b65eda7
"""
πŸ‡¨πŸ‡­ Ultimate Apertus Transparency Demo
Shows EVERYTHING happening in the model - layer by layer, step by step
"""
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'src'))
import torch
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from apertus_core import ApertusCore
from transparency_analyzer import ApertusTransparencyAnalyzer
import warnings
warnings.filterwarnings('ignore')
class UltimateTransparencyDemo:
"""Complete transparency analysis of Apertus model"""
def __init__(self):
print("πŸ‡¨πŸ‡­ APERTUS ULTIMATE TRANSPARENCY DEMO")
print("=" * 60)
print("Loading Apertus model with full transparency enabled...")
self.apertus = ApertusCore(enable_transparency=True)
self.analyzer = ApertusTransparencyAnalyzer(self.apertus)
print("βœ… Model loaded! Ready for complete transparency analysis.\n")
def complete_analysis(self, text: str = "Apertus ist ein transparentes KI-Modell aus der Schweiz."):
"""Run complete transparency analysis on input text"""
print(f"πŸ” ANALYZING: '{text}'")
print("=" * 80)
# 1. Architecture Overview
print("\nπŸ—οΈ STEP 1: MODEL ARCHITECTURE")
self._show_architecture()
# 2. Token Breakdown
print("\nπŸ”€ STEP 2: TOKENIZATION")
self._show_tokenization(text)
# 3. Layer-by-Layer Processing
print("\n🧠 STEP 3: LAYER-BY-LAYER PROCESSING")
hidden_states = self._analyze_all_layers(text)
# 4. Attention Analysis
print("\nπŸ‘οΈ STEP 4: ATTENTION PATTERNS")
self._analyze_attention_all_layers(text)
# 5. Token Prediction Process
print("\n🎲 STEP 5: TOKEN PREDICTION PROCESS")
self._analyze_prediction_process(text)
# 6. Summary
print("\nπŸ“Š STEP 6: TRANSPARENCY SUMMARY")
self._show_summary(text, hidden_states)
def _show_architecture(self):
"""Show model architecture details"""
config = self.apertus.model.config
total_params = sum(p.numel() for p in self.apertus.model.parameters())
print(f"πŸ—οΈ Model: {self.apertus.model_name}")
print(f"πŸ“Š Architecture Details:")
print(f" β€’ Layers: {config.num_hidden_layers}")
print(f" β€’ Attention Heads: {config.num_attention_heads}")
print(f" β€’ Hidden Size: {config.hidden_size}")
print(f" β€’ Vocab Size: {config.vocab_size:,}")
print(f" β€’ Parameters: {total_params:,}")
print(f" β€’ Context Length: {config.max_position_embeddings:,}")
if torch.cuda.is_available():
memory_used = torch.cuda.memory_allocated() / 1024**3
print(f" β€’ GPU Memory: {memory_used:.1f} GB")
def _show_tokenization(self, text):
"""Show detailed tokenization process"""
tokens = self.apertus.tokenizer.tokenize(text)
token_ids = self.apertus.tokenizer.encode(text)
print(f"πŸ“ Original Text: '{text}'")
print(f"πŸ”’ Token Count: {len(tokens)}")
print(f"πŸ”€ Tokens: {tokens}")
print(f"πŸ”’ Token IDs: {token_ids}")
# Show token-by-token breakdown
print("\nπŸ“‹ Token Breakdown:")
for i, (token, token_id) in enumerate(zip(tokens, token_ids[1:])): # Skip BOS if present
print(f" {i+1:2d}. '{token}' β†’ ID: {token_id}")
def _analyze_all_layers(self, text):
"""Analyze processing through all layers"""
inputs = self.apertus.tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = self.apertus.model(**inputs, output_hidden_states=True)
hidden_states = outputs.hidden_states
num_layers = len(hidden_states)
print(f"🧠 Processing through {num_layers} layers...")
layer_stats = []
# Analyze each layer
for layer_idx in range(0, num_layers, max(1, num_layers//8)): # Sample every ~8th layer
layer_state = hidden_states[layer_idx][0] # Remove batch dimension
# Calculate statistics
mean_activation = layer_state.mean().item()
std_activation = layer_state.std().item()
l2_norm = torch.norm(layer_state, dim=-1).mean().item()
max_activation = layer_state.max().item()
min_activation = layer_state.min().item()
layer_stats.append({
'layer': layer_idx,
'mean': mean_activation,
'std': std_activation,
'l2_norm': l2_norm,
'max': max_activation,
'min': min_activation
})
print(f" Layer {layer_idx:2d}: L2={l2_norm:.3f}, Mean={mean_activation:+.3f}, "
f"Std={std_activation:.3f}, Range=[{min_activation:+.2f}, {max_activation:+.2f}]")
return hidden_states
def _analyze_attention_all_layers(self, text):
"""Analyze attention patterns across all layers"""
inputs = self.apertus.tokenizer(text, return_tensors="pt")
tokens = self.apertus.tokenizer.convert_ids_to_tokens(inputs['input_ids'][0])
with torch.no_grad():
outputs = self.apertus.model(**inputs, output_attentions=True)
attentions = outputs.attentions
print(f"πŸ‘οΈ Analyzing attention across {len(attentions)} layers...")
# Sample key layers for attention analysis
key_layers = [0, len(attentions)//4, len(attentions)//2, 3*len(attentions)//4, len(attentions)-1]
for layer_idx in key_layers:
if layer_idx >= len(attentions):
continue
attention_weights = attentions[layer_idx][0] # [num_heads, seq_len, seq_len]
# Average attention across heads
avg_attention = attention_weights.mean(dim=0).cpu().numpy()
# Find most attended tokens
total_attention_received = avg_attention.sum(axis=0)
total_attention_given = avg_attention.sum(axis=1)
print(f"\n Layer {layer_idx} Attention Summary:")
print(f" β€’ Matrix Shape: {avg_attention.shape}")
print(f" β€’ Attention Heads: {attention_weights.shape[0]}")
# Top tokens that receive attention
top_receivers = np.argsort(total_attention_received)[-3:][::-1]
print(f" β€’ Most Attended Tokens:")
for i, token_idx in enumerate(top_receivers):
if token_idx < len(tokens):
attention_score = total_attention_received[token_idx]
print(f" {i+1}. '{tokens[token_idx]}' (score: {attention_score:.3f})")
# Attention distribution stats
attention_entropy = -np.sum(avg_attention * np.log(avg_attention + 1e-12), axis=1).mean()
print(f" β€’ Avg Attention Entropy: {attention_entropy:.3f}")
def _analyze_prediction_process(self, text):
"""Analyze the token prediction process in detail"""
print(f"🎲 Predicting next tokens for: '{text}'")
# Get model predictions for next token
inputs = self.apertus.tokenizer(text, return_tensors="pt")
with torch.no_grad():
outputs = self.apertus.model(**inputs)
logits = outputs.logits[0, -1, :] # Last token predictions
# Convert to probabilities
probabilities = torch.nn.functional.softmax(logits, dim=-1)
# Get top predictions
top_probs, top_indices = torch.topk(probabilities, 10)
print(f"🎯 Top 10 Next Token Predictions:")
for i in range(10):
token_id = top_indices[i].item()
token = self.apertus.tokenizer.decode([token_id])
prob = top_probs[i].item()
logit = logits[token_id].item()
# Confidence indicator
if prob > 0.2:
confidence = "πŸ”₯ High"
elif prob > 0.05:
confidence = "βœ… Medium"
elif prob > 0.01:
confidence = "⚠️ Low"
else:
confidence = "❓ Very Low"
print(f" {i+1:2d}. '{token}' β†’ {prob:.1%} (logit: {logit:+.2f}) {confidence}")
# Probability distribution stats
entropy = -torch.sum(probabilities * torch.log(probabilities + 1e-12)).item()
max_prob = probabilities.max().item()
top_10_prob_sum = top_probs.sum().item()
print(f"\nπŸ“Š Prediction Statistics:")
print(f" β€’ Entropy: {entropy:.2f} (randomness measure)")
print(f" β€’ Max Probability: {max_prob:.1%}")
print(f" β€’ Top-10 Probability Sum: {top_10_prob_sum:.1%}")
print(f" β€’ Confidence: {'High' if max_prob > 0.5 else 'Medium' if max_prob > 0.2 else 'Low'}")
def _show_summary(self, text, hidden_states):
"""Show complete transparency summary"""
num_tokens = len(self.apertus.tokenizer.tokenize(text))
num_layers = len(hidden_states)
print(f"πŸ“‹ COMPLETE TRANSPARENCY ANALYSIS SUMMARY")
print("=" * 60)
print(f"πŸ”€ Input: '{text}'")
print(f"πŸ“Š Processed through:")
print(f" β€’ {num_tokens} tokens")
print(f" β€’ {num_layers} transformer layers")
print(f" β€’ {self.apertus.model.config.num_attention_heads} attention heads per layer")
print(f" β€’ {self.apertus.model.config.hidden_size} hidden dimensions")
total_operations = num_tokens * num_layers * self.apertus.model.config.num_attention_heads
print(f" β€’ ~{total_operations:,} attention operations")
if torch.cuda.is_available():
memory_used = torch.cuda.memory_allocated() / 1024**3
print(f" β€’ {memory_used:.1f} GB GPU memory used")
print(f"\n✨ This is what makes Apertus transparent:")
print(f" πŸ” Every layer activation is accessible")
print(f" πŸ‘οΈ Every attention weight is visible")
print(f" 🎲 Every prediction probability is shown")
print(f" 🧠 Every hidden state can be analyzed")
print(f" πŸ“Š Complete mathematical operations are exposed")
print(f"\nπŸ‡¨πŸ‡­ Swiss AI Transparency: No black boxes, complete visibility! ✨")
def main():
"""Run the ultimate transparency demo"""
try:
demo = UltimateTransparencyDemo()
# Default examples
examples = [
"Apertus ist ein transparentes KI-Modell aus der Schweiz.",
"Machine learning requires transparency for trust.",
"La Suisse développe des modèles d'IA transparents.",
"Artificial intelligence should be explainable.",
]
print("🎯 Choose an example or enter your own text:")
for i, example in enumerate(examples, 1):
print(f"{i}. {example}")
print("5. Enter custom text")
try:
choice = input("\nChoice (1-5): ").strip()
if choice == "5":
text = input("Enter your text: ").strip()
if not text:
text = examples[0] # Default fallback
elif choice in ["1", "2", "3", "4"]:
text = examples[int(choice) - 1]
else:
print("Invalid choice, using default...")
text = examples[0]
except (KeyboardInterrupt, EOFError):
text = examples[0]
print(f"\nUsing default: {text}")
# Run complete analysis
demo.complete_analysis(text)
print("\nπŸŽ‰ Complete transparency analysis finished!")
print("This demonstrates the full transparency capabilities of Apertus Swiss AI.")
except Exception as e:
print(f"❌ Error during demo: {str(e)}")
print("Make sure the model is properly loaded and accessible.")
if __name__ == "__main__":
main()