From 249f7224bf2c0512ff5bad9c60574a757fbe6e3a Mon Sep 17 00:00:00 2001 From: Simone Angarano Date: Mon, 24 Feb 2025 18:23:43 +0100 Subject: [PATCH 01/17] v2 --- .gitignore | 3 + README_MLA.md | 38 ++++ config_hub/pretrain/cfg.yaml | 137 ++++++++++++ litgpt/__main__.py | 2 + litgpt/config.py | 8 +- litgpt/generate/base.py | 16 +- litgpt/model.py | 268 ++++++++++++++++++++++- litgpt/pretrain.py | 4 +- litgpt/scripts/convert_lit_checkpoint.py | 8 + 9 files changed, 476 insertions(+), 8 deletions(-) create mode 100644 README_MLA.md create mode 100644 config_hub/pretrain/cfg.yaml diff --git a/.gitignore b/.gitignore index 8c416e1b37..b235c703e7 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ checkpoints out wandb events.out.tfevents* +evaluate_model +test.ipynb +mla_test.py # test artifacts from tests/test_readme.py **/custom_finetuning_dataset.json diff --git a/README_MLA.md b/README_MLA.md new file mode 100644 index 0000000000..bfeb7f0ee1 --- /dev/null +++ b/README_MLA.md @@ -0,0 +1,38 @@ +# Multi-Head Latent Attention (MLA) + +## Overview +This document outlines the modifications made to the codebase in the `litgpt` repository to add support for Multi-Head Latent Attention (MLA) block from DeepSeekV2 (https://arxiv.org/abs/2405.04434). + +## Changes Made +1. **Configuration**: Added `latent_attention: Optional[bool] = False` parameter to the configuration file to enable the MLA block. +2. **MLA module**: Implemented the MLA module as a separate component in the `litgpt` codebase. +3. **KVCacheCompressed**: Added support for the `KVCacheCompressed` class to store the key-value pairs for the MLA block. +4. **Model**: Modified the GPT model to include the **MLA block** as an alternative component based on the configuration parameter `latent_attention`. +5. **Training**: Updated the training script to support the MLA block and added support for training with the new configuration file `config_hub/pretrain/cfg.yaml`. + +## Installation +Follow the updated installation instructions in the `README.md` file. + +## Usage +1. **Configuration**: Set the `latent_attention` parameter to `True` in the configuration file to enable the MLA block. +2. **Training**: Run the training script with the updated configuration file. + ```bash + litgpt pretrain --config config_hub/pretrain/cfg.yaml + ``` +3. **Inference**: Use the trained model for inference as follows: + ```bash + litgpt generate out/pretrain/mla/final/ + ``` + +## Notes +- Pythia was used as model for the experiments because it comes with many versions at different scales. +- `pythia-160m` (160M parameters) was the largest model that could be trained on a single GPU with 16GB memory. +- For the same reason, the `tinystories` dataset (100M tokens) was used for the experiments. +- Experiments on larger models are expected to further highlight the benefits of the MLA block. +- All the tested implementations use FlashAttention (as implemented in torch) by default. +- The resulting implementation of MLA depends on the `litgpt` codebase (especially the `CausalSelfAttention` class). +- The implementation of the MLA block is based on the DeepSeekV2 paper and includes support for KV caching (`KVCacheCompressed`) and decoupled RoPE (`apply_rope_mla`). +- A further improvement would be to optimize the implementation for speed and memory usage (for example, by merging matrices at inference like in LoRA). + > Fortunately, due to the associative law of matrix multiplication, we can absorb $π‘Š^{π‘ˆπΎ}$ into $π‘Š^{π‘ˆπ‘„}$ , and $π‘Š^{π‘ˆπ‘‰}$ into $π‘Š^{𝑂}$. Therefore, we do not need to compute keys and values out for each query. Through this optimization, we avoid the computational overhead for recomputing $k^C_t$ and $v^𝐢_𝑑$ during inference. + + Unfortunately, this was not implemented due to time constraints. \ No newline at end of file diff --git a/config_hub/pretrain/cfg.yaml b/config_hub/pretrain/cfg.yaml new file mode 100644 index 0000000000..404f5d025d --- /dev/null +++ b/config_hub/pretrain/cfg.yaml @@ -0,0 +1,137 @@ + +# The name of the model to pretrain. Choose from names in ``litgpt.config``. Mutually exclusive with +# ``model_config``. (type: Optional[str], default: null) +model_name: pythia-160m + +# A ``litgpt.Config`` object to define the model architecture. Mutually exclusive with +# ``model_config``. (type: Optional[Config], default: null) +model_config: + name: pythia-160m + hf_config: + org: EleutherAI + name: pythia-160m + block_size: 2048 + n_layer: 12 + n_embd: 768 + n_head: 12 + padding_multiple: 128 + norm_class_name: LayerNorm + norm_qk: false + + #Β Wether to use latent attention (MLA). (type: bool, default: false) + latent_attention: true + # Whether to use MQA (head_size = 1), MLA (1 < head_size < n_head), or MHA (head_size = n_head). + #Β Not compatible with latent_attention. + n_query_groups: 12 + + +# Directory in which to save checkpoints and logs. If running in a Lightning Studio Job, look for it in +# /teamspace/jobs//share. (type: , default: out/pretrain) +out_dir: out/pretrain/mla + +# The precision to use for pretraining. Possible choices: "bf16-true", "bf16-mixed", "32-true". (type: Optional[str], default: null) +precision: bf16-mixed + +# Optional path to a checkpoint directory to initialize the model from. +# Useful for continued pretraining. Mutually exclusive with ``resume``. (type: Optional[Path], default: null) +initial_checkpoint_dir: + +# Path to a checkpoint directory to resume from in case training was interrupted, or ``True`` to resume +# from the latest checkpoint in ``out_dir``. An error will be raised if no checkpoint is found. Passing +# ``'auto'`` will resume from the latest checkpoint but not error if no checkpoint exists. +# (type: Union[bool, Literal["auto"], Path], default: False) +resume: false + +# Data-related arguments. If not provided, the default is ``litgpt.data.TinyLlama``. +data: TinyStories + +# Training-related arguments. See ``litgpt.args.TrainArgs`` for details +train: + + # Number of optimizer steps between saving checkpoints (type: Optional[int], default: 1000) + save_interval: 1000 + + # Number of iterations between logging calls (type: int, default: 1) + log_interval: 100 + + # Number of samples between optimizer steps across data-parallel ranks (type: int, default: 512) + global_batch_size: 128 + + # Number of samples per data-parallel rank (type: int, default: 4) + micro_batch_size: 4 + + # Number of iterations with learning rate warmup active (type: int, default: 2000) + lr_warmup_steps: 100 + + # Number of epochs to train on (type: Optional[int], default: null) + epochs: + + # Total number of tokens to train on (type: Optional[int], default: 3000000000000) + max_tokens: 100000000 + + # Limits the number of optimizer steps to run. (type: Optional[int], default: null) + max_steps: + + # Limits the length of samples. Off by default (type: Optional[int], default: null) + max_seq_length: + + # Whether to tie the embedding weights with the language modeling head weights. (type: Optional[bool], default: False) + tie_embeddings: + + # (type: Optional[float], default: 1.0) + max_norm: 1.0 + + # (type: float, default: 4e-05) + min_lr: 6e-5 + +# Evaluation-related arguments. See ``litgpt.args.EvalArgs`` for details +eval: + + # Number of optimizer steps between evaluation calls (type: int, default: 1000) + interval: 1000 + + # Number of tokens to generate (type: Optional[int], default: null) + max_new_tokens: + + # Number of iterations (type: int, default: 100) + max_iters: 100 + + # Whether to evaluate on the validation set at the beginning of the training + initial_validation: false + + # Whether to evaluate on the validation set at the end the training + final_validation: true + +# Optimizer-related arguments +optimizer: + + class_path: torch.optim.AdamW + + init_args: + + # (type: float, default: 0.001) + lr: 6e-4 + + # (type: float, default: 0.01) + weight_decay: 0.1 + + # (type: tuple, default: (0.9,0.999)) + betas: + - 0.9 + - 0.95 + +# How many devices/GPUs to use. Uses all GPUs by default. (type: Union[int, str], default: auto) +devices: auto + +# How many nodes to use. (type: int, default: 1) +num_nodes: 1 + +# Optional path to the tokenizer dir that was used for preprocessing the dataset. Only some data +# module require this. (type: Optional[Path], default: null) +tokenizer_dir: checkpoints/EleutherAI/pythia-160m + +# The name of the logger to send metrics to. (type: Literal['wandb', 'tensorboard', 'csv'], default: tensorboard) +logger_name: tensorboard + +# The random seed to use for reproducibility. (type: int, default: 42) +seed: 42 \ No newline at end of file diff --git a/litgpt/__main__.py b/litgpt/__main__.py index 8fde3ce102..6c72ac528d 100644 --- a/litgpt/__main__.py +++ b/litgpt/__main__.py @@ -26,6 +26,8 @@ from litgpt.deploy.serve import run_server as serve_fn from jsonargparse import set_config_read_mode, set_docstring_parse_options, CLI +import torch._dynamo # fallback to eager mode if torchscript fails +torch._dynamo.config.suppress_errors = True def main() -> None: parser_data = { diff --git a/litgpt/config.py b/litgpt/config.py index 7106ea581d..b52e23e068 100644 --- a/litgpt/config.py +++ b/litgpt/config.py @@ -33,6 +33,7 @@ class Config: # Transformer block (self-attention) n_head: int = 32 head_size: Optional[int] = None + latent_attention: Optional[bool] = False # to use multi-head attention (MHA), set this to `n_head` (default) # to use multi-query attention (MQA), set this to 1 # to use grouped-query attention (GQA), set this to a value in between @@ -64,7 +65,7 @@ class Config: attention_logit_softcapping: Optional[float] = None # Rotary position embedding (RoPE) rope_base: int = 10000 - rotary_percentage: float = 0.25 + rotary_percentage: float = 0.5 rope_condense_ratio: int = 1 rope_adjustments: Optional[dict] = None # Transformer block (MLP) @@ -289,6 +290,7 @@ def norm_class(self) -> Type: n_layer=6, n_embd=128, n_head=4, + latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-31m/blob/main/config.json @@ -299,6 +301,7 @@ def norm_class(self) -> Type: n_layer=6, n_embd=256, n_head=8, + latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-70m/blob/main/config.json @@ -309,6 +312,7 @@ def norm_class(self) -> Type: n_layer=6, n_embd=512, n_head=8, + latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-160m/blob/main/config.json @@ -319,6 +323,7 @@ def norm_class(self) -> Type: n_layer=12, n_embd=768, n_head=12, + latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-410m/blob/main/config.json @@ -329,6 +334,7 @@ def norm_class(self) -> Type: n_layer=24, n_embd=1024, n_head=16, + latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-1b/blob/main/config.json diff --git a/litgpt/generate/base.py b/litgpt/generate/base.py index 572c700a0c..4d998c2f0e 100644 --- a/litgpt/generate/base.py +++ b/litgpt/generate/base.py @@ -420,10 +420,10 @@ def generate( @torch.inference_mode() def main( checkpoint_dir: Path, - prompt: str = "What food do llamas eat?", + prompt: str = "Once upon a time,", *, - num_samples: int = 1, - max_new_tokens: int = 50, + num_samples: int = 100, + max_new_tokens: int = 500, top_k: Optional[int] = 50, top_p: float = 1.0, temperature: float = 0.8, @@ -526,16 +526,24 @@ def main( fabric.print(f"Time to load the model weights: {time.perf_counter() - t0:.02f} seconds.", file=sys.stderr) L.seed_everything(1234) + ts = [] + ms = [] for i in range(num_samples): t0 = time.perf_counter() y = generate(model, encoded, max_returned_tokens, temperature=temperature, top_k=top_k, top_p=top_p, eos_id=tokenizer.eos_id) t = time.perf_counter() - t0 for block in model.transformer.h: block.attn.kv_cache.reset_parameters() - fabric.print(tokenizer.decode(y)) + tokenizer.decode(y) + # fabric.print(tokenizer.decode(y)) tokens_generated = y.size(0) - prompt_length fabric.print( f"Time for inference {i + 1}: {t:.02f} sec total, {tokens_generated / t:.02f} tokens/sec", file=sys.stderr ) + ts.append(tokens_generated / t) + ms.append(torch.cuda.memory_allocated() / 1e9) if fabric.device.type == "cuda": fabric.print(f"Memory used: {torch.cuda.max_memory_allocated() / 1e9:.02f} GB", file=sys.stderr) + fabric.print(f"Average memory used: {sum(ms) / len(ms):.02f} GB", file=sys.stderr) + fabric.print(torch.cuda.memory_summary(), file=sys.stderr) + fabric.print(f"Average tokens/sec: {sum(ts) / len(ts):.02f}", file=sys.stderr) diff --git a/litgpt/model.py b/litgpt/model.py index 234d174466..5158b99f07 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -264,7 +264,7 @@ def __init__( ) self.norm_1 = config.norm_class(config.n_embd, eps=config.norm_eps) - self.attn = CausalSelfAttention(config, block_idx) + self.attn = CausalSelfAttention(config, block_idx) if not config.latent_attention else MLA(config, block_idx) self.post_attention_norm = ( config.norm_class(config.n_embd, eps=config.norm_eps) if config.post_attention_norm else nn.Identity() ) @@ -512,6 +512,229 @@ def _load_from_state_dict(self, state_dict: dict, prefix: str, *args: Any, **kwa super()._load_from_state_dict(state_dict, prefix, *args, **kwargs) +class MLA(nn.Module): + """ + Multi-Head Latent Attention (MLA) block from DeepSeekV2 https://arxiv.org/abs/2405.04434 + """ + def __init__(self, config: Config, block_idx: int) -> None: + super().__init__() + + # key-value (2/3) and query (1/2) projection dimensions + self.q_proj_dim = config.n_embd // 2 + self.kv_proj_dim = 2 * config.n_embd // 3 + + # qk channel division for RoPE (50%-50%) + self.qk_nope_dim = config.head_size // 2 + self.qk_rope_dim = config.head_size // 2 + + # q projections + self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) + self.uq = nn.Linear(self.q_proj_dim, config.n_embd, bias=False) + + # kv projections + self.dkv = nn.Linear(config.n_embd, self.kv_proj_dim + self.qk_rope_dim, bias=False) + self.ukv = nn.Linear(self.kv_proj_dim, config.n_embd + (config.n_head * self.qk_nope_dim), bias=False) + + # output projection + self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False) + + # cache is disabled by default + self.kv_cache: Optional[KVCacheCompressed] = None + + # layer norm for projections + if config.norm_qk: + self.norm_kv = config.norm_class(self.kv_proj_dim, eps=config.norm_eps) + self.norm_q = config.norm_class(self.q_proj_dim, eps=config.norm_eps) + else: + self.norm_q = self.norm_kv = None + + # configuration + self.config = config + + + def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor: + """ + Applies RoPE transform to `x`. Note that `cos`, `sin` need to have a batch + dimension. + + Args: + x: Input tensor, `(B, ..., T, head_size)` + cos: Cached cosines, `(B, T, head_size)` or `(1, T, head_size)` + sin: Cached sines, `(B, T, head_size)` or `(1, T, head_size)` + + Returns: + Encoded tensor, `(B, ..., T, head_size)` + """ + if cos.dim() != 3: + raise ValueError(f"cos must be three-dimensional, but shape is {cos.shape}") + if cos.shape != sin.shape: + raise ValueError(f"cos, sin must have same shape, but cos.shape={cos.shape}, sin.shape={sin.shape}") + head_size_half = x.size(-1) // 2 + x1 = x[..., : head_size_half] # (B, ..., T, head_size/2) + x2 = x[..., head_size_half :] # (B, ..., T, head_size/2) + rotated = torch.cat((-x2, x1), dim=-1) # (B, ..., T, head_size) + dims_diff = x.dim() - cos.dim() + if dims_diff > 0: + # Ensure that shapes of `x`, `cos`, `sin` align + new_shape = cos.shape[0:2] + (1,) * dims_diff + cos.shape[2:] + cos = cos.view(*new_shape) + sin = sin.view(*new_shape) + + roped = (x * cos) + (rotated * sin) + return roped.to(dtype=x.dtype) + + + def forward( + self, + x: torch.Tensor, + cos: torch.Tensor, + sin: torch.Tensor, + mask: Optional[torch.Tensor] = None, + input_pos: Optional[torch.Tensor] = None, + input_pos_maxp1: Optional[torch.Tensor] = None, + ) -> torch.Tensor: + # notation: + # - B | batch size + # - T | time-step (sequence length) + # - C | model's embeddings size (n_embd) + # - C* | attentions's embeddings size + # - nh_(q,k,v) | number of heads for query, key and value + # - hs | head size + + B, T, _ = x.size() # batch size, sequence length, (embedding dimensionality) + + # q projections + latent_q = self.dq(x) + latent_q = self.norm_q(latent_q) if self.norm_q else latent_q + q = self.uq(latent_q) + q = q.view(B, T, self.config.n_head, self.config.head_size) # (B, T, nh_q, hs) + q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split for RoPE + + # q decoupled for RoPE + q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) + + # kv projections + if self.kv_cache: # cache + new_kv = self.dkv(x) + latent_kv = self.kv_cache(input_pos, new_kv) + + old_kv = latent_kv[..., :input_pos[0], :] + old_kv, old_k_for_rope = torch.split( + old_kv, + [self.kv_proj_dim, self.qk_rope_dim], + dim=-1 + ) + + new_kv, new_k_for_rope = torch.split( + new_kv, + [self.kv_proj_dim, self.qk_rope_dim], + dim=-1 + ) + + if self.norm_kv: + new_kv = self.norm_kv(new_kv) + old_kv = self.norm_kv(old_kv) + + kv_for_lora = torch.cat([old_kv, new_kv], dim=1) + k_for_rope = torch.cat([old_k_for_rope, new_k_for_rope], dim=1) + + else: # no cache + latent_kv = self.dkv(x) + + kv_for_lora, k_for_rope = torch.split( + latent_kv, + [self.kv_proj_dim, self.qk_rope_dim], + dim=-1 + ) + + kv_for_lora = self.norm_kv(kv_for_lora) if self.norm_kv else kv_for_lora + + #Β kv projection back + kv = self.ukv(kv_for_lora) + + # Split qkv into query, key and value matrices. + # To place the num_heads (nh) dimension right after the batch (B) dimension, the first step is to decouple the + # embedding size (C) into num_heads (nh) and head_size (hs). + kv = kv.view(B, -1, self.config.n_head, self.config.head_size + self.qk_nope_dim).transpose(1,2) + k, v = torch.split(kv, [self.qk_nope_dim, self.config.head_size], dim=-1) + + # k Rope + k_for_rope = k_for_rope.view(B, -1, 1, self.qk_rope_dim) + k_for_rope = self.apply_rope_mla(k_for_rope[..., : self.config.rope_n_elem], cos, sin).transpose(1, 2) + + # apply position encoding to each head + k_for_rope = k_for_rope.repeat(1, self.config.n_head, 1, 1) + + # split into multiple heads + q = torch.cat([q, q_for_rope], dim=-1).transpose(1, 2) # (B, nh_q, T, hs) + k = torch.cat([k, k_for_rope], dim=-1) + v = v # already reshaped before the split + + # The tensors `query`, `key`, and `value` are now accurately structured: within each batch element (B), there are + # multiple heads (nh), and within each head, there is a sequence of elements (T), each represented by a vector + # of size `hs`. + + # Efficient attention using Flash Attention CUDA kernels. + # NOTE: efficient implementation is disabled if `mask` is not None or softcapping is enabled. + # ↓ (B, nh, T, hs) @ (B, nh, T, hs).mT --> (B, nh, T, T) @ (B, nh, T, hs) --> (B, nh, T, hs) + y = self.scaled_dot_product_attention(q, k, v, mask) + + # Re-assemble all head outputs side by side. + y = y.reshape(B, T, self.config.head_size * self.config.n_head) + + # Output projection + return self.proj(y) # (B, T, C) + + + def scaled_dot_product_attention( + self, q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, mask: Optional[torch.Tensor] = None + ) -> torch.Tensor: + scale = 1.0 / math.sqrt(self.config.attention_scores_scalar or self.config.head_size) + + # with softcapping we cannot use SDPA + if self.config.attention_logit_softcapping is not None: + scores = q @ k.mT * scale + scores = do_softcapping(scores, self.config.attention_logit_softcapping) + if mask is None: + mask = torch.ones(q.size(2), q.size(2), dtype=q.dtype, device=q.device).triu(diagonal=1) + mask.masked_fill_(mask.bool(), torch.finfo(q.dtype).min) + scores = scores + mask + scores = F.softmax(scores, dim=-1, dtype=torch.float).to(dtype=q.dtype) + y = scores @ v + else: + y = F.scaled_dot_product_attention( + q, k, v, attn_mask=mask, dropout_p=0.0, scale=scale, is_causal=mask is None + ) + return y.transpose(1, 2) + + def build_kv_cache( + self, + batch_size: int, + max_seq_length: int, + rope_cache_length: Optional[int] = None, + device: Optional[torch.device] = None, + dtype: Optional[torch.dtype] = None, + ) -> "KVCacheCompressed": + + kv_shape = ( + batch_size, + max_seq_length, + self.kv_proj_dim + self.qk_rope_dim + ) + return KVCacheCompressed(kv_shape=kv_shape, device=device, dtype=dtype) + + def _load_from_state_dict(self, state_dict: dict, prefix: str, *args: Any, **kwargs: Any) -> None: + """For compatibility with legacy checkpoints.""" + + for attr in ("weight", "bias"): + legacy_key = f"{prefix}attn.{attr}" + current_key = f"{prefix}qkv.{attr}" + if legacy_key in state_dict: + state_dict[current_key] = qkv_reassemble(state_dict.pop(legacy_key), self.config) + + super()._load_from_state_dict(state_dict, prefix, *args, **kwargs) + + class GptNeoxMLP(nn.Module): def __init__(self, config: Config) -> None: super().__init__() @@ -795,6 +1018,49 @@ def reset_parameters(self) -> None: torch.nn.init.zeros_(self.v) +class KVCacheCompressed(nn.Module): + """ + Buffers `kv` have shape + `(batch_size, max_seq_length, kv_proj_dim + qk_rope_dim)`. + """ + def __init__( + self, + kv_shape: Tuple[int, int, int, int], + device: Optional[torch.device] = None, + dtype: Optional[torch.dtype] = None, + ) -> None: + super().__init__() + self.register_buffer("kv", torch.zeros(kv_shape, device=device, dtype=dtype), persistent=False) + + def forward(self, input_pos: torch.Tensor, kv: torch.Tensor) -> torch.Tensor: + """ + Writes new values `kv` into the cache at the positions specified + by `input_pos` along the sequence dimension (`max_seq_length`). The batch + size of `kv` (`bs`) must be smaller or equal to `KVCacheCompressed` batch + size. Returns the full buffers, adjusted to the batch size `bs`. + + Args: + input_pos: Position index, `(bs, T)` or `(T,)` + kv: New values, `(bs, T, kv_proj_dim + qk_rope_dim)` + + Returns: + kv_full `(bs, max_seq_length, kv_proj_dim + qk_rope_dim)` + + """ + # move the buffer to the activation dtype for when AMP is used + self.kv = self.kv.to(kv.dtype) + # update the cache + bs = kv.size(0) + kv = batched_index_copy_(self.kv[:bs, ...], -2, input_pos, kv) + return kv + + def reset_parameters(self) -> None: + torch.nn.init.zeros_(self.kv) + + def get_cache(self) -> torch.Tensor: + return self.kv + + def build_mask_cache(max_seq_length: int, device: Optional[torch.device] = None) -> torch.Tensor: ones = torch.ones((max_seq_length, max_seq_length), device=device, dtype=torch.bool) return torch.tril(ones).unsqueeze(0).unsqueeze(0) diff --git a/litgpt/pretrain.py b/litgpt/pretrain.py index 739ac2df77..a711f3dabd 100644 --- a/litgpt/pretrain.py +++ b/litgpt/pretrain.py @@ -21,7 +21,7 @@ from litgpt.args import EvalArgs, TrainArgs from litgpt.config import name_to_config from litgpt.data import DataModule, TinyLlama -from litgpt.model import GPT, Block, CausalSelfAttention, Config, LLaMAMLP +from litgpt.model import GPT, Block, CausalSelfAttention, Config, LLaMAMLP, MLA from litgpt.utils import ( CycleIterator, capture_hparams, @@ -457,7 +457,7 @@ def init_weights(module, std): # need a separate loop because `mod.proj` below is a `nn.Linear` too for mod in model.modules(): - if isinstance(mod, (LLaMAMLP, CausalSelfAttention)): + if isinstance(mod, (LLaMAMLP, CausalSelfAttention, MLA)): mod.proj.reset_parameters = partial(init_weights, mod.proj, std=(1 / math.sqrt(n_embd) / n_layer)) if not isinstance(fabric.strategy, FSDPStrategy): diff --git a/litgpt/scripts/convert_lit_checkpoint.py b/litgpt/scripts/convert_lit_checkpoint.py index fbc4a888a3..efbc626b6c 100644 --- a/litgpt/scripts/convert_lit_checkpoint.py +++ b/litgpt/scripts/convert_lit_checkpoint.py @@ -77,6 +77,14 @@ def copy_weights_gpt_neox( "transformer.h.{}.attn.qkv.weight": "gpt_neox.layers.{}.attention.query_key_value.weight", "transformer.h.{}.attn.proj.bias": "gpt_neox.layers.{}.attention.dense.bias", "transformer.h.{}.attn.proj.weight": "gpt_neox.layers.{}.attention.dense.weight", + # "transformer.h.{}.attn.dq.bias": "gpt_neox.layers.{}.attention.down_query.bias", + # "transformer.h.{}.attn.dq.weight": "gpt_neox.layers.{}.attention.down_query.weight", + # "transformer.h.{}.attn.uq.bias": "gpt_neox.layers.{}.attention.up_query.bias", + # "transformer.h.{}.attn.uq.weight": "gpt_neox.layers.{}.attention.up_query.weight", + # "transformer.h.{}.attn.dkv.bias": "gpt_neox.layers.{}.attention.down_keyvalue.bias", + # "transformer.h.{}.attn.dkv.weight": "gpt_neox.layers.{}.attention.down_keyvalue.weight", + # "transformer.h.{}.attn.ukv.bias": "gpt_neox.layers.{}.attention.up_keyvalue.bias", + # "transformer.h.{}.attn.ukv.weight": "gpt_neox.layers.{}.attention.up_keyvalue.weight", "transformer.h.{}.norm_2.bias": "gpt_neox.layers.{}.post_attention_layernorm.bias", "transformer.h.{}.norm_2.weight": "gpt_neox.layers.{}.post_attention_layernorm.weight", "transformer.h.{}.mlp.fc.bias": "gpt_neox.layers.{}.mlp.dense_h_to_4h.bias", From 8350ac2063d85825dfa67e284fe73a460aa5756f Mon Sep 17 00:00:00 2001 From: Simone Angarano Date: Mon, 24 Feb 2025 18:37:23 +0100 Subject: [PATCH 02/17] added link to results --- README_MLA.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README_MLA.md b/README_MLA.md index bfeb7f0ee1..d56240b12e 100644 --- a/README_MLA.md +++ b/README_MLA.md @@ -24,6 +24,9 @@ Follow the updated installation instructions in the `README.md` file. litgpt generate out/pretrain/mla/final/ ``` +## Results +Results are available at [this link](https://docs.google.com/spreadsheets/d/1-VnTDoK5JuNPGMjory_z1hQkI7y-RgiTpTsUpa3bVEg/edit?usp=sharing). + ## Notes - Pythia was used as model for the experiments because it comes with many versions at different scales. - `pythia-160m` (160M parameters) was the largest model that could be trained on a single GPU with 16GB memory. From 2a599da25bfbd7206a72a652ca745db64f51a01f Mon Sep 17 00:00:00 2001 From: Simone Angarano Date: Tue, 25 Feb 2025 09:19:40 +0100 Subject: [PATCH 03/17] uodated README_MLA --- README_MLA.md | 12 +++++++++--- litgpt/model.py | 13 ++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/README_MLA.md b/README_MLA.md index d56240b12e..adacfe6b37 100644 --- a/README_MLA.md +++ b/README_MLA.md @@ -1,7 +1,7 @@ # Multi-Head Latent Attention (MLA) ## Overview -This document outlines the modifications made to the codebase in the `litgpt` repository to add support for Multi-Head Latent Attention (MLA) block from DeepSeekV2 (https://arxiv.org/abs/2405.04434). +This document outlines the modifications made to the codebase in the `litgpt` repository to add support for Multi-Head Latent Attention (MLA) block from [DeepSeekV2](https://arxiv.org/abs/2405.04434). ## Changes Made 1. **Configuration**: Added `latent_attention: Optional[bool] = False` parameter to the configuration file to enable the MLA block. @@ -27,11 +27,17 @@ Follow the updated installation instructions in the `README.md` file. ## Results Results are available at [this link](https://docs.google.com/spreadsheets/d/1-VnTDoK5JuNPGMjory_z1hQkI7y-RgiTpTsUpa3bVEg/edit?usp=sharing). +The results highlight that MQA and GQA considerably reduce memory usage and increase the speed of training. However, this comes at the cost of a significant decrease in performance compared to the baseline model. + +The MLA block demonstrates a better trade-off between memory usage, speed, and performance. It shows a slight drop in performance compared to the baseline model, while also reducing memory usage. This also comes with a slight increase in training and inference speed. Smaller projection dimensions have been tested for the MLA block, showing a consistent reduction of memory usage but with a significant drop in performance. + +Overall, results are not as significant as expected due to the small scale of the model (limited by the GPU memory) and the short training time (1 epoch). Further experiments on larger models, bigger datasets, and longer training are expected to highlight the benefits of the MLA block. Also, further experiments with layer normalization and other hyperparameters are expected to improve the performance of the MLA block. + ## Notes - Pythia was used as model for the experiments because it comes with many versions at different scales. - `pythia-160m` (160M parameters) was the largest model that could be trained on a single GPU with 16GB memory. -- For the same reason, the `tinystories` dataset (100M tokens) was used for the experiments. -- Experiments on larger models are expected to further highlight the benefits of the MLA block. +- For the same reason, the `tinystories` dataset (100M tokens) was used for the experiments and the models were trained for only 1 epoch. +- Experiments on larger models, bigger datasets, and longer training are expected to further highlight the benefits of the MLA block. - All the tested implementations use FlashAttention (as implemented in torch) by default. - The resulting implementation of MLA depends on the `litgpt` codebase (especially the `CausalSelfAttention` class). - The implementation of the MLA block is based on the DeepSeekV2 paper and includes support for KV caching (`KVCacheCompressed`) and decoupled RoPE (`apply_rope_mla`). diff --git a/litgpt/model.py b/litgpt/model.py index 5158b99f07..beb14de7a7 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -524,8 +524,8 @@ def __init__(self, config: Config, block_idx: int) -> None: self.kv_proj_dim = 2 * config.n_embd // 3 # qk channel division for RoPE (50%-50%) - self.qk_nope_dim = config.head_size // 2 self.qk_rope_dim = config.head_size // 2 + self.qk_nope_dim = config.head_size // 2 # q projections self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) @@ -550,7 +550,6 @@ def __init__(self, config: Config, block_idx: int) -> None: # configuration self.config = config - def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor: """ @@ -583,7 +582,6 @@ def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) roped = (x * cos) + (rotated * sin) return roped.to(dtype=x.dtype) - def forward( self, x: torch.Tensor, @@ -605,7 +603,8 @@ def forward( # q projections latent_q = self.dq(x) - latent_q = self.norm_q(latent_q) if self.norm_q else latent_q + if self.norm_q: + latent_q = self.norm_q(latent_q) q = self.uq(latent_q) q = q.view(B, T, self.config.n_head, self.config.head_size) # (B, T, nh_q, hs) q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split for RoPE @@ -614,7 +613,7 @@ def forward( q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) # kv projections - if self.kv_cache: # cache + if self.kv_cache: # kv cache new_kv = self.dkv(x) latent_kv = self.kv_cache(input_pos, new_kv) @@ -647,7 +646,8 @@ def forward( dim=-1 ) - kv_for_lora = self.norm_kv(kv_for_lora) if self.norm_kv else kv_for_lora + if self.norm_kv: + kv_for_lora = self.norm_kv(kv_for_lora) #Β kv projection back kv = self.ukv(kv_for_lora) @@ -685,7 +685,6 @@ def forward( # Output projection return self.proj(y) # (B, T, C) - def scaled_dot_product_attention( self, q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, mask: Optional[torch.Tensor] = None ) -> torch.Tensor: From 9ab7ed831ef9c26e43ed7850ba64469bbb6c4ef1 Mon Sep 17 00:00:00 2001 From: Simone Angarano Date: Tue, 25 Feb 2025 09:22:52 +0100 Subject: [PATCH 04/17] Updated README_MLA.md --- litgpt/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litgpt/model.py b/litgpt/model.py index beb14de7a7..2c7a1330f3 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -599,7 +599,7 @@ def forward( # - nh_(q,k,v) | number of heads for query, key and value # - hs | head size - B, T, _ = x.size() # batch size, sequence length, (embedding dimensionality) + B, T, _ = x.size() # batch size, sequence length # q projections latent_q = self.dq(x) From 7ce13ff2f4919832a0b280cc84807a335eaab561 Mon Sep 17 00:00:00 2001 From: Simone Angarano <74110683+simoneangarano@users.noreply.github.com> Date: Tue, 25 Feb 2025 09:52:52 +0100 Subject: [PATCH 05/17] Update README_MLA.md --- README_MLA.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README_MLA.md b/README_MLA.md index adacfe6b37..8320f0e87c 100644 --- a/README_MLA.md +++ b/README_MLA.md @@ -31,12 +31,12 @@ The results highlight that MQA and GQA considerably reduce memory usage and incr The MLA block demonstrates a better trade-off between memory usage, speed, and performance. It shows a slight drop in performance compared to the baseline model, while also reducing memory usage. This also comes with a slight increase in training and inference speed. Smaller projection dimensions have been tested for the MLA block, showing a consistent reduction of memory usage but with a significant drop in performance. -Overall, results are not as significant as expected due to the small scale of the model (limited by the GPU memory) and the short training time (1 epoch). Further experiments on larger models, bigger datasets, and longer training are expected to highlight the benefits of the MLA block. Also, further experiments with layer normalization and other hyperparameters are expected to improve the performance of the MLA block. +Overall, results are not as significant as expected due to the small scale of the model (limited by the GPU memory) and the short training time (~10k steps). Further experiments on larger models, bigger datasets, and longer training are expected to highlight the benefits of the MLA block. Also, further experiments with layer normalization and other hyperparameters are expected to improve the performance of the MLA block. ## Notes - Pythia was used as model for the experiments because it comes with many versions at different scales. - `pythia-160m` (160M parameters) was the largest model that could be trained on a single GPU with 16GB memory. -- For the same reason, the `tinystories` dataset (100M tokens) was used for the experiments and the models were trained for only 1 epoch. +- For the same reason, the `tinystories` dataset was used for the experiments and the models were trained for only 100M tokens (~10k steps). - Experiments on larger models, bigger datasets, and longer training are expected to further highlight the benefits of the MLA block. - All the tested implementations use FlashAttention (as implemented in torch) by default. - The resulting implementation of MLA depends on the `litgpt` codebase (especially the `CausalSelfAttention` class). @@ -44,4 +44,4 @@ Overall, results are not as significant as expected due to the small scale of th - A further improvement would be to optimize the implementation for speed and memory usage (for example, by merging matrices at inference like in LoRA). > Fortunately, due to the associative law of matrix multiplication, we can absorb $π‘Š^{π‘ˆπΎ}$ into $π‘Š^{π‘ˆπ‘„}$ , and $π‘Š^{π‘ˆπ‘‰}$ into $π‘Š^{𝑂}$. Therefore, we do not need to compute keys and values out for each query. Through this optimization, we avoid the computational overhead for recomputing $k^C_t$ and $v^𝐢_𝑑$ during inference. - Unfortunately, this was not implemented due to time constraints. \ No newline at end of file + Unfortunately, this was not implemented due to time constraints. From f46a2b1c17de7043033e5c445c442abc79775ea2 Mon Sep 17 00:00:00 2001 From: Simone Angarano Date: Mon, 10 Mar 2025 13:04:32 +0100 Subject: [PATCH 06/17] add more comments and visual representation --- README_MLA.md | 7 ++++++- litgpt/model.py | 22 +++++++++++----------- mla.png | Bin 0 -> 240557 bytes 3 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 mla.png diff --git a/README_MLA.md b/README_MLA.md index adacfe6b37..5d378fcf75 100644 --- a/README_MLA.md +++ b/README_MLA.md @@ -44,4 +44,9 @@ Overall, results are not as significant as expected due to the small scale of th - A further improvement would be to optimize the implementation for speed and memory usage (for example, by merging matrices at inference like in LoRA). > Fortunately, due to the associative law of matrix multiplication, we can absorb $π‘Š^{π‘ˆπΎ}$ into $π‘Š^{π‘ˆπ‘„}$ , and $π‘Š^{π‘ˆπ‘‰}$ into $π‘Š^{𝑂}$. Therefore, we do not need to compute keys and values out for each query. Through this optimization, we avoid the computational overhead for recomputing $k^C_t$ and $v^𝐢_𝑑$ during inference. - Unfortunately, this was not implemented due to time constraints. \ No newline at end of file + Unfortunately, this was not implemented due to time constraints. + +## Visual Representation +The visual representation of the MLA block with my implementation notes is as follows: + +![MLA Block](./mla.png) \ No newline at end of file diff --git a/litgpt/model.py b/litgpt/model.py index 2c7a1330f3..2af9b777fb 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -525,18 +525,18 @@ def __init__(self, config: Config, block_idx: int) -> None: # qk channel division for RoPE (50%-50%) self.qk_rope_dim = config.head_size // 2 - self.qk_nope_dim = config.head_size // 2 + self.qk_nope_dim = config.head_size // 2 # no positional embedding - # q projections - self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) - self.uq = nn.Linear(self.q_proj_dim, config.n_embd, bias=False) + # q projections (bottleneck) + self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) # down-projection + self.uq = nn.Linear(self.q_proj_dim, config.n_embd, bias=False) # up-projection # kv projections - self.dkv = nn.Linear(config.n_embd, self.kv_proj_dim + self.qk_rope_dim, bias=False) - self.ukv = nn.Linear(self.kv_proj_dim, config.n_embd + (config.n_head * self.qk_nope_dim), bias=False) + self.dkv = nn.Linear(config.n_embd, self.kv_proj_dim + self.qk_rope_dim, bias=False) # latent dimension for kv + shared key for RoPE + self.ukv = nn.Linear(self.kv_proj_dim, config.n_embd + (config.n_head * self.qk_nope_dim), bias=False) # up-projection only for LoRA part # output projection - self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False) + self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False) # unchanged # cache is disabled by default self.kv_cache: Optional[KVCacheCompressed] = None @@ -607,7 +607,7 @@ def forward( latent_q = self.norm_q(latent_q) q = self.uq(latent_q) q = q.view(B, T, self.config.n_head, self.config.head_size) # (B, T, nh_q, hs) - q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split for RoPE + q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split channels for RoPE # q decoupled for RoPE q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) @@ -630,7 +630,7 @@ def forward( dim=-1 ) - if self.norm_kv: + if self.norm_kv: # normalized separately as in the original implementation new_kv = self.norm_kv(new_kv) old_kv = self.norm_kv(old_kv) @@ -644,7 +644,7 @@ def forward( latent_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1 - ) + ) # split LoRA and RoPE additional shared head if self.norm_kv: kv_for_lora = self.norm_kv(kv_for_lora) @@ -659,7 +659,7 @@ def forward( k, v = torch.split(kv, [self.qk_nope_dim, self.config.head_size], dim=-1) # k Rope - k_for_rope = k_for_rope.view(B, -1, 1, self.qk_rope_dim) + k_for_rope = k_for_rope.view(B, -1, 1, self.qk_rope_dim) # reshape to make it a 1-head tensor k_for_rope = self.apply_rope_mla(k_for_rope[..., : self.config.rope_n_elem], cos, sin).transpose(1, 2) # apply position encoding to each head diff --git a/mla.png b/mla.png new file mode 100644 index 0000000000000000000000000000000000000000..5c3a941acd1f55b3b145ddbdc9b848cee6b01015 GIT binary patch literal 240557 zcmdSBWmH>R)GkbMmr}e)aCdii_m-SHM_s z@O8k7*YZ*BN#3EwtatrM{>j0o-_Oq}fBPSJ%Zx8<_Tun-Y}CL;mZQT&4W%PQ4U;9r z{Lh7z1!{e}1`OiIH*)*G{Hzc_*vv%@_`eQAhslWOlEFVv{+GL0 z$zevgm=PuqG5;?&ig3}O{qHRPJwF_II?!TRh^FxWaw9sB+0}n+@s2F?!CKez<3Yl1 z!qEGB!a2K4^Y$w&)_=zF;YF2)>|5czT|@u3F3MoQH%9nZ{B5dp#O^FzKf5wuA2~B(`(C+Et{F zQ0(Q2VpqebBauGe-nWJZttoV z4(JzdXUjB>e>{Z~IdtD>AFxOo>U{i%(dVu(=@u&I@TE?_ZV9uSpB9tt*Skk@ybL&i zI{3zF0E;^|n0TOPp{CK4cNc>)2c2hiZr&@`%jfMUV-gKj=)Ozdvj^Y92@aB^uXdu& ztJzzV!FylT{S^Q9P(g&L%NYLSN&ZU7@I4Gz z=?GY-TA9=P=pjO#B@f|3KG-1o+rnvdgw5c`>7H7DdjA}0Xu-_}%M$hBtHFaQ10AsC z4JQV`MU_mh4lrkNR&C<_u$nmwV6A2@a0>vO5&hS?Lj;j;wepg|X6;o5&_4{$1o-uF zTdF}~x3XlR2a~MpqQB!L_-36+ifz6=s=ME3sbzg^?}L8dwo$!j24XAl|Ls|gcMo14 zJaW?a$7pq-Nax=UgYU1GLNRFO0@sKOUhpkg9H(Z!jFwu(y6+0p)8=Yz3P2y_at%6} z!SC3Im>IN6UGxyRf}72sFJV4+^-Bx*d&Vw-2y=pOg|+d*|Lyf}!$Z1n3hquTIu@6I zL-Go5O*$5)+uyw2U|16Ry(|GTBk(K*l{I-x*@KJo=CZZAuyyzftS?it@ zJ@k2S|MQH7*JambmRDuTV5)h*@y`d_b&tg$o*=Jj+F<(+Q!3H9_n?sp`u49}e_C5 zDm^=3O579q9NZM1KbS?JYUevDGVL8-%nv41MeZ%z7PpWD?evA?q)l@@1}OFq?{8P` z!F`2OEDJa0>cX2PlIy#d5iF8L*ZV7X`v>SEZE_VB#1)U`eWE4cMb~qK(lfjFs|3Mq z&@|Uf(n`tPwp=Lh-vQf)<{?B%g7dQf2$7tmk3fqC`N!!8h*h&=NKO*ldZ$dOwWs{N zJ`-WK`{iT*^Ny9JJio0h4%D2FM7m1#P#QK9kn!~JIa$YCf3{PC%}<22cd>s!=Cbc4 zMHs(FOP>}Uv@`^Q&zH|TTQf|u(os?%d-WX@M?0lVtNyf#9)CqcQ+A_T~QMPVJYQpP{LT!Iuio^Fx+xoSN-Do1b6N@my1W{1e9A6iQd z_g4+RnIAWp$jUu!S?|7M$m}GE?^YhPttagT9j6t1;7-wjV1Z8TdkBg$?QSzk&)lvz_B>?TO!N!~`CoQ1B}G0-1>^F7 zD7@jZEctV)t?H`fDpI?8T0bIR@21h!UvG(Y&BH1m!d&9UnzDa|#8TBQZLCr0q8+za z)`3rJhxwO#&&&=uybq-W$SD}L>L7iRMZ!e2x$v-yegoO@7;`SXF>?Xd%#g*0bL`-E zYggd*39E>KU0^?l#W(x{(+s5ND$U@Xfg0*5yr%c__|>L0;~X6ZFJ&%=bRZh%^9}_E zwD(7}9hNu!mcYFkt?S!|6*(|&Z8!4z^fq}m_*5lWkT_ISG96T>KJE=0e4fQ~bnS_< z?TII%K6QJ(5*+!_a;;=mYVYo12~+>uiOl`wcB=E133;GP-PQQil% zhr=I@lF#VR!;}zpi)k_U?GN|JbHoXvW!^`wkffKW1|#&CyZcUXS4d=c8&P_V824n$ zQ++fXRl!29Nw3SpakHLHC*tc8!cGSl>u(MpPT&#EwjrDzpYNd@@~@-a$FNk(Pc+?9niYuXLb_1l@Y9YpPWT_IrR&GSnb;B zq|Qpw5QHc2heo1{7iC>UUr-N@1+UP2IYFEpD`|-jEpwoOrfhT?UB!o16!m)l=^EE7 zAKICI$>UlFsTwx5M2Eg61G zj4m@rUbb&t2SKi;_7K=hc!df4=;4?PRn{c=2fq9TAcRpvpAA9uKP>%<5^*WT`yB7T zhlpOU1n&Ce0u~pSXS9!>bo`8ANP5vnMPHXHDY;Tr;1+znNaeBVR!ZtQHdKnh2NLaF z7x7&$cEuv7`ui+zr!9p<%Bt`I7hTcp1o~L9CW=)2KShF1M5umjT^_#PmN1)V6TJC! zebCVwPE6?b`Pl1PVGMf5<>sf+k>62se1%_CB>lvb;8iz@a;D!9C`*U zeByS_-otU+vaJDoesCJ&s&08g$5d`mo(4fe1UZN-Lpk=pHZvwNRaiGC$czX){%SxV z+Y>!Y0X)!x$+j6#O4>5_0CjzKkUW2?>GE@Seqad%2>*jr-n)e%zC6W;SAm8@IbHx93^$sKjI%m+XKc)_C#+{MWL%Mt+3G z!goX-`u!Ih((~fXZ_&hII|&uAaa!E&n)njHs4Ye4K z@Pey5F_q&)40>=OOpGUhKME%$N*!81;R>)cOsSBQ|z(+w>-|R<6WSG|O*6>&CGM32i{&4l1>1MUoY6&|JY+jRz=!q{rt+M#FKB|NQsjP>_O9s6xzxz=Hm19nQ)veL8w4by=$fB?_1+4K zu+rtoO=xMxNY9o5#v&tF?;*5(i_&WO!$5D7x<7!ZdSj`G&wD$+tS%h}otGo;6_7r6 zbwb?F)puKB1qw~4|C%g`d}Qz$kHi%>&?$E1s&2)px{0CBJi7LNuZcL|gu@~3NI zWLK`tGI1^v$HGqJ-VRy{qfHMhWO~i7N9sm*!MC%);QAU><+F;~j%}&K`A^3g4KARC zWUH4;av0Q8fe1tj)Jq?l^oAuFXp5Dt8@H#vm4)ynWXL_`IQ!*NI*%c9(L;(#t0o$k z%-SoD^s?#LieGZh=0~1qFNWg0FioY}kg%Ac4B40QB4pU6xDh#OXs0$XR z3wrY?JTy0h@Nz4S`to#zNpNyzm>;w_<1{|?2VG!wOZe`sOUcW}k_FaDwQTg!0hDA~ ze8o}f7*P`axNGG$s?hwL?6ke7tY3AG%Ny6&hck#DvG`1NULPzEi!BZ8ioy?;R?!=k8yncMAA8QD~;TETYzogiRyf@in${^HI3i-V@C{Oc>bDrshj%~_r2o9Th8{2QXZEglRd_kdaH zw6zG`NKCsP)?KH5i>MlHn+C!yGDvVG3vm; zJKA-7(Kp5&J*wAwQd|1#(7tP)mNWJ@z%|{G8_1?ay-^Mj@|1#oh452 zIa~7Xo!zQ6y^{U2XA?)QbBwOL`z17~s-lBzv#>=NjlTyo+j4k1B;x4bX}yUL}0b*+3nM!^6i_3&?*oT?QR&gIjPJ&`B6P8 z75;da?~R{k&7RY+!oDU}OvE$|?lHaJZiFE=C59QD$aUXO*5>^WliJR=8t$(Ho7R%q z$oS=QyB<(>U00o*DFf3+5nhT92@;K~cQO*0)5eta_0P$x`?k_9-eYRk;=^GLshXsi zjSA_rs=C9aqaugr~E@FZ?%I+o} zzTwZV0Dssai-A<*tc`djmt~|=U>SSiHV240K$op0mx-@Nljow@=#7KZ3Y^*R%8!2L z8CH0jECJV(iEZXMwHe!FCC7lK}TN~IJlAcS%n%!vai^YA<#1LweHp0Nh+j9)^ zn<}B1HXPT^w(t^Q1TB7O7y{D%O@jRck&;d-AK%cJ6y#;}9)+lDRdC$v zD5&$Uif}q}!fW(h(M%(BX5@t7flo5gwwWZ;pj!facqYYC8ROGbFz_WC?VAUF0UO`Q zzz&t+`RS5JU$TR~xMOSA{dJeyhI~eq4lY#tmZI+ANLyMue%t!=**N`ciW8+`Bk3~y z46;h#6r8S0kK{7??$1dbUj6EA5itcJK4{QS# zNBWbRg3J2*tmD0Bx+@w(EelJVomn||1g^83Jc6}NdgrBl)G5$pXfyd65chjnj?yED!sXkxz>-PVU zX6zhAvHP`L?DIQc;q>=*Oi;jH{8=aEd6Fj&`~z7rM0KGTGQ91kF2*N9WPf|NleJ~% zRq8wHbY_S@tXpA7g;B${d39KRaKE*^%&}J80i06_9{Iv>kN#9(fz~T(%P8POKAg^R8-Xd`$g9iBMox(-u?zA2xK6!Dk)PliM>;D2 zXPh-)p)(`L_c>0{C`qs$_Y7k#(R@Zk0gPfl`=Wp~@JqIrZimq8^DD)CHXX*t`q6qN zop3Mm8-)z)u(2Q2^$v_`xZ280>(ymwY2YdG-I&5;R?evo+^^5Bpgv`7va%V?N>Y`Y z2K%WJ%xu8?mfux~ zG#7v%7n9>2kQM!vV%lQ3|90#=;Rk>2rqXRmJ+6(S9<}5uRF&e^aD{@hA;#kDWgycg z=okG6l8vG!xB+86D&$DuC+&1640Q616O`it1{&tl^ z@kwvric}vCQJu0-Xr}b5#@!lFzj~c0bU(`zm+IcNt?%wZCVh9YPFC--mj)iFcFyA^=>a_I$~XVpKCxz9l$s$wHCYn|!6JR`=pd`>7x*7g?efzSab zS}OIec4;he#zjdTsf4BM$<3OE?({wTVC{gMTZj!zJ=4-!06P;jbYj9$5qFYhkoPEn<>dGxH29) zR~`5D4F(b!(bfGcPcUFg8);X+PaHV?xlP!jK1$MDbYnnna*kT8n(>Tr*@ng27#buC zc5P=+8BF=fDMDbZ_0OA9UT{Ehg*o78R~yqs#2S`JlL992`ol zAMX^?tH;RiPwT7yo#T3%!GXvR{Y0`KW{(Kg>QMf)al)xF*fKvI&*Llf}1`;ZF0`+*3Qv+X3) z7qjxKcxP4EWaGp?89b~vEVD80F-Sdoh3n1M9Gb(AmKr2n*Id`YIfV~DC**w`mf70~ z%x>XoskyY?c^rsfBq2fNd4VcKH4SGO)_3K|FB9)zOHUp}v_0Ln5qHWRD|X?q`55!! zgu_I?FWG0B2W&{U!?fOL*f?yAEi^tO0)F{~PZP~vnwu%xA>AJ*#r2?en*k!38Q^D0 zt@cf68t6sx`c&-1vE^H`OHI&fYg3=plznvj1t0$C%CJTYP_f9fnj`Ez{KquGs*`jH zKc@(Y4+lJ9_$(S^*5#Is5@}rc%hdI7QC}olKo(Bt?xR$q{2etNy1||xO&Sn{CYrC6H%*!bA|*1Ptk@XE6}UMeNsh4 zG^^wFqDi~)Jv`>Dqg#CRWzf$6(NCKbSL52`UZnGliT;-98~iFY>~$ug%ommh;Ks`U z->LM6_HFvZOu3rTNfX@n34%A*oLESK1(^0X{BVw#jvK-ZRj4(t{H&)3ck>(1)CB|c zjjD0IK>cFf_VmZFB8pZ-(a$7?YVOKnrJ|nG?z?g-*iZq6zEO3ocT}lS3D+cHrPkbk(Q>q&n0*1@r@Quzptp3Il zX8r~`!;MJy35*$WCBF;T>68_FC@ zR!bb#?#4?8@FXT~QZ$1dEa}Vd{()_O1-ke2ym<4>Uj?R7!ec!{dn?@tO)nS(`aTw2 z9Ep5Rl#?e?$(!iPr;ov@+@la4?$t$n;C#NJpvNp2E&wPfbz6~B>LuXxy)l(dbta;H zBJo7w^D!?oRE`Y?W#9~VxIMpTiiaQ)qd#=7s+CclL%HysNjk_o5PC(&uqtoeD+Hma zM&uV(5vE}c;&d%ml7jgT`vNsfCdzD{MfjuN)dyfaoaAq9xcQE)dtQ{{PcW~i?pe*5 zAma@QU-DY?&r()DUDCM>eagW^+5GP4IVi_D*&oy^3+j=DXHz2cbeFgNI)@sJJNmmlj^haE(SiJ z)>qN0Th^CTIHB4@EP(e=?(E=eM+Dv~kM#RE^}L3944D9%ca~u?Bf};=u4&*`vdg3o zrUJW3^`wXGke5c)&m}th0zXH?iD;MOcWI;6`QRWPdJk0yTll+xWr<~z&-}1)QP!INBq6{e-8B4(uSD!_dVJzGNKC@L%*UaJyj*2!?d>bVX^R;C(o?W`#M#m*!G>Gar)4w#`?bbh? z{|$RzV8XM37HPu)o{5On>f4O?&?M2y3!@TuIdKLPBBIC0M9-`eUN|V0%mqnvWNrgM z(YEEsPDzQMlm1p~f?I1wXAomeM!V?X!BT} zDw0CW~#-F7LwW{r9yx)$@cLTpNuSi==A zTC7PDTo1QR6r-ZA$s5poHf;1B7{*31I$5T_Pn%r0{}IJx%{A!-@9iFfWS+w&I;2J; zvzrO-t3461nY{ma=yI&-FJ7lYS+V>XzQ4)V)w0&8=WOu!?H9IYZ`Im*Ll)4YV8dtN z9~~ovsCP0C*cpBt*KPf4ime#-q38>aJQ`L{C8w`^-y;;#SiX=FTmKN5*!&U#=uns3D4$%iUFnt8(%WvcS(f+o}@+`3X-o;h|?b#zO-J`8i| zOdnF^oHr(ptztX#G3sk-Ldy8-ErG?n840X;`vg45HLA#hEpmLHX5K>OeesSn5Z@5omg3+$VFy{?Nt5UQ-c~2pXLyyRS(;} zNcegj(1V<4-v&l9U#>-Hx1})7>yRT+4zP~238@ox+2S0QI@uR}tZzN)26vn`(04nm zPce;hG20VLKm4OjBdq%cYB^w$bAuw6gd?#@f!aRvDc?7p<1&2WHx=66AVt8lw&!~B zXJqHcrMR};F$L=qmkc(nlTj7fLBHP@fYl}XV)rUbqd+;5)Dzt?DGxmy%5l27u!7YQ zI4 z_lfOE3#Eo?Ckc^pG8JHIM%^9=#XO11xX`a(BJ$R%5I}0%4%W-V1@PLemR_6Vknl5x zwKx~skUf!U0wPTy3q{ZL;1_deVAF7mhB?!KcNJ!fh^_gE$O;a(+f9N|%8jM_-KZ=? z58aW0J7^bHxE*CSTu7bgVnE=uFbxxS&4i_kccZackL?ieuQljx^`i8|DJtOap1Yp} zpCCsXK#dk<3){>SFDRy0w)7x%N{}pDD6hsA*6ozz+gm}b`SMOo2F5bOqcvlOVBmJA zXKN{qVqb$Y1TeIBI;UsqF(~+!t%k|8!6@qP>DHCLbQ1mIhZf%q(O2uK{PeTz=p~&! zEiEwN(oBAO+cUC5y^T9TMots+lMXE!wPokCnjonqh69Ux-Wc#MaWgnhM4ub)&#YGp zm6>Ug^Xqk#9h!r3wis9kPI&~2Yumx-DwmfPi^}U8 zD6_1c#~=4q_FZhWV8VQPHn60Pimj_nDeRp=4*)58vq-wC^d`Y&m$aG}l(Cm$uga{r z@RdvB8F@A^lvRMdVoi>(HlrXc)T1FE9%u}VLa;6#Z1RlLSi!(0LMDaQMn?=}Tp~X> zwDRR?9)EItdNtB2i7glrHH9j>bnUw5t?_{|6?!jOuZxF-`D&7FW8n0Q%zP6#D&D?p z^qF$!KL}tHanz!*C4D6Cr>skUt>6v|dvA|b2WQ%h7tyZe7*R#KT>I_mT?68YU;`mX zVe0IaWKGueH3xcRJFj_Da79AaNRinbtI;pQ8x_uHg z_lRBVm8#wIib2&E%D9HrO{+yH!?vv!aGL6D{S01p)Vl`anPe;APx8VkMQv*8&4XDJ zKfpre82JDUWwWaLEJJ49)-(tmkBslAqx$Bq+=hx~t?;H^Vy7^CVaV;+L9iDiW&Jy{ z-PT0k(t8SJ1j5R#98|3h*~Zk^MFVXz4s2B(6jNKPw3KLjn}+@-F3>9U9OhE4-exeg z=8JPN;0AqusPJi(xvXQ4)YVMoOl89@SrUstnsmu~eM%szGp5Xs`Vc)8qvYFBb%VXp zqOcP{rtxGFvqSAFv+1Xl^&L&TMmjj{ReSrC@vkpzlA!e zH_SS~n?YuaN~BsAMK1qT%&+;_Bq$1dwy0>Y@VJdeto&o@g&9mho%ulf_Sg%j*u_h~ zj9lCM1#;@<&-df5=VX505{eOQ5T=|HpQ0@ji&(I25zO)q{6uBIxZI`?voOiOK5cWFa3X<6Lr{G$aek2(~Aig5fq+$+)gdaQZHr*Vt=<~aMwZ0B9Y zY>K)%4uX`)%aZpfCSfEj6;K+nNuA+-QF;5=6$5O(IJBc_eCdntTg8zhL^vu?Whi^B zRHVy#{$RIq5Z@~bo#P5^;)~~ZhE6~U=oH<`RYc6*G|4KgKgkKpvA3~kM}Nio(!AlO zzJYGuy>d=FChvhWW~+h7MHq7O*=( z`ma6gC6XJd-63+u<}(61_*dk0MmpQoOpDAqQ=VOZ>I<;Q^es<13hb-`N_!CvUiDRHx+ z0)tR=qTa}-DVC)-wYwA4p)LYlJw301wpNcFEvn9GkKq0*!n=A7v^4wpAV}ao%$YqVcp>U!%*H+sNbP5Y?!5m3pi{&yht2 zL_#=loBEB_f-E(jKfwm&sNXx)qo1x~!4sRMxmYIz@Pk|qD9Z6myd+0lT^0;7U5O;V z?3qrEuh`oh2kZS5#THcN{v4t2R9Rk=T}>MnUQ_jv+CAin)df2N**A6_=pel)&Hcq- z>&I(!dM2D%1MZ?>CK*(sUb(y~tSfAuOMyz(Fv*Gp9rS|N#;|zA#@W^WHb`AVO9zBj zp{evk_ReuPBdQb#KX5&Md>P(YGbg+D-SNKY(dgWkesm%GdFAROtOYHgz@uG?CiiuV zZNqVoDxk?VIZw9Bq)Bev4(g)*VU^5?JplVVYbR~-Be9yF<9=ga*}cwB_-dsGkkMY8 zWt<`C#WczZwN%V+o+P9?hti0|M%eB*H82Y~UjDmZBqyzU^O9}g; zRb*|&!4w3J4|QT#I?L0CWT^Ypg$pzLiR@#7a{TEkiDZ|_++|{}uG|2p@LSSKiz@xqPIgM(xJI#@PwWA=#Yf3~ z3%kFTrN<2cFyXT1Iut&Lmd1`09)+?eHUnoqduT`YFLW_IKFM9^X~lR8B;o35Gomw) zhlYGD`C8(y%dJci`BZ4&B>()QF^_A?6f5Q@=|`9-vpBhRo$#IErLSkISg1>g@o~6B z*qe43F918nz(7RFz9+Fc(M-Q;QIcTj>_dfAU5lQ~MKFaYJcV`U10ER@f{)LTM=c6b zHE`fN&uyOby-mkxhE!!n70ml2;b?}(Hj$x;HWJ0XPC+zlMHX<*FKrS#^3OT^K+pNHFGRUT}ZY!H982jm^Ndhl+z9*ZFDxj~j zh7hw}Zby$imRN+dYY+OK|MgVC(PyioT-jpY^ebgXyS#UDo7i7AF^XFCx0nzU3vmyZ zLDU4q2FOcR1%0xWdqThDTdtsO?rCC&1GxJb%!}sP|NGPT@~)d&si|eZ~a0a ze@S0m3Xd@ure$n}%nmHbQzU{B6Cf2sr@DFCW@7-&)wC##oyo-}LG&dd^~Y^Bh{NAR}D4x^+2 z`;;efmrDbQd~P&#mmZ|eTET)2bB5mrHL9ErPVk#33^)9Uwzhbv09S|a^UrF*_|2y1 z^W_Pcg0=&5Y2S+vhIOfoei7~I&QD=EVlo^)wexN8wHhtkjeJpaBwbsv=h92ZkoR?8 zHvVaHGKuxSnI2g}Q(olBRIn28S*6*I050b)1v)&c@2q$&rBCX8CD{kRN^BcJT~0kB zJ$V=oz$(*1v!w{I>%W229J0zFQ;igb%;3|q;g3qViG>`O(z~;MY>b|F(}if<5wyWl z`+g6LLi9u1acmySd_D`?HlTl!qI*X2qze}uC3+k~Rm(5ImShH)?o)q`JkRWQW~{7e zn-?S27rR?yA1K1O{QJYQ|qR;f}X+ zq1Q_xGW5AJWZDmPv1R3ncbOzOLveNYe(pr1wuT)yTGrs~H6WHL)@MX9q&jC!=wqim zRpr10dNT3#q|I)RrRE_obbgoVA5qX}le4BE#+V#g0OHHgK^*tP!LFSo|JBw-#r4gpI=!0qtDv zrZUaC?w_nhx{m=5KhHr`f*}BM)@1VedDs1|iK@(IA*OqkE zkL=zYvVpE*<+l7mc>(I)%7BRET?|lbfDYCmk|(uoqKDuZm*db1WH8;26QZW zCSCN5d#@vda`7R9OQJA%Vbr4=3ZCJEXg!mtWV&hXJH<+m`O;sueNfs<*~<@!dYz2T zb*fxZwP^>0D1p5Wa8s*Sdg^rQ)ZC9~-!WwDT7`RhbLvl>mx)dV1(7dI@Yrl&iR?Lh){MdhqCTI~kfsf& zZ=VoJvC|$jJrRPT->M zfuvDC7(<}AX-v0Bcn+T>5usV5)sea?pI>Br;{ClzvmqoDRwBiueOZU0`d?7h(+r1wJc0J?(vDc>%$fJ z50yOn+I%=4n{Yqu=lL}NFkc`svIidm>yFg8r15Z$jKhBuIR#F5&FSn(oK-NsSNmr2 z9WXQM{EJ^@Atv;;ZR6Hvy>bmmIk{&4dvRF6di~V6zMy_TQ*ZgK_1Z=89ZF(FXME*( z{5ffAW0#t4j`S_G?pQ&veL0udZjq6JcNR7D52(QQ(9f3U-T&D-f!Ch(8MzZKdVByn zqD_i#JQ>v4iiiVQi_a`C`&6xffL3kEqrSHyHfYb3gp|Yv+g8g}92sN=7(`@3iz@V@ zbQkF230WV1R+Dw&PT9o%ahaeH_2&3GCpFeTnu@7)qI0$PdpW!NCsT=Eg_yPxdTBj! zm(#J7gy@U?IM3j zolmSoQyS(edL>h;yJhvm8&g`Yg?A=>vQTt-%2NaH->*SEmHxd2dx9kKSEQ~=p0Q=o z?+7*C9BJ?|1N>6vOOAoycg|+JWS68^GhNGV-z+e##-CK)Mu~j1W-v{d)jRs3EH&t`zY*+g0`O6^j>SFxQUjP8AkrJUg-Lu$r6=hBl0$jBgv>q;4Mal9-^5_NfI0 z@H3i`B!!=VDMdW4X?@w+bX!zYw=AJ;wa!OP{eaD_t>`DEacSg6s>pU+sZkySx<&rB z?=BbL6S}I(Zt|={8Vg5KP5LElfmLMTv3$e2#qLy&raW0L94>K4g^fi)x+02Lo{`q0 zF-GG-z-GO+>P$)0=?WxUR!<{ORaDQBTV4fYKW2G{S6>xnEN5ZF06^zs&ec*)AQ#1b z$?%5s_%{c}+4FU|M0SZ{l|_E(4CgxH#~khwO2ug}p^kpspPxR9tV~t8PoMG#Y#NUL zY1?M-f%kP4CX|lM0~d!qHz;oa%2GdbxM@()megLaiXKR@oR%tGa?EdUt#DSov>J+A zbUML&Y)rGFci25HN?FD|ao6}Qb5}QXdiNPN^L};UW{nO(>;=7U{7OUX{#-3;ANP?73mYP{$Fz&Da9mfTgB-FZ{IoK6jyotkW$?(1Fe`J<+Uc#rstsZ$q|i z6^fMQ;#F2u$Xk_94!MNjvBKlXPYyZPtQxmc2S_-GE=p^+kq);O$cf~*yOcgnea)H3 zr8AFLH56TYAO!m8(X*40=e9-oE_|82niP^ImV7F`i|>FM(1m|X4eB15kr z|B_dJLv3k;FbbPj8l1z95s4OwS3KlJ9+)3b$T6X~lq<~2d-ouk%{X594QVy^@Yv6^ zyhLpYde8w4TgI*`Fa0VP`Q*qnFy>=t!O{$VUh5f%aOx5wUKw|&lB8OC?UUr1lw!;$ z*xXb^sfk$FrH(Mj2Ngn76GZoQ9S7Xc^xs>cn^fM)xVet5aZ;yg09*xJe`?eH>93Yb zhJv=6T+d-Ptx+rA+jq7}j_j;`^SXI-^(5z9sOJ4>C!Dh$s~hzLiT0#rIvG&-blaRq zhg{px$|@#2udOaaTm#M@mtmkI)shlFg$oR9gF`#vI#n2b;p<68N3oLQKf-~mRagV% z2&KUb#WHpY6yz;r+iZVC$GGk`zqB^kd5kYpci^pAgJ1Gu9>fR@H<(yR zIqvbl@=&@)1pqJ4yfL?`_I&BYch5*nTUpQGB06FN)!HmiqO-j2Z*T>+Dd4zN%<<*r7ElB@?(n6fMJ zCVef_zJI0cW*nUH?uPc~P zc?geeBK5|zX_;o*GILHPsW7PU6|oyzh!FazmPL`4KUyzLX&z)|>QPUKGnK6zdcLB4 zRnAw75$Ypu9=Zpb95vS?n(|viHrLu?A4T0fu29ZW2P=>I^bx5D`Wlr^)8kFXr6_pN zyGymGLqD^(UI?eZ8h*oCYEyOWB~@l)tx7gj?lKI+BxB9?Fp5=JEtnKFS(F|l)@Z%~G&s7TksIIvr7-$+5&daj%rR<*q4pXdEDeY8kX zh*Y?~f`ek-esIMRC3NH;wA`?!7G5g#pz^P+HRWY&F^*}u`-MxycIu+roVaB$FR`DLrioe zkjX289*XuLpngQh9RCL{$$R_=L~fHnj|bg|_&EFNz*`^%jAoT5{%R}B!RJBolY?VK z!It@%oK-LPga6f!iiUJ=U=}o7>h_1up)2Bl zB1-X->*dBPcral`hKX@3AE5JUqd7ufXt6{;j)iPXBs(lIf01|i+978Tp#~gBuxwBw zqF{tJtT_OYs>8*sB5izj#puC=sKUqyt5b#g=TrRQ^CX0_jSrGpuJY^)`3LemM`DL_ z7y_VCYK)Ejjd%qBYX0#kauV&FgQA}l*@LNsjRSbY- zY~rC!)`z~@6VR1@>txdL+@RV}5|Z@=ju894zPnt?4>*{I8=WsWHyj}NWeX3rMf4TK zwza+}!#6_;%@(*3R(ZGLRNold-IBhyqdewphO}j9&G4WTB&yub`omw$9zAl^c@S*p ztjUk?vjpZN1guL30Y8uKYkXHDy^J!5cEyxBGdvbVq`yo%+4nltKThiOs~n(u8(=-) zHD2g<6mKz=?wRksQxpver&O-KM(E^=`qS(P-_eFjTl2Jz3Ra9-c5E~nJcNo0rvpRb zf7eN@LNR%9skIwdg08(En%pUy*3-XYJoVq{g+b6reVy&61zxxYcPzG~X;p3J`dpQ= zNL3NP3hY4eU(UZHr`R9HYJB!EvuDrgH!+d_HMcoEq6?Uc^aS;*@1digyb1z;{}_|p zt3|vMVEUa@_|{s-{tVo&0ULNeblGvxJG1xJDfp&jxW^UdF2i;kygZ$|C_z5O9){)VL|9e4-iT=6W;^qw$F)@#cA=< zBaEkCKOywCyFQEH)}y0*gq>RfssAI#zX?VhCuJi48FQZS0wM5T(5C;ixO6ZRxVN~H z&y@xjB13NdGzxAv`Lt`abXM>CDZ@Zp#h$zw%$@7y_4jF{8H$jMvvm)b{mY&R<64Cv z_3k6|n1}h7BMv?V7kw=44}#PsG&11V`szs$ulD8FOZKnW5u)jXg};RA4>BJ2uBkHa z3}W2va8X~3zb4)7Nfbl%!}Cb%;E(am@E(DZ>26u_U)h}Z5CkFy^+oDt!dE zh&T8K_Sw`FAVfvWOI`?HIXKSjdL8}h|9=-r)SN%jiEA|Idp? zI>cgfVZuQFDQW%nT>lJ)SZ;#PQ> zu>27ZObHP?niLh({GWoyACpGt1u_1a{r|zb-C+-*hVK7k>#f70`og|nMY=nrL%L%S z=`H~QrMqiL=|;L62?1%Od+2Tu>24ULK}!1U@%KFMbLx^5?;rL=DSN;!e5wlnvu{WP zUL+pFyi@n9GQ)Npd%t)G`Tu@xwIs~^hFKNib0Y))w;BQG?>c~NI02M7hp~bukP`rH zAa;{a`B*ZGd!C99|36P^DVvMjs0#oGR`IgWf`6Wl>Or|xTaS;(X|J$=+d)%WWGD7;I>|8Dv}c|A;KIu6Dk9teN{8ORm4 z!z%aoL-RqA)&CP5%)7!=i#Nv({;lBms$UcV-T!V2%>RMa%3D_5mf7C^C&%i7N&!y~ zwM$F>&!}8sirw8&cpuM9RV`VW^pX8Veuf8 zOOO+e&{GaKVzdXa67Mv@eh&b@Bo2Vuw8jA{^$Nz?? zWX;EoI>0G#f4be{f3u)u@0@fz#Ka{D@H6;bVLJXy=V%rxO+;VIIjLDUnD9ezH(6cB zzZIq!YX=x2U!#cC8~<530BzJELw^bgo-6D-FBLm^ZMj_5;jn)Z{^LTyDmV8dnjKS1 zf0J?^%x=m$@5<6`z5e#d|589bmGz6B2wSy37M4|GQ%UrAL6(;%G8cY@Y@^H0|n zn4!jbIkX6S$A^BvuJwg}n~4Y8f+kX%bMJmv*t?d=%$)$}o>iEnK4iYi!RQ(zH$(Bx zWyFF?3)|+A(ws1<*yLj6w+#P5rBjUUXP9@Dv7aN{o z6ST!^0EJ;YUL^UmeT$&V$}Dq&a2IwLWI9*m)c5al_}>;~B{6QqH&tfN4gnU<;=(Q+ z?b5rl9jJQyzMk|4TKrvM01hI9PL~PcCU0Qd&OQPfd|gu0na}v`cU4X@n-Bm^!4G!` zAxj$l&cnWv*dK5E~Gj)n8D3VAd1g>jY3t4b6St6QP6%%}!QAf8ZeppQ@Htp`fOHd(Tnb zM)y6L0=44KW3Yqmf!nFMIcP6NVWiwY^VuE%cr^Z*xWmk8>KL*ADT5lhzTf1G#%J{C zl~Sfx7(&9C_LnQ}?eHCUTJu<2T=uP>0X6>LWDwGGw8EMI)H?Hh=WS-^VzmKX z^DT^_0WRo0pN#YSd;@b?D>=z{z9f?Vk2NC$&R3(!`q@^Y0bc6?KwNQ%Eacw6=K3g4 z7)lt8{$}3q`F`DD{*&`J1i1Nbn84!@G3gJLfA-x>aigW0j%pVtdy_;SYrR(evfX5e zj|V{9;h%@I79Il04EWt2&&z%Ajo<>SI-Cn0N(h@RYy6%}nibFap6hdDO1X?L6GgMU z)BjgI@9XK)e$G?rxV2-S2@oQd+tb-K8`#abG@s?r7D;ht_@(>Ai<6;{}c^+2l9ZIqhSY6m3tm(+o6JTk}tiunjO? z-Puci@+0F;wzo)?2Sd?dpQ~7fwm7?)LK`q;*Qg@ z^#RO-LycsDh%bRxDZlKM)1#CY0+$^415LPvFNbnuj^_ysIFk{yil|-6ujtvZBs7)t zj4cuVTg^@R?!mKC(%|X7^V$1muBoG8ymR1y?jpk3B|Z2mpW><{rJ7-MKxffzO)G7Q zEFHntCEI-r_TNCW%RWQxJtw>k zbU6tpEx3kUqY@OsVuiturc&CM3k{DjjWx`p(nSe6%|;U1c&S7ZcBvEBcUCW`X}0`^ z-6^8+Z~G>O1B4>Z@Qx=wBdCvdnb>73s{K61A&W)s0T4}PcMnx=L;ZI({R*!bWctgQ z%$CcCjy-O;UKrjl&AY*vErc?S>3i@IPx+#E`EwjmADASk9%kJI)etYD*3DUO*IdJs z0hfn;wPuiFIo&07vq+ni6l$~!T{Ap+K&KNOvc2Fo(G}=xQm=vquH)4*Uh~3GtWe>e zm`H+`9dfv3(Qc<<48r^Jt1v#+btNNrU3h(muI+mN56(H=L!FcTFbXd#p5!zqtBAc` zK<3JQadh^9s36F#_-!+ANvc!hPG_srbsrqk%uxgB#xUf0LR z;K(5IaMnwzt)lwLw@t!&#^(cRvhTdZeClY8NX(_!ntCi-Z=p*1)jWUOCI+}85AkpU zWo`JQJ4pUt_)b6?l6^l$jbA_KJ3E-7pY!x>{q|d`;d+W!LWR!7NxEhBV)Eqx{Zs{X z=gCLy!p*-jwAm|Fk=~A}zfFB?b@X-GM_Xj>0%0;+kx3$5@Lj4pH8{X zq0Q+x&ow^ZTBUpHWvF%%TWx!i=6}&1j3@|hh&2-b6QSah*9wcV(P@W+x<>U`LF^y% z(GhN%pMbxZpw;W3Q85R@xQJlYItt(=UNQpeON~P2kYAUDD^IcU;EV4In)>K22W1>S znhMzs_`(+{Ru8Md;fx#;7ZC<-VK96CE_?r9ZbNES2%MS^7l?_UjIify^Uk#GLy%*$ zL?vhCW8Ar!df;nf6#F$je9w>N8B%566%$-pw3iIM zc|WWYj4tZw7{Y7VGPgScn;%)lC&p0n|ouu^(3 z>o1WJE%U49HKw7yVxe6oFs-aeRFBpzr0xmej~ELMNvA8KeDM)eP@BIMjvmx_R3I58 zkJHV3>efod(xbf0MdBm!9k{BU4IX_RHGH#&OsuZ=0x((6E#8Zx26Ia~qQ5F=$yvUK-8bc z$Gp;)%~qc9rCKIDvlZv_P>%?;0(EGcrh|QPREEkW*20Ii?h&#|J-+9CyliUd$tq$AhlC#_x7i>5P&z67$h< zUBOo~=gx3f_+#zI4&TJ@r?GsMZPI4RheLD>p0oBI>mfhFW0{fo)k3-4-=ndEO~YC` zNd2ic`T;$jLY?btNgI=c9cQPerkdVM({l48>d!g5yiXW2JaifNr>%cE+Fe4$d=M`<) zcPA!W^aOs+H!ID3pY5i zz8-FfU^w*--Oy5jOsb*eh=)Ac=h09N`cCa-Tu`*`cKB3r^!tIPThwbg__q~T=)3h1 zw7dat9gt&a=;E<~5GhmeG|h8{Tsn)hFQr)y&(jNWb{z(*k+G}%wC1Nff+RpiuV%;> zF?Qu&Bei!-YJ2s~r;`l+QrtJwn-jMn+|2g@aQPk7n@Q533A1<60`j8b$kbgB;?&4t zVtj5mRa0^vrFGIzwztkM?J%}okDpw&I5?snhySNVZ@~nY17j=I{m_2KbDJQ<`l*}p zK|J%Be%wJ%v6~P_{@gN~FLi`~LS!IKDM3D*8wqEDR{+*;1&bRTYNqM~AEISzW|(t4 zM=(fjc`x*Hf~BiH4Zl9K174O&GzR)ke&x{WpSLyNw>c3qUqg$n_mbklqv@21w*O-5 zKp5YX>T4zq3*y@^c%`(9A=_%bY}SeWVbU*6=T7|l9qazqmW7}F=npuAWREPnCSwq) zXY(^_V-HK_+C;r$My@2ROiNoe3C=!+uxRtj6VmD_>>3U~uh`bmHp?Di31-W&m{EVp zO!%E1E{SHNfDtta11~i@!$ifV+qxg57ZU0(%6>L=J|1gE_o!aE2)lnkV@7kkb(weN z@Hw*M7GlF}K17|W5N1tA5aKXhelFo$5iLa<@nT#S+6Gb!zaukixYvL;MjDlKUBn$I zoESDr#>$+_nX~C z&_;6jz9hUyd&yz$Dfu2ME0&pY*xnggJs+xv(@)3iucG)gC-b6qJj?iJ)wsg#(ovS| zCOyYa;zC#hdlF@uox)G;;kJzD^4s{!2I^N>1^Jdg^OI9Vry@yPu-`Oz%5zz{^quOc zE5D1iF^y9D%0fR8<;=nN>~zye_{~zJ2C*Sl%EpVrUB%<8ik*&%&YYh^#Z7%fs2}2m z8odtIJ}oGwNS=DRNStNlh?KtAKWf z^$&5;${QcTS3{L7pA^~f!y=n|-Y+r=*Dt=^a$fMA`(iiE?$(MExfE&}b4`JWp(%wC5Rt%jCb zg9JMtZat0q5lAh!vH9FPW!(8nuPteK%6=m|6zM*>!g6hg5v@L|%6*EuP$m8?dl#<% zM|+Ffi{2-J?GGic{Xy9}!Qy~bwW2@3*|c}Tj`aGm4kHsbtzK!PWHc1jdk%wqF&Cqf zHzmy4O7cal?8Zr}inmH5M)Q@JF_YTJO#-UZLDsaD26wD##Es#)1IEo5<0kc25mdVc z5_JMWE1^8B*qt*()AhyP&F<7lk@ZvjjBb6>-0YToMk&ou#1TxFh!~`+s-&2N_-SUr z9YFBn2{t%Gzo74@N}KS!4|xD^e{pB%)sv|s$B#y9UuO~QmY$Li_hh>~YR&_NDr1mr zX;1l>Ssu;jL<~;de5K#U{=-*27Ok{_kzY&JMSJe#{+TUJQy3RA zp|R>f)2c_`G;b8<&AWmCmg4@rkbvAZz3(=Y{qa%<5sF(pxIvq$2Z_ch`n~#rhe>8g z6L5(mgYL<%vb8JGeg7DhC{%~n{w;m${EGd&A+ z@r7jxVDrzVcF!As_`w zF^61dEg#Cw%ZPQ^5UHyH^yPp@LXu@3s7&sxWvP}+h_QK1*5s1Eg!?@@zLv0VD1~tD zow$drdjTy1gpaLP8ccK z-&D|y%ur@!n4XV#mjj`xOM_Mk0E7?WRw^)%HSbqx?sBxriA@9Kk1lCyprE`a37|Hh zSH{_$)O0Q?Me_f%&HM>hlXw`r5cISX{e*l!5obMMnCTdqz}Dj(7^!T7N^ECL4e>x; z3HDj46&5$_rySx{QsPhyk zi5SKp&=E*W?W!>LgGfNut4D?p5r|5h{M_{s}+(Jbb(j9N7?%uj~*P}Ds ze#Ry}CIpaRaICe@ZIZv>*i0Inq!HG*eeYkz9W6{Y*d79b%?6iFoJ%LLt?)DNg8fcj z*Pxb;LLNS4ABaTST?mI{a}U*hM3Un@`ITa1y7}{0DY;AQ1yG3i148`?aEqQ^`@8*N zTO-jKk>4FcF8OPJmxVW8Qfi^P^?PEdF_KTioKm{cv%}3o=yKYEez~4t7Z(>nz*J-- zV=?ZkPJ=RM*Lz|MT9(rlBUq{wEx*#GH&I>Cr|uV8)QlG>JYF`o>J`e zMNj{@dBir`vWwQ?N`8cpD+`*QHpkq_9l0JF&cWT|!4>x2#A-<{FHwAssqT78#eziE zHl^XYy_SXsRuO6JFt(rOw_~OQE5p|(3F!H6hF1Ege`$|m*te~l8xfrJju_45_Mlum z%WczPNl8rfN-QhzJ0=goHgsd2e@`m8hBe)mKcoH|@suQ!;LP{&&`?y9tU>-j_W~sk z+ikA1&{^Mht%5JP!Ki<~0hI5k>lT#27Zf9>m5v3TdS7dgwb*zxC;uO#qZ!y5ApYP? z##it-2t>WhTR~Cqe6#iJ?1YLRanW^bsL@^=a0c$X;}jm$TF)5#z5^_PHLW_4mw~WWR$iJv>!4 z%j8yVpjJ#!z^#3y3Mhw9K}5z~8VodFkuLgTE~ z?#LIpAgt{OmZJh+@9ce&B9q0GJWPS8Hp8-S#1~8OHKkcAL7@zo6Y7<-C$mH`FKzUF z=LN;qDF|$<|AZ%En^cm4eB`4+UDA9Qr7RoyVse2f&^>FnZA!I zXRm5c#_&dY!;09# zh}h%I*ebI0qctEEv^Y+!O9VRx3v9_fPd*=Yxu}xQB1#u5Ou8y;zO7ZVW3X?40ge@N z_mh<0Sr>GFM;{U}e|uP7_ZlA1Q#dD7zF36Y((Hm#+m8(Y{;urY-a_R~j0K$eM-`7k{h=Sc{=yuXy8&mjcz`Hbsx2 z-Q}i%lhTh8$GKRXZxd3KXY|>q1BiV_ROG*0T8dR5;i#W{Os-fVOF)5we>6CSlB#_$ z+@bWtm#%EWX@iYPAg%ag7lqwf^-QV(2PH)!M2a=Nfuhb~OzdWxCo{pa7j3KM)dC{@vx)u&DfXJ!w2w z12%0$&k$PXx%eB-3a1f|+*rv*E-0JYj%}E0T@rZ2W`0S+d?hdb`vACp3s2i8s%$FG zsgX7bytHPLre<655vk`Xxv$KtVdF9fZASqxU*dxp!KQEvvbJMux>LHKfim zS{Fh~%m~FU-EHI%ib;MK!CkSUq`w@O$^WBmMr44YN7Ze(P45$c zB@ySQb|Qp2Q=!~QZ49ZRMUI(NYp4hd)bkCvi_Z(r%oR~O7DoV8qTjJPf6aJLxeFIH zq>m+8H&VVHm1b5h7cIlU8^>Jthx-g-bN^ncTgfYRT5~?bcEI#~`**1W+UaGuX3BR2Zx zJR_Esmza?{J1<#mXNO%Xc7-&_A)Ap10>7`Okl`#{quP%A&9*D`vEZHmmzVJ#yxPfa&ckH#BCz~Lw8tITP} zxVFpgZXMM*t_%o;`>FYc-`0)?p`r|z)ctafdn-#Ap5kU!tK>_JH%%7r2w=A-T*ct> zZ%8IQWOO$a2!AO1)b$FnFA5Z&{m^jkGHZ zfe>4#?6l6wn+}QWI*Il!1woLLsTVB*#~8K85fG>uQ}uE3w-%HHl>vrI3i!Z)xa6L< zAk90$95a{m>1Zp;laGCttZ#Rghn%kGL*at%#7Fz|k;?bVzdpYmg{Vg`p)+AHSth68 zG?g1c%QiP|l|zd()HR&g9x0glBC|jS^-TH6PAzjDTAxWBD=e&NHgJ5AHIO!=)l#jJ z7(~t^D$1AoR>ptpsYs|lUMXhs@}+s4et4tzxp7S8vwV^5`T^GZFAQ^?b&}TG+>v0m(7OR|x7m z^p15x2;yhj&8S;0;>I*lVT@%DFn=bu&-%iRyt(PBO@FTBwY+W6M_x!$uhDR zJ5q^UtvAcGq;`mkpB7EfJH)9f5w%Fp>>j?Fdx%8N^CB)Znrea=p`KNB(x8f7m8w+m z!KeKZHq|E;V8XMQ$y~C1Yv0B~{IpUMAGDG_?~JD_6S!&K;kAioxKO(%^W#{yfgcVh z!Vs}tKzwyhFy#+YGnNCLplhZG_dZ1Hl>5|fVp>M;ZL`?Hc5?XAZ=fgjvZV>92i3`3 zgli!9omhC>0ShR%Tz;$pbM0&2@n;h7;jM`>YLpQ>zH>MITFFh-={Wz2D^4b;#x8z= zQTz1VNJQ11RHu-$=$c&Geu?V4MIFWFiOM*Cv~3HzU6`lWUPP1iH+@nyOf=n?67ag)Kk2%Fq3Ozm7wp9G2qt;NY<&so#3A# zTEXr?BKbxEZH#U$`489fDAog_z2JsdxS*)om}Qpj?>QDRi$&u&AibNhH$dBroeNF| zuaaUT^~Vy`_)nb0K3k!D<3b?o#krQsXe#lCl#oq<5d?IZJ6jx?nZl>FaCnEv5A1nR zJGxR4L0(V;Ex)FDabp3UzJmmw$Vgd5X-tgkNv|UXK^<~U2=Dj2?;rCFv>p0QQ__R5 z&%?rZ2bhaCY|hU?c^pS$6EjuKF>}K;m`&f6SHnH~vSd<}CN&tMoaHGCb0x58qRLgU zKhM!`_u#VD`ECw|WT$=MI#`u&7m2Kwz&`iO<-JcPSF?Z(BV$7!QHoDU<1=08 z88eYI`K$Wpy{Xu+Y?s~372nE@Hn%fd-bXIHF!}X zKO<{oh)Q5hn+!%qVaLMEh(EG%nRR`)0Rgx=8b1UPAwsYjH;v@a09$JS!FdyqKWH-% zHs#4HKRJH^<=Y)L&0DzA60|y5@s24p5+pdRlnBzmQ*&Eqq}s6*#_#=jMKe&;EmQDL zAIs?tN~DUDz_`Xrc%;`?Xn0PoKD6P)k zCjYSB-J_B~cETgtij{rWMWeSfv&z$6mr_ibHu@Z|=tnCNw%%MN@v58v-Y?tjkI$+7 zN&A5wgZxC&Uir;I6%^B!>R3jftz)s|-0k6fu!%3&J6PvzEz>fFQzgArAIERRB*yp~ zzfIfz7ihoQjCxo47Z7v%d7I|y*p?G5iPVL-FlyII(1wuZ;nq(jJT?KqJLW3Yf z#gCNHd#a&<(zxyszBjAx#c!4``9s?&QIyeDD($wX=#c2zcG(=PxeACam*mOtj_a3R zq99wooRRIfQ%~IkCf+DH6;vsn`ks303Rv>R^V2R4{3U2rUCB{66Kh-r_~eU4@*09M zGk-Zd5XxnXBB|*d4x()hE;3kd|K@-wi%kHLwF$O{u7>`4vgu zEQ{go$Z;ebON~F{i>psE%V#_DSFD}f+$UETz&tQN+7xn3{}K9ZTLw z*5S8psiRGAMg5XN>=WE83JE{j@bDk`H^Dcw`5qNt6YDm%D7FXplebRlP-tGdijG>b|CQMNYu66?(tb7J-`R-NbblA0|`)W>1$qe1Z0Zt%jW`kcqJ@ zW^BBp>~`H^y7n%sxw(hb!>|7&qv@n>jRR!U&*#cG%&2J%24h%)%|(0<)N_{B%BJnU z{?zH%^c~q+jVj>2#ukG%s1~HSRblYM(>O;ZI^-vEMMTewrjW|N{piJ#dHaPZ>|^9o z3{ck8B%Sa1=yAH3tgqAnBqjd;_JncFSsr=<>+7Mt;otK*zvg;IdPs&pKrsrlBZ$6Ae5Jri1J0PQxlA) z`Cw$qZ~^o#8R?3}MygxX&{A>r2lag#qH&o)`80C0sOOPl&SsujtCq(^YMM65JF#WY z!?6DNDYDB{KgAju? z&^Kq#g?^8wF;L_aKb#l>DqJoHR|9D^lc0Nc=N~!Iq$i?}ub4-W3Dt{X0nO5+P(XAr z$+nisCAH*TBszQH%GlsI7a*2LraJ!lYdIW``~GiNj0s-N7mqreZbwr3_4MLP{=WR? zFL1W`iH(Anza*Cj(6|@ZdvBvygr(E}(5Pf3w$6E*XkXpJCW_&@e0(O*jp|-hk@lgX zrR(dL`Ej1yEraeFeZCP-e!8R`aqqOCaa5zG&@! ze-C+GwM;D4VbqIx!_ZUmbnkIg2VPfMXug&x#Vl`jD728$SQ!`FqQKW|dl?cCqQTvj(BG4XqLeb3i z&wv=fd@hcH`9lH1mK7{k3l`NT?Z0Y~<%FWW?7UOm>_0-P{|$U%J2*ziB+?-KLP(!& zO|2zZ?Q2@G;#V?6T#l}3%~z|`;np$wR!fn3mSOovbTsZr?Dy9)o~&&osD!sqgnjD~ z<|Zc}B`}@SOM29;FE=} z(7DBKsY8@rldHvGD(B##yOXCZ=)>hNPbAh1x}oK~ANJV&LARz%^0`_R5ENv1#oVWJ z8C32&QeJD;JlxqsdvEP^YGV>HsWEkr9ge{GPUb(iUXQ#8eHA3>Pf|24*T^-MVv7qL zJY`H)GLqE0T91rqS2~9TDc6`r&JHlLJjepHwbSLdTtx)Hx{E&Wq{f2>xOQWAcyQZ? zKxWnMQ8mnD!Acl6Bu!CjWU6e`S38PKd+j=Ay8akJXSq78wJ}SH86`s?mxU6ga_RE) zF-j0wTfT84Fbt+)9M%EVh?xf>mu(aP6QP*d6QcI5lgc-$>N=e^YE1pyP6mVCRTP4H zEhI(p16^~SQ*i6=QeENZO-|)a`&(RSQ)+!{!HG|=Yr!~mQvVI}WF-KsiDHQRD{c-= zE@l?^kl-Qg8{}I$LQ*DQ|GibXZzJK{AuZp-K~aKcuQkIqB_?P>oI@4RxIUc}h0{jq z&bNl@bZ;%$xA=@2QOY*nW((Rhqc9bVwVL=3)y=p+dhh{>3$;V7x7v&&gY7F|qu$($ zCTDd4)#t0jlJX%`1}ef(d^YqcoocSOW@f6GqdUUxI-rZkfv^z$B|~fqTCDAi z!&FyKW}uxq(Q#KyrO9J=V9mr;oe8q`d(@S<%bHgPJBN(5O4$c8;ND-K!8pn21MjX> z1V@rg0?sub=O2Nsb37on_f8KSB_>YHMK7}%D<*~LIPDBxUswP#{tJAF{h~(L0eJ2a$U_!iU0$f~U9&g6kx4YsXOIQxR0&(=BQE0Dk&$CMcBx$e3pACDd+5 zR03bsaDDdvlmCUN8FEkQ7AiYju`vad1O7v)(p8PTqz!An&>b@kuFO)D4LCV+WGUY< zkgErrKclgvX*h*6P6T=_(~rZ$ucjV3`=fjys9{c~u!FSJ{rl6>`iBZZj;)^n^EJsI2{QB*avww|s0gw=V)?MM5OCB_dn(WRk5G(TnYT9(fa=v+D z0?l+Zn9T>b%W#Q`sI}4Jy`NI@a<^JOJ!;S{C!;Z$iE9>wd2zl@$o*rA&6UjXsTE9E zi&2Drci?^&Ou{Xh@bkM^ZLZ^N8R%3G3Ae97%%0KE29g`Q4_? z2xwh(%#&hUvDKPKid0R0ZDoF^5ZtW5g?&XjA(Q-CcGeJ-Xs3Q%Ec&>wv^mW{g2sU6 zwv9w0HmT`bdB$|qtU-+%Ce?O2j`oM^r=F!=rXc;BFJ<4ZZn=3AzR5i}p?C%`n#X6V z!|xj$n=P9w*EyOW(LBti+kS3tzR5w;J&7S`1w@hw1N1i|r~~X;0$X6K>L`CXr=v$B zWj=o3p1giu5X5uL{LvZbKQ6!B={Y4t^X84Z6dkv;Lg-i|GREsq3K_g|$yRe>W<&AR z5;O#*a@M(OrRZuT9~ZA=@tFySC2QyJqi&pyvOw}-5CX3XA;M@JQTf%KhQ zNE~kO_7oew*YIQivRnN&gdHNHeKSLv4Ieo1_YwL$MsPEK7K}0WU6doe2hn%u-9|s^ zOMy!(T)D!0xYp(YyW-p3&L9z$%<%T&6lo;<B9@g2g!9%fNY<-GyEJy;BYl4`xv$%^{mTcVXbfylnx&R=5FS7{myd- zC3z$a3l;`y+8ShEY#Oh(GEOlNdrVH~Zq=ade&=6$CF*MQ=?2j9wcfS8$)cpZIwyIy zNRk_S{d9I(Uz;#x*hjlkSPeq0nvTMSjB|Bd!fl6g)U41nauI$_$_;ScO#0llq|5h9 zQN>}k~GF*5mE4X}f%t@Li#=v?U>iqnozy8j#>##BLHNsy0shm0ugtzsT)(BT~@k zG99Vtv1nXm`29#+X{E{D0^F5vtz4O|Tkc$G!`NIVtCb}D>;-gkfwVWDq)Lb2yrl#{ zS<(Edxx{6wM581pO=E>bQ#5SJw^<93mqeQWTaM7+){Lg10UP|6VP-<%4wIk^ zpE%-J;=zIBLoSB$l(s_NIg#+*hZCx?!OX?CEEl$W1F`}4?>f(s?^gu>3NzHGE90MF ziRcQ=6W`#lKIG{;1V3&Fo(Mx;nJ$tmF)CcYg~S=9$GU!Nihm;|&l?zjPEGfxC(!gf z(kNQsQ(O4JYpVBf1}Kw#-V$DCLZJwh9C@B6J5AiJXpcKj-7eVvdvCZjO7^vRGZs=; z>&%Y-Z5rNx+HJv zZ5tDuv#jL(j7ve%1ErEB&1Fjd+{O?hwd%`saFhD!b`AUpbaR8HX@%zt9KE5|Pq_+QN&4?ciFxZ(6sudcZ3IqbcrtFR9Vi zeF#y9q>&MYKp4iGJjEUQv}+t+Yz7a<%OJDAIv1up-^mr1G5ZoGJhQeYR#mF$d-Gx} z+s$-~i}*!3xB0VN#h*R>4wsu8T3qZ+bn`UZW-Z~P190TtzQkL`jpZfM7erG*ZHIIDx3?_WGv7nNt&uCRK2BfAe}B(6EjZxavTT0T4qxm=kN_>E9Up`uqqEW z?1i@%FM=CLNQEdyu;0{-NxTqiGipOtwR4f;&P$hVCykEVdY^$18dH6 z$xkJj%Z+}Ldb5sx6O!7kW>` zST19_x0mqntmfg811mTe;a;9+A+)|SLXzPdcN^pGJ8fNGT(n)HUm2tE_g*fUsY_() zeF>lJ;~R^V#<2}(80H%yc1$nIv73P)Iz4ZCZN8%+<~6<4@bOVLycNBH>$sUGB!gu8 z2sK@nb4|5gnSZp~_JEgyrUaGo^{BSNea^G*9bP>@bli=O^2g5Rldmpwv^2a&dHR|wqird~zB?^j(sD8<&k?_QI#D25x2#oq+gdLR zuWEy0cvI&&8A=5FCq}N4(zzT(d%PwYXlYU@IaJGcDB$!ugI{c<2d>M&JI)c`tQ_fW zm#eeJH^-el^q&%T-aq`5IYgR&#X;(EF1;y@LgVMw>TzKgumC-^TuFLV{5hn3Z5qti zdHc}e^4weTuJzPkNaeg$R?qkZO{<|W#X5cctwAgZvLEbQ1U7o}yz4t>omM_~dTbGQstawvGuYoJ9SF?=p$!i_0sIQQ?Wgx8Z{^kYA#O>xq;#~9E!Dt+%Tg|}Uye_06-|}=~d?+J)fORPY z*%IgU-Gwhk6Y7PltO4aDh$L%Izv1zJ>hsKtGNVeytZ@7j2>k~rKaqeI9l*4FF zvEz8Dgmy2mGq`CffR~ytiY#h(R2_TPV`rwZ;{h?-B?g&*mm6K@IPuFdd}>pzu6igA zMPn@uaJ*{fMowZ#Q;i|vQ%I~1H7(I@o!i;nHEVDMrh~D{oC+3X6;>JajVXCQBcM?muMFr%AE_wuwaC zE3zK+8%sOpS~7mmbxVSCXy4ydSDGkY+dCHX$2S6u~ufoan8q{Yvc^I*5Tz$>9t2`%;bIZqi8O zJU}`?TW0&^V*k|*r$qRfyMY(Yz<^h?nTamVZ(VYkE@a}s0$k1-wo;FZKX%mdseo}L z9k3%Q=QDw?O?WX!jBKE1ii~FWqUTH1;Bv}XI5?a{%X0JJH-8C)%recfzX+*2?yU*r zORcr(MMS@pm&6bEH|F_ah0K{|xKn0>&}wi?_P z&N<$NZ_E4*Jkr@-@!#k1ExtTmUq`v9Iq4L^!IXG=a;>#!LD%Z#^D&=t*ASIP$9Q~H z7+ukKg=>0iKwu1Q?m9Td$fqrfs!htR21*g08%aRlKS&t8JLO=atDzC~%@%fZ4-vxA zH=3ha*wU2(Cq|Lkpv;GZKEP3mj3k(N<-rkrPV*juV9P3%jDduO1sobKUjEci~%v~h6_XR>%$!@@%CdaN?7kD#u;i=ITt?p z4KXVsI?MD3>9gwlgpP*45?-?r)i60~^_)kplCwBAEz;&YAP3s7VYS5Bsb1=R9V;N- zCHC?CH6qD*aEwqyAa>4T7T!D_%Ya$aH)N={DLF)u)&oyD$Tj2>38Ch&ANAm!%x4p@ z(d@vI0FaE4Dtd2VP@sw3>X>jXUx@uHf+(GQSPTNRHtiaSJ=bvWhP;CFV8zM4&*?;R z629D@9_)XNc3pqp*RtatL_|Xu_I*8=L;Oh6N3m-CVGbLQP&}b?+hWY~VUDi#7X{oK z+u(ctxf;l+Nes!MpNWZXt>xeWKOC?(&C&xRz}hla1UoRh=BvwK+7lcV% zIo7#k;4{D2kBw)c+ovY`A%ecFWuSq+Tdh*JgPCCzO+6y5d0aTE?8A42Y4w2FqVJTY z%MZY*QI~JS9VJh4iMUemdDrKE7g5F)ID>|Fn;)hdENowmkO^ z*ticC@LUL+VdKc8*dSU6IlXPKyrI*cab3tR?lJbm)A=A}-0~6{8Un~mgz$ALt`gbM8p?B|fN1G3FH z`tUA#*z-P^ap#sdB;MHtt(qnb@SuhqCJ+&y>m`v*G{|j{pNO`3Y&?aXg^YgYKJnL6 z?-T4b!RJc%Ps$2K|3QK?BKJ#D0&Xk5JEQAa>n72NQ5zu;<3`cI?w7-oN#%A-`+xvl zfW)r?c8+KopMF6@5|T`J0tWxJE9+ zr1CjVabZGha`em6bl<;Jk3@^H)17U6!D0wJmu*mYrjxzN_}XM}}oy~k3+ z?jmmtAS*!c0>eX6;KUzl7!~TvXf-&rT#dleAHa7?-dd{t+Y-CQ@fX#o)ZwB*K)Pz- z21kNq`KJ)^VW?uM0NXo&u{-ra4C&xgw|Iyv-KrsB>1UIcOZg9dW$aY314!fsSnr4j zD8hZ$hG}D>s5>PE)C4sFql{-C0CKas@d9&q6L1e$`D0Q%17iIzowo^5%t5H^Nz_&% z99rlv!_I?&C|Lw5mB^s#aF`Q%pQPr};x_L`Z(S*B91xmF@w8sa=m|#QOR95`2F%x_ zcs#6g8F8<+NMw^mOoX^-c}8Oc!2?^PTSNDx z$+`~7luP3>s-tR!-yAFzh+HP3L!oY%`!{p;VRYZT1M!VQRdx757Pihoau#aS$UAXd zq2HqC1*d6u5G>_Ek{A#UN0PXw*wdz&y$ghNyg5FOu3W$Mozn2^eqoN7PEt4a4wYb9$cR|>85pc91xgShmk zXuvbxh@XSV3_AP}ehoaGeGthUm9+3QJ=8xHV-BBd=SA|{H@<;(+xgk~vWX7o!v0(4 zDlO-oY*SIjMM8?zoC2X?ZpNx6<&i|fReesDg!FNw zz3Bwp!V(tf*<;Kfj|7-6lW%IRkH%~S%K$5Q{$={}?&Qd(34l3p^7pk`zFjr2$K&APi6X1D z>u`iFO=Kr_-oDuJW-`V2bbGrGEIW6cYS7VNITv0^(qCIS$7mD(LI-)4WEO$T?BKnj z0j1H%i(4kAQd6^tiduT1H)ZgBTl4r@wAT#OT*)-}(z0C2=o`iABlSJoO*`YKonY9{@!eT{hZGLsHSzQGz-zb2>IIzse0M6(rxs*Th zLi@q7FsGDZJo1T@Zkfk2b+(&Y%<9-5i-`LTx{8r)aR4M=4lmgm zhXRWc1hj(ww07EJ^sU@51|j-u%)6H&Zub!SqrN^oQ4qTP^<3LdLObadE#u3KS>kF< z6D$RNjN?jLiYL5AuwsU8epKGQM=ww?KyU31a}=)R41FrczTQP@o#i_djI!vU>sHxy zkqp|drb=BH5rkPXO-UY@MpYh~>i*P+^{J9kK?5AoQ94l0?I2MG9} z^z$s7(KRl=t!$&Sxouc2`%k$zE?GVAz7@qEGD6Mb_|m0UqkEw6fCekE zX;};>OH{EubjQq@@`{OERm0n}f0{$*A?kMZQC^24_o4Ta8%FUu2G)Ib-`y^{&NX_B z%K9@T7LPfaKeU>X`ZJxYu{K=$Bp{{Y30DTUwwqHKjj=*$An!K@Q`ew=i_DYSHHL}( z1Gx8MbR6ecSo7@s%`RDwte$^hwRKS$#RIFq>B*8S8Kw7yi1=$SmDMk9b4M*wqOLqU zr{K0~5U57tJDV}qeP`3n!YynSj2=)KYJl}Sh?>2`$n?`wJWA!9h0)nhhDzcYq}^P- z=!>@S=W5zk1z{t>rWy-P&I^rUa}(F7ulJ1T{TZ3|IG)Xk zSc&21jaZGX>;)7hG{z1I`p%FW&u&UE4wve;w_(lNc@Go?nSciRnv)F^j{v})FG6A@ z!sj?do^9_agiGu`1z`iO>V+J!t)I9jamYIL>N8x9FiZsFsGc@O7MON5^ubDL@h_&# zZWR3$mUkm{5@4OXVXkk4=9%O=_KJsM?7->P{_F3r&-OBB5?^)*Wjve4Jr@o%4K(y6 zJKXc^2)`R6>+NyF*t|hOV0}(`WJf$rog+9cl>?<(S*6}Pj1Rcx^8ZqQm+OshA0vq$ z$i<54<}Q{kXnFO*5xOw3KGNloh{qbLPT;&BX&z)h62#Sxs!`4P?KdL;nm7B z-wd`y47^s$4E=f}`%w7XY})Nl%5%M-Wg0WoaU|$?;@suktFpZtuf4{%BzSbfXI>iL z1{LAV?tifQP2`UTOPQnI<i zEC^!?-ZIdW{8ozT#NSkF)1%aK3by=vccF=QYzr+0D`963w+~9Fc*-vCps(u_qPRyT z_$QZ!JOmO3@Q`PTQ7|$vGhbp89nW@Wktn((5k*6X&{>jJs{C#?SRA@`Io4J>#jPm0 zU(Q-r{o=Vi$$ab7t$1Xkba(GlvmrsQGgi4uj^Q6e@EJYSUZs;Z3zhZ|63P~czjD3B z)3Z{Q+|rCwwPe?NqQ;$Cw;Gxop@ep*W~tFQ>dJjF%6*u{ML?B`_J$ioT|-#IT5}6N zuFifkO=+3&yc*Zf{+cLMES0t4aOL$^r?-E(S{DR0|CbeAmK# z>pUMUPSsXFd&a^!hH$A)vc_+UCW>Fi?!-Gj{xl5d!q9+9g+PPEIMoeJ<0{E9e7&E6 z%{7wMX5I(dAQI|7FE;;%;6(C0hmp=7yv@`4k{7d8kAm153#4+MD|z#=f2DY` zpN5{`>S!RZxJX2jFy+Nlv{YgoO<`*I++6Kc*nkjK8q6^ZBhD^;a~ATek#V?hI&LxL zn65%`((6AAe7p_gTS7oL4^U*HGGaJH*kJ`tRURF(EmV7o6I(`t(Bi!-SX zxKeZ0lO>4}L47DN>@D$6d3c7cK~*#7kJI;hDCl?zG;(u3ddPB$PYuC4Xns4hpS*zH zKgv+IoTsd|y6Dhh{1+6ED~9QBNITLd?YF(`Jl3zaY}|we9fi>LZEbdH`iR>kDX%k# zrUOsu%@Kc{a%D|9r*d$P+j22a-CYfqopVxi10y4B1IH14%npaZE3$gJ$!n(N1b3*Z?oV~qCNE(LwrNblmFJu{TKEJq)dYF zl{RbEH{xi5zgA5#LN)>K;^3dI_%8NC{n#!+YMs#oy7iFMR>8M0R*qB(_}+N|#UA`3 zYyk3O9v)z1d>A6|qMZkawNuc|XYz=L^}+Y^O@lN!n6+yAqcG#5KwtLe>s|dSM|d}h zBlr_yHkX3U{(5y45_xUh;8VE+V85zC)AUR}=MuR&QF_hlyxvHHH4p^!sQZy3<}<`i`$|SJy7mU8P=k`=xKAn50@$=n57usBt z^NyZuSFrUzRPcsviKRULFkT=(+3afjun`{a{seB+|zx@N#LSJ(UP$NOKbO(e;avBI%D{#Z)LwY+oZk);SFvVROcrULspza17X%}_G!s+?_z&b^e zTpfM6DgBk9|JBJ>F0jLxdRGXVYr4n$%x3sjmBMZiJo>!s=a(z+Jk2l8JD(bea|5hp zeHb|FNY?3Jvbuzr(x0?sHqo1qjA)?gv6Y{^4MdJkESBSiit0daqN5}6z;qK~7_6D< z?8dqe4}+6Ne<)qSkCm|fP5uW-%%b`9v(@d;h^{=YI}l%KTE{Ue7?o%vkmqlqd7RcO zSo??X+o-sFc_8B>?+oCNC}04S@lp+>F=~o*riljFR}o;YBTtQacEDb*4}s06|9)DM zT=M~P#nmjG{!5o0S?liiWOZ()%6PKH-4Q_fnN^c_rpii{awRpZ16y9jO-cRd@p^RN z^Yw#)r(J(M&nx-~^eu{z%R$r66$(i$L4h~R=Cp_}Q7JZpnR7I90LlO71*{JUI_q%S z>Fggb2qXX0a5kx~Uu-p7tyJ>_>r1Qm^_d5-`!xV z67kq%L`()VT4)6g=AG_LPw!N;m#_9jYzm`uQ~o>pZ-~@Mzzf3GE$SX?;*ZpmB)3H; zClISK8#)1Y1q|kUTMb{Guqq_`O!-cc7wFE^eOo`4FQ>f=ZeeSklKb~v8a102Bw%rqUhwdoo^!JhcivX3%UJw{=N8ja+bGJu(hMkzrRbEqERB zS##junTRZs14_S`LbsFuhiqWVJwf5tk+~E$1th=ZePJ{%lg1ZHiSQ4r-C-qaWm^56 zL)y(WU_7<-KOQHlX| zq*TDHNYh{K{B4pSE!^K7EOoMvp8Mfuzt)%sZ@!c57 zL-7xqOy}^q|FbVZtmDJ5c+aM){~bYW#ly=h3dWxq|Ls5?=<)W!TqG>-KE^1I3A{|Fb$YvDC z(sp5l!=&-5u-Rqo-x@&N5YCCFjtfpv;sZ_nmgD+DIy2LGd8mnlz1XnP{? z)Pell`3HSrkxH?0iE@58G9F6?k^Xa_hi9-ZRIc}IZ$7h#+j(21^{|&ntI;9fEk(j= zE#_~3`3IN(rZT?Y36jBN@bBP6qWcQ%`trG2i(CM1ZbZj#>?d662AeRO1%d%+Q4tQ| z#RRa>q7aA#kSzOPpCXqSbQt)(I|@ZIseYx|`UeC4>m#8uPcnmq`CX693$Hz^jC!0p zk?0E9bEAkkTNU$$mD%bOTCbrruI-;+185bqc9~{VcD>K&OHc-qm3oj(RltK5 z3_1<5(LzU+kV-gN&SP&Ydc_i5u_( zYm=Qu1kWGLD$AMG3p~I*3&J2;cbidpPFI@_Wc&;+Qp=sY^k}f<$#m|OX--sQTF^l_ zdh@CMO>XtoA1wPrmw~7X0R}Xer+ZWHnCzo{oZK7ft?x}nT2Qyc{hEq)wH}p(PX(~{ zPQD`@KqZfIg{rnpzg@3PyWR!YI)w}R9#llyP#95et)~d=hAComM4|BOXBo?XiTxjc zOi*A>@IVVf`bT9~f_ysr3aPn(@ND-}#W;o04EyCm1*UaFBwH>(G`r!pi=aOuhu5dFJ>VpN5T=J|2nR#w&{NnE0z&)S@mL5 zf5#a@a9V3U?~+_rt6Hk&u@Z#mP~r=~;_(7)9lFgf&T7_pS^AO*lEV1`FXn{f0iSZKjc=zZi}iGQ<})<@IEqVN}Ke%J2YU z+5Z0&CQd(J9_uOhMC}ik;i?KI^R*TU;n?)?TUYGvIhtToObBTq1z0}gwGvQb7z-3I?ZV)#Ss{_!;L*{hhd<%>}J{xB1NjJE&%gZ+O$ zj?-L23+^#9k@_!E{PE}Sn0l7DWE#kjU~Px~W1IhY9bo)K;=`;jtq1^aj?hj7{|~$3F3T?R#f%DjMk?6yZI6idC$OZa5&!QQBPw8i}u^IA?52=+849Rg8aMIw}+b^B#tL5O~sxl znGR$2n$>CI8XC7d*;?QmPaeDw5|7FsNxbqB;oZ1LF1s_uw(Z*aiKRX`w~X!(CBEB< zwd1<{X^4A-O7jZpTnmkceudzYy1Kq5ouP5?T7kUw$@d&nz)ja!!VUC0j_`_KV>71Z zbD7Zf(H<;KS$mvD$)xe!Qr*@&m;OlRmlJH(OIY9GaT#z4{M*p^bw9-Ehi@HgC4uk_ zyPeDCF_k`rM|ZYq*fMP8^(b+%TB656WRm`o=~zG;T|VR(GJ~TptwSxuFF|& zUzn?aKE$PLZcM^a_JGy1_e(d__0sZr5zVWN`(Cu3%)u|X?L6Tb`TP(t_{BhSrluz% zh_ofAk}5bkHoF(T5(}V<^1ghUA@RXu{hG{o^y#G5PDLFN#1M$3#(#~%WuE5z8yvYu zJtPR$y+$X1ivOz(BK}C^(wXlM3C(9WdT5v4RFqHu{(9ZqXR3)aTecY-qjs)MIyq%M z|K3}5dobaoS5$aarPc)9!>xWA~A4WTy4*YBC^utyy&d{pL^b&}; zyfEII zUYPAWUA-g;k=O!vDRD_Y^4b7Q|RvAxMsx!GlF;=SzlFD&B2?EbfovX1TffNlPEq(g32d{l z0kO&UI5DfUTzD5$jm|mhQ6I*m2S2EPcokz?TxUJnw3r22cdf-9!O75-4z?mOCt&vKDS-Fj7i=_PG zdrc>k;IjETAQJv~(@z&@>8hocr<0uc5j=^;sNSqV>d`N%P$axFm{46fKJ`yX;RpYa z*Z9416judoP_SmD&|i5ID^Ls>vh}Je?~t`Tz^X6x-U(*YZM#8q-HR8}Zh4zLv7d8F zbZ1Y7Rp~Q5oXOJfZi78vDZqE!Qm{%9>aaPq=QKi+Iad2SU?@#^YAZJ;8PV|27lG_c z3C_sq-F0&R=YcYFb0h8E@&uD`YYo=37VA$y#PLHjkD`QkT0ur40(&ap+(k8}oOv}I zO?~@@vCir;#>TFD^!npUzf%vl(NC_XlH`IBt>1IyntNXI_@^dWVCBHg^xUQQ%{$k8 zeuQ`yy(;-*ycWnw4Tqh35fy5o?b!}T_6)vIP0ec3p&8_w+<*KObu^$#-35T^!vG>V(PA&%(cs&QIt^SYa{kyj=rI`U> zn(I)=Y477e=MjN{CbBZ^zz&Y2*7s{3#lAIw)~@h1pA@q-4<9ah-`D(5`v|RmZA9Se z9m05eoz~9j0eMc>mTx*6ECB(MKtv@Pfn#Lsmnr33B-Rv*m#-azkZ~YgB}{@m%D!#2 za>Do3lIDr+%7{##=RN911?ydvS16m;Dpp7dp-|k6c8>gZ(aQ6ac!uskI(oWp@B(o_ z)kUYq1=fCpmxwQfbRlC`N!?%tpEdWLx1rm+FzFS&cIAbq##{$^S*QETbO`^juKLpq8cmN) zhoT){S$4SS)9=r3HdhWw0(g-&xW`JTDp;Au7YRA!Ntz%PW%J<1Yh;@|h%Is+wd~8- zcuoovT}BJ_5+8U=_9;T--q!KPF`KK~i;bRsA>~;3-Hu=9 zAM1<&_@n-yWZCk~4^fwx_3MYg#t$AV6noxIb7!_JXj^}F-1=tLgxgk4idEQE|E;<* zd%Docg&e7;7eqU|^!fF5{@cB5t>OgYT4rh!Evn8+Z5@8*=7DA@JbBl(%ozNq9 zI&W)PXEAQJ`NH!=DP-IKShiSU?*|`ewEgY%zFBg{N`i#k=}>)XhAFk0fd+S$QzskW zdfu8!u9kZ;`4dA(F4G_QGHd`c|F;-PHlO-}cra4}+I8S}I=re)T$>}rS zE}AMAEH&KeEu1LRQ7dnLwm7c6h_J2Qh^b=<`+i6hGe$GX`YuxoN4FaLUsNB!-~b^l zL-{ivMxsTh2TwLN`1i(m>8zK6$Et08?9y-7pO=%&dZ$4W?C}iyoSfBJhky_qe9#i;FV#XD!@AqmRV=!S_2#;8JwazfzMIXK zYpbjf{fx2<7GtO&%9mC(2jdM>_xM9TQA0EEekNZ-e@r7hpVGLg`jEy0TFjsEd%bMR z%NIT6F&aMDhCf#du_W5|6Vi3M@9H|)JsAD!(KRhwl_POFLB&(LKAD`4Nk-;*q`I)M zuemqV)}?vnZrL0gWaQ^hfeWgmP+TleQrF$+m9wgUrhYaNIh)p0^}eIK6+jCsCVo}FQxwW|K@{@w;A*Bjg^$d}E4vtcwhL}ZP zC91`=U7@wPS;6RUTG5ud-lf4FyB(x9H&vj0OfRDP?Z0y$v8p-tsXiLu= z*t=PLy@&P=+Qai^1WWO?BxBqCcO=HoZ$hmn?#Durw#RbY!8Y?y*vlAi$4@2df{OF5 zyYG@o(RfQauEL*g{9=PUPjTHiJSyPXzQvB~Z#KSiN7JX$kOOR)-<8Mc2UXCh8e`iv zJ^Fm7mj~SR-~=?mJXuI$obI{()MxCgvlXd`$%5n7VZPxZ5=X6~*c$3L(x#;NWKSa| zwYXR(4$Ps8;!Gy;u3H3=31gKuT(`~c5e*yYt2bUh74^ybDA*U=<@guu9p`^KUvz(& zcD`;6fB+|n%s7TRAu+3gLiIe(^vow^mo(oe^Xz@ysu6N2%y8RaUH767+>xn+8(QsZ)qK7p%I0_y%hp9bHJX_U+`3lY^SL)l{h}OW}88gnS26 zxzi_y`(~3ROA=(vH=W**mXkSXQm@aMyAvR^;Ht2;!X?KmXh`uBm0I= zyYb06pz8vM@jcn3o&I8@3Y>{$s0H5jL?z_=(HK-M^pYkE|ds+pI<6LXy`tSRTgmHHOm+;Wv)Y1EEfyV#8f$r)-R%6@a+pr5{*H`CvU)+S)IpB{ZwSEK zr%92bB$iZDRu8gT3`2SeyR$t;`BNzp3fwQ zg7%bU^JX@>JFq!=0?_94P35u+=D1j$kf`jAbuY(lzh2lhcnoK7s)XbtYAls&#)&0yIjsvuc&>> z=I7@vGG5DWYwh|VqkZOEr_YXML*WOcJ044G*Ur9jzMw<}mazD=mGSd%tcGL?ZmG~Z zUTzmC#SI0nu}NjuE>y*4Th1kBVU7cKRvIWuTLos4$O9`INIsXLQdK6Sr|>B@Z5eL$ z>E|JM%9<)BZ|l-6jLI~%zBi(Hn@*=Ys@qf;adMwZk)VuzqIQoV;8v&+@^a2R%tkF`qT5e1-(wXAXt09g?cV6W2XbGFe$F7x`_Y zc1cjzc_69`Qozj} z|B?R|!kDovCfe`0)##~O+&TNzT|!-S&||k)Ju@Y^GH`ON%e%RF-dQ~;x+~|y1poNt z-iDNu_cd+PM#+GV71+-8{ajvI0kdbJN#4R1sA`djUwVC*mx{X9j@V!NGD2%>DJnff zmDmUoH@dZ{&Tem<)u=1ZD)%@Fjjy!Ru7kPMh{zcuWao2rlrF!99fcYy8H8?PBwM}0 z-ZDtT8ymh$akFI`v^&P|eOU5`z{zhxk$`M6oNCE#hLc{Fq4#B(0!dQH-(-6Wx^79Tarlcxj!ESA1MNdqFpNWV^97TL`sdd)_5y zRvp(%1-8#d25n{mg%^k?y0kvNLkt#C*BYFIEoIiPwE)T2meNyLYbks-u_bDA)`^7l zV73?ArVE(4Xc+sS;A9()?{6$K`CNAj4-?EoKsRZeps&;Vzmv;Loj^Oh(0!g8s=79L z4_{HcA5Bk{R~9-gAg8;i2x_*>-c2f3J5=-}JZDzo_6x0Jp|1Hj`!Z6*@zz6<)-SW# zK=;~n4Vsl4Kj2(ODr{U2y^*HTB(1IxfD;tT0Ex>7Y+k3E`#xN2h$8=^UPVsMW_qKirN>PD6YoCVs|F$TizZzV*x8 zhin>9$LH|s+^FX#yn5YpeVgUwM+$Y#F|Z?0y&}ubcaiy)vxJJx*@bmYr$+RQys;wl`W}jD&;M!;vC~plVN(_eD$3NL@W8)71))|)h0FAukJDp4bJrq<0z8XQNEKsQL&We z)*X~r5ouucJxgNRRFa<8EAwkCMg7WtsaI=FKZ=~^AR~DLd@^W|mxt8=V)@vf2~@0r zn*U$OcPtis(;_R7g`b?Bj|G|L50uEZ&Phw@e!l962&qD<$wR}HZSW(lZCBZYEmlG; z_S#wyq$~LOO+BC9kp`qZEWnH2%*TlueTe4Vz;LopALXH#c3Bmeu9hyTyc4|jK6DbT zt#2xGw@ zz$!ND-YUH@toaPjIlwR+RMv~bOiRVMy*XtqB}D!-ym6YkDY;$1pEUvC_>c`}h&G&) zX4yAb6I<+g^aylvU(Ht91p)&s{i6mdahudQBOccuHBKX2i*aEFYEV`+_b9|At8SYfLnEiIb>*m^|ELcKGejcVk~3d?2;&1C@KY` zFR?|i&Hv^pk4@%o5$$dlhu?M7mRfMOyjGFn`GC;NwXIv&BiCl10~wVf-FP!VUOu1o zVE>q1h4SeT+A*q`sKmG3H{ZCP7q||JCeH2Eo$Qe5Fo8XsOPZ+B7uVU9t*D@@;WWn1 z-7BMgeICMvV_Xz*@p+g;YQC|^Z`ixJK^(R_9PeUKy_m5%UX()8CRu01v7he`HaYw5 z#9!&2%x>!Q+aG+oJ)5*$QXCh$#&!;o2)Az0`KElnJ60$;#QvjBG-<5wLN~z)0MkB9 z0Y#JBiQi)OgAu%0aAt$a(gtj1T6Rt~e4^3_Mqqn1w_S;_Zp?`GBp~Rxh-$vuUa0DD zQ<4PFYR}6YCreY&N_&^1G5yNHS=DTNrR8B;Ui;g!7^11XmZltW)iJ6e&?=zt@ty9+ zS#oDoG(lExFjG6amjDSqZN9l>}` zLceeldNM(Rd2R}^N%p3jEWr*HSxM45Jc+?oD@$5T#jvA2er4R;(lqfkOoftZfVt|# z&1V_ksCTlQI@8DKK;YmVYw-@3#fY1Lb&H@XAukO+zdx(-HI%McmbcipetEVtdGI8t z(akWD^Onk@-8;WzJ)gqczoGRIR9C2%2=$OnW9M`e%3;!=6g;d}0TrG6X2v{Ea%(U* z0Uhc{xkO_0n*mi$Q;q`@9su{RM$*2OB+teoFIQZ%=@6%U+JT_{Ns=pH`82;bS-L_1 z+sk#qy916tU$1W25X~^}Gz|05XdluaZ2E<=Fxnc%&8$2iz;@(T;pMUJRSU7AR zSEgXP={rinAFhruR9%VclyC49l8&n;%h<{*+!CykWw*bU+|D}MNR=PB@`aUyz2e+i zU-mnWu+5V-L>m-v!Ws{ZdSQB2>h}t7mc_b~t!PGIrdGgH(e7p_MtUUb`HZTdqSlq} zw|Inw{eovqYZk{44r7*|C*9l%v`;)*X?gfc36MKFHWi3SF-6g3N~WN(Mz^$yLdPcF z0@stViT#T&!4$woDzj?(zQ@K*H!=Jhh(j4C8PNhq?~YJj0`iQqn}eqBDuZBz6EC1M zmDemJPbb*i zHRJYhnhz+id6ogL%tz<4)NwzcFWYi@2k5_WAfUjQC*5Cqugj-LfH`m1QR<_)8EY{9 z0E}M#5HF60eRF0DZIKw(vf+Sr!|ma|5;j;aRp6x1BUbxJjZA@3JaC7uhMw5GbW^0~ zW}4C8|HJLs$$qg-W^Qvlt+rKjt)aSncHJxNin5Eg>%6pVX`8|I4QA0Zjg4qF1wxK@ z)V5!MIt4Yph?Sh&+c(5zn)`f1S@kbX5*sdK(B5;UKd*|qTWhcT2iF(*7>E7AV-)&7n3-S1Z|5 z3U_CoL2Vy%cTn@CEo=H2C7$Uhd-3}HwOxI%4qK|S@t?VbqGdj_nr;AO(4mI8B17KJ9r6>|=)pqj! z@(l@2)*lk-k#5%=0Shv9a42=ISuZ|@pQY{-QO?JD`iF=O($AB1th(9N z9r&k#Duo~4ZPwKz80G9c)^gu8Dnf8I&fV=}P`}ljLx(e_j?^q5*YOp?i`>Rca{#92 zw>+ET6X={f!-zfEJqo7^loINd?(Ob2n{IxP&Q%)bI%+pxgI_e=7J$Dt=y~SOfNgG< z_<)nE%dWQSowoR0Yv@OI0@u9HdaRqS=H@wZ88Pe$aHcoOTE8YJ%2t`ZEd-wuahE9M z5@k56X(3?(rB;p8w8h`u*x@lqc>CU{17M`wES0hdRz$gi$^lJ(!HXFb58o*<@4NN- zub}d{(`z?}(Qa;b*`$g&<@TE^saTaFi zp}@{(xJNi&3pNKFk+}}8TwT?$d7AjHLx7;JFnhkc$MV>VYOS^>4LAXkp(4yycuU8X z9@x=A!;=FzuR(bG`->`6zt6v(14#SI)Dgu!zqFh%0gk#DMtOkD{vIy8uP&Q}6tPbz z);K#8__lp{Za)ssNwM9Wr2V0kf;F1J03MBvncgr?zdN=)7(+O;8gulUkzC1FoJ{ij zc{o0}ED`G}yk3tw{iA6zr}?Xq^&1TYP=00S$9avpdN=ZogVpCS7NaR5BCGirofxq3 ztfufL-( z!JZ$l+Cn(|OjQMp^L@zLt+rnkukwmU2#v zw=9rl>IPoEL~%Vh!22{goV-YaiD;|2HDDbhH`2l)?<-0fY$`cLcuNJ-oiUv!1eaeZ z1#g+KNg01{66h&l9Oc|qvmYh$;vwBYSfR_cz?zR2o!sVx^(25{HJ~V=C|9}?AZd8g za^9k{1zG-@h~N>(MruUg5HYpKRHi|5%gv9zJlsloasEj=-$mX(#D}!Da%{D1w@OO7 zUYG^dL)T*iI>C}#FF@E}e#MnL1RC1XoB1z)1d8XPqJ>X)FjZ&YQEQ+cqml(mTgQ8hes^%y}djM74$>bqL?ddv7 zmDF}=(5?}_88kIM@kfJZH;_TKTT+m*nSLA90WHAUon^q@e3ChEt9Q4JE?qWN*8Qzp zO>nfzR_U)Sz~xrn={s~mheq@`St%45NNXl7ZRjb!+YRO_`9`yXZh+I^zuc9)TItg# z=DCt*4>0NpFA@oq(5uZ4eX8Hb9W`+`C;7GFID95J)_1b5eg^;<7X((Imy?}J_B6Cb zlV5<2h_~OD>9-0iszUh%Y{RUFJf5mqGMd8^)U{qrwdPM$NNsPOQTANL(7;Y5gD|{e zCfz-fYBW$KYiQSW^f#AKXfV-Y+oUNS#CQAG`8)C3+bv0t7cF3mZMe*Qs zDAbg(m!8?wc9Dhp)St38R_0xKSuHn7cZ`u9M&tRmJc+FLW#ZODrtH2BlxztkIx3j( z6fqDC#W8H(q}KV+WxOy3Jr|ZSCEBMalsps4;?6MDUHG=TyB62{^nF&lLbKKRO!XXI z_V>w%fWvaGD;VRzZ&CNG�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 Pq~C3IeYG;!gV6s12 Date: Thu, 3 Apr 2025 00:27:43 +0000 Subject: [PATCH 07/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- README_MLA.md | 6 +-- config_hub/pretrain/cfg.yaml | 20 ++++----- litgpt/__main__.py | 3 +- litgpt/model.py | 81 ++++++++++++++++-------------------- litgpt/pretrain.py | 2 +- 5 files changed, 49 insertions(+), 63 deletions(-) diff --git a/README_MLA.md b/README_MLA.md index b4aa260719..01ef90c310 100644 --- a/README_MLA.md +++ b/README_MLA.md @@ -35,13 +35,13 @@ Overall, results are not as significant as expected due to the small scale of th ## Notes - Pythia was used as model for the experiments because it comes with many versions at different scales. -- `pythia-160m` (160M parameters) was the largest model that could be trained on a single GPU with 16GB memory. +- `pythia-160m` (160M parameters) was the largest model that could be trained on a single GPU with 16GB memory. - For the same reason, the `tinystories` dataset was used for the experiments and the models were trained for only 100M tokens (~10k steps). - Experiments on larger models, bigger datasets, and longer training are expected to further highlight the benefits of the MLA block. - All the tested implementations use FlashAttention (as implemented in torch) by default. - The resulting implementation of MLA depends on the `litgpt` codebase (especially the `CausalSelfAttention` class). - The implementation of the MLA block is based on the DeepSeekV2 paper and includes support for KV caching (`KVCacheCompressed`) and decoupled RoPE (`apply_rope_mla`). -- A further improvement would be to optimize the implementation for speed and memory usage (for example, by merging matrices at inference like in LoRA). +- A further improvement would be to optimize the implementation for speed and memory usage (for example, by merging matrices at inference like in LoRA). > Fortunately, due to the associative law of matrix multiplication, we can absorb $π‘Š^{π‘ˆπΎ}$ into $π‘Š^{π‘ˆπ‘„}$ , and $π‘Š^{π‘ˆπ‘‰}$ into $π‘Š^{𝑂}$. Therefore, we do not need to compute keys and values out for each query. Through this optimization, we avoid the computational overhead for recomputing $k^C_t$ and $v^𝐢_𝑑$ during inference. Unfortunately, this was not implemented due to time constraints. @@ -49,4 +49,4 @@ Overall, results are not as significant as expected due to the small scale of th ## Visual Representation The visual representation of the MLA block with my implementation notes is as follows: -![MLA Block](./mla.png) \ No newline at end of file +![MLA Block](./mla.png) diff --git a/config_hub/pretrain/cfg.yaml b/config_hub/pretrain/cfg.yaml index 404f5d025d..961658e57c 100644 --- a/config_hub/pretrain/cfg.yaml +++ b/config_hub/pretrain/cfg.yaml @@ -1,4 +1,3 @@ - # The name of the model to pretrain. Choose from names in ``litgpt.config``. Mutually exclusive with # ``model_config``. (type: Optional[str], default: null) model_name: pythia-160m @@ -7,7 +6,7 @@ model_name: pythia-160m # ``model_config``. (type: Optional[Config], default: null) model_config: name: pythia-160m - hf_config: + hf_config: org: EleutherAI name: pythia-160m block_size: 2048 @@ -17,14 +16,13 @@ model_config: padding_multiple: 128 norm_class_name: LayerNorm norm_qk: false - + #Β Wether to use latent attention (MLA). (type: bool, default: false) latent_attention: true - # Whether to use MQA (head_size = 1), MLA (1 < head_size < n_head), or MHA (head_size = n_head). + # Whether to use MQA (head_size = 1), MLA (1 < head_size < n_head), or MHA (head_size = n_head). #Β Not compatible with latent_attention. n_query_groups: 12 - # Directory in which to save checkpoints and logs. If running in a Lightning Studio Job, look for it in # /teamspace/jobs//share. (type: , default: out/pretrain) out_dir: out/pretrain/mla @@ -47,7 +45,6 @@ data: TinyStories # Training-related arguments. See ``litgpt.args.TrainArgs`` for details train: - # Number of optimizer steps between saving checkpoints (type: Optional[int], default: 1000) save_interval: 1000 @@ -86,7 +83,6 @@ train: # Evaluation-related arguments. See ``litgpt.args.EvalArgs`` for details eval: - # Number of optimizer steps between evaluation calls (type: int, default: 1000) interval: 1000 @@ -104,17 +100,15 @@ eval: # Optimizer-related arguments optimizer: - class_path: torch.optim.AdamW - + init_args: - # (type: float, default: 0.001) lr: 6e-4 - + # (type: float, default: 0.01) weight_decay: 0.1 - + # (type: tuple, default: (0.9,0.999)) betas: - 0.9 @@ -134,4 +128,4 @@ tokenizer_dir: checkpoints/EleutherAI/pythia-160m logger_name: tensorboard # The random seed to use for reproducibility. (type: int, default: 42) -seed: 42 \ No newline at end of file +seed: 42 diff --git a/litgpt/__main__.py b/litgpt/__main__.py index 882e225e6e..7e2b2dd46a 100644 --- a/litgpt/__main__.py +++ b/litgpt/__main__.py @@ -3,6 +3,7 @@ import warnings import torch +import torch._dynamo # fallback to eager mode if torchscript fails from jsonargparse import CLI, set_config_read_mode, set_docstring_parse_options from litgpt.chat.base import main as chat_fn @@ -28,9 +29,9 @@ from litgpt.scripts.download import download_from_hub as download_fn from litgpt.scripts.merge_lora import merge_lora as merge_lora_fn -import torch._dynamo # fallback to eager mode if torchscript fails torch._dynamo.config.suppress_errors = True + def main() -> None: parser_data = { "download": download_fn, diff --git a/litgpt/model.py b/litgpt/model.py index 2269aaafc9..1a51e1118d 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -502,27 +502,32 @@ class MLA(nn.Module): """ Multi-Head Latent Attention (MLA) block from DeepSeekV2 https://arxiv.org/abs/2405.04434 """ + def __init__(self, config: Config, block_idx: int) -> None: super().__init__() - + # key-value (2/3) and query (1/2) projection dimensions self.q_proj_dim = config.n_embd // 2 self.kv_proj_dim = 2 * config.n_embd // 3 # qk channel division for RoPE (50%-50%) self.qk_rope_dim = config.head_size // 2 - self.qk_nope_dim = config.head_size // 2 # no positional embedding + self.qk_nope_dim = config.head_size // 2 # no positional embedding # q projections (bottleneck) - self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) # down-projection - self.uq = nn.Linear(self.q_proj_dim, config.n_embd, bias=False) # up-projection + self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) # down-projection + self.uq = nn.Linear(self.q_proj_dim, config.n_embd, bias=False) # up-projection # kv projections - self.dkv = nn.Linear(config.n_embd, self.kv_proj_dim + self.qk_rope_dim, bias=False) # latent dimension for kv + shared key for RoPE - self.ukv = nn.Linear(self.kv_proj_dim, config.n_embd + (config.n_head * self.qk_nope_dim), bias=False) # up-projection only for LoRA part + self.dkv = nn.Linear( + config.n_embd, self.kv_proj_dim + self.qk_rope_dim, bias=False + ) # latent dimension for kv + shared key for RoPE + self.ukv = nn.Linear( + self.kv_proj_dim, config.n_embd + (config.n_head * self.qk_nope_dim), bias=False + ) # up-projection only for LoRA part # output projection - self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False) # unchanged + self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False) # unchanged # cache is disabled by default self.kv_cache: Optional[KVCacheCompressed] = None @@ -536,7 +541,7 @@ def __init__(self, config: Config, block_idx: int) -> None: # configuration self.config = config - + def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor: """ Applies RoPE transform to `x`. Note that `cos`, `sin` need to have a batch @@ -555,8 +560,8 @@ def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) if cos.shape != sin.shape: raise ValueError(f"cos, sin must have same shape, but cos.shape={cos.shape}, sin.shape={sin.shape}") head_size_half = x.size(-1) // 2 - x1 = x[..., : head_size_half] # (B, ..., T, head_size/2) - x2 = x[..., head_size_half :] # (B, ..., T, head_size/2) + x1 = x[..., :head_size_half] # (B, ..., T, head_size/2) + x2 = x[..., head_size_half:] # (B, ..., T, head_size/2) rotated = torch.cat((-x2, x1), dim=-1) # (B, ..., T, head_size) dims_diff = x.dim() - cos.dim() if dims_diff > 0: @@ -592,61 +597,51 @@ def forward( if self.norm_q: latent_q = self.norm_q(latent_q) q = self.uq(latent_q) - q = q.view(B, T, self.config.n_head, self.config.head_size) # (B, T, nh_q, hs) - q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split channels for RoPE + q = q.view(B, T, self.config.n_head, self.config.head_size) # (B, T, nh_q, hs) + q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split channels for RoPE # q decoupled for RoPE - q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) + q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) # kv projections - if self.kv_cache: # kv cache + if self.kv_cache: # kv cache new_kv = self.dkv(x) latent_kv = self.kv_cache(input_pos, new_kv) - old_kv = latent_kv[..., :input_pos[0], :] - old_kv, old_k_for_rope = torch.split( - old_kv, - [self.kv_proj_dim, self.qk_rope_dim], - dim=-1 - ) + old_kv = latent_kv[..., : input_pos[0], :] + old_kv, old_k_for_rope = torch.split(old_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) - new_kv, new_k_for_rope = torch.split( - new_kv, - [self.kv_proj_dim, self.qk_rope_dim], - dim=-1 - ) + new_kv, new_k_for_rope = torch.split(new_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) - if self.norm_kv: # normalized separately as in the original implementation + if self.norm_kv: # normalized separately as in the original implementation new_kv = self.norm_kv(new_kv) old_kv = self.norm_kv(old_kv) kv_for_lora = torch.cat([old_kv, new_kv], dim=1) k_for_rope = torch.cat([old_k_for_rope, new_k_for_rope], dim=1) - else: # no cache + else: # no cache latent_kv = self.dkv(x) kv_for_lora, k_for_rope = torch.split( - latent_kv, - [self.kv_proj_dim, self.qk_rope_dim], - dim=-1 - ) # split LoRA and RoPE additional shared head + latent_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1 + ) # split LoRA and RoPE additional shared head if self.norm_kv: kv_for_lora = self.norm_kv(kv_for_lora) - - #Β kv projection back + + # kv projection back kv = self.ukv(kv_for_lora) # Split qkv into query, key and value matrices. # To place the num_heads (nh) dimension right after the batch (B) dimension, the first step is to decouple the # embedding size (C) into num_heads (nh) and head_size (hs). - kv = kv.view(B, -1, self.config.n_head, self.config.head_size + self.qk_nope_dim).transpose(1,2) + kv = kv.view(B, -1, self.config.n_head, self.config.head_size + self.qk_nope_dim).transpose(1, 2) k, v = torch.split(kv, [self.qk_nope_dim, self.config.head_size], dim=-1) # k Rope - k_for_rope = k_for_rope.view(B, -1, 1, self.qk_rope_dim) # reshape to make it a 1-head tensor - k_for_rope = self.apply_rope_mla(k_for_rope[..., : self.config.rope_n_elem], cos, sin).transpose(1, 2) + k_for_rope = k_for_rope.view(B, -1, 1, self.qk_rope_dim) # reshape to make it a 1-head tensor + k_for_rope = self.apply_rope_mla(k_for_rope[..., : self.config.rope_n_elem], cos, sin).transpose(1, 2) # apply position encoding to each head k_for_rope = k_for_rope.repeat(1, self.config.n_head, 1, 1) @@ -654,12 +649,12 @@ def forward( # split into multiple heads q = torch.cat([q, q_for_rope], dim=-1).transpose(1, 2) # (B, nh_q, T, hs) k = torch.cat([k, k_for_rope], dim=-1) - v = v # already reshaped before the split + v = v # already reshaped before the split # The tensors `query`, `key`, and `value` are now accurately structured: within each batch element (B), there are # multiple heads (nh), and within each head, there is a sequence of elements (T), each represented by a vector # of size `hs`. - + # Efficient attention using Flash Attention CUDA kernels. # NOTE: efficient implementation is disabled if `mask` is not None or softcapping is enabled. # ↓ (B, nh, T, hs) @ (B, nh, T, hs).mT --> (B, nh, T, T) @ (B, nh, T, hs) --> (B, nh, T, hs) @@ -700,12 +695,7 @@ def build_kv_cache( device: Optional[torch.device] = None, dtype: Optional[torch.dtype] = None, ) -> "KVCacheCompressed": - - kv_shape = ( - batch_size, - max_seq_length, - self.kv_proj_dim + self.qk_rope_dim - ) + kv_shape = (batch_size, max_seq_length, self.kv_proj_dim + self.qk_rope_dim) return KVCacheCompressed(kv_shape=kv_shape, device=device, dtype=dtype) def _load_from_state_dict(self, state_dict: dict, prefix: str, *args: Any, **kwargs: Any) -> None: @@ -1000,8 +990,9 @@ def reset_parameters(self) -> None: class KVCacheCompressed(nn.Module): """ Buffers `kv` have shape - `(batch_size, max_seq_length, kv_proj_dim + qk_rope_dim)`. + `(batch_size, max_seq_length, kv_proj_dim + qk_rope_dim)`. """ + def __init__( self, kv_shape: Tuple[int, int, int, int], diff --git a/litgpt/pretrain.py b/litgpt/pretrain.py index ca4b554e37..b3921eb859 100644 --- a/litgpt/pretrain.py +++ b/litgpt/pretrain.py @@ -21,7 +21,7 @@ from litgpt.args import EvalArgs, TrainArgs from litgpt.config import name_to_config from litgpt.data import DataModule, TinyLlama -from litgpt.model import GPT, Block, CausalSelfAttention, Config, LLaMAMLP, MLA +from litgpt.model import GPT, MLA, Block, CausalSelfAttention, Config, LLaMAMLP from litgpt.utils import ( CycleIterator, capture_hparams, From 07b05389dc0af36e5e3ce7d68cd2b7448d468be9 Mon Sep 17 00:00:00 2001 From: Jirka B Date: Wed, 2 Apr 2025 20:44:18 -0400 Subject: [PATCH 08/17] typo --- config_hub/pretrain/cfg.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config_hub/pretrain/cfg.yaml b/config_hub/pretrain/cfg.yaml index 961658e57c..5244372b9a 100644 --- a/config_hub/pretrain/cfg.yaml +++ b/config_hub/pretrain/cfg.yaml @@ -17,10 +17,10 @@ model_config: norm_class_name: LayerNorm norm_qk: false - #Β Wether to use latent attention (MLA). (type: bool, default: false) + # Whether to use latent attention (MLA). (type: bool, default: false) latent_attention: true # Whether to use MQA (head_size = 1), MLA (1 < head_size < n_head), or MHA (head_size = n_head). - #Β Not compatible with latent_attention. + # Not compatible with latent_attention. n_query_groups: 12 # Directory in which to save checkpoints and logs. If running in a Lightning Studio Job, look for it in From 18af658d1faed5729239637393225eb673f9569f Mon Sep 17 00:00:00 2001 From: Yu Shi Jie Date: Sun, 13 Apr 2025 10:54:27 -0400 Subject: [PATCH 09/17] MLA: modified to support specifying custom values for q_lora_rank, v_head_dim, etc. --- litgpt/config.py | 9 +++++++++ litgpt/model.py | 26 ++++++++++++++------------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/litgpt/config.py b/litgpt/config.py index 4aba4bd255..0ff8af4108 100644 --- a/litgpt/config.py +++ b/litgpt/config.py @@ -11,6 +11,14 @@ from litgpt.utils import find_multiple +@dataclass +class MLAConfig: + q_proj_dim: Optional[int] = None + kv_proj_dim: Optional[int] = None + qk_rope_dim: Optional[int] = None + qk_nope_dim: Optional[int] = None + v_dim: Optional[int] = None + @dataclass class Config: @@ -35,6 +43,7 @@ class Config: n_head: int = 32 head_size: Optional[int] = None latent_attention: Optional[bool] = False + mla: MLAConfig = field(default_factory=MLAConfig) # to use multi-head attention (MHA), set this to `n_head` (default) # to use multi-query attention (MQA), set this to 1 # to use grouped-query attention (GQA), set this to a value in between diff --git a/litgpt/model.py b/litgpt/model.py index e62b902e51..3f5311ad18 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -524,27 +524,29 @@ def __init__(self, config: Config, block_idx: int) -> None: super().__init__() # key-value (2/3) and query (1/2) projection dimensions - self.q_proj_dim = config.n_embd // 2 - self.kv_proj_dim = 2 * config.n_embd // 3 + self.q_proj_dim = config.mla.q_proj_dim or config.n_embd // 2 + self.kv_proj_dim = config.mla.kv_proj_dim or 2 * config.n_embd // 3 # qk channel division for RoPE (50%-50%) - self.qk_rope_dim = config.head_size // 2 - self.qk_nope_dim = config.head_size // 2 # no positional embedding + self.qk_rope_dim = config.mla.qk_rope_dim or config.head_size // 2 + self.qk_nope_dim = config.mla.qk_nope_dim or config.head_size // 2 # no positional embedding + + self.v_dim = config.v_dim or config.head_size # q projections (bottleneck) self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) # down-projection - self.uq = nn.Linear(self.q_proj_dim, config.n_embd, bias=False) # up-projection + self.uq = nn.Linear(self.q_proj_dim, config.n_head * (self.qk_rope_dim + self.qk_nope_dim), bias=False) # up-projection # kv projections self.dkv = nn.Linear( config.n_embd, self.kv_proj_dim + self.qk_rope_dim, bias=False ) # latent dimension for kv + shared key for RoPE self.ukv = nn.Linear( - self.kv_proj_dim, config.n_embd + (config.n_head * self.qk_nope_dim), bias=False + self.kv_proj_dim, config.n_head * (self.v_dim + self.qk_nope_dim), bias=False ) # up-projection only for LoRA part # output projection - self.proj = nn.Linear(config.n_embd, config.n_embd, bias=False) # unchanged + self.proj = nn.Linear(config.n_head * self.v_dim, config.n_embd, bias=False) # unchanged # cache is disabled by default self.kv_cache: Optional[KVCacheCompressed] = None @@ -614,7 +616,7 @@ def forward( if self.norm_q: latent_q = self.norm_q(latent_q) q = self.uq(latent_q) - q = q.view(B, T, self.config.n_head, self.config.head_size) # (B, T, nh_q, hs) + q = q.view(B, T, self.config.n_head, self.qk_rope_dim + self.qk_nope_dim) # (B, T, nh_q, hs) q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split channels for RoPE # q decoupled for RoPE @@ -653,8 +655,8 @@ def forward( # Split qkv into query, key and value matrices. # To place the num_heads (nh) dimension right after the batch (B) dimension, the first step is to decouple the # embedding size (C) into num_heads (nh) and head_size (hs). - kv = kv.view(B, -1, self.config.n_head, self.config.head_size + self.qk_nope_dim).transpose(1, 2) - k, v = torch.split(kv, [self.qk_nope_dim, self.config.head_size], dim=-1) + kv = kv.view(B, -1, self.config.n_head, self.v_dim + self.qk_nope_dim).transpose(1, 2) + k, v = torch.split(kv, [self.qk_nope_dim, self.v_dim], dim=-1) # k Rope k_for_rope = k_for_rope.view(B, -1, 1, self.qk_rope_dim) # reshape to make it a 1-head tensor @@ -678,7 +680,7 @@ def forward( y = self.scaled_dot_product_attention(q, k, v, mask) # Re-assemble all head outputs side by side. - y = y.reshape(B, T, self.config.head_size * self.config.n_head) + y = y.reshape(B, T, self.v_dim * self.config.n_head) # Output projection return self.proj(y) # (B, T, C) @@ -686,7 +688,7 @@ def forward( def scaled_dot_product_attention( self, q: torch.Tensor, k: torch.Tensor, v: torch.Tensor, mask: Optional[torch.Tensor] = None ) -> torch.Tensor: - scale = 1.0 / math.sqrt(self.config.attention_scores_scalar or self.config.head_size) + scale = 1.0 / math.sqrt(self.config.attention_scores_scalar or (self.qk_rope_dim + self.qk_nope_dim)) # with softcapping we cannot use SDPA if self.config.attention_logit_softcapping is not None: From 6cf4282b88f499e363bfef74b9e24f4492224f80 Mon Sep 17 00:00:00 2001 From: Yu Shi Jie Date: Sun, 13 Apr 2025 11:10:35 -0400 Subject: [PATCH 10/17] clean up --- litgpt/__main__.py | 3 --- litgpt/config.py | 7 +------ litgpt/generate/base.py | 16 ++++------------ litgpt/scripts/convert_lit_checkpoint.py | 8 -------- 4 files changed, 5 insertions(+), 29 deletions(-) diff --git a/litgpt/__main__.py b/litgpt/__main__.py index 7e2b2dd46a..a92e2027c2 100644 --- a/litgpt/__main__.py +++ b/litgpt/__main__.py @@ -3,7 +3,6 @@ import warnings import torch -import torch._dynamo # fallback to eager mode if torchscript fails from jsonargparse import CLI, set_config_read_mode, set_docstring_parse_options from litgpt.chat.base import main as chat_fn @@ -29,8 +28,6 @@ from litgpt.scripts.download import download_from_hub as download_fn from litgpt.scripts.merge_lora import merge_lora as merge_lora_fn -torch._dynamo.config.suppress_errors = True - def main() -> None: parser_data = { diff --git a/litgpt/config.py b/litgpt/config.py index 0ff8af4108..c19b15f79b 100644 --- a/litgpt/config.py +++ b/litgpt/config.py @@ -75,7 +75,7 @@ class Config: attention_logit_softcapping: Optional[float] = None # Rotary position embedding (RoPE) rope_base: int = 10000 - rotary_percentage: float = 0.5 + rotary_percentage: float = 0.25 rope_condense_ratio: int = 1 rope_adjustments: Optional[dict] = None # Transformer block (MLP) @@ -305,7 +305,6 @@ def norm_class(self) -> Type: n_layer=6, n_embd=128, n_head=4, - latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-31m/blob/main/config.json @@ -316,7 +315,6 @@ def norm_class(self) -> Type: n_layer=6, n_embd=256, n_head=8, - latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-70m/blob/main/config.json @@ -327,7 +325,6 @@ def norm_class(self) -> Type: n_layer=6, n_embd=512, n_head=8, - latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-160m/blob/main/config.json @@ -338,7 +335,6 @@ def norm_class(self) -> Type: n_layer=12, n_embd=768, n_head=12, - latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-410m/blob/main/config.json @@ -349,7 +345,6 @@ def norm_class(self) -> Type: n_layer=24, n_embd=1024, n_head=16, - latent_attention=True, padding_multiple=128, ), # https://huggingface.co/EleutherAI/pythia-1b/blob/main/config.json diff --git a/litgpt/generate/base.py b/litgpt/generate/base.py index d6633b51a9..a9721938ba 100644 --- a/litgpt/generate/base.py +++ b/litgpt/generate/base.py @@ -433,10 +433,10 @@ def generate( @torch.inference_mode() def main( checkpoint_dir: Path, - prompt: str = "Once upon a time,", + prompt: str = "What food do llamas eat?", *, - num_samples: int = 100, - max_new_tokens: int = 500, + num_samples: int = 1, + max_new_tokens: int = 50, top_k: Optional[int] = 50, top_p: float = 1.0, temperature: float = 0.8, @@ -538,8 +538,6 @@ def main( fabric.print(f"Time to load the model weights: {time.perf_counter() - t0:.02f} seconds.", file=sys.stderr) L.seed_everything(1234) - ts = [] - ms = [] for i in range(num_samples): t0 = time.perf_counter() y = generate( @@ -554,16 +552,10 @@ def main( t = time.perf_counter() - t0 for block in model.transformer.h: block.attn.kv_cache.reset_parameters() - tokenizer.decode(y) - # fabric.print(tokenizer.decode(y)) + fabric.print(tokenizer.decode(y)) tokens_generated = y.size(0) - prompt_length fabric.print( f"Time for inference {i + 1}: {t:.02f} sec total, {tokens_generated / t:.02f} tokens/sec", file=sys.stderr ) - ts.append(tokens_generated / t) - ms.append(torch.cuda.memory_allocated() / 1e9) if fabric.device.type == "cuda": fabric.print(f"Memory used: {torch.cuda.max_memory_allocated() / 1e9:.02f} GB", file=sys.stderr) - fabric.print(f"Average memory used: {sum(ms) / len(ms):.02f} GB", file=sys.stderr) - fabric.print(torch.cuda.memory_summary(), file=sys.stderr) - fabric.print(f"Average tokens/sec: {sum(ts) / len(ts):.02f}", file=sys.stderr) diff --git a/litgpt/scripts/convert_lit_checkpoint.py b/litgpt/scripts/convert_lit_checkpoint.py index 955861268c..75c6934f56 100644 --- a/litgpt/scripts/convert_lit_checkpoint.py +++ b/litgpt/scripts/convert_lit_checkpoint.py @@ -77,14 +77,6 @@ def copy_weights_gpt_neox( "transformer.h.{}.attn.qkv.weight": "gpt_neox.layers.{}.attention.query_key_value.weight", "transformer.h.{}.attn.proj.bias": "gpt_neox.layers.{}.attention.dense.bias", "transformer.h.{}.attn.proj.weight": "gpt_neox.layers.{}.attention.dense.weight", - # "transformer.h.{}.attn.dq.bias": "gpt_neox.layers.{}.attention.down_query.bias", - # "transformer.h.{}.attn.dq.weight": "gpt_neox.layers.{}.attention.down_query.weight", - # "transformer.h.{}.attn.uq.bias": "gpt_neox.layers.{}.attention.up_query.bias", - # "transformer.h.{}.attn.uq.weight": "gpt_neox.layers.{}.attention.up_query.weight", - # "transformer.h.{}.attn.dkv.bias": "gpt_neox.layers.{}.attention.down_keyvalue.bias", - # "transformer.h.{}.attn.dkv.weight": "gpt_neox.layers.{}.attention.down_keyvalue.weight", - # "transformer.h.{}.attn.ukv.bias": "gpt_neox.layers.{}.attention.up_keyvalue.bias", - # "transformer.h.{}.attn.ukv.weight": "gpt_neox.layers.{}.attention.up_keyvalue.weight", "transformer.h.{}.norm_2.bias": "gpt_neox.layers.{}.post_attention_layernorm.bias", "transformer.h.{}.norm_2.weight": "gpt_neox.layers.{}.post_attention_layernorm.weight", "transformer.h.{}.mlp.fc.bias": "gpt_neox.layers.{}.mlp.dense_h_to_4h.bias", From 15727c6205ba16be2b0b0336d79afddecce5d38a Mon Sep 17 00:00:00 2001 From: Yu Shi Jie Date: Sun, 13 Apr 2025 11:12:23 -0400 Subject: [PATCH 11/17] clean up --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index b235c703e7..8c416e1b37 100644 --- a/.gitignore +++ b/.gitignore @@ -17,9 +17,6 @@ checkpoints out wandb events.out.tfevents* -evaluate_model -test.ipynb -mla_test.py # test artifacts from tests/test_readme.py **/custom_finetuning_dataset.json From 47bd94e8145e2b24d5ef21b5ac38900ddf5a2d78 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 13 Apr 2025 15:22:36 +0000 Subject: [PATCH 12/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- litgpt/config.py | 1 + litgpt/generate/base.py | 2 +- litgpt/model.py | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/litgpt/config.py b/litgpt/config.py index c19b15f79b..fb84939644 100644 --- a/litgpt/config.py +++ b/litgpt/config.py @@ -11,6 +11,7 @@ from litgpt.utils import find_multiple + @dataclass class MLAConfig: q_proj_dim: Optional[int] = None diff --git a/litgpt/generate/base.py b/litgpt/generate/base.py index a9721938ba..5d97ba6440 100644 --- a/litgpt/generate/base.py +++ b/litgpt/generate/base.py @@ -435,7 +435,7 @@ def main( checkpoint_dir: Path, prompt: str = "What food do llamas eat?", *, - num_samples: int = 1, + num_samples: int = 1, max_new_tokens: int = 50, top_k: Optional[int] = 50, top_p: float = 1.0, diff --git a/litgpt/model.py b/litgpt/model.py index 3f5311ad18..9e060a3f14 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -535,7 +535,9 @@ def __init__(self, config: Config, block_idx: int) -> None: # q projections (bottleneck) self.dq = nn.Linear(config.n_embd, self.q_proj_dim, bias=False) # down-projection - self.uq = nn.Linear(self.q_proj_dim, config.n_head * (self.qk_rope_dim + self.qk_nope_dim), bias=False) # up-projection + self.uq = nn.Linear( + self.q_proj_dim, config.n_head * (self.qk_rope_dim + self.qk_nope_dim), bias=False + ) # up-projection # kv projections self.dkv = nn.Linear( From 43187c25afd53a4901c279c4847c08f070c06493 Mon Sep 17 00:00:00 2001 From: Yu Shi Jie Date: Wed, 23 Apr 2025 03:37:39 -0400 Subject: [PATCH 13/17] major change ref --- litgpt/model.py | 18 ++++- tests/test_mla.py | 190 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 tests/test_mla.py diff --git a/litgpt/model.py b/litgpt/model.py index 9e060a3f14..58c7692ef5 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -580,6 +580,9 @@ def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) raise ValueError(f"cos must be three-dimensional, but shape is {cos.shape}") if cos.shape != sin.shape: raise ValueError(f"cos, sin must have same shape, but cos.shape={cos.shape}, sin.shape={sin.shape}") + print("x shape:", x.shape) + print("cos shape:", cos.shape) + print("sin shape:", sin.shape) head_size_half = x.size(-1) // 2 x1 = x[..., :head_size_half] # (B, ..., T, head_size/2) x2 = x[..., head_size_half:] # (B, ..., T, head_size/2) @@ -588,6 +591,7 @@ def apply_rope_mla(self, x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) if dims_diff > 0: # Ensure that shapes of `x`, `cos`, `sin` align new_shape = cos.shape[0:2] + (1,) * dims_diff + cos.shape[2:] + print("new_shape:", new_shape) cos = cos.view(*new_shape) sin = sin.view(*new_shape) @@ -612,15 +616,23 @@ def forward( # - hs | head size B, T, _ = x.size() # batch size, sequence length + print("B:", B) + print("T:", T) # q projections latent_q = self.dq(x) + print("latent_q shape:", latent_q.shape) if self.norm_q: latent_q = self.norm_q(latent_q) q = self.uq(latent_q) q = q.view(B, T, self.config.n_head, self.qk_rope_dim + self.qk_nope_dim) # (B, T, nh_q, hs) q, q_for_rope = torch.split(q, [self.qk_nope_dim, self.qk_rope_dim], dim=-1) # split channels for RoPE + print("q shape:", q.shape) + print("cos shape:", cos.shape) + print("sin shape:", sin.shape) + + # q decoupled for RoPE q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) @@ -629,9 +641,11 @@ def forward( new_kv = self.dkv(x) latent_kv = self.kv_cache(input_pos, new_kv) - old_kv = latent_kv[..., : input_pos[0], :] + if input_pos_maxp1 is not None: + old_kv = latent_kv[..., : input_pos_maxp1, :] + else: + old_kv = latent_kv old_kv, old_k_for_rope = torch.split(old_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) - new_kv, new_k_for_rope = torch.split(new_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) if self.norm_kv: # normalized separately as in the original implementation diff --git a/tests/test_mla.py b/tests/test_mla.py new file mode 100644 index 0000000000..7a3eb883c1 --- /dev/null +++ b/tests/test_mla.py @@ -0,0 +1,190 @@ +import pytest +import torch +import numpy as np +from litgpt.model import MLA +from litgpt.config import Config + + +class TestMLA: + + @pytest.fixture + def config(self): + # Create a basic config for testing + config = Config( + n_embd=32, + n_head=4, + norm_qk=True, + norm_eps=1e-5, + latent_attention=True, + ) + + # Add MLA-specific config + config.mla = type('MLAConfig', (), { + 'q_proj_dim': 32, + 'kv_proj_dim': 42, + 'qk_rope_dim': 8, + 'qk_nope_dim': 8, + }) + config.v_dim = 16 + + print("config:", config) + + return config + + @pytest.fixture + def mla_model(self, config): + # Create an MLA instance with test parameters + return MLA(config, block_idx=0) + + @pytest.fixture + def rope_cache(self, config): + # Create a simple RoPE cache for testing + seq_len = 16 + rope_n_elem = config.rope_n_elem + batch_size = 1 + cos = torch.ones((batch_size, seq_len, rope_n_elem)) + sin = torch.zeros((batch_size, seq_len, rope_n_elem)) + return cos, sin + + def test_output_shape(self, mla_model, rope_cache): + # Test that output tensors have expected shapes + batch_size = 2 + seq_len = 16 + x = torch.randn(batch_size, seq_len, 32) + cos, sin = rope_cache + + output = mla_model(x, cos, sin) + + # Verify output shape matches input shape + assert output.shape == (batch_size, seq_len, 32) + + @pytest.mark.skip(reason="This test is currently broken") + def test_attention_mask(self, mla_model, rope_cache): + # Test that attention masking works correctly + batch_size = 2 + seq_len = 16 + x = torch.randn(batch_size, seq_len, 32) + cos, sin = rope_cache + + # Create a mask where some positions are masked + mask = torch.ones(1, 1, seq_len, seq_len).bool() + mask = torch.tril(mask.squeeze()).unsqueeze(0).unsqueeze(0) # Causal mask + + output_masked = mla_model(x, cos, sin, mask) + output_unmasked = mla_model(x, cos, sin) + + # Outputs should be different when using masks + assert not torch.allclose(output_masked, output_unmasked, rtol=1e-2) + + def test_rope_application(self, mla_model): + # Test that RoPE is applied correctly + x = torch.ones(1, 1, 16) # Simple test tensor + cos = torch.ones(1, 1, 16) + sin = torch.ones(1, 1, 16) + + # Call the RoPE application directly + ropeified = mla_model.apply_rope_mla(x, cos, sin) + + # Check that the values have been transformed + assert not torch.allclose(ropeified, x) + + # Test the shape is maintained + assert ropeified.shape == x.shape + + def test_kv_cache(self, mla_model, rope_cache): + # Test KV cache functionality + batch_size = 2 + seq_len = 16 + x = torch.randn(batch_size, seq_len, 32) + cos, sin = rope_cache + + # Initialize KV cache + mla_model.kv_cache = mla_model.build_kv_cache( + batch_size=batch_size, + max_seq_length=16, + device=x.device, + dtype=x.dtype + ) + + # First forward pass with positions 0-7 + input_pos = torch.arange(8).unsqueeze(0).expand(batch_size, -1) + print("input_pos shape:", input_pos.shape) + print("input_pos:", input_pos) + output1 = mla_model(x[:, :8, :], cos[:, :8, :], sin[:, :8, :], input_pos=input_pos) + print("output1 shape:", output1.shape) + + # Second forward pass with positions 8-15 + input_pos = torch.arange(8, 16).unsqueeze(0).expand(batch_size, -1) + output2 = mla_model(x[:, 8:16, :], cos[:, 8:16, :], sin[:, 8:16, :], input_pos=input_pos) + + # Now run without caching + mla_model.kv_cache = None + output_full = mla_model(x, cos, sin) + + # Check the shapes + assert output1.shape == output2.shape == (batch_size, 8, 32) + assert output_full.shape == (batch_size, seq_len, 32) + + @pytest.mark.skip(reason="This test is currently broken") + def test_gradient_flow(self, mla_model, rope_cache): + # Test that gradients flow correctly through MLA + batch_size = 2 + seq_len = 16 + x = torch.randn(batch_size, seq_len, 32, requires_grad=True) + cos, sin = rope_cache + + output = mla_model(x, cos, sin) + loss = output.sum() + loss.backward() + + # Check that gradients aren't None or zero + assert x.grad is not None + assert not torch.allclose(x.grad, torch.zeros_like(x.grad)) + + # Check gradients for key parameters + assert mla_model.dq.weight.grad is not None + assert mla_model.uq.weight.grad is not None + assert mla_model.dkv.weight.grad is not None + assert mla_model.ukv.weight.grad is not None + assert mla_model.proj.weight.grad is not None + + @pytest.mark.skip(reason="This test is currently broken") + def test_reproducibility(self, mla_model, rope_cache): + # Test that results are reproducible with fixed seed + torch.manual_seed(42) + batch_size = 2 + seq_len = 16 + x = torch.randn(batch_size, seq_len, 32) + cos, sin = rope_cache + + output1 = mla_model(x, cos, sin) + + torch.manual_seed(42) + x = torch.randn(batch_size, seq_len, 32) # Same random input + output2 = mla_model(x, cos, sin) + + assert torch.allclose(output1, output2) + + @pytest.mark.skip(reason="This test is currently broken") + def test_attention_patterns(self, mla_model, rope_cache): + # Create input with a distinct pattern to test attention behavior + batch_size = 1 + seq_len = 16 + x = torch.zeros(batch_size, seq_len, 32) + + # Make each position progressively stronger signal + for i in range(seq_len): + x[:, i, :] = i + + cos, sin = rope_cache + + # Test that attention focuses on specific positions + output = mla_model(x, cos, sin) + + # Later positions should have more influence due to causal attention + # Check relative magnitudes (this is a simplified test) + early_pos_avg = output[:, 0, :].abs().mean() + late_pos_avg = output[:, -1, :].abs().mean() + + # Later positions usually have higher activation due to seeing more context + assert late_pos_avg > early_pos_avg From 56e62ee8bf0cac74d7e84fee5ac8a5f8ad5bde82 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 07:38:19 +0000 Subject: [PATCH 14/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- litgpt/model.py | 3 +- tests/test_mla.py | 96 +++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/litgpt/model.py b/litgpt/model.py index 58c7692ef5..ecde570cca 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -631,7 +631,6 @@ def forward( print("q shape:", q.shape) print("cos shape:", cos.shape) print("sin shape:", sin.shape) - # q decoupled for RoPE q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) @@ -642,7 +641,7 @@ def forward( latent_kv = self.kv_cache(input_pos, new_kv) if input_pos_maxp1 is not None: - old_kv = latent_kv[..., : input_pos_maxp1, :] + old_kv = latent_kv[..., :input_pos_maxp1, :] else: old_kv = latent_kv old_kv, old_k_for_rope = torch.split(old_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) diff --git a/tests/test_mla.py b/tests/test_mla.py index 7a3eb883c1..dd452cc4a4 100644 --- a/tests/test_mla.py +++ b/tests/test_mla.py @@ -1,12 +1,11 @@ import pytest import torch -import numpy as np -from litgpt.model import MLA + from litgpt.config import Config +from litgpt.model import MLA class TestMLA: - @pytest.fixture def config(self): # Create a basic config for testing @@ -17,25 +16,29 @@ def config(self): norm_eps=1e-5, latent_attention=True, ) - + # Add MLA-specific config - config.mla = type('MLAConfig', (), { - 'q_proj_dim': 32, - 'kv_proj_dim': 42, - 'qk_rope_dim': 8, - 'qk_nope_dim': 8, - }) + config.mla = type( + "MLAConfig", + (), + { + "q_proj_dim": 32, + "kv_proj_dim": 42, + "qk_rope_dim": 8, + "qk_nope_dim": 8, + }, + ) config.v_dim = 16 print("config:", config) - + return config - + @pytest.fixture def mla_model(self, config): # Create an MLA instance with test parameters return MLA(config, block_idx=0) - + @pytest.fixture def rope_cache(self, config): # Create a simple RoPE cache for testing @@ -45,19 +48,19 @@ def rope_cache(self, config): cos = torch.ones((batch_size, seq_len, rope_n_elem)) sin = torch.zeros((batch_size, seq_len, rope_n_elem)) return cos, sin - + def test_output_shape(self, mla_model, rope_cache): # Test that output tensors have expected shapes batch_size = 2 seq_len = 16 x = torch.randn(batch_size, seq_len, 32) cos, sin = rope_cache - + output = mla_model(x, cos, sin) - + # Verify output shape matches input shape assert output.shape == (batch_size, seq_len, 32) - + @pytest.mark.skip(reason="This test is currently broken") def test_attention_mask(self, mla_model, rope_cache): # Test that attention masking works correctly @@ -65,66 +68,63 @@ def test_attention_mask(self, mla_model, rope_cache): seq_len = 16 x = torch.randn(batch_size, seq_len, 32) cos, sin = rope_cache - + # Create a mask where some positions are masked mask = torch.ones(1, 1, seq_len, seq_len).bool() mask = torch.tril(mask.squeeze()).unsqueeze(0).unsqueeze(0) # Causal mask - + output_masked = mla_model(x, cos, sin, mask) output_unmasked = mla_model(x, cos, sin) - + # Outputs should be different when using masks assert not torch.allclose(output_masked, output_unmasked, rtol=1e-2) - + def test_rope_application(self, mla_model): # Test that RoPE is applied correctly x = torch.ones(1, 1, 16) # Simple test tensor cos = torch.ones(1, 1, 16) sin = torch.ones(1, 1, 16) - + # Call the RoPE application directly ropeified = mla_model.apply_rope_mla(x, cos, sin) - + # Check that the values have been transformed assert not torch.allclose(ropeified, x) - + # Test the shape is maintained assert ropeified.shape == x.shape - + def test_kv_cache(self, mla_model, rope_cache): # Test KV cache functionality batch_size = 2 seq_len = 16 x = torch.randn(batch_size, seq_len, 32) cos, sin = rope_cache - + # Initialize KV cache mla_model.kv_cache = mla_model.build_kv_cache( - batch_size=batch_size, - max_seq_length=16, - device=x.device, - dtype=x.dtype + batch_size=batch_size, max_seq_length=16, device=x.device, dtype=x.dtype ) - + # First forward pass with positions 0-7 input_pos = torch.arange(8).unsqueeze(0).expand(batch_size, -1) print("input_pos shape:", input_pos.shape) print("input_pos:", input_pos) output1 = mla_model(x[:, :8, :], cos[:, :8, :], sin[:, :8, :], input_pos=input_pos) print("output1 shape:", output1.shape) - + # Second forward pass with positions 8-15 input_pos = torch.arange(8, 16).unsqueeze(0).expand(batch_size, -1) output2 = mla_model(x[:, 8:16, :], cos[:, 8:16, :], sin[:, 8:16, :], input_pos=input_pos) - + # Now run without caching mla_model.kv_cache = None output_full = mla_model(x, cos, sin) - + # Check the shapes assert output1.shape == output2.shape == (batch_size, 8, 32) assert output_full.shape == (batch_size, seq_len, 32) - + @pytest.mark.skip(reason="This test is currently broken") def test_gradient_flow(self, mla_model, rope_cache): # Test that gradients flow correctly through MLA @@ -132,22 +132,22 @@ def test_gradient_flow(self, mla_model, rope_cache): seq_len = 16 x = torch.randn(batch_size, seq_len, 32, requires_grad=True) cos, sin = rope_cache - + output = mla_model(x, cos, sin) loss = output.sum() loss.backward() - + # Check that gradients aren't None or zero assert x.grad is not None assert not torch.allclose(x.grad, torch.zeros_like(x.grad)) - + # Check gradients for key parameters assert mla_model.dq.weight.grad is not None assert mla_model.uq.weight.grad is not None assert mla_model.dkv.weight.grad is not None assert mla_model.ukv.weight.grad is not None assert mla_model.proj.weight.grad is not None - + @pytest.mark.skip(reason="This test is currently broken") def test_reproducibility(self, mla_model, rope_cache): # Test that results are reproducible with fixed seed @@ -156,35 +156,35 @@ def test_reproducibility(self, mla_model, rope_cache): seq_len = 16 x = torch.randn(batch_size, seq_len, 32) cos, sin = rope_cache - + output1 = mla_model(x, cos, sin) - + torch.manual_seed(42) x = torch.randn(batch_size, seq_len, 32) # Same random input output2 = mla_model(x, cos, sin) - + assert torch.allclose(output1, output2) - + @pytest.mark.skip(reason="This test is currently broken") def test_attention_patterns(self, mla_model, rope_cache): # Create input with a distinct pattern to test attention behavior batch_size = 1 seq_len = 16 x = torch.zeros(batch_size, seq_len, 32) - + # Make each position progressively stronger signal for i in range(seq_len): x[:, i, :] = i - + cos, sin = rope_cache - + # Test that attention focuses on specific positions output = mla_model(x, cos, sin) - + # Later positions should have more influence due to causal attention # Check relative magnitudes (this is a simplified test) early_pos_avg = output[:, 0, :].abs().mean() late_pos_avg = output[:, -1, :].abs().mean() - + # Later positions usually have higher activation due to seeing more context assert late_pos_avg > early_pos_avg From ba55cf1b15cb085847a9da1010a817edf1545897 Mon Sep 17 00:00:00 2001 From: "shijie.yu" Date: Fri, 16 May 2025 04:32:11 +0000 Subject: [PATCH 15/17] feat: deepseekv3 architecture --- litgpt/config.py | 2 +- litgpt/model.py | 373 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 299 insertions(+), 76 deletions(-) diff --git a/litgpt/config.py b/litgpt/config.py index 7f01353b74..8a2ea24a0b 100644 --- a/litgpt/config.py +++ b/litgpt/config.py @@ -93,7 +93,7 @@ class Config: # Transformer block (MLP) intermediate_size: Optional[int] = None bias: bool = True - mlp_class_name: Literal["GptNeoxMLP", "LLaMAMLP", "GemmaMLP", "LLaMAMoE"] = "GptNeoxMLP" + mlp_class_name: Literal["GptNeoxMLP", "LLaMAMLP", "GemmaMLP", "LLaMAMoE", "DeepseekV3MoE"] = "GptNeoxMLP" gelu_approximate: str = "none" n_expert: int = 0 n_expert_per_token: int = 0 diff --git a/litgpt/model.py b/litgpt/model.py index 689e17a058..aaf6c1c7da 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -14,6 +14,7 @@ import torch.nn as nn import torch.nn.functional as F from typing_extensions import Self +import torch.distributed as dist from litgpt.config import Config from litgpt.scripts.convert_hf_checkpoint import qkv_reassemble @@ -272,12 +273,23 @@ def __init__( ) self.norm_1 = config.norm_class(config.n_embd, eps=config.norm_eps) - self.attn = CausalSelfAttention(config, block_idx) if not config.latent_attention else MLA(config, block_idx) + self.attn = CausalSelfAttention(config, block_idx) if not config.latent_attention else MultiHeadLatentAttention(config, block_idx) self.post_attention_norm = ( config.norm_class(config.n_embd, eps=config.norm_eps) if config.post_attention_norm else nn.Identity() ) self.norm_2 = None if config.shared_attention_norm else config.norm_class(config.n_embd, eps=config.norm_eps) - self.mlp = config.mlp_class(config) + if config.mlp_class == "DeepseekV3MoE": + self.mlp = ( + DeepseekV3MoE(config) + if ( + config.n_routed_experts is not None + and block_idx >= config.first_k_dense_replace + and block_idx % config.moe_layer_freq == 0 + ) + else LLaMAMoE(config) + ) + else: + self.mlp = config.mlp_class(config) self.post_mlp_norm = ( config.norm_class(config.n_embd, eps=config.norm_eps) if config.post_mlp_norm else nn.Identity() ) @@ -515,7 +527,7 @@ def _load_from_state_dict(self, state_dict: dict, prefix: str, *args: Any, **kwa super()._load_from_state_dict(state_dict, prefix, *args, **kwargs) -class MLA(nn.Module): +class MultiHeadLatentAttention(nn.Module): """ Multi-Head Latent Attention (MLA) block from DeepSeekV2 https://arxiv.org/abs/2405.04434 """ @@ -551,7 +563,7 @@ def __init__(self, config: Config, block_idx: int) -> None: self.proj = nn.Linear(config.n_head * self.v_dim, config.n_embd, bias=False) # unchanged # cache is disabled by default - self.kv_cache: Optional[KVCacheCompressed] = None + self.kv_cache: Optional[KVCache] = None # layer norm for projections if config.norm_qk: @@ -636,33 +648,42 @@ def forward( q_for_rope = self.apply_rope_mla(q_for_rope[..., : self.config.rope_n_elem], cos, sin) # kv projections - if self.kv_cache: # kv cache - new_kv = self.dkv(x) - latent_kv = self.kv_cache(input_pos, new_kv) + # if self.kv_cache: # kv cache + # new_kv = self.dkv(x) + # latent_kv = self.kv_cache(input_pos, new_kv) - if input_pos_maxp1 is not None: - old_kv = latent_kv[..., :input_pos_maxp1, :] - else: - old_kv = latent_kv - old_kv, old_k_for_rope = torch.split(old_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) - new_kv, new_k_for_rope = torch.split(new_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) + # if input_pos_maxp1 is not None: + # old_kv = latent_kv[..., :input_pos_maxp1, :] + # else: + # old_kv = latent_kv + # old_kv, old_k_for_rope = torch.split(old_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) + # new_kv, new_k_for_rope = torch.split(new_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1) - if self.norm_kv: # normalized separately as in the original implementation - new_kv = self.norm_kv(new_kv) - old_kv = self.norm_kv(old_kv) + # if self.norm_kv: # normalized separately as in the original implementation + # new_kv = self.norm_kv(new_kv) + # old_kv = self.norm_kv(old_kv) - kv_for_lora = torch.cat([old_kv, new_kv], dim=1) - k_for_rope = torch.cat([old_k_for_rope, new_k_for_rope], dim=1) + # kv_for_lora = torch.cat([old_kv, new_kv], dim=1) + # k_for_rope = torch.cat([old_k_for_rope, new_k_for_rope], dim=1) - else: # no cache - latent_kv = self.dkv(x) + # else: # no cache + # latent_kv = self.dkv(x) - kv_for_lora, k_for_rope = torch.split( - latent_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1 - ) # split LoRA and RoPE additional shared head + # kv_for_lora, k_for_rope = torch.split( + # latent_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1 + # ) # split LoRA and RoPE additional shared head - if self.norm_kv: - kv_for_lora = self.norm_kv(kv_for_lora) + # if self.norm_kv: + # kv_for_lora = self.norm_kv(kv_for_lora) + + latent_kv = self.dkv(x) + + kv_for_lora, k_for_rope = torch.split( + latent_kv, [self.kv_proj_dim, self.qk_rope_dim], dim=-1 + ) # split LoRA and RoPE additional shared head + + if self.norm_kv: + kv_for_lora = self.norm_kv(kv_for_lora) # kv projection back kv = self.ukv(kv_for_lora) @@ -685,6 +706,20 @@ def forward( k = torch.cat([k, k_for_rope], dim=-1) v = v # already reshaped before the split + if input_pos is not None: # Indicates inference and KV cache usage + if not isinstance(self.kv_cache, KVCache): # Check for the correct cache type + raise TypeError("You need to call `gpt.set_kv_cache()` with the appropriate KVCache for MLA.") + + k_full_cached, v_full_cached = self.kv_cache(input_pos, k, v) + + if input_pos_maxp1 is not None: + # Subselect along sequence dimension if needed + k = k_full_cached[..., :input_pos_maxp1, :] + v = v_full_cached[..., :input_pos_maxp1, :] + else: + k = k_full_cached + v = v_full_cached + # The tensors `query`, `key`, and `value` are now accurately structured: within each batch element (B), there are # multiple heads (nh), and within each head, there is a sequence of elements (T), each represented by a vector # of size `hs`. @@ -728,9 +763,20 @@ def build_kv_cache( rope_cache_length: Optional[int] = None, device: Optional[torch.device] = None, dtype: Optional[torch.dtype] = None, - ) -> "KVCacheCompressed": - kv_shape = (batch_size, max_seq_length, self.kv_proj_dim + self.qk_rope_dim) - return KVCacheCompressed(kv_shape=kv_shape, device=device, dtype=dtype) + ) -> "KVCache": + # Head dimension for K is the sum of its nope and rope parts + k_head_dim = self.qk_nope_dim + self.qk_rope_dim + # Head dimension for V + v_head_dim = self.v_dim + + # To match DeepSeekV3's caching of K/V for all query heads + num_cached_kv_heads = self.config.n_head + + k_shape = (batch_size, num_cached_kv_heads, max_seq_length, k_head_dim) + v_shape = (batch_size, num_cached_kv_heads, max_seq_length, v_head_dim) + + # Ensure KVCache is the class that stores k and v buffers separately + return KVCache(k_shape, v_shape, device=device, dtype=dtype) def _load_from_state_dict(self, state_dict: dict, prefix: str, *args: Any, **kwargs: Any) -> None: """For compatibility with legacy checkpoints.""" @@ -758,11 +804,14 @@ def forward(self, x: torch.Tensor) -> torch.Tensor: class LLaMAMLP(nn.Module): - def __init__(self, config: Config) -> None: + def __init__(self, config: Config, n_embd: Optional[int] = None, intermediate_size: Optional[int] = None) -> None: super().__init__() - self.fc_1 = nn.Linear(config.n_embd, config.intermediate_size, bias=config.bias) - self.fc_2 = nn.Linear(config.n_embd, config.intermediate_size, bias=config.bias) - self.proj = nn.Linear(config.intermediate_size, config.n_embd, bias=config.bias) + self.config = config + self.n_embd = config.n_embed if n_embd is None else n_embd + self.intermediate_size = config.intermediate_size if intermediate_size is None else intermediate_size + self.fc_1 = nn.Linear(self.n_embd, self.intermediate_size, bias=config.bias) + self.fc_2 = nn.Linear(self.n_embd, self.intermediate_size, bias=config.bias) + self.proj = nn.Linear(self.intermediate_size, self.n_embd, bias=config.bias) self.config = config def forward(self, x: torch.Tensor) -> torch.Tensor: @@ -805,6 +854,223 @@ def forward(self, x: torch.Tensor) -> torch.Tensor: y[token_idx] += probs[token_idx, expert_idx, None] * expert(x[token_idx]) return y.view(B, T, C) +class DeepseekV3MoEGate(nn.Module): + def __init__(self, config): + super().__init__() + self.config = config + self.top_k = config.num_experts_per_tok + self.n_routed_experts = config.n_routed_experts + self.routed_scaling_factor = config.routed_scaling_factor + self.scoring_func = config.scoring_func + self.topk_method = config.topk_method + self.n_group = config.n_group + self.topk_group = config.topk_group + + # topk selection algorithm + self.norm_topk_prob = config.norm_topk_prob + self.gating_dim = config.hidden_size + self.weight = nn.Parameter( + torch.empty((self.n_routed_experts, self.gating_dim)) + ) + if self.topk_method == "noaux_tc": + self.e_score_correction_bias = nn.Parameter( + torch.empty((self.n_routed_experts)) + ) + self.reset_parameters() + + def reset_parameters(self) -> None: + import torch.nn.init as init + + init.kaiming_uniform_(self.weight, a=math.sqrt(5)) + + def forward(self, x: torch.Tensor): + bsz, seq_len, h = x.shape + ### compute gating score + x = x.view(-1, h) + logits = nn.Linear( + x.type(torch.float32), self.weight.type(torch.float32), None + ) + + if self.scoring_func == "sigmoid": + scores = logits.sigmoid() + else: + raise NotImplementedError( + f"insupportable scoring function for MoE gating: {self.scoring_func}" + ) + + ### select top-k experts + if self.topk_method == "noaux_tc": + assert not self.training + scores_for_choice = scores.view(bsz * seq_len, -1) + self.e_score_correction_bias.unsqueeze(0) + group_scores = ( + scores_for_choice.view(bsz * seq_len, self.n_group, -1).topk(2, dim=-1)[0].sum(dim = -1) + ) # [n, n_group] + group_idx = torch.topk( + group_scores, k=self.topk_group, dim=-1, sorted=False + )[ + 1 + ] # [n, top_k_group] + group_mask = torch.zeros_like(group_scores) # [n, n_group] + group_mask.scatter_(1, group_idx, 1) # [n, n_group] + score_mask = ( + group_mask.unsqueeze(-1) + .expand( + bsz * seq_len, self.n_group, self.n_routed_experts // self.n_group + ) + .reshape(bsz * seq_len, -1) + ) # [n, e] + tmp_scores = scores_for_choice.masked_fill(~score_mask.bool(), float("-inf")) # [n, e] + _, topk_idx = torch.topk( + tmp_scores, k=self.top_k, dim=-1, sorted=False + ) + topk_weight = scores.gather(1, topk_idx) + else: + raise NotImplementedError( + f"insupportable TopK function for MoE gating: {self.topk_method}" + ) + + ### norm gate to sum 1 + if self.top_k > 1 and self.norm_topk_prob: + denominator = topk_weight.sum(dim=-1, keepdim=True) + 1e-20 + topk_weight = topk_weight / denominator + topk_weight = topk_weight * self.routed_scaling_factor # must multiply the scaling factor + + return topk_idx, topk_weight + +class DeepseekV3MoE(nn.Module): + """ + A mixed expert module containing shared experts. + """ + + def __init__(self, config): + super().__init__() + self.config = config + self.num_experts_per_tok = config.num_experts_per_tok + + if hasattr(config, "ep_size") and config.ep_size > 1: + assert config.ep_size == dist.get_world_size() + self.ep_size = config.ep_size + self.experts_per_rank = config.n_routed_experts // config.ep_size + self.ep_rank = dist.get_rank() + self.experts = nn.ModuleList( + [ + ( + LLaMAMLP( + config, intermediate_size=config.moe_intermediate_size + ) + if i >= self.ep_rank * self.experts_per_rank + and i < (self.ep_rank + 1) * self.experts_per_rank + else None + ) + for i in range(config.n_routed_experts) + ] + ) + else: + self.ep_size = 1 + self.experts_per_rank = config.n_routed_experts + self.ep_rank = 0 + self.experts = nn.ModuleList( + [ + LLaMAMLP( + config, intermediate_size=config.moe_intermediate_size + ) + for i in range(config.n_routed_experts) + ] + ) + self.gate = DeepseekV3MoEGate(config) + if config.n_shared_experts is not None: + intermediate_size = config.moe_intermediate_size * config.n_shared_experts + self.shared_experts = LLaMAMLP( + config=config, intermediate_size=intermediate_size + ) + + def forward(self, x: torch.Tensor): + identity = x + orig_shape = x.shape + topk_idx, topk_weight = self.gate(x) + x = x.view(-1, x.shape[-1]) + flat_topk_idx = topk_idx.view(-1) + if not self.training: + y = self.moe_infer(x, topk_idx, topk_weight).view(*orig_shape) + if self.config.n_shared_experts is not None: + y = y + self.shared_experts(identity) + return y + + @torch.no_grad() + def moe_infer(self, x, topk_ids, topk_weight): + cnts = topk_ids.new_zeros((topk_ids.shape[0], len(self.experts))) + cnts.scatter_(1, topk_ids, 1) + tokens_per_expert = cnts.sum(dim=0) + idxs = topk_ids.view(-1).argsort() + sorted_tokens = x[idxs // topk_ids.shape[1]] + sorted_tokens_shape = sorted_tokens.shape + if self.ep_size > 1: + tokens_per_ep_rank = tokens_per_expert.view(self.ep_size, -1).sum(dim=1) + tokens_per_expert_group = tokens_per_expert.new_empty( + tokens_per_expert.shape[0] + ) + dist.all_to_all_single(tokens_per_expert_group, tokens_per_expert) + output_splits = ( + tokens_per_expert_group.view(self.ep_size, -1) + .sum(1) + .cpu() + .numpy() + .tolist() + ) + gathered_tokens = sorted_tokens.new_empty( + tokens_per_expert_group.sum(dim=0).cpu().item(), sorted_tokens.shape[1] + ) + input_split_sizes = tokens_per_ep_rank.cpu().numpy().tolist() + dist.all_to_all( + list(gathered_tokens.split(output_splits)), + list(sorted_tokens.split(input_split_sizes)), + ) + tokens_per_expert_post_gather = tokens_per_expert_group.view( + self.ep_size, self.experts_per_rank + ).sum(dim=0) + gatherd_idxs = np.zeros(shape=(gathered_tokens.shape[0],), dtype=np.int32) + s = 0 + for i, k in enumerate(tokens_per_expert_group.cpu().numpy()): + gatherd_idxs[s : s + k] = i % self.experts_per_rank + s += k + gatherd_idxs = gatherd_idxs.argsort() + sorted_tokens = gathered_tokens[gatherd_idxs] + tokens_per_expert = tokens_per_expert_post_gather + tokens_per_expert = tokens_per_expert.cpu().numpy() + + outputs = [] + start_idx = 0 + for i, num_tokens in enumerate(tokens_per_expert): + end_idx = start_idx + num_tokens + if num_tokens == 0: + continue + expert = self.experts[i + self.ep_rank * self.experts_per_rank] + tokens_for_this_expert = sorted_tokens[start_idx:end_idx] + expert_out = expert(tokens_for_this_expert) + outputs.append(expert_out) + start_idx = end_idx + + outs = torch.cat(outputs, dim=0) if len(outputs) else sorted_tokens.new_empty(0) + if self.ep_size > 1: + new_x = torch.empty_like(outs) + new_x[gatherd_idxs] = outs + gathered_tokens = new_x.new_empty(*sorted_tokens_shape) + dist.all_to_all( + list(gathered_tokens.split(input_split_sizes)), + list(new_x.split(output_splits)), + ) + outs = gathered_tokens + + new_x = torch.empty_like(outs) + new_x[idxs] = outs + final_out = ( + new_x.view(*topk_ids.shape, -1) + .type(topk_weight.dtype) + .mul_(topk_weight.unsqueeze(dim=-1)) + .sum(dim=1) + .type(new_x.dtype) + ) + return final_out def build_rope_cache( seq_len: int, @@ -1035,49 +1301,6 @@ def reset_parameters(self) -> None: torch.nn.init.zeros_(self.v) -class KVCacheCompressed(nn.Module): - """ - Buffers `kv` have shape - `(batch_size, max_seq_length, kv_proj_dim + qk_rope_dim)`. - """ - - def __init__( - self, - kv_shape: Tuple[int, int, int, int], - device: Optional[torch.device] = None, - dtype: Optional[torch.dtype] = None, - ) -> None: - super().__init__() - self.register_buffer("kv", torch.zeros(kv_shape, device=device, dtype=dtype), persistent=False) - - def forward(self, input_pos: torch.Tensor, kv: torch.Tensor) -> torch.Tensor: - """ - Writes new values `kv` into the cache at the positions specified - by `input_pos` along the sequence dimension (`max_seq_length`). The batch - size of `kv` (`bs`) must be smaller or equal to `KVCacheCompressed` batch - size. Returns the full buffers, adjusted to the batch size `bs`. - - Args: - input_pos: Position index, `(bs, T)` or `(T,)` - kv: New values, `(bs, T, kv_proj_dim + qk_rope_dim)` - - Returns: - kv_full `(bs, max_seq_length, kv_proj_dim + qk_rope_dim)` - - """ - # move the buffer to the activation dtype for when AMP is used - self.kv = self.kv.to(kv.dtype) - # update the cache - bs = kv.size(0) - kv = batched_index_copy_(self.kv[:bs, ...], -2, input_pos, kv) - return kv - - def reset_parameters(self) -> None: - torch.nn.init.zeros_(self.kv) - - def get_cache(self) -> torch.Tensor: - return self.kv - def build_mask_cache(max_seq_length: int, device: Optional[torch.device] = None) -> torch.Tensor: ones = torch.ones((max_seq_length, max_seq_length), device=device, dtype=torch.bool) From 7e3ea786bad3261254e0881cc7a4ac3795913858 Mon Sep 17 00:00:00 2001 From: "shijie.yu" Date: Fri, 16 May 2025 06:47:54 +0000 Subject: [PATCH 16/17] deepseekv3 --- litgpt/model.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/litgpt/model.py b/litgpt/model.py index aaf6c1c7da..83e80a8ca0 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -282,7 +282,7 @@ def __init__( self.mlp = ( DeepseekV3MoE(config) if ( - config.n_routed_experts is not None + config.n_expert is not None and block_idx >= config.first_k_dense_replace and block_idx % config.moe_layer_freq == 0 ) @@ -859,7 +859,7 @@ def __init__(self, config): super().__init__() self.config = config self.top_k = config.num_experts_per_tok - self.n_routed_experts = config.n_routed_experts + self.n_expert = config.n_expert self.routed_scaling_factor = config.routed_scaling_factor self.scoring_func = config.scoring_func self.topk_method = config.topk_method @@ -870,11 +870,11 @@ def __init__(self, config): self.norm_topk_prob = config.norm_topk_prob self.gating_dim = config.hidden_size self.weight = nn.Parameter( - torch.empty((self.n_routed_experts, self.gating_dim)) + torch.empty((self.n_expert, self.gating_dim)) ) if self.topk_method == "noaux_tc": self.e_score_correction_bias = nn.Parameter( - torch.empty((self.n_routed_experts)) + torch.empty((self.n_expert)) ) self.reset_parameters() @@ -915,7 +915,7 @@ def forward(self, x: torch.Tensor): score_mask = ( group_mask.unsqueeze(-1) .expand( - bsz * seq_len, self.n_group, self.n_routed_experts // self.n_group + bsz * seq_len, self.n_group, self.n_expert // self.n_group ) .reshape(bsz * seq_len, -1) ) # [n, e] @@ -945,12 +945,12 @@ class DeepseekV3MoE(nn.Module): def __init__(self, config): super().__init__() self.config = config - self.num_experts_per_tok = config.num_experts_per_tok + self.num_experts_per_tok = config.n_expert_per_token if hasattr(config, "ep_size") and config.ep_size > 1: assert config.ep_size == dist.get_world_size() self.ep_size = config.ep_size - self.experts_per_rank = config.n_routed_experts // config.ep_size + self.experts_per_rank = config.n_expert // config.ep_size self.ep_rank = dist.get_rank() self.experts = nn.ModuleList( [ @@ -962,19 +962,19 @@ def __init__(self, config): and i < (self.ep_rank + 1) * self.experts_per_rank else None ) - for i in range(config.n_routed_experts) + for i in range(config.n_expert) ] ) else: self.ep_size = 1 - self.experts_per_rank = config.n_routed_experts + self.experts_per_rank = config.n_expert self.ep_rank = 0 self.experts = nn.ModuleList( [ LLaMAMLP( config, intermediate_size=config.moe_intermediate_size ) - for i in range(config.n_routed_experts) + for i in range(config.n_expert) ] ) self.gate = DeepseekV3MoEGate(config) From dcc89de9dcb66e6019cdbbd629b015cee8ef7787 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 16 May 2025 06:49:31 +0000 Subject: [PATCH 17/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- litgpt/model.py | 90 ++++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 61 deletions(-) diff --git a/litgpt/model.py b/litgpt/model.py index 83e80a8ca0..5454d1e919 100644 --- a/litgpt/model.py +++ b/litgpt/model.py @@ -11,10 +11,10 @@ from typing import Any, List, Optional, Tuple, Union import torch +import torch.distributed as dist import torch.nn as nn import torch.nn.functional as F from typing_extensions import Self -import torch.distributed as dist from litgpt.config import Config from litgpt.scripts.convert_hf_checkpoint import qkv_reassemble @@ -273,7 +273,11 @@ def __init__( ) self.norm_1 = config.norm_class(config.n_embd, eps=config.norm_eps) - self.attn = CausalSelfAttention(config, block_idx) if not config.latent_attention else MultiHeadLatentAttention(config, block_idx) + self.attn = ( + CausalSelfAttention(config, block_idx) + if not config.latent_attention + else MultiHeadLatentAttention(config, block_idx) + ) self.post_attention_norm = ( config.norm_class(config.n_embd, eps=config.norm_eps) if config.post_attention_norm else nn.Identity() ) @@ -706,8 +710,8 @@ def forward( k = torch.cat([k, k_for_rope], dim=-1) v = v # already reshaped before the split - if input_pos is not None: # Indicates inference and KV cache usage - if not isinstance(self.kv_cache, KVCache): # Check for the correct cache type + if input_pos is not None: # Indicates inference and KV cache usage + if not isinstance(self.kv_cache, KVCache): # Check for the correct cache type raise TypeError("You need to call `gpt.set_kv_cache()` with the appropriate KVCache for MLA.") k_full_cached, v_full_cached = self.kv_cache(input_pos, k, v) @@ -770,7 +774,7 @@ def build_kv_cache( v_head_dim = self.v_dim # To match DeepSeekV3's caching of K/V for all query heads - num_cached_kv_heads = self.config.n_head + num_cached_kv_heads = self.config.n_head k_shape = (batch_size, num_cached_kv_heads, max_seq_length, k_head_dim) v_shape = (batch_size, num_cached_kv_heads, max_seq_length, v_head_dim) @@ -854,6 +858,7 @@ def forward(self, x: torch.Tensor) -> torch.Tensor: y[token_idx] += probs[token_idx, expert_idx, None] * expert(x[token_idx]) return y.view(B, T, C) + class DeepseekV3MoEGate(nn.Module): def __init__(self, config): super().__init__() @@ -869,13 +874,9 @@ def __init__(self, config): # topk selection algorithm self.norm_topk_prob = config.norm_topk_prob self.gating_dim = config.hidden_size - self.weight = nn.Parameter( - torch.empty((self.n_expert, self.gating_dim)) - ) + self.weight = nn.Parameter(torch.empty((self.n_expert, self.gating_dim))) if self.topk_method == "noaux_tc": - self.e_score_correction_bias = nn.Parameter( - torch.empty((self.n_expert)) - ) + self.e_score_correction_bias = nn.Parameter(torch.empty(self.n_expert)) self.reset_parameters() def reset_parameters(self) -> None: @@ -887,56 +888,43 @@ def forward(self, x: torch.Tensor): bsz, seq_len, h = x.shape ### compute gating score x = x.view(-1, h) - logits = nn.Linear( - x.type(torch.float32), self.weight.type(torch.float32), None - ) + logits = nn.Linear(x.type(torch.float32), self.weight.type(torch.float32), None) if self.scoring_func == "sigmoid": scores = logits.sigmoid() else: - raise NotImplementedError( - f"insupportable scoring function for MoE gating: {self.scoring_func}" - ) + raise NotImplementedError(f"insupportable scoring function for MoE gating: {self.scoring_func}") ### select top-k experts if self.topk_method == "noaux_tc": assert not self.training scores_for_choice = scores.view(bsz * seq_len, -1) + self.e_score_correction_bias.unsqueeze(0) group_scores = ( - scores_for_choice.view(bsz * seq_len, self.n_group, -1).topk(2, dim=-1)[0].sum(dim = -1) + scores_for_choice.view(bsz * seq_len, self.n_group, -1).topk(2, dim=-1)[0].sum(dim=-1) ) # [n, n_group] - group_idx = torch.topk( - group_scores, k=self.topk_group, dim=-1, sorted=False - )[ - 1 - ] # [n, top_k_group] + group_idx = torch.topk(group_scores, k=self.topk_group, dim=-1, sorted=False)[1] # [n, top_k_group] group_mask = torch.zeros_like(group_scores) # [n, n_group] group_mask.scatter_(1, group_idx, 1) # [n, n_group] score_mask = ( group_mask.unsqueeze(-1) - .expand( - bsz * seq_len, self.n_group, self.n_expert // self.n_group - ) + .expand(bsz * seq_len, self.n_group, self.n_expert // self.n_group) .reshape(bsz * seq_len, -1) ) # [n, e] tmp_scores = scores_for_choice.masked_fill(~score_mask.bool(), float("-inf")) # [n, e] - _, topk_idx = torch.topk( - tmp_scores, k=self.top_k, dim=-1, sorted=False - ) + _, topk_idx = torch.topk(tmp_scores, k=self.top_k, dim=-1, sorted=False) topk_weight = scores.gather(1, topk_idx) else: - raise NotImplementedError( - f"insupportable TopK function for MoE gating: {self.topk_method}" - ) + raise NotImplementedError(f"insupportable TopK function for MoE gating: {self.topk_method}") ### norm gate to sum 1 if self.top_k > 1 and self.norm_topk_prob: denominator = topk_weight.sum(dim=-1, keepdim=True) + 1e-20 topk_weight = topk_weight / denominator - topk_weight = topk_weight * self.routed_scaling_factor # must multiply the scaling factor + topk_weight = topk_weight * self.routed_scaling_factor # must multiply the scaling factor return topk_idx, topk_weight + class DeepseekV3MoE(nn.Module): """ A mixed expert module containing shared experts. @@ -955,11 +943,8 @@ def __init__(self, config): self.experts = nn.ModuleList( [ ( - LLaMAMLP( - config, intermediate_size=config.moe_intermediate_size - ) - if i >= self.ep_rank * self.experts_per_rank - and i < (self.ep_rank + 1) * self.experts_per_rank + LLaMAMLP(config, intermediate_size=config.moe_intermediate_size) + if i >= self.ep_rank * self.experts_per_rank and i < (self.ep_rank + 1) * self.experts_per_rank else None ) for i in range(config.n_expert) @@ -970,19 +955,12 @@ def __init__(self, config): self.experts_per_rank = config.n_expert self.ep_rank = 0 self.experts = nn.ModuleList( - [ - LLaMAMLP( - config, intermediate_size=config.moe_intermediate_size - ) - for i in range(config.n_expert) - ] + [LLaMAMLP(config, intermediate_size=config.moe_intermediate_size) for i in range(config.n_expert)] ) self.gate = DeepseekV3MoEGate(config) if config.n_shared_experts is not None: intermediate_size = config.moe_intermediate_size * config.n_shared_experts - self.shared_experts = LLaMAMLP( - config=config, intermediate_size=intermediate_size - ) + self.shared_experts = LLaMAMLP(config=config, intermediate_size=intermediate_size) def forward(self, x: torch.Tensor): identity = x @@ -1006,17 +984,9 @@ def moe_infer(self, x, topk_ids, topk_weight): sorted_tokens_shape = sorted_tokens.shape if self.ep_size > 1: tokens_per_ep_rank = tokens_per_expert.view(self.ep_size, -1).sum(dim=1) - tokens_per_expert_group = tokens_per_expert.new_empty( - tokens_per_expert.shape[0] - ) + tokens_per_expert_group = tokens_per_expert.new_empty(tokens_per_expert.shape[0]) dist.all_to_all_single(tokens_per_expert_group, tokens_per_expert) - output_splits = ( - tokens_per_expert_group.view(self.ep_size, -1) - .sum(1) - .cpu() - .numpy() - .tolist() - ) + output_splits = tokens_per_expert_group.view(self.ep_size, -1).sum(1).cpu().numpy().tolist() gathered_tokens = sorted_tokens.new_empty( tokens_per_expert_group.sum(dim=0).cpu().item(), sorted_tokens.shape[1] ) @@ -1025,9 +995,7 @@ def moe_infer(self, x, topk_ids, topk_weight): list(gathered_tokens.split(output_splits)), list(sorted_tokens.split(input_split_sizes)), ) - tokens_per_expert_post_gather = tokens_per_expert_group.view( - self.ep_size, self.experts_per_rank - ).sum(dim=0) + tokens_per_expert_post_gather = tokens_per_expert_group.view(self.ep_size, self.experts_per_rank).sum(dim=0) gatherd_idxs = np.zeros(shape=(gathered_tokens.shape[0],), dtype=np.int32) s = 0 for i, k in enumerate(tokens_per_expert_group.cpu().numpy()): @@ -1072,6 +1040,7 @@ def moe_infer(self, x, topk_ids, topk_weight): ) return final_out + def build_rope_cache( seq_len: int, n_elem: int, @@ -1301,7 +1270,6 @@ def reset_parameters(self) -> None: torch.nn.init.zeros_(self.v) - def build_mask_cache(max_seq_length: int, device: Optional[torch.device] = None) -> torch.Tensor: ones = torch.ones((max_seq_length, max_seq_length), device=device, dtype=torch.bool) return torch.tril(ones).unsqueeze(0).unsqueeze(0)