{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sequence Modeling with RNNs and Transformers\n",
    "\n",
    "In this tutorial, we'll build sequence models for tasks like text generation and time series prediction using RNNs, LSTMs, and attention mechanisms.\n",
    "\n",
    "## Learning Objectives\n",
    "\n",
    "By the end of this tutorial, you will be able to:\n",
    "- Build RNN and LSTM models for sequence tasks\n",
    "- Implement attention mechanisms\n",
    "- Create a simple Transformer architecture\n",
    "- Train models for text generation\n",
    "- Handle variable-length sequences\n",
    "- Implement teacher forcing and sampling strategies\n",
    "- Visualize attention weights\n",
    "\n",
    "## What We'll Build\n",
    "\n",
    "We'll create:\n",
    "- Character-level language model with RNN/LSTM\n",
    "- Attention-based sequence-to-sequence model\n",
    "- Simple Transformer for sequence modeling\n",
    "- Text generation pipeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 183,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "JAX devices: [CpuDevice(id=0)]\n"
     ]
    }
   ],
   "source": [
    "import brainstate \n",
    "import jax\n",
    "import jax.numpy as jnp\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# Set random seed\n",
    "brainstate.random.seed(42)\n",
    "\n",
    "print(f\"JAX devices: {jax.devices()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Dataset Preparation: Character-Level Text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 184,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Vocabulary size: 38\n",
      "Characters: \n",
      " .ADLMNPRSTabcdefgh...\n",
      "\n",
      "Original text length: 1364\n",
      "Encoded length: 1364\n",
      "\n",
      "Sample encoding: [ 0 11 19 16  1 28 32 20 14 22  1 13 29 26 34 25  1 17 26 35]\n",
      "Decoded: \n",
      "The quick brown fox\n"
     ]
    }
   ],
   "source": [
    "# Sample text data\n",
    "sample_text = \"\"\"\n",
    "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.\n",
    "Neural networks are powerful tools for machine learning. Neural networks learn patterns from data.\n",
    "Deep learning has revolutionized artificial intelligence. Deep learning uses multiple layers.\n",
    "Transformers have become the dominant architecture for NLP. Transformers use attention mechanisms.\n",
    "Attention is all you need for sequence modeling. Attention helps models focus on relevant information.\n",
    "Recurrent neural networks process sequences step by step. RNNs maintain hidden states across time.\n",
    "LSTMs solve the vanishing gradient problem in RNNs. LSTMs use gates to control information flow.\n",
    "\"\"\" * 2  # Optimized data size for quick demo\n",
    "\n",
    "class CharacterTokenizer:\n",
    "    \"\"\"Simple character-level tokenizer.\"\"\"\n",
    "    \n",
    "    def __init__(self, text: str):\n",
    "        # Get unique characters\n",
    "        self.chars = sorted(list(set(text)))\n",
    "        self.vocab_size = len(self.chars)\n",
    "        \n",
    "        # Create mappings\n",
    "        self.char_to_idx = {ch: i for i, ch in enumerate(self.chars)}\n",
    "        self.idx_to_char = {i: ch for i, ch in enumerate(self.chars)}\n",
    "    \n",
    "    def encode(self, text: str) -> np.ndarray:\n",
    "        \"\"\"Convert text to indices.\"\"\"\n",
    "        return np.array([self.char_to_idx[ch] for ch in text])\n",
    "    \n",
    "    def decode(self, indices: np.ndarray) -> str:\n",
    "        \"\"\"Convert indices to text.\"\"\"\n",
    "        return ''.join([self.idx_to_char[int(idx)] for idx in indices])\n",
    "\n",
    "# Create tokenizer\n",
    "tokenizer = CharacterTokenizer(sample_text)\n",
    "encoded_text = tokenizer.encode(sample_text)\n",
    "\n",
    "print(f\"Vocabulary size: {tokenizer.vocab_size}\")\n",
    "print(f\"Characters: {''.join(tokenizer.chars[:20])}...\")\n",
    "print(f\"\\nOriginal text length: {len(sample_text)}\")\n",
    "print(f\"Encoded length: {len(encoded_text)}\")\n",
    "print(f\"\\nSample encoding: {encoded_text[:20]}\")\n",
    "print(f\"Decoded: {tokenizer.decode(encoded_text[:20])}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create Training Sequences"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 185,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training sequences: (1075, 20)\n",
      "Validation sequences: (269, 20)\n",
      "\n",
      "Example sequence:\n",
      "Input:  \n",
      "The quick brown fox\n",
      "Target: The quick brown fox \n"
     ]
    }
   ],
   "source": [
    "def create_sequences(data, seq_length):\n",
    "    \"\"\"Create input-target pairs for sequence prediction.\n",
    "    \n",
    "    Args:\n",
    "        data: Encoded text data\n",
    "        seq_length: Length of input sequences\n",
    "        \n",
    "    Returns:\n",
    "        inputs: Array of shape (n_sequences, seq_length)\n",
    "        targets: Array of shape (n_sequences, seq_length)\n",
    "    \"\"\"\n",
    "    inputs = []\n",
    "    targets = []\n",
    "    \n",
    "    for i in range(len(data) - seq_length):\n",
    "        inputs.append(data[i:i+seq_length])\n",
    "        targets.append(data[i+1:i+seq_length+1])\n",
    "    \n",
    "    return np.array(inputs), np.array(targets)\n",
    "\n",
    "# Create sequences\n",
    "seq_length = 20\n",
    "X, y = create_sequences(encoded_text, seq_length)\n",
    "\n",
    "# Split into train/val\n",
    "split_idx = int(0.8 * len(X))\n",
    "X_train, X_val = X[:split_idx], X[split_idx:]\n",
    "y_train, y_val = y[:split_idx], y[split_idx:]\n",
    "\n",
    "print(f\"Training sequences: {X_train.shape}\")\n",
    "print(f\"Validation sequences: {X_val.shape}\")\n",
    "print(f\"\\nExample sequence:\")\n",
    "print(f\"Input:  {tokenizer.decode(X_train[0])}\")\n",
    "print(f\"Target: {tokenizer.decode(y_train[0])}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. RNN Language Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 186,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input shape: (4, 20)\n",
      "Logits shape: (4, 20, 38)\n",
      "Hidden shape: (4, 128)\n",
      "\n",
      "Total parameters: 32,038\n"
     ]
    }
   ],
   "source": [
    "class RNNLanguageModel(brainstate.nn.Module):\n",
    "    \"\"\"Simple RNN for character-level language modeling.\"\"\"\n",
    "    \n",
    "    def __init__(self, vocab_size, embedding_dim=64, hidden_dim=128):\n",
    "        super().__init__()\n",
    "        self.vocab_size = vocab_size\n",
    "        self.hidden_dim = hidden_dim\n",
    "        \n",
    "        # Embedding layer\n",
    "        self.embedding = brainstate.ParamState(\n",
    "            brainstate.random.randn(vocab_size, embedding_dim) * 0.1\n",
    "        )\n",
    "        \n",
    "        # RNN cell\n",
    "        self.rnn_cell = brainstate.nn.ValinaRNNCell(num_in=embedding_dim, num_out=hidden_dim)\n",
    "        \n",
    "        # Output projection\n",
    "        self.fc_out = brainstate.nn.Linear(hidden_dim, vocab_size)\n",
    "    \n",
    "    def __call__(self, x, hidden=None):\n",
    "        \"\"\"Forward pass.\n",
    "        \n",
    "        Args:\n",
    "            x: Input indices of shape (batch, seq_len)\n",
    "            hidden: Initial hidden state\n",
    "            \n",
    "        Returns:\n",
    "            logits: Output logits of shape (batch, seq_len, vocab_size)\n",
    "            hidden: Final hidden state\n",
    "        \"\"\"\n",
    "        batch_size, seq_len = x.shape\n",
    "        \n",
    "        # Initialize hidden state if not provided\n",
    "        self.rnn_cell.init_state(batch_size=batch_size)\n",
    "        \n",
    "        # Embed input\n",
    "        embedded = self.embedding.value[x]  # (batch, seq_len, embedding_dim)\n",
    "        \n",
    "        # Process sequence\n",
    "        outputs = []\n",
    "        for t in range(seq_len):\n",
    "            hidden = self.rnn_cell.update(embedded[:, t, :])\n",
    "            outputs.append(hidden)\n",
    "        \n",
    "        # Stack outputs\n",
    "        outputs = jnp.stack(outputs, axis=1)  # (batch, seq_len, hidden_dim)\n",
    "        \n",
    "        # Project to vocabulary\n",
    "        logits = jax.vmap(self.fc_out)(outputs)  # (batch, seq_len, vocab_size)\n",
    "        \n",
    "        return logits, hidden\n",
    "\n",
    "# Create model\n",
    "rnn_model = RNNLanguageModel(\n",
    "    vocab_size=tokenizer.vocab_size,\n",
    "    embedding_dim=64,\n",
    "    hidden_dim=128\n",
    ")\n",
    "\n",
    "# Test forward pass\n",
    "test_input = jnp.array(X_train[:4])\n",
    "test_logits, test_hidden = rnn_model(test_input)\n",
    "\n",
    "print(f\"Input shape: {test_input.shape}\")\n",
    "print(f\"Logits shape: {test_logits.shape}\")\n",
    "print(f\"Hidden shape: {test_hidden.shape}\")\n",
    "\n",
    "# Count parameters\n",
    "# n_params = sum(p.value.size for p in rnn_model.states(brainstate.ParamState).values())\n",
    "n_params = 0\n",
    "for p in rnn_model.states(brainstate.ParamState).values():\n",
    "    if isinstance(p.value,dict):\n",
    "        for v in p.value.values():\n",
    "            n_params +=v.size\n",
    "    else:\n",
    "        n_params += p.value.size\n",
    "\n",
    "print(f\"\\nTotal parameters: {n_params:,}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. LSTM Language Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 187,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input shape: (4, 20)\n",
      "Logits shape: (4, 20, 38)\n",
      "Hidden state shape: (4, 128)\n",
      "Cell state shape: (4, 128)\n",
      "\n",
      "Total parameters: 106,150\n"
     ]
    }
   ],
   "source": [
    "class LSTMLanguageModel(brainstate.nn.Module):\n",
    "    \"\"\"LSTM for character-level language modeling.\"\"\"\n",
    "    \n",
    "    def __init__(self, vocab_size, embedding_dim=64, hidden_dim=128):\n",
    "        super().__init__()\n",
    "        self.vocab_size = vocab_size\n",
    "        self.hidden_dim = hidden_dim\n",
    "        \n",
    "        # Embedding layer\n",
    "        self.embedding = brainstate.ParamState(\n",
    "            brainstate.random.randn(vocab_size, embedding_dim) * 0.1\n",
    "        )\n",
    "        \n",
    "        # LSTM cell\n",
    "        self.lstm_cell = brainstate.nn.LSTMCell(num_in=embedding_dim, num_out=hidden_dim)\n",
    "        \n",
    "        # Output projection\n",
    "        self.fc_out = brainstate.nn.Linear(hidden_dim, vocab_size)\n",
    "    \n",
    "    def __call__(self, x, state=None):\n",
    "        \"\"\"Forward pass.\n",
    "        \n",
    "        Args:\n",
    "            x: Input indices of shape (batch, seq_len)\n",
    "            state: Initial (hidden, cell) state tuple\n",
    "            \n",
    "        Returns:\n",
    "            logits: Output logits of shape (batch, seq_len, vocab_size)\n",
    "            state: Final (hidden, cell) state\n",
    "        \"\"\"\n",
    "        batch_size, seq_len = x.shape\n",
    "        \n",
    "    \n",
    "        # Initialize LSTM cell state\n",
    "        self.lstm_cell.init_state(batch_size=batch_size)\n",
    "        \n",
    "        # Embed input\n",
    "        embedded = self.embedding.value[x]  # (batch, seq_len, embedding_dim)\n",
    "        \n",
    "        # Process sequence\n",
    "        outputs = []\n",
    "        for t in range(seq_len):\n",
    "            hidden = self.lstm_cell.update(embedded[:, t, :])\n",
    "            outputs.append(hidden)\n",
    "        \n",
    "        # Stack outputs\n",
    "        outputs = jnp.stack(outputs, axis=1)  # (batch, seq_len, hidden_dim)\n",
    "        \n",
    "        # Project to vocabulary\n",
    "        logits = jax.vmap(self.fc_out)(outputs)  # (batch, seq_len, vocab_size)\n",
    "        \n",
    "        return logits, (self.lstm_cell.h.value, self.lstm_cell.c.value)\n",
    "\n",
    "# Create LSTM model\n",
    "lstm_model = LSTMLanguageModel(\n",
    "    vocab_size=tokenizer.vocab_size,\n",
    "    embedding_dim=64,\n",
    "    hidden_dim=128\n",
    ")\n",
    "\n",
    "# Test forward pass\n",
    "test_logits, test_state = lstm_model(test_input)\n",
    "\n",
    "print(f\"Input shape: {test_input.shape}\")\n",
    "print(f\"Logits shape: {test_logits.shape}\")\n",
    "print(f\"Hidden state shape: {test_state[0].shape}\")\n",
    "print(f\"Cell state shape: {test_state[1].shape}\")\n",
    "\n",
    "# n_params = sum(p.value.size for p in lstm_model.states(brainstate.ParamState).values())\n",
    "n_params = 0\n",
    "for p in lstm_model.states(brainstate.ParamState).values():\n",
    "    if isinstance(p.value,dict):\n",
    "        for v in p.value.values():\n",
    "            n_params +=v.size\n",
    "    else:\n",
    "        n_params += p.value.size\n",
    "\n",
    "print(f\"\\nTotal parameters: {n_params:,}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Training Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 188,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initial loss: 3.6380\n",
      "Initial perplexity: 38.02\n"
     ]
    }
   ],
   "source": [
    "def cross_entropy_loss(logits, targets):\n",
    "    \"\"\"Compute cross-entropy loss for sequences.\n",
    "    \n",
    "    Args:\n",
    "        logits: Predicted logits of shape (batch, seq_len, vocab_size)\n",
    "        targets: True indices of shape (batch, seq_len)\n",
    "        \n",
    "    Returns:\n",
    "        Scalar loss value\n",
    "    \"\"\"\n",
    "    batch_size, seq_len, vocab_size = logits.shape\n",
    "    \n",
    "    # Reshape for easier computation\n",
    "    logits_flat = logits.reshape(-1, vocab_size)\n",
    "    targets_flat = targets.reshape(-1)\n",
    "    \n",
    "    # One-hot encode targets\n",
    "    one_hot = jax.nn.one_hot(targets_flat, vocab_size)\n",
    "    \n",
    "    # Compute log probabilities\n",
    "    log_probs = jax.nn.log_softmax(logits_flat, axis=-1)\n",
    "    \n",
    "    # Compute loss\n",
    "    loss = -jnp.mean(jnp.sum(one_hot * log_probs, axis=-1))\n",
    "    \n",
    "    return loss\n",
    "\n",
    "def perplexity(loss):\n",
    "    \"\"\"Compute perplexity from loss.\"\"\"\n",
    "    return jnp.exp(loss)\n",
    "\n",
    "def train_step(model, x_batch, y_batch, learning_rate=0.001):\n",
    "    \"\"\"Perform one training step.\"\"\"\n",
    "    with brainstate.environ.context(fit=True):\n",
    "        def loss_fn():\n",
    "            logits, _ = model(jnp.array(x_batch))\n",
    "            return cross_entropy_loss(logits, jnp.array(y_batch))\n",
    "        \n",
    "        # Compute gradients\n",
    "        grads,loss = brainstate.transform.grad(\n",
    "            loss_fn,\n",
    "            model.states(brainstate.ParamState),\n",
    "            return_value=True\n",
    "        )()\n",
    "        \n",
    "        # Update parameters\n",
    "        for name, param_state in model.states(brainstate.ParamState).items():\n",
    "            grad_value = grads[name]\n",
    "            # Handle nested dict structure\n",
    "            if isinstance(param_state.value, dict):\n",
    "                for key in param_state.value.keys():\n",
    "                    param_state.value[key] -= learning_rate * grad_value[key]\n",
    "            else:\n",
    "                param_state.value -= learning_rate * grad_value\n",
    "        return float(loss)\n",
    "\n",
    "def eval_step(model, x_batch, y_batch):\n",
    "    \"\"\"Perform one evaluation step.\"\"\"\n",
    "    with brainstate.environ.context(fit=False):\n",
    "        logits, _ = model(jnp.array(x_batch))\n",
    "        loss = cross_entropy_loss(logits, jnp.array(y_batch))\n",
    "        return float(loss)\n",
    "\n",
    "# Test training step\n",
    "batch_size = 32\n",
    "x_batch = X_train[:batch_size]\n",
    "y_batch = y_train[:batch_size]\n",
    "\n",
    "initial_loss = eval_step(lstm_model, x_batch, y_batch)\n",
    "print(f\"Initial loss: {initial_loss:.4f}\")\n",
    "print(f\"Initial perplexity: {perplexity(initial_loss):.2f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Train LSTM Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 189,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training LSTM Language Model\n",
      "============================================================\n",
      "Epoch   0: train_loss=3.6247 (ppl=37.51), val_loss=3.6086 (ppl=36.92)\n",
      "Epoch   5: train_loss=3.4922 (ppl=32.86), val_loss=3.4787 (ppl=32.42)\n",
      "Epoch  10: train_loss=3.3774 (ppl=29.29), val_loss=3.3657 (ppl=28.95)\n",
      "Epoch  15: train_loss=3.2904 (ppl=26.85), val_loss=3.2788 (ppl=26.54)\n",
      "Epoch  20: train_loss=3.2301 (ppl=25.28), val_loss=3.2162 (ppl=24.93)\n",
      "Epoch  25: train_loss=3.1910 (ppl=24.31), val_loss=3.1740 (ppl=23.90)\n",
      "Epoch  30: train_loss=3.1667 (ppl=23.73), val_loss=3.1468 (ppl=23.26)\n",
      "Epoch  35: train_loss=3.1507 (ppl=23.35), val_loss=3.1296 (ppl=22.86)\n",
      "Epoch  40: train_loss=3.1413 (ppl=23.13), val_loss=3.1184 (ppl=22.61)\n",
      "Epoch  45: train_loss=3.1334 (ppl=22.95), val_loss=3.1108 (ppl=22.44)\n",
      "Epoch  50: train_loss=3.1282 (ppl=22.83), val_loss=3.1054 (ppl=22.32)\n",
      "Epoch  55: train_loss=3.1239 (ppl=22.73), val_loss=3.1013 (ppl=22.23)\n",
      "Epoch  60: train_loss=3.1202 (ppl=22.65), val_loss=3.0980 (ppl=22.15)\n",
      "Epoch  65: train_loss=3.1171 (ppl=22.58), val_loss=3.0952 (ppl=22.09)\n",
      "Epoch  70: train_loss=3.1141 (ppl=22.51), val_loss=3.0929 (ppl=22.04)\n",
      "Epoch  75: train_loss=3.1114 (ppl=22.45), val_loss=3.0908 (ppl=22.00)\n",
      "Epoch  80: train_loss=3.1102 (ppl=22.43), val_loss=3.0890 (ppl=21.96)\n",
      "Epoch  85: train_loss=3.1069 (ppl=22.35), val_loss=3.0873 (ppl=21.92)\n",
      "Epoch  90: train_loss=3.1041 (ppl=22.29), val_loss=3.0857 (ppl=21.88)\n",
      "Epoch  95: train_loss=3.1028 (ppl=22.26), val_loss=3.0842 (ppl=21.85)\n",
      "Epoch 100: train_loss=3.1003 (ppl=22.20), val_loss=3.0829 (ppl=21.82)\n",
      "Epoch 105: train_loss=3.0983 (ppl=22.16), val_loss=3.0815 (ppl=21.79)\n",
      "Epoch 110: train_loss=3.0975 (ppl=22.14), val_loss=3.0800 (ppl=21.76)\n",
      "Epoch 115: train_loss=3.0960 (ppl=22.11), val_loss=3.0786 (ppl=21.73)\n",
      "Epoch 120: train_loss=3.0944 (ppl=22.07), val_loss=3.0773 (ppl=21.70)\n",
      "Epoch 125: train_loss=3.0921 (ppl=22.02), val_loss=3.0760 (ppl=21.67)\n",
      "Epoch 130: train_loss=3.0916 (ppl=22.01), val_loss=3.0745 (ppl=21.64)\n",
      "Epoch 135: train_loss=3.0888 (ppl=21.95), val_loss=3.0730 (ppl=21.61)\n",
      "Epoch 140: train_loss=3.0886 (ppl=21.95), val_loss=3.0716 (ppl=21.58)\n",
      "Epoch 145: train_loss=3.0854 (ppl=21.88), val_loss=3.0701 (ppl=21.54)\n",
      "Epoch 149: train_loss=3.0847 (ppl=21.86), val_loss=3.0689 (ppl=21.52)\n",
      "============================================================\n",
      "Training completed!\n"
     ]
    }
   ],
   "source": [
    "def train_epoch(model, X, y, batch_size, learning_rate):\n",
    "    \"\"\"Train for one epoch.\"\"\"\n",
    "    losses = []\n",
    "    n_samples = len(X)\n",
    "    \n",
    "    # Shuffle data\n",
    "    indices = np.random.permutation(n_samples)\n",
    "    \n",
    "    for start_idx in range(0, n_samples, batch_size):\n",
    "        end_idx = min(start_idx + batch_size, n_samples)\n",
    "        batch_indices = indices[start_idx:end_idx]\n",
    "        \n",
    "        x_batch = X[batch_indices]\n",
    "        y_batch = y[batch_indices]\n",
    "        \n",
    "        loss = train_step(model, x_batch, y_batch, learning_rate)\n",
    "        losses.append(loss)\n",
    "    \n",
    "    return np.mean(losses)\n",
    "\n",
    "def evaluate(model, X, y, batch_size):\n",
    "    \"\"\"Evaluate model.\"\"\"\n",
    "    losses = []\n",
    "    n_samples = len(X)\n",
    "    \n",
    "    for start_idx in range(0, n_samples, batch_size):\n",
    "        end_idx = min(start_idx + batch_size, n_samples)\n",
    "        x_batch = X[start_idx:end_idx]\n",
    "        y_batch = y[start_idx:end_idx]\n",
    "        \n",
    "        loss = eval_step(model, x_batch, y_batch)\n",
    "        losses.append(loss)\n",
    "    \n",
    "    return np.mean(losses)\n",
    "\n",
    "# Training configuration\n",
    "config = {\n",
    "    'num_epochs': 150,\n",
    "    'batch_size': 32,\n",
    "    'learning_rate': 0.01,\n",
    "}\n",
    "\n",
    "# Create fresh model\n",
    "model = LSTMLanguageModel(\n",
    "    vocab_size=tokenizer.vocab_size,\n",
    "    embedding_dim=32,\n",
    "    hidden_dim=64\n",
    ")\n",
    "\n",
    "# Training loop\n",
    "history = {'train_loss': [], 'val_loss': []}\n",
    "\n",
    "print(\"Training LSTM Language Model\")\n",
    "print(\"=\" * 60)\n",
    "\n",
    "for epoch in range(config['num_epochs']):\n",
    "    # Train\n",
    "    train_loss = train_epoch(\n",
    "        model, X_train, y_train,\n",
    "        config['batch_size'],\n",
    "        config['learning_rate']\n",
    "    )\n",
    "    \n",
    "    # Validate\n",
    "    val_loss = evaluate(model, X_val, y_val, config['batch_size'])\n",
    "    \n",
    "    # Record history\n",
    "    history['train_loss'].append(train_loss)\n",
    "    history['val_loss'].append(val_loss)\n",
    "    \n",
    "    # Print progress\n",
    "    if epoch % 5 == 0 or epoch == config['num_epochs'] - 1:\n",
    "        print(f\"Epoch {epoch:3d}: \"\n",
    "              f\"train_loss={train_loss:.4f} (ppl={perplexity(train_loss):.2f}), \"\n",
    "              f\"val_loss={val_loss:.4f} (ppl={perplexity(val_loss):.2f})\")\n",
    "\n",
    "print(\"=\" * 60)\n",
    "print(\"Training completed!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 190,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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b8zMxsKSAKzkQOaArL1n9tls1aqV+9xbYNkeLzU11Y1PdmxM7W9CAWr7LFv5Bhsb+3d3ww03qFChQi7oalnCVuf46aefdn979dVXa8OGDe7fbXbZ1FYaJTT/tffH2GfYntOC5u+++66r85uZnbP7tG7dOuzxBWJOEACycfXVV9t/6fc616FDB3fuxRdf3O/+W7du3e9cv379goULFw5u374941yfPn2CVatWzbi+aNEi95hlypQJrl27NuP8p59+6s5//vnnGefuv//+/fpk1wsUKBD8448/Ms7NnDnTnf+///u/jHM9evRwffnnn38yzv3+++/B5OTk/R4zK1m9voEDBwYDgUDw77//3uv12eM9+OCDe923adOmwebNm2dcHzFihLvf448/nnEuNTU1ePzxx7vzb7zxxkH71LJly2ClSpWCaWlpGee+/vpr9/cvvfRSxmPu2LFjr79bt25d8Igjjgheeumle523v7MxDrE+2Dl7j8yqVavcWJ9yyinB9PT0jPvddddd7n722kPsPc/cL2OPk5KSstfYTJkyJdvXu+9nJTRmDz/88F73O+uss9z7kPkzkNPPRVZCn8knnngi2/s8++yz7j7vvPNOxrmdO3cGW7duHSxatGhw48aN7tz1118fLF68uHsfstO4cWM3pgAAJBLmmgd/fcw143uu2b9//+Dq1auDK1asCI4ZM8a9h3b+448/dq+/Vq1awZNOOmmvsbDPSfXq1YMnnnjifp/b888/P8vXaLdde+21Gefs8WyMrf/2/Nm9P5dddlmwYsWKwTVr1uz1mOedd16wRIkSe31m77zzzmBSUlJw3LhxwY8++sg9ls2XM8vq31eRIkX2el8zP569l+vXr884Z58P+/eUuY9APKM8AoCw2bIYW160L/uVNcR+Ybdf3e3XbMsYsKVVB3Puuee6pTwhoV/C7Vf0g+nSpYv7xTXENkSwJVKhv7Vfly0DwZaQ2a/uIVary369zonMr8+W8djrs1/pbX5jmRX7soyGzOz1ZH4tX331lavpFMqGMPYr9LXXXqucsuwTy74YN25cxjnLhihQoID7pT30mHbd2EYLtlTJflW3pXtZLXc7EBtDy3KwPmZe2mS/smf1ObFsgND4W9aMZcXYErNwnzfzmNnrsR2NM7MlbPY+2C//4XwuDof1pUKFCi6rJMSydKxvmzdv1tix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K6fixYvn+WuyL1P22bLni5cv7XmNMQsfYxYexit8jFn44m3MrCTC2rVr3QoeW/WSF2ypvy2LR87F65gVK1bM/buxeax93vadx9qPBjlB0BYAAMTFRDwUNEP8CAXgbUIfC0HbrL7wWkaP/aBg9v3Sa6/pYMvjUlJS3LEve6xIfYm2L+2RfL54wJiFjzELD+MVPsYsscfMymjZ6ylSpEie/NBtP6SHHjfefkjPK/E+ZkV2f9bse8q+gemc/psiaAsAAOJGPE74ElksvZ+WEdutWzdVqVLFLXkbOnSoxowZo1GjRqlu3bouA7dfv3568sknXcaFlUcYPXq0vvjiC7+7DgBAwoiluQViW2581gjaAgAAAIfJlr/17t3b1VYuUaKEGjVq5AK2J554orv9q6++0h133KEePXpo8+bNLoj75ptvqnv37n53HQAAAFEo9nPcAQAAkKFatWp69tln/e5Gwnnttdf0119/uXIIFsC1DcdCAVtTq1Ytffzxx27XatuUYubMmbr44ot97TMAAEhMsT5frJbL/X/ggQfUpEkTRRuCtgAAAD4tmTrQYZPHQ2GbX11xxRWH1beOHTvqhhtuOKzHAAAAQHzPF0P9sI216tevr//973+KRbfccou+++67jOuXXHKJevXqJb9RHgEAAMAHtow+5IMPPtB9992nBQsWZJwrWrToXhs12CYGyckHn7rZLs8AAACIfdE+X7z88sv14IMPuk1X33rrLV199dUqVaqUzj///EPaLM6vTYWLFi2611hGCzJtAQAAfFChQoWMw2qgWpZC6Pr8+fNVrFgxjRw5Us2bN1dKSop++uknLVy4UD179tQRRxzhJpbHHnvsXlkBWS0Xs8d99dVXdfrpp6tw4cJumf5nn312WH23Zf4NGjRw/bLne+qpp/a63bIs7Hks68L6etZZZ2XcNmzYMB1zzDEqVKiQ25CrS5curlwAAAAAcn++2LJlS1e2KS/mi3Zf68vRRx/tsn4z/9369ev1n//8xwWIixcvrk6dOrnyUCF2/xYtWrjnrV69ups3hjJ4r7nmGnfYay5btqzuvfdeF5TOzoGea/Xq1a6PjzzySMb9J0yY4ALEoXl05vII1rZ9Bz799NOMTGLbXNYe0/qUmT125sfJbQRt89h770m9ewfUsWMZbd/ud28AAEAssY2rHn30Uf36669uYyvbwMo2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wM2fP7++szpUu1nN3MWLF7sgMQ6gUyd3kT+4S2013rW//dbnPgEAAETAIQVtrRTCiy++6Ca1o0ePdsvIzLJly1SmTJnc7iPySv78GRuSFdu1Tq010bU//9znfgEAAESQrRibPHmybr75ZpfxYdmvX331lR588EFdeumlOS5jMG7cOP3111+utq1dHzNmjC688EKVKFFCl112mStz8MMPP7iNyfr27esCtgfahAx7grauqe/d5ejRPvYHAAAgmoO2jz32mF566SV17NjR1fpq3LixO//ZZ59llE1AjDjllIzmqfrCXRK0BQAAicSCqKH5bGZXX321uy0nVq1apd69e7u6tp07d3alEUaNGuX2fjDPPPOMTj31VJ155plq3769Cwx/8sknuf5a4k7HjhnNE/N5Qdvvv5fS0nzsEwAAQAQcUk1bC9auWbPGbYRQqlSpjPO2OVnhwoVzs3/Ia926eQVsg0GdlfKF7tjxmCZPlmwj44OUWAMAAIgLVvZr4cKFeuONN9yl1aEtX768Ro4cqSpWVzUHrAbuwTaceOGFF9yBMJQvLzVsaJtqqGnaNBXXBq1fX0IWSydXBAAAxLNDyrTdtm2bq88VCtj+/fffevbZZ11tLpvgIoaULSvtrqVWY8c8Vdefrv2Fl3QLAAAQ98aOHevq11qJBMt+3bx5szs/c+ZM3X///X53D7tLJCQpXe01zrUpkQAAAOLdIQVte/bsqbfeesu1bRfc4447Tk899ZR69eqlwYMH53YfkddOPTWjeYq+dJeffeZjfwAAACLojjvu0MMPP+z2arANyEI6deqkSZMm+do3SDrhhIwmdW0BAECiOKSg7S+//KLjjz/etYcNG6YjjjjCZdtaIPe5557L7T4igkHbMwt8kTER3rrVxz4BAABEiG0cdvrpp+933laQWUkw+KxDB6+cl6STCvzgLidMkLZs8blfAAAA0Ra03bp1q4oVK+ba33zzjc444wwlJSW53W8teIsYY3XCdtdra5s6RkW0Wdu3S99+63fHAAAA8l7JkiW1fPny/c5Pnz5dRx11lC99QiZWkq1ZM9esv3OmymmVdu2SxnmVEgAAAOLSIQVta9asqREjRmjJkiVuV9yuXbtm7JpbvHjx3O4j8pplLuzOts2fvlMnyltvRokEAACQCM477zzdfvvtWrFihQKBgNLT0zV+/Hjdcsst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mM99AwAACYmgLSKvTJk92ba7drlsW8uwLV3aO/XOO9L48b72EAAAAInEatpmyrY9559nVKKE137rLWnJEv+6BgAAEhNBW/jDNiSzUgnm1VdVZusSPfzwnptvuCGgtDTfegcAAIBEc845UsWKrpn/q09134ULMyp6PfWUz30DAAAJh6At/Mu2tTIJmbJtr7hCatzYO/XLLwENHVrI1y4CAAAggRQoIF1zjdcOBnXlrudUaPd09OWXpdWrfe0dAABIMARtETXZtvmWL9X//d+emwcOLMbkGAAAxISBAweqZcuWKlasmMqXL69evXppwYIF+91v4sSJ6tSpk4oUKaLixYurffv22rZtmy99RhZso4XdkdrC776q6y/617XtLXr2WZ/7BgAAEgpBW0RHbdudO122re0BccEF3ql165J0220BX7sIAACQE2PHjtXVV1+tSZMmafTo0dq1a5e6du2qLVu27BWwPfnkk935n3/+WVOmTNE111yjpCSm5FE1P73sMq+9davuKDxI+fN7VwcNklas8LV3AAAggTBDhP/ZtkWKeO1XXpH+/tvVDCtZMuhOvfVWQD/84G8XAQAADubrr7/WJZdcogYNGqhx48YaMmSIFi9erGnTpmXc58Ybb9R1112nO+64w92vTp06Ouecc5SSkuJr37GPW2+VkpNds8Sb/6fr+250bYu/2+a5AAAAkeDNRgC/lC3r1bYdONDLtr3vPlV480098khQV13lZdleeaU0a5bE9xkAABArNmzY4C5Lly7tLletWqXJkyfrwgsvVJs2bbRw4ULVrVtXAwYMULt27bJ9nB07drgjZONGL4CYnp7ujrxmzxEMBiPyXFGjUiUFLrpIgSFDpPXrdV+5/+nFordr8+aAXn45qOuvD6pmzez/PCHH7DAxZuFhvMLHmIWPMQsP4xW+RB6z9By+ZoK28N9tt0kvvmj1EKS335ZuvlmXX95Qr7++U1OnFtBvv7nKCbr/fr87CgAAkLOJ+A033KC2bduqYcOG7tyff/7pLh944AE9+eSTatKkid566y117txZc+bMUa1atbKtldu/f//9zq9evVrbt2+PyGuxALR9qUqkMg75LrtMZd98U4FgUIVfekpXX3qZHnuunFJTA7rttu168UUvKJ+VRB2zw8GYhYfxCh9jFj7GLDyMV/gSecw2bdqUo/sRtIX/SpaU7r5buuUWt1Ov7rxTSZ9/rscf36iuXcu4yfEjj0jnny/Vru13ZwEAAA7MattaIPann37aL6OiX79+6tu3r2s3bdpU3333nV5//XUXnM3KnXfeqZusnFSmTNvKlSurXLlybiOzvGb9DgQC7vkS6gtV+fLSmWdKw4Yp35o1ur/S+3q93DVavTqgTz8tpLvvTlHz5ln/acKO2WFgzMLDeIWPMQsfYxYexit8iTxmBQsWzNH9CNoiOlx9tfTcc9LixdJXX0ljxqhe/fqu5O3jj3uVEy6/XK6+bYL9WwYAADHENhb74osvNG7cOFWqVCnjfMWKFd1l/fr197p/vXr1XO3b7Fi926xq3tqXm0h9wbEvVJF8vqhhSQXDhrlmof97Qg/c1U9X31jAXb/rriSNHp39nybsmB0Gxiw8jFf4GLPwMWbhYbzCl6hjlpTD15tYo4LoZb8yZNrZIXDHHS7r9t57g6pe3Ts3bpw0eLB/XQQAAMiOLe2zgO3w4cP1/fffq3poArNbtWrVdOSRR2rBggV7nf/tt99UtWrVCPcWOdKkidS9u9deskRXFHlXRx/tXf32W+mbb3ztHQAAiHMEbRE9LrxQOuYY1wxMmaKUL79U4cLSq6/uucvtt1tNOP+6CAAAkF1JhHfeeUdDhw5VsWLFtGLFCnds27YtI5Pk1ltv1XPPPadhw4bpjz/+0L333qv58+frsssu87v7OFC27W7Jjz6sAQ/syrh+881SaqpP/QIAAHGPoC2iR7583o5juxUbMMC2TFanTtJ//+ud27JFsu81Cbi5IAAAiGKDBw92m2l07NjRlUIIHR988EHGfWxzMqtRe+ONN6px48aunu3o0aNVo0YNX/uOA2jTRurc2Wv/+afO2fy6Wrb0rs6ZI732mq+9AwAAcYygLaJLt25Sx46umfzXX9KgQa792GNSaOXgmDHSSy/52UkAAID9yyNkdVxyySV73e+OO+7QkiVLtGXLFk2YMEHt2rXzrc/IIUsk2C1pwEN67jEve9rcc4+0YYNP/QIAAHGNoC2iSyAgPfOMgruLMgdskrxsmYoV2zuT4dZbpUWL/OsmAAAAEsRxx0k9enjtf/5Rq+mDdd553tU1a6SHH/a1dwAAIE4RtEV0bvpwxRWuGdi82VJSXNtWpvXrt6dMwgUXSDt3+tlRAAAAJITMkdmBA/XYPZvcPrrGFob98YdvPQMAAHGKoC2iUvDBB5VesqR35e23pQkTXPPxx6XQZsyTJmXEcwEAAIC806iRMqfXVhk+SLfc4l3dtctbBQYAAJCbCNoiOpUpo8233bbn+nXXud3HiheXPvxQKlDAO/3MM9Lw4b71EgAAAImif39v41zz5JO6/Yp1qljRuzpihDRqlK+9AwAAcYagLaLW1osvVvCYY7wr06ZJr7/umi1aSE8/ved+ffu6zXwBAACAvFO7thTaWG7DBhX9v4FWKSHD5ZdLGzf61jsAABBnfA3aDh48WI0aNVLx4sXd0bp1a40cOTLb+7/yyis6/vjjVapUKXd06dJFP//8c0T7jAhKTlbw2Wf3XL/9dmn1ate86irpnHO807Zj79lnS9u3+9RPAAAAJIb77pNSUrz2oEHq3e5PderkXV2yhDIJAAAgToK2lSpV0qOPPqpp06Zp6tSp6tSpk3r27Km5c+dmef8xY8bo/PPP1w8//KCJEyeqcuXK6tq1q/7555+I9x0R0rGjdP75XnvtWummm1wzELAgvlSrlnfTL7942Q3BoI99BQAAQHyrUkW68UavvXOnAnfcrtdek4oW9U69/LI0erSvPQQAAHHC16Btjx491L17d9WqVUu1a9fWgAEDVLRoUU2yHaay8O677+qqq65SkyZNVLduXb366qtKT0/Xd999F/G+I4KscG1oU7J33pG++cY1rb7tRx9JhQvvuSnzxr4AAABArrvzTql8ea89bJiqLflRTzyx5+Yrrgho06aAb90DAADxIWpq2qalpen999/Xli1bXJmEnNi6dat27dql0qVL53n/4KMjjnCbPWS48kp7812zcWML5nuZt6EVa++951M/AQAAEP8sc+Chh/Zcv+kmXfGf9IwyCYsXB/Tgg8V86x4AAIgPyX53YPbs2S5Iu337dpdlO3z4cNWvXz9Hf3v77bfryCOPdLVts7Njxw53hGzcvTuAZejaEQn2PMFgMGLPFw/2G7NLLlHgrbcUGDdOWrRIwf79Fdy988Npp0mPPSbddpv3G0TfvkFVrhxUmzZKGHzGwseYhY8xCw/jFT7GLHyJPGaJ+JoRRS67THr+efsyI02dqqT33tVrr12shg2lLVtsBVhhnXtuuk491e+OAgCAWOV70LZOnTqaMWOGNmzYoGHDhqlPnz4aO3bsQQO3VgvXMnOtzm3BggWzvd/AgQPVv3///c6vXr3aBYoj9aXCXp99qUpKiprk5qiW1Zjle/hhle3SRYGdO6WnntLarl2V2qCBu+2ii6SZM4vr3XcLa8eOgHr2DOrLL/9VtWppSgR8xsLHmIWPMQsP4xU+xix8iTxmmzZt8rsLSGT58klPPy2deKJ3/c47VW3BGXryySL673+9U5ddFtCsWd6iMQAAgJgL2hYoUEA1a9Z07ebNm2vKlCkaNGiQXnrppWz/5sknn3RB22+//VaNGjU64OPfeeedumn35lWhTFvbwKxcuXIqbkubIvSFKhAIuOdMtC9UuTpm5csreNddCjzwgAJpaSpz880KTpyYsYOvbQKxYkVQ330X0Nq1SbroorL66adgRsmxeMZnLHyMWfgYs/AwXuFjzMKXyGN2oB/tgYiw1X6WSvvFF5JtjDxggPoNeESffx7UV18FtGpVQJde6t0cKuUFAAAQM0HbrL58ZC5nsK/HH3/cbVg2atQotWjR4qCPl5KS4o592RebSH65sS9UkX7OWJflmN1xh9vwQXPmKDBzpgIPPmjp1O4me5vtpnbtpLlzpYULAzrttIB++EEqUkRxj89Y+Biz8DFm4WG8wseYhS9RxyzRXi+i1FNPeZvk2kqwJ55Q4MIL9dpr9XTMMelasyafvvpKeuEF6Zpr/O4oAACINb7Odi0Ldty4cfrrr79cbVu7buUOLrzwQnd779693bmQxx57TPfee69ef/11VatWTStWrHDH5s2bfXwViCiLzL79tpQ/v3f98cel8eMzbi5ZUvr6a6lSJe/6lCnSOedIqak+9RcAAADxq3Zt22jDa9uE87//Vfmy6Xr22Q0Zd7nlFi+hAAAAIGaCtqtWrXKBWatr27lzZ1cawTJoT9xdG2rx4sVavnx5xv0HDx6snTt36qyzzlLFihUzDiuXgATSpIkUqlNsm5D07i1lCtxbwHbkSKlECe+6ZThccYV3VwAAACBX3XWXVKOG1/7xR2nIEHXuvFPXXht0p2wR4fnnS1u3+ttNAAAQW3wtj/CaFSE9AMu6zcwycgHnttu8AmETJkh//indfLOUqQ6y7dz76adS167earU33pAKF5b+7/+oKQYAAIBcZPWVBw/2Jp5WsuT22xVo3VqPPlpeP/wQsKpemj3bK5Hw+ut+dxYAAMQKioEhdnfsffPNPcVqX37Zi9Jm0qGD9O67VvPOu271xGxPuqCX9AAAAADkDlspaOm0FrRdu1bFHnrIxXI/+MBLHDCWREDQFgAA5BRBW8SumjW9zR9CLrnE0rH3ustZZ7kVahnZtc8+6+1lRuAWAAAAuerppzPqcxW2aO3o0apfX3rllT13ufpqacYM/7oIAABiB0FbxDYrVnvmmV57/Xrp3HO9egiZXHyx9Oqre67b3mW2XwQ1bgEAAJBrKlSQHn0042rgP/+RNmzQBRe4/cmc7du9pIINe/YpAwAAyBJBW8Q2S6G12shHH+1d//lnr97tPi69VHrxxT3Xn3hCOuMMadOmCPYVAAAA8e2KKxTs1Mk1A0uXSjfe6NrPPCO1aOHdZeFCL6kgLc3PjgIAgGhH0Baxz5ahffSRVKCAd33QIOmTT/a7W79+3h4RoRq3VgK3bdv9KioAAAAAhyYpScFXX1V60aJ7Ctl+8YVSUrzpaqlS3unPP5euv56SXQAAIHsEbREfmjXzUhhC+vaVfvttv7tdeaU0cmRGuTG3k2/LltK4cRHsKwAAAOJX1ara1L//nuuXXy79+6+qVZM+/FBKTt6zSe6TT/rWSwAAEOUI2iJ+WLEwq2lrNm6UevTw6tzuo2tXafJkqXZt7/qaNVLnzntvEgEAAAAcqm3nn69gt27elRUrvB3IgkF16bL3XgtW1ev9933rJgAAiGIEbRFf9W0t8tqwoXfdMm3PO09KTd3vrnXqSJMmeQFcY3exPc1smVoWdwcAAAByLhBQ8OWX99RD+OADacgQ1+zTR3rooT13tes//OBTPwEAQNQiaIv4UqyY9NlnUpky3vVRo6Tbb8/yrjaH/vJL6YYb9px77jmpe3dp3boI9RcAAADx6cgj994J95prpF9/dc2775b+8x/v9M6d0qmnUq4LAADsjaAt4k/16tLHH+8pGPb0094mEFmwu1gp3Ndek/Ln986NHi0dd5y0YEEE+wwAAID4c845Xk1bs3Wrd33bNrdAzDbItWpeoZusmgKBWwAAEELQFvGpQwfp+ef3XO/XT/r222zvfuml0vffS+XKedd//90L3FqiLgAAAHDInn1WatDAa8+Zk7HMy5IHPvrIW+UVCtxam8AtAAAwBG0RvyxQa8vQzK5d0umnS9OnZ3v3du2kKVOkRo286xs2eBNnS9QNBiPUZwAAAMSXwoWlDz+UChXyrlutW6txKyklRfrkkz2B2y1bvPaYMT72FwAARAWCtoj/zIaePb325s3eurM//8z27lWrSuPHe/Fdk54u3Xyz1KuXtGpVhPoMAACA+FK//t6rwC67TJo9OyNwa5W9Mgdubco6cqRPfQUAAFGBoC3iW7580nvvSW3aeNdXrpROPllavTrbPylaVBo2TLr33j3nbG+zhg2lzz+PQJ8BAAAQf/r2lS66aE9k1hIL1qxxVwsW9AK3tiGZ2b7du9nOAQCAxETQFvHPlqJZtLVevT0Fay1wu359tn+SlCQ9+KD3Z+XLe+csznvaadIVV3hJuwAAAECO2e5jVhqhWTPv+qJF3sZkVsYrU+D27LO9m+203fz22z72GQAA+IagLRJD6dLS119LRx7pXf/lF+mkk7zCtQdg2Q62cs2CtSGvvCI1bSpNmpTHfQYAAED8JROMGCEdcYR3/YcfvFpcuxUoIA0dKvXps6dUV+/e0hNPsMcCAACJhqAtEkeVKtLo0VK5ct71n3/2CoZt2nTAP7NMW5tbW7C2SBHv3B9/SG3bSvfdl5EcAQAAABxc5cpeSm3+/N71//s/LwN3t+Rk6fXXpauv3vMnt90mXXWVlJrqQ38BAIAvCNoi8TaB+P57qUwZ7/rEid6uDwepd2Cr2f7zH2nGDKlVqz2ZDw89JDVp4pXNTUuLQP8BAAAQ++zX/8GD91z/73/32jzBSnVZLLd//z13efFFb/XXQfINAABAnCBoi8RjO4p9951XMsH89JPUtau0bt1B/7RmTenHH71gre1xZubNky64QKpbV3r1VWnnzjzuPwAAAGLfZZdJN920Jxvg3HO9hIJMSQO2qstq2oaSckeO9PbXtfJdAAAgvhG0RWJq3NgrlVCypHfdJsgdOkjLlx/0T23J2j33eH/SuvWe81Yy4fLLpTp1pLfeIvMWAIBEMnDgQLVs2VLFihVT+fLl1atXLy1YsCDL+waDQXXr1k2BQEAjrAYTEpcVqz3vPK+9bZu3ocL8+Xvd5aKLvGlrqVLe9TlzpBYtvD9lvgkAQPwiaIvEZTv32uYPVrTWWMpCu3bSn3/m6M9btpTGj/eqLXTuvOf8X395m0c0aiQNH86mEQAAJIKxY8fq6quv1qRJkzR69Gjt2rVLXbt21ZYtW/a777PPPusCtoCrgzBkiNSpk3d97Vpvs9x//tnrbpZbYAkDDRp4121ll9W57dgxx1NXAAAQYwjaIrFZQVorj1C1qnfdZr0WuJ05M0d/bt+3TjhB+vZbbyJtVRZCrGzCGWdIxx3n3U7wFgCA+PX111/rkksuUYMGDdS4cWMNGTJEixcv1rRp0/a634wZM/TUU0/pddtpCjApKd4v/bYSzCxe7AVx91kBZqu5pk6VbrnFm4Mam8ban1mJLuaaAADEl2S/OwD4rlatPXVtf/3VmyBb4Pb996VTTsnxw9gGZaNGSWPGSHfdtack2ZQp0oknesHdRx7Zs5EZAACIXxs2bHCXpUM19CVt3bpVF1xwgV544QVVqFAhR4+zY8cOd4Rs3LjRXaanp7sjr9lzWDmHSDxXvDikMStaVPrySwXat1fAkgh++03BE05Q0JZ0ZfqsFCggPfaYN0Xt2zegv/4KuP10rUTX8OFBvfJKMPPdYwafs/AwXuFjzMLHmIWH8QpfIo9Zeg5fM0FbwFSqJI0b59URmzxZbvZr2/M+/bR03XV70hlywJapWdmEL7+U7r5bmjXLO2+VGKwGrj3sww9LxxyTdy8HAAD4OxG/4YYb1LZtWzW0DVB3u/HGG9WmTRv17NkzrFq5/fv33+/86tWrtX37dkXitVgA2r5UJdlSfuTdmOXLp6QPPlDpM85Q8pIlCixYoLQOHbT2k0+UXq7cXne1DXBHjw7o/vuLaejQwu7cV18F1LBhUI8/vkGnnron0B8L+JyFh/EKH2MWPsYsPIxX+BJ5zDZt2pSj+xG0BULKlvUiq1aQ9qOPvF18b7hBsk1EBg3as21vDliM1+K/3btLH3zg7fxrG5WZzz6TPv9cOv986YEHvERfAAAQP6y27Zw5c/STreTZ7bPPPtP333+v6dOnh/VYd955p2666aa9Mm0rV66scuXKqXjx4orEFyqrv2vPl2hfqHwZM9trYcwYl2UbWLxYyX/8oXLnnafgN99IFSvud9e335bOPTddV1wR0MqVAa1bl6TLLy+lCy4I6rnnghmbl0U7PmfhYbzCx5iFjzELD+MVvkQes4IFC+bofgRtgcwKFfLKItSuLQ0Y4J0bPNhLl7Xo61FHhfVw9v87Fpw96yxvjwlLlLF9Jazm2NCh3mEJON26SSefLLVt65U1AwAAsemaa67RF198oXHjxqmSreTZzQK2CxcuVMmSJfe6/5lnnqnjjz9eY6y+UhZSUlLcsS/7chOpLzj2hSqSzxcPDmvMjj7aq7dlu49Zxu28ea5sgkaP9m7bh63iatNGuvJK6eOPvXNDhwY0dmxAb7zhlemKBXzOwsN4hY8xCx9jFh7GK3yJOmZJOXy9iTUqQE7YPx6rX/Dmm3uya63eQbNm9o3rkB7SHsZqjf3+u/TUU1KZMntumzNHeuIJqXNn77ytmLQ48aJFufR6AABAnrOlfRawHT58uAvQVq9efa/b77jjDs2aNcttRBY6zDPPPKM3LLIGZGafHwvcZt4s137dnz072wVjtlDMMm9LlPDOWaKAbdlwySX77WkGAABiAEFbIDu9e0s//ihVruxdX7XKS1WwDNxDLJRtiby2wtHm3QMHSsceu3e53C1bvPIJV13lJVLYpmUjRhzy0wEAgAiWRHjnnXc0dOhQFStWTCtWrHDHtm3b3O228ZjVt818mCpVquwX4AUcmwxaiY369b3rK1ZIlnE7YUKWd7c55UUXeXFdSwYIsTwEW0Rmc88IlEEGAAC5hKAtcCDHHSf98ot00knedYue3nOPF7y19IVDZCXo7rjD2/PMYsFWJsFixFabLDO7/fTTvU3LLHNi587DfD0AACBPDB482G2m0bFjR1WsWDHj+MDKKwGHu1mu/dJv1q+XunTx0mqzYfkGVgL3hRekUDUO22P3rru8+O8nn3ilugAAQHQjaAscjK03+/JLb9ewUFqslUlo1MhLg82Fh7e6t5YFYUvXpk3zknktUBsyb54X1LX9J6zMwnffSWlph/3UAAAgF8sjZHVcYmvTD/A3vXr1img/EYOsfpZN/kLFaS17+5xzpIceyjb6atW+bOWWleb673+968bKb515ptSpkzRzZgRfAwAACBtBWyAn8uWT7r/fC9aGNiNbu9ZLg7Uo6oYNufI0NqG20rmWCWETaYsVW/myEHvKV1/1EiyOPNIL9v7vf15dXEooAAAAxKmiRaXPP5f69Nlz7r77pAsv9IK4B0gOsLmilVC2QG2Ilcu1OadNY22/XQAAEH0I2gLh6NjRm9meccaecxZFtbVmn36aq09lSb3du3ulzMaOlc47TypSZM/tVlbh/fethp7UuHGS6tQpr2bNAi6ObHVz33lH2rUrV7sEAAAAv6SkSLZp3WOP7Vn99d57Xp3bv/464J/aCq5vv5WGD/dK5Rr7wd+msY0bexXBrG1lFAAAQHQgaAuEq3Rpadgw6ZVXvKwHs2yZZMsbzz47T7bntbm4zcktUPvhh17MOHMA12zenKSZMwOuYsMzz0gXXyw1aOB1lbplAAAAccCCtbfd5hWmDU0Gp0710mYtE/cgf2rTVSu7ZXHfYsX23Pbzz17WrS0ou+EG6Y8/8vh1AACAgyJoCxwKm/X+5z/S3LlSt257zluEtE4d6amn8mTXsMKFvbjwxx9L69Z5E2x7qtNOC6pq1VQlJ+8dnbU6Znb/Nm28GPOQIV7tXMvCta4DAAAgBln0dfz4PWmzNjE87TTp9tsPutTKEnYt7rt4sfT8816mbcjGjdKgQVKtWtIpp0ijRlGCCwAAvxC0BQ5HlSpe4VmLgtomEWbTJumWW7yNymymm0fy55datvRKIQwfHtSkSWu0ZUvQrY4bOVLq0GHPfSdNkq64QurbV7L9UCwLt2FD73j4YS+4CwAAgBhi0dZfftm7bNfjj3tLtHIwuStZ0iuzNX26lwhw2WVSwYJ7bv/qK+nkk6V69bzgrk1xAQBA5BC0BXIj69Y2gZg/34uMhmqMLVjgzXStMG2EtudNTpaqVvWe9ocfpC++8EokZMeybe+9V6pdW2re3Jvn//13RLoKAACAw1WihLfS69lnvYlg6Nf6Jk2kwYNzVCPLpq6WCGA1bZcu9UonWF5CyG+/Sdde65VOuP56fuwHACBSCNoCucW2533pJWnKFKl16z3nLe21aVOpd++DbhKRm2wCbsvaLF5swVvr2osvevN3m4y3bbv3/S1Rw1bUVavmbUZx1VXe/N+yLObM8WLSNmm3GmcbNkTsZQAAAOBgkz6LptrutTVreue2bvUmc5Y88M8/OX4oWzhmpRMWLvTK5toevCGWafvcc96P/fawNkfcsSMPXg8AAHB2/xwLINdYyqrVGBs6VLrrLq9gmGU5vP229MEH3tqzO+7YO4UhD+XL5wVv92UT8iVLvI3N3n/f28MixJbI2XGgxzzhBOmss6TTT5fKl8+bvgMAACCH7Ff3GTO8Ml32S735+muvvoHVw7JaCDaJywFL2rU5nh2zZ0v/939eNbBt2/bkJNhRoIDUooW3f4IlBNgl80IAAHIHmbZAXpZMsBIJtlNY6dLeeduczFJdLQuiX7+IZt5mpXJl6eabveRgy6AdMEA65piD/11amvTtt9KVV0oVK3qJxLbhmWXqvvyyVxuNTSsAAAAirEgRb65pabAVKuxJkbVM3FatvKVVYbK5oc3vrHSCldKyUlwhNrWdMEF68kkvwHvEEd4mZraHgm1+Sx1cAAAOHUFbIC/Zbg62U5itMbvzTqloUe+87eprs18L3l5wgTRtmt89VY0aXmLwrFnSmjXeBHzIEO/cpZd6k2+r8HD++VL16nv+zoKzltRh5dRsIm+x6GbNvGCu3f/dd72MXgAAAERIt27SvHnefgshtqzKitda2YR//w37IS0H4dZbvWnt8OFSnz5egHZflghgAVubO9p80OaRVrkhB+V1AQBAJpRHACLBtud95BEvrfWZZ7yCYJZ6YCmr773nHVY0zAK8ViQsh0vX8orVM7OyvJlL82Zmk27LprVA7YgRXq1beymZrVrlVYSww9jmFfZ4luRhtdCOPtoL/hYunPevBwAAIOGUKuVtamC/otuv6rYDrf3abpm4Vhurf39v2VT+/GE9rE1Te/XyjtCcb+JErzqY/ehvK7gsA9ds2SK98YZ3WGWwk07yjs6dvekxAADIXiAYTKzfPDdu3KgSJUpow4YNKl68eESeMz09XatWrVL58uWVlERyc07E/ZitXesFbl94wUtrzczWnNkE2mrflisXE+NlicNWutcyL379VfruO+n7772Jek72b7NJu/1ztMNKNhx/vBfDtkRkqzSRF/wes1jEmIWH8QofYxa+RB4zP+Z0ifi6E/kzFldjZlFUSxyw2rabN+85H6p3a7UNcmnSZZuT2d4Itr2DHRs3Zh34bdjQK7FlK7QaNUpXsWJr1KBBWaWkRMmYRbGo/IxFOcYsfIxZeBiv8CXymG3M4XyOoG0EJPIH8VAlzJjZbg5vvSU9/bSXrpqZ7exwxhnSxRdLXbt6O0LE0HiFapxZ7VvLvrDJe+bvCDlx5JFSkyZefTQry2aXlqFr3y8sS/dwEpKjccyiHWMWHsYrfIxZ+BJ5zAjaErSNVlE9ZsuWeSW7bP6ZmUVOLXh78sm5+ov51q1eKQV7ujFj9mTgZicQCKp8+YDLYbCSXFZaIYH+ecfHZyxKMWbhY8zCw3iFL5HHbGMO53OURwD8VKiQt1zt8su9DSP+9z9vl1/7LcVmtbZ0zQ6LVtrM1QK4lpKQV+mnuchizpYta4ex8glz5nj1b//8c89h3x0sA2PDhv1LLNhtdmT3+FZmwYK69j3DDmuXKJH3rw0AACAm2S/iVnDW6treeKP3y7qxDcqsRJfVsbKg7qmnSrnwBdrKYNnevHZYAHfsWGnUKG9VlpXc3Xfj2mAwoJUr5Q77wf+++7zAbd++UrFi3hTYDlupFdoqAgCAeEXQFogGNim2ybEdVmPA6o9Z8a9Q6QSbuT77rHc0aOAFb232W6mSYoVlxTZu7B1ZsTi1TeZtIzTLxLDDNq2wc1mxmLYFge1455296/FazTQ7bEJvpRtsmZ4dNtlv1Mjrg+2EDAAAkJCOO84rQmtJA/fc4/2qbiZNknr29Oabt98unXde2DVvDxTAtf3R7AgtOJs924sXz54d1J9/7tDatSn655+A/vnHu49tATFokHfsO6+0+LItRrOjRYsDLkoDACAmUR4hAhI55ftQMWa7o5KWdWs7eX322f7rySzNwHb26tVL6T17alXx4nE3XpZ5a5sbW8x6xQpp+XKvisT8+V7t3N9/94Kyh6pMmTTVq5ekOnUCLms3NdXbTMOezzJ/rdaabZTRrp1UpEhuvrLYxL/L8DBe4WPMwpfIY0Z5BMojRKuYGzNLd7UaBvff721WlpklCFhWrq0Ks1/DIzRmloVr2z9YWQUL7h6M7Y9gczYL4J54oldGK57F3GcsCjBm4WPMwsN4hS+Rx2wjNW2zRtA2NjBm+1i3TvroI2/malkRWdhVt66SzzxTAdtIwmoFxEAJhcMVyra1DA07rG0boi1dun+phcNhCSaWkGIZulZP1w7bJM02ZbZgbqJ8RPl3GR7GK3yMWfgSecwI2hK0jVYxO2YWvLXM24EDvY0JMktJ8VZ5/fe/UvPmuT7PzG7M7Mf711/3EoHtW6sdNsezDF37ET87Vi7LVl1ZbVzb5Na6b122h7aMX8vSbd8+dkssxOxnzEeMWfgYs/AwXuFL5DHbSE1bII5YdPCKK7zDyidYPYAPP/SKge2W32auAwZ4h81OTzvNSzeworJx+mXW6tqG6tlmZpN5y8q1WLdN0u1+dmkZtDNneseMGUHNm5eulSsPvpuZZfNaqQY79mVfAGx4K1bc0xf7LmOB3XLlEiegCwAA4qhcl016nnhC+vxzL1JqdaYsemqHbSJgmbcXXOCluOYhK3t1661Z32Y/1I8eLX3zjbfx7dq1e26zFVMW2LUjO1ZOwX6UP/54L7hrScV2WJYueyQAAKIBmbYRkMi/HhwqxiyHrFbAiBEKjhihQGgjiX1Z0S+bkXbp4q0Xs3Yu1SaLh89YwYLl9fvvSS4WXrCgt+db+fJe25JMbKMM+yJgt4fLhr5CBS+ga/t+ZHdpwV27b4iVaViyxHtO26zN9quz+m95uCoxR/h3GR7GK3yMWfgSeczItCXTNlrF1ZjZROSFF6TXXvMioZnZBMUCvFb31iYqdt2nMbMf7G3VlQVwbV8E67bNpQ6ljJb9IG8/vls2rlUis3q5dt0SAKJFXH3GIoQxCx9jFh7GK3yJPGYbKY+QNYK2sYExC3+81syerbITJijJ6t9apDG7WaqtA7Ps2xNO8Iq1Nm2akEHccD9jtiec1dENHZbdsXGj9/3Fjr/+2r/scDgs2yN0bN/uBW4zs6Cuxd3PPder2WbB3khvuMG/y/AwXuFjzMKXyGNG0JagbbSKyzHbvFl67z3plVekKVP2v912e+3Vy5uoWJKALXPyecys2oPtibBsmTevsuuhc99/702XLf8hJ2weZvsf2Ea2Nf6/vfsAk7K69zj+n6UtvXdQQLEHL0aM7cYYjfXaYvDqgwaT3GuMaCxJbIntMUZN0USTENNMnmshwYgFQ4wFsETsKCooUYMImgWpLtJ23vv8zstZ3hmmvTuzu8O+38/zHGanLDtz9p2d//m/5/zPTmZDh4axmC71NlS5LIXYai0RVrfJY6yZ0Wfx0Wfx0F/xJbnP1lAeAUiWtKaIfv3rYa0xZRM1zUBTRLVuLFr0S0H39OlhExX20uxbJXC1PkzTChR4I4Nmuap71HJRjlx7d7z4YjjTY9GisESDBgra3EyDhEI0mMhO1GbPIHn44bD5WSD6lWuwkN20pM8PHDTpRf+vnp+aZolowKFfOwAAQEkUVKgkgprqTP32t2ESV0VnZe3acPNcNZX1Ovlks/HjzQ45pNWmqGr8r8SqWrYvfSm81Gxc7YmwZEm4J4JaWEYrMy5THOZP3Bf7mbvtFpbKUsksxVxaUdWnT1jqoYzJyACABCJpC7RFOlOjmrZqPiLVdAIlcJXIVRbRW7fObObMsPloUztu7bdfuB5Mbc89EzkbNw51j0q8qX3ta5n3KehXl/skbvblsmVbk7Zq+r9UT02bnY0aFS7xUwljJYI9rZHQTBE1JYrj0GwRDSL0K9aAYtddw9kjKteQa1+R+vowIa3ZxMOHt3PlIwAAQEIpTrz1VrObbgqnrE6ZYjZt2tbyCdpUQEldNU1B1RKhY44JSyhod7Aqom0g1LIpPNZJ+DlzwiSuauNqK4li5RZ0kl6PU1P+OpvmRYwYsbVp1q6SvGp6HgmbaAYAKIKkLZAEigLPPDNsyvYpA/fkk1t319Ja/2i0+fLLYbvttvA2FXhVNlLTBpTE1aWiSxK5JVEZAz/TQ13XFDfeaPbcc2b33hsu5fMzQrS5WrFZvNk0W0QzSNSyJ9HoOfolfvq1K2GsFhbS0Uiiv+2zT+Amzxx3XPh92vhDTQlnJZlHj95+d2MGAAAlUhx45JFh+9WvwuVASuCqVJfO+IoudV1NNBHAJ3APOih2GYWWohVJWoSm5ilh+89/hnMhdNJdsZhOwGsRm16mLnUyXTN3862e0oTkfBukaRauNkLTSirtiaAZuoq//GopnVhXzluxlhK+PXrUuJVgJHoBoO0iaQskjSK+vfYKm0opiJK2Tz+9NZGraDNa7lpFVjXVQM1TkK3AW7Mt1JTU1aWWxKFZfm2qYqEWpUGBBggaOPjBgwYEGjioffJJmDTWr0tjK61iVCk65e2zk716fCm13V56KeVmn1x2Wf7HaLCh2btK4PqmGbpaIamm5xO9VII4X6JXh5+eW2tvxAYAAPLQh7lf5aVpqn/9a1iKa8aMzBVeCkDUfvSjMEupnb6014LqT2mZURVTHKUNydQK2bAhTMpqJZQ2lfUntxWDKdmrlVO5ZuwqZlu4MGzFKVM7wDp2DFy3KZGrOEo/RxOd1RQ3aa7FuHFhU1xWpTlyAEAeJG0BhKft1U47LbyurJ9m2r7wwtaWHUFq1y0/Izd7Vq8Swn6tlyJbXSpyzLX2HmVRQlazMtTiUBJUiVeNm5SoffPN8FLBvn79foaIZpooN69yCoMHB/bQQ5ts7tziEb8v3fDEE6U/J5Vn8CUmdBi9+mo4u1iXej46RP2sFzU9r+zZJTrXoBkwGriofhwAAGhhCh5UNFZNZ4gVcCiJqwTus89unRigLKXKKzz+uEtBDlTiV0lc1cFVU6ZxO1y6o5fhK4zloi7RSfZ3390ag2n7CV3qdm1NUaqNG1Pu+9Sy6f/XifrJk8PrCsO194Fm6e64o1mvXltXV2k/BJXlUsks3a9SWgCA1pcKguh0upY1efJk1/6lQolutcyeduWVV9rRWi6Tw+uvv+7uf/HFF23RokV288032wUXXFD1Ow0neUe8pqLPqrC/Vq0Kg25Ff1pXrwJfihBLXZuvDFo0ieubpge0QmTIMVaYcvJa6qc/k/7X4/usvn6A/eUvNS6X75Ojavo00bJBP0skOrGmOWiwoZWVanq+GgeqKfEsOk+gwYdvmmGiSw1YNCjSR4+aZvJqjKj6vkqCVwrHWHz0WXxJ7rPWiOmS+LqTfIw1FX1WwPLlYRmFv/3NbPbs8ExrPuo7xY0qwq8Eri51FrmNTxdVLlvlr9RV6gK/WkqzcxW3qGzV228HtmDBBluypJO9807KfY+nuE1JWB8PNSXprPBc5RkUSxVrqtObPS9Ds401q1ilvBRPKoHd2iumeF/GR5/FQ3/Fl+Q+W1NiPNeqM22HDRtmN9xwg40ePdqUO/7jH/9oJ5xwgr388ssugZtt3bp1NmrUKBs/frxdeOGFrfKcgcRShuzznw+bpwhRpRSUwPVb7WpaZK4pAooc//GPsEUpEvU7MegUvy59U8SodfNocfq15BsT6ddy8cXF/w/tRxJN4uq6gng1JVn912o6ZDTrV8v5ojQI2GOPcMdlJYm14jJ6HuGhh8KWiwY7aqr8UQp9VmpijwYWGuxoEKIZKJp5rAoiGleqBIUmEPkaxZodrMGNYgw13af/Q98PAACyKHM3YULYdLZXWchZsyyYNcsaZs609tEkriYG+HIKt98e3qYPXS3J0Ye1L9GlFV76AG4jVDXCb1SWTS9V0unA6upWuURHKpVySV7FU6pS5pOoiq1UokHxk+ZdqFSDulsb4Bai/0czf9VKoYSyfi1KFqvp15odz4l+bYcfHlbCUPyksllKDLehXx0AVFyrJm2P87vYbHHddde5mbdz5szJmbQdN26ca3LppZe22PMEUCCq9IWyPEVqmsbooz21+fPDS51uz6bsndaG5SqmqohTmTGti9c6Lt+i1xWZoiopcamN10rdfM2XNlD+X4eKkrWa/ep/xZphomocfv88teyBh4J/HY46n6CJ4JrlUSoNbh58MGzl0OBDlUb+53/CQ1SvS3Xs9Np0qeemphm+egtp4KKmjUf0dtBj1JSg1usnAQwAaJMU5+lM8MiRFkycaMs122r9eqvRHgs646rVXb5GUjSj6JfWeDprquL5PonrE7mqtZSAmVvqRu0lkOtk9KGHhi1KM18VZ+mktN9ATSe5FYr70F3J3eiJ8kL8RmnF+E1wf/zjbeMmxW++Ke5RfKTbdak4SoeAmr5WMlsxoprirAT8igEkWNXUtG1oaLCpU6dafX29HaB1qgC2Tz7RqhadlSuKDhUR+iSumq7r1H+uyFCRmd9h65lncv88TSmIJnEVoKvAqy7V9Dw0BQBVz++KrJaLfo1aGal20UXh4aHDR/vjaVbw/vuHgXx0iZ4/5Hy9NzXV2tVh4WexNDS4ST42c2bx2Sel0KH8u9+p1djgwf1t9epUyQOfbEpYf/3rZlpcoucMAECbpiDgjDPCJjrLqbO5KnKvpkRu9ol+zcj1H/J//vPW25X1U12k7PJcSvAmeCWXVhGpW4pR1+sksl+5lK/pMTrprHhKTfGZZtEqHFdJKiVVFWfpxHuuwoyKkbQ5m1pc+jX62FFNJ8F9sleXOiGvVV/hLOOU9ejRx77whZQddli4P4Ieo+esxLWeh8p9adYwAFSLVk/azps3zyVp169fb926dbNp06bZHjptViEbNmxwLVo3wtfOUGsJ+jkq/9BSP68toM/aaH8pShw7NmxRiuCUSVNE9fbbltpy6dqiRZYqVBzVb5GrgD6HQBk8RXB+t67hwy1QGzrU2nfpYmkF8YooExy8b8/HmcZdatFDKTogyHfIZVNiVN+nFZjauEPBuxK+ulTg7wcDOlQ0iNEMXjUdtgr21SVqCxak7O679VkTZo4/+KC8es16DpqRcsstgdvPRQMJ/Vy/UYmu6/np8NVAI5xgFLgliKrPq9eitnhxynr1Clxf+U1GKlm/ty0fY9UuyX2WxNcMJI4+5HRWVs3zcV+06QM8MuZzlIXLtWmuYkOd2I+W5Yp+zSquxq5vyma3+SjBqxPkqqymk+TZTffH3W1Hq5byLdjblmKzju5w+OEPt5Z1UKwXpZVP2XNA1HS7ry+sFv1aTZU/cg0n9Bw1/0Qn39WnABBHqw/Zdt11V5s7d64rvnvPPffYxIkTbfbs2RVL3F5//fV2zTXXbHP7smXLXKK4pQYVen0aVCWtuHJT0WcJ7C8VwdJOUWrZPvnE2i1dau3efz9sS5Y0fl2jr5cutVR06VxEStGfz7BphsaWkE2i+yGke/WyhgEDLD1okKUHDLCGgQMtvaW52/V1//4WKAuYvdtCQrSJ46wIzQxRy0eHmQJzP7E7l4svTtn999fanXd2trfeamcDB6ZtyJC0DRvWYH37pq1z58BqawM3UFi3TnXoaqyuTq2ddeoUWJ8+aevdO2319Sm7777OtmFDyu0OfdddxZ+/NufeeoRn23p7+/aBDRiQtv791RrcZb9+4XXd3q5dYG+91b6xKTc2duwmGzduk+2770YbObLBvWX9YaBlkWvXpmzt2hr3mvRau3ePv89pEo6xSktyn63VWQ0AyaNVVp/7XNiiH9CaaasErkoqaFWXmiYAZJ/gUWyoYvVqjz++7f+vNfrRJK5KOESzeGTemkRJzfHjw5aLToJrCww/69WXk9JHm040q+nXrH0S3ngjbErW6teoMg/FKC5RrFKsrIPqA6upFnAc/lyATpCPGhVuyKvn6A9BvQ4Nc3wFjzFjwktNCND3arayDmF9j84/6P/ShAEddsz+BZIrFSjKryKHH3647bTTTnbbbbcVfNyIESPsggsucC3uTNvhw4fbypUrW2ynYQ2olCTu379/4gZUTUWfxZP4/lKUp6mHkd2iUrpUU9EuXf7732ECt0yBTqH7zJ6Cel0OHGhB9Hr0/jZUmiHxx1kr9Jdm8t5yS8omT946e1c6dAjcmFUfbzr/qMRua0ilApe83bx5258/YkTgBiQqK9ivX+AmLuljV2+hrc87fIto5q/GxIMGaQfZZbZxY39bvLjGvX01kOnWzRq/X5PjmRi/VZLfl4rpevfuXXTX3aTuNlwpSd7ZuanosyrqM33QaH18dI8FZcZ0m3Y0bQrtjhqdgpndlIXLt5trhXCMbeU3PtsS7jcme9UUL/iJ1L16pe2NN5bbvHn9bObMGrc3sr5Xf0Z9fKLvV+yhYUVLLebQSikltJXc1ZAmF9Us9qu+lMRVUlvPUU2JbiWJ/T4SSgRr/2hfJkKvQzOZfTJaP0M/zzc9ToeQ4i3fPI6zeOiv+JLcZ2tKjOdafaZtrl9aNMlark6dOrmWTQdESx4U2tWzpX/m9o4+iyfR/aXXXKgYquj0tWbbbknmpt97zz755z+ty+rVlvJRj+4vMgM/pfv97Izo7fm+QZk1JXAVFSkqU6BfqOkxVZyRSvRx1gr9paV0N9xgdvnl4eYdCsJ1W58++n+3Pk4BuQYZfpMPTTTSQESJUAXyemsoqPdLCDVLRQlhBfHFBiWa2aIAPtdslCBIZewPE6XacdrI5IEHXE+U9Ho7dkxZOj0oZxLY0+BCteiOOcbsC18I3zZ+Bo7GyEk8NJP6vkza6wXQBBoHaoPrHJtcuw9GX47LFz71rdBOpn7HUH3g5qIPzegae2XcdF2X0a91yazdsqm7FT6rFaJ4R6uK/vu/ww1jC1HMo6GBnwOipvINfnZudlP6QiUQFF8pgezp16uTzTo5/c474SxaDUmyD0O1QhSzqW1ZNLgN/d+PPmoVoZPtxx9vdsIJ4Ya4vu/8Ya+hkF6DT9lEhzA6ka+Z0qtXh2W8FLNqKASg6Vo1aXvZZZfZ0UcfbTvssINb4nbXXXfZrFmz7OGHH3b3f/nLX7ahQ4e6EgeyceNGe0N/6bZ8vWTJEldaQbVwd9bpMwDIR9kcv/OUpNO2tq7OOg8YYCk/8FeWS1GGT+BGk7mKlLTOyTdFbqWcgvc1dzWro1TKShVL7GbfpmweCYw2SydfP/vZ0s5bKNAulWZb6FD2sy90mOtSgbhq32qMq49XJWZffNHcrBRt/Kbv0ff63Zw1KNFuz3qeeqtp0KLVqaUsV4xSGYhiNLvkwQfDlk2JWy099ONzJa313DRmV9Pb2w++NLhSueuDDgpboZp9+tOg11uNdYABAE3kM33jxuX+sFEmTAlcv5Ir2vQhkm9apN+rQU0bpxWiD85cyVx/GV29pRJdaBFaBVRsPkg+SmxqPwHN19D3R8NzJXijVTx8SWYNFXzcpabVRTrM/DwRNQ1JshcN+tVIlawWpJrDaj/4gQ69lAVBf/voI51UL/69ej7R56i46aijzE4/PYxP/TkKxZma6K6+UXym2DGpJ96BYlp1+KFp0ErMfvDBB25a8JgxY1zC9guaOmP64/RexiyKpUuX2tjIbjI//vGPXTvkkENcshcAyqJIQ8lPNZ0WL8QX3oomctWU8cp1W/YuB4VooKCmaK1U+lupU9m5krq63b8u36K3JbhOb9JpRoTGhGrFBi/aZVmtVAruNWjRzF4/40LNL1f0TW8NzcjVY//1r8CCYLONGtXeRoxIucGOnqPfFE4DlkceCcfBuSiB7OvcTZ1a2vO89dbwUj/rU58Ka9Ep8avxsQZUGm+rrp3e7vqzoLH9vvuGgyqfqNbgSgOTaCI7+rUogUxNOgDYTugEuqYcquWiP/L6MIomcn1JLt9yZdmy+Q/HUnbSUsZrSwI31a+f9ezRw1KazesTu35Vl2+K9dpQma7thQ+/c9Gvwx9WEybE+381u1WHmM4XKHTXiWfFKoqTNL9EJ9fVlBT2NYF1qXhsSzU31xSvKLHsN3/TzFkdpnqcTrbPm7f1sK2r0/ig9E11sw93xUDTp4dNsZL6RT8z17BIQxntF+HjMB3OGkL5rUn0f0erkOj1+8PcH/Ia1vgT7HqL6vsUX+r1qkzGbrs1e+USoO3XtG1rdcCSXqejqeizeOiv7aDPdEpZp9H92qJcTVmh7NvyrT2vJEV72Ylc35SV2tLS3bvbajPrOXy41eixkfuIgLbF+7J5+kyDCq1IfeihMKGqQYxPjuoto3Fv9tLDaqAEtTY/14xpnX/WBC4/y0YDGM1oViJY+7BqEOb/XOjPgt5uSpjvt19m9ZTw3FHaNm2qs0GDknectUZMV4hWht177722YMEC69y5sx144IF24403uk13ZcWKFXbVVVfZ3//+dzcxQXWITzzxRLv22mvd6ygVNW2rH30WX5vsM02r9EtYopfZX6s118aKmoYZTeQWatHslxLEbeyEfps8xpqBDketZrr/fq2wCqxz57QNHlxjAwemXCJVh4bCfp2I9nNYosMWPzTQeQ/Nq4szB6US9LN12Ostlj2M8iuylBhWAl1DIDW9DiWsfVOCWXGZ349Qr1uJcr0mNT1esaaaT4qrpVJbj7H162saayz7+sK61HNrY2+tsiT5fblme61pCwBtkiIbv/ytVDqnpiC+UFI3132a1hiHIg//vQXoYzRvWSplkvRhE03k+lbq7W1wgIDKUzynGmu+zlo2BegqTfj66+EkJ50v8RufKeDWjFo/Q0MJ3qefDpvqxGlGSi4K1vV47WHT1PMo+vkavORbGKTZM8UWDWmQpJm+GnT41bqbN9fYkCH9bfz4lKvT95nPbF1eqLe2/ozkK+uwaFF4n/bMQflmz55tkyZNsnHjxtnmzZvt8ssvtyOOOMKV9uratatbMaamVWJ77LGHLVq0yM4++2x32z333NPaTx9ApSkr5KcFFqMPoFzJXU2HVNPKLX+peK3UeVea0qiWtRdDUfrAyRevlXqd7NR2SUOV//3fsKXTgdsgNkyoxf9dKqH5xBNm//d/YSJYh63fAE3nCHTd18fV8EXVSHKdv/AbpJVSokH/T76hUHRFVjGPPWaxKPZSOYnOnfu5chKaQJ+L5sQoVjvggLCp7q9PHutPhvqfUteIYqZtC0jy2YOmos/iob/ia9N9pojEJ3F1qaJRvmn6XqHrai21XW42RSsK8HV6uxKtlWf/tuljrA32mQ57LaNTPV41jZm1jE5JUi3X02BBsyU0M1YzfDX+1cBCQbkulSDVIew3RYt+rcGIagGrDEQ2vUwF8MU2ISmVZukq6Nfz0jhdP/8//9Psv/4rbHpbTJlidvfd4Uxf0W7Tp5xiNn58WMZBfaFBlCaJFRpz63GteWhX20zbbMuWhQNdJXM/m6co9dSpU+3000+3+vp6a19i0WRm2lY/+iw++iyGhgZLL19uKxYssD4NDVajeM8nc/2uVorv/Ne+tcTqrSj9HvU3KldSN25MV4ET+xxj1d9nykzpUPYbuimBqaSmL+Olk/G+xq9WKWUf4r4pBtL3aCsTxTVKEKtshEo/LFiQe3PdaqLXreetiQaanavYTbGdYs1oBT7FmlqlpfJealrYo3NEit18f6qfNOlAJ+r1/6rUl07WV8v5lCS/L9cw0xYAEkoDf79OJy5lYZTp8QldRT1bTlmnV62y+iVLrFtDg6WUpfKnsqPN12ZrSuJXkUih0+NxKcKpVAJY0Y8iI7RZihO1GZnaoYfmfozGjCpxoNYUGmRoxokGDKNGmY0ZEwbb+n811lZQrRnCegv50tRK6Koe25NPhk2ziEUDEAXz3bsH9uyzGoCE0bcmYkVpjD5zZti+9a3cz8vXwbvkkvDPR3Rcr8GC38NRAyAls/2ASX8q9By0dNA3v7Eb9Kcs/FvWp8CW5j5QL5Sw3bBhg2vRIN8PdNSam36G5ni0xM9qK+iz+OizGFIpS/fta5t22cXSOlNXSqJD2Rv90c6V1F250lLRjJffRDcSA6aa8nvR9/gJAWUK8p3Yz7otyHO7WlrLbTZssLSSI9FaQ6iq96UOabVclGxU0wzVplLCVglPDTv0svxJdx0eaorJdPgr3lJTOavVq1OubILfdkQf2X7zNL21/OR4JZU//jiwQYNSjXsJKo7y9YXVtMlbWCs4Pz/R/plnir+eXPs49OwZuBViep0rVmz7s7p1C1yJCL/QUc9Ri0J9f2Q33a7Z0f/xH4HtvXcYv+o1qX80O/r991PWt2/gJjko2axEu+73Q0P1kcp/KXbNluS//ekSXzMzbVtAks8eNBV9Fg/9FR991ox95gcG2cncXAne6HUlgqMtzuZtLUERTYxErwYHq9Np6zlsmNUoKorer/+rWk5xVxHel8VpPK3ZFjqMfJ+99dYy+8c/+ttf/lLjErjRaiUK2DXgyEXL8zR4eemlyj2/SZPMfv5zs6TPtNXv5fjjj7dVq1bZU089lfMxy5cvt09/+tNupu11112X9/+6+uqr7Zprrtnm9rfeesu6+wOhmV+L+lh9zfuyNPRZfPRZFfdXEFjqk08stWaNazVr17qT92o1uk2Xuh79OnJf422qE1Qlgo4dLejaNWydO8dvXbq4SyvwmLy1ibYjvC8r318aJr33Xjt74YUO9sorHay+PrUlOZpyq5yWLGnn7l+2rPBkke7d07ZxY8o2bNh+xhNDhjTYnntusn790rZ8eY0tW1bjLrt332wHHbTZDj54k+2//0aXdNYEgnXr1Ccp69MnnfPcVF1djWu77LK5tRdYNsnatWttl112YaYtAKCFKRnpk5OatthUfhvb7GRuU1u5gwV/ilyn00tQsAawIo84pSCij83+Pl2nHnBi5Jq02atXYGeeafbVr+YeHGhJoHZunjEjfBsce6zZqaeGs31FsyQ0S0Obu+kQ12wLNc080S7VKusQffsoMPbL73RfdHK8ZttCyetJ9tprr+VN2CrhfOyxx7ratkrKFnLZZZfZRRddlPG9w4cPdxuZtVR5hFQq5X4eg/bS0Gfx0Wdtu780SyxQRsqftM8Vp+lk/ZYkb67boy1V5on91MaNrrkplc0k0BlWv3NVdvPTG7NaUOT+bZrO0jbj7397O85aW6n9pRm4Kr9VyLp1aTdz1294pqZQXwspNRNZh8jmzYEtXBi4sg+vvZZyMZniNu2ToEut2FLJBJX7GjkysKVLU261l+JCreJKp1t27LB0aTvXttXerTb77W/1GgM3OUHJWq9378CtcjvwwMDFrnPmpOzxx7U6LXxMly6BHXigVsoFrkyE3yhOExM0e1qzjtXU75oBrKGcmt/sV7O3NTu4pSfg15b4A0naAgCqk4Idn5isBH1y5wj8m9zKqQ2nhLQvJVEJftlgroRuvlbsfmXtSARv9/QrVLCu9u1v536MEq2XXhq2XPzSPzUFvBow+LGI7lPQq8SvWr4N4pLk3HPPtenTp9sTTzxhw3KcuNLMiqOOOsrNkp02bZp10OikgE6dOrmWTQPClhpEaxDakj+vLaDP4qPP2nh/KUGh5guUlqMJJ/aDNWts40cfWUclbP3t/oS8/i9leioopbgzZtmvJkVdpSZ4m9Jqa93rqNlyrKHl3pcKxVXCoBCdRFeZLbUSnlnGNcVvOiHv3wKqwqThhJ623xjNX1dTTdy5c8OmUl56foofd945LJWlMl9KGquptIOSpX7Vl/5v7aOgFh36KEZVWYVwb8Xw+elSCdeolStTbuLBjBm53yGakfvoo2aPPpoqe2KE+lKlzFpCqccISVsAQDIoMaLTqbkKKsWlSEcRSIHBQXrNGqv/4APrpmWFxZLFur+cakWVrgcsWtZXKKlbavI32pgRvF3Sr0y12dRy3aeZHGr77WeJpopj5513nkvEzpo1y0aqsFsWzZI98sgjXRL2gQceKHmWBQCgvBP7QTptK7eUYErlSpYoyeozWM3ZKk1TB9WU+aow9dIgX1O4uRLD0dnF7B/RYhS/banw4WK4UhKaY8eW9zM11FFS128Upzq5NTWBK/M1f35/mz27xp5+eusMWbVUyuzll7fds0FvYc1W1p4LWtSkmcXl8mW9qw1JWwAA4lIE4WeM5NstIZ22+ro665pvcJD1WBfIl7AkcJvb8j2mXJpJXKENRDL6zUdhPpHrv+7a1VJdu1qPdu0spShOAzHdl2dDkcamxzD7A1VSEuGuu+6y+++/382i/VBTTdyGID2tc+fOLmF7xBFH2Lp16+yOO+5w1/2mYlpK2Y7BKgC07sl9TQtUay7Z0xubq2VPVSxTSpMDfIzZnLSqpKkJX3/pW6HrmqLKJIIWpy7PPp+tIZDKfJ1wgtlJJ+V/27z9ttk//hHu06Dk8SGHhJv1+vu1KdqsWSrBEL6VfdMhqzITaloxpl+/XzWmZLWStEr46vt06UuHVROStgAAtDZf41ZNRZfKpQhIsy6UvPVJXf91KS3f48vd2dVvUqeWozawwucuTfl/fXK3wI7SJd3nk8gkgdEEkydPdpef+9znMm6//fbb7cwzz7SXXnrJntVOcablhDtnPObdd9+1EZouAgBou+JObyznxLviwDKTv0F9vW1avdo6bN5sqez7VVKi0nvaaxWbWjPWGs74PcRJ9JbymE6drJ3vd8WT/vYiZZBQ/Ne1885hy3e/SkkUKyexvSJpCwBAW6Oko5/RWonacdHZIXGSvP4+BfZq/jb/tS4rsZu0//+3zGysyGzgSiaBmc2RmPIIhSiZW+wxAABUpMRVBfaFUEmJFflKSujzTDN64ySCFavFTR4riVtpeu7NUK5CPdQ/3+8jTnI4brI4+zqTD9oUkrYAACDe7JB8JSGaOhtkS9JVdYBXvPee9enUyWoUSEcTv8VKQkRbOZuJRGcDay1VJfotV1K3UKK30O0KykkCAwCA1qRYROUM1CqxX0Q+iulKmTXsH+Nr/Oa6XuwxFS4rkRHrtkR5CU/lH8pN/Jb6GJWKIy5tViRtAQBA69HsA19DbtAg26wCVSo01dRZAvk2iSuU6M13n7+93CRwJQN1X0pjSzI31b279e7Y0VLaIULb9MZNArM5HAAAqFaq9+5LiDU3nyBuYuI3WLfOPlm50jqn05bSSrJi31NOfFmIks9qldyXohCfzI3WF85VczjXbbW1Vquktna71eq0QvWKa5I5g5ikLQAASNYmcU0pCxE30VvovnJqA+t7tXnVlg2slG7tVInBUDmzgKP3MeMCAAAkMEGschJr6uqstpRNiGXTptJmAJf6mGLf01wlmvz//9FHsb9VvbRlP7HiamublhiOc5u+rrKNYUnaAgAAlFIWQjOAy6WAWYFthZLAwdq1lionCNcsj9Wrw1YJF15odtNNlfm/AAAA2iptUKamlVLNLVqDuJzEb6Hr0VIVzVFqYv36yuyFUYh2O1u40KoJSVsAAICWTAL7s/kV2CQuaGiwukWLrH9trdWoNnC5pSB0WU4SuCWWLwIAAKD6ahB7KnmQK6GbVYM4/fHH9nFdnXVr185qlJDNVad4XYHbKr1RneLzKkPSFgAAYHuVSlmgALOcOsDZ5RcUBDd1FvDo0ZV4VQAAANie96zwJbQKSadtnZK2TY1jGxrC2beFErulJH/99ZEjrdqQtAUAAEDmRmdqgwe39rMBAAAAclP9WW1gptZGJXP7NQAAAAAAAACoUiRtAQAAAAAAAKCKkLQFAAAAAAAAgCpC0hYAAAAAAAAAqghJWwAAAAAAAACoIiRtAQAAAAAAAKCKkLQFAAAAAAAAgCpC0hYAAAAAAAAAqghJWwAAAAAAAACoIiRtAQAAAAAAAKCKkLQFAAAAAAAAgCpC0hYAAAAAAAAAqghJWwAAAAAAAACoIiRtAQAAAAAAAKCKkLQFAAAAAAAAgCrS3hImCAJ3uWbNmhb7mel02tauXWu1tbVWU0OevBT0WTz0V3z0WXz0WTz0V3z0WXxJ7jMfy/nYLilaOpZN8jHWVPRZfPRZPPRXfPRZfPRZPPRXfEnuszUlxrGJS9rqgJDhw4e39lMBAABABWK7nj17WlIQywIAACQjjk0FCZueoEz+0qVLrXv37pZKpVosg67AevHixdajR48W+ZnbO/osHvorPvosPvosHvorPvosviT3mUJYBbpDhgxJ1OyMlo5lk3yMNRV9Fh99Fg/9FR99Fh99Fg/9FV+S+ywoMY5N3ExbdcawYcNa5WfrIEzagVgu+iwe+is++iw++iwe+is++iy+pPZZkmbYtnYsm9RjrBz0WXz0WTz0V3z0WXz0WTz0V3xJ7bOeJcSxyZmWAAAAAAAAAADbAZK2AAAAAAAAAFBFSNq2gE6dOtlVV13lLlEa+iwe+is++iw++iwe+is++iw++gzNjWMsPvosPvosHvorPvosPvosHvorPvqsuMRtRAYAAAAAAAAA1YyZtgAAAAAAAABQRUjaAgAAAAAAAEAVIWkLAAAAAAAAAFWEpG0z+8UvfmEjRoyw2tpa+8xnPmPPPfdcaz+lqnH99dfbuHHjrHv37jZgwAA78cQT7c0338x4zPr1623SpEnWt29f69atm5188sn273//u9WeczW54YYbLJVK2QUXXNB4G/21rSVLltjpp5/u+qRz5872qU99yl544YXG+1XW+8orr7TBgwe7+w8//HBbuHChJVVDQ4NdccUVNnLkSNcfO+20k1177bWun7yk99kTTzxhxx13nA0ZMsS9B++7776M+0vpnxUrVtiECROsR48e1qtXL/va175mH3/8sSWtvzZt2mSXXHKJe1927drVPebLX/6yLV26NLH9VcoxFnX22We7x/z0pz9NdJ+h+RDL5kYcWx7i2NIQx8ZDHFsccWx8xLLxEMdWFknbZvSnP/3JLrroIrcb3ksvvWR77723HXnkkVZXV9faT60qzJ492wVmc+bMsUceecT9wTviiCOsvr6+8TEXXnihPfjggzZ16lT3eP3x++IXv2hJ9/zzz9ttt91mY8aMybid/sq0cuVKO+igg6xDhw42Y8YMe+ONN+wnP/mJ9e7du/ExP/zhD+2WW26xX/3qV/bss8+6D1u9TzVwSKIbb7zRJk+ebD//+c9t/vz57rr66NZbb218TNL7TH+j9PdciYxcSukfBSGvv/66+9s3ffp0F9ycddZZlrT+Wrdunft81ABLl/fee69Lehx//PEZj0tSf5VyjHnTpk1zn6EKirMlrc/QPIhl8yOObTri2NIQx8ZHHFsccWx8xLLxEMdWWIBms99++wWTJk1qvN7Q0BAMGTIkuP7661v1eVWruro6nQINZs+e7a6vWrUq6NChQzB16tTGx8yfP9895plnngmSau3atcHo0aODRx55JDjkkEOC888/391Of23rkksuCQ4++OC896fT6WDQoEHBj370o8bb1I+dOnUK7r777iCJjj322OCrX/1qxm1f/OIXgwkTJriv6bNMen9Nmzat8Xop/fPGG2+473v++ecbHzNjxowglUoFS5YsCZLUX7k899xz7nGLFi0Kkt5fhfrs/fffD4YOHRq89tprwY477hjcfPPNjfclvc9QOcSypSOOLQ1xbOmIY+Mjjo2HODY+Ytl4iGPLx0zbZrJx40Z78cUX3XICr6amxl1/5plnWvW5VavVq1e7yz59+rhL9Z9mLUT7cLfddrMddtgh0X2oWR3HHntsRr8I/bWtBx54wPbdd18bP368W7o4duxY+81vftN4/7vvvmsffvhhRp/17NnTLf9Map8deOCB9thjj9lbb73lrr/yyiv21FNP2dFHH+2u02eFldI/utQyHx2bnh6vzwjNaEg6fRZomZT6SOivbaXTaTvjjDPsO9/5ju25557b3E+foRKIZeMhji0NcWzpiGPjI44tD3FsZRDLFkYcG0/7mI9HiZYvX+5q6gwcODDjdl1fsGBBqz2van7jqqaVlgDttdde7jZ9YHTs2LHxj120D3VfEk2ZMsUtu9Cysmz017beeecdt0RKSzsvv/xy12/f/OY3XT9NnDixsV9yvU+T2meXXnqprVmzxg2U2rVr5/6OXXfddW6JitBnhZXSP7rU4Cuqffv2bqCf9D7U0jvVBTvttNNcDSuhv7al5Z7qA/09y4U+QyUQy5aOOLY0xLHxEMfGRxxbHuLY8hHLFkccGw9JW1TNWffXXnvNnQlFbosXL7bzzz/f1XXRZiAobRClM3Q/+MEP3HXNUNBxphpNCnaxrT//+c9255132l133eXOfM6dO9cNRFVriD5Dc9IMq1NOOcVtgKFBKnLTbLSf/exnLvGhWRwAWh9xbHHEsfERx8ZHHIvWRCxbHHFsfJRHaCb9+vVzZ/eydzzV9UGDBrXa86pG5557risuPXPmTBs2bFjj7eonLc1btWpVxuOT2of6A6eNP/bZZx93pklNmzSoULy+1hlQ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",
      "text/plain": [
       "<Figure size 1400x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot training curves\n",
    "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))\n",
    "\n",
    "epochs = range(len(history['train_loss']))\n",
    "\n",
    "# Loss\n",
    "ax1.plot(epochs, history['train_loss'], 'b-', label='Train Loss', linewidth=2)\n",
    "ax1.plot(epochs, history['val_loss'], 'r-', label='Val Loss', linewidth=2)\n",
    "ax1.set_xlabel('Epoch')\n",
    "ax1.set_ylabel('Loss')\n",
    "ax1.set_title('Training and Validation Loss')\n",
    "ax1.legend()\n",
    "ax1.grid(True, alpha=0.3)\n",
    "\n",
    "# Perplexity\n",
    "train_ppl = [perplexity(loss) for loss in history['train_loss']]\n",
    "val_ppl = [perplexity(loss) for loss in history['val_loss']]\n",
    "\n",
    "ax2.plot(epochs, train_ppl, 'b-', label='Train Perplexity', linewidth=2)\n",
    "ax2.plot(epochs, val_ppl, 'r-', label='Val Perplexity', linewidth=2)\n",
    "ax2.set_xlabel('Epoch')\n",
    "ax2.set_ylabel('Perplexity')\n",
    "ax2.set_title('Training and Validation Perplexity')\n",
    "ax2.legend()\n",
    "ax2.grid(True, alpha=0.3)\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. Text Generation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 191,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Generated Text Samples:\n",
      "======================================================================\n",
      "\n",
      "Temperature = 0.5:\n",
      "The mso  aseool eelr aor eefcne e  metelnoaeor  eirm  ioea imroep  oehrss ll eenis ln nicue ie coai\n",
      " o r\n",
      "----------------------------------------------------------------------\n",
      "\n",
      "Temperature = 1.0:\n",
      "The cao e aLrmsylu  i tktandlscijnr l.Ni  aiaestlxo posime nu..esmisNuurdee.  nv n mg erTibttoolrwur sml\n",
      "----------------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "def generate_text(model, start_text, length=100, temperature=1.0):\n",
    "    \"\"\"Generate text using the trained model.\n",
    "    \n",
    "    Args:\n",
    "        model: Trained language model\n",
    "        start_text: Starting string\n",
    "        length: Number of characters to generate\n",
    "        temperature: Sampling temperature (higher = more random)\n",
    "        \n",
    "    Returns:\n",
    "        Generated text string\n",
    "    \"\"\"\n",
    "    # Encode start text\n",
    "    current_seq = tokenizer.encode(start_text)\n",
    "    generated = list(current_seq)\n",
    "    \n",
    "    with brainstate.environ.context(fit=False):\n",
    "        state = None\n",
    "        \n",
    "        for _ in range(length):\n",
    "            # Prepare input (last seq_length characters)\n",
    "            input_seq = current_seq[-seq_length:]\n",
    "            input_seq = jnp.array(input_seq).reshape(1, -1)\n",
    "            \n",
    "            # Pad if necessary\n",
    "            if input_seq.shape[1] < seq_length:\n",
    "                pad_length = seq_length - input_seq.shape[1]\n",
    "                padding = jnp.zeros((1, pad_length), dtype=jnp.int32)\n",
    "                input_seq = jnp.concatenate([padding, input_seq], axis=1)\n",
    "            \n",
    "            # Get predictions\n",
    "            logits, state = model(input_seq, state)\n",
    "            \n",
    "            # Get last time step\n",
    "            last_logits = logits[0, -1, :] / temperature\n",
    "            \n",
    "            # Sample from distribution\n",
    "            probs = jax.nn.softmax(last_logits)\n",
    "            next_idx = np.random.choice(len(probs), p=np.array(probs))\n",
    "            \n",
    "            # Append to sequence\n",
    "            generated.append(next_idx)\n",
    "            current_seq = np.append(current_seq, next_idx)\n",
    "    \n",
    "    return tokenizer.decode(np.array(generated))\n",
    "\n",
    "# Generate samples with different temperatures\n",
    "start_text = \"The \"\n",
    "temperatures = [0.5, 1.0]\n",
    "\n",
    "print(\"\\nGenerated Text Samples:\")\n",
    "print(\"=\" * 70)\n",
    "\n",
    "for temp in temperatures:\n",
    "    generated = generate_text(model, start_text, length=100, temperature=temp)\n",
    "    print(f\"\\nTemperature = {temp}:\")\n",
    "    print(generated)\n",
    "    print(\"-\" * 70)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7. Attention Mechanism"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 192,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Logits shape: (4, 20, 38)\n",
      "Attention weights shape: (4, 20, 20)\n",
      "\n",
      "Total parameters: 111,014\n"
     ]
    }
   ],
   "source": [
    "class ScaledDotProductAttention(brainstate.nn.Module):\n",
    "    \"\"\"Scaled dot-product attention mechanism.\"\"\"\n",
    "    \n",
    "    def __init__(self, dim):\n",
    "        super().__init__()\n",
    "        self.scale = jnp.sqrt(dim)\n",
    "    \n",
    "    def __call__(self, query, key, value, mask=None):\n",
    "        \"\"\"Compute attention.\n",
    "        \n",
    "        Args:\n",
    "            query: Query tensor of shape (batch, seq_len_q, dim)\n",
    "            key: Key tensor of shape (batch, seq_len_k, dim)\n",
    "            value: Value tensor of shape (batch, seq_len_v, dim)\n",
    "            mask: Optional mask\n",
    "            \n",
    "        Returns:\n",
    "            output: Attended values\n",
    "            attention_weights: Attention weights\n",
    "        \"\"\"\n",
    "        # Compute attention scores\n",
    "        scores = jnp.matmul(query, key.transpose(0, 2, 1)) / self.scale\n",
    "        \n",
    "        # Apply mask if provided\n",
    "        if mask is not None:\n",
    "            scores = jnp.where(mask, scores, -1e9)\n",
    "        \n",
    "        # Compute attention weights\n",
    "        attention_weights = jax.nn.softmax(scores, axis=-1)\n",
    "        \n",
    "        # Apply attention to values\n",
    "        output = jnp.matmul(attention_weights, value)\n",
    "        \n",
    "        return output, attention_weights\n",
    "\n",
    "class AttentionLSTM(brainstate.nn.Module):\n",
    "    \"\"\"LSTM with self-attention.\"\"\"\n",
    "    \n",
    "    def __init__(self, vocab_size, embedding_dim=64, hidden_dim=128):\n",
    "        super().__init__()\n",
    "        self.vocab_size = vocab_size\n",
    "        self.hidden_dim = hidden_dim\n",
    "        \n",
    "        # Embedding\n",
    "        self.embedding = brainstate.ParamState(\n",
    "            brainstate.random.randn(vocab_size, embedding_dim) * 0.1\n",
    "        )\n",
    "        \n",
    "        # LSTM\n",
    "        self.lstm_cell = brainstate.nn.LSTMCell(num_in=embedding_dim, num_out=hidden_dim)\n",
    "        \n",
    "        # Attention\n",
    "        self.attention = ScaledDotProductAttention(hidden_dim)\n",
    "        \n",
    "        # Output\n",
    "        self.fc_out = brainstate.nn.Linear(hidden_dim * 2, vocab_size)\n",
    "    \n",
    "    def __call__(self, x):\n",
    "        \"\"\"Forward pass with attention.\"\"\"\n",
    "        batch_size, seq_len = x.shape\n",
    "        \n",
    "        # Embed\n",
    "        embedded = self.embedding.value[x]\n",
    "        \n",
    "        # LSTM processing\n",
    "        self.lstm_cell.init_state(batch_size=batch_size)\n",
    "        \n",
    "        lstm_outputs = []\n",
    "        for t in range(seq_len):\n",
    "            hidden = self.lstm_cell.update(embedded[:, t, :])\n",
    "            lstm_outputs.append(hidden)\n",
    "        \n",
    "        lstm_outputs = jnp.stack(lstm_outputs, axis=1)\n",
    "        \n",
    "        # Self-attention\n",
    "        attended, attn_weights = self.attention(\n",
    "            lstm_outputs, lstm_outputs, lstm_outputs\n",
    "        )\n",
    "        \n",
    "        # Concatenate LSTM output and attended output\n",
    "        combined = jnp.concatenate([lstm_outputs, attended], axis=-1)\n",
    "        \n",
    "        # Output projection\n",
    "        logits = jax.vmap(self.fc_out)(combined)\n",
    "        \n",
    "        return logits, attn_weights\n",
    "\n",
    "# Create attention model\n",
    "attn_model = AttentionLSTM(\n",
    "    vocab_size=tokenizer.vocab_size,\n",
    "    embedding_dim=64,\n",
    "    hidden_dim=128\n",
    ")\n",
    "\n",
    "# Test\n",
    "test_logits, test_attn = attn_model(test_input)\n",
    "print(f\"Logits shape: {test_logits.shape}\")\n",
    "print(f\"Attention weights shape: {test_attn.shape}\")\n",
    "\n",
    "n_params = 0\n",
    "for p in attn_model.states(brainstate.ParamState).values():\n",
    "    if isinstance(p.value, dict):\n",
    "        for v in p.value.values():\n",
    "            n_params += v.size\n",
    "    else:\n",
    "        n_params += p.value.size\n",
    "print(f\"\\nTotal parameters: {n_params:,}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize Attention"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 193,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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vvnG7PPBBx/IuHHjTF+2bNlihl43atTIdai2evPNN00fA7fPNmHCBDMc/YUXXpD169dL+/bt5eabbzbHD/Wvf/3LDO1et26dXHzxxdKjR4/gFwgAACCPcgAAcNG7d28nJibG0V8XCxYsSHV/mzZtnH//+99h29566y2nQoUKwdv169d3Ro0aFbx90003OX369HE95zfffGPO98cff5jbe/bscVq1auVUqlTJSUxMND/369cv7DG33Xabc+ONN5qfx4wZ41x88cVOUlJSmsevWrWqM27cuOBtPdecOXPC9hk6dKjTpEmT4O2KFSs6zz77bNg+l112mfP3v//d/Lxt2zZznNdffz14/8aNG822TZs2uT5XAABgPzLNAIB0NW7c2AxbHjp0qCQkJITd98MPP5hhyzoHOND69etnsraaTQ5kmzWTq/bv3y+ff/65GbZ9LjoUulChQmZ49YkTJ0wGWYdjb9q0Sa688sqwffW2ble33XabnDp1ygwV175oZvp8sr3x8fFmbnV65wy9VgE6tFwdOHAgy+cGAADeI2gGAKSrUqVKpqL177//Lh06dJDjx48H79MgWucw63DkQPvxxx/NsGWd46x0+LZWvtb5vW+//bZUr15drr766nOeV4d+61BoDVr1uC1atMhQf6tUqWKKiP3nP/8xw7r//ve/m3nROpc6p0VHRwd/1jnOgfnQAAAg7yJoBgCcU9WqVWXRokWyb9++sMBZC4BpgFqrVq1ULSLiz18xWoVal63SbLPOdw4tIpYeDa612FeRIkXCtterV0++++67sG16u379+sHbGixrte2JEyeagF8Ddg3m3QLd9KpyFy1a1GS7z3VOAACQP0V53QEAQN6gGVwNQLU6tBbC0gJfWtVaq2Nrpeq//vWvJlDWIdtaoOuZZ54JPlaHaOt+Gpz27t37vPoxaNAguf3226VZs2bStm1b+e9//2uqVn/11Vfmfg3M9TyamdYq1prd1iBaA/+06NBzXZNZh1trZewSJUqkeU4dnq5BvFbO1i8ANPv9zjvvnNdzAQAA9iPTDADIMJ1nrIHzoUOHTODcsmVLUw37yy+/lMsuu0yuuOIKU7n67ABVg1ud46uP0azt+dCstVaz1krWDRo0MFWyNYi99tprzf3FixeX1157zQTBOsdYg2kNrN3WXdaq2PPnzzdfCmggnhZdsmrgwIGmYrdW4tYvDD7++GOpXbv2eT0XAABgP59WA/O6EwCA/E3nPuvcaA1ub731Vq+7AwAAkGEMzwYA5BgtgqVZac3magZY1zYGAADISxieDQDIMTr3uFy5cvLuu+/KlClTJCoqd76r1XnNGqRnhQ7z1sdv3749WAEbAABcuMg0AwByjK7b3LlzZ5k7d67XXQEAAMgSMs0AgFyjWVwtqvXoo49KyZIlpXz58jJs2LCwfTS7+/LLL0vHjh1N1esaNWrI+++/H7xfC5HpPkePHg1u00rWuk2zw3q/Lmt17Ngxs03b2ecAAADIKIJmAECumjZtmhQqVEhWrFgho0ePlqefftpUrw711FNPSdeuXc3yVT179pTu3bvLpk2bMnT8Vq1ayfjx4836ynv37jXtkUceMfdp8KxLTAEAAGQUw7MBALlKl4HSNY+VLtk0adIks07yDTfcENzntttuM2s7qxEjRpig+sUXX5T//Oc/5zx+TEyMFCtWzGSYNZMdqnTp0mat5fRopjqABSYAAACZZgBArgfNoXT95gMHDoRt0/Wfz76d0Uxzeh544AEToAMAAGQUQTMAIFdFR0eH3daMsC5NlVERERGpssDJycnZ2EMAAID/IWgGAFhn+fLlqW7Xq1fP/FymTBnzX52rHFoI7Owh2ikpKbnSVwAAkL8RNAMArDN79myzrvMvv/xi5j+vXLnSDK1WtWrVkipVqpiiXlu2bJFPP/1UxowZE/Z4LfaVkJBghmIfOnRITp48abbr/Ok2bdp48pwAAEDeRNAMALDO8OHDZebMmWb+8/Tp02XGjBlSv3794PBuvf3zzz+b+0eNGiXPPPNMqgra9957r3Tr1s1kprVKt9IA+tdff/XkOQEAgLzJ51AaFABgEZ3jPGfOHOnSpYvXXQEAACDTDAAAAACAG4JmAAAAAABcRLndAQCAF5g1BAAAbEKmGQAAAAAAFwTNAJCHLVy40BTOOnr0qNhI+zZ37twM7atLSDVt2jTHjm8jfc7lypXL888DAID8jKAZACylgVR6TQMu2+3du1c6duzodTestGnTJrO01iuvvJJt12n79u3mvaH0/dGnT59s6CkAABc25jQDgKU0kAqYNWuWDBkyRDZv3hzcVrhwYVm1apXYrHz58mKb5ORks9az1wLrRXfu3DkY6AIAAPuQaQYAiwPOQCtWrJgJrEK3adAcsHr1arn00kulYMGC0qpVq7DgWn300UdyySWXSFxcnNSoUcNkOM+cOeN67pSUFBk4cKAUL15cSpUqJY8++qj07t07bO3katWqyfjx48Mep8OrQzPgZw873r17t/To0UNKliwphQoVMn1esWKFa1CpfX3ggQfSLQ4WyNIWKFDA7P/++++nyrzqlw6tW7c2z/+dd94Rv98vTz/9tFSuXFliY2NNv+fNmxd83F//+ldz3oCHHnrIHOfnn382t5OSkkz/v/rqK3P72muvlQEDBpjrpM9NX5/0RgLofTfddJP5OSIiIhg0p9cvvQZt27aV9u3bB6/HkSNHzL76hQoAAMgZBM0AkA/861//kjFjxpjMc1RUlNx9993B+7799lvp1auXPPjgg/LTTz+Z4cBTp06VZ5991vV4eizdZ8qUKbJkyRITnM2ZM+e8+piQkGAC199//10+/vhj+eGHH0yQqYHi2davXy9XXXWV3HHHHTJp0qR0M7FPPfWUdO3a1RyvZ8+e0r17dzP0OdTjjz9unr9u16BzwoQJ5jm+8MIL5ly67eabb5YtW7aY/bWfOl88YNGiRVK6dOngtu+//95krPULioBp06aZQFq/BBg9erQJfufPn59mnx955BF58803g0F/YFRBev3Sa6Dn0HNPnDjR7H/vvfdKpUqVCJoBAMhJDgDAem+++aZTrFixVNu/+eYbTTk6X331VXDbp59+aradOnXK3G7Tpo3z73//O+xxb731llOhQgXX8+l9o0ePDt5OTk52Kleu7HTu3Dm4rWrVqs64cePCHtekSRNn6NChwdvajzlz5pifX3nlFadIkSLO4cOH0zynPk4f/9133zklSpRwXnjhhXSvSeD49957b9i2Fi1aOPfdd5/5edu2bWaf8ePHh+1TsWJF59lnnw3bdtlllzl///vfzc/r1693fD6fc+DAAefIkSNOTEyMM2LECKdbt27m/meeecZp1apV8LGtW7d2rrrqqlTHe+yxx1z7rtfl7F/D5+qXeu+995y4uDjn8ccfdwoVKuT88ssv57hKAADgfDCnGQDygcaNGwd/rlChgvnvgQMH5KKLLjIZ2O+++y4ss6zDr0+fPi0nT540Q7pDHTt2zGQ+W7RoEdym2WsdSn0+ayivW7dOmjVrZoYvu9m5c6fccMMNpq86JDojWrZsmeq2niuU9j0gPj5e9uzZI1deeWXYPnpbr5Vq2LCh6admmGNiYky///KXv8hLL71k7tftOiTb7TUIvA76GmRURvqlbrvtNpP1f+655+Tll1+W2rVrZ/gcAAAg8wiaASAfCC1sFTo/NjAsWucw33rrrakep3N8s0rn4p4dROuQZTc65/hcypQpIxUrVpQZM2aYIeZFixaV7KDDpjNDr+E111xjhmPr3GINkDUoTkxMlA0bNsjSpUvNEOtQZxcX02OkNfT8fOkXHTqHPTIyMjicHAAA5BzmNANAPqcFwLQwWK1atVI1DXzPpkXHNEsaWqBLi4ZpoHZ2gBta4Vszpdu2bXPthwadmgHW+dHpBdaffPKJCeZ1Pu/x48fP+fyWL1+e6na9evVc99dAXANzzb6H0tv169cP3g7Ma9amQbNeKw2kn3/+eRM8n50RPl8Z7dfDDz9s+vL555+buc1ff/11tvYDAACEI9MMAPmcFonSocU6VFurQmvApcN9NWP6zDPPpPkYLZqlw3916G/dunVl7NixcvTo0bB9rr/+elMsTKtAa5VtPY9mP91o1ex///vfpgL3yJEjTWC+du1aEyiGDrHWrPCnn35qKmJr0+rRoZXCzzZ79mwz/FoLh2ll7JUrV8obb7yR7jUZNGiQDB06VGrWrGkqVGtRLg3o9fEBGij/85//NMOz9diBbZphvuyyyzKdvc6Ic/VLr4sWZ1u2bJn5MkT316rmWjSsRIkS2d4fAABAphkA8j3N2Gr29ssvvzTB3hVXXCHjxo2TqlWruj5Gs5l33nmnCcg0oC1SpIjccsstYfsMHjzYZGM1IO/UqZMJhjXYc6PBp/ahbNmycuONN0qjRo1MYJ5WoK1BsmZSdfi3HvvEiROux9Wh5zNnzjSZ7OnTp5uh3aGZ2bTo8lC6pJY+T+2HBuZa0Tt0frBu1y8DNHgNBO0aNOt88LPnM2eX9Pp18OBB6du3r1muSgPmwHMvV66cqaINAAByhk+rgeXQsQEA+UifPn1Mtjl03WUAAID8jkwzAAAAAAAuCJoBAAAAAHDB8GwAAAAAAFyQaQYAAAAAwAVBMwAAAAAALgiaAQAAAABwQdAMAAAAAIALgmYAAAAAAFwQNAMAAAAA4IKgGQAAAAAAFwTNAAAAAABI2v4/vV15TeorQCAAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1000x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Get attention weights for a sample\n",
    "sample_input = jnp.array(X_train[0:1])  # Single sequence\n",
    "\n",
    "with brainstate.environ.context(fit=False):\n",
    "    _, attn_weights = attn_model(sample_input)\n",
    "\n",
    "# Plot attention heatmap\n",
    "plt.figure(figsize=(10, 8))\n",
    "plt.imshow(attn_weights[0], cmap='viridis', aspect='auto')\n",
    "plt.colorbar(label='Attention Weight')\n",
    "plt.xlabel('Key Position')\n",
    "plt.ylabel('Query Position')\n",
    "plt.title('Self-Attention Weights')\n",
    "\n",
    "# Add text labels\n",
    "input_text = tokenizer.decode(X_train[0])\n",
    "plt.text(0.5, -0.1, f'Input: \"{input_text}\"', \n",
    "         transform=plt.gca().transAxes, ha='center')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8. Simple Transformer Block"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 194,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input shape: (4, 20)\n",
      "Output shape: (4, 20, 38)\n",
      "\n",
      "Total parameters: 274,214\n"
     ]
    }
   ],
   "source": [
    "class TransformerBlock(brainstate.nn.Module):\n",
    "    \"\"\"Simple Transformer block with self-attention and feed-forward.\"\"\"\n",
    "    \n",
    "    def __init__(self, dim, num_heads=4, ff_dim=256):\n",
    "        super().__init__()\n",
    "        self.dim = dim\n",
    "        self.num_heads = num_heads\n",
    "        \n",
    "        # Multi-head attention (simplified)\n",
    "        self.attention = ScaledDotProductAttention(dim)\n",
    "        \n",
    "        # Layer normalization\n",
    "        self.ln1 = brainstate.nn.LayerNorm([dim])\n",
    "        self.ln2 = brainstate.nn.LayerNorm([dim])\n",
    "        \n",
    "        # Feed-forward network\n",
    "        self.ff1 = brainstate.nn.Linear(dim, ff_dim)\n",
    "        self.ff2 = brainstate.nn.Linear(ff_dim, dim)\n",
    "    \n",
    "    def __call__(self, x, mask=None):\n",
    "        \"\"\"Forward pass.\n",
    "        \n",
    "        Args:\n",
    "            x: Input of shape (batch, seq_len, dim)\n",
    "            mask: Optional attention mask\n",
    "            \n",
    "        Returns:\n",
    "            Output of same shape as input\n",
    "        \"\"\"\n",
    "        # Self-attention with residual\n",
    "        attn_out, _ = self.attention(x, x, x, mask)\n",
    "        x = self.ln1(x + attn_out)\n",
    "        \n",
    "        # Feed-forward with residual\n",
    "        ff_out = self.ff2(jax.nn.relu(self.ff1(x)))\n",
    "        x = self.ln2(x + ff_out)\n",
    "        \n",
    "        return x\n",
    "\n",
    "class SimpleTransformer(brainstate.nn.Module):\n",
    "    \"\"\"Simple Transformer for sequence modeling.\"\"\"\n",
    "    \n",
    "    def __init__(self, vocab_size, dim=128, num_layers=2, num_heads=4):\n",
    "        super().__init__()\n",
    "        self.vocab_size = vocab_size\n",
    "        self.dim = dim\n",
    "        \n",
    "        # Embedding\n",
    "        self.embedding = brainstate.ParamState(\n",
    "            brainstate.random.randn(vocab_size, dim) * 0.1\n",
    "        )\n",
    "        \n",
    "        # Transformer blocks\n",
    "        self.blocks = []\n",
    "        for i in range(num_layers):\n",
    "            block = TransformerBlock(dim, num_heads, ff_dim=dim*4)\n",
    "            self.blocks.append(block)\n",
    "            setattr(self, f'block_{i}', block)\n",
    "        \n",
    "        # Output\n",
    "        self.fc_out = brainstate.nn.Linear(dim, vocab_size)\n",
    "    \n",
    "    def __call__(self, x):\n",
    "        \"\"\"Forward pass.\"\"\"\n",
    "        # Embed\n",
    "        x = self.embedding.value[x]\n",
    "        \n",
    "        # Transformer blocks\n",
    "        for block in self.blocks:\n",
    "            x = block(x)\n",
    "        \n",
    "        # Output projection\n",
    "        logits = jax.vmap(self.fc_out)(x)\n",
    "        \n",
    "        return logits\n",
    "\n",
    "# Create Transformer\n",
    "transformer = SimpleTransformer(\n",
    "    vocab_size=tokenizer.vocab_size,\n",
    "    dim=128,\n",
    "    num_layers=2,\n",
    "    num_heads=4\n",
    ")\n",
    "\n",
    "# Test\n",
    "test_logits = transformer(test_input)\n",
    "print(f\"Input shape: {test_input.shape}\")\n",
    "print(f\"Output shape: {test_logits.shape}\")\n",
    "\n",
    "n_params = 0\n",
    "for p in transformer.states(brainstate.ParamState).values():\n",
    "    if isinstance(p.value, dict):\n",
    "        for v in p.value.values():\n",
    "            n_params += v.size\n",
    "    else:\n",
    "        n_params += p.value.size\n",
    "    \n",
    "print(f\"\\nTotal parameters: {n_params:,}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Next Steps\n",
    "\n",
    "In the next tutorial, we'll explore:\n",
    "- **Brain-Inspired Computing**: Spiking neural networks\n",
    "- Neurodynamics and biological models\n",
    "- Plasticity and learning rules\n",
    "- Event-driven computation"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
