| """ |
| ๐จ๐ญ Advanced Apertus Transparency Toolkit |
| Native weights inspection, attention visualization, layer tracking, and tokenizer comparisons |
| """ |
|
|
| 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 typing import Dict, List, Optional |
| import time |
| from apertus_core import ApertusCore |
| from transparency_analyzer import ApertusTransparencyAnalyzer |
| import warnings |
| warnings.filterwarnings('ignore') |
|
|
| import sys |
| from io import StringIO |
| from datetime import datetime |
|
|
| class AdvancedTransparencyToolkit: |
| """Advanced transparency analysis with complete logging of all outputs""" |
| |
| def __init__(self): |
| self.apertus = ApertusCore(enable_transparency=True) |
| self.analyzer = ApertusTransparencyAnalyzer(self.apertus) |
| |
| |
| self.log_buffer = StringIO() |
| self.original_stdout = sys.stdout |
| |
| |
| self.log_and_print("๐จ๐ญ ADVANCED APERTUS TRANSPARENCY TOOLKIT") |
| self.log_and_print("=" * 70) |
| self.log_and_print("โ
Advanced toolkit ready!\n") |
| |
| def log_and_print(self, message): |
| """Print to console AND capture to log""" |
| print(message) |
| self.log_buffer.write(message + "\n") |
| |
| def start_logging(self): |
| """Start capturing all print output""" |
| sys.stdout = self |
| |
| def stop_logging(self): |
| """Stop capturing and restore normal output""" |
| sys.stdout = self.original_stdout |
| |
| def write(self, text): |
| """Capture output for logging""" |
| self.original_stdout.write(text) |
| self.log_buffer.write(text) |
| |
| def flush(self): |
| """Flush both outputs""" |
| self.original_stdout.flush() |
| |
| def native_weights_inspection(self, layer_pattern: str = "layers.15.self_attn"): |
| """Native inspection of model weights with detailed analysis""" |
| print(f"โ๏ธ NATIVE WEIGHTS INSPECTION: {layer_pattern}") |
| print("=" * 70) |
| |
| matching_layers = [] |
| for name, module in self.apertus.model.named_modules(): |
| if layer_pattern in name and hasattr(module, 'weight'): |
| matching_layers.append((name, module)) |
| |
| if not matching_layers: |
| print(f"โ No layers found matching pattern: {layer_pattern}") |
| return |
| |
| for name, module in matching_layers[:3]: |
| print(f"\n๐ Layer: {name}") |
| print("-" * 50) |
| |
| |
| weights = module.weight.data.cpu() |
| if weights.dtype == torch.bfloat16: |
| weights = weights.float() |
| weights = weights.numpy() |
| |
| |
| print(f"๐ Weight Statistics:") |
| print(f" Shape: {weights.shape}") |
| print(f" Parameters: {weights.size:,}") |
| print(f" Memory: {weights.nbytes / 1024**2:.1f} MB") |
| print(f" Data type: {weights.dtype}") |
| |
| |
| print(f"\n๐ Distribution Analysis:") |
| print(f" Mean: {np.mean(weights):+.6f}") |
| print(f" Std: {np.std(weights):.6f}") |
| print(f" Min: {np.min(weights):+.6f}") |
| print(f" Max: {np.max(weights):+.6f}") |
| print(f" Range: {np.max(weights) - np.min(weights):.6f}") |
| |
| |
| thresholds = [1e-4, 1e-3, 1e-2, 1e-1] |
| print(f"\n๐ธ๏ธ Sparsity Analysis:") |
| for threshold in thresholds: |
| sparse_ratio = np.mean(np.abs(weights) < threshold) |
| print(f" |w| < {threshold:.0e}: {sparse_ratio:.1%}") |
| |
| |
| weight_magnitudes = np.abs(weights.flatten()) |
| percentiles = [50, 90, 95, 99, 99.9] |
| print(f"\n๐ Magnitude Percentiles:") |
| for p in percentiles: |
| value = np.percentile(weight_magnitudes, p) |
| print(f" {p:4.1f}%: {value:.6f}") |
| |
| |
| if hasattr(module.weight, 'grad') and module.weight.grad is not None: |
| grad = module.weight.grad.data.cpu() |
| if grad.dtype == torch.bfloat16: |
| grad = grad.float() |
| grad = grad.numpy() |
| print(f"\n๐ฏ Gradient Statistics:") |
| print(f" Mean: {np.mean(grad):+.6e}") |
| print(f" Std: {np.std(grad):.6e}") |
| print(f" Max: {np.max(np.abs(grad)):.6e}") |
| |
| |
| if 'q_proj' in name or 'k_proj' in name or 'v_proj' in name: |
| print(f"\n๐ Attention Projection Analysis:") |
| |
| if len(weights.shape) == 2: |
| |
| col_norms = np.linalg.norm(weights, axis=0) |
| row_norms = np.linalg.norm(weights, axis=1) |
| |
| print(f" Output dim norms - Mean: {np.mean(col_norms):.4f}, Std: {np.std(col_norms):.4f}") |
| print(f" Input dim norms - Mean: {np.mean(row_norms):.4f}, Std: {np.std(row_norms):.4f}") |
| |
| |
| zero_cols = np.sum(col_norms < 1e-6) |
| zero_rows = np.sum(row_norms < 1e-6) |
| if zero_cols > 0 or zero_rows > 0: |
| print(f" โ ๏ธ Zero columns: {zero_cols}, Zero rows: {zero_rows}") |
| |
| print(f"\nโจ Native weights inspection completed!") |
| |
| def real_time_attention_visualization(self, text: str, num_steps: int = 3): |
| """Real-time attention pattern visualization during generation""" |
| print(f"๐๏ธ REAL-TIME ATTENTION VISUALIZATION") |
| print("=" * 70) |
| print(f"Text: '{text}'") |
| |
| |
| inputs = self.apertus.tokenizer(text, return_tensors="pt") |
| input_ids = inputs['input_ids'] |
| |
| |
| device = next(self.apertus.model.parameters()).device |
| input_ids = input_ids.to(device) |
| |
| attention_history = [] |
| |
| for step in range(num_steps): |
| print(f"\n--- GENERATION STEP {step + 1} ---") |
| |
| |
| current_text = self.apertus.tokenizer.decode(input_ids[0]) |
| print(f"Current: '{current_text}'") |
| |
| |
| with torch.no_grad(): |
| outputs = self.apertus.model(input_ids, output_attentions=True) |
| logits = outputs.logits[0, -1, :] |
| attentions = outputs.attentions |
| |
| |
| last_layer_attention = attentions[-1][0] |
| |
| attention_cpu = last_layer_attention.mean(dim=0).cpu() |
| if attention_cpu.dtype == torch.bfloat16: |
| attention_cpu = attention_cpu.float() |
| avg_attention = attention_cpu.numpy() |
| |
| |
| tokens = self.apertus.tokenizer.convert_ids_to_tokens(input_ids[0]) |
| |
| print(f"Tokens: {tokens}") |
| print(f"Attention matrix shape: {avg_attention.shape}") |
| |
| |
| if len(tokens) > 1: |
| last_token_attention = avg_attention[-1, :-1] |
| top_attended = np.argsort(last_token_attention)[-3:][::-1] |
| |
| print(f"Last token '{tokens[-1]}' attends most to:") |
| for i, token_idx in enumerate(top_attended): |
| if token_idx < len(tokens) - 1: |
| attention_score = last_token_attention[token_idx] |
| print(f" {i+1}. '{tokens[token_idx]}' ({attention_score:.3f})") |
| |
| |
| attention_history.append({ |
| 'step': step + 1, |
| 'tokens': tokens.copy(), |
| 'attention': avg_attention.copy(), |
| 'text': current_text |
| }) |
| |
| |
| probabilities = torch.nn.functional.softmax(logits, dim=-1) |
| next_token_id = torch.multinomial(probabilities, 1) |
| input_ids = torch.cat([input_ids, next_token_id.unsqueeze(0)], dim=-1) |
| |
| next_token = self.apertus.tokenizer.decode([next_token_id.item()]) |
| print(f"Next token: '{next_token}'") |
| |
| print(f"\nโ
Real-time attention visualization completed!") |
| return attention_history |
| |
| def layer_evolution_real_time_tracking(self, text: str): |
| """Real-time tracking of layer evolution during forward pass""" |
| print(f"๐ง REAL-TIME LAYER EVOLUTION TRACKING") |
| print("=" * 70) |
| print(f"Text: '{text}'") |
| |
| inputs = self.apertus.tokenizer(text, return_tensors="pt") |
| tokens = self.apertus.tokenizer.convert_ids_to_tokens(inputs['input_ids'][0]) |
| |
| |
| device = next(self.apertus.model.parameters()).device |
| inputs = {k: v.to(device) for k, v in inputs.items()} |
| |
| print(f"Tokens: {tokens}") |
| print(f"Tracking through {self.apertus.model.config.num_hidden_layers} layers...\n") |
| |
| |
| with torch.no_grad(): |
| start_time = time.time() |
| outputs = self.apertus.model(**inputs, output_hidden_states=True) |
| forward_time = time.time() - start_time |
| |
| hidden_states = outputs.hidden_states |
| |
| |
| layer_evolution = [] |
| |
| print(f"โฑ๏ธ Forward pass took {forward_time:.3f}s") |
| print(f"\n๐ Layer-by-Layer Evolution:") |
| |
| |
| sample_layers = list(range(0, len(hidden_states), max(1, len(hidden_states)//10))) |
| |
| for i, layer_idx in enumerate(sample_layers): |
| layer_state = hidden_states[layer_idx][0] |
| |
| |
| token_stats = [] |
| for token_pos in range(layer_state.shape[0]): |
| token_vector = layer_state[token_pos] |
| |
| stats = { |
| 'token': tokens[token_pos] if token_pos < len(tokens) else '<pad>', |
| 'l2_norm': torch.norm(token_vector).item(), |
| 'mean': token_vector.mean().item(), |
| 'std': token_vector.std().item(), |
| 'max': token_vector.max().item(), |
| 'min': token_vector.min().item(), |
| 'sparsity': (torch.abs(token_vector) < 0.01).float().mean().item() |
| } |
| token_stats.append(stats) |
| |
| |
| layer_stats = { |
| 'layer': layer_idx, |
| 'avg_l2_norm': np.mean([s['l2_norm'] for s in token_stats]), |
| 'max_l2_norm': np.max([s['l2_norm'] for s in token_stats]), |
| 'avg_activation': np.mean([s['mean'] for s in token_stats]), |
| 'activation_spread': np.std([s['mean'] for s in token_stats]), |
| 'avg_sparsity': np.mean([s['sparsity'] for s in token_stats]) |
| } |
| |
| layer_evolution.append(layer_stats) |
| |
| print(f"Layer {layer_idx:2d}: L2={layer_stats['avg_l2_norm']:.3f}, " |
| f"Mean={layer_stats['avg_activation']:+.4f}, " |
| f"Spread={layer_stats['activation_spread']:.4f}, " |
| f"Sparsity={layer_stats['avg_sparsity']:.1%}") |
| |
| |
| top_tokens = sorted(token_stats, key=lambda x: x['l2_norm'], reverse=True)[:3] |
| active_tokens = [f"'{t['token']}'({t['l2_norm']:.2f})" for t in top_tokens] |
| print(f" Most active: {', '.join(active_tokens)}") |
| |
| |
| print(f"\n๐ Evolution Analysis:") |
| |
| |
| l2_norms = [stats['avg_l2_norm'] for stats in layer_evolution] |
| if len(l2_norms) > 1: |
| trend = "increasing" if l2_norms[-1] > l2_norms[0] else "decreasing" |
| change = ((l2_norms[-1] - l2_norms[0]) / l2_norms[0]) * 100 |
| print(f"L2 norm trend: {trend} ({change:+.1f}%)") |
| |
| |
| sparsity_levels = [stats['avg_sparsity'] for stats in layer_evolution] |
| if len(sparsity_levels) > 1: |
| sparsity_trend = "increasing" if sparsity_levels[-1] > sparsity_levels[0] else "decreasing" |
| print(f"Sparsity trend: {sparsity_trend} (early: {sparsity_levels[0]:.1%}, late: {sparsity_levels[-1]:.1%})") |
| |
| print(f"\nโ
Real-time layer tracking completed!") |
| return layer_evolution |
| |
| def decision_process_analysis(self, prompt: str, max_steps: int = 5, temperature: float = 0.7, top_p: float = 0.9, top_k: int = 50): |
| """Deep analysis of the decision-making process""" |
| print(f"๐ฒ DECISION PROCESS ANALYSIS") |
| print("=" * 70) |
| print(f"Prompt: '{prompt}'") |
| print(f"๐๏ธ Sampling Parameters:") |
| print(f" Temperature: {temperature} (creativity control)") |
| print(f" Top-P: {top_p} (nucleus sampling)") |
| print(f" Top-K: {top_k} (candidate pool size)") |
| |
| input_ids = self.apertus.tokenizer.encode(prompt, return_tensors="pt") |
| |
| |
| device = next(self.apertus.model.parameters()).device |
| input_ids = input_ids.to(device) |
| decision_history = [] |
| |
| for step in range(max_steps): |
| print(f"\n--- DECISION STEP {step + 1} ---") |
| current_text = self.apertus.tokenizer.decode(input_ids[0]) |
| print(f"Current text: '{current_text}'") |
| |
| |
| with torch.no_grad(): |
| outputs = self.apertus.model(input_ids, output_attentions=True, output_hidden_states=True) |
| logits = outputs.logits[0, -1, :] |
| attentions = outputs.attentions |
| hidden_states = outputs.hidden_states |
| |
| |
| scaled_logits = logits / temperature |
| probabilities = torch.nn.functional.softmax(scaled_logits, dim=-1) |
| |
| |
| original_probs = torch.nn.functional.softmax(logits, dim=-1) |
| |
| print(f"๐ก๏ธ Temperature Effect Analysis:") |
| orig_top5 = torch.topk(original_probs, 5)[0] |
| temp_top5 = torch.topk(probabilities, 5)[0] |
| print(f" Without temp: Top-5 = {[f'{p.item():.1%}' for p in orig_top5]}") |
| print(f" With temp={temperature}: Top-5 = {[f'{p.item():.1%}' for p in temp_top5]}") |
| |
| |
| entropy = -torch.sum(probabilities * torch.log(probabilities + 1e-12)).item() |
| |
| |
| max_prob = probabilities.max().item() |
| top_probs, top_indices = torch.topk(probabilities, 10) |
| |
| print(f"๐ฏ Decision Metrics:") |
| print(f" Entropy: {entropy:.3f} (uncertainty)") |
| print(f" Max confidence: {max_prob:.1%}") |
| print(f" Top-3 probability mass: {top_probs[:3].sum().item():.1%}") |
| |
| |
| last_hidden = hidden_states[-1][0, -1, :] |
| hidden_magnitude = torch.norm(last_hidden).item() |
| |
| print(f" Hidden state magnitude: {hidden_magnitude:.2f}") |
| |
| |
| last_attention = attentions[-1][0, :, -1, :-1].mean(dim=0) |
| top_attention_indices = torch.topk(last_attention, 3)[1] |
| tokens = self.apertus.tokenizer.convert_ids_to_tokens(input_ids[0]) |
| |
| print(f" Attention focused on:") |
| for i, idx in enumerate(top_attention_indices): |
| if idx < len(tokens): |
| attention_score = last_attention[idx].item() |
| print(f" {i+1}. '{tokens[idx]}' ({attention_score:.3f})") |
| |
| |
| print(f"\n๐ Top candidates:") |
| for i in range(5): |
| token_id = top_indices[i].item() |
| token = self.apertus.tokenizer.decode([token_id]) |
| prob = top_probs[i].item() |
| logit = logits[token_id].item() |
| |
| |
| if prob > 0.3: |
| confidence_level = "๐ฅ Very High" |
| elif prob > 0.1: |
| confidence_level = "โ
High" |
| elif prob > 0.05: |
| confidence_level = "โ ๏ธ Medium" |
| else: |
| confidence_level = "โ Low" |
| |
| print(f" {i+1}. '{token}' โ {prob:.1%} (logit: {logit:+.2f}) {confidence_level}") |
| |
| |
| if entropy < 2.0: |
| decision_quality = "๐ฏ Confident" |
| elif entropy < 4.0: |
| decision_quality = "โ๏ธ Balanced" |
| else: |
| decision_quality = "๐ค Uncertain" |
| |
| print(f"\n๐ Decision quality: {decision_quality}") |
| |
| |
| sampling_probs = probabilities.clone() |
| if top_k > 0 and top_k < len(probabilities): |
| top_k_values, top_k_indices = torch.topk(probabilities, top_k) |
| |
| sampling_probs = torch.zeros_like(probabilities) |
| sampling_probs[top_k_indices] = top_k_values |
| sampling_probs = sampling_probs / sampling_probs.sum() |
| print(f"๐ Top-K filtering: Reduced {len(probabilities)} โ {top_k} candidates") |
| |
| |
| if top_p < 1.0: |
| sorted_probs, sorted_indices = torch.sort(sampling_probs, descending=True) |
| cumulative_probs = torch.cumsum(sorted_probs, dim=-1) |
| nucleus_mask = cumulative_probs <= top_p |
| nucleus_mask[0] = True |
| |
| nucleus_probs = torch.zeros_like(sampling_probs) |
| nucleus_probs[sorted_indices[nucleus_mask]] = sorted_probs[nucleus_mask] |
| sampling_probs = nucleus_probs / nucleus_probs.sum() |
| |
| nucleus_size = nucleus_mask.sum().item() |
| nucleus_mass = sorted_probs[nucleus_mask].sum().item() |
| print(f"๐ Top-P filtering: Nucleus size = {nucleus_size} tokens ({nucleus_mass:.1%} probability mass)") |
| |
| |
| final_top5 = torch.topk(sampling_probs, 5) |
| print(f"๐ฏ Final sampling distribution:") |
| for i in range(5): |
| if final_top5[0][i] > 0: |
| token = self.apertus.tokenizer.decode([final_top5[1][i].item()]) |
| prob = final_top5[0][i].item() |
| print(f" {i+1}. '{token}' โ {prob:.1%}") |
| |
| |
| next_token_id = torch.multinomial(sampling_probs, 1) |
| selected_token = self.apertus.tokenizer.decode([next_token_id.item()]) |
| |
| |
| selected_rank = "N/A" |
| if next_token_id in top_indices: |
| selected_rank = (top_indices == next_token_id).nonzero().item() + 1 |
| |
| print(f"๐ฒ SELECTED: '{selected_token}' (rank: {selected_rank})") |
| |
| |
| decision_history.append({ |
| 'step': step + 1, |
| 'text': current_text, |
| 'selected_token': selected_token, |
| 'selected_rank': selected_rank, |
| 'entropy': entropy, |
| 'max_confidence': max_prob, |
| 'hidden_magnitude': hidden_magnitude, |
| 'decision_quality': decision_quality |
| }) |
| |
| |
| input_ids = torch.cat([input_ids, next_token_id.unsqueeze(0)], dim=-1) |
| |
| |
| final_text = self.apertus.tokenizer.decode(input_ids[0]) |
| print(f"\nโจ FINAL GENERATED TEXT: '{final_text}'") |
| |
| avg_entropy = np.mean([d['entropy'] for d in decision_history]) |
| avg_confidence = np.mean([d['max_confidence'] for d in decision_history]) |
| |
| print(f"\n๐ Generation Analysis:") |
| print(f" Average entropy: {avg_entropy:.2f}") |
| print(f" Average confidence: {avg_confidence:.1%}") |
| print(f" Generation quality: {'High' if avg_confidence > 0.3 else 'Medium' if avg_confidence > 0.15 else 'Low'}") |
| |
| return decision_history |
| |
| def comprehensive_tokenizer_comparison(self, test_word: str = "Bundesgesundheitsamt"): |
| """Compare tokenization across different model tokenizers""" |
| print(f"๐ค COMPREHENSIVE TOKENIZER COMPARISON") |
| print("=" * 70) |
| print(f"Test word: '{test_word}'") |
| |
| |
| print(f"\n๐จ๐ญ Apertus Tokenizer:") |
| apertus_tokens = self.apertus.tokenizer.tokenize(test_word) |
| apertus_ids = self.apertus.tokenizer.encode(test_word, add_special_tokens=False) |
| |
| print(f" Tokens: {apertus_tokens}") |
| print(f" Token IDs: {apertus_ids}") |
| print(f" Token count: {len(apertus_tokens)}") |
| print(f" Efficiency: {len(test_word) / len(apertus_tokens):.1f} chars/token") |
| |
| |
| print(f" Token breakdown:") |
| for i, (token, token_id) in enumerate(zip(apertus_tokens, apertus_ids)): |
| print(f" {i+1}. '{token}' โ ID: {token_id}") |
| |
| |
| comparison_results = [ |
| { |
| 'model': 'Apertus Swiss AI', |
| 'tokens': apertus_tokens, |
| 'count': len(apertus_tokens), |
| 'efficiency': len(test_word) / len(apertus_tokens), |
| 'vocab_size': self.apertus.tokenizer.vocab_size |
| } |
| ] |
| |
| |
| try: |
| from transformers import GPT2Tokenizer |
| gpt2_tokenizer = GPT2Tokenizer.from_pretrained('gpt2') |
| gpt2_tokens = gpt2_tokenizer.tokenize(test_word) |
| |
| print(f"\n๐ค GPT-2 Tokenizer (for comparison):") |
| print(f" Tokens: {gpt2_tokens}") |
| print(f" Token count: {len(gpt2_tokens)}") |
| print(f" Efficiency: {len(test_word) / len(gpt2_tokens):.1f} chars/token") |
| |
| comparison_results.append({ |
| 'model': 'GPT-2', |
| 'tokens': gpt2_tokens, |
| 'count': len(gpt2_tokens), |
| 'efficiency': len(test_word) / len(gpt2_tokens), |
| 'vocab_size': gpt2_tokenizer.vocab_size |
| }) |
| except Exception as e: |
| print(f"\nโ ๏ธ GPT-2 tokenizer not available: {e}") |
| |
| |
| try: |
| from transformers import BertTokenizer |
| bert_tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') |
| |
| bert_tokens = bert_tokenizer.tokenize(test_word.lower()) |
| |
| print(f"\n๐ BERT Tokenizer (for comparison):") |
| print(f" Tokens: {bert_tokens}") |
| print(f" Token count: {len(bert_tokens)}") |
| print(f" Efficiency: {len(test_word) / len(bert_tokens):.1f} chars/token") |
| |
| comparison_results.append({ |
| 'model': 'BERT', |
| 'tokens': bert_tokens, |
| 'count': len(bert_tokens), |
| 'efficiency': len(test_word) / len(bert_tokens), |
| 'vocab_size': bert_tokenizer.vocab_size |
| }) |
| except Exception as e: |
| print(f"\nโ ๏ธ BERT tokenizer not available: {e}") |
| |
| |
| print(f"\n๐ TOKENIZATION COMPARISON SUMMARY:") |
| print(f"{'Model':<20} {'Tokens':<8} {'Efficiency':<12} {'Vocab Size'}") |
| print("-" * 60) |
| |
| for result in comparison_results: |
| print(f"{result['model']:<20} {result['count']:<8} {result['efficiency']:<12.1f} {result['vocab_size']:,}") |
| |
| |
| if test_word == "Bundesgesundheitsamt": |
| print(f"\n๐ฉ๐ช GERMAN COMPOUND WORD ANALYSIS:") |
| print(f" Word parts: Bundes + gesundheits + amt") |
| print(f" Meaning: Federal Health Office") |
| print(f" Character count: {len(test_word)}") |
| |
| |
| apertus_efficiency = len(test_word) / len(apertus_tokens) |
| print(f" Apertus efficiency: {apertus_efficiency:.1f} chars/token") |
| |
| if apertus_efficiency > 8: |
| print(f" โ
Excellent German compound handling!") |
| elif apertus_efficiency > 6: |
| print(f" โ
Good German compound handling") |
| else: |
| print(f" โ ๏ธ Could be more efficient for German compounds") |
| |
| |
| additional_tests = [ |
| "Krankenversicherung", |
| "Donaudampfschifffahrt", |
| "Rechtsschutzversicherung", |
| "Arbeitsplatzcomputer" |
| ] |
| |
| print(f"\n๐งช Additional German Compound Tests:") |
| for word in additional_tests: |
| tokens = self.apertus.tokenizer.tokenize(word) |
| efficiency = len(word) / len(tokens) |
| print(f" '{word}' โ {len(tokens)} tokens ({efficiency:.1f} chars/token)") |
| |
| print(f"\nโ
Tokenizer comparison completed!") |
| return comparison_results |
| |
| def save_complete_log(self, filename: str = None): |
| """Save complete command-line output log""" |
| if filename is None: |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
| filename = f"apertus_transparency_log_{timestamp}.txt" |
| |
| |
| log_content = self.log_buffer.getvalue() |
| |
| |
| header = f"""# ๐จ๐ญ Apertus Advanced Transparency Analysis Log |
| Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} |
| Model: {self.apertus.model_name} |
| GPU: {self.apertus.device_info['gpu_name'] if self.apertus.device_info['has_gpu'] else 'CPU'} |
| Memory: {self.apertus.device_info['gpu_memory_gb']:.1f} GB |
| |
| ==================================================================================== |
| COMPLETE COMMAND-LINE OUTPUT CAPTURE: |
| ==================================================================================== |
| |
| """ |
| |
| |
| full_log = header + log_content |
| |
| |
| with open(filename, 'w', encoding='utf-8') as f: |
| f.write(full_log) |
| |
| print(f"\n๐ Complete analysis log saved to: {filename}") |
| print(f"๐ Log contains {len(log_content)} characters of output") |
| |
| return filename |
|
|
| def main(): |
| """Run the advanced transparency toolkit""" |
| |
| toolkit = AdvancedTransparencyToolkit() |
| |
| while True: |
| print("\n๐ฏ ADVANCED TRANSPARENCY TOOLKIT MENU") |
| print("=" * 50) |
| print("1. Native Weights Inspection") |
| print("2. Real-time Attention Visualization") |
| print("3. Layer Evolution Real-time Tracking") |
| print("4. Decision Process Analysis") |
| print("5. Tokenizer Comparison (Bundesgesundheitsamt)") |
| print("6. Run All Analyses") |
| print("7. Save Complete Log") |
| print("8. Custom Analysis") |
| print("0. Exit") |
| |
| try: |
| choice = input("\nSelect option (0-8): ").strip() |
| |
| if choice == "0": |
| print("\n๐ Advanced Transparency Toolkit beendet. Auf Wiedersehen!") |
| break |
| |
| elif choice == "1": |
| layer = input("Enter layer pattern (e.g., 'layers.15.self_attn'): ").strip() |
| if not layer: |
| layer = "layers.15.self_attn" |
| toolkit.native_weights_inspection(layer) |
| |
| elif choice == "2": |
| text = input("Enter text for attention analysis: ").strip() |
| if not text: |
| text = "Apertus analysiert die Schweizer KI-Transparenz." |
| toolkit.real_time_attention_visualization(text) |
| |
| elif choice == "3": |
| text = input("Enter text for layer tracking: ").strip() |
| if not text: |
| text = "Transparenz ist wichtig fรผr Vertrauen." |
| toolkit.layer_evolution_real_time_tracking(text) |
| |
| elif choice == "4": |
| prompt = input("Enter prompt for decision analysis: ").strip() |
| if not prompt: |
| prompt = "Die Schweizer KI-Forschung ist" |
| toolkit.decision_process_analysis(prompt) |
| |
| elif choice == "5": |
| word = input("Enter word for tokenizer comparison (default: Bundesgesundheitsamt): ").strip() |
| if not word: |
| word = "Bundesgesundheitsamt" |
| toolkit.comprehensive_tokenizer_comparison(word) |
| |
| elif choice == "6": |
| print("\n๐ Running all analyses...") |
| |
| |
| toolkit.start_logging() |
| |
| toolkit.native_weights_inspection() |
| toolkit.real_time_attention_visualization("Apertus ist transparent.") |
| toolkit.layer_evolution_real_time_tracking("Schweizer KI-Innovation.") |
| toolkit.decision_process_analysis("Die Schweizer KI-Forschung ist") |
| toolkit.comprehensive_tokenizer_comparison("Bundesgesundheitsamt") |
| |
| |
| toolkit.stop_logging() |
| print("โ
All analyses completed!") |
| |
| elif choice == "7": |
| filename = input("Enter log filename (or press Enter for auto): ").strip() |
| if not filename: |
| filename = None |
| toolkit.save_complete_log(filename) |
| |
| elif choice == "8": |
| print("Custom analysis - combine any methods as needed!") |
| |
| else: |
| print("Invalid choice, please select 0-8.") |
| |
| except (KeyboardInterrupt, EOFError): |
| print("\n\n๐ Advanced toolkit session ended.") |
| break |
| except Exception as e: |
| print(f"\nโ Error: {e}") |
| print("Returning to menu...") |
|
|
| if __name__ == "__main__": |
| main() |