From 63359703211f01292ebd7dce0e86b9bda69771b5 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Wed, 17 Jul 2024 02:39:39 +0100 Subject: [PATCH 01/24] KEP-2170: Kubeflow Training V2 API Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 1362 +++++++++++++++++ .../trainjob-diagram.jpg | Bin 0 -> 153020 bytes 2 files changed, 1362 insertions(+) create mode 100644 docs/proposals/2170-kubeflow-training-v2/README.md create mode 100644 docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.jpg diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md new file mode 100644 index 0000000000..cd9827aa68 --- /dev/null +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -0,0 +1,1362 @@ +# KEP-2170: Kubeflow Training V2 API + +## Authors + +- Andrey Velichkevich - [@andreyvelich](https://github.com/andreyvelich) +- Yuki Iwai - [@tenzen-y](https://github.com/tenzen-y) + +Creation date: 2024-07-16 + +Google doc: https://bit.ly/3WzjTlw + +## Overview + +This document discusses the new Kubeflow Training V2 API. + +When we built the +[Kubeflow Training Operator a couple of years ago](https://docs.google.com/document/d/1x1JPDQfDMIbnoQRftDH1IzGU0qvHGSU4W6Jl4rJLPhI/edit?usp=sharing), +Kubernetes lacked better features to support distributed machine learning (ML) training, such as +SuccessPolicy and RestartPolicy (FailurePolicy). Recently, the Kubernetes community launched the +working group Batch, and then the working group actively worked on evolving the batch/v1 `Job` API +and built [a new `JobSet`](https://github.com/kubernetes-sigs/jobset) API to manage groups of `Jobs`. + +This document consolidates efforts for the Cloud Native ML Training between Kubeflow and Kubernetes +communities. + +## Motivation + +We often implement features similar to batch/v1 `Job`, such as “suspend”, on the Training Operator +side since the Training Operator creates blocks of plain Pod and Service for each rank once +Kubeflow Jobs are created. However, if we continue taking the same approach (re-inventing the wheel), +the maintenance costs will continue to increase. + +It would be better to replace infrastructure layers with `JobSet` to avoid re-inventing the wheel +and improve the Training Operator + +Additionally, introducing `JobSet` as an infrastructure layer would allow us to introduce batch +workload features such as +[the PodFailurePolicy](https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-failure-policy) +and [the PodDisruptionCondition](https://kubernetes.io/docs/concepts/workloads/controllers/job/#handling-pod-and-container-failures) +easily. + +Please also see the [Kubernetes JobSet and Kubeflow Training Operator collaboration document](https://docs.google.com/document/d/1C2ev7yRbnMTlQWbQCfX7BCCHcLIAGW2MP9f7YeKl2Ck/edit?usp=sharing). + +### User Value + +In addition to the above motivation, we will address the following user feedback while implementation: + +- Confusion around Workers: https://github.com/kubeflow/training-operator/issues/1790 +- Support batch/v1 `Job` features: https://github.com/kubeflow/training-operator/issues/1718 +- ExitCodes for PodFailurePolicy: https://github.com/kubeflow/training-operator/issues/1749 +- Migrate to MPI V2 API: https://github.com/kubeflow/training-operator/issues/1906 + +### Personas + +We can identify the following personas of Training Operator: + +1. **DevOps Engineer**. They are familiar with Kubernetes concepts and they know how to manage the + Kubernetes workloads. Usually, they are not experts in ML frameworks and ML algorithms. +1. **MLOps Engineer**. They are familiar with ML frameworks and they know how to configure + distributed PyTorch settings such as rendezvous backends or MPI configuration. Usually, they are + not experts in Kubernetes and ML algorithms. +1. **Data Scientists**. They create model architectures and advanced ML algorithms to train models. + They prefer to use Python for their work. They are aware of `torch.nn` APIs, but not with + `torch.distributed` and Kubernetes concepts to scale model training. + +Based on the above personas, we should build an API that everyone will benefit from. + +### Goals + +- Introduce the `TrainingRuntime` and `ClusterTrainingRuntime` APIs that will store blueprints + for model training and LLM fine-tuning using various ML frameworks. These runtimes will be built + on top of **JobSet** APIs with additional functionality for special use-cases. + For example, training using MPI orchestration. +- Introduce Kubeflow `TrainJob` API that allows to reuse these runtimes and quickly start a new + training job without understanding complex Kubernetes APIs. +- Update Kubeflow Training SDK to allow data scientists quickly create and monitor `TrainJobs`. +- Create community-supported `ClusterTrainingRuntime` for distributed training with PyTorch and MPI. +- Create community-supported `ClusterTrainingRuntime` for LLM fine-tuning for various foundational + models (e.g. Mistral, LLama-70b, Gemma-7b). +- Work on the following JobSet improvements: https://github.com/kubernetes-sigs/jobset/issues/463 and https://github.com/kubernetes-sigs/jobset/issues/572 + +### Non-Goals + +- Support MPI V1 implementation. +- Distributed training for TensorFlow, XGboost, JAX, and PaddlePaddle will be added after initial + implementation. +- Migrate Kubeflow V1 controller to use `JobSet`. + +## Design Details + +We propose these APIs: + +- **`TrainJob`**: A single API which allows data scientists to initiate a training and fine-tuning + job from the pre-deployed training runtime. It allows users to tweak configurations for their + training jobs such as model parameters, dataset parameters, or trainer configuration. + The main goal is to hide unnecessary Kubernetes complexity for data scientists. + +- **`TrainingRuntime`** and **`ClusterTrainingRuntime`**: Set of blueprints for how to start various + types of training or fine-tuning jobs. Runtimes are managed by Platform Engineers and allow them + to configure infrastructure parameters that are required for the **TrainJob**. + For example, failure policy or gang-scheduling. + +The below diagram shows which resources will be created for LLM fine-tuning with PyTorch. + +![trainjob-diagram](./trainjob-diagram.jpg) + +### Worker and Node Definition + +To better understand what does Nodes and Worker mean in the diagram above, +the following table explains naming that each framework or technology uses: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ML Framework or Technology + Definition of a Single Device (GPU) + Definition of a Single VM + Start Command + Reference Docs +
Kubernetes + Container Resource Unit + Pod’s Container + Any + Resource units in K8s +
PyTorch + Worker +

+(--nproc-per-node) +

Node +

+(--nnodes) +

torchrun + PyTorch Elastic +
MPI + Slot +

+(--np) +

Node +

+(--host) +

mpirun + Reference for OpenMPI +
TensorFlow + Worker + Worker Pool +

+Cluster Spec +

python + TensorFlow Distributed +
Jax + Process jax.local_devices() + Host +

+jax.devices() +

python or mpirun + Jax Distributed +
PaddlePaddle + Worker + Node + python -m paddle.distributed.launch + Paddle Distributed +
XGBoost + Worker + Not Applicable + python + Rabit Tracker for c10d +
DeepSpeed + Slot + Node +

+(--num_nodes) +

deepspeed + DeepSpeed Distributed +
+ +## The TrainJob API + +The `TrainJob` exposes APIs that data scientist can override in `TrainingRuntime` to create training job: + +```golang +type TrainJob struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the desired state of TrainJob. + Spec TrainJobSpec `json:"spec"` + + // Status defines the current state of TrainJob. + Status TrainJobStatus `json:"status,omitempty"` +} + +type TrainJobSpec struct { + // Reference to the Training Runtime. + TrainingRuntimeRef *TrainingRuntimeRef `json:"trainingRuntimeRef"` + + // Parameters that data scientists can override + TrainerConfig *TrainerConfig `json:"trainerConfig,omitempty"` + + // Configuration for training dataset + DatasetConfig *DatasetConfig `json:"datasetConfig,omitempty"` + + // Configuration for the pre-trained model and location for model output + ModelConfig *ModelConfig `json:"modelConfig,omitempty"` + + // Custom metadata to apply for Job, JobSet, etc. + Labels map[string]string `json:"labels,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` +} + +type TrainingRuntimeRef struct { + // Name for the training runtime. + Name string `json:"name"` + // Namespace for the runtime. + // If namespace is set, TrainingRuntime is used. Otherwise, ClusterTrainingRuntime is used. + Namespace string `json:"namespace,omitempty"` +} + +type TrainJobStatus struct { + // Conditions for the TrainJob + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +``` + +This table explain rationale for each `TrainJob` parameter: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Parameter + What is it ? +
TrainingRuntimeRef + Reference to the existing TrainingRuntime that pre-deployed by platform engineers +
TrainerConfig + Configuration for the Trainer such as image, number of nodes, accelerators. +
ModelConfig + Configuration for the pre-trained model and location for model output +
DatasetConfig + Configuration for the dataset that will be used to train or fine-tune model +
Labels and Annotations + Custom metadata that needs to be applied to the TrainJob resources: JobSet, Job, Pods. +
PodSpecOverrides + Custom overrides that are specific to the TrainJob and need to be applied to the + TrainJob resources. For example, the user identity. Usually, it is managed by + custom admission webhooks that inject data to the TrainJob after user creates it + via Python SDK or kubectl +
+ +### Example of TrainJob + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: TrainJob +metadata: + name: torch-ddp + namespace: tenant-alpha +spec: + trainingRuntimeRef: + name: torch-distributed-multi-node + trainerConfig: + image: docker.io/custom-training + command: + - torchrun train.py + numNodes: 5 + resourcesPerNode: + requests: + nvidia.com/gpu: 2 +``` + +The above command will be converted as follows: + +```bash +torchrun --nnodes=5 --nproc-per-node=2 train.py +``` + +Additionally, the Kubeflow Training SDK allows to create the above `TrainJob` using the Python API: + +```python +def train_func(): + import torch + class Net(torch.nn.Module): + """Create the PyTorch Model""" + ... + model = Net() + + # Attach model to the distributor + torch.distributed.init_process_group(backend="nccl") + model = torch.nn.parallel.DistributedDataParallel(model) + + # Train model + model.train() + +# Use Kubeflow SDK to create TrainJob. +from kubeflow.training import TrainingClient + +TrainingClient().train( + name="torch-ddp", + func=train_func, + num_nodes=5, + resources_per_node={"gpu": 2}, +) +``` + +### Example of LLM Fine-Tuning + +This example shows how to create `TrainJob` to fine-tune LLama 7b: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: TrainJob +metadata: + name: tune-llama-with-yelp + namespace: tenant-alpha +spec: + trainingRuntimeRef: + name: torch-tune-llama-7b + datasetConfig: + s3: + bucket: datasets + path: custom-datasets/yelp-review +``` + +### The Trainer Config API + +The `TrainerConfig` represents the APIs that data scientists can use to configure trainer settings: + +```golang +type TrainerConfig struct { + + // Docker image for the Trainer. + Image string `json:"image,omitempty"` + + // Command for the training container. + // Validate that command contains torchrun or mpirun. + Command []string `json:"command,omitempty"` + + // Args for the training container. + Args []string `json:"args,omitempty"` + + // Env for the training container. + Env []corev1.EnvVar `json:"env,omitempty"` + + // Number of training nodes. + NumNodes *int32 `json:"numNodes,omitempty"` + + // Resource for each node. + ResourcesPerNode []corev1.resoruces `json:"resourcesPerNode,omitempty"` + + // Number of processes in a single node. + // By default this value == number of GPUs in resources limits. + NumProcPerNode *int32 `json:"numProcPerNode,omitempty"` +} +``` + +The following table explains how `TrainingRuntime` parameters will be overridden with `TrainerConfig`. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TrainerConfig Parameter + TrainingRuntime Parameter +
.image + .spec.replicatedJobs[name=’Node’].template.spec.template.spec.containers[name=’trainer’].image +
.command + .spec.replicatedJobs[name=’Node’].template.spec.template.spec.containers[name=’trainer’].command +
.args + .spec.replicatedJobs[name=’Node’].template.spec.template.spec.containers[name=’trainer’].args +
.env + .spec.replicatedJobs[name=’Node’].template.spec.template.spec.containers[name=’trainer’].env +
.numNodes + .spec.numNodes +
.resourcesPerNode + .spec.replicatedJobs[name=’Node’].template.spec.template.spec.containers[name=’trainer’].resources +
+ +### The Dataset Config API + +The `DatasetConfig` represents the APIs that data scientists can use to configure dataset location. + +```golang +type DatasetConfig struct { + + // One of the following can be set. + HFDatasetProvider *kubeflowv1.HFDatasetProvider `json:"huggingface,omitempty"` + + S3DatasetProvider *kubeflowv1.S3DatasetProvider `json:"s3,omitempty"` + + // (Optional). We can support the Iceberg dataset using PyIceberg. + IcebergDatasetProvider *kubeflowv1.IcebergDatasetProvider `json:"iceberg,omitempty"` +} + +type HFDatasetProvider struct { + // Path to the HF dataset. For example: yelp-review-full + RepoId string `json:"repoId"` + + // Whether the dataset needs to be splitted: train/val. E.g. split=train[:50000] + Split string `json:"split,omitempty"` + + // Secret must contain HF_TOKEN secret. + // If the secret object contains more than one secret, all secrets are passed. + AccessTokenSecretRef corev1.SecretReference `json:"accessToken,omitempty"` +} + + +type S3DatasetProvider struct { + // S3 endpoint. + EndpointUrl string `json:"endpointUrl,omitempty"` + + // Name of the S3 bucket. + BucketName string `json:bucketName` + + // Path to the dataset. All files will be downloaded in that path. + Path string `json:path` + + // Secret must contain AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY secret. + // If the secret object contains more than one secret, all secrets are passed. + // Otherwise, IRSA can be used to access S3. + AccessTokenSecretRef corev1.SecretReference `json:"accessToken,omitempty"` +} +``` + +The following table explains how `TrainingRuntime` parameters will be overridden with the +`DatasetConfig`. + +All parameters will be set for this container: + +```yaml +.spec.replicatedJobs[name='Initializer'].template.spec.template.spec.containers[name=dataset-initializer] +``` + +#### The HuggingFace Provider + +For the HuggingFace provider environment variable `PROVIDER=hf`. + + + + + + + + + + + + + + +
DatasetConfig Parameter + TrainingRuntime Parameter +
.huggingface.repoId + .env[REPO_ID] +
.huggingface.split + .env[SPLIT] +
+ +#### The S3 Provider + +For the S3 provider environment variable `PROVIDER=s3`. + + + + + + + + + + + + + + + + + + +
DatasetConfig Parameter + TrainingRuntime Parameter +
.s3.endpointUrl + .env[ENDPOINT_URL] +
.s3.bucketName + .env[BUCKET_NAME] +
.s3.path + .env[PATH] +
+ +### The Model Config API + +The `ModelConfig` represents the APIs that data scientists can use to configure pre-trained model +input and output location. + +```golang +type ModelConfig struct { + // One of the following can be set. + HFModelProvider *kubeflowv1.HFModelProvider `json:"huggingface,omitempty"` + + // Potential output location for fine-tuned/trained model. + OutputArtifact string +} + + +type HFModelProvider struct { + // Path to the pre-trained model. google-bert/bert-base-uncased + RepoID string `json:"repoID"` + + // TODO (andreyvelich): Do we want to support any Transformer ? + TransformerType string `json:"transformerType,omitempty"` + + // Secret must contain HF_TOKEN secret. + // If the secret object contains more than one secret, all secrets are passed. + AccessTokenSecretRef corev1.SecretReference `json:"accessToken,omitempty"` +} +``` + +The following table explains how `TrainingRuntime` parameters will be overridden with `ModelConfig`. + +All parameters will be set for this container: + +```yaml +.spec.replicatedJobs[name='Initializer'].template.spec.template.spec.containers[name=model-initializer] +``` + +#### The HuggingFace Provider + +For the HuggingFace provider environment variable `PROVIDER=hf`. + + + + + + + + + + + + + + +
DatasetConfig Parameter + TrainingRuntime Parameter +
.huggingface.repoId + .env[REPO_ID] +
.huggingface.split + .env[SPLIT] +
+ +### The Pod Spec Overrides APIs + +The `PodSpecOverrides` represents overrides for the `TrainingRuntime` when `TrainJob` is created. +These parameters can include the user's identity or PVC. + +Usually, these parameters should not be configured by the user and should be attached during the +orchestration (e.g. using Kubernetes admission webhooks or custom clients). + +In the future, we can add more parameters if we find use-cases when it is required. + +```golang +type PodSpecOverride struct { + // Name of the training replica in the training runtime template to override + TargetReplicatedJobs []string `json:"targetReplicatedJobs"` + + // Override parameters for Containers. + Containers []Container `json:"container,omitempty"` + + // Override parameters for InitContainers. + InitContainer []Container `json:"initContainer,omitempty"` + + // Override parameters for volumes. + Volumes []corev1.Volume `json:"volume,omitempty"` + + // Custom Service Account + ServiceAccountName string `json:"serviceAccountName,omitempty"` +} + +// Override for each container. +// Parameters from TrainerConfig, DatasetConfig, and ModelConfig will take precedence. +type Container struct { + + // Name for the container. + Name string `json:"name"` + + // Command for the container. + Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"` + + // Args for the container. + Args []string `json:"args,omitempty"` + + // Env for the container. + Env []corev1.EnvVar `json:"env,omitempty"` + + // Env for the container. + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` + + // Override parameters for volume mounts. + VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"` +} +``` + +#### Example of TrainJob with Overrides + +This example shows how to override user-identity for sidecar container and add volume to the +trainer container. + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: TrainJob +metadata: + name: pytorch-distributed + namespace: tenant-alpha +spec: + trainingRuntimeRef: + name: pytorch-distributed-gpu + kind: ClusterTrainingRuntime + trainerConfig: + image: docker.io/custom-training + podSpecOverrides: + - targetReplicatedJobs: + - initializer + node + containers: + - name: user-identity + value: 123 + - name: trainer + volumeMounts: + - name: user-123-volume + mountPath: /workspace + volumes: + - name: user-123-volume + persistentVolumeClaim: + claimName: user-123-volume +``` + +## The Training Runtime API + +The `TrainingRuntime` is the pre-created configurations of model training on the cluster, +representing as blueprints. For example, Elastic PyTorch training, MPI DeepSpeed configuration, +BERT LLM Fine-Tuning. + +These blueprints can be deployed within the Training Operator control plane and stored in a Kubeflow +public repository that users can apply to their clusters. + +Platform or ML engineers can tweak existing blueprint, based on their requirements. For example, +using custom configurations. + +The Kubeflow Training Operator can maintain more Training Runtimes when the community is ready to +support them. For example, runtimes for [Jax](https://jax.readthedocs.io/en/latest/index.html) or +[MLX](https://ml-explore.github.io/mlx/build/html/index.html). Initially, we will support: PyTorch, +MPI, TensorFlow, XGBoost, and PaddlePaddle. + +The `TrainingRuntime` is immutable, and so to make a change, a new version of the `TrainingRuntime` +must be created and then changing the `TranJob` to point to the new version. +This provides control as to how changes to runtimes propagate to existing training jobs. +For example, when training is running for a long time (e.g. 1-2 months). + +In the future implementation, we will introduce a revision control mechanism similar to +[Kubernetes Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment) +to control versions of `TrainingRuntime` and enable rolling updates. + +We are going to create two CRDs: `TrainingRuntime` and `ClusterTrainingRuntime`. These runtimes have +exactly the same APIs, but the first one is the namespace-scoped, the second is the cluster-scoped. +If `trainingRuntimeRef` in `TrainJob` has the namespace, controller will use the `TrainingRuntime`, +otherwise it will use the `ClusterTrainingRuntime`. + +```golang +type TrainingRuntime struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Framework specific parameters. + MLSpec *MLSpec `json:"mlSpec,omitempty"` + + // Number of nodes to execute training. + NumNodes int `json:"numNodes,omitempty"` + + // JobSet spec. + JobSetSpec *batchv1.JobSetSpec `json:",inline"` + + // For gang-scheduling using volcano or scheduler plugins, supported for all frameworks. + GangScheduler *kubeflowv1.GangScheduler `json:"gangScheduler,omitempty"` +} + +// One of the specs can be selected. +type MLSpec struct { + + // Custom Spec for Torch + TorchSpec *TorchSpec `json:"torchSpec,omitempty"` + + // Custom Spec for MPI + MPISpec *MPISpec `json:"mpiSpec,omitempty"` +} +``` + +### The Gang Scheduler API + +Gang scheduler plugin is used to create appropriate `PodGroup` for Volcano or scheduler plugins. + +```golang +type GangScheduler struct { + // Plugin for gang scheduling. + Plugin *GangSchedulerPlugin `json:plugin,omitempty"` + + // Time threshold to schedule PodGroup for gang scheduling. + ScheduleTimeoutSeconds string `json:scheduleTimeoutSeconds,omitempty"` +} + +type GangSchedulerPlugin string + +const ( + GangSchedulerPluginVolcano GangSchedulerPlugin = "volcano" + GangSchedulerPluginSP GangSchedulerPlugin = "scheduler-plugins" +) +``` + +### The Torch Spec API + +The `TorchSpec` API represents the configuration for the PyTorch distributed training. This configuration +allows platform engineers to explicitly configure `torchrun` setting. + +The distributed parameters are taken from the +[PyTorch distributed launch run](https://github.com/pytorch/pytorch/blob/94dc3253a0fefbfb95fbe467ddd628e4c2eb08d7/torch/distributed/run.py). + +For Elastic Training we will always pass the following parameters: + +```bash +--rdzv-backend=c10d + +--rdzv-id will be set automatically. + +--rdzv-endpoint will always point to the node-0 Pod. +``` + +Since the [etcd and etcd-v2 are legacy rendezvous](https://pytorch.org/docs/stable/elastic/run.html#note-on-rendezvous-backend), +we won't support them in `TorchSpec`. We can introduce them in the future if users will require them. + +```golang +// TorchSpec represents the configuration for PyTorch. +type TorchSpec struct { + + // Number of Procs per Node. + NumProcPerNode int `json:"numProcPerNode,omitempty"` + + // Used for single-node multi-worker training + Standalone bool `json:"standalone,omitempty"` + + // Torch Elastic Policy. + ElasticPolicy *TorchElasticPolicy `json:"elasticPolicy,omitempty"` +} + +// If the Elastic Policy is set, the numNodes parameter is ignored. +// --nnodes=minNodes:maxNodes +type TorchElasticPolicy struct { + + // The limits to restart TrainJob. + // Insert it to the JobSet.spec.failurePolicy.maxRestarts + MaxRestarts *in32 `json:"maxRestarts,omitempty"` + + // Min number of nodes for HPA and torchrun. + MinNodes *in32 `json:"minNodes,omitempty"` + + // Max number of nodes for HPA and torchrun. + MaxNodes *in32 `json:"maxNodes,omitempty"` + + // Metrics for scale up and down replicas. + Metrics []autoscalingv2.MetricSpec `json:"metrics,omitempty"` +} +``` + +### The MPI Spec API + +The `MPISpec` API represents the configuration for training using MPI orchestration. +E.g. creation of host-files and SSH keys. Using MPI might be more efficient for training on HPC +clusters or for some ML frameworks (e.g. [MLX distributed with MPI](https://ml-explore.github.io/mlx/build/html/usage/distributed.html)). + +We will fully migrate to the MPI Operator V2 functionality as part of this KEP. +Check [the proposal for the MPI V2 APIs.](https://github.com/kubeflow/mpi-operator/blob/master/proposals/scalable-robust-operator.md) + +```golang +type MPISpec struct { + // Number of Procs per Node. + NumProcPerNode int `json:"numProcPerNode,omitempty"` + + // MPI Implementation to create appropriate host-files. + // Can be one of OpenMPI, Intel, or MPICH. + MPIImplementation MPIImplementation `json:"mpiImplementation,omitempty"` + + // Directory where SSH keys are mounted. + SSHAuthMountPath string `json:"SSHAuthMountPath,omitempty"` +} + +type MPIImplementation string + +const ( + MPIImplementationOpenMPI MPIImplementation = "OpenMPI" + MPIImplementationIntel MPIImplementation = "Intel" + MPIImplementationMPICH MPIImplementation = "MPICH" +) +``` + +### Supported Runtimes by Community + +Kubeflow community are planning to support the following runtimes. + +#### PyTorch Distributed Runtime + +Initially, we will maintain only multi-node multi-worker runtime and PyTorch Elastic. + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-distributed-multi-node +spec: + mlSpec: + torch: + numProcPerNode: 5 + replicatedJobs: + - name: node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/pytorch-mnist + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + command: + - torchrun train.py +``` + +Example of usage: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: TrainJob +metadata: + name: torch-distributed-multi-node + namespace: tenant-alpha +spec: + trainingRuntimeRef: + name: pytorch-distributed + trainerConfig: + resourcesPerNode: + requests: + nvidia.com/gpu: 1 + args: + - num-epochs=5 +``` + +#### PyTorch Elastic Runtime + +Training runtime for PyTorch Elastic: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-distributed-elastic +spec: + mlSpec: + torchSpec: + elasticPolicy: + minNodes: 5 + maxNodes: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 + replicatedJobs: + - name: node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/pytorch-mnist + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + command: + - torchrun train.py +``` + +#### Additional PyTorch Runtimes + +The following runtimes can be maintained in the future. + +Single worker training: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-simple +spec: + replicatedJobs: + - name: node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/pytorch-mnist + command: + - torchrun train.py +``` + +Single node multi worker training: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-distributed-single-worker +spec: + mlSpec: + torch: + numProcPerNode: 5 + standalone: True + replicatedJobs: + - name: Node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/pytorch-mnist + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + command: + - torchrun train.py +``` + +#### LLM Fine-Tuning Runtimes + +In the future, we can consider to use [the `torchtune` CLI](https://github.com/pytorch/torchtune/tree/main) +for Fine-Tuning with PyTorch. + +##### Llama 7b + +The following runtime can be used for Llama 7b model. + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-tune-llama-7b +spec: + numNodes: 1 + startupPolicy: + startupPolicyOrder: InOrder + replicatedJobs: + - name: Initializer + template: + spec: + template: + spec: + containers: + - name: dataset-initializer + image: docker.io/kubeflow/dataset-initializer + env: + - name: DATASET_PROVIDER + value: hf + - name: REPO_ID + value: tatsu-lab/alpaca + volumeMounts: + - mountPath: /workspace/dataset + name: dataset-initializer + - name: model-initializer + image: docker.io/kubeflow/model-initializer + env: + - name: MODEL_PROVIDER + value: hf + - name: REPO_ID + value: meta-llama/Llama-2-7b + - name: TRANSFORMER_TYPE + value: AutoModelForCausalLM + volumeMounts: + - mountPath: /workspace/model + name: model-initializer + volumes: + - name: dataset-initializer + persistentVolumeClaim: + claimName: dataset-initializer + - name: model-initializer + persistentVolumeClaim: + claimName: model-initializer + - name: Node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/llm-trainer + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + - name: TRANSFORMER_TYPE + value: AutoModelForCausalLM + - name: LORA_CONFIG + value: | + {"peft_type": "LORA", "r": 8, "lora_alpha": 16} + command: + - torchrun hf_llm_training.py + resources: + limits: + nvidia.com/gpu: 2 + volumeMounts: + - mountPath: /workspace/dataset + name: dataset-initializer + - mountPath: /workspace/model + name: model-initializer + volumes: + - name: dataset-initializer + persistentVolumeClaim: + claimName: dataset-initializer + - name: model-initializer + persistentVolumeClaim: + claimName: model-initializer +``` + +##### Gemma 7b + +The following runtime can be used for Gemma fine-tuning. + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-tune-gemma-7b +spec: + numNodes: 1 + startupPolicy: + startupPolicyOrder: InOrder + replicatedJobs: + - name: Initializer + template: + spec: + template: + spec: + containers: + - name: dataset-initializer + image: docker.io/kubeflow/dataset-initializer + env: + - name: DATASET_PROVIDER + value: hf + - name: REPO_ID + value: tatsu-lab/alpaca + volumeMounts: + - mountPath: /workspace/dataset + name: dataset-initializer + - name: model-initializer + image: docker.io/kubeflow/model-initializer + env: + - name: MODEL_PROVIDER + value: hf + - name: REPO_ID + value: google/gemma-7b + - name: TRANSFORMER_TYPE + value: AutoModelForCausalLM + volumeMounts: + - mountPath: /workspace/model + name: model-initializer + volumes: + - name: dataset-initializer + persistentVolumeClaim: + claimName: dataset-initializer + - name: model-initializer + persistentVolumeClaim: + claimName: model-initializer + - name: Node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/llm-trainer + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + - name: TRANSFORMER_TYPE + value: AutoModelForCausalLM + - name: LORA_CONFIG + value: | + {"peft_type": "LORA", "r": 8, "lora_alpha": 16} + command: + - torchrun hf_llm_training.py + resources: + limits: + nvidia.com/gpu: 2 + volumeMounts: + - mountPath: /workspace/dataset + name: dataset-initializer + - mountPath: /workspace/model + name: model-initializer + volumes: + - name: dataset-initializer + persistentVolumeClaim: + claimName: dataset-initializer + - name: model-initializer + persistentVolumeClaim: + claimName: model-initializer +``` + +#### MPI Runtime + +For MPI, we can add support the `DeepSpeed` runtimes. + +Example of simple OpenMPI runtime: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: mpi-simple +spec: + mlSpec: + mpi: + mpiImplementation: OpenMPI + numProcPerNode: 5 + numNodes: 5 + replicatedJobs: + - name: Launcher + template: + spec: + template: + spec: + containers: + - name: mpi-launcher + image: docker.io/mpi-launch + - name: Node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/mpi-training + command: + - mpirun -np 2 train.py +``` + +#### TensorFlow Runtime + +_Will be added after initial implementation for PyTorch._ + +#### XGBoost Runtime + +_Will be added after initial implementation for PyTorch._ + +#### Paddle Runtime + +_Will be added after initial implementation for PyTorch._ + +#### Jax Runtime + +_Will be added after initial implementation for PyTorch._ + +## Migration from Kubeflow Training V1 + +These API changes will not be compatible with Training Operator V1 APIs. Thus, existing users have +to migrate to the newer APIs. Kubeflow community will provide instructions on how to migrate existing +training jobs to the new APIs. + +### PyTorchJob Migration + +The following example shows how to migrate from `PyTorchJob` to `TrainingRuntime`: + +```yaml +apiVersion: kubeflow.org/v1 +kind: PyTorchJob +metadata: + name: pytorch-simple + namespace: kubeflow +spec: + pytorchReplicaSpecs: + Master: + replicas: 1 + restartPolicy: OnFailure + template: + spec: + containers: + - name: pytorch + image: docker.io/kubeflowkatib/pytorch-mnist:v1beta1-45c5727 + imagePullPolicy: Always + command: + - "python3" + - "/opt/pytorch-mnist/mnist.py" + - "--epochs=1" + Worker: + replicas: 1 + restartPolicy: OnFailure + template: + spec: + containers: + - name: pytorch + image: docker.io/kubeflowkatib/pytorch-mnist:v1beta1-45c5727 + imagePullPolicy: Always + command: + - "python3" + - "/opt/pytorch-mnist/mnist.py" + - "--epochs=1" +``` + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: TrainingRuntime +metadata: + name: torch-distributed-multi-node +spec: + numNodes: 2 + replicatedJobs: + - name: node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflowkatib/pytorch-mnist:v1beta1-45c5727 + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + command: + - torchrun train.py +``` diff --git a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.jpg b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.jpg new file mode 100644 index 0000000000000000000000000000000000000000..08ab3508a1a4eda202a6963879900d1280685409 GIT binary patch literal 153020 zcmeFacU)6Vw=f!{i3o@YNJnW(Q+fxHCenKc>4Z>((5u1&(oxU=p-Lz879eyfp(BJI z0@8bxCiTm6-h1z9?|HxHoO}Pc=Q~b*nY}VId-mGX)>^aHn%qp?`~cj0t*ERBz`+3k zaIhc1%_7c}vYecSrnZKnvZ})0GI{{mfcG2#aCY%<*H(JTY-nW6O!(t(cl?=WX$^k+ z=k-4b*m_SU{;VAUK=J$sW&Tkzk&P|b8e3o=`(<^9&>_ddn_dlXps-k+7={COuX-firS_lSvzv8n&baMK1L zzkO?n&=MEtG2j+C4lX&)O(%d6+uXNsasCYd_v;eg#^QyCi*xG^HvjECz@JaPbqgQw zHtFsAgm}b%mdC>lt{x|CIQ-x@K&g zRY1hZ-Lq;`P)Jx#*U$>=;T;0`T3OrPF~TOMq+^|s$1ZRCM_6`_ja}#~_`>2o_KEaZ zOt200|Dc0Ki+~UhALkbCZEUVGId;O}Vlg1VCnCVdVu}5E3zr;=&?CP4vRalDZtp*R z9U*-1xU!v+h5x0td&0s#m4J?JNENl9RrWVlq0s|5@FKhX%?#i!_8GUxamfKPfKBLQ z=Esk3{f_<*ZG$lJu+97Pd5|^35`G1}L_OpwJdk}<@CHyOvvnqNs^Ka|tqR)WMYu-I z?oyIvz{>g+BoCW**Lv0;nl2qDC>wemPq=JyqO`m6F`^B{MbOZVOkTU3*6EnF1)4iW-io%`!49I$~%5etr z0x20HCztVp!>)d3twIK$`l`@OFyQ*)Y2XLG8$fzS{qYT;w29;Fy7HhY_|-gQ_R_+& zf6#^YYpyu3RQOJSiQaQ`kP0xb#P%EQ>xm@3FC^Ae(*&K~BoNuNG)*Te)$sO&(UwN~ z7L(nYksix{F+J||SRVi+>G?;}As~9#N}7x5JR-%(&obqb@Nroji8Sk`O$`)e9l}Q&S&HKu*y@Sq9;&eEc^*_(ZM)) zCJd!CyjPVp1!np+y%le9j{X)Lzr{p{Jc|A0Jlu71+4TK2byIkItaeo+ON+^l?&zyW zHsiJ2@8f*&!aqp9Qy+9g55EZ_vgvW6;o;h<>|bfwQlk&29#qiootk_{1OyWSwpY`e zPFNOeuQW#)1SeAQrFme<&aG@UqZ9lKBy1p+gCGiF{XGplV+J0BjmF)v`;01S3(grEip*AFkYP3msKGxW=nCUGv zAu_KdP%gP!T&_W?-zp}EJ*?m_4L`iE{yk0)$GNzwBvx9+)mTHQ)J(K{9zLL5K{s*9d zU`KoQ#GM$E*Zb%oAt0c zwKUYx8kL*^*E!bl)DTOZZNZh}RSPwvz>> zn?FFw-FJMJ!6x4bZX>C1rW%m$rmsnkDT6ybxr!weD+B=JW`tE{d~{#r2eSq%=_(!^ zjfAo+QF?f493%(u(V4HNH|%wEF5}u4=#5sv#Hq(RXHs$kM!uQj&UI6Ls23RsPpY6; zCPud=%bxuA+`+{!b(97w6x8cY@|I1(LvF24x1RKBRCQl(MG)KSC6+lwIZEo#cR&7E zTPHpZ%L81ow@thw8*gg67A_${8Hn>R^dC&HB$fFpb(`!yoXPRSY&$q!(Zbd)Dj8rc z_tzxcX&QDl+Dn;^@V}dJjFxyS9~5pw9E{IX0D;cdsi%FB z!aq4?3G02y=JiltXVo)cJAng^k4Xb5Xq0eR*2S(-@q2)>JKy)=^J>CD&ERy;HHrl$ zvCmr@GQkbzWx{HLCr&dF14>U)x~->Gt;v_R$;nmpL<=qSlkE)R9VJsJ7uTe|&HJ#w zCYqmmF_F1LN7@m0)xy%6v3dR^2}ZA;`DEmxGd@B*dvxUOd$c#ueiZkh=F>&7awjcQ z**Yv@OJgS9{!mSn&@Vm7uU1H2O+>oOTub*bIb&O0VCk;RYuX~|z(1ss-i7=aCwfc& zS#OUD^3yt|@=B)q0=Adp(mm`oAO@bw^2c0*tViW8SJBXU@`8gn!qdK%t#Z;W&IyO7 z&@};#=}dc#KRQqwWcGE{dr42KA7(ErxG~ZUXmqog1ZlZ`2WQ>@&YxYQ^0YDK9d>)A4Ug-rriK;03*RC>6{TqIV%j`x9MK(4=6U$3~jkk zN&3yZ6h82Zm__!JNU(SlitF#rsYx(}%w_HEtx%85D&c)Al~MqXBT^p@@TIOWotVM- zG&Zzq zyPH$ss@C~5fVeDOoVYgg8y(`wMjL+Vr7HG)dS&g$)Dl1tB84)2GeSs*)FcaHM7&{? zpGsO>l;C>ok5j;Q^Eq*`@SyJZOIMvsFTO93?tYUUuW$z>4OHVINvPwLGH4wd9%wqQ zroIW=p$QOaOx&*jnIRz@PEp5xDT0%F%^%8kn2hGBX?|v)qUM?(ws`DJpA%Us;nRAL zGJ168wNAe1d%=kq3 z>3%VFi!h9V6ORM)lg*25pq5{dTFx$9HpdvxQG1a#ZnpQ8e67mEZXW^CoYbQxBr+Nd z!OMOMk?{(hwG>P=ltQ&19E$8+`Bex%;(Q+iNQRmd*7KPE%sE@F2*|7Jqi+bwM_E^m zV)DMeofGe60pU4)^q->tu}GGAkIYK*^^{T{j?IvOzqEi-w(kxP>;|CUr{cMr9RY`0 z{j4^db*{X0RGA!t9W@rfN59(~3mI@-wUNE7GO<2zT%Fw}ayVzsXv>s&t37b=9lfsF z5=~*56Vo$M`;LGh_UhB_p>FEe5|?NrAsHP6WC*y_U>+FAlQFV^o9a+BC6U~|Jt_+d z$|9Y!C2-DsQeEoe9OR0!%UL=xV8FORBZq8MuXH|;*X@Oc|5D}m*S8;)=7AV7v6P-V zLD2@P8-|8UbQ_Kln1Y_|vK=)x9w)NAl7c878+tSP7*f!OwveLCz9KaZ6%-pZ0ZO27 z*Vh@BhK{bQ)FB_X4LH0lLXR%PNOy5D#Qb>ZqE$pq2clze9qi-Kz?W#FtLei5vTR-* z*BtFkkfwW*xz}4$^#=|!_U^c)z?|v~&(vA)2*p|%S>GwP#eVxNxP{j#`13w|$;Vtq z30Q~HsVoW4c#gUH)R-19yXc>EUs9!js=|0E` z)8>1@hrB4o$6x(>^h|+jBco}i_L;t?igIBIrH7uenVxfAaWO<6A&xS_T>-}CH2OsJ zNc`Gu1syMr%Z`1i&R?72oOf$jbYF>Wh&1_8#jcAW!>it)zK=OQoW{$Jh`1dkG%@I0 z=TKZhFzcizB9qzBTuv0)_NC;=s8~L)y78^APzyOGrvZcaIZ9{*;|vFpOlp?uZ!zdK z%mhO8tUSq}`b~N&xGZidsex3P_q?Poo<99k1M>iCPDZ{QmXb1V2Q)WgHkj-N@K^UvUSI<499K`JOQ<&8WdyLp1keMX<9o^}S=bx%u<1az>0Xbu6eXNavS5eI@PvYe8 zr*4yVU9jT*1WI}DfRTu0li2yMXn8eTT0M|f6Mc>5o2& zzxc%*a7(dEQro#2dNAuGf_`iFhine=v*reAs-a_TqmFZYNq%_9G`Pp*7F~eQDUGP2 z&0Pm4HzGFH@VG(Olj{ElNTs(MSKRSAWFO3WhOo}OFDO7CcyQg5B&519S-??8(dTo|!b<)P(WptkH#tSV62c;`r*)Zy zjL3ts5WbyHU$@_aO-1k+JGs>#j%x+Ws?~2PS_Pdsw(XRe0r)a+seoFx8Hl;+pd+s}>9{Chrnz0w4Zw@CZiVWKQ0z}mCHn@j zBd*tUG-y-JnCUTEIP)Y1Nd*_}UEf|dTOZhKLGQw^v{2kih7}-4+L|s{Z)$grEKlz4 zZrJXAo=wU04s*PVaK=0dMCX3j_L=%KV8_9k1xZz}5(z%N>&NDSaCU;{)Qrp9gzmX8 z4CK(_&L*eH7fJ;Lf@)ArkKzYZgrsBYha5C0n}~QfLd?i>EbT*njEV8NY#yaXqq*zz z_7D3&wy`?gZWjsPz^zD^`TUP%(GKbki^ce*DH#NEz z+v>3)x0~exa(SDyO|l^UIVZ^qfjV^cu=>j3=atA~Rfx9IxT@Z|tj@Jg{P$Y3YYF%b zfU`sq5)7u7yOeXicIjFezhe4U+kZC^cen^vP}8qPqLZSgX&D?z*B~;(a56s&Pvyyv z>#+Y?X#!mxMHgk~z7v~GV~KrVigz*8<}E9KRLt>pgR4~Pb-NIi*Gy%)ZlUdJuSekt z@KWQxQf1g$1z?!lCiC&cUIlaUhyjy+!p!ZHveu z6|8?LkivEBYL{KP?y~v1<{=4wLt_zRjeAS>w#Q)_7fDTwInwlm3J$jbrKYqdUu+MZ zhfcS;H=mJRSIu6WWD;Jvaal$zoVDP`Yb_=_N5u_0WZ8evP*%QYfyR0mVHFW;XidC-l^laK54t3AOaR1Um7kC=i{ zk1BeDHZqNCDe|v$%A$IBCky7dDaYf;b;jW8?eBNDMI3;1ztWKz?G|CQAPsdth4Pc0 zLZN3=ad1b?!22yk4ESbPCa~~J^T`ds-P^U38M9}kE)-{s3FzS`_C(Be`-H<_d7l)J z&Zoh_nMt9OJ zijsFR zDe&Vo1NwkDfoFar@YzMbOz$1Y*6?-J;GG-5J>B5(w+2=ZQ}I;8QV(Lk<^;c^dvXI{ z`yMFOF9fEWKzFfOAI4~>j6tT2bXUJkVHS589&Rt4uARz|@5?^Q{yP?5YZ;kVX0kR{ z_Q&!&B;#9*_xeC(;=IlcOQi@uBhR}Tho!ZLULHu&I+1aZhwDWRnYWN=ur&7LOH)&z;O?SE=K3?`d8LDS5 z0_oN~hQK*|NhxBYv6n9}ttzb^^u6DljCM=bAI$7uu}+u_RhXxk_|`dk5*TTyxaL5` zKO|en5l#wy8dZGkU9dy=~Q_GYbj?=^L@hPfX*IY zj@iOhVm&=PwFDa9$BCYTU*Pwyg83g-H6?VBB=!Q*dH0;3vljyVpt3t zfIOug9ef9Z610&b-@MRH6|QhBOY%r5pSr>yx(XWxj@9#lOnAMAO>`FpDdXN(b*uN*TW00QAf#C)`h)40`E@ z!E_RmB6Xjgt-T80qI)&YT3;A*#7qg{-tipfYO;bR-c@g!cA3<89gmtaUV0m6FVIcN z>reN{KVxCQ1we-r5BI>0Xt@Ym_MNET>;@SXct_E}`JWjivqnXa*pNA?zj;T57xpQV zaj%7(PR?}bBFu11O>M{n^$PLXC1Y~ddD67H(C8r1!r3RT400zTn_rx|VUWCM6}j*s zL73mQQGJLmh$wVbT%`Moh^Sn4psQPQZxQp1R*vf7TnTqO#Wf|tS9LH7TobtD4pb(-bTg&?=fh(wGFSqlAe#xKC8eXHN*7+nAqH z0Yk?Y#(leUJ?RRJlgz*+J)30^HFwlN*r_OwhqUPP9c2bNBQ-oz({Gak725>cmfGc7 zQ-NFB$NBR`M$$><=kG^_7bbqnI(NErj2IX>=DWsj4ApfBYOAmwG$!7@dPe%A5@y~I zka6}!fpY6k)s|O*Va+^qIi#iacHL~2bE~h-0ec7sf`VI93Vj$O(aPby3y&GjQT1Aa zDrIiy7uq58yb}hM<0oUR^2s&K!e;>bQ)X zOStdQBoKmtPgs0uvuZ@o)91~F>WWEtf19j)cPQQVX1*%UlSPHg6Sru#T6hCoL|{o< z8#BE#QPPJrvp(9qgD|4C%i$+72C$_D9?IN%M=KSg!G-(P?@{>C)w`~DmS9uZf{@NE zsEk@XlM%jTBG90wBbf@=pnoy@j-ZVM5?{jb*b16jsJTV(EOXV^Ekj8j?WypSvfPQZ zJkQljL62f;Rh15H^+LK|mQ^SVkLS%Mu93&Eel<5;VJR2td{CtpnAgvNtiG$Ca$&|Z zmbZ8GR5hpDfxp|-kbdIOb>sxPWW?uWp$U!!0&MI<04D z8GpIn5%V+G*ro8u6}4qwFKk#XufI^`K{ zRP6Z;E%l9V&`Urqik7P7ku2o{3L0y^ZWc1osYD?E95Y~KwRX^OLqhpD$zY$vX~439 zK2&|>pmZP~!j2k;^sq(N@_4v_(GRkk-^bZ|O9Z{x4yi0?tvK)GhKjQ)jCj z<)dFjV&QO?EJNIq*ceZej3IK00q)p1*?hm#^}OG9k~mhcce0T(s+ut*Mw$F81d_LK zNb}J88Tizt!~T7xM95e6%QS?lB)#QKWZ@p_6>t9jpqS@Qe)|$lfW>X(!dX5U1$sZ` z!_4en!xOG-L=Rhpeb{qj;tAhZCi8-cDx|I&W*H=6&mRCT7*XhH#*&$_!ckRkshA=-x}j z0eqdRX5vRlKJbp2K#G4D7o=^(sRZXlg37{V@X2<4m?`PreR5V}U)4)j3CI+B z>;R9kq$PSc3Y^2&(0}rD6$XV;!vx zPyT19Yr>|GIgk>X?ZACJ{<$LAAz9T`@ zEM1P6?IJSG+EdfUiyggXhRZ9Y`$v=J7~lousY!3P$j4!dZ{SA3F!luz|D78EX_fh5 zjJs*jPYc(A!g}MpFA3sNUq?b&*|x#ZU0zlfqInydn*Vm9rA6oWE-m68>9GOsf|WaO zXYcvnGdPKmUrKvIsO3j(kuQc8^krp2}S(}8swz^3oAMoQWp^xsw6R;3DNW%W#S{5U_2 zQ$4XHGQ|clM;SK&{HX3@6%GCwFI_`0v6&KIYq%qAuhNn={O#3BVuS5j9u!x{ ztJm4Xt;WSn$kd7HC}S(VE}dk2z{_62EYwViqAn6oQIV;0b@$GpCXl^oj_sb-0(C>0 zI%XpSaB1_4mnHJJ25HqSc+%YJB|{B77o0BB$gizO=G*{O53hE|l-jXtUkSZcm$Fc? z`m4s-G-7;fsDdQNqR8&g8^FsFLvuPPD9+=ICBd%`(Hr0&=Ftf0{N~?`#O&i90P?tT zvoB|kCH0I3J%q&>+5@yiRkRQG0scIfHYaD4&iiUookw#${iJLlTUOkr1SUtL`MrR6 zsoCIl#uqr#o^^FDbURax^?}iD=gm?hXTy~n!4W>e?~iIXyvT+&Iah>^BaX*M-7spB zO%|q1q&060n@M?WBlw|F&*x0MKh5X+p7-un_e41>JV56^$>t*;QJHH7Yq=Ls+6(Ck z2nfszjL9oZFLTxwdtd_TXD*cUgbYplbuAp-(2a)27?iBxF2DN>h2wAFo(}=D$+g!xdr@;K=!6_%=<7R?7LVBVR_WIHn z9}O%0ZR$!A4irFHp|1Dy%e=bilqCSBiv-KtfS;_}lxkyTEe_UkCP81U69%7u8lWaF z#R#Ag6bp{uJ8j zLOaqxm$BJ4-4a(v;?Xtebj~R$J}y1QaAQTO4#wN+UdyA&n@Vj64}BB)*s z%_%<3eRPrOVE8r6l>RTcXhIza!C+^(< zvElkYncE|UG3_sU4dD*Y0BW|q*jyaptp&|_4Z`Ip!EpvFYl_{^`Iwn!I+W<-0g}uZ}RCAII*46{uWAWhA60$Fl3io3cDxF=2{Z=c0M^mSlMn!OLTJ z-Q(-F*Hul6;vWFNUjKPFShw16`zUEk!mfJSC5g6@=#L3EvT$CPyZp*+f=ra_|aaUiQPdWmjn^C|mUUsYG0T@yf zV`pIH-5-aWcl4GntOZNIF`LP(Hrns2Q}O(_O_2=Ixp*!}Qc^lfwZoWd_Cc4!`KtaM z=b09>_6(Tz;l!>6!QONXKGLqvF7^V@loVZRd$MQdU#~m_ThQUr-JQ+Qezmy9(93$t zF_6#{z0n;1p~i$E%Ar!;>wp1<7#I$gA$zh66CvrlUU0Wtv9OoSK}dxRF4ao|ld63A zBwwET+46zxJrVOfuOb?Q9(4<6NNjt}|IjBlb4?t+VjpZ>(3M$MZFFPYG4F-XPMYL% zLf!fTHX|<8%9Yex_0%(pI@N>7znEMQgP69}Qi5c$njk*uZ!^dX3OkFBj;#Y`mI_9} zT?`h#`~nZZ1lyF{03xN=-PO195UG}RgI+Db2@RL81vn@@y&29&QO{oi8g}2{HsCh= z?bmJ=)r7FR{3t20ayn!>H&05%_$Y{$D7RJ*QOr}Rs%%9)@7?g!V< zaR@kRi1xw{5lN)D4RDfw7QMw{rOaBC7l3SVSaY2)8`V4iqUv`bI$Q^v9G#CF?5s-M`WDw} z%fLZL(=T`cyDw&M>Hf&!%@- za=m=tk@Nk@?ux~`lk%nekBNi+cdYBbT7CXYgaKgQeNP1oA{|H(VDm;hi}{PhqonL=}JYn zBo2_U zO)ALz)}B$OHceTMoSxEp#rL_T5YeY;=94tWEP$l#IhJ7NwE%-eBSB(aPZ3@_g(y!s z=*AVEhubI|Ws_Infj1N+5;R{61EOE)d zxqp?~>AFn67e(~t0aFPSA10ofB=ERP{Oh2{b%?m=h6%7r8-=*F+R!yx-$NXY>9;-> z%9+hI$!7{GMm>EiVdw9e)hIoLHsLqF3u#D*_`|N;-k;qXbFov$($XVbqd5`jVEz^8 zeBE-Ka{LIoDJY~H6iq_1E6Ng*(zWCECHpy1(BPuTA*pwluTbKPS|uI#RU5+sU9qyv z?@CGxT+YI;jlEx(PKqK7XmH&88=QjjYy3Z|->y~pOBnPkjPMYT@$j@x&Q(k23YaN| z!{SFQzcwTB-s*@pm+{vq;yjyfQoNQOI?GDYl0EOuGR`S#0P}O}!00D6)>(4mzQ9x2 zcqFoTL1|`OG4JY|XW=qB#!`I>f2{*TLBEH%DqmTzwtl3a+uy*bjOp>UznV7eE zeJ&Psp}t1a!4cM`g4;v4|Ebgqb7BJf`v+5mc`m6PGYOBC()7HA4ilgvR_@PMvHQ7& zcI61Jyl)~rnRke{xfZ0*{!bih(YX>VMj+xA#IzoM${?{^S5+Q-%VtHX4MmO?X=g7dt)2v9m|jM!7JWpk&{NdD!(lrdruR#X^O|lSEZdaGVeB zU>CNq{V9$P%a(7;;@wlSx>I-qc%rCkRbwUUp)D8%g+{0C%(~2zWQz`=UFW-!<_N3& z8PTtNbd-*-)-*tkwUipL%-S={lDTJB7II##-2T6UICUeUH}Z6!a=pU(OpA{ggTC-G zkd$sCdLJZ0`@COy$B2r=4ZF<0D!SD%!t3jc~1V)=od*?*KpEz=SmMZ!5ej#^% zs-BSKWEOY%)ox&`LyPqVn`LXaEmo>g@NAOpIPdoa)*1j|X+I+)lUJn6Ho_OX(G7+$ z-sx;B|AM68+9Raj`~;{>)~R+3WgSA>*8^PU{`yf=XpcmKiDKBQ?mEXWYYf9O*08_r zV9fa>CnqFJ8ve1xTm$b@BmGF7YY2*OHxf+ed_C=U@o164kH<#fOtmm6@vMoFW$LGd z6Se|z%ht`7JT=HnwW&LXV*N*fr|SiD?(- z4PG4u0kPzW2Dn?sZRtZoKzxT3r?3@vo3ll9H2`?+B;gL4H^hs(aaJRlft z|7ANd=7kI0f{)GK?5l-oS@dz(Up1UEz7AFiF|e$2+*13?|hO@96|Tm z_5?5+FB3F(1!>D3Dm?0cG+~}8Q2MNMH9P9yld(-sPM}j<9L^)KsaQj)8vyI_9Ywab zZH9{9V&u96wytHD20JoV1y?v*AkjB~1m@-^5$~c}HZzS3&B==d&$-@NiBaWk-i8&# ztyv?1^a~F8iP5nNdU78^AKvw5o-^62@CL|z4l6}?rfdc=Fbae^9`C7x)U4Svb{z7f z93z2EVl-@`2QsyXtMsfuQcw<%aNyoYaz&_K_B|j3*Sj5b%q2c(5m;CVD{EXn4K=Xn zb1))KdGNk;KL=!uALDSM%mGG>dwj@A=N&QalU#ey1BUgT6|Lku8N@)d5ovJQ>c}X$ z&J0X^1Kws7)5LX>$EigbyuaJtf8dE-txgM+YHIH%dTO;{Hqzf(LUeCWdIhmK<7(CE zv6!T?^Cij1SrBrHHj>f&Q=w*4^{ zjce698)T2>zk7{Vh&FY63S6%Lj#%!CaNx9AB$3HIu(o})dzTbI$N>LIEcthBFlw$; z#|I@wE^Og@g$+_{(2PBgylTy}&ZIHDu~!ef`9i%VoPUYFuQr?%-NxavMVOW9ixasd zHKwz*M3GAKsOb(yvAg^j>D^@}=>@n1^xP3?INA!aq1{s&Bhb+Tx0si}Crq{lDSs02 zoERLsLGq!DEHQ_-zON;``XP*lx5rP$r5p@>-94Kcs;1AD)F0TeaPKPQB`c_#H&s!6 zS@QgYSP75!8^z0}Zp_ME5Dl^dO+v~OIsK&M#NUReAm?lL`-*lv>)sOU7l7c^Du=)O zl7D?uUTDBTy~30hap2bBreX{6zZ}sujlFw|YE1dTOLnnAmq9$fQr9<rz+)k2}nJ`QL(aI z>o@#9F}T%nOV07O&v|s7chxN300O(pd}~Qy{66ZU7{>yKbHuS3hI*u1S}!95cbuu;9Hk$MSt|rY*hT5q!W!nwicG zAYe%^IJEu-U|cY}xS4seMq7NzfIJ_!IFfxKy+*Bj1DF>bxA?IuGf{LZiYU1L)s5A{ z5xQO18eHAeBx~pzmpL60GB}fnKZXSk@nQ}5Tijr+?X$t9dN%<12mc44Fbr!=tSjof zV^mz+qRXS1pPwI#QWO04qg$~%c6Ln^0|x+HJ(M!T4>X22f1yma@JC7vA_BrL&85FKVQ^DKo4^X_3|$J`-h#`Y~D zf$Wiwz~)>etGhXUdT@*wqYNWo`G0T@+BpG74D79n5ZS8Y=YNW?$=TsBh*S`eC zND-4-SbHG|?H!Q4us432xIM|K#K(~bQFfW*|^yj?7mupU5}bYz_u-586Jzs?gq8JBtT*&zCv8m%Lb(v}8>X|Uum*8)m7 zbb|_%Ejp+6`Nxyf9#Jqj2efe5ZY88Own@#v-_IhvBLue!1w2gPBo}pqvVSy~EQg)z@4x z`h|gvQQ}c4X)``>+)zR(s4&Q%?47Psahd>i+p&Z7Ss0YqtQn5*mA|)FCqjMb#+snK zvl`g0;KLDFgXnuYQ;IThd5owQ?Pf2^q{*CcKHY)sL=_n6c5{%&`EJCMv6_Sh7ju!F z4JG~3FG?!C0qpMSU2|g%l~{|F3K)bPV%6!Q=U3Z`(%m4_3Wn$LuM0^99wr}Nk9tWq zmJV}&H)9Oe@^xl5A@#m9jq`V**{r4C|*lmlY4vF4Su561AiMu1v_Nrs-2656b6i0yZ%aNCKHOCXxw} zORv*KYepK*J)2#0-i2rsMRIqG{rtJxZ&KqdQcD|$5mH*+j5%J5++A5-3u?u>=*%u% z`Wjq*HNLf}hA!ZF&}_J zWRN~BNELnxV;>ikU!(s?L0>6w!M{J})sG-fZ%m{>rz9hfR|hP;5299uxxbDyFAjtA z%6aT&(-&S(Zj0=+R_|>i5{u5h>}l7WEW|7tNBev$=B-5jn0Myu-h}!55*k`q#O-WI zt@}7VxKhs?);m5PNZ2qoCun`AyyQT2s7ky0RHan}qDV8at1MZ+*V-C*wfXcYFE6sL zU|h)%T6DT-y_@Op_Dv+8v(bKBCN$zo^D@IsYkj=0@mY)3_$DPRTUJO>&e@|@M{0Lp z*5jbjSC(I`jiRS9G=1vnR(4RbP-0;$5q!nZ`!HmamqrCt2u10{e23R`03iasmDL^f z-B>T&gPz;5IcOH=b~8U?2v;7hf5@_TOaXD%dWq*Wt`)VG?89(Qq}+~%9(xY5NNScN6Tw25V5v+ z{>==I?vD?SFmu!`Uh%ymn0$uDFaM>)45zg<(6h*&O84|strZdy7AMMw+9$OrA=1N! z!13z!t~)`P%Ne2CtbcVBbPOVSoNgk@K^h2~+QFxEM$*8cn|^*1 zP3>HvGor1b&>c8OPyEGaXzk^75?)z{%b0OG!>6-a1+l1g^hku3IQ2c@&;8pt4U9oo z%@@oiOfI{6XJn4oe2*{Uj~Znowc zQbDSdxY6WD0{h14=?*KYP~Mf4Eq$pEj&R(Zvbu@cs=LSIhu`{MjLzKQeC@5mqbJKT z71P=g*$M*>GxWcb*pXu6;fP$X8IfChWtZ6T##JO!grTYTG!aAi6CW{;wTm%Pk<%bi z071`Fux{}IyC6AZ^B*E^Bmk1jcQ}4n2i$*XTk@B335sBTmf>5%ndV0wnmj=j6&4#^ zQl>a7aoelS@zx)_un{9_7c6UBt}$bo?f@av`(w?xnb*^?R#(&zv@6I{P?`-F3JsIe z{q}MuWH91D#n_AC!fE1lvGG{5RQIv9#vzFi_QVhsVHH;>#_*AkO{`5UODerAiNE>~ zkonzwFk}2bSQ;{1YMxOd>?BTYsFn~nm_im{KP3h$nDMG0;j|x zu9I}DQfv03a9Wdo1J!+8xS>m~!fLyC$w%;}d`=$&b2{nS$Um1A~` zQL$A?Ry_)7prS?G!0%w=0A@t(;pg59!uLH4@S03o@^(`HMX^$6UT9yZ&lk@P&Vq_4 z?$b+z7%$EGV!hMyrC57BSQPknSb7e-ZK{^kG9Zw}#~v<$k5cx+MFbNoW8=w5;%2Q~ zEthZU{2PW^ULGIclPFgVlCv52VZ~?QL3~!*VXrIo2Q|^yfdWs79Q;@r)kBu5bX}QJ z=)C7B*6u};f8IK`?1R>!GPkFW8Vht&Q5csaqD?|{S9t0~_W8e>?vI%{aSp43w~4Qx zKe_>Q7+h(ReM!6lys3rBz@(E&!dAQW%ZgSH(wd;$O>N| zN^n+@u8kKiled1>gQHzW&kQt2OxIyNb)2spi#QhpDB1;Zmmngy=#hda;8(0z>vH`q z%elR6+CEQxU*zkYZi%IX$Xy7*QdV94RI1Pg$2U{30ZYMk@lmkiewa3*X&r-h!h$YSev8uu3^SVJ;uckwEXx9iX>lk?Bq^TNa^U z{jJqZ6qRV9mIb1e5z{ThS4Wxrs$2cOGw~M8;Ek+FcjejE$3%QzD-ZOPdz# zdpz6O8X>!yP`Z@OOw$u7YF6#`wAT(diJ~o+^+epU;vCt{s(FU(x~sP}Lh0A|u!r$hrjozV%qpVMH)VJum|ag&tt>k^pRd3F zSMJ?Jkt*}r(PGV_=Eo9him!NM53FbO+m}A<8WZhx`rgv(zwkSfy8(E9!U~f1Yt&NY z&LZX%=+h`?t)d;PSubmfI8(&oq2>B%x_T5S)$l?mWkCGFE~4f|O*}EnuFTZk%f+=K zy8AeUTesoO&rty%^nP-33(!UH9kaFoXORz!-ngP5FA42p+sqqEP%XS zjZ&iQ9y>w{M5DkfYrI0K;l0rW+F7hqw zJ(Wi>7juge*LjVZ(#%JQdDpKs-*t>jKUZpxjC||!^Lgw5dK?)`0-`1S2mla{RfxM4 zOr0cI9zC=ZAWl(|NA)R_9%^vK?R{CBTVoh*^TPU<(DCQ`lt=Qqk(SqLaOocA%h3GH z{KHCe)xUbjV+Z0Uxs_3Uru6xCMD}3)-yiUIz66xZWX-Hxys5=%W>-A*IDeT3%hvXv zw1cj-dU*7)Q^tKjRgP{=RfO04tMl=->~;NYKW;tKNSR1l z1Zyey^px^zjkLg(lmH(a%IIe&>fib7v~<08(nQ(e$3OMF($={p}BCrb6rX+kKbiZA-mJd3aAC`&nfXHRU2BEl@XAE}f@= zOwaC{@`}LyU~u1_XR$-p5l%696_5lXo&P{b|6ll5iFb(13DZ3V_Z=F<3_f{> zyXg$K#nb!WEQH5DHh+$@Byj_ou$Z5cSMoYJ&k~Ah6q}B5#}jtEy?|I3j_c~yA16?l znCKXhMbqDPwYq*(#(Ijb;ArU>wA-1y!&Tb?-Et|kRbaE>E)3BRq+#)wgDxE3la*cn zH;XJ*)tIs9XBLjB#T9S#t7^9{5Yjsi!mIY-yM^O@8@krmzyKZ9Z_Bv~8jY`p#M(lY zxAwFH*6R?V6O7Rt((#S&*A~F`GS7JB4ze)LdipaL&O&{|tlC=o-JCxX9#z{oWlZ_p z0Em-#t}b?)L6nhGEuclXll^Ej$2irw9~09DGU{)!C2L49GDu>l0UgX=RrvqjXf)zo z77y>Z>FU+^Ts=_ge7CR3l?uKj1izz?QlR-NBv>V$OI_Qv!mr$gZtfHmBzWJz9%!7` zD23XB=U|Sm=RI?i_$tsFn`I9&a8o4(!3kF0{NL%n$zo5mj?d^KnD}>7g;;lh&snr} z-VK!DEa#Z9V_Pp?%n)evwW`C=(AW(7uR6gD7g$f0QdzT?KvLVn^PI20%mwgS)}KpO znRG3n)LFn!G3x8>)*2|ui0u&1f7402xGUIkK1F@`2D_GFRn=KcTpZVJtxLCQxY8KKv(nILIqo_zndJjk^G$|nvs?tPyFA2Sugx-rMYhUNvuD#yL4I3t+9gsU{{G&NV44 z6@Gbb-ZH!o+sxhDixCTn@SnDDL7p?js&9|hmR z+?Tl-eD8GH@dQfpjlL;*P1mu!kbQ7;Sasbh@{?9*puqBO{^YZQE-s3x0 zkJCfyIygfGbok%g*!ORXiDzubdJC^H4y8I!H*|s{@zPsr;7%%sFKyGuYsvcXQSL)@)2x-o5Jor4@3Xeznw>&JE{i^?HAGmNZLdZ3m|On@8kj|YzI0ug~yn8TPmX9M3rIV@aLod0e5LiN{!?Z+lu zd%yAe9W)smJaL)($)N17d1INT(oaCWHT{JtGDsxK!S-JQ)_;^8^1hYN)YwRpEp3vr zF)$75lc!o@sp(c!IGO_)kUs;mz8K!=1qa#VGT7+ zVX)iz5f4#AxoBL#+W3)d5Qf4YmRES?+<2{5a=G}OCFU5iYqP3{pX#A`U1t)+qkZiH zQUaeZ_*_=%o^^bZ+t!@7{%?QPLMljPZ0Q=+{Fo`J6A6Koc|w?3@x zcbKkGjwawo-Oyz9Pz7a}NN4FO_N}eVN!kbIL}8fSk0PZ)C)^e)(~|){pJtE;K%WX@ zYo%!P=2P3Po#RaiE-LnrUrn2yS!;5tZ}pM-4vABZ_s$obA768{B*SszT=TDe{ zVkV!Jj@f!9x9fey#1K$+d19Q?@7IX&+?$R6^|ji6EsUDwqn1$rT7t@ZLl4S_CEw@y z>}x~$4)=9B4OIMr ztS5ZEXXGp8-3FUTpZN8GIEp!c0*szXCvp7*h&9KWlpahs`Q4h1R&jc7bJ(fgMifH8 ze*H+&`wdyZ@%Cp7vKR<@0^blJd4s9Mq>UBP0Lz-2o5Sa)vt)%5tUW^>W*C02vzKk^ zNwYs*BPV^*=#kL$-@L5q4$6~r*DclJ>Ypb1*G0=vR)XKAT4Y)g6b|jsq%g@4EUrnu z4_uCR3-afIiTl(k8Ecp~DLqKk5FF-Qv+xdE;G4wFJzAw0^u%I?E`D6=rU@7(7`!}i z_u!F^hyY)i@nkYiZ=2@W!Zi6Q8AnpPz&vZ9fEeH?o)~9n&cYe-2Mfz@9>?1b4}RA( zqZ}Q06r4tZlVW>MSt&ISa0|Oq0cXWcM4_rm?>Zt&-dD$BeL-3YL+|inac+J-XL!f0 z@Kg^vY)Wj#c@Q~OwBcKH^RCaYG#vVmygaB3Q!j*;lD%GL48)jjrP~zba3ZO^dYJ#) ztwGF$`_s}UN&m&B!M~i^k{tNp^uPU8##j})TD%dG2Qf*4JfV*^buvh}Xm?4Uv8)+v zwS66In*Wev+CI)N#uK@S==RMY?_=q8DdEsU30rmTHP$XMrbTdf?pW7`CpCky8d@E! zbf?oh(4F_&V)2y(?S3QqX~p3=tXU;eYf25|Vu>lgEcLH0sCU`$$L?=8xO@(J*O)t( zN?fdfxD&CbXu%M42(8hqV%@gXW8Z$=h`YQR3~^)q=fhiu0Ro_{R$G_nB-iJJFQxjg zLbd-^hs|#fp2tiRHdh5ZE|1A%tlqP z5fp_#c&K|CcPi=>)l_bdX_cn5Pg%RkpkoQ$>Ipm#C97jN7@NI&JpTQAO>2#U+v28Q zw^$^jh|8+-^LNLGw5q(>Y=IP04^>`bm|1apJxqC!Rj_CAmn9z@(6fFhZaR&NK96$X zE}<(kJ%iB*GH}7;&}DuNvD*DBYW*cVKVw{z_{QIp&lvN#*WR-svCT;~x2&%1<`Luf z3yhPq+r_(OvbZ4$vvKa)M%$~FS5BVcDptl;-&Pbh?R3S55H(}*FNTR5aEA9ew%9!n zrEQSWrW4&=PB4Mk|Hi9n)H|d|-FSlj8g~BW48z9+K^~)lCcTGSQRU5W)E!0fB6z+) za_68Ic@w%$y7{V`$PDOH_9Lm_-n1>0(~3e?(jiF{+1=-iAwT`9N45T~Tdb+kFP+xx z{EZ9Y^&2ETXmfFUDz#6L_Q>3#umU9EdQ>Uwu4v8OCE`H-AgqF%{HD(+Q=&>a9e45u z4^6H9N;kIRvz6OMFZOMFFoPb$tgI(?Rq`jm#lhPl+Q{a9<&s-}cYX~TQe?_aK;oAZ zR>}vs2y@(&*qr-App0t+DLrb$GXH}f8$7)EgYIK%cUm{$G_Z0W(PpmD?l=1Ot?`yC z13hC4#;8jhQzn!cpClTg8u$A|!)qLU{M2oazhxk@S0-!q*2(TeMFww!XPWebDyQbO zWpwA|Mc+O3d*OB0U=>&i${2poin#mc^I)_g{d%&7Xk3xpN|h_YqAA)K$hwOljv^jQ)d zI8z?P6utmv)D~(qnss?OxC*oZD9pdB1YGKt{V6W_{}tPQpc1|Aq5ZBnvca_3MII!g z9W|(TWw_o^Q4k>XVU{E8`^S%jE7dQhnT2_u()>0SIg1@P$ys0dw(_8^=_6&03Gd-- z4819d+>V=-)FXm^A~R1HAT#eL@XP}-5!_)q zZ%eUoAWkzKR>a@#-5@D(4|#O795K?yH{ZvgMNq`Yb!VFW(_*HUVSn62}p1y*8UfC4FQKppYXH= zL63J2%pXEpZg|d(wO6jIM9Tbig@#brohKe-9h1ds|arYDV(?-~_ufb<6C+%eA7_Pj@ejT+P%R zml345XS$?@_ul(H62G@r_3>@wg5B}W7B%NpKLHliRY}e9UExl*|2UzTbrJ9NG6y2s zIo~Rt6XN+OHoSE0M^2+sd1pgT4nZYX+`|FPUgT{Z^ZkJ){)&sQZs1EWyxa^w0ZQ{f z0r$ZB7^HT-Mb?HS^McZ~VM37a_5K{Z;!^)yD$!4xT8W%GGlhkPU|(BsxvjV$XZ<5d zX=zdToky@ewyGby`*eA4iN5ASE!hg_p_GS`&#AH{Rr#!E98cS$UsP)-56|gRVi3eQ9Ed24 zb^wV)RccfCkuTcL9!*& z_}~jubEue_kz6U*VHRh0@1CSol}cF}&B!!6%7mMb7tuaXn5z6E%w)2Gq+ZAs5Zm1T zA^r$1aS-X{y&oER0SgQdsxZ-t5Nd<&)Q4E?dm5G$es)xXSFLE3Lq#mb4#%hXnCMB- zE>?0b$iV9%*4_{Ghb>9E9+b&?0ujBg(%ZCo0!v3_nS~u6S>f)Z)pa||OKNgn_yz)> zUEOFk`VoB(b6%Htn$XqV=>UbEiafQt+*Q+sQ=?1X6PM#tx5>Q~q}ATn8fg`wv3f)2 zNM&xlKAhl81%}Heet5HBuHCEl#M^A&vo|J!zJBq>Vwtg^0{;LrQ~XXauc~&|R`&qC zE|?CavadaA2l?voYSm3YYS$862rbvp5@@h(_qgd6h5xg;{b`s0L!kt$ZCs^wNH%ff znPV(T173nSdW;#hI3SN>C(KL*!S#K&28b{Q2+6p zp`f~JPtqyRYYwleW70EmJ7ObI%CS%0nwPR-yYu!#E~}z61&Lnvy#T7g`c)263)jVO z2g}At%kvpQL1Am30hG%==(i>E<(%_@Ton0R|BT7;A~U^}oOjQW)0I6P5nRZjDqxfR zETlMNL(=7BqJCxH)gnXo#WqpM4AS962(R9z?~zrfL}2F;w`d1Hw>Gtkl$U2z5|Ace z!NyW+)UhyeCw2k%EH?KGdlQli+KHmxh509I{LJ`1U^M z#%U58celq_hGa&(c;t{WIvXoQsp}?NL|gk2v*ch_Bt9GP&KH{#ah%t`elvfRoK; zO07Q6GQ<=V#-c$rj`3cIE*lpBZ26r9LQ&xmtb9JV0WVbD-6DPFS+5inf(jo{Via;4 zk#`LGz!TdESY|k*V^Y9jaA5M9GpF@~LSh|Y%EI^+|L1p1{c|^y(`C6h9;nCN_ZNTk zG3%a9)XCZ%3nWzi`a62y&7svubNcdlB%1LXJg=KapxH2BcEP8t6#iacUznC0aQp%_p z(GLApkt3(q%n`F`dS|Y?7Uzc8u3B{Fo`L4jnwl^BrwpW;dwDS0cX3r9SmQpc zjkl||5^FAo;x2?fSTU|Q=LlsUUMODJldKP`KiKsilh;haC2-_>KOrmwSsW2d)hy}w zSFMFh^w?CQpVjbdw>crYl~0n}7|M8fPE9j?<&q_P2PX}u(ExmD!2;wM>^bv~4VBSL37 zb;Ijso8ZQ>O?dyTI_B-<{aS9v4;#E$N;ZQHI+XHC@3aQh?9)bwmn|%V|B%bbBi&P( z`5w<9O&Pn=lk71otTht0Hq+CPY~=eBK%nm9V|Wms^(U!_q=3GzJEqgw6LVy(s|%n z=m5u;G4WyQ%&(I~j-t0`jnAzH(Z}Q;H#*P+g+*P@xqjGP`o166daEc&;%4FE{Ygrr zIzz{!$s-W-7pcRG5|rUq<3zT9 zUoEo|Jm=@1z@-$|fh~5*8nJrrH?WycW9^9`ZFtd*gwZCKTB^$;ncD#3^p!2-&0V$%>Ngg81*Oo=*w?-dcG=BSdx0<)bh)4fYD6F>S~)eh&`Mq}Y`$_I zAm&9>EgRDDCZgJBu#e~aGuo)@oe1xvv!h6h)CaTaujbT{cjg{`jIbn$nTlP?cwMn` zh$Mjev?%$KXIV@piTk##21`m)n*9R6@B;OG0yYa#%;!h z4sOja-Y;>%B3;2cr0x@BG{#i0SCGc~=_o$(mF5iZv=RiV*Lz&*Dx*5Bk{=)zV&^Lg z(7&6w12z3JmG01f`wb$anyCBBZ+JR^N}0l2h-Z8UpPw~yu(refurZ`O^Fl;nOzi=A z7ms}T#Zm-p@r)klhHR?aQT3&XfP7d|bdU&8;8*=H-0hVIgV-c3@Vuu{5!#pRJrgB) zymFb|(Wv4bRbwj!o=r4I5L=!H=@= ztuGa3s`SByiMYS6#O*mpi#bN;p|po(-7PJwMarLALOB2c&=(&7Arf%w@kVW`*|cn! zrdgVcS#;0q+$5ik_1rWiTKd(*;qLbDYhpJ}>fScD1-t0J>?v-baoE+VCQ0gL`U&u_gJjX2X+V`=FU>L zu_tA_zu3CEPmgrsU%QBaw%NNbiG7Hnhk2^;7NFIBKhwJdoq3@4+L;KW;w6*vx5Amm zbqhpssz;%!kL~EBSjydSMrMml{xC~%ruAUAzB(&8`SI!Ko6px3ZkTEnljyf9AfYI$gJOPe(_&QnE$JY5ux9Q;3gbNd#2u3RT7Y2Zjl!)zQQEb2O*eckoD@WT?*utva7L@ zekxp$w8AdJSQtMs^n807b-tj!A$c+<#(1Z2S;h#aox$+|K zV{WJhAMo>-4rze^Ht?+D!QqsSsEoytQ!aIL>ftbrH;jXYiGeJs@6o0Ipvr&E+q26* z3w;zA4bT|8te_2!J$%Td&%3z0QAl2&fGc!2t1R4r$$4tRKOR*Z;!wIp28tnu+wO^j zn^H>b(QrtfoAJxeR?EGIL^h0_Xr}K^{)Iz<=S01b(g9z+4eGopeQNg;0RJn8NhWCM ze-CfyUMa03l|7IKtmBM!!ajbyTF!%dF4OS~2J0*~wI@pS>PG@nx}c7M$N7y9^>BbR zntfMyXs)rEdu8mbAbo&w0}s-M>XSj0p(QQ^714%#C2^mDwBLd~b9fKi@CJukFCzM0 zd`>Npb=q2vzu=U8f0kbWYmOdMRC2F7|5kg?d#Si&*N`SpnT~LIeztd6MpE&0^H<-Y z{|z?tKUJUm54)xlM*qVUI=J$x$hZ6YDH1}D1=5S_k_Zv>F!sLwCE<-f(XE<| zYhuVh&@E0|PD!6X(XCIjuJw3y%dft@?5*t8V>A6f;j%(hP^Lk^pK#ffimB34$DeRn zn3Grr9xh{?UVPAs@82O-?vft%mi`uhiR2xF=&hZDiB4YyC9N>ewlpF)OMU{V17q?{ z20HG0IFwI?1i#iptljD?)9vZhOh)e+`1)n+%Mu!Ebw`*O^)J~d46Q6HM^%>>`eqN_ zQ~nKI#7Nn8`}V~L;alSyk(L5|8us=B^HZ4*hGNJ+w|mn2yseuFV&-&U9A7Fx={kLx z4bX6dkCg_}aevIM%^h5G_xN4Bk;6~G*@bl859knM-ZW7jCG4dIFH7prK_MD#>OS0Z zr@6Z~&7&UPL*o9aC7o9ClX%D8KA~sq%Cdo{a|c2V?l7X=>(=kPHWh7hQl@D%#t)va z(*5n^R?V22ta~4imWR-o(4m{GhD(TO7fA6qG-E>S{+TEPonJ#>YenXohR{y{L({7z zA5xDP1Ke0EoxweH#(k}RvgA9n^J{_gTzQbB=#AAp|IdtaR`vbjD!%Zxer9$USLf-c z5iPJiH0njlW0D#3zUdr+E_1&Gw(|AvR$w1Q5r_nLRs?-%la9rjsHA=?> zorgO&YA~M{cyJl*w&_fljn;2_kpnUHauOO|TNE=Rt4UuA?r$Wyuj)nWa(B$`>CtN} z^d4(U(9*S9LEcvGyS-s=Jv%G)WDPbS_RpDsCLY}EWN8*uE^?|y!R9F6>v~P3tir=q z8XI5TwTU?F@w|zhaxduMpT?@YP>ys@LsL7cQ4_HFi61{y0+IzQjkroS@=Ei9la_v~ z($eg_CQA}Qv^Pb0RT+r_jyXK`YU~s;muZUk8c6-3jmi%TA?r_ZpVTzT(Lr`k#Oj+G zPKdK+*cT)?^IJHy2Z~gyz8X0q8`yD4TVA!_={+5|ORRFNc-e4st)#n)`;$asb-_Bt z>90jES)|hT@0lUp7 zC_Dug&p$H`Du<<+vsg0{S8wtzW{Hk+F|69Z8VFy+)%sQ~KI5nRDB`VBAY55LH;Gp2 zsN6@V0HemcWs3AjCRmHwus)sA`hj^jM-7T`&fWTVn5=dY9ayx*Dvbmx4nLXg;wQj& zWNz8wl}^2_b)v1jm#R2*@@tV2Ds0+kvr4TQ2xNNt$GKfyzJp?3Kd2sa4NQJ%6j10e z`Kc~bm@;wzKMZAw^0fXi{>pc^K9w(fUJuX0VtSoE$)h;|6RI>S|6{m0d#83NjDffx z-}g1Hyy0IpiFKWOrt8ZcP<#6>dnvrg@(+cP+J5)w$Jt(t-6!SFX5L9Yr6}|$@A*kK z3R*l?qn~Laxwe}8QL_(HtC=hiCt=$sl=DP_|GO$)fq<8z7M;PArEmS6NEt<6k}90b zGZKz@$L;QrUDw=Q+1D5wUJHw>I0*>{XQ$?rS&4;}TSQu=OS}4?nDAAh-hD^e4vlY0 z@kYKf#gR1(8?xpUyGKDU9Rs?^Y#Th^5Vd%aEu=y6=`8k>=}nTBj?)RDH3hys`Q>AT zj|zgbF^?^bSjU_auI-{G&1dwyllCAjVf?~Q?%lCkx=HY&WM z3y9mCe!5VYrid6s!Nk*9GoQ?ENOrbHg_lh62K102Y)m{rjdduC|6+;G%bIiceLuO**3UcalcBVZr_Hw z^1ahcIWH)TXj-U7Rn@Dv6Qm#0B28qfA|AH8wdGz-Jvt-O59Pv6s(-f7zokud&PA*} z4J*eJ_fI-IPpD5=2dvKG?D%M+w41wKdbYKY-JEm6>{SIz4?KkFg<`+4%%9xw^SqaL z#GgNHnll|X5^x~v9PxxZadeXx^?k@Z*Gh1!G_JC*-2VFEZR^`9XQ0anS&SEb=8+Vv zCRY|wDC3c=g_xkPF|Ow7jbU|E^FeiXbMr(O-t1za1Wp&&Yj`_4-I!@?d_(w6=+HCZ zi49YEKu|^f+^{xmz<1L2Hd0Uv<<}|PB66f7hVCQY;`S=u-Qe_0-TMi!|8&gs9S2S| zysZRJ+4j{;uyefYUu`)$P7m_vq?r>9ow`L74Fs9!4 z@I=_Qn};SGy7Eos7Os9Ysi7%A5Vp=*{7Lc2!rOk{*ATL2i;4m5so-~3lT2_Zp=GB# zT7ARGK-dem^WNO6aI{vR71}N;sLr`)sc7>s4B%7`q}bOj^Hnx4&Nvx(_B6wH#(aC} zeAk5W{=k-puHu(I<+?#xS?&1AbzHUPi^cT?{~_U(D2{qSW@zf;Sp^36jwLHLXEXiGE!5RC!I1x%3lBRi17wx%(xx@Q*ia!CL@l%(4 zg|`X|xEs`j-BV+lhL?La1j%kIRW#Xbgb4EG+L5W(IqW<@zThs;rRlcv2;hB4Fx)>` z7NcpbH2A$6uc(lWvQv}rY%JCf?CS^y>@cf3>cVfnUrp=TZC zRBMduH@oJX*J*~ICn5(x^{<8vY`4LyQ_D~imEM~Iu;*YT+ed3eZauq(sz{fL%|=_k z1NDzXRKSaVCr#shZc=VnR8{Z*o6#Da(nwNomfha{h{TO$sa~=xxyqFjsdnzC*Cn;{ zo9fAcr_?iXxNU|F-`fehaah~i8DXZWR6WNeZf)*O%d$L_47*^hBR+ynP~TXpRt#ME z`npEb_zM;?4Adz{mpsMRP>s%lEGcz69@n z?a$cAPfJ6pZ9vN(HuJP;+J<{$Oo-ii~WoH^mSMX0~UVD0e)P{KtyN* zD8TWZ`Pn#ShGw_!2Wt_@;5)|OlpMV7*iCjh)wXvo5@48TO_Yr_MkKZiROuo#_`@UP zXsEkw!gtiqSMT3_)XKbgLqt0Ngi5{!*W=sjyAjQh_1j1kUw~&4W|O<@lx@fDQK98R zUs1`8r?~>rY&D3Fo}Ho`U&#BO5UY&LMp&d;=dX7X7o|Btnnp~DJfOGh1tK1s#nnjN zOMO3dTHVs_XTbwK-KHB}>WWi{OUB3P+MkEddh zrcS6t3gy@wAL}oQxq`Z0?-9#S;Bt0n2-6KCt6(m-DOF>bPUt0udQ;X*O^W;RS1g5$sq|3>3;2Xtd$UU5j zXmt|Z(OH{(Htq=}9yY>s)z*hlBf7`@v z_S}lj7}Fg)rRbY)zjF)20)^q0J)ug5H)4)1l%?==!z2htMbn>j!%Z?h-)Dca4T-Wo z^x@ft^<EE@l*qmaf-lA z+0?W`zS51f8+f#6i;Z!!jBUC5>Y8o2%Z)lu0 z_Poj+vW89ARouC>DO_5v_bnT}PTT-T$ryVbHEr^uHya@KRs3^zO9-5 z6js4v_p*dUjaxR4>I*n3!S4eFCvY(wCqg4ys^{ThraV=3O*?)O8EcgFY*_-}rl33F z7DKsUI^A&*IAraEQ?u6Pc6Bu}7h~;}*9pq4@c`10E(bi{C46CPS2t}s+8n=GVo^|I zDqp)f?}fk|2M2y_-vuVU6tT$M7W*W!OyAs-^7M1V1fhdpv!ez$ryg{8m}Ly&mwErQ|4W0P{ZT(mU-+v-&(&lQvfk>ocJ|1%tb~g>zU!MSuTWyW7((E#V7Qp=ge3 z&Xy{bP^Tvb>$PcRS4jFVj45PwjWx_J+GLuj#nH&h{_L-ioObNRNo+I~Rb2E^W3&_X z4Py0Pr$>q-kGAvBqIVtBXSu5tt;4SD>J_V-17dk~8hnOrrTTtU>%Mo(O7PQ_*6{EH z3&B5*2pYwug)7#e=oGRj3W9c79C56Hm|7C1eJbfON0cB>d?x~u*|Iv*ghr0okR+iL zE)~;RFn%97$ez!afI3%P8gf&0@7l-sioG%DZpShLPO=#WUfWueahrho7 z(1687^u)~Y1(MY>8hTnS~Dd%8I4R(O~cLoUk^4t-?C6WFeRN! z=ATULYqQvR74~%Yg%5l6w%D=l_U`Ns$*oztuft=*6PjJR@|sj~6ww+zlx>rHdpA8F zyL33FIh7hj~5h|X3g%b{n z4I5X@TS|NuuaP5TMx2sFBHp%ZZ0$I!Z1MN+rpkfLpm37Ehhg&j{~4FZ&>$G~ewd+0 z<493+?iG2Lq2tL^KT&UzeK(b9Tx2-IcE7+sO_s0Z8Y#7>Kobg}Ve^_B8$P{$E-cm1oK*l)BJ8`Pio<&JBOP>ZKMX)pZzxn9?uMtx(`Wey|%xP6PFd*ZS-fDGP-lMi_|Wi;nAg2J}a-K?hv%g zVAhmpts_#JYG!3z9%=WwY46D-7w3M_oVGGquu?Z*BObaH)+M&LF_fHFuO=uoCf1`n z3gT%!GKlMw&C+Xv+y?pNf9EYbEY9BLdvMuEiwwi^E%nXzAR%*gprrA}K+vJ5*oWRM zxUX7^n@@aK^EJ_obV%Oi`H-4u0smylsoj}iwW7(W-$HO#P1o%Xx5#RZZ4qht@6|Cf zM@LS1_+(1;P)t>5&d;ycWjCs$#SiM^)PMwyTBRQ+X@1KgGN%N&| zvSMT(*2!$!ge)Xhe#c(K88(EmqvHxHm@ZD4-LL854>p$Of(UV0ZLb0YJPSM?^g{|7 zud${al+HhM$UzxKVP0NIbFu6XQ6v@*ho;I%007B120DtL z=?oJ$qayTo^p@sQmJ&L{gI7pAH0!6s|oQaW=J1MZj6Ut zOZm(S5~qujZH#Mb-Ji*eX0sQGEN%vuC(Ku)2Bcs*I(xhFyvA1e$Zt$&9wdfV5-eC# zrF(HbYWN+%_#ID%|F!AfCv&YAg}b9!S;mV^YT_vc%|VA_`!4*BzWAjxno3v<{T7!c zk>9kS4v%@2TicPakJ1ss7`_;sR_n34&C)tFD|KtGV7b<4M0uB2)=>cSt!<0o<7}}2 z_p@WIAz$8aDPl6Bv$M1QvNPK)@uXK@4T)j`F3C_qBuZz8zcvDO9dr!6rfV`GTD`QG zyYo@=Tw;*K_y_#JsDZpB`oQgN0#Z5Mc(xql=q%hQ=kYsC;qDt-l9{&T`?oIux4oWi zl*kE22_iN~E&!j;%FNwg89+Eq*#)utiY<2^C2@$noSQ+{0li$kcu#=erT)3=BfmBR zJ3Z=pA-unFY19w_hJ z-wy|6%&W+HI+52IMt|OjCWDWMb5jRc9OaWVuc&zyL=0QMYbz=AdTO~sISr%F-}umDr+lWe>7>x=4(9Q9@{8~yu>MHNv@|%RFnU4zk*)iO zD#_4+FT*$eWmWJamryhQemnC4Bd2!Yfx=%O15d2op12hDkLf$@Y9^;nKJ>|!kWCm~ zO^IgLW#61pKUZ-u9^cV*@u(#teIoH%gB5*eslm&Zbn)e!xy-3mCbj!qx{dJkyHAj_ zq$RJ^L{U3$N9{lUz^q!-izvhOmhA-@FJNkq+hH>3M1fys_m?d|I%&cttpDMA50R19 zpxvlvARb%Lg>vaMuS@GvAV>7esnXHDvSKRg4TBR|N;(82pqf!*nlm^VC{JD@qa!@rqCQjNqy{QDXR4Y-YC z%ktr#yZ`J5ubPwVB;1m9esH`dYtBs(SFx=0>7}<~*mz~v;fR)|@VmXF?@Jf0_>SkQ zBw{MHX1j>Q{$d0bLZ+esdYlp;2;;de0`S`qny8p7uucsP3rkH&*%069 zbi174!{mfNVX>I(V_``W#$R;D_seqYr=Iu_6hJ=Tye=N1Ali9eF_zdk4cXBm`<%HG zxo;o)qp!Y$RUPZ+brLL1jw3VIX=MHJ6d6+94($=S;met08~+8T&pmCpL+`l5PK!C5 zfQ)K;rddNu7+Gv6BQ3}W8cM7R>Q&L<)-KPFS@!;|0h>-XTr--s>2}9X7ar%%F^g8x z#QbuvUmsk(V{Uiznyy*VE^9i*-+#8FWYaTc{=EAgre^LH4-DDmcuiI?v?SR*MEPr`j&(m-++$beX?|ZMO%r1#S#!AJ#pe4Y@0O3&*XSEx z%{iQND}szE+ZJf(%f2lTzucdtOI?ndLk;Kgns2Nr3(qDE+|ISA8Ux3uZ$_v&P}z@a zyFYU#xPCAwUSaDD^>Vym;srVmDxCc~CM5sqK;;J}1=d_?(B7aC-R@4_cJn8o-SFqI zPblA!NccOUZ$f8D=^eL7<`=%hY{w#mxX45zAovL_m{c;^S3`H_10&-ebtaj~0ju)ZMt#&`1K zJ@-D2f9RvSn5T?YPvzxpWxuOvA3JkYGghD1N;BUU+M!jEfXaVQP|eN<^-lw^G00bE zN2fT5qM&7bWJa43TnFy?m3@9?aYMIsS$+b@6Vwy%U65dk;h~i-#~(hw9OW-ZmsGs= zg)qJ_Vai$!?F8*c2%F|zk&W9YroybEbQFUgG{5EjG2#J7YH1DQRkf@=BqR6qC&`># ziOgQ;8{pCp6&7;)2E}X6-=@$%9IqO>8P`6Z)V=sI?BT+*uth(s%X%6-K{K)CmkIqP zW>i2mLZkcqQ2}XxI&8Vc9GMhvlz}tGaVl)mJdN7{7RSY$vhx;l1Ci1^d-@lv#8$!k~H~By9c)%{^9|qcPBK_}d4oDN!_UC0q9IJVuu@jR% z8PWCc45ZL}=hPzzzc&alRTX3k?mH+$2-ZpCF;?IZPr(^XxAlPYhPoAFg_~ zF3OPdkUBkX@H}7&s;g}j>EaU%)!VCIvmBmws2P2h_$H)jNN$`45YUeFVEi9}qTWgT zEw}g&Ni_G&{v*YKKZK4qO#NG3N@j+Gm}(bna^c0v5r+Nxk1b%>Gyr{^dMm-M;f;L* z#{`-lZARRLbd0=nVKh9=gwIJV&(@8x`VFhI%;cLu?(tuum%+gC8T(FmMf_N$5jEq0 z*Y2KZd#5FKqbR~;MCD@VKE&-9FF#N5LWo}5H+c-CFQ{ScBvn?eRClCZmy+!kNWplf zg2RX<;Y3O9$#2bZc}!^W>eUGIE8PkopJ*1TqmkDD_P`h`w^i-mymgZ;f*&h9@4v8$~4#G<(SBma=R^!`l?z|2Z<1 z)?T5TNhNX0r5nyj$cMb=OQSr#&mU$96(`t1Ctdg*>)@Tw#~{c`qNSVnauaT#do{90 zws+KW)<$D6_PXohda2s9S|Mb|oGUDKMfEUcFHA+u&2f0E3{#?^VEu%@KjrZ(lkAu_qFZ!O zYmN~7_%~MCeqT9nN$+@>!oe{|p~EHd0rCAk6<^)aYdFNBxCrv>S;N$$#Q_~7rVUn0 zvue-w1FZaZb;OIAvSl!Zatj?tY07o&Yizgupj31L46Io9$IEMQe!7|G%9qt|q*%|k zz^k`6Np-ko2cKwe_9-?k#sMR}8q6{?kt@Q$6We|4whHF~A+j+R$>7o^0lWy9!4Lmb zo0b~4NV1STVB|=aJX#r@6g50P5`vU#r*W+eG_*0hp0Tjx=-mHhzQr-RAk~#)qw;Fy zFI*ejy+{#$*SgkSj?8_9iO@yw9eM*MQRk_S)@XeH1OJYts(T!$)Ple*W9bXPCr+2u z?J{{S$?cO>l%R71W)o^b86eWd7VSo-uuPKnVv^!Eny~82b#!e6FdDUTB~Pv`vdB-_ z57d+_93ZDWIbk&dm(}Nwj5v-i+QD}2Y@M_b{XZapC+ihA<&1(^9&xthNm5dbs=X@i zI#A)!Rq?Yw7_FscIwoMX3?*{>Mi!qTd5rsf%fgrR8tW0XNLR69X28eM;MzG*RBu;Y zP*mW;FP3toDnhUQV4@76rje5Rq4Yw_H{dF&SUPI-+C>hewXP7iaU3(gtQSbD=2%x- zl|h+wdDRRtl+F)wxq&Pfh zzDC_@v)L9QC03I^1YLp3wCfRpDe%-SO4<()#}!X_IJW-@aA7=vb71{Q5nNh7LnT<8 z?*0b#@-D}>)M%c>H=o1-$6|y?XM&TmN^RI1fh;{U+S}}`XG+%f0>vOa7alq+^6f?YbX|#Iu7BTg;g_Lx%>!ZVc`Xe{exWi zA5+6dYqE_5bp-v8`o0ml$;1h-7LOU!hrE#^zLF09!jw&Y38!y}#2DXBwQu{^%7Ffb zs`d};koq#p|bZ3%q>TjYY z;k;u^dG1JMbAQo@C2rgsKkDfl>{&r4eoXu^W$ghkO3R)^XjC*%yN{}QfZY{LbStJu zhR_XKaz6R&GR<1|Y^+W|cqXLBgT%2~qhYR#$lu^$75RlsO#3ex7CM?@+;;T>w6{cG z9n`8oJ5BigG*526l1wY6-*umLVAcejcmF{mFL$IVl>>)7Ns{gU6X{;sV>>J1fSe1q z_{J#JVYY)tz~aXPU`w0v2&h>3O#Su-1nV>K^jOifeiCkgGT8Lg9@6TNq=;6Hb-cg(d=4bk)Ju%N7JG4(-TK9SE;E~TU-nO**P^d8dUsKhV7$;GT*WdUJ#i?tGd zCSnW6bSta{IG$_#1pJ`)e`(;b^+ps_Eh@CPVY^p&m^%SB_0*qcVjbSxQyZw%%>oAv z5DP@~Io2DNAI4&MwMUN&P4M}Ql9ldiz)XU@@E(I!w{L@eW!Fi(Hf z(us@?qqKa>c@U!La;IebyfL8VrkywPpt0;K##B1FdU2bA3z$FSZAo3*W+d+#Cmk8c4wx0Qah>9j zC<(GT&drp%-f^S=QE%l>bgjbI797F2RVn#y-M6OZ)oW83s$#fM1ba2jQ9^);Sz8WI%=@HK}~~2xl44@ zYbfS~K>7xiV;u%3>f6mnV{jh+BNfc~1SZRh31ow<=+jFNm6vER#k*7tb!~S^G*u5v zJ#9vY+fT##lVGE#15eMc`pY2wMLBeGk16Wb*K8Xb>%|(C;AFV4ePf(wJQe z-zA|qv&|e4*E$;*#`f87OR7t$kWK&Jf;~ zV7P=@N=^eNGGtSORRk?xUk&QWzkueHc&G_?KB0ID=Zfr-A*a!0`CkBfPjQq+lWoDf z)wHtcK@A;@OFE>yu&@l;OHl{PjW`uAN1OYH;x$#2N=yefoR#qmd->v_Ddq?*&6M(} zriULWKf4e@RGVArW7l@jb5-}g{u)A>*4!~8c3rvH(wTnk`)J?&!&|E~;}Hee#p>uHnz*b-#aPSxj2`S5(lGF){O@B z3_xvR^Z_c0{{tz2JMBO2n7`I?i+SrfAt0j$$}%u4^DlZ~Zq(~7Eq>J>fFHNKi zp%EQiT3ZRfCm~J1du%(&Am9 zuT@8%=TFK|2x7nPq|vQ>MzC4SA|nbrSn1!xI1KQMlnf64xtQv1>-5G~F2Qp6>FBGR z)spicbYM}$Ek#f>0$H%8felMG&`;`N3sx|qr$q z6xM2*YnK+0cOb*v1X==oYiwv}f;GFB6N)J@Ztjt`?Nhz(URwQ|VxG1@wYn92I1e5Y z_=ne`vKN|jN^T_PK%9f!GAEX?r`mUOUxKb9+8ZCXSI65$;xHz}k1S#oecrdHw%&k?1P4~N(@SJ>jvjPm$uiq3? zYj!E@XALVTGrGAp_oLymDrbTExRd>D6L#sG0k|+B-iJOnRFx$~`}GbE>)Q;la-LA& z?=z!Z0%iGvxo4yr62FFpPU)MG@MHWjmb+7UIpwgk2is0L@kw8Od^5V1ZVpic7gm@k zER^n*&WVo&1i1UEYq>OLAMZfwRlG#e3mwQYEIPlcrB|tbocsA5gG~8u>GGTH`z$Zu zTH3;eZ`>`IG!LGx7`&{%??de2tlncSF3C(~Jn9g%_XctHF}GGxdq3e+=L$}BJ2^q0 zV7GU+t@R`^aZ)&-URDYcQY)dd=}7;g#yY=*?ABIIo1W3U zo}=lR7E?!|2!D$z&zWffhFxnD0Mi7M@wmFW4aa}pV^6;9G?^g9wd#=XP1!8IG!D~B zeYErp&ql6tvg;N8g*v$uX#|?8h7}n^ z5v{V*eZ8LAVFM!uM~EhK&iqEpt)(z31OLEP9s9Op));#i6swj8B8z<2a2(U`Yn8(L zah&4@v(2|IBK1i26OG9_e!Vk=tvLgT5|;M+HliQl<^tiP`u#kh7eVgOrQ!J{P`F}v zd8O*ObGlJ*mV|vNMpw&xKbsFPXNrOIx3=CbP`*FZZA`75=C1LZ!lr^b3k!p+t0@6; zMWwB2p@MP~PdAPn-cgfH8dirc!>|A2$0L32u$eETOk9DM&|=q^dItJwXVt4W=W4By zyTfSrsP5HeGSgP3{?s%mZ5uVOv%wmiG-D@nv)J#jw@PmK$iku-fU>Tit2Q z=3XMhK|4UsH>AAVZ1%)}?t`(mTR5x3!khUw?Uh%6*Qp)Wo&u`#*)?GJ3TZ#tET{XS z6165RKL9jNFL}%Zl&r5I#pZ1VCx8fLVsE*8{(`-0w!RO&3d_C^=v7<6G-5(yw9!mE z?r2luR9d_#i_G(LBn#e`xXGb`FON_GQx)ibG5NF&e_3IVJ%`0BHC<$e+1+s(^K0A* zJ~oo)cU?D^m=({&=#EWzr&V~PXB!ljtsHwrWe5>A+N^15F%NPr9j`PeTi!%PdX;I) zREf_^2k*#;YzgMWU{Nu(27;M81KCHOjagz%y}50vXnrzF+96L>tST&@r|Hwwr!6&p znH;Ql0QsAue6%UBe8JQ;eKW$hhz!bPrS06rCiJ%<3|J9a5YDM-@&g5PkvlLPCCuG3i zkksTJI`a%m^Ymaa6p{qz(CX)_ozjznxRuQ2^^=%>K4|3) z$u(w8{cyqS9<`^5Np4Pe(uo$kKf;$3$ag;VrRyt|yYGZii+g!)kM&B%`hdXQ%~1{% zYAfxq8?Y@lRXi~31KeLrii}^eb-Yru=qZS$a|XA9rDC5 zBuQHs#aHdSu-cZr+A6T}jAUd5r)}15vOH1H@zGE*nwe2{ng4*6Hf!|9?E@rL?0G~s z$>^9Yhw>CgZJe+%z1%9Q$4mJxDYdV=BqfB4y*>H#oPO_~RgTzBJ#%{pjcu{zFr@5U zYG#63`YHt^T+_rsdVF5tNZ_ALJj6?*caf8}`!B<@M1e)s2Lx z7!gF&zc{HxHN<-kZhSi_5E$5Y`-4f!gzm(ZI?E-9zE|s_xe?@AVFqg_Z?%d{y0xlY zZXLJ178wH!z}0onGw&`w_x6-;R@ls3O9_~Ld%q&_d{AKWXYXDR;jK`yTcmBE<(PE+ zvx@L=S>V{~mWL{yohCoq8cQz3?4kjRQ#fqmOut_z3brSml(VR;JCeAk8kf3kmOFeB z*t{j-YoU_XsbbPs--#IPr1O6d9pH?y0A9u%o?=xQx(je=3^5qtMv$A@l}mwPrEO(S3%MWs71W{A;l}ywVwGrZs}YVl=alpD=L*2DZbOBf`x!gO!c+_v`$Xv z9obRkWC!a%WR;n1%;CZSX&=kGhU*gldPrr-o?KF|?*=*BW<4?wHQBK;IyTjF`!O#8 za?EPz$U(x^yuJ+*49+OHD$QUpI1C**H9a|Kq!gLFmbyOTbD9K7J<{;;MCix5Hg7cq ztVA8{sI=~=O!696bXJr%hm~cL;AHa{`(Aqbt3N)XnO#d}m{HzHNYjj>{^s}OS@0x| zWBw3(3s5_8v)xtTAwt@+Z);CcdPdQgCX>Xlj7-EH3ZQSK<&W)M$T#hi8S7|FpF6G~ z)d+JTAh9<4s#(u894u)jetna3Ke_r%$IDpfrfHi)9W2vy;;PSmsW0cD`kbDsMza-N zYby7lj;GQK?9<}G70o7HxE5$o_O}DNF>j7+xN>W7o9&of-8S{@%%Xe~+;#>}aT73(JAlVy0(1K8{7h~9z zbr~*jwC;ZSj2D|8wQ#C)^|eja!TDBJT%{{6(+K)?@P5&kKu+C~^^qXe@9}LdB-}s& zI?`rNdU?XiuWMYSAu^x|UR#+|_G5(=Mdlb|Q>|OA_snAEfM%c%dY;yM;%ULrHhc*_ z$6~(Gd?e`&GMV)R)P$KO6BaRH-~z7geca|`qmsfbtQIv9-IZ7$(j| z3;9i9cx2seSLq8?gFfZ``62!5f!GXu11@+1IGvb47--|{LlzV`xu>>B!^Vh`F7Wjo zd>daZlwdVg4BM{1*KA@P=55I{m!Gt9gs<(qO6K>eQ0!5+2uBpPn{AsG)v?Ko*?w;8 zbcTOi*{G3UypRuz?c3)n6-p0Us+@2c4*d^eYS`%xS0L2kFTB)Uui|OrfYK+RNwNF;e(SK+NJW!2}SWQx@$txbaZ{E z>xeXt(kC7%luMCglg$CjLt?uV^}UF<0Uf_7UUsJG5StVLXEJnX$2&wOigVhFIy+45 zcy)gb*jQlJYn`mX^Ms^^=|vDSseV&vJXZMu7D+$%@GC#^;F|2mv7b41A{>hBl3$RD z$zo?ix|+qo`y>R1&_xzC_EG3Zl7%>KcH3-iR<-Pt-H8e1uIy1ixT)`1C;xY%Zr=ay z$NyWCN&xpiU4$rDbsMzqJatzFQ*t(A91QTSu@f97BT)HuTx>i~L^qkfRC{?VHh%lO zRaCtFB&5-30pojmVs_&Vx~ynr<2Xh$QUW1&S@sG?6!l8Gdu~(C)w7o(0Wih;)v!vT z@R&sd4pAxFcQh>;>}uvHlndW3c^Yca6HNNYLj4pc2wnQ8Vj28Xp=d}kZ~v)S$^TTS z@ZS{qpSk|2TK{y7+?{Bu9ft?bs$cx4$M`DqxT}hr)g8ERQGRvVM{?e;X)W<2eY)Zi z$Y!8#>3MwgKwRce=g(!n#1t%LGE3IAN7mC#r?b%)B2+bCrHwM z%!^->Ei$=K_e%A9?b(ijkqpuJ#N{Cw{OkP<#=HnWu+75BNuaSZ*^0+Nwc}pdqBwz; zYT&B_C+XRHa_GB;rP$XOv_-UU3V>_v{)d5 zjZIcXHthT3)78kvHe#F9)*+6+V#8;Ki!bs8vchx9I_qpR&R!Y#QOwW{jCURcdytK- zM;3}Yn@26dmWOsLl3_uQ(~%$R@AX%)+V~mPRju2Jb~&qGi__-&sC6}5n--bV%!k=G z4`Jvc5I-~(9Nlb} zF625XXH+F=dW}BNx{zPEct8?gTl`JodcrBWr=G!ucj^OsoaBwn!#i4jQ@H&U7CDpV z1ZdsWtojI7e6Rb7fh($?@*DT9r${<*db>WCmssm>ihU1Na#90Xlp?>X&pfk_7nv#C zU5RlPkc6}xrGV{GC+Gf56CkBc_?;awvK@1J^`XDP5zso^7~^6UJY%P=OlwrraU%-F z7=LnEUgC$nEFCgH=(0r!{SWvES3XwZYiMf;OZLfV%A2o&#F5^00NGumK6`WYGLPWA z($=Pi1+UjUo#&TF@<+2fZk6MADzKfHIt6%Zf1LqYx+hA3=lOt%XYH zvd^s(^$9O{d?3ah3obp8wJNL4?KV!wb}U;R1?}hukW>RV)hS%ZS%#$*2YEd5N_1+O z1^=3!UXz{dV)EC%&~T*V$Q7uN>evHykixl}B_Ou1!}yfG?>8ZNq9EV!ihDBi)n(MB zBJpRYjT>f>l2O=-$v9l}f&%#KL;Mk{ma@4mw0%Iu&hTI(0nM(TXRyfF8|pg}CMlHe z+lkF_8qAec*;?niq-`Su4)hSdcr{9hi8m`oy>6M?v2V2$W0I2o#A#$={A{Z*4%3A3 zCA-n9=)A0~Rj8C6q?d!1W#D^R=0SxRu*xMgP1*pb zGtenA`I{oQ0}z~5CVf(GIOE2wL$=mt{{m$NPSH6gws>r`7MJN|xexVrhNF$iZe# z@H+0L0jPEkW5rE&j@zL${C!2|DIf4x z!0EdK3wFC}s9zrNcvyL@WPr18bhk5)0*EuX9UZR^U#NPJ5hF3E95h4{`%%hJ*||q! zN0KNY85!E;oh>dmo*$(wZi;^hvrDrPv{UmP5F-!pFe9uxPKl7&a9Q_kGHC?NVyRrc zwShxbHkRk8>l&E=AY|GGVU92&Pyn!RlK?t2GH`^1#{J17Y;o(3Wka(dYg4v^g#}np zEMOpL1Jg9&efi0nQtn+@vNI2GFsb}Y=pT+7*!<%DdvU5W_$MOiH)KQV zE*&m~wU>JpqV5zUJkbS}@Y-FN{DuAPT*l7XDS#W;QbppTuJ&5l$Lfoe93^+tVn>Ct zlnu*Roq&FKT2E`4^LQG;*&~X1nU459%9>*zRm%y|N{J3v`~bmq*$^p7=lI-RVZ52-(&bW&?UM9U89&;@KBn%Ar^FXxuU}n*HVnPvY0VBoH6E zBP}hLt`&CvW0`9*oBL_TM)K@sLly-mQHBK#vs>$xwbS0j&jg199v@HG{c|H zHK^>L20)g#GiUu^9EqaK{2;eVoWI&5~?&_{cin(E(Qrd)OJRqinBQy@HO^;=f(zOq%Fa4%C{v#4^^05LG8JJ*?G7LTH zoI52ow8}~pjKl5?ohdh13Qi3j_ef0pNGA9h^xZ(kZ8w23b!UCzo^9Iwd^aL@EzWCA zXJq&lq5qQ3G%&_rvtxl!UNkW5UMjMnV8QQKwceSG{ARh>OOu-14UZlpyG+pd$>Pk> z^AsoSh5Yfme7o#z9XNx@ncIbMH@M|b4Gj)mWXw(FOg>3o5 z?;Khm)dy2914c&r-4Vp-jcTJaqE3BJTPHI7w#!eAlE@r$Ba3GvTH}>#CcT!bx@yYB z2?tO{Un2t}9pTTg@TZPmE{`mOjHO7XeV#T3p7J-xuR7#VntNPIJ>+;_B6_=a3)L8YJ__S5$RnG}ybpUMK8A4bA zF`n<7tK!wDZEChf0kN{Rs`aXFV9e&hb4RO@nx$qBIzdPb2J&mx&hFX#Y~^HX0?bp9 zCVN3FaV-fmYhbVC-QeWt>Mw&$bM18VB@>gjRar6<{Dye&l>qzJW;=6IThG++?E#L= zZ5iQDgW}Q38gly& zwPz_kc0W+2!!+XL%ZH+Ft}`Hc!`yG`Z&=lSWM}RMC}D-@&An=h=KKY^&hMj4>JatX z{~*3(!!;v2C=W4lF2iYwL)dJ&+qVJ;htocszbV#JU#e@I*w@~vn{#Qibzy9Zbpm*d za9=g<+Px9JFexCq1xM(pxdDX z-7CZ=+mMGA4*d_^({hKtu`Zif>TqAl9ljagc8=fsrP4@`I)&~*;1yd^$HB1R6__u> zc`aF|iTSvr(J&U4QElW~%P=9KM68bq6WWaO%c-z<>WB?^QZ z?(|7#Jg9CV!QYG10WET1K0n*EL6rx%boc35jir?aP=4* z-^s!B;#U29-og<0WPN>y<>w(h^7$IG(79iQlJx*Au$SC4r!Y&{?N*m!1Yn?DQ;?Ih zkEwR-nCJAdl15(*)&5 zzic-~ug7-3=S<~Mq)dTG*GBqWVvY5ZGfAJl?;i1&J^7n8llOHf_?o_fgU@{q$+mCn zlWsrH?QZ=rOvYHC)O%IQ)p;F>Qee{sSS$U&x`Y`?5-$Q_?cDaG*Cka9g{ekG#oYMx zFYrP{9x8BM?5o=pr}Evl?=PD)yHMxXi+n(%zbVAutFFQ3n{#~n!vftF03jaPt7+>} zJ{;#Pt4i$6Q}uzCj|d4b#)xX}wIzLW#gaQ2Ll@2f{&nyUTU&aFb0})@61_#G%y-}^ z)yKIMTLsXUp)%oZ`*O&tmWi7SZQ>Wq)y%bztp&rw&Wn~Os6ZW%O=(r>FyM6*##rBl zO!x~uUfU@c2b5R2Mt5sjbdM;H3H_!>Shff=lYG&8Sf1LycXZ@bsC*=Vc7l zEJkl(5$1D%-dwO7$JLQT@B$tIPsrKO`^>FZRtLeDQ1Vy_vS=Aw{y@0$m@Swfzg@)X z0e#dLc4(v8FL@zw>%)ZO8K7>Sy|Z3f&GP8+;tSLnLvsu5q;m2OByY0^7iX+p75pCW zSwCDJFVAV+`gB3fK45RGxyNPqt4|xcY?vqj%tIv9a?X|SUc5}Gnw2swVcrjL=?WVC zk=JG7%9vM42n_xqRM`wFrU7>6w?(VV%v(jEkrP~;`ecUOSf@mdD?W&dMOav)qOrPG zKYwT=^Ei52F4sqrVYJJc-W?}2fz0y9CRm3E+!jkY0jDVP|H``St1|*pEN*(Lz27UF z%tHK${C*w_9oV|alNXQHNL{(Dy}-)dqCOrvLIpwK)xaSSz~lT0JBlKxs7+ug*;I`6 z9MQqrxz#wPg;DQYJr%pnBc3-c_gA><|7ro{{|wk&i;Cz0wLLc%nZhF?VqGgI$ES3) zG91{fF`eE_PyE#?bF_xkaYz}NmFYQI7dg9;O7iU-I_s^v^j53KGPnH5E=%D~;!wYw zjvc$`A%0J{n!N8Od`*9p+ISN9gP`mg3nkjLRM}S;=lZb34XqYp_Yc(GWW8>;UsnK0 z+w)7xopm$<`~g$90e_tlREZ~9*xKS-@O;V0)FXAXE9&a@w{r7&hz?x55xlOx*#Q)^ z{lbZ-vHMm}Y=9XP)(=XGGAML?HO-gk((PsKsJe9ltdWuocMBgsReY~8_`bQQ-2h#c z)+BU8_>jgckF0A(X2yC( zX7>hf3U(y8NJ+lcE?!T;4V{^9@56vn4iaPI5t3K^*GbObrn~=VgsQAZlYIX;(P{^F`a+Rr{_`BB$Tbf0mzZlwL~GX7&A@PB+Z#vRGv zrU8x=_mQU?Q+2`a#w(2zA2AK~%$Im&DS+y|Hh5(C)5RBebkjwGKlX~VR5duA1VYXJ zL=QIV_2zVQKAIR6E{w;h9M(4}2Fb|_$^4FJM^gb+P+ESPpsmJq&E?I942Yi7)RFtMf7lWAEWt|; z!TeL^M7}+?cB*!%ZQzuqa|O;VgG>bPE(#GZt}lh{+U5)ODs&qp#0Z}22M1nICLcAr zY?`UmmFvL~Wp`qkXdlLer=1yT|Dlw<^wY|4qp__eodZgNObTn9Uhf}TJ+CIyHat@8 zMzU)xMu&Q268*mnsP2W4o1MWg?ypzKJ)1FUn)<=#SNOyX$Ly8sNO)K5Z40! z9rMS&=1(yz7k_T@?CjZ)ip1?!(0Oaf)+_ZL@pxL>j)i=GGq-96{l8rA3EbKI!l<~u z1U6}rFGyBJw8CDML%MmF`!3S!)X3Zng<4^^hFSt6dwQ*duT@J8$ zXkEL#%JkKVFdA)Wu^LDw{wfdT+wwKB2(Ecl2XWt0l#N=f^@S?$lnp=#`uUSU({gft z-`I$Vf(P z`Mx-I9P$v4vuKPQ@|k^o@eCh5X`*ng+7ulNT7Q8Wi+1p(d5cdR1S4(d!CH4pPdW=S zM$45*H`75j(YyYA;#Qxc>Me@7LcYDuO5;c}z9uHq8Yd}T63|v73NrAV-$-jMdD-G^ z4#1|irP$_+S!GX1WMu3|ZwtMKImZ-33m7h^!0kx;8L#kco0Qmu>uAyE={nzXLVrBI zLJqu;`%Q5!P#H!>kekq|M1S%R3kABfa=Uhe#hbYVWmVFOD#@^cBQ)m0iLq>mPh%C9 z!yHLLhpQ{(=<9jK_M2i+z5cD@Z;CC2&b5KFEcZ+THgBZ#tNQWWtoRb0qrAT7sOx&*3i|l&H^ss-z~S=&N2PSU_Z4<3{iQRm&c~Go zrg>j>#L3YQMWnzRj%SBUm(0e1&^q8B!Gx_Up?IQSH0~JK)&vl6-+FMgWxry zXdZQ3E+LT+5Naek@?B$~nZ_5W;E#2HF6Hx_^|<_XM|k7kCMTt((0p|3^$OS#H}ZSE z{5r@F?$L&$TXD?p`h!qZVVxTc4_;M=xeTsc|2YRApgO3(Px6v~Pdhy8ik zFC}-s;K&YS_W%jLbIbfFT5{)nPt`OEsE-uT&M!)10Hq1$N_&sYO<8K6oc$cV<<`}EgVRU|cO z?r+Ryb%Q5(77v;db`ZU}-_XwYG9}@c* z4o{*<9%Q}cXE%Qae1hx8#kTEM#)QKo6y3t&NwYR28-VaNW74WtAsGHkEyv269~P(-mKC_i z7N(?T62U0(g#BeWzZUz|VRtqPO7tc0(*k&obAgqem+@=&Jo(IXgrcdaIb;}S&pYt2 zfCwayWOTevlepH40o&%b&0u&@^My9u(S*=RN5V1}FYC2I-xNu(@g%r+f0)~jt)Q=8Hg8&MLlSu~qVrG!^P6Ia zYQGzZll-Pmz97g8OkiQy4pwcQzsc14q-R_}i;(zN^$ZqgLSiDGpdqoi0 zys&$dVegUgAW7-Likg?D%*jD>t*v^#9@IG3r(KO>^mE{ExHC#qD~S;xn>1=-}D@ z8fT+^#t4Ba2K?3FVgr!n^#;l7P}Qkt<|byWtM4MAJ7zNEQYA@0D1M{C(rbX;z+Pf5 zvsd0lVwB_2Cr@S?rtqAGG(~Bq4(6Mp5a`wJUn=ZURBZkLVppANpU%YwIWR08R=vlR zNK&xdl&IAFVPhs6FAW%R88;$rIqxy{C)eTCBXGW` z^e@w1*<(Mio0Rwfn>Sx7OIi&lkgi-KH%c?5^ohoIFHz%TR-tHFJqz)XO8Oq4SaSBK zu^9QAw4uwhQ0OE!bx?Laqs^o zQWJGBuFK103rbv%_r7h3sh?EqOiX!r>VUVkRQ2~jclx&_5fU``n;z*uvfcSyNC}o{ z$h@mceB1;QOE~(t>Yyhv0LvGc$^~ELC$j^l8fL^!)z8nf_k6SQciPG3SjZ$$QYZbL zsT)x?^5X`3R%C@p^n=bsw~a^JBT3-bNUaNPjf+@-)k(o`3c(WM_Ic96Z4zk{rh>CQ zk6t-bx|+q)S2^se=tp6vY1Gw%F-caDS+uf;X5b|lv@+d> z^u}w2eC9hqI+XHT-ucx$qTPO()gc{e-FJ>O%eX$4X1eQQBbwrs9Is5s1v$3mB3e6m zRRg=@Bk(3{^%=@%ryWj?KMTN=!0Pal^l#Ejc?4N23__cYNQIFiHA-?KU!OM43on{Y z8U=RQ+XQMH7w4p!9GY|oIu3cns~WL?II$BNa!9Ep<^T0r5eLthVxNwArQ!;k#ZWPM z_OUiW(ZRvfU%v}S%*%B~Kru}MKNHSVp#K&~z+J)hH$IkN`L4}G!VahKg=^<#KApf* zb7qSol$7gU-ll1usoics!1I~$H-~yl1Dq>XBLeb}U9EtY4-X&wrg-dcx4T|oo?A(X zoXk@Y#Z+U#MZpFIdnP9&1UD9jFpavC+kPewCAmEBc2!ylX+zW<+9EseVbedcjm1iSMP(fBkau3=srrO%C&yt(Ez3|7_ zu@zm@ub-DV<=(5jrptKL8JLLmsv8sI5M8R73Ld3uTdW~0$#^uu&nPGtWPAi15I!BK z^pC4rlN-6u2kkTxXMM{(h5tx;)I_gk%EqRx+~i6@r(&J({W$^SNhE-zfDH0Poy=wu z5`iBQummyVwuZKAA%w7*#h8xU>D8yj5~rD=C+B5h4Z1cH9(yLZ(h1y3u%3Cb@^6Zwy$^a*%KWw4yAZ5?$?6%!P4`f? zoDn89aFDxNX3gm_SG4BNXN9a{1#tMQ4qK$b?PjYrtnSjt&xjIlW!$4Sa#b1XHjkR$ z=!E1P>)7~8D#z49^D{En$xg5X%Evo@;&VFDcgjlWIZ8)(CFwD_uLUOx{;1wqXhpno zN`8L_?TV>J;?}HIw9bnT8w)P(Q&lX`ho-X(RRl4Lubg{!<(6_>v^=FF4*IvfTJ`>A zJ3hKIA%W==kEPTCq32`7PIYyvuXUI-(oap0nZOJ31s-v#w=`EtjaWNjU3(v4aA{QR z+yAdy;s5E?{(tG!3^$)csh(73)H{7%)=Qq7*QC(5m96bJ-?=5@v)32M5gSn~ zWf4s4Pi!{QEY~v?F81XTJjzYxq~p-cU4Tu_wXqgk`?p$^SK!&oHAXT|rcxw3p!s*= zbM997xI@Ego^Z8%9l-j>Pt*)ll2h~;JZ`od)~C)xx!K&dGsbnld19V@yGp`81Pwlx z0)z_wILDCNYb~}cYuGkGh2iKR_Y}~Uw&)A&lqugvsYnq08NcgIjT$zj96mQj(_Q=G z;1Hibp|;yV`<66uU`P;!lzWZ4=ko&GpobHUx_|^zd-EoL*@m+d>0$YU%!JlQp)JZ9 zq@Q_2{>WpY2bEuuVrFGWH@3SQrvL^OP<`50Ayq-3oSx5@+M*T73SyDePWDb4&pV1( z_=K?$u>M+nSFwy2$HUZ~+GCYH{VR0cUn^cou?M)-y2S={>-I=ZY*(rWjcN5`^p~q(WdDdwa$;u?W+p2>AFK1p zs^r$p7~oOebvfzp$r8($z&n>G$h+}dT0PHxQvm6Vz;y!TsLC%F10Tnn(M>33xV^ur zYn4NZTSj(p{q2KBSZ7IeEZ{#X^bp|hGkM=rYSQ2G-HMtLFh-MIkFH^cHi}$eAue^B z1~@JMM}DcMvI1q0RF6D%wOuBs&GZM{-k8h! zCAELAB+s3>!_ddVi({Mmk#tSX#*%~Lk)KQh8z&}Z5noC~Nwbz=apcuRdHxr*{pO|0 z6%Je<-PWdYV2<$s6tqDOJavI99Sk4>&a+Za8@2S$$cmHvr`w%>3QDQnN=mDH<#t3< zo~1leEORc(4SJ{F9gTseVJ0p#8~UwG1lAL zpw0e-zaqq%+68jnKpk)oS;={6r4u&8ZdzAetNKL}B}wQg+dIg!dyr1=L4syZn&3cHNiz0xrYo;VLehgXegQ<$)C>W_tf{1)FrI=NbIJ|iq5#%3&%P0 zgeLz|*Vx_S5gpX_gOgcqtd(Ny39X3=nwe-=p{qzyiR-1K7CM!^SCmbAzM89{eUJhp zcOAEKJZyJD*V!4A&w)WyVSRv6L!+8I6P)3r6=&dt;Nr3brbe#Y%Z9_V0?DGO;WV+mj&!oZ6yDm5P8kFs4!3$brgzU>B_?dQ)QX!-=})+t-=Ij#3tCG7Dww!}2)w7tFnp|Z zvTrT}>U%D~e|DzZsJH;xXww3e8;@33bBx&W;O#`xb%Fa9FWZg!b!?tUe$KrUpWWB6 z`{zM*p(_l!9aEOw4cm?`_7O)5oW8EpYhGExbkf`08i#y2!5a%Me=e@ZIxSby`gb&b zPw=4#j9=7PMN_8(m&5|9w-Z7PJQCZ7K>8S8{cf%(A;s=&$>J3qviDHw9bkH_h7pcKcnOAWJIs6zIZ!3`GImoz)f7U zs3J##Jq*Kj9cab5t&1vY^s4t|G9FQFD`(x0#^O&hb-eZ!Y<_4K-29n z9}OWGzk4RMt)~yTdkRy#JliKrDyM0Yt5}L>Rq&GOcq;nbv7$+yIzt*|SJN&Y>eah0 zZB6()9xC}t=qkN5$IR3bonE6LSSw&a`;k5oM}R6pRX$T#d)R3~QDNfln`1`HgyUVJ zotLVBVkCq4gmb(sqP(x|>|7bMQyOYqk6!TSd}5zpR#H%u@5Ja_@ZwCaeQ&d75pr?S ztny4;-OM&p%iU{Ytf-cyIHNo8b8svc4V((zwAc`D{{w5%*nl;;-&M?N!FRvlHRm-^ z#LlAAf$3@iFelVgS*6O^FKg^E$<$4oecqLtaQ==cY%s=oy!bP)djTJ+(qB*xDBHf9 zuZYgwO0esaZ*O1|hMylg&vbSvnJM(!D31?5@r4y6CAq=POOkR;(>m_Rzw3cew{Yh~ z5z-s!Lt0I`hlVtnk(#`>d3exk|J)lsxsHwZZ<#;2eZ~P#3)1szm`v7YzkaLB=_Ux( zocz>_cC>xj_hkV8wny_q<&;cTC7-{Ef1(2G@+aU-?GO8F))Q#eKiyBP#6*e?g(MJJ zIigKPKiV|UGi<>oiwR#n!nm!uG_!i4vHqCUqgF|2b<)g(=mcvA6gov9roqe&mSgQ( z%*(J&hNX>e^9Xy=S^!hAJ2Vr68k!90@L*=s88}QhlGD4UHO}kKJB;jBsA$yw;!Biu zFwF<5=_G}7Cl4mS3E321HEs~63OA(Zbum}#>to@W@+KcQT zYhaYD0~WRz-EuX48WW6S3e9Tt&BznDu&4AO z-EWF_Ghl8k%G!ChDwm8+I0(A?be3BQv>&AAqb91_H%i- z6+-yea7;VjLP?rp8`JTqZqVj+>UHJ&mT-Ui*NV!~WJpn|c1A_VNb1)__Zj-WqfxKC z{JuBstJ9>AR4X*7ROtpb3VDKHh566dRgPVUE&ZlY`(`0*`#6Z;GDj3!?aa$C)Gu}4 z_~MqmAA|9gGHoZ}Jqz!DdPmw{yhlJ9biQB&7Awh~fY{g@+yieM+ek7nPK@)*_qud) z(hrWjEJVqr?=S)!^z;RDjU}fY1{6E1!g++B+-AaVF=KpS6YRtJurwb%wLtOWoS}OO zw>1}ZU61Zp0XLUd=weFYl7-E~4#R@AApL`hW>@zenm|t}3Vh)7>e|@8DjXjAafMlg zj_pg2#K04SCtgun>|ov1eNaMsH(p=`@bV=2t83}F=G^qUF;m#CR>;}t(}X`p!!5c9 z!i}~$cF!CncE}APR9!>6B>X=y@BhNJiWVQ}O|PJLReA+oJg@iw0GX#;H?^}Ze|-yS zm97-D~`4v|H06ze*EWfn-TeX$}QGFY`&sMjD7g{v7!88~eNu<7) z5lZU4y4SDNtQdO71B62v`5js6b1!3L>0MWP&N84u-F<$9wpGHABn~yOHx~f3ips`D z`={Jmx;uW2*ITRoG0`!nVPFzWx>rcjC*x`5WjRkKj5#`j3qW-ZyRXXc>J)HY2&yE5 z=~11g#L3KRw(SVFkz^}n4Rf@6sxmIkGRxnfUdoexfF`mPb0y(b5KtE3O3VB$;swO8&DiC@IemqAj-YfMg8d|vg`KJY{Qu#+{LReqtCqp-$wt!)H??h37R>`P+ zZsw-arsQD?jTx-9q8)JFPBv)zLT?U9RtO3!v9p3YF^;ed=fALG&zkQDz|$w-DQkW3 zXP^-zFe@$Z)%Z;LWn#7ur~&md4PwdMi1P=rQgd=DyxH#jagC>O^mDhj%9E4?W`aH8`O z-DJq_3*c?D{xjo$5KsQ+oZ`+AzDb6>u(?}a=gWD^#Y7aPwtejowM8-ucI>!Y*)(`X zY|)-C<&7ur4i$p5f*;>TPc7#6aJXee;YK(Et2DCwt;-A5M_Y$bPy0t)@*L&Ocr1Kd zMvXX0TZ5yQ&f`~@TcSE@>fN%Kw;Q#d+4CqH_3O`ABVq346~{~?TMk4GNARj9m~ToK z(6?pZ6lXuj^mVFBDE@m=6ir{0#j@1v)y*biv*CUrOXh5qLvJ2lE$D}Dd{>?caZsr? z$j-y|08H#EIFl90?{O;eFg*fasF07u^G?V!U$T=_y91JV9m|vZNuMC8LwZQ|l6W9k z`DZ9s&WUs0g#&#TcS>QG)YyoouMbtMtze#@}Jt z{}-3@^w)+W*%D)n>}2tCuzpa@#|QhnVKEVHu}XU;2f{_U;NgXI+jrcJlzhjkyno7 z04&5|lVjpkw-J$x@_Jn>1KUB7L8L>UWyZ!y)Au$F#-brU(o-y`ajkyWazuZJ^L53X z+~IGFCqG-`1CS0uz5Y!xbr?sHhXH zb2_)VI%@DRbaPR$>&~{QRtJV&mAWH519s9)8V2u{)!Iqbm$dVi*1xoDwM(0JY*vsH zssfmnbj@4Y#XO~u{?>{NP{jFg1KDJ0tv1rOZAzZ)%_H7z$i_s@^7MU%S`wTuNp5lW zXIuAv(u!j5Z}ZUNKfBeiJAM3F;W(h)P1CMyiY0zPfi2h_`+1(fG-N++ck_v`?5nlw z6uT=FuA*0N)i*7Ck*by-YW%Z6z71e5VxgQ1?Q!EtvM4!V;dA{IHNP}Nc`w-k(aH4+ zau8|)436g;GqHh{MP=1WjS8)-GjRSd_TDq7$*y1f#tRV@0TDquDosj2dIu39AWcf> zO`<>`0coLwz$Lx+8kF8Ugiu9#4ZQ}CP67exO}L(1_ulut@BKc{o_S{8Pw&k8g#jif zXNI-1&b9vk( z@ayJ_!*s^xGp?zt!yCCPPMasz;x@T6r-334F@x^XjqDfl+XqbFXk^xn?j&NPqt+Q< zg>!XjQ9Ht=`SB~Cq63X3AP{a0dsK#ss>>jXJU|wKKLy+x6-tM?nU^e%V5UUiTh*dn z-MX6GJE>vU{L{kpJq&;!FT%0AYxObpbJ$F@x-&L%E%}WSz!m%LiJARi8q=_^oVa~l zyjjWbFvrwD`N$X|LPb(V+-bSitZK#{3Y+&jF-~t5(WOtjY2L~M`c&7Q^4mEmm1?Kw zKRfoGXffL8k<}Xf=3j)Tft~pBrq$Zxz|XozmPa_5k;JuG&8l-1cdi5gHFFL%3&rKM z;V*2ri&mi`$G@tCByw$MMZdy{NN^Tn2ejAzp`r;zsDacC4f$GD$sOVI_qO;9x7LO( z<3d7GAVJY@cKeMn?Z1%(E&lvNjO~*F?&(&geya@g%eLRAT}AM2hogtvxrfLpiFoiT zA@?(6^k~6qqG5Q$EXA^h&kLPwSXx~c_$4WMA(5i6IH2qEsRYzJ@UGl1LJG~@r(cGA zea7qy!mQC%Ll-!_Xp|^z$yslg7VY)ys%$pZpPzrq0pQ;yNW4D@(A?zNAQn&yZnbM$kOhS?EB`8vZ(`%$4*=*o=< zOD@Ho=!cje$2`jKF3qp}ifjv>pZA)lCS!NucoZ`cN3~JKy!h+3G-)x7QF0J=DMV5G z0sMCH8?R)<#@qld@UO zExv#O^6_R)L~qa1(go>s21Aj?^4~#T7L+<6&8{8~57-@7I}}wse^EJM+U=juR6W-< zF~6ZHIQ)V@TA$K&Snn2Q4lCgl76n>mPKVZuPefRe#3%~S6yh7g(Z7~ z!Id((lW%n40kKtv0+Je=F)Y3169yRjjfWExKNc}(td~Uph?~F1PV^RAsCCI@J?6uM zm>=+9Zzlv!IntD$M%KdGgJ)Q77{vj$_;z=y=J1$HW$aYCqjk(X=K+JroC9?k9?w)` zSRH!y7eG#@(Mf>)kL9morx%7NN(aj{H@eNz@aW26U71aJs3pQu@|~vR0+B!7l^cPTmw;wk;;uRu-`~hOnj0 z0iRdInH1l5SK)Fd+*rHh-7~F<`556xaXTefQRG zLp_Pxy*$a}TwHX>hR4w3n6KXt`yHQzXh=j26}n01l0?a?AF|cloBEeLhQtoHU+7ds z>yD#feKiqhyuw*Rmr+}aU05DG9v5*$w#3-9*U=CBzBh3nv$v3+IE(iIxqI>G@Nc5_++_9YhGU%~9Qb46 z_S^lotfcu!KpC39c;WKEymoiWihotjHcA)^pO-^wT^YkWDvZ9S*NQb!%x?g}8uk`i1msSoZ-T1NgN7OF zOV+GVQ$`iX@jBCEZ@0OEm3KE~3$5;2DE-QQWU|W4X}1AKfPgpJ8}j$o%aBc6TP}`;Onff2U6A zu~9p#=v#gY-x{>6PiTkagf$BqSPN52M1$VI3lOLgnde}cnt|V0aJ%s5VBv8YumoBi zytW>areMOsgrviAy75s$ormbu=*}Fw^Os&BxZa=8{LdsI0EqO?A^IKrog ziA$Na8RzM>J37!zLCwuhZA&Jw#W(iSz>-qX0$y9>)UJn%9!rg;7F=HB^FFmg+fZlr z_zAOqu4!x&^d36A&je=r>ie;0g_j^J^zJ`PSZ5%0*0Q|C0cML<&4X$SqP_d%$NWi!~KQ9)Z`aI@E zy&(E)>h6TJ&k&{i_p7i&d7`(Qi*Do}8*03Lej}DB_^!$PYo?bjO0Mn@N zuohY`b8}5)3WZ+&NS56@juXG8B1l3lY*`C!FD)L5ACY>?e{L+rx%JGHl^(fi&8A%& zA@=poJhUnkwL%;GwbXID!1?IvH5R$Xt3+Qan%RKR{6@a{_mKP_S;rV z=Kp>6k*cy)i3G+jazdk*phRQxAXawwSxuEh9V+i4s)I4cgU6~7TR|CavUjloV}{N5 zGmDnw%)pYrc0UsxlX}G!_nA4@UgZ?Nu3`wVD5?d4XK$b0=ic7V{*YROfcOC4Xng1% z-l|$BM$RIxVC`<*S*uZ?`4_e7!=jp;Hi>Uer44ro#11~sO{STgk|`RHGgy$m7fJuC zx0^nPZ<9KB+2uDP=us~>v#i?>ZN@uGgQQr*+Md1gdUi3)!8B)>+If97HF5~;sz{M; zS5Z`uIy49!&7y0ySGJ*vkBe8d&!4x?vSk^1xW7)>x_4;%+oq3ZBGQqm)=Hm;&yn?8 zbo8?0m#U5jV9V)%O+WSvg4$1&*LV#7qRRG^UM<2Xog{4)z5XgOjcK_2`-+HiKw_$GBqR_xX;2G6pg{FVZMB4W3 z@t;Yvu=xnx+!}e>qC!D4MlZqpT(4K}jHmg27H2~*Bilb#y{Ijb73yb?ve@{4XK~$BXS!i}{eU>|I8KgHr;( zB^03f8P`5Hs9Y^;aza@w=W4QGfg`|OjEW*Z(H|qwBbtybgOq zMu1cY_G)t5a?5yH|FXIryX1^QyE}WMy2=CoXNH(vQ&wR^mi7+^3DBm|vtU%vpJUl} z+zjsE)3e=IyWTYQ&rhnoHq$r6%QblltgL)ErKC)e8uOgtYl1TQeb=wQJClnH@>V}c z&h9MD@w|m!{&VamS($oshGOk3#;t-s#SQSaPHH$TJ;IerDZx0`8$WRhN%Tx*@z=pO zJFfc?WnI*MLe3c5mjF_DR3RnU53ah3yadDB{C|98$1uEI@beJW1%v@)L(fleL!KhM z(|sPd;0On2QIGpmn#%0V*flTmfqpIW%`gx;%*+Ga*bTwf5FA_6;qwHLx&bx8{GD9F z3Ca91j7)W-Yql<bmV@5&OI*KIjd-iJ2~qtc>W1 z1HqWbFfBrbNtos1EOm>DTnjdlL+I9An2Xz&vZz6x%Nw*Qo;R?Vq2mk3H`3T=f79je zi@ru{@os&jHaB?^x-Xs_ljm34wzLsuR`e6Vaow}GQdx?eFR|v1)*kV+_Cl8?dSO6a z2IbhI2}o{jXlUC0sfU=%^1CBur6$G(Gap2g_Pj*@+GD`A8l7x%OqaNvjdOjMl2onr z5&~mftFEi=8XEb=o9c281TU^Y4WWG^uo@cLM%pwSd;;kZ1Y5KiIp&PIipaa4ce5f! zxmD_tm;1zB3<(o%E#+XxUy`$3KibUp-0$@N)vlvo>AO@0m6EDAxYq0S)m>zj+zU2e z{)%c`ju5-9UAYI$_r2>EV1vyi!}Tq!>NGHo%q$kQGZ`ik}jL0bfv2y_fyxS>b;x5K?Wu^8)cV+E!TPRhiG( zq;NH~eMv$W3OA5Gy6a@=;z_=MOg*~pu3u@8bjp0)8-fBh|jn9TNBQzE4p2 zUqntW%m&VNh{Ph` zZ~8p`7KX!~K%YN#QPKTl=IHks^*8}@UqnB(FqKTkELl=n`imo@BlICz+pA6DDD%C9^AjYQEHg;G#dyiNpN#1YI!bV?!HFmXXP?ARxPEOjF4~8qetYqL zk#W--KXCEvW>ZYXXWn8Ar060(Fs~zQBmecUR4Bn&XMh>X!$2z+Ab~IqIdrh~t<~`% z@ijh8wz*H3n6f7#d-q6FjZ+Hf;fd?@5}P2qqQYOBaf$T~p`pBBhXpn2-wRZZA75SiOUeB^=pS?;A?&DZ}or$$r3CUj_Z+ql?^A1Que~H7zUI z;>#Z=mv!dajcwaM+uW$)OvHCIp8R@1=sdjL_vOIWQ>!nI!JCCshn*x+v4W>ky%Ac# z`-}CdIXA)tm>syYH0DJ!`M+Hyt7d%-$+@|eeIej@UJSf2x{?2jC?)&!b>%@j{>DKj zXIH!!x?C<|@m-hzGCTofoD@Wy-|=71KG2Cdto==}IC1^+wfYeKgpK+31f^)JNlh08 zNLjhJRsfJ{c_FTIuy1!+oT|!9Y(hi4$F-0uud~|Nf+9WJlQZq7N4;*dgNw?m(@Z$Q zBvQ_J=d+mY)4+5=auLC9x5?SGB$e~h%Tc?AR(Vo;Tid3`#&=2I@Dtxp%U417mg&8z(L z^zbQFe_mA2j;j*BaMEnttl&Dm8YG;WeJ@0{uU_VO7o%Qw)Y1Qi%vChsT&!^Y&s;y14!uKhydrXMTsP#N;yFQ5s)=H`(l3wnmgPL(jg^~dD1 zn#NXv649?TC)77nUdGK~{CQyBAOF=$4s%+hD5-K2OtC*3c~Mv}P~AkvTIx$ze~d1OZSFdd zeE939PXmN>Z8JarkCpW5j70)S(Tu6lG$-Xr)haxqyDejE&3>gQYY$r3MI`xsmtuqq zyis!x`>z7TKQ{)C<;&BT-NsvAkIM)xgYzmvv=3GJ+;lbA(s9aS#9X1@r6u;nW>0nh zm=bRPJO$pn>g(z8zpp4r+}%Q+3Qn zcgR_jX1iqU$sL>o)rrW=m>n_k(oT{+o}GSg6TShaZuUehE5O?cVu- ziOOBq<$?NTg#HcsILT@xKEou5X3AO8IyEdT8k;%A^xJn^v-wMfftUUG6qWj!rl)s~ zCwGN?nX8ESdFg>PN3wmEC?Y;M{db2zp5k?Qk7})_hqZG2X-M)O=_;9CtzBKB*q|B7 z5oPuAMpXi?DgAVCRkyA=HmW1WHYuPhb|&!7)@o(tzr7Q!dg4NhS!{cfeY;F@<4g$5 zIKn)5ca7=7CQ;oDzsZ()7zvcz7%`oxc5s^!J>5QW>AmvF%{5-DQo^H9UYw^$Vvf~PVW!S8qPZ+ zqRm;&x8__G@vpEmr&5j^#`|cle|uv_VvT(Cc+;2`fM?|WZDbF(?nuX&J2x+~NXLx!8-1!ws_Gz5wvmNoJszSWRF079F-#O(j$*DUOe^v(N&MUc#% zJ!Pt6_}QI(Wa{h{p{(j-(c_L{6uv@)}XfK`?&luA#V4$n5bbFGE-x5(*7=Y5(~!4w_e0vD3DnN zgEv`;J%{Url+-Be{mUcT*&GzaEf1VjXPZNghJdJE4JHR3mF4=V$ z?$xzb>A+R#&#hSgX{4#!1w^C0%yhIoSol#T)3&0G+;7l({;L!Fndc|F=SRItciQd1 z4ympB&ulx(rls9JesDXwFHeK^8KPiJQ8{CgmaYZ9-#g+}F?)ISPRi{%I^#mW`DpM| zE=~#_g^z1;9iCSVK9d?3XMJcrTb9A9(#)BhRxni>mo{`*;3DTDI&>ye@u{b6ce4q5 zPRNIQEz5AciwomE@fQ8cLVeFIKHhqNxbrWfmPXc3gsr8=#xKrofh18;S!Nm6#8@G^ z_mK=8%BJVd8)NHF z|0kM9JJWP)euXW7&Fb#%>+3g6*SNJpPm#mp-&c=v2ocGP(^fXYoTp!l+uMD>ShgHJ-^n5v_d_r*BVQ6S*D;X>-JYdyky6FWT z-qP1NpYf^RsT9bQOqOjk6Pz%QWkaG;3k zWKLIDwsK!~3mracDqEP+Rh|3W7#cS1hC!mgG2e!5Thw0f` z?zB%iSHW*m?aV1<#oep!ieHo1$h2WXxP98&Fca1=;7-k!JU|oXsEbZ=azRr8503;p z!gGl&{KdTKR%6!ZzcUwsUgo2BMf~Yb>JRT`CoZnpmn_dMMX;s@6ymN0S!`B`OgMQb z^g~w+=AkK!9q$WJ+VR_*z8}?Z7zvfgId&KK{aJkD8Mi1<0vWaDUCW^H0HlGs=3C|T zVM|2w-?VH^p&_+U>aP`!cAT6QyRI>EPK0F(G_U^8-opQ-O6LDl&NmXhrXK7p;T(@^ zU<9^KM`bKRz>b$Zv@!T$;$u9EKkYTRwVcofB?!iRe#}D`+HyZkO_WX$xD(71%m;Gq zA^M!nN{$xR&_%5Ly#uFunq)$g#K!VT2#%K3k(dcJprQ8?X+5eZv5%zMU~I-CExqBV z?&Z8#vr^ZIeTKJgUXWo??^W+rpS6pUVe9zK;N!VwrnR-rc|m6B)=l_A{^qiQL;km# zrdwv(Cb~aso^gM&N6zkvzdzi^Kq+=6uek>0KIs}ly2({a^WA(ze@)hnwIwwlW_L>y z_3SEO{-A^*cN?Mr^$V2@YDJ0S(z{}zi@Mf)#aWdv!)_-WKr?TBf*fLqt7ms>TqP@L zAki6`i*aJ!-qj_892$Es*ad;Q+R`@bJ+Um?>6@Z|?%u;>wGJ8-Vd@ic0w&eW6|O!RiIWQ;feQgYXPPH949k5{iGULDLl7K$6)Gd4)j(Sk>kJw>h=qjwV=e)X_jMC}caVG}%cXEI8mTQ@w^>l(UVaQb}jdO&PWsep)pu_-n!P zxqX(y(y)x&b(?^D0;r=fBMRXeu7Q;HzOpw)Br!8tA z2o|@bgDH%~i0uMjr5cQ53Hv;}w?AcrI7o`TZM zNZ1M(F1@<2b}`)3w7oTwC|E%bILLY6ZEnDP`OQsGl3L-Si9jNXSd^67Bn z9Z>hdFo+!C!QoNlCNI_|=4=lP1u~!Aw?N?%aPq-lL<4hIGRVAs#JI%7;IF5=Y&>Fg!l>oUxHX({ z$1@sJ$r3o2UAny&tD(E?u-23N102!9wkm9c?>chyTe;H}p*E=j8E0mPN!QEkIz<{y z!T1ZJ@vgz?s`C_GJ-v;RKdCWw%&j|uAzO6j-;C1YEREbU*y?4wqsr@MlnictB1%4r z>Tdo_FfH|L3;#FXW)*!jEaa#Dsd=qW6FPb!n-{WR;8qzP|K#mY6-%EAd$myeP{#dQ ztqz;1dlxqHuk*7{cN}jZ#(@(Q`AzOlEQTL+q zfGwwH#bT!A%iOCS=GgV=2g+#e*bPtewn4i*a#5O@`whCfKbU?_AH~0BSj24BIe5pD zrfH)!d{rTYX2!fL{_R8&e_|b#DQAP8&f@cMsUogO!R|_^v&vXAJ2-emHdCf0IV{2M zG{{Y~1cg>K5~GP*C$E3kX%agr67Fq7msgM$7anTI_>N`Hf(%a1GQlDaApI17Gv}Ap zzHqBh{-`44sPxiCCrhU9w3np~yRdY~FpcE-#-6ZFbYLLUrb7|dWIf8Cb;mpJ^3x8- z(af=)d7`7}iG^oeO$zeQBiXD$lV#YIXYtPM3+X1tAk~A#H-mLeJkCR2@h2{gdLNJy zIg#PkgCgjg{s&-S-P$aXT;3BffexqV?AgfZanI(J2I-GiPlou^g{If$NQ5m*sYvfMDLc6Y1(|M!5Z9)g ziaT`CylJA};nk9Yb_lm9VIVpx`Jnw4?pJF8Q(WyP@Ph8TVw4i7JxHlv;3hJ6?~=HXE#UZ0nW1oV_16n6qzxS z6#xp`^~GJCe-^L+I*SPG$%6LYrN3j-xLWEg?D)jszSgZ_1cPM1pmdro#rvnH_R+m) ztA_eVYfa1`OB|SgW-l^6y8^JC`Wqne=OesY^9E6!tX3^71{%CePPg z>HTqXf|1e#Oty3ho4tFoIT36*;nn^oZ7K7B;7~)jeYBu=PLs~W)a1KCQTE}u$f7_X zP~=SvmmmS#fA+9lu%(o72=@9aeECJi^p=LmA0_eDgH-X{%uG@1(gc6gu>2qQ^A{yn zE*JU5J?m@*jE&U@8M!UfW)=M3y1zgQODhm>LqcdlSIIggWX#CLFmJehQpV^Th_()%QS9$ z_;}L#Xn-dra|4Ba!1+UijTHXwLq4l)k!p)=-ZD|Wo*KqP>iXmT&wr=~tRWxX+CQPu zuiGl{t8{JFv^_>X!6}l^zNIU97OH1?s4768=M%HIlqi0h2VZO>qtwcgRozzp@_-XR z6`WyMWkOOs-EUvf=$-peS4G|5CvD2|5B1M~_^#i6@~FeV=A*vUgA~T52~)hmTMyiJ zDffp*O4?-eOuf~e)sWi{^%Y!_gWjFwzPYq%w5YQvg>g)(yQ{*IFS!AyLmnD0Klk-n zeWf?sr8YOXLYR-K6y4VJ>*4!I^M?4x>!Wgk4jc{Q6cGu78^dVoa@?t9rtjs;3W z=Q3Ym+;8av%%%RkR_ZR7%ARQmo2zM|_%+x{(vZvgQRD!mrhcBv88(%%yIpdRT-vd} zu%86m^ig6leg{&$xSy!!PIf%5yTDzLRu*5QvL+;3Epp~$&tUrM@Rr}q2Hi%Ej7KYK627>M(+R1`E!T6L`3 z-%j|x%{ttcgr}g8rdXi4igR6_rqD*L8b`U}6mN_B@EJ7Bf;-lsmY}ZLg3aZ(r>)6R zZ6qYQr2|d_Ou@@x`W7#~wVGKX3W5WUM6|RY%lH^nBOJ&N=us@Dfxk1jd$5PbrefY3 zkKO0zB^@50ZmExH14OjI>`7%ueD-;kT!Zc;2K?9JZb9CYneHI_rq~Wy&&YQ(CPic~ zJ#W9}sif>)N54IdS<0whM!GTCL{0L^n*%Pazq;+@Br~0MS|@iix3#l=l+MjB^U=LN ze4_sc(>{gJIDFTyju7?ZiABp#hhLjdnLVABDd~tq2X(wJ&S{*7-C3Fm-?oXvyIKSH zk-^^yKqA)gsy;G8Ck;k3NCK%#+wp24tv<*`u)SFXMiGK~22QoxaOZvx{$^I=j} zYo@sYg|mJZY_~^MI2)ZlyE|h%zi{&BG^tpH=$J=K|!}jT9|2XX#a5t zQpZ(3{B(e$Wf|w3fpMklD|Z!j%T&y&iP1WSV1;p;Q? z!)zD@kh^BnryWwY?Me~4b{)E>;a5HteRjWnSX3$Vr}{_C<>wTw4-Z*3E(&A`QzI{R z{k)B1GWh;HPec}MZZ(%Q9_VqR+XjKlB}%(^H?XYCk>vI`XSxX2cE_%|5Ae3uxc4)G zTwTNr5!*}KOT-~o#;2&l9TLAaNoC1&L##9O?HSO$ZiZAUy&?KNpHOfkp(+ZOmdx{e z2~z80nT^qN@QMg7CnepoCEDuM}7nghx_!TsV+9312 zF)7(Hce{TzNgm$j&|0Udq1+3u=(fdEt?eH87^hiL>o!rUuUl^sGca!6WrK~Hr#WXj zFr_~bGTEROs29;OeUGG1=V8wW&-V_|ZyGY4)@1|wEZU_6I}?}$W?cQ+9zWlNExkOB zd2=8m&lr+T0ge#>T=5`56OM*7>4geq)NaoLfB!@paaFxmrhFPQ_AxEK9qwh|?hJ-Y zUkHp%_#3i;D5@#)UTS4hR7HNuPCfLH3+5s8G8M<$QiP9@hr5Aeor!A+gw88ee1L1& zc6+r^%KR4(i$&<JA0(GbTpX>ueXd`rQM%TBJq zromUC4%fOg;nr$-G1W;+Gd(~Iq)~sVsQK$JqPwlXRb4C2E}(^atX&gITGU$z6bW!U77G5y6RM1iYfbq9hf-pwgiKB}@3>I|vX&^PVE=ts`|N87Q*_XDOp_cu{Jm;t*FlRGKa*_v z&Hb`>#~o9{?ZC8elh-Pi%VKGk60@XtW6|5z#P?3Gd9k15)f`2d2(Ou118$67j^w>` z%+NJdmimc#t{|Ut_YK>^ab^B@PyA-!q`Auj6P9kAu>Gcjf}&-9{xP;fcVt?(SF7sz z>qGcjHK~93N2_GX)eob6Greqz>6=-d0eg3OV(tABcQy)N?}(fkd3B8M+TTTuc1Nok zScF|ZbMb)oE%4$_56Hk=Yr6?GHxSVn^J-&qsX;zpRjgmZN=oM8V32-IN6a1C`)Ld_ zG0gP>Mp96+6e7Wb=%0PlL`o& z1dS~Kgup|=)@Y}II4Q|zq8X@>_cm0sdn*SzqDO@kRnFv!J)%-8lfic#4U|h6Pc2B;+iXpgOgR)Cnx;ELJa@|v`&aL_Loa9+-57)|8XDVQ0qjByd4RMpW zHq`8m)Rp@VTFJJaV>speCYlE0nq zG|AV_-yQWHKQx8GYZaIdCf_OPE%1>~YS zZV!8JZ@I#fs{2UcjlFEl)n^g{gZ#Qt>uyips*xOquZYIiPwzy!9*OSdmDn>JJ^1YV zB)ByMylg|F;wm;#a&ZTeY3gcHp~2L@pJw*K{c1zDodIT&>+&o-twuDmY%y|;$?^)t zTJGo}pwVgxSsdhTT5DCY%<&mGtHjFcr4$pU&E zUEQDARiw|EZBN{jWvKwPs8}G!yxke=&KL`16W7vU042DfPfnBWxW1Mn!q_N-&8qmz zMts+*45IgsyJrteHnacUo283CcMv7avO8LSWqmt@=Q(iSNXPi&+I6A?a*k0P)6%FP z;AZh{w*G3WRSSYAL6}4ha-sBQRvcGuC$vsXs%)iK(bJvA_kYnZdUAtT0y5N2z)X zFPt`~KoWAQJO$DXWyw{8To2*TTGHhh7h5TZ_~%1%=~%q|pya3z9#b`V!>8||R-V}0 zxZlRAb1j*0Mns?Z$B4eeNSBAm8hoPpcDbI8UWf7=ZW9U>9%i!&f2rl56^FNFIea~R zf);GXE`@KQPCmbK@K_RcY1RTuhu0s#lt4Xr`Bf%cuhs8s!WRW zO46zujEfQUj{#i6`%XlZLI(J=7rlZ(4)ip8(HMuRF_Ra*obOrlruy4M$iy$T+@C))f8 zFU<&7BaEUZuU~#2{^kxPn^;*PCDqZ*z-b1)8GbctEIpzd4X)QOVZnTasotrW-5opTAy0!t*Z&zd=aEIzdu zX?&OHG2rx|DW&!EosiZs5C$rwL_U&CAC#Z#6Bot?jbffR{lO%DMB-<3 znCbYmqGeLc8zkD0m)5jJ|nX^Y}-ypX|V&LSEDb>+=#MCKSd-5!h z4B@D&3UU*&Jd_f;^tes+%Q4@ZElBys8?keApRi;@vixIPSDy%KdzUI>B|K!cOZ1M+|MBgZ@_AOP8` zFIVpg6@;$_%}lLhm@g%5_GXT`>g>l}jhf@%uiGN#RY(dOL0~fMT4@%aBy0&i*+#56 zggDVnFv~CbVQx5(M%Td>Ao@x$pgIWI3|<5_(X$lPtR&5f=vI`|_dBHQl=lju-i?8y zO0#>jhJ{CX#o3(?yGxEIL$MPOgOd*KkZPR+8?$%uk&bOmzE>es4JyaK>s zD^%LC0jKjy+eXjpW9*KAR@!vRs*ARgM;}2DHrCbv1QNxfDwr_Sjh{X6ZQXC}gm7Rz zM`P}<7X_u@y2l_Sll8oPF?PrJ=ynCA?dlDMeZy?_bNM|5!<$Lj4+Ig)e0vO%ppY{$ zSZGf2Bc5-MR0-v~xfNjLWfnZ|`WF#N-DOP&xbSh^V}wkthu|M7j*_NZ%_v#Ss{Z${ z6(PrKa^n;!RawH5J0ki+F|5%wh?2W@YzR62GK5OzOwSf^idT8*C_RM-!w(~vSSF=pX%!+^sIjO(I*J?DbP4r6aN5AFJ z7+oT$ZFit`s0uD-^6oLYk~`C&PpLhsk&RyRSheWoD37*LW{clko$XOm{y+mP?VemL zvc%e&6XEMO`$CRdZ;^^6jS=>_Z^FD5b>vW5t>o$+!5)*B5N@Io~jBVIAf0j^2j7 zxz?-L2E+H^2u_9D>d`Oe>3Rgeik1^w60y9x%{u>Iy1IXS_kSgwZ6IOYIZgD6Ob=j9pn$CaulN^OXc-j&YoU%B>@2bhE9=qm^K@=#gHKWnGY zpHu#L#h6eq@cEzT)%Q|Oi94u^%e9kXh_gt*v zAJLh<`g9vM>Ruf$IMz41*+`4ZbGR$FigLM({wU|LM7PIVDXSVyW z4N{Dzt&;prJl{*Vz{t|?@n}0Jb#;u8(NCe|#B=weEu!yvXNw zx_qs|WM$v5QRm$GL`aOnG5zp&X#;>4Es~&Gzr|Rstv6#WzMw~C?(=*OS5B>smeH2> zTPaL1tKPeRbV5EU)_QUf&_A&kbc{?h+PxqF@um0#aRrT82GiMmD7&@p0cBdV58K>I zt_rS-M~<{z!qD4NyyGpz>QI^sUwD$iJh_={Thbv~mqheIm8$e}>pkf{!`11)SDtbj z3PC%)D;aPY8l;F~QU#c`H+(^HcTX(Zc-NFcX^_iK=s!-Xi#T-VA(EJA2sseSp=T)Asm+R{Ve zwv?DZ5B)-&PMNe~ofJkECHv&mTgmIqs)pY*vV5x@%<3tykGf2Fl3sq|tg@=ey(seK z&x-_h=lCuyXW|e^Y;GgUF_4S z>oZQd4PP&19IqU za%Y#cFo%!Tz{wYeBYx8qHr|4W-ztxl%OL>56&+oZZB4gJ^NOG6FLef8%STA0M8g1F zuJqXnM|tF&GuN!8INhQQ0$Q$Fn;&^^QQHlnGvEQv`Xxa~uwcTRFL|=y9q-hJlKOC| zG^s@&FC1prZ6XXy?LPGKNziD(h>8*iIb@l}7kJ*VBi4bdlAjUlBGj0q1nicMSI#!@ zN#pTax@%#koh(VkhOQjIrCF8%qTzt;6D*DqN%lGCV@ zk%eHbv~>f6hAF%BMOj$eqT?#l7^AUARz#$RJ#uwcfqCg|>?LTLoW9#nTUse3Zy{=l zSzt2b!{m$!K-W6>zVWGo%-8P6f5tOxv$>eM1E7cXc@%@*W2Pwva_T-2qT@_x#Uu57 zb%7^g0v=0Bkz<#-9WF)>q2HlBsIlI=E=-$}m66FI^(#M|vCZ$insBTZc5dE0y#ikE zbKpDPSiD5{G=g?&$?mQTqe!`rm32U0pDCHqZr5}gsrXZrO6ceR>h=_A4N6|p@cl)E zH1R)rJLQ`MzEF^Yj5L*u8Iy}mEYt@ty5#q9JD`(~WX4{-k7fwPjBe+|VUTIf6w**i zf549i-8WhzdHl0Ui2U{!BSqumQw!Mq$JIhrVw_T9af~XB6yKR!T0-IpR+#M=jY~aW z+%=?SQ7E&SZ4oIGxNB?^FLYxqCgRvp;fHqO7;*W`(Q6$by?Tn;O&!h|)H`1mB_WsP zi;j#R-&CHC7bn6u;v300gVL{s)=v@PmnAqh#Y0bWS{7ImL%@5;Ty;b8-9_n~Q18X< z!(`U5TsdS_&~_MbYQx&R$&hC~M@nYM67Q`GQohUq|d*8U1;l@4~#U zKFzwwc4$`C#00UiSJJgch$Vp5>!IVtdQ3O3>E?08srZ`&Yq?F7tA(2D<#0ZOQzW)R zZn6A)xB@Xp7CPJa+!7MEyqBrqbcuPV7n4kR{G4(Dg!~;glU~~#DuvGC!m+Y%5WevrhD!r z_G)F|MV`9=6t;`s!T@IYN7Yygj+dnTCP}N0rwlhZataDk=6~5)hRe}VITJhggP~FD zcYZ6cq3+7JrG9GBCBqJC9{A{or!~Yyj%u_(9T`%FHTyZz7RWQPEN8O4OQxX5SpN73 z`k^Ll$IDYO8Re-RDxenC{CyyD8VYr)gA+%nNqaWXdhXI51ltx4gyquNyUJ_2k*e*T zw?1&zHge|8j+|fc<#J+FRHJ+}>Ta*b`QY+d_g4~O*MqSHSIWY&2~Dg1XKh;y0YDRu z!>e~pvzz6Jtb^*z1|d4I3&vC834vf(wb6Aa;P8!QV{1r0kLk!Fq%is#oK#DHT8B|<0v93O+FSA5FwP%rT5;OfboNwyOGVwVQR#UnMMLG?wAL-(`AH+Q zD9s70n$w(6ia}~-n^ATCI~NMU2;rRM4nK`F?|AD?c@?8A{dwx$J=j z>kL-X&;uL)Uy0(w`d!yVCBzw`GBf^m2K>Ze(cCcyYKp>T8=|i8_z~C>T0;>c)Ab!d zdp=Q|83^%Z!kl$VWUJS5SH0BWu#`?f5ax#L3}4es+5%Dz>44a?wE1(7s&t1ZozD;hmT<$=XaGWg~l=(7Sy^N z4L=Qf)zW=}QaL1x3XKa_Jy?I6Jpfzt_7{%5I1)bIhw%Tq-Fo%+&eY#dn^Zjg%4QuD z+EKS%drCZJrcn5d!E14RA#dv)mR|=J1tMQV=c~mSC8CKS|DWENq9Wt-f=f`>`mFdu z_>9EDu(OA@=+&T%MR;v(V;hd*=AGC%&bdA)r0wez-LS@)g3NJ;4(SS9^6jC-9{{S$N`Kj0r6Kfk&2 zcmwa;g@ANYxfC<#Kd-*U*z3~|P$2(^QUK?selay{$sU#52>mO}dv zd*iP$%b1-@=kYqxMU8n$nS>`RSY1lRInGgXcX1XwtRDCSXrQ>dBZi0J%t%zOw;!)M zKz2QpeZZAe#uwIontIoPm{lK}q`mvYhtuw8ppR?-O&&;FV$xIqsR{ApHiZS|Un!fj z9?H@wB)uqb>;zY$S3uMr`JieEN%xb2bRz8$zJ-Sd^$f!0-0q%p%LtLA%c-WGV~T-M z<^&bCab$A^?HCXa`aW?8uj)^gjG?CsmNs~&T4%iG*;6N~w{o3v_|1}w3yadrl} zKYYZ}pZ%PsRQ0#rMe#fzFRCdCFU`|vSkDaJcfO>^>(laMG}eiv276bRV`bAke*(xp zxX@G$eem_027H6kQ0c-uJSG)>Jwq`&uEpaf%_YwY`T;a+a7zQ&Q5Ty3;C$|J6`3)_ z<1N4STD@W{?h)_kWS(4Fclj-Z>~*|>Vw!&eh-*)IxWy;C$^fF_8}dW+(oGv0aHNgR z1IZ9;3v+dr(7wfyobVqGbt@iLfk%Jxu8-jJO}P~)jJZ|_8y`Q+ zM@r@g@eEo26!n8{fR?~*oql;pZ^uHd`Lg2Ttl*OKL+Qfj2Mo+nn??#eJ?-}5)4a2Y z1VNj=Yhc&lRcLp0-T2*@@1JGtn*4{|@BiRPA0e^sD?7Ih3)*4^9_b_~thbQULR0Rb z20Dh2JLyOhP@Pw(&{@| zB${jAwB?@2tg3xJ3L{&!kAL9ebFU9VeDM3;D_-TutIP>bua7he$ta9q+OX=vHMyXR z5nF-%c<9gaXk*VYvB+V+w>}V^XL}Dvb3BNmcS}Vgl>lYD@C66y@7=@tYaNJhjV z{sMIybv#FYWKafVjhDLN$6W6jB6GM~=vBhLN{~eYJir1a*|5c}704U0CeVZRyF7%Y z+~wyxu8|>6N$*)CR*7h;Yi%UD*b}ngV zQ(JHQV6+i0+jTcvu*m_+sWlp1pOJqykhk3m@xFLA1y&_afC7D|XT91rJ#e3$0o$L7 zyXfyhepcqv{ey$-1^KIqOXNqe`vaSYUFy=zDCtaRhx-Z)UN5Qd5vb~wLdsT7kCg9m zd0*~_q-@YjE!JG6%ou$Y(B!9GvQ!8+)8aF(_d)7?f~n(qF<1)8)Ai^5xYxBp?zvAj zlR{f;0l>=t%de3!r=DWXG=8lMJvgGjy$d4O^)=~vm~&=YL)Gp^n9oM4=RzG|nzR__ zVb=-+dAEJK$IbB0VUBC8#Umnd%@?Ku?+V+^9R>mjk)2L1MbRko=J9u6?BdfSy<)8x&Oa*iQM*J);6WCNf5FgEPF6l;_qq<~MBauyHRY`exz3j( zLBAhZvb~+nqL?%Ov;DKs8thFi$IvNE-#4fQh43-!-8Xya>G+o@eK&uD@TJ)`ZXWuySjWjuJw+l0|6fW*h&6kbEZBMPt1kUBns7$DL2*#A#M6 zK&;YQ=(HPmY53RO%)!PT%5h0;sWV`*xzt#k1Q#Ld=T`Z<)%Ev{GJbpfHPQKs!}%l0 zTz(q~&%8Cy%292IRi+s)g_vKqLgM1*in8z56Q0u;^AB7MvkaT()|anK-rw@02n6>C z8&@8dTK(bcn1dXg8pL0r(Y8{Z0HkI==s}Q*Q;-RMtLmfwG>#6*_8=|xn9Hl(?e~zZ z-kIHXqG^}=+2_^L$6X!KR|ZM+6<3X_w!&E^TH3KpCf;ew5@arG4@^|aMl9|$FIU!& zppP;%XMAz>xamCVoA%2#*Oj>DuHSu8I(|ZlW>(0KK;Ok$g=(HXJarQ7l*3A))==&M zLAy5~-+8Gz)bP862nNCf@7kn8O&u*m<#j`DRL%H)+Ki!3B?J;bW7#l4ilU@J;l{kQ z5j%1madB%FyEk9$VyCFG3vSLhOR6Bhs&JZODDbuFvI*N@E=XHTm=VIzBf_iXVVx7B z;veixQY@d+c!?#_Q5h_2XmcJHZ#BJTO$Rj`d~-x_bF>=S)? zY_-xsqq^VDtOT6+P^612pT+5+z_6Xf_i z25kql3ZrMqpMSnqtTdiZc|n(fbHOPF2H7uZ)N0Nd=5D_&E1GGpf%Ew_K+Znd!-RYN zztC@pUvMKwA(ETq1n+&l(=}@;=Gcd^jsmJzF&&$!9>S4fhH~qoBBfCy-{QHCSotGF zZai0ltlByd*A~ri_1(0}0Kjv)m<|r_Y+9^Xf#nxrAgo~cEvymC#pim7a%uH#*E-Hp z|Iji`jRt!IkB-<9gU1vc+H;|oo^ADMF&IDT!>bQ1M1mHHaRHoZl~nSfb}p494Hzmj95j zJGX7?vp>4ETlFo=M$wKZgd8$DsjN6`TrmXB+AA1qnBh<+vwhP6)vHQQr=!Qb4Dmdx*5e!jI?hoD+dyCyZQr9viDH*U$CD-4 zs9r7)+!GZjB@x_;FipKYbF4gFEZpA<(-Z+fej{JtTEmEXJx|;cI<+0^1f$Yo6V#go zZH)qS?au6;JC$=BR;LZ)b0CP;OStF1x-5F_D_s`kxo^li%vsu$XNJu;4_E!k`?weq zcUb5YBikdRqV{qdGx*~4(3#n^A)?#kRXMDDx!?`f7^ivz-1-aXA^0s>PDMpd{$5@) zShLX?Ht^-~{1{8#s9i!p^PB#hGYFWRCN;{0{+&A{2^C8d(x2nF%j3}Y9%XRP9^eqq zCYrjFLIXM)t@e|d>uLX@uVrxCa8r?)tIg~)(_W+GC1jH(oS5T!l7y^Z@U5`n@QNkb zSLmS~cxm09{?IiEveP=RD*-@H%~afeFmJ;(?b`^b9*q8I;jYKY!-{E<2GVmSHEL1? z$GTMFCnX-jcH^!eBCFfz9cFGksM@poSAZlL^2zjLY@caa$gRS zF5MOnZI)AJtqgVT5DKc5Si1oF^w+hm=SZUdSFiTY8>Xae!zJ0%520jr41>&jn)vDg zvbkQ}=-k+KhN5d4%hb7um^~7uvxp*z(bKpNA#a10!(K1URpIwru_+2$eBjktvY4j8 zjn{Om>enm0kSjEY=u*{b!a^YveBB93w&=(5m6H5Fe~ZlOIc3wY@rL@ym%FB~!&n+2 zHP8WOa0#!ebsFW{w?guV?Me^sR+gGDN z2Ll`uqNGqV5-4okORPI^*7#)uVRVmcEp5rq1s<*BDPIe0I0IEj!@5}biT9J*4`%%$ z@qlr(a7&bzfe&|Z>#|vz_m!Sg<>|=3;!ewN$(DAl{{6$rc-rtAgN;LJ)5aoI2#s;D znRgs3H|`!+8i-R>E9%l8|C#^I&|<1Hn!R%9_SN)=oAhasQstSj zCO=4F@q2^jVqrm9agh_>hPnomn_g?&wcr;a8`jaK?+bXnThAe|Mg@(Neb~E0-8;9E zna1Zj9r7Elq;k9^z~}EfWdgp z@8vf!It28~8_y9#jL)(j;}`v!%i4Cv4fXPw{~FqzwOF4syPqObdbmh0;Oa=nsirVR(S9z5n_Tear$N0}6{qozEDn7)Z;w_+ z4iAhOpp8DQf$?Yte-EjT_Wh%wOH!wRyc@K>p;efw_`gdb{(qFh*8)$5_i2LQff6}e zz@PEsCO>zpf$*g6hzEin{010K8q|Jxv73lbDDlDQ_?oHA?3n+HqUINJmrC7qQ%n;K zNP}0-b|uy?&{K6T5)rWh@enj^+xZ zAp;jfo9oXkAWfRHTAzfhKDBup(;5jM?x!Emk!}|Fu^V0X8wXBshzsLYRW{j`L1^hM zESyWTCRqtWSb&-9OB*I^Uer#f^0?d6V+G*8Qk^Q*Zfn*NdNWRcNJPY++e+zzOb_TB zs7$Dm4r%>`2WWiceGc@G?9^L9F_xl8$JeUS zzG#frYsfzIs=u^q(2$p^SKMl}`5*%`(Cv6|5K?HCC8ht>qd`3eh_1HF5IrlV3~z3D zT^(O-Yox=W?Gg*4GZE;1Nql>YhV7~)>ASnByt#SaV_(r`mPR8c2OP^vsuQjF{i|Q% z8Z&Gq(!Q_0f#sv$o9agy8>RV~d5{PX2M8-4xLy7MZp~7EUqC4?leUi1fjk!zq7y~a z(8K%m-_}9E5LC&yMiZxq+maQ`8l0&(iAy||=Nr-V^Hu-2c#Mi?^n0xPE046vq^46F zQ9!NDcDVsSpsW(XUQVN@gcsl_pyNtXTvL`-_)7NM#Y5Tcr{b1x_kTWe^G**@34*-- zBhA}N;Za5v*m!#30=HE)DztE<^l_BITS#7KiK~gK`MnW0(R#1#_ZrUtyV4VI3 zr$H@jqpjLLu2VQ;Kov86QY5W3(VoX z{Sz*9!iRc#3)G3|)Qy_$s~T$ZQe{zL#K7+AGfF^jcGm1u5_;%d!CheA(%ZYb_3r-c zJ7133^Y44?*AHiI0=oaaB*0aerfclfHfXaQ+IK&n)Q^RmXO#3cq|;X7Zdw?qIi;|e zWvGCJS!4YYK0lwR73Lx%?AU6yKgPr$Ir+IfX)?HlMNrraJ_@ae&87qcOJNvm8|Ln3 z+lLJ~#GEP~F{*&lL7hZYypFnG5p-77zG~xn;;0IctflLCgaCsN00XlC?dTyxzD9Eom z{QY46ku_-cd;K1pVF?sGlKRavKx`;8by}ZZ(OmdRxv8IxVoC;SMzN2VXS?&psplcr ztDq7CKRx?41qJunj-SG+PpbExm|ElV?v=~2X^NPmLy{60L?aTp6DnZ}5VRA-mxDT?!l~_0K zIf_Fx$Zmpj$sLTXWXc3v;P?x>d{|+NCJd;`ODUZ5Nl+wy{s(Cb)BZat^1c7@qH@HD zGu6^l3FQfQ2!QBxo08V1O-{_lOz=J_Ve-EDkw}C~)KUv}z&HKtOJt#r2VdDJTBMVg zhI3_XNAK2?{nYvvfAaDeiPa1`ne%Z*?n!gMoW{`9lu_QCAC({s#%A@>%zihQ?pQ^e zptBTnsAM*+S{Ny$?o68KCD3N-O}u&y5CYh4jmxH}FSD?oZAFm<=buFUkn@2Zv5^3_ zrhn102-XZ0h<-*Fh7@$jX_Bo4;irkk1mjx~ukQQ9k|P=qD~SZA7qhkbKKO=X{kbjU zrn}OaJb+vu;&tj~xFuutnPd7-lW&>Eg>Ka5v574Br)UP;+e1OUg69+wh2AN&_fn)L zykn8Ye}<6QaJ=m-CKn)>O!!t)+UoR{Epc0yqU5tMXABxMD?U|UtrCXIfE!TLC5VND z`=Pc|dlo)B9*?`Q^zuf6SP2IC;K$TP1-;{52nOV+$2h$zPm>DET$D? zHbxZC3&DxZ99xYA_QypAt-tO!(uLPG$k^L=T>Q>@c->Sl0a;qqA4r_=d^ur1KEt@I z!Kf|T6Eq>2cS3L2he2Fjmx`&Yb4y708KHd$Q#E9L!bPg*gx>qT^}1(y6*w){46%+U zsemqsDyzh+n-#YKr4{L3#4DK*yXn#ytWKyq3`&6><68!n-yQ$Q`Nol<7ysiay2%}X zddz9YGJ4U2S+YSFlTITZT{B{GkY5H-W*dsQUFV#O!%qv93AozLXyHzC91UJ*lW zy>4kMhLn$Kj@HIWi7jtD#eA@&VR9o;nV%JnCkAa%zg`_)TrUbzR{6zwTy3!ixOZSk zJ1$cOF;br~;diP;4AQy|(mf8Msgbj5UPIS?^yIz0M^=pnr3GLo?5RJ!4Q8RP6U49< z7W$qS+Ii_!8AcJdhZ@bcIi-bZz1Cf3_Gf8IKJLf(s&)~PY2fdDV{A$?w1dm%jaV0f zGVyxb6_q7bJ4s{WBwHbevMh{Uw9vBqIhn-qu)!R|c<0g5L~C`Lj*v_(?a%FG-R)O? zoD)3N$MLz&sFP4|)5Y*zJ<_o`ORU6DTiTYSxZ`HMfQT0@wxvqtR~6+gz+Uq3v%sW8*mHiFi*jmOFFP7@bMYLdIYAeq^H!jL z0t1@F$k%&HEi&Q*C@jvL%Hl3zHj^F^+Edr7q&&YSpr92H)UuRG4fs%P(RyX4}x^>_;&C>iT76+oPK|2a-?A{l5C0h#eu*MppuvO=>y=cAFaZ zJpyJ9^XIXq&@l*+e{c%!T&J%Ru%niUTioujEzF-F`}3RWu-UP%TZXdkgUP6KLd0+) zj2ke8RQ@CDP?`1^Hx_T~ML}myuS%p7k65Bu!3!z<965&@6vWfw@Yk z=5#EYDb@j!=wH>}-1w0x5J1RIq{QIGL)-rJ(a zCZc0pmqkzMQDm3WjFaY7W(k%Ht=@F4=-4d$ams3jY!S?LSzA>4t<4KAyZo}$=EGOq zuC1j0F|ta_sg_n6@FV3~`_vybbi2Q3B;%eW=K15dhzp%Eb> zEy1T3o;NbhD=Fh2&NwC$_X68(c?jHkX)9Z;s=2krD!p|yr-VS6xTOgwc_lFS`s!@J zexA6BQmb8$f4A;YjMl|s@`;RX^VAosDoDBcQ(1ygX}4t={Z=L~N%IHK?_%V+v!ICP zb`|Gww|%D>iv4%BpXa&dinYAIxgBm?vUq1Z(|H|lVmgMJ=N<>A7GlE^`uQQrM{}TO9eb356ffoE z@(P&~p+k4t0n%XzO6|$%G|Fd}#_V3%s;RN`I#)#yafPzs(1jnyTjwyq0!#|3a(QiT z*)q?JYp6z(&d{LZq=nmVTb) zC0o_nXulo$H(Mre8ck`>bJetm!d`&h$&Bs6{YGkGtj0j~%9Y!%H<%}AyK+u_SN&K| zPGIQs>hhM&^j3})0z%-JUvWjb%Zs?HrP?Q}fKlwN*6MbPBUYvHsmq3zph9JAd+`SZ z>YFYgf`yvR&!+rWoqv3N{cRu=WU~e#&a)0x`OYiQKkG**_Dk5B?s2R4#XG0(*@EM4 zxt0S>v>LAB{A-a52Y(*eM-ym~zfoeWd+s0O$^Z5l$)ta_u-7vPnrXA9$b;8^cRObD zcT9=+aSHEQHusDVD-i2R#PRAtehu}q(TQ5Dsc!$V4Q*QM7vrke;&-EJCvBT6dxU==K@(lN@`opTKn>Y>EF+BiHM_m5q{JUU zHD3qdm%R!-H0d2GLEa(DCTyXmQE%HXF!{m^+IsqjLPgW1wB#CY*d+dmfiHl&orDQL zIqTbNIB~>!mQL8h;pOcKcXfI99Oj@R{v-*w$P{@g{SS^$v{h@8m(LZGCyvi+$iLMW zHH``dLG$5u6tTACLIL?p9K62ma$~bzgSK`K?p@px_7RgPbJoNo?)5P#xv!0$oPgu- z-Q_Y{A+iuOae^)~Xh^Vut9ZzyUgU@G&sULda}$ar-fqm|{)@||?JeOsj2{;$qgJnA zMWQJ-U0Y|uoafb(zH)$J=BldiG5uwb)MX;U8h01_?JvtrE{+&l+gTC;e$g{Gd$B8Ch}7l1xN=g+XWupj(>#tvwtXG5vpjd#j|S3pZz#PvI+ZZ^+I^uuuXg+0kqy?m=Kb00j* z_t*B-Hd*nn&B9;J^FEU?(#P>}yoP2F-}}+1kGI-xT;)lsxVN<(zQ~DQFDM2831g-> z%*7N4{Uf)SBgH|&?2bKnlBgm%NM?N1o@Alc&irkC;UIR%LeZ|KqN!j9{#{g(=qtx% z&Tk~QXgrJ(e3;jxx19(io6U zWg}SSLfeTBb)lI~%jtH=1#fBVoJTTh_Y|=oUmYJ}{7_U+e?wFDh_1c$msp~Bc7xig zebsrTjl4wF+fyopisu04bo$HzV&2TTq+0KKUWXxaPn4*36Y@D%+i-?AuQG*SJ*n@D zLmhnIm@wcWpF{#wUKd#af0oRUYeu3kBStwpD_F!FcNjL4)w94=4SNa7wRV=Fz}@CL zb8YOfm?i)9FMbT4du;WyF2&^+Szx9M&HFE+MIPfJy{`cnZ`XzZl5R>kL~7K!NXAq62Gn5Nk`Ka56vDylr zLp-f=t*bPHuZ-izom)OCxXt8zjyuyv zr)vV=v1G}o_i_f5Z_*yj60d%F-+(SZ8$U7Ds0|SBf6Y%Z4IixXUP|6!E#3H87;naz z&0@r*w)J3?1b;-LI22j`_(VmpKSJ3BRkuLc&NEPy2RXB>WbaaS2iv%TmWk3ntC-OV z6VeB}C1i5cpG6gE4-2W3EtFAs zmTIFWQFOUKHwN$=ICu`9>8hJraRLg9^e!SAo9fjrM5^XPEkhn|!5jwvb#fsUB;^$x zV_4i}QNMHmYKZ0siRMIC+u7k(>cZEiB(~WC?lq6nI(p7OTsn@nHu9@6ln@#&)pD8L z^q#qkVJ(76$~VAciPD7M6JXmB0g)figt?F-VK{R&5+6KX%n04fTDx@m=&SP?Iy-4_ zaviAQT~Pp|8M2h?q$lDTA#2toTR4{H?PV)Ei1A>EGJHo~(QKjBnAfZv8y}C1n#nhp);m^T#GHH37mPkeh?j4`+1FF}Sqykw+ck z+(@@yQ*r3$p9MP54$co5x~0_z3^I*%xq4VGReW;|&5_9jRv;5z)k|2^k23uU*={a{ zb91?mn5%#BBD$Z{PS)T(B;?|zLVhPpF12|H&sFbtaZsFI((T>+RlQJ`J-hvM&dSF_ z4o^af#E$L3eb})Zj1p%RXOl+B`WI?D76~A$r1u@-bQ?JzW=(iqo2D_xkF_qO7XXM;rrQ_# zq4F%h@0X<|XBIWo4(ET;CV?A&RKunx7Wg^Z1H?NVo+p#gykbBMFFIiS+I^T>|8rU& zN}r_nd60{e%h&fhjL=I|$%YZ=1P%ab-Iu4phVLVHSE36$nDe_AzyNA&c4FU)VS_>b z1R5v7G)kJUdVwj++ik!%ZF?WFA^FK*4u&J6V1k{6a7>$fa(pOaY&G*ZK}f556sJYo zSc8j8%gtC!?Q-er5-*qUVMPI+dNP4COGG`wcX>h7VMG)vz8-np?1gOz9djtEGFNTV zy@JFguVfQOrqB3Nn22HW;v3CBI3IQIAl4)xp|0xRm{$V;#;0AMR{-@KgueMx)t(oR zakE)I;tu|}bk6;;vG8$yOqH!=^Gaey%>~YYHGI{#Y&GN({!^u;%kv`B0DLIC(@Qjl zKRu(Qc+XvJK~f*98o+a~-6*kSR|qL;)zDmYm~o!@1e6_I&7;QMNE5~ZowsA7JuA5X&^QT-tKd|YYBFx}}vytWXoNk=RJ~C~#xJnn)sKd~?B6zv`BZh`U+4KDnI*ex=NzRLsKH^e|q4l3y&GGCU$c z_FPiMXfNXZk@$`xfZ&rObg?UI$F%1lFG1CDVDI%Smftozsa*grCsLL69GObHIdK;E^$c*s4g> z2`gZJ*tD^~E zu8Pw^U$aehWUC*=Cif{N=t1TI!i9^rhO{=gTkiM^W(wa!ThG;_aSiTxULMtid3cc5 zM;C6nR)(h~C$o=>pA1mbX*53DX@xa_a9C32a6*dgh|?#~Fe4!@-?j8@s!jJRRiG|M zUCbt;tt`nau7i}>DWuX`DM2U z2Z)B%>jQf9#f+1<(c_!Ms*;KJ2GkD9K#dD74JX^zE*B8=S z?*HH@Ib12tmgLPkjk?(~bAssD8D7mR`PD5}I8vZ5^)yv< zR0J%-z4LH0nHi=)+lkT-=p$c=DCv~kYM>t`d)!O)Z7>2m`<05QSpRYnzeDM`b!j7L z!&n-$n!n!H>#0?|M|kyYe^wkn$+Yd$u5EL2g2Gw0{uw9#pwnAVfDD^dw2_Uzl4|TI zE0^g6RV44uV`P*uHoU4CM%m`^VYBvrR3XvrJwb1gALjxu z5$&fx-X@ZCJ4}P?C@W{O@VgoFFbecj)#0V3c~K{g>VkaXQ7q=>$8I2V6SpsOl+d6z zArSvO8Ugz{YqeZ-EcRze59kVO_Q->>R%DIi3+Ik#$zIwc6B=qUt;kXRzK?-w7?M6d z3;}#pujoHojFv;{3JzC}R!G(MNq2<&&LtNz5@~t9xDPqL|Nlw}_c2iZvN>dpO09Nt zVK~~?0o?uOdvxBJeMxp$TXRJ+rLTXY4^8q?<~mV3^{AXPrq?3JrcZIiy>75W50>JDl0=aIp_H)F zdaq|aI7R-dzcXk%;uD9|Rs{ud7r)lVe1b2=h_|D*h~+9;2>9$Xdd2qkwR9*9e({(m z5R#7cH`P;9A;fVcQm{I#Hf;P;frTDs8d!xJV>XnSXb+|VCYZ8ZL$1}IM@*UyD5+u{ z<8iio#|U0o4DpqFwin-M?>wwqlt{+*F3vc284qYduPBwSqGsY` zM|Y3>vy1ol@SDf!rqq2qfSNSkZ{-aTX|?HZTYDflft5k7a{w4fppygK_-V~h%918! z@6mR0sS52{+&2RP8Jd$9wCM*Mwa0{q+fP*#n?4Y{>DmGX$YgHLkBa%f=A=PHYcrXRRhCeKZaZ)MT_g_ft@U8+-_9-&C9cpLUkBaVtVaXMxmI~84( z9D`NF7b#$O>x0v1)>(S%u~RU3QYFm&Hp5oEiaAR;lglYwNW+<%&~D_bqj7tD?|?ve zhJGMkhOsL|^83iK{gb^I18~Jwd0vm!xvHLO-x!fuiy!NO9ccC5?VCqJjURbZ&d4fh zqOvE~{|GD1BS;+bM2hpyyuqb{znx=SA>5`s*u7N{&aL*{R;}G%qQI1vWSc=@8Zgv& z6(KNK%UR9s3dRm|{qQvB0T#lPZvpXZ`{}I^yD#{sKVJ3zJqnLe&sC~LCv#CiU}5?b z)b*R`d|d^>RDRtRLi@s15Y=qvqs4A7`iMlUpf}Aoe~H3V2kQbub~L*-fK0fk@7OV= zp^5=1?xrMxJ_3HQSzV)c1A%@TV56t;-WB9_*yL|fz|OH|-f;cAPPI8Bwn{P4F#v4= z)wyNQpOn?x4mo0jo4$9R*9|m_LxTFE5&qXGY?4jAN;mK*5}N{7%JGoH&rK^NYvXM= z%m znUOiO>+PZ^gLLlAPvq~vL_xZ#FxWl6JXd%6!*T-UV4K=lt)KnTD9c4^D4tkA_}whyE=J4;o{%el!pq0L!LD@>GKjUF=eU;!R|89C?G4uUlGss=P?d zJ4fvdaHLA_$|y} z`{JQuf5M=ve~Ch0rs(FuLVk^Xlr6qjP3!$pkEfE1t;jk z{aC@jMgcoHlWp68P%ozfL9d;w^Bahi&c3=SX|l%s?jPd8`yS_$7&m<3GUxNq>x97R zZ&7%Nh{pT-0@Y0PmneLFHpQ*^mjw!s%I2?8kd}BEo?&G7u8whvRHTviRsXdd0e4nso7t;=s% zrYt@@0%symVQPnePIV!NtjUA&Xsph4V|95|l`|6{sjeWO|FIYYH?hk;MGd@Z#i;%R zTM-BP$>3+$AtiW68_7jc$DD5s6%~3^fwu6GWPSJIzy}A%uok&1;0C|>poYFP!hg>~_dE!-2aa<-ft} zWq#|DvLA}(A-SM zyEZQU^IZ1ZT&?;m=xn-%E=*ShszRe#{PxbmP+duef#>J^_taEPjZZTw67Hp@)MaKC z`3?Hi7=}Yy2Hn_%e{c*bxUbbx?#94+M2z9D1N97D{9}pT-;y)WsiO>c5p0LoW6T#H z1CGY(e4&$hg|!ZpSkp`O+5w1Ys@4!K07-omc&5o!6&32G{QF!;iP>ynyXlAG>@kzQ zd1d}bAOC=$QFvbiQE$GyGjs`caPm=UPeyZ1WHbsM_4ZQi3xT&&^X;_paR#8K9X z3thkeDm~O$LTCmVw8+@ebsV&p5Oc>%axC|N8s3MjQf~uPkaP75?(B5R(c=n4yRj-1 zXoCKHjOdEI>=;>Q{Hh@Q*3l3-z!_B_A#Dx{Mle9Fw_qf{Fz5U9wKOWJUBO2Nb|NAL zS6ZbCLh6!8zV=r&WnPW`RROYZTJXiFiXcT0aIAkUVw?FKvqcvlU;2A>_KQ45%wGOZSqU|6+!lsdj$xhQ zegTJwhH5bSWW`61lXEp{d&$wuI;0+$mJ^fwjv2dqwe-XD;#FBO=Ir1$8Tt% zOO;5Ww=rh(CST*^dPKXODEiQ&qOv@tbxv^t!Pn*Fmm>q}SsHW3ZIv$DgX%KA=2gA) z_vwPz^oK8CPGAfbnhJrO2gwFDm1nO=||m-lTZb-Fy;vmH8Do zNlSUJ>j-y0%2;&IC!OJI^^%eG5;%7DliUY{KCiv|j_xzl3>zhjnOdzI|#nl0X%l)o3pzyBjp zamg_B!cI5 zlXI(4b&abCrAO9tl%mn>Z}0e(q}ob0|68*OYqGK4`43LG3Zs{0=o2jicylQ?%H`^IBc3ev1PX?9;&j7r1okVT1hbZ=6V<68}Y*(U87k$ z*5JXv1*T9YbI%g3tQv>Tj*|H+z?*7(Tx{02p?#aPelJFGa=Y7MLwqTpZt^^D1H+S( zC1hI-x~$|6A4ujx1hI8{5%jsa= z6Z)lLrN=gtin@o>u4_LS+3qb_cjD{;dDR)&4odd$+a8HmRCng+dfSR1iEGEVj7faL1L}jY>G51{0GdV4-!hQ=&R_Zv3D}9 z=rZG0Hug-5=XcP?g{lh#{3FOTwWGkUzM#L6~U--uG>(Kjj7YN2}kaiHe; zs@5>@JRLPRc`sYLv<|?X>%QLiGK+Udvc=wU_S{Tv8?{W0O1W&7RPtm6zO&O#YD>&l z;gj#y@W6RREG@vn6pc?xFLDnY6rx}LE=+c++~OR~n&Vd>m#u z?K|k=@S$)}H7QFQx${h1jHg5dRJX39{o5A;81{eTv31M=9C4} z+X*jx+$oe>Ol9TsB@I6?*7P7MKD{bQG^)F09^AA33e|VWI<)~? z+u@vVLj$-M z5N?Jd);6~8WDWw6(~S@JpG8wj%~sUss|7mQHG$TeMI)l1{BiNb8&Z)zQFI4#-(ztS z;64SZ8vhnH{jc>wX~Xw6#1`dOMc@Az3E(mBz7en2?^}bbF}uB9Qrqn@Q-_O3?w0{c z_AH@G?lm7969}PmD9-QG{>duzT5!efwxqZ(gX?dI$Hd~AB@#b8iVQWJCM2Mn-dApa zJj@IU0B@{aVhU^WqRoEF4=fA3J6Bw>2@S{*rVVXj;qf!~RVizn@KA+Y3RLKhQEM3c z|Kg|`8*ycC5${n~&|?>|^4sxK$=E)`xNPE^P%0xblXk1)Eh&9!{y3(r%~qDYv(9SX z_*_zv_YM&b{gzd|g3_37!a=uY7>DSk(&3(I|~@cPPmUidx*CUrtA1uDWWN+ZR!2)$lwg;`qXP zC7bVCEc)@JB5~^yX_(qYobEWh-Eo!1J=LPVCfpD17fc<^8?F@|F17IS4gugW7vT<< zL1$!MKW6joz8Fr3+O>&0SJ=JVFK{4{MQXlafiNDL7NH!p}w;^VMsp z>7&P$lw4Y4@B~Xs!EYBBUnMJsF0}`X=Pv$96~n=qV=6U%MI46870TKa#e5v@&|?wy z_c&H(lLo!Ym~<`rlA>&J>ii(+Kxk#*$`HX;`X|HWR^C<;ynFFc;_Z06t(d_6p^WwGRgOu$R?&vnJ8!yHo3^@g1AQ8H+tQlyYFntxJ=DNZhElNYL%qi}iu#l*4-21K#t1 z+?yZLthcqIB-a3w{FCT}lc@6_yHfizAwgptQe&@%HADrc_VYCwXJ5etd(|D9?Lk|H z!2iSBdqy?cZd=1BASi+;(z`V2(rZ*6x}l165a|RGdT602D!n6JkluSq=qSCn&;vv| z1QG=4?fG)fclJ5^jPt#FKl>f;`~6^y43d$V`yT6F*Id`N)|>%3$K>*XH6bRdJyg=7 zLZWV88c;8)QErREyW-okK;h<=BIANYVEsubYcHcWZHr4W@BA*Iu2!$!HMYhzu?uFl z?=lq7=lRG2MVO7BA2GQ5CxLV^{;%}ZAdSVgipD?m)w7YHolbO7%Gvf>fb!Urlv$B8 zcV&T3KF-hnBml?GV~_k#08?cNo}dDRrfcW#OFR6PN{U$3FFD}g-*k`&Bp;vr1J%T? zhdwSVomx2DvU%$$I^}J&cypbF+qG&wk{l381z)2j(}#SU691`fE}`@wB#2abr6rOh zsWrA<1}sNat#lTWcu^&y<7nO zHWFBEutg{_c@1d0z#GjqSqRF_fi{o$!8fcQfv5d#F-**RQu9nLuyOScFvZ845hI?f z)x4|KfWM2T2=R%x(e((z2Ad<_-V_iP2ZI|zTXodH;=lbQh?N#gc1{xnQ9s%m5%VmH zwKtv|d747VVZO?)Z=jGYG)~XL89|DP4#^4>Z=iMuYSZ#stxKzHO2x*ZEa!+A;igk} z(){O|{d;EGgyO-T;NwQ?0P8$D4^xVZ4B${h7{9!*|osI zqk%JQCF-+9CRu^u7;ZwR1a@~|jf`}0CAlO)*`G>tfB8M9^{P*EB6jr7G_jPKk2 z%f@R;Ij_UL!h$Qs`{Lt$+S*i4BDh0Dq8yxz#w7`E%@F{GF8?-;^0=sEiE&bsdzzem z#=#LsGq_t=p*sMrXtqgmpHLY9?b^n7@`XoH#y}Wp8glaH@$H1awwHcCo2XD9;>9w* zJX$j?q7Mv$4(*bwDDzb22E*T-s(}sGMw##@xMkcL zy5IR>(5q&N{Dra-*|zfEQ;S0SCnFY3LyqNe8>pMk5R>jCkSacSY9=C7*nC&k;V;D|qTx=AXrHv>Cl#7$4)|1;f*Hv^D(a!}K24;TOd4 z=8;dUaR0#Nb91>8h^NTwP8+t{hy4qT{UPtQP$#U!X$r&TK~%Nsh17H^-yD}St(sVp zkIB3TD(a2fu19R9jy$vj-*S6pzCREuk`}dnRMD1=b#;%p~fRDb#mFy?bi8 zFKF}jq=Ry8w#EWYFI(ZJTKdS*@C|_$1H^{UhHdiv8_1f4cM^ls5eKG zn;b5WS$?}tv!*>0;%A)zs?1sxyJu!QQ<{M;&W>wu?A-LZ;a@$_8e==;NP%39zrwEv z|Eui7U4Nus^f*AgrvRD`DXQJ9=*qN#o=&+k<5c2$cAkqw_F&mJ#+={&Ng&?u$A^qe z(S*txLy!8)%@jjwA^4VKm)@)ov`%u7wq@f ze$Xx}(`!i{lDqQ=LTn6neJQg8>Ht;DZIc|5^=ScR@fI$?z(bgWO;b?S+uUFdW@~E) zF`x3tZf6`wKD1%!m2{tWI#*x1{|0mlb7}$!ok8p;e=oerq~uW zG0abW8*PoWIuni6 zX>(sAHTti3!W0{k2_plHaq2984E?wDLv*BBd~)}s8U%+}<5!}bz8XuPV{F}&_}+1B z{v=#Bs0}Xk$jANmzY_}RwQT?+2(o7KOdf+QSb(WVuhmQW!FsBu#IZ*^j`UO@^a@<) z!LK0}?;x*3?52)-(El=YMBDJxVtV0s6o!iipMdBp%2*mvPJ1^wMYjuUL6)9kK7R<4 zFETQHOl->;LZn$VFf;6c+g|Eol>97;D!Q|~3+sS($K)>%u2553i1z0dAA5%%_8eGm z)Bq8v^4!a^Y+h4HP_?Q}dIHZDfwrx1bx~e`@6QQ+h1VyUS?`2|!@pB>S;>7|3IyFr zbhv4O%2b-9>AIJEhm|4A(Ss~-J|cn{O=?<1(Jo#9W0on$%At0 zQ7ic|#*(PS3@Q^QF9K)S9;N+%6k2!WII2zE%L6x}mKo)Wg{BfF-h}aS1}i>}67Z(y z5QH(;;5!W;Zj$nS+VE4%Z?>pnsL6waCnG5f#>6FNFebxgoatWo21}d!Zyh*pc$~dw z05ZS`)EE;x6lO}2LC=%78YaxeG9`Oz`TCzwD(gb)kkfxS<3EMqR=r3d183P) z05Qix)elD4v*-1@McUMKCjhJb1{2O+QK|I4_B*27%^o_xI`4xy4+s}d35s68N$`FC zcI8wzZn`&aD(O!6rP`{gG9O(VAdEz1*73IgaIJZbU)i%N3m}gl$_fcbM!|-dVpm6( zXKrjhU+qY#q??Bw#96qvnVeSZjcj}E4BZz;`$x|GWZ1WC??=~Ojo(CzBMACjl81MJM<7y-vj{!KHmqOgdCT>h|cG>g~teika`D%F>w&y_$YL&%uAMgB*_ znBwu)OAsco`y@(e&3U+%q~So8R}=Vk2HE23?O}?2h@ka4Y2AoCysQv!U+T^~S!S#!>A77(ese4j(IDBjc` z*8p{CpXP30yZh>56Pv)WM>;Mu&e`HYQ%5hPp;cM{r|k(p@0|5F%dtC5s^Kdhi76DO z2ODSz0@wE6IC4}&3;yPf?WJPxkQXw*tV-dwk{NB_+%D}0`8s-|th(B*Zq7LHqTBPK z)>zwXrw1y{#u*)?(sp=YfiOCP?YlJZV}a`6{Ls;6dQVD%SQaf9*B4rc=3$ImU5 z-h`#^axAF#@chTR7xsDP@=*K+dG>&c7`VSa`G62}XqN03!jQ7an>s$v&+W$2&+}0Y z9WE!BQ4sLQP<>@r><+x#sZUGa$V>QL@Pq=s+ppjGwK}0Olh&8fgNGn%^Pw=305~H* zAO#edZvPuOZSMz*w()o^GJzcMs{diIZKAbNF51wO9pC;#(dPyJuEksd-itW zKfc`~Ad>3SE+le&kRTTc_~sNOs-sQ~c)1;#2i*3XExL*Su}m8o|Jrp6Q8xsVLIoh^ z4Wi@(2CHOIF4Jv3v+bFmS>z&@_Ua!u#whbd3nV4zb@&nkPv-6gNoJltR}JXS$v0=% zai+D%n%b1LC_;qQ3czcB+gny6hqfip=_z9}Ku_ks0$K3+l&Qrx=`t^q5#&rUJZ_h6 zUW6#JsADX^&9>n;uoMw*0EPEl+LiZQ31Y}kRIcMdK|Fz$O)gGZi*g5 zp5KHf$%uq0b9Qb;6Dzt{KoiV_R$ON(W{Sf;P6 zloVVh{>M({{}8JE|F(1Z+sN8KeivklnyuD3u5cY zD0-GIgI^SR_PlQ?F*w$8p2g1?N7wm9>0T&3ulyyQeE921m@2DptQ&=SeaKc}5_$F_nxnMFvt9XfEaFtKRgKoWmT?TAPQ)&S}49T6&B$;upx~f zfL=CQ6wkkyAvv?y$wj47XkDFuZ@Ihc}}|6PmIwuXoZS%>3WrxBE}#M{5?mBn0me3OOS2c-64iyfSfKQ z9TTl$tY~#q7l|u!2mvz)ds@LdK$z`yVW&Ip#NB|@>z1_9S%0Hpt#WzdkUQtCx6C+k zldyVm*LA1!T<}!9TPRTzU^x0}X3XFefc1G|l*W3yucp${fdWLZ-<&Z){K$Slut>Wo zl&TU#X2|#JDK~hy$F@~-; zM|I{Obzfo6yY|uqiwEaN$XC(ikQZS~XB}Nhl`iZ}bJ)hkDrE}cD3r)t^`)~MIKTP_ za9hOWXMT*Vik{orPdFtZkw46h5Yhs!>kp=>_53ioEE6ZjTkAkUuI>?HpnZS1?hmC$ z;<(xF&dL5oQX-o73b%k&)|}RP@p$=5_7M(Og;VN1CCcmAg6HWqfx_-xRV|9;b3o-bp%`Vxgg`j4oZ{IdzT+)h)1 zUwzpwehR7AK|!W;UQZx<*+a7Ex;SEFgoWqkmIe`SW;L1$uqfEc{fdsSWz|MlI zv`u3(!6+Md`OKkADzB&nSc2)223$_Rvd=kq%oaY0+J3qQ7N4rGhCj88&a->h!I6Hq`wn~mu86(+E-SJ$!^N$sbLC!@!z`t`TxOD}4C zj#`p!T`OBqJ4$c%AhmNli-RTxsT}X(NY@^0-n?d|JOnf%AcGh0yF|?0y8HqYVz%4{ z>-ZR2zPgQf&-OXzeW-krTQch5FP&wb6z#eWobQVbm`eYzAM>|YWN(H=AkrOZH>WI! zqGJ};wo$f>Ilv~Tw#&%K#GHWBJ&5^|047-RmyWK2q5o!vJtk;`X(`qeZaJ1JOt8($ zNH(gJzDl=RgXB5QYkHN~SkWLl?`L#As>zuQP1tOSR~Vl%yP2e@f_fN=vZRY(%$E6G zo7TKr6Wno&YgiC1 zORS*78AJQN0j*jMNRmlG7+@1EEd`rQ^jsW84{@%t#YL)E65 zOJmJbMhqA-s5w13(?*cA*;eKdonquit)E_K$mCnZQSW8g1k%QP==11C47q-g zg9*f-BtOrlR#m*5%}+6N$l-}~W`FW~GBXC60BUDsOk2H$E{-}m*~sIoV?*k-iXJ$W zqgwV8T2QCgCP0%cGSbeTKy9(U@wUoO>FBDWw`JmMB^OT7LmGSMdV=sd&^okp*8$2U zu>Yl>`M&5QrK+fIrLW#jzEW1+3Sv(xGhrB-${kj%S#te}vK@rk0Wgy|p!bDhaJ~U5 zDwj9=iNi9TR8p+41I2Bz8bTNbTjS!&e`yeObo#msKeAEK`&oi&k z?fiTw*7Z;#c73h?x3{;e8~B6iVT9*~Lg9?2PI2jga`W$?6xxJnc&Kdql1KDcw6>lW z^FSr}+WgnkbxHIh4V0R-WVbi*5r*bZ0@o=gERuQh%(F9+JG+>@S3pi z2bppUY7c3XKeWVBl70I24Z2d`=c@~L)ekM*l0&R<>xb)|(q|F)&2;jzn6)wt(#ophWq+s$HR35JEj-BeLv=yL-WP(<{!MYTeBi_D0wVbY=?B{H3)wp&D zij0OwSJ_G|6vT&_ph-ntNMGUSbXkDuIAxgl$Fe1}>EY1AD8Ce`h(#fvrG3t6-VMa0 z_y}>k>f}c@Pne#>@#8uYx^9@yN633p+1nA7D=(hHgY9KL$1>*E*?YC9=(|Jnn1_TK zfA4?|BfcO0AP1;>KUrPrCJ||QbZf4{P%lu2NtF{BV4OWcDvANO5Z5m)UREf7sLV#_ zPsB}(8vgz~>bqF;NxD%SM*`{Gd{WK;oViIwyD`XuW6oWh7HhzdP>J@wR5{hA#v+oBsv)zrF6rw zB{^8grbi-HzZ z_nsPcuA*(62^GVb(#^jOJlDZx)?7+H@X!0k)6aYSD7X~)UVaOItZTzs+yp5GfS{To4&3&kNW0348F@W@r-L9P(J_V9A)CV7^zu>O zD^?=h9Ba)(oM{bFLeYKxa{d#`%9#G$x?+I^z~}AjI?*8x@n@}!1^$pM?q==#qsX7H zCg<{8mnN{?Dd6C}+zJNU*&Dn$Bv3Pg$^LowuF%O~WY33l!29v8p!^UH{`H(7sk^En zv(heot`vi8Gw3f`p<+8Tr^RhzLrKQF5GgVx=hh{+Ih2|yz#+uMPWIi|`WNv>IJN@{ zBDo;8_WrVIdviY$Rhu#QKM9PMd3rn#OOkg(6p0_m1wej`I+>~}{le*s9(whC^dXR; zy_4K{243>tZtJ5Ob(b4`k!f{GE}s*!1M3qdBP({^%S*!Ac=QpXd-mL5{@)rYKy2>L zD>f4<3shA`K{|6422Q~y?y{!h5`mGLdOi*9VTOp#7zKc|@3NX&ocIgNmh_+U2$4|Z zW<<#ayZ6NK*5m$bGK#WMhl8uhu!$dd?b$L?@-G7%OlPexC^Vy-?KV|{wIRX7cwcYY z!CPhU;kuH(^)xbi>*~46Q)V&G%zuYGaZ4o3p?wC(Un$`-oR4XdQbWmQGSc5fpyv%UMz2pP<)sU!hjxCyuyR zm4(OdV@vuZtsAw&zZ%B2|6&XWfB#Q~!TgJzspZn`7rK6#(Khso+}(WQF^FfKB{n&Q z4h1cfh^}YhN|uMe{oU1+Vtkku2vD_T)sg88PBT2On>LeogtD~L+CvTYFA%!nHc7Q6 zPyH=H`O!(#HVQw_IHDwUU|@SU`Z=7s!IRU&*rRi+At9PqkJA z+htuJHAMA8T^f0Yp9KT5fohzBvV3a+yDl0wQ{~_OsEPD4HBOt$;1tsY+8u0z?iP6N zl_a>X_I3i|TUt`22_~iZm3F8q84a>Qqv=-7pZyzcP152`oc3vVu<$c_ZBSlFtwWDK zEN!Lh)fjp7+^zoi515xn72I_VDrC-Iiu34+MRGGbAU2aRW|gIWOx90YtPdyWtBxrX zSedzivGAWJDx*$-ij1Q$5 zq)ybnMBXXCD-Vr>ORg;XveIpXxpgSQP32t=6_!!tUUKnSV78NR^ap81n$8lci5i z3=k(O8}Gk(YN6!?0dzwJkDI8?%S0Qejkj0w>z}`BhJBW1;S%`eGE$2lk|k6`2!Tk# zDfCXLzbIs^(tvxDk)91*emNoSvit>7c{6%&6%x|TNRLj1_EG08D^i7YW%XlZNt^z7 zVD7OTL%(QywBAo-%&npze>Pyi-2U_1vrf{J4}xr8M@}o+@XesL0rz?Z z=OK3XR^Yf13BioMoP6#iWNo2(S0p3pi3$#9_LER;F}tR}1fiDcy3jzV<%y)8;@{}v zn;MQlTKIHmLlEBwVVX=5i7I?$i(?cF20mct?-WV|KDZP2CGo8dg7Hj^QGrxQE;`+` z#J#y>+bt>r8#@HF>zMjO&EGRg=sD^Gh*75e1nx4)Mp;{&9sOXJ|5fv+VVty9rg81L zeZ6GW4E3~^y`qAqz@u6*!crL;dW&H|h4W?gBQKP#TsB^?v)~7RHL8K8NYy4#P*=;U zS@Ov0vDW8q@&eII0%z549WH@G@BX5zEy?c_p`E_tSn3;b^zR9Sj)n)uFXkkx*06sP z3{bxPqV%^0iN9}5{y+9Vy5Vmu2-~?O)Z>=)4+?%cS!n(3-|ct(>GM2YRyasKn0xx{ z#e*rjDgTIQHbAz$ofNp!0>nT5x&7F)o`ECj=#50_8U48~IuOdBbDUAYv{~>6TL@m? z<$?crO`1fyeLBNS?3YS{ejBuRmXhY<6vhBp zDZQe(_G^rKG~i`~L2K7jf>d`!BC~sH$0w9e%r#nAaSW=NYS%ym6Qj$uixSv885eX!zoF zhzWTuDkV{AQ}>K6FVQ>5NocFi997#jel!xy9ME{om^ia|XjU>_8`F*YS`i=wPUW2MO?fg%{%m3QWe2NzwY2PjI`<(A%+uo;cPLa2sV1y}5SCyEG0^iYo z_})v)2dq5ujzNza=6;VS4W8(U4 z@`i_$)UPmPxv1W%W2b@u1>=3mW;sa#P>3e}G-_hZY=JLNUv;G>zA54QXzzd{qt0ll z2~rI&4o=->eL210Qp&LVWiw?LVjioDmqU=Z;`cmkE}XTmEGf>)r48qBvi9bE!lv?e z(qvUT@Is4sg5-@9nPjqqL6Mz_`!(;RS*}1##D+sm1)?Q8Slxn1RORGM*DGD6G1Q9! zwEV}?(zud>b`3?W1S`uF+4n%TgJxo8OKl5rx^4J>*X8;3qkolqan|s&UpV zB#_82zTsCH7oUTzo3s*FecK`uwT}7kHqpyO%Lry%!FKPJo2j%xv4ySUgglUBF|m?;-X)`C~iA zNQt4n_-8U!2MI3H5<=b6$Qm;QC3OeflGln&y;v|~deHd3>D>6x0yDM5zToMXA=8sP z<>)_{$5zqO++H)~l9L`b-kw%_#=?8&&P(aku7DJ&fS9cUhu{Lo(^m^QmQ&2UGb|}M z=`Y?RBE3tYkwUL|Y>CaQIz{?^{JMR%ZqMU?YpLx7f)S znO>0^#;i+CW%8B@<49@ck@eG8+9z0~1&+20b{S;LyVmjlM!TFRf#jVIcQ=Jp6pa}64@FnH!=EhIjvC(6sh%1CEHwlLE$8b<+Z7}<7bE55LuNCp;Obmhr35F2n& zhibWz6{N2L{}>Eo+WibhYMf4Xp0tuSjo$2kk+Xt%&zpWyqUJ9aigaPc%)Sbcsmy7EPW376*6vfUo5P|Uut>OBO z3%&d%C1Yml!3kzl7jFfkgmzM!XzZ_Cta!8=#U2x~^>a(JVz;dPls~MH*=xeFZ1mYK zu6RA=a-_77Fa0C%u|)aj>WI)(#f5_v7KJDuX1I_cF{Q^o)w$F$8Bw2mCQtWo7&Uh$ z#(-Sad61W@yfhsasH;tSGnQ+eyI{mBb_>SJsRTD9Ac&Ey+Er{OoWB3MX*z92E+4*- zLBnbhgLlt;l~JJ&4S*;=uFp!6!#oJprjIeCm6RTH$EHuzZa-oRzj!lgdh*%x^fO3O zS067$zxGAAuq=Jyv_0)m7R1RF1EX67bcl|7F9AvawnZJxf$37R!|)VcwWvGrmGBCA z`#G#POics!BJR!E+KkKKtj#tNU*AbLI=*l0gx&8%mw3^}> zFnqn@mtWf0V=l+${js&L2fV2C<9*7rOgMJ@NJ015z9=hSWHhg;P3fq|@4H>uh)AQ` z?nd1+YC&7Em7h;ai~Pws_vYqXn5*}2W9!mRvb5tY=DAH{+NX2wWz3W4f|;u@n+LE> zn`3H(^g8*G+Lb7h@&1RFwmq(j4fs|>OMmbON0))665r=_7*$>Ax1iX0=Cmvr9yPjIkJ)^0!r}Z?aG+1KXaX&9$Rzpju+-tep!~MOy z5n7m>I=IlNN%q8YgE7^pKkO5js0t8rV_L=;7MyK%L0{GkMH){v=#Nfaac|kh85l<^ zbru5a@acC)p7p^Gkqfy+-;~46E!gwp!fn-oA90rEVve{-M-?Zh;(jQ%8YsIJ#VVo5 zyIq|74k4+)&*AoK{lNy^i6W_!`LFh;!4a!V98l#4n^cB~898MB{D;lGaNxs$J6*qnx(Vf;D=^6cF8DIBbRT86Oie;=5?J|UB(XAeZ z;U!P?^;OiRn~wGbtvS4wS}s!*bnmnj(Jg5)7Nxecn_#@(812;?%xlVUKRJ76Pn_wKXPLzqkqO}f8ry`XerlZf8OeTGr zmSPi99+Jraivi4!8Pf)+S!b$R_=WF89KRniOt*Gjn;o)y$7eEV-}PNtU+auPeZHp7 zOU`nB>07@mf;2d8+v26KSHu?J1=@13+#48}VtU9P2iQ+boHAHki<6q*_%);f7QKTz ztxiTHqq6vKm2~iU6|7&3l`t!<_!hpfow^s5H5P=t*fN;*d4oUhFgDb-p!-xWsr@eI zw)xewNt0Q5#)~kSiT|AdHZuR$qW5oyS*7;o*K}yv>I`lE8Ye6qX&ALw7`)GAt1-?H zDWMkiricD>tWe^z;Epf&yrF;T&&t6N{ML1j4G(U za(wa?NxFb0-hU7R_-c*?V;9GN&K#*z8e}r>1o0sSm1g(SVbRH^Z;N`IiuzF0N@K-E z5y=sbctIj1LTz3X)!Wy->w7RdoBH&Chn zoYs+QDi>r)p8JJTU&TZ!>kJGRYs(6bYZnR<)LI!* z>U)`NVx&CCox8y==fJNrCrCzfv+gx=7L8~YS&O<^U$Rt>lZ7PC=`0k|ctX}Br95(R8$)R5#%w+$ zLBjL>-Bg8P^PF7(HBke&&U9O_(&7HWeeI;frYMICBImIJEORqM7@xf%fHJ1+*omlZ zJ>?$hvthphU&NvnL}S7bUYaXd!c*i#XLRuRM=blkgS;2}_c*Kjh-_T`A&Tb9dQ&DE zFYq{~;ZS-ouw6+j_tooiBRiPaHo+%1#;4S3^XE?~r!$eBtp&^N1h%}n&_C!$rBrkE zR6H+GhM%^QWGeN54%G3l0f#;JA-1ehT>e!~ptYsRW&pmet@SDXr~Qi|dsY1}#%o0< z+ZF_!-Co4;-Mu}jrWK{ln0xMQ_&XTbV+OTn%PWw0s0I22aS1*R?P3`fI)QuP99*63 zNB*UFWfTaL*~($%p()-Ln9KAMPF}N|y(Au^osM|uQ7(SUU=p7H%dwaVX18=p0V zqVoPkpc>8*J61H7SoYd;Os12!&PnUbqR8SM++{00vm7pA87FLWBOx@k4+E8a?Yk2y z)7m2b0E}CkAW|UmbjfZq)Vi?t?Gj_ym9PyM;%l}r6)ZL8jQmjo)3EGSTl0Q4v!~Kc z9@1U1^zfF7xrSr(uCh3*_%zrnI0C*Fh0=rq08Ve;CH=rMS^OCBLQ$=&UJq)T%;f9u zG|)VRW*C;b6+b&w>35DDVAVo_te0mb>e6G|z*|kxx0WI!RntiMg;6a@frJYkQECx` z0pUk=C*nOp9C|^iVUqR#cdKxGX|I2?GLc0HtnkEZ3HkCOLu!_K$84Y;W2Z)6dW{@9P~E=4l<$OlxcFS|{(4_p8jv*{Kbtrq8I&BCH#k zW7gVHnJbirSEeQ8MjaS{5S7OchmHU|4fh}~P+4DB!(k=7;QJeC@xz~9M6l~@gt^PK z#@H*Y!B7Z&ZkkZuh`G+0T|vzd6|36#Qg`eDDI*mM(WdV3@zo^LZ>}kSN%;(Zq}(#e z+lz2ZXx6VYv`%mR`}w<3$$R_H@-+S;X!&inXo(JeF#vyqsSurAgiUj-1XOV)J-JUn zBY;EE`_YSTHn6ty@^SJ%2SvP5usCqem$3Sip!ld!b1XmlW$l7}JtI^?3%?wHBbrFiB{`EoxfV z+8HhKS5d1;gT-gA-wYpBPJniH$E6N9kN&Tc zgg6uei+>xwc}`yfcJJ<+6qj=2xccKx_X&3281hd+$)HNqe-hAO6b*zgVu7C)FVv>U z1Pfswx6$$XZ}b?Xtw65S6y)-a%pX|(BybR%{VTAqP1q*uL*)mctmLuWgGZyMA72_R(AD^TCf9!+(v672Sg5t{)J<7#De@}V1f~^laF5BWGV}6-dx%|o zA^e3%Qx>;KB~in0VR+YYW%toYrGayvry}+A(8~yVVexlnAP%q9n0B$wLW=7XaE13H z9M00Z^(!Ul4Dp(wCTPmfjC*TRCEFMxw#ce-6;Ya-I?+W1d|&Je+W5XldU~ng+>9R$vkB2r**3M{qrGjxQTJsWvE0A+E+gmy^?#u%ku zsD$7+gTh|UWi7Ss3jT9Y=i=aw)g?8@9=z-8j%&s@b%qbN^<%C9jE8)s5!R~rHHB{H z{3uExtmZ&tiJN!-0xAZm#9$D&h0l>IHS6h5r{FSH);kQ0jqx|^gjO)G({lJfM{Ul% z_a{Lll)a4hTD73lIe^oVI2j4}apclpTFM*EBqH8;FZ5298O8V5pn96!zk*sKNC`4g z%)+PUkiJA)KYQ5sU9_%%P~9>sBZh7!j*(p?VJUO-G3YOXQomPvSct$B+8210*>>HZ z&`8nUtSt5ydp)-i9-HsrysCQki98&OTCQFAr=T>LF#a3CsgQDuW0sV=O-J#?G^QG- zBoiG^N{b7{UArfL@-Z>^y2{-K+>D!6{uR*tdW8ZIg>M4pIU|c^(oW_+VO4-qb@P~y zze};T$xHC3UZ9tEs&3(51U0xtseG{o#Ym!+?elk#k2@<74481MMgv`CO*PD(Izy$XCg1A{wu>y!oj*#wM&(LOFrY)swRJU0!Wg;BYxEDJNd~iXNSLS z*!-;r?BA=hd&Ilis=q7jCNB7&r>d%5!MnZ~*D|UWOuu^y{A?bPMrv+ z>fGt{f9!bUAD@{J-#fO*O*3f!nTjKfF;if_ffLHg8*($q?Yb92=k z*nBmD;Z~~kUVm__a38FTsXkny>4|PTbI!6l@>owCQ0Bk@ybam?DV3kOMwdUnK{nk6 zrsJnMg*^W7!*{yx5+~!O zNtHgp0is$|;zRdswS@^1`sUQ_2da2qubVXScC>rj^34FfHC9Hmx73XalY_SbXzXGH zq!K_hP>=ysOG{=oDhI&pnW#Uh|0jWP^-5YR!d!a51~M6gbOjxinRf$5yhBbdMO7|> zZpC=C)ndF@pS)o|jJb&jjQo>e?be?JC(&sZNB^7m>EZSAd2Tw7Z?42I>$A+E*R`bE zPm;41=UDw(H9Kwz#Eb1GzG$R~!)Ze?b`BJm&Nseu2L{_O>6qH-arS9$cYHteyb8;~qwX1i;>G&rBR(9uV zX)yn&$^Tppg?vk_kbm|zqJ{RDQ=`t%+>t*(YT{Jhg5Ok_A}G8i;O#oqsoJ&KdUKm@ z76{j}nq1DIQ$O0yz`y?H*i=Vr9@y>P{q~gRQn!)jw+~zI&$ThT`2oI?+(Ib0;h|_| ze44pf79kk2Vepk?_pHmJ zY`#lJ8kud`bf%wKonQL$*D_C&BBEqEO(Mh&KdaFWAwfoB_R{BeHZK&c^|JIBxut8t zYw@~qdLJ)V8bDr@S8d@af+<|w*Gs;lm6jrgG{ z(*S5M8e9N{4mM{cq-D6L`>F2p=sOR)C?$Z`%%CUeMcBnSsE11 zo)fb{V59seK_R)vTl`2Y%tX?`;nu95({V)Yj-GX1n~t_yt~F;#UQ9tu7R`(8rah8G zh0{lJRpgT1A7{`Ok-D1(GW)tXR_BN{veFFrJbbmDc z2YnX;bnMXy+vg2>$a)**_WQJCvoB$-2_RPHR(1`?YW2~`nlKb^S)0lK@VHBG4b1e* z%Z6uqoxj?X^)92m7gIeR`;bCIq--H?sp4CPQ@NpuIaLgB9rbRN)FN`ktez$U zvrVY+WomNx`%2^bOoG%!3m^ZX-&M}J)ax|OF^z`8CA<3d=>V?wB^NK5 zk{<{BpfsbcF_o7$^Nk=6I`4JGJQT<*_;}Y)$9VJ`)HIiY->R^_{YP;y#`*A#UfZ$2 zk%MpF&sKSfwyRSo#KjkE+(v38m&V|56<32XXx*Cz=vonz7W0B&hm;6EzS4x$t(u#C zef`?gsq}0slx+8BKU>py!&Rn&Ys{CsJ7XPnF<2gF4G(5SecckkVVQiUy}>E4{`djd z%Um;hJJ`1EIcPq@rDUYY$uj<4l-+q(5cIr&flYj?>rET6WVU z`f$*Xjx>{dc>H-YQ1PAZ5}X7rh;0V6qLdts_?XaPv4KhfFd>LllRi2ZVuOLHcn+3U zY6vqScf_ttP=;cd+5AORk zzi-a&nKl(jSlXDWFQ}Y;&CPH2<2A#tdDNSIhLwEcj{)_sz<@3a3LdlE`)PphFIl8Jk1G(O-9(PGjXXX3` z@ES;bGvwT}0NtH^-f42qg059467NOR3)5V6cGncIub9WpSAA}urTK<$IQO|Uby1*Y zNp@-|l4?AfPha=xHUt7Wn?d@U!LKY8^qAu7XH_gXez?vLdl+rG9pD8kZV?~;WBTzQ z?=lpYU;-KQWCLJR*Dss>+JC$&qNer;p>1hN?-hw=UOa8vvsP^zy=5mbzBa8euNjjZ z)_i`S`jMdmnaM?e*Ym@zRtoJ~q4Vf|mLcV7EJaVlLeZV_0T+arLwD7o=vp85TZ@#l{qs6< zzvcc(aP~duI?vAV`afHo|HV1Fm*%S5g}Li#c8ryN>Xo10R!y#vbsTmi z_q7Rf6Ni3G|LLDo-iP}-=`i2vO!CpAG3L_T!e(2Vdqet6(^W9ud4UO;Xi=GHkB{Df zevlk2;_wJr=#6C@H)935`!(Mys}ysH2(EOz%W~n}zjP|nv}YX&yIgoMmEWy!rbg&) zC{piIH1t;eFc))whAge}d;RFHkTn;_U8vx5MYp0bI{4uOaIRs@3)KmeWfWzzT&AVZ zP2NgMD+zx=fMy1Jb{5LwzI(HjI#Ia*OmRU0#Fq6FM^l!QDUY9~psPO%iCc}T9XEL6 zXKtD)pF}k^QtiUa6+h|$CwwQhDz|rMgD9qqRRzGm!EiVK{3gRO(>4S*JjU0wbY@b@ zlfa>%uSxX$afsTQYtZtyMhCXrl5VHQ-3m(2n2FC{`q}mIAL+fU%@i1TCj6=-k*Rs( zc?xsy(Bn~I4^}3{kBx2nu2?o9uI@YE?!#REB;e`QR2@H2Muu?wKkU6{RFhr1?;C8` z01@d`KsqSWOM*T$X(B>EN%;n%d(4a^zZ@^um3N3%vo*-;`@fX-lAv|dEEr}3!oWl z9JBVi>`K_oO_wrX+P2Ug1#{lVw;hIclgvL=Tv*Cv2Kr|1t+4p~EPflRt5WbLGBa5+ zY1bBhWqrck&UM12x&5yvX@O`OC8o>p9Y_HZQFDTz&JI%jJ}vf_fT4xBIIbMdR0nWKPP z(LwIpaxNzpetQcLMd-&K>{d^9zF3l>71IW*Ud-Tg4av;9{f8RQ7we*Ele^$gyW8J$ z;IT;u%(r|t@3@$vdDU8oSK6wF|zkz%-y|VG?{9VP32gIygj9P+?x3CmqitIqF zFEW&pos?WJDuBL4B=A-4kNnCTC_NcX8g=;TKCN zFR;GhfPN?2EK<68Im#KHy!|z5+*^_=d2;t7N4h+Q_zPeRD^w+NtOlElBeaTTB3mUs z;&Q~5-QD;!$R!JFWe%yFOD^Yp>lV$%yrXO!8g_!`(8W7 z>6sQndFbry%(plYu{7gcv@>dy-2I2kvW&VG0#84_EZge~TQN-0%8jCXW?IhDW>11U zRcY>a$2}sA|kcb4=%Cwq<0dwwz0=|z=AHb!l)C23M zX3F}j60xl7aE!x>*TgQ;#;LnG!MHE3D0$P!L(D% zb4iR+-`2bxWnXWs1++>|ObBRk!8*$ZQ%-QOWJ@rJE?G5&Ljm9JC;dK98?*D=OF$}#Haqgx$b z3tc|W^L=IMMkrIydcQGv)Sl!HxL;~5H+@^O{e}hh0iL#2xf+Z3dcbEXoMX-43r0ld`y?+AtD7_YW<2-nFu0vqrnjKdOyjHYW*W(-_OXy&`5-Hp9 zkhyTHm(6v~M2GZclGN=%D`cjniMGhNpg6xubO);KY54Jm&7p zyfCRD(=P_w{as6~FNT$xTzK#wxs(hj{=!vwxIC*gLH9{B4{#XeY>iu`lq*~22A?CB zlGcb2F8iL^YaBys1pIr7 zdNY&1NDa9_J;K^ltWd{E@xaZ+ka#)ds%XEE4-pER6LH9x!N$#XzUM>(PXESL^ws?_ zXpd1Dv3cfep4#LT1MQ}YKvAAJpiIlNJ%Tb`OF)Ac+NbHUKVKkDZ<3)Qpe59#yJ;o6 zVrc^xPCOQ!m$(7@GuFY&Zmtb5Ehb9wH>n|QUtPD{PZ1-$((p_IdHu^sb101e%vG7GUoC} zJM)_n|G-teI$V>`&2v3P!9ClZ2RwFK&q9`4LFi1Qnx5Oh!qMDVu8aQF6@QT$em4q# z<0`WJ-l7K$!%KQT?bOMHj!O$vomh^zr4sC*bPB-wx-w$_}p`f@1NP@H_CsUhVZeY*_?qP3bnH#BI>MxF9SydW z$j9=N>B3(wo!(8Aq!D|1RM>Fg_rmZu(rIrAEssd;TQIf&p9H7_7AQVO~WfBLiydq?s$=wS5|J4%siu-_&)e{U5{(r zx^uUpFMxHS<G5WPhVo7xK57UeC+}!#mat|?>*~59E^T5_Rx9Xx@U$78u}P%Q4nU?e@(~&7 z^xIMRn`WS6}qm?VL#~N(io=HS{MUQg1?Ifw*t?{<)g*KW&0OBvO)$fJjZ?F}J z6iNnLal(3?YedIlP%oz6LzwV`2AYR*-_b}zra?%8HRt5t$s5}k)ck%8-~BhR==5~$YiVE3&Y<~r{7Id|6MBlcd78- zrNV!$Qo&rSa%lWjrQ!5_sZzZkrup+2bY9AY@lElHnoYMuzz+>2K<1(JEE{X2&1josJ~W!dzY7+sg2XtI8=wPFj?k?zkf`}6CwSVv-3Z^aVXzY1lspa=%aH%i zKI=1@58iwFdltU{Ofwm#g`oe$miavH<2~yGfggD{87AkJhlxElg z$tn2g`ef_@BFIZYZlQ3xYIRyCyP=?l!DCMctm~m>z2voDd#BsmJ}hkWLr`SKSnkky z=0Z=>cyQyy^AQb~DEu`{wo8RVn>y3C%ehc$9UkKQOb6*22l~*J&cO!#hY|+gHKe3= z3|h~d;cgvf_~T=_+4 z(?agN6Js)v`D=^AAchme2WrQSzaR?s!ls@mwDpWrjabwuseU$b4CE=X_Np%S>0XQ= zJ_en$>+p6bJycJg%q`_m@qIIr7rI)q!77SKx30-i$SssuNnTi6oue9xbt5v>=@? zRGjjpp<@q*8eyZM6bOgPuJGC$yo9*+|T9B=qH3^ggX-Rl6rr-dhZ zV_{P}W=pag8lcyS(6t7&kIt4Gs}@itCc;q%)baJ%680CSRh+@N|HFVlO zy-ES{{zi2S2{~ikx$>oILJzuPt|LRs(*_=rR*Gmuk5x8KFFcx`9B+sd_Ik#yhCGO$ zA8pVk79%lVy&?x%ycYTR>o2L8-~T;D%s=;f{7)Xe14EyXa>f*H#R}Krv_8Zg zm5eQq&JI4AJfNPdc3@p9^|e)C$MRUmW%pYQLn2x1`OvvIo`*Yiep9IM8n3*tnBylM zii1>s1R!s2U{C6qbG7RdeOZE?{ruW`T@WHj>&g7i(B`JWs-gVQfY~^{@|Dvu#x{@- z7JRm9{c0YVA2@VKo@W7%*->Dhyu3V2UQ$t!FCWSVr(qq}(hF~&sA)drO{lqNT+82A zxLRF{8y<}v%}qPC`D+6B)5xMlQV%H^m$HpQwXGhC7-IG-^J;Qq?Z0Im=h_FXZNCbX zKQ^6khK^jtva)AUbSvfFH8P2ah`@#0uPnveEyBMf8MB!keogO8({DaewS;(27 zs6_RzOz=r(PiJTh54t#V7*D$37 zH>Iqx+*i5YOgL7bSKX9Q>e|~`T8+BTQ&=&`UX#qZrU~G>#^i0)IPXP$iRutMw7=(; zH3Z$5G|DXg?n_XL26f^8gyk_FX z6>{~m!FbiTYR5z`&!j~joF4&{A7kEAuMzWCcAAqG>N@hqm!E{{(K4i@{YHKgC^tCy z(4WqCyKkyEWX3ycdmoIA+86b9?)SbKSspyPVaF42cS`g6s;)(u!#xsC@9h*XR-IlF z%;<;KNN3lG*Xgu7rix^3deejVzDBk$RL;+=khNMqmtno*fW5vbfJxJ5hbrXQ;P}7u z$Zr0r>ou#{~L$oBOuEKIR(V>mAyY7jIHpnq$LV0-8L@2z7f~ zduV21ZW1aJrLHRSyrguyF4sn?8~E+gt;ahr-~pSTCo}E)AQ9WcWXGIh#M4NAUhBIZcFh7a-?6Y5Zu_Swth@kE^`GqF*|DoyT;}GWUWXoaX&Xl zZuqTJCuH}JwT*GZ4tCYM2ldfvjS}VFAg-5_jTdHXen#A{a}6D>Tdb|{a@Jkd??BWM z)}xNJrN^jNjXt$Vf|36GX>dhgOq;5ReslZhxH5Gf<>Z6(u|?F+5XJB3!;(0+;k8uF zhpSHLqHW&lbcD9Y{+_44>^Cje>2(7Yg|LY!Rs5^+Ag;p^Y&JS})||DW$uF$Zy=YJh zmQ$31H^Y12i~PPLDmRi2we%t4;V~uL+%eK2|GZ!o5rd@6jJ5d37yYK)zoA%(siM?@u=)T#Rd~fYiyOYGtxm%5*H1&(VRP;IFwZZpP zQkmH(yswS`^Epd+r9M@!j|gR>f$$5X>n2(+UA;Db>D4#-jSRL7N#meJd2DzqLqY)sWUY6`puQD}bOdnr_o z$7cs-HW|hJdG-4#6^Ao>~h*RFjZ3;5Agj zI==G34>uj$wpx*b#2h=YbOf`mrDle1IdE%-%%p0scbBd@PX?`1kV(oEpOwFEFOy8Vm3MejOMA+8kB-}}& z2O8s}w!zIP%lIyMo^8n;K#i}dzHtm^7G`IQav0e%Av0UAf?mGeEpRK^-JdSfA-2Ls zN!mVMejW>`y5o-S^ho7pASIbFwz1m*c?cRLbeQ|Q}j}x)f3NWoW5FFKK;Q20vmN6@@VDs_lJ~%@UQ^JD8 z`(1gg&imuhl5DW?)rDHMQ>xk9JL@$+dq|0vruAX3dz<#XY1=MsH?af9P;&DL%T?Fd zXS#HoHeCV(-3e}2LS@*C&XHCUl087T9+3FWb*!E|1X5c%DV|}llko-<7FG{2{o|ic zspL^n__H00lxhyu#L7b0Is*>bHnOx$6Bk$0<$Ov8NMCF_F4i(c*SV(}c&3EKn&F1c zOmplpU*uwoY9vzvO05r<+S-{#$9(R>C@6mXv3Z?m0(H*jIK4XE*>0N`xk@D!;ZY?} zs;+6t4b)@O$2#k*CYoUix_ZB=CN*!vTOHy}OSLYEB+YoFSM06(2S?8%7Vsqi=Rnw0 zalPD+sYsK;Qi6pg&U{sxhAUx&@E7U*|ny4$?G0gb8?t zU%^pR)Sl_aG>ZF)T;}L~K+>M76BiE;YxUdNiCHVhq_Nvt zc`zN|CZO2XwsD`V+#1bRnXuc{aC~ZV^SPWz!|k!~ z@Wq8PvG=5Gl2X9+p>qQ=2@v=gq2&?znlSO4EHQq%DulQ&*=T0#aF0gRD!o~YwWs-1 z^;5~_QZ=y3aB31iuC|b$tEFy_M5n3SbMr{_%W3Z`ODW0~_K&5Ohlef6q5_%TK37qd zwpATU7j9qZmKg6B(GmS^&c8|kjSQvn+9rW`}I?2h#`)2Bk6>)EEs#^LGd3&f-V@0QkW0K9W zGn zXrMI}OpbAH3F}pF(Vcv_hd;30`x?t%REV{zcv!{fL%V*@BfS%euVx6vzG@44I!`@i zNxd(+w4Z}LqWlGz$0_yge>FYvZ+(*wxwP935t->0g{2b{ByZE4CRGG*-I0kt#Eh#A z6D1QZap(xxG;?@L@}bq(lp_nP-=qa}51JgF=Cc>u64c?x(U)3>G*NU$;hNmUw?iu{ zpAS?PFEsGC@Emx%*t|3yIfJ9`roZx@RP5N04N%u!c5osvO^%Pop&a8H7;3)Aat1>@ z%}!QBI`#OlemeD|k|-c5aTg?z_LE2vR~rvJGwC}D(xb^b=NY!I9JH+z1C2@^7ON!u53CD}+iLV&lF`s@u6=>oR7!-J})ph{l$H_4*0{^V+ zb{z>({C53kL_X%rX9+rXiwX!cjR&1CmG;`5 zq~Rtn^%*p=tK61;l5GoTBUHnlOwgW2Mz7{0n4@?vFS%$Td?)!dcT3}HSpLAo zZ>fy`xd!(?ZIqsI;c7c4)f?JoCKgj;V?Fl|I|s;DFQe1zDe(ynr->RLegTFKv{t)e z`IRM#55GBQf7(ENln-+9 zP7`Ki58Y2&Z2g$~yKE%eT#lXf97BJ0Au9TQ5C$HA?sFIcTb~ma7q14fhJcQAlUczF zp7pv)d#TdD0B@iD0>nMsC8J0urCS1Or7Q!wpz^c!VHy7JUL&G<-mX|3x8$X*aMJ-5 z3t7>BD3UK!$0Q^~e-CKJzP5;a*y$xwBZ8k1pns<>^*y4uqNH=aX=)=wN^W%`I89S#o1uo5%- z!qeKlZa2CRg<}dO&SRkf3*k+9rS{XeBpFXBZFP)dJ(KAeD_N#VFs+@V-Q1+5bzuH? z5^~VVSO)zjm^AGTuPIi|y%)5OcP zjQtUnA|ClCT&|l(2GiXO5CyX$vYu3^iGWWT{UaA3)G;CrO%0zys+t|6-YUMrMxqV>J+pji_8Q5UhG_C|2 zsM4lHKrP91H7L)u-Ww~9V+62j$1I;cQGynDmp_vm9luR`iy^r97hpn5_7{M5@E3s3 z@Vp}3vC7QFME&EK=pB7S!y)69SGl=w-|lGfBtLR^w4oua;D{C+8ciXN=Wf0WMe{it z(atErK0K*99g1BkQqUkC*2%Rk6GP8(;>QJ|8)g(@nhp)gRwdXlp8_{Jhs{IoaP@O7Lwl?ze_- z_0`&uqaS5xHhTx!ImYLW8g5aORY<+)6fY<-Q4#@ zg`G|a0yg)IMKojKnJyse2w&Ft$-lIBJ>9G}Iyv zKw4;Nwt)7?vHUfkbu@DFvF4AqeB#_qEA?3pn^|4hrr7{dfA7)E^j3aDY6s3MUn!eP zb#&O6a8Tc@m*x$HT7j1T-2HQ1Z{KgjYTc_eLqxqxMfJr!@}7VI9cGdrUrr_Z)w*=t z?sLNn?)^VK3&IPNUZj-7%hYyv&(r`mOC7up^Ve-zegR0$<+0oB7CY8XRiZkRd<&Kf z$WkC0K@d;g*M-x#R;sRxb_hqc@^82o(lQR9ql`K~DQ06uW$P{D2jq4~#X`JFDuUVQ zZ?Zj7aP*EBj7((kQP~-6V$_ z2$S`wbr;nGci>dCPt#fkzJ6N7y^UK4v1w-?TGG?M7H}E{xw|z!UH>iZ(MiZq9ODp! zlfLDobRJP#MI9|C*s+?LsN?C0vi!IwoY&d&R&SChDmzI}7}{y#jmb}0o0)kB0Jz{& z$nK{qSHF6Wv4a*YJ;u;*gQpT~r@7*UZes3$S^q?2l?}bR-?5zygek|^JGW#hi6-^= zfD;?IZ$LgXeJB2+$xkMBCWT|vBd3Yr2^0F(mcjIE1vN&?LySgV+d2kGntv>5Zs@}O zA2978&X6qYy#b^{g9Z-Q`bg`XDU2$6G8)R4wkQ#`DA7B-)=F2zFOOGr~2$*PpUkQdhzpWHp`6C4D%m|8VKvxzRv2hy!Pz3~du zE-GUhpsMi)fp@DP&m;8b%R{&o*E@j1d-jG#`X9~D>oTISI!Ti(a4D6soIo{8g(ZpJ z;=oAV!jV1X3cAKj+X#4^Ve~XcntQUcY}meR<-p3JjKPmyYNaqvJbJVgv6aBYd4+xa z7vP?q@N&A;^1x{3zIYg#8?l{e?KLr0gyzRVft}tv{?;I>O_A@}Dfs^Um$=8w(~ zJ@7hpl*uRYEZEQwM|reAznfE=;-tUvXld?2*!c9^gUG`w$O8kVezDk<@vh0R1^46( zM?}hL)>O$6`J1wT9PsZ$t+vk$E^Z9&l^$J0H^diC6B7RA1$nkoz4+wAKYfGBo&O&G zH}2d2-`nyF@VH)o{n`pYSOljW{BtalYVmL`Ik$Q|&no+EN#il<*n-`3qObMgm2QRV z3itr)AnLV*s7IT{jWoN0UMJ+OnNp4`>mR4!KCRCcYiY+3!&op|C!veyoc;O$tP)A0xO>eZmU#R zk-aNhYQ?AJ4g(KbGr4g;9@8T1?Cc%TuQD@plQJ_i)mrZ8J*e9O;-Qs=?CrckfL$}~ zX0_KV4eV6*;JJs58_DS#*@F*f%m3)`HNO^^rOokTSYdAh!WM)urExFoxK3nMb79d4 z2KRn=)OO$Z<{BCWpcL|X(VZE-Up##H2KP zPY1SM#XYJ0ugh8>KYfTP#EF&{J2KrrFu2mj6r(wDB!7EFFh8 z^0c8#3Emxn170D1q7md$@|4@s)y)RIIY=Y*Oif8km)v|2TS7(kUW?U4+JO?e*84mu z-K1SI;5dw&Xd0H(R5{U>h1KA)>u?W=3#0a57Vgw@Ie4?Ne4p#YCask1P3~wcOUL_( zsbcP*^1Y68OZZ;==6gAzp%>ck?2o{T@_7SeSUIWQUJfC8qoY{SU0jPk=D-gotQWru zB|9JFTZU;W$SNC9Q$p{1nQ^Q|y8FFW-abV3gTY z=`AJFER`6|A9Qtc^lqcsunfgc5L`XTP01;(pSs8D9nq}+D$gu~lRDG?@dRYco-_oR`)j(cz!NZ3S|p3*R+P z^+J2%OzwACLO~mUaEmHPnjCzdE$(qOJz!^du$}h(gp4l7fh->$yk|2dn@*eyzfvXI zuN#W#dxbX>#Kl+NnJhRXR5-M+p$_C-lRwTf^> zCk$dYeyaxD2UZ3*JI>v4iE4&y0Ovo@1X}GoIlH=$j|@;VPv1bq&5Y>6n^l^dZE9(w zR1R%q7vFBCGNfwdq^o5liFeBN*szmUK43`~+Uso{K%59S2P^A-A-l9CN9H@HO+4Wz zDLku9ECO#`K3eIu$NDxMyxc7brUSK~&J~Dz4%rV7 zi;Oefq*R*X@~Y~d5mGl2q1c;3=TrK6)$%N%C6$Q}6l(85&u10S4qRdW-%K)3Vp>l9 zQVpgm<#O`E!?(i?K8g<7*JM^V;{_RZb8+|bPx94`TpLR>O!R+rjM#G$E4EyHS%WLe zBvI2;Ls7+??c3*B?!DV-ob95Vcbtc-bjs?SQQY=9R(s_!Fxp9RC58Y(7Pfd$-*Uc7 zWhvKOZ(W@Q@?#?tQan(}l1c@P>Ao4Fnapg&wl76>39(*Jmo~J+8e@j#yZ~OW92XF& z8q)%z6F&?X+)~%kxdDpO6aQRbdlCc)nBC|8blAf)>~`5>7?a!r6pYd1WKKI-uv|Yi z&v44I?1G`nfhyo8Bfp_0j~$YJq!ojpyZs6G5qi<-Np4QaORue_>gqQ2%FdU75r77N z>_*IfZrF<2W1aBV$!8;zJ@tnAKN|Xhe8^0rTbHaSOqQpX*pWA$fXuKXWb46Eow=0^ z$R6GDHfn7SUyd3ArpxWQ9a||A>nOj(3_m@y879n@wuNPNC#VhrZNKfgBd5X0fx+g^ zFY)S61&Li>k^qqUDT^loC&8Ya#g67TB=`I*tg69~?8&&niO=MwB!V*J zy)Pw{+U@#(&LB$D{Q_Js`UT*o*93q2Ho;!Gp@1lC0&5Q%bnWzxE*LbsANYJWojSzy zuQ(7)lEb24c#zxe^Cgsh%9s57l$}oD$oaSpG1$b@c{1oyw=VE%#8?_=Au+<1nxRgwux=$c$CMib=w728^lVzG*Ju4b5ZlVu=aib3TD2qE(w0`h4ctp zKk#7@Ff0MK#O6G5uxA5@*il0*r%*ZFXxqX^)(qG;0PgM9mgMeUE)-zD!FubQnsg6A6UgR<;V&_YEWW zWh)oUIog~E&&+J^Js8mMnoPsfoLuFxygEUiS3|Dji!*JDQa`kKJhk-GEKf$-&<)=A zNKjRGTcNp=RsCF9Uza}@7Gc{ovYuzde~%!@GQWe_VeZs)m^B z{^YN_S>)^yt$&$ckLl0KhgH(@nr*?LLr{!YMZjtr1&5&q0^WHs>0l`yf7`9YdsgY7h(*!Vc zSTcq=>TprKvzFSV0wdK5L9WiYY#Rh~4Mdzai;r8|r)v zY02q)-sm-5o7zk>efN)pyq@}I^>xDevP)&)&Y_Z5z>;trE#gIP%SP#_*r@1i%s0!= z@ntivDHVG^)c3x`;a@5oa7GVY{U*Mg zgi_FwtZ(|WR|1O83~D##dAcrj`)j*^-H7v#rKF0rYYu9pp`EaL`+*fP`%R;~S~+xn zN`_gFwcS{yPO8Uv))zINk$eH=x*qx!6&)<{7c6<>!z|HsdLV2{*=a>UurUF zqWo34R>5W#uv0gC5Yi7x1G@{Z^+pj;<~2Q5gL8lCM^s?%8)xpb&897l#{^#XP*L^z zq}{{$Zr=AmT_fDma8nmIe1wYCol|E7(c;wM&*chPrDA|>J4gA>?S0VtN#WV->Nx{L zAC8}#`e66mxG45R#aHkN|F1!Zu?4Y|>J6C^x5=j~zW`nKj9Q6yt^O9pBT^Ma$q$5x zyohpf32_N2bul;g$!$TymNMcYE1ln7k7a=+pLjoi6YyM=QdKghH%nGZOwh$242I+E zPqwc{@565Ea?9{TLsaveTXR(ASOHuVZQ<5|5UX*dRJ*^&A}3Ebog z8WXrm;2`0LXk5K1Ez4veZ`?-VO6HZ4Ef9Wj@y+n$-h^KDYGUQ_Nu4jg2y|Fu z_0Tb5G;D5IBy*oRRX|%ZN=qZS{O~te)nkc4RkdiJf`ubH&dUm;)!_@;p!8bv$-j>M& z2gDMYRL#2nG-oKL+h}ueG$*;M>qzRL(8#YE>ntJB=Z{mspfSWvmc863o0s?Bw=TtN zyhML=3O}UD1hIMP|IuPO(w$0$cRH#9s*Ra?mR%tbnibaiHusoZCkmwPcg zEJ=D9qU7c!2zD;>^Z6)}>4knJy*%lSZJzVZiLM1zr5CblPn|OJP;o_LVNXUj8i$S3 zF1J`bt6_zf6?YFRL2dT!$*MPtYx`Z9UsWp*mMMdyv6bvrtsu8U0d!3u+408dwXySE zpn=}7#y#M76eD|v$V<6+hBKcGn!qi51`c`O3AyWucdo#8vilE!_nueT`-MSTw!iw` z3j77Y8e(rbiPt*~OG1je2BUQUY;MMvC*7kN_sn=UKnP^Udwn-gx( zBb&%M#pBAjhZ)`<{e+K~vg2J9-u4Q}e_i22G5w6yGdE>bX0dS0goj;p-tge9CcTbF ztakdX^d~VW9>@DnZYxC<2E%T54nD23s;CTt21${3}q^fHH^L~ITFCYcH(2O>&B z=l1LOoU5B#fLsxu#^o4?XEVb07%0jub|n@#6CH@D2v|H zQ?Kd~0a&Eqx*jJmA`h%;rkd2S4iK?^vu6ad8nD?DPRh73pPv$mZvF=|Z zMn=5yMx{^vIEL-*dTd&uP@B#9ch2&?#Vhs$R?HjwYL^8(NS_aNT)GhYY`tH~#^3PQ z8cI0psm%J6rfw*zZ@W7G3@%T5JZ_cyGFe(Z?^uW7ZbYA-&i9&AnYh`ukt-W<8zf;9 z8Q$}sm)_Gn+e_7Ulvn@r$IOB3oZH(FG75{6($F9&n74;DUWTV+V%yfidqk9md0WL% z-bFb#qj#8ao=mQcvRV<(N7hWWHy9E3+Ri3{{!2|uXXB!oeNH7NM3E$WS)zdLU2C8u zZFDM|6RT9#HlQvnatVh|kD754aX?W7mX9xDc zfr8tg-o9;J(C#^tjg>RG5&49*8crE#6|2PfdXQ;VBKM<}5li9A=FhejMqRz8&&7i? z<3Ge@|~;Up!}kUAcbogNJ+nV{eSq%@89>U{H`WuNO$mKy{{Kt7p7)5`7R6 zo|7M?D~E!>m)fUIaVwR3s*Ee-)!>&$1(Z4n%@=zQ@xB$4rRdev4NtcL@x5K~;NXI} z(s|5@Xv{(t@z6<;=&6U~XO8OfNW;ro*?Agycw6qLv^@J7=)p-vigi(H&3rag@97XQ zq{S-EsuMZDAX8IjsA8|OGbC3;{SsDPAr12D~y@M&~)jL#5FAjDb>zb)N3d;teJpNcHtVynVheP2V#0MZN?@}$r6jXZ8 zd5)^7P65LT4eVrJD${~;EOB*UMX2RYD>Sf}BW`hMq|`iT-lUQl{oFo;`r9Q=>6$N;Qccyam%ML?MAp#{+UFI8 zH{)fKSLvvQa)iTk^18GVano6cbrJaAmw44)rk_OEdPo+Fg4-{f1#;YCh)rUKx zd?3j4ArgD(sv*6YghybOVdI>hQ_)3leFMNF-hh-CN*kFeh3GUE_4_+!?z>?YtJ_hb zp_*FJRo?moe{AoW0e_y3sWr=z+c6aA_mn8zq!i8*O1%Ps>O}R}w|c9aTN#3HZR*zb zvF7V~q)CY4*LrjFp>09{*y;Oz16`Z*t~876%CwG15l5G$j|C0Sgd@fK+lWTG>2}Y1 zZl#(`OZvFY2ve(y(S4TMK1+(ys-mkx6Roj)?|Sgn6!TY3DM}767te`NH#Ex>u2fVK zbUg4-%Ys=e3Gp6of18?w(oL^}aZi&v?Jn)5kFigWV=12vi_4>H4b7!?MUzTTPo%Ux z;w0%>;_!4VKPdQ}4#X6^=9f7A4oKAywScw^68F1ZA<=est)W)|h3#eX(^@rV))EH2 zGi6G&r%nwFfWCzd3ZE@+%2ipov3V{SOh=~+RgjPXTEdC3l!#4uY0ZnA!DO_!+*0hd ztrRQz{pH)oMvxpv%srLjcm>EzPmn@~v=$wkiNdkF!(`Qzvl7REpo=`b5SNkd;pugD zgKr-K^e9ArM!nTlk_j$R=wuCB-x}4B#XxK8*DLKrv{ik>!!fc8AUz2Jup8P}l;tw0 zx|-6;$Im$+Uy&J*Uls|y|G7q@NJ=|Gt5CeMU%W9vgm6JNy6#MQa{o$vzV7(j0h_h( zUx0prz=st#=brC&YZN`r8ch?P~FD;s?y zIb?CupoDDNT)H^h*>j-Hofoy17%y8)rFe`FUdf=-SVh(C^Ub#*-+Vh!hKi{%Vgq;Jmk*eSF0A3byFm>ldU9;ZmbHqZ2;x zc+oQuGKcZDTxpY4Df_p>5NWQU$Ctz`9eSc6lKOI~?0Fu8(zqmKBp5c1{qjgRjt3jo zv{vnPsPK}Fezh@8|M+?DJPBff%9PVSuM|JR2S&lRjV6>U5YHP5Mq^8X{<#ZE!|t*w zs#ZLIZ?m5C_YVvkG^wiUimIxrL`Mi@zJkxgW4awo6yh}i6pQtmi+d0PfhXppiNtmF zqc7DXcK4jW6>?P!R>Kb`!oICzt7Insw8KuWw6CZLQ7Ln4V z@)-_6qwH=#R{u@CkC;h1YKU)eQBmBuY`@AA*PK^}PHP|6_fU#$4qj<`jNPU&Gl3oh z!mVzTbi}6DF0C;e?R5P*b`1Z3D3BlF?;WYmb%DK zzPmKgQ|EvLFYgR4?t4S&+5|@%@HR_gW;b!0 z>UR4H->{Zwzor&FGLkEc8bl8f^}j_a6EKmYFtS+d@<0yYeGr>cccdR(fm;_bo+xTz zv|B*ta0|t<^@<$fV`X=Wy`w`9Pvrd!r564ITq&N(h-XoKNXo5K3&01G%-`*{AE5S` zPuYI~_Wd|}`48UM{sKt391)K*5IH_zfw*WSGLi~Z1N$yCVrWkNWk z+?PWnI>?#GvDsgl<*vH{&;abyX?ox}`n4ZM(%?Tk{|LSZ(PhstdiIDW{N>YIa$fz6C|f5(*$XP;7`suBRMxYw}42_p@F7pf&vm6Xfg;0p8o4R?0fItRd=7Nd+VNu z`?hM}k|G7}%!>4!-442U?JMP(Cjx#k=m&La9eK%mj(D&Ry}vsO#G ztl9@5b0k|EV+ozJg)4f>`#CLRcVq?E*x48B`u^6EC3N%?-T8@997#9uSdec-m$^61 zwB6<9F;qD+?Y>%aA+|Vx29iCQj@JZHLFRJ?#3rc<24L?70W0NLN#THgDKWMaUjmnh zb@$ybM3?zni~;k;UZRE5ie${xOd5Yjd?Mw?&WuD&b{5QPvzt<}y2D7H3eWE%{>9k|8 zkjm7FBlg6aAEMIv-bvz@&Apyyk5t$~UM=D%M4g^m9{i|Ehe}CY6(vn=kA#T(Oi z!Lxp=wJglfm6@i=*lljAslpoHi|v-(!e-qvSg&?#T{b&Vs06i09b9I0v2wQ_v#j1e z_78Myy^w<-4-woqS3%=tOE-x3z3SN)IP|L+jQ#2PXuuylVT0a{Km{C5>RWvLxc==w z=4-nC+yVaOkQ{g;w>ek*`WEHdz3KSNKYj=r^h^8bvMTTSR9B)EvJ%=k(RCJJBit8T z1WS6Nc|pG32c{z#xQ0sY`A4wrRqN0VWh|^)84lp#Iue-U9pee?(3H6?H^X7tW-S{? zL4?do`SuvXe$Rf*q5ic_A_Yxn(!cxP`>((E%U}w}XRZXa@<=%D@T@_odZaCmMj68< ztg@hz#gzACB6!+YJ4k03b4NgE4K!P0&l3Xep0~r6@pX(ZMh4|v(ASzio`-wYS%9?F zFW{Dn%xTjsVI=cY)O2*kw8L4(>8YZjUU&O-X?Iwr_yOY9`G4LbXSo*R|J_!9J5Yd`J!*0wf$=y!N44oJ?*ngzR=To(N;GTa^b z`2>6wy>W}U!=a9fd%NknPt=uL9ABOhxB3M}`Sg77f8E=f?|uOh4ta7cf}uu*t#5^t z)i-gXxjz$ERS%$%o=e{N9-3c8$UfpZsYFS6?~k61qnmNMC6bvrW0N^85N(YP%P0;C z=5Oo*;uimxahU(7r>9my#_C)u)_3ZDK{e5q{ubuxspuE4;zu&(2J03(3(g%; z3|R3J9mS0kcW2gS7?{0(Hc)_()hf>L(dh7W8-4L@a}{u#W_kLGg)Z=ttEawukqt`j zbHKJU^XzF!HM&ZDB%32hk3lisyz!mt8@|{k{lT|9i$4V7-hV3%lvcAudn{jmmVs*y z-HRs6M6T`|2AuCi8PmIWPNR7$0Zpz1Eu|HSlGCrf+4i==TE{+I{zadn9j<{2tGDx0 za~k$qCn)JXVTi;S899_%Witsj*oi&G+u@W&;G3Ste})gMZr_WRM=rnY*inkK17%tj z;aWAXoj*V~^HEz2&~t^+%D{Xbz|pGs0TEKrZ)BH`1*QjDHgXkD*CW9!rcN#B8q}TI z(A;15A|nA*Cc1y8zO}$_yVfr%Zi}qTi(jdAQ{Hxs8cNleZf4*3zBWYlzBB zNV2M*h(aD?Hy2h0nX`o>P`zy|Rt-x{T4L=OvzYIoSijQJvNjvT{+bH|GG3D>agJFk zn@}rqem8T^A;u(};rUOwL`3{6?q>)a23*Mu+)*ZJ+44(Q@ULt&<&SB4HL57$Il>Kj zH$w7Pk`lh}H|%wCJ98K124#z{Rc`iCV!?WlOvJM1`p?=MvNqTKwa=HKj@x97H-O?l zc)sz!6F$Af5SzJmWkY5f^*pbPVTyTSg?U*j`w2phA(we{%UKuoa2M#c*?a0%3rU+s z*Sxx`e`R%`DL<7N&=I!0cL^2mldnfwIi{&lzej0a1V1;@>|A!E_MT^(;Bb8@HS zSB$4c=ZTiL77reJcYwvX5SythXF-x>?ON7#e&Qv{E}==YQiJ7Dxj76Mf@SE;Z0rxT z=NTZVG_UM*vT}?Y4n$CRg~g#g0%|I=b~J~0tTO8xG)4_C;s_hW?TCGz^o~)}{l>A~ z^0jn=Zb)$W6>Xl(V_W1LE{M#^u*5I(FpY9I?aU>=Xvk#IiUchR@&)IgGv8RQtXR_h z!E*yD!mh?cPj5=abB!i9s%VTkERQmk8Li7xXGVrHaI{Df$^J>#Oy*Y3J(_NWoQ~gz zIhXtI%l*KL(2^G8nq!oW%}SO8x9}jTuteA(=f~EVy@i9W@8|pNRYA`Ky!7iF^`jup z))hf~-!4wVZWoFHNxaSyP=yv2t6u5`C#Xl6>pJUa_OflzNVn@*_qkU)VJ$|uJcp{3 zS?Zb_!^ON-ir6_sw}C3wvw~>et|9sl%-8prCk4W738U%l(n1e=L@ z%Cp|31dIp3KT6*W47G2Lc17>4W;@|3!2@7>Iq zMPuI~{&teQXZv;SFwd7@76hu{wOVJ*iC{r7R*9Gx1Fu|uiV+~i{gtb#c}dc;-?l4Q z4hcGNg8kjmcFkDnaG`<3Z$hh&Bs`cC43S=fW#bshP5}nq)rl>m8}Fy5_BX`SzmCy; zN0KKCAKcKp?`A4%F(mA+Bh0M0)ZdYu4xHkwyC&eyZQGGAt#6=QWbd~N_rr^;Sy3Hi zncfF2ZBQ=4EY5!OdD7}0ZR?C-6*pCnn!Ia>K|^8b+Pdrvt79(g#}Be4>;zZ!lc_U` z^-fKPO|985otd8<4iqW&Apzuo{nkb?$V2j0C=N~S+;*1E$)nd*5+8ai8dh`-)9VGA670gt38|K zz&vE%(W+FZ>9-k&iQyPbZw-v_`(<=Bz&Q2);slBIr27o#G_hHm?FBuAGm47M4`Jj* zUJ7O&8id=~8iH_KdDF*Nl3Oj|&4EIc8z$f$4iD) zw@pBeVY$e+OAy*VDecqIVK>gp^Zk%BDX%mlG8#1K>p~zgyu@1g9W=E~S-q_GJKyig zOz8)OGQVVpQOBCp^NdrPacjr?2;w!1 zw7!f}bgDPnb{puZ{NYg*mzIUMWyUabY5fF7IAPD2xD=WwhZDvN+3Kh*+nNsRupAu<-PI;&-%i42q+X)>z@~(wRK}; z-@L2s#WH8!ii6lHY9u|YZaPu869RmrnzbcnWaA#h6CR@QaY4K_Q?A2n_BJ5hYqz44 ze+edb@5n@$G2}?zfKYn8O;vckRdPIaQ-?9T(+N&AfY@vN+iVC-*872{yAKVTmESf= zDK@#1!8Z&iR85r$*I><$jGgDppC&!J>fBmUUD<4nrxo$`p6+gQxj+mW$|&ic5q{WF zsHi4kXx?I<28{H)x7}O>wF+@Oqr~UvT{tI}kO|H47Z+&_{0@K>>7B0q!OL3_=@`vi z+!Y!Nq?ujXJ5p!XQKkBH&p+k@e{B$FMl?lXXToLe6J544l1AILP9rb;p6%A?XlXFo zuQK*=-Ycf0#SzD>h3l>Sa}N(Dy7Ks!Ed!=uDiyYZWpXl@XWR5SI+;8&ce9Wqf61IG z_ix%B{$`hK@Abg0$eRGzaCSZh+?%^0hV>o+rSzZJl~tF(wWm~>XDTL~S@z2_hKxA^ zZ}&f1d9SU?z(cDQ$C=r78*5xjHiz9}sb{2#)UZ;J41?9mzC+{kZLLNv3ac&8&u=dp ztlBu;?a!r`WV1dX|KNcbJ_W%~SIwuSEvt;3#CalIygb!^RnLmNcr?tNnkV*iO<9Ck z%#3_vW@^7z1yVuHxAUngHmLoK${Xi~W0XC1qu-men=5}<@*naPf)yfsg;bCp7X08W zx_0*R5qNy3X(7cogDYv)4* z&=;MA3yNw@#?{WQb-QQqlH0n|#ql^BdTP1&*i}AC33QE=D0U6&A!m6&HcnVWoI%Ft z%BDAsy8{0+c~w#WiU-pufiZY8SEXcOUXQl?DntZw#THw(7Tjj0=cfJYpw-4*Sk?0-NgW@g5a5^9`rTb&9$Prf=4 zTdcY@szjxNksu&auU0hR1q52+J=QJQpwm#s)?sGtX%86p1gVKpzLrVkH13>n9$vy{ z+Mv~=1$s=>`~BK6D_l)FGbqS_?cS-Zv;pX$X;WGp4P<&PO}L;S@6~AQ*x(JK$UCNY z`h}p}&e5n7X~!mgkihKY3*du~Gt;6XM=dI=^;mISl~d+Af28o)YB|iM;q+%wCQ+lc zzT+;eo8?rCAt`cxVKX}zam8=&ioC`NYv^{GJKi^p0 z;Ap*FlfTc(#aUBpbwo+tG%4R7I$eFyxqd-wJ3Fn$Rnz5YpxgJH=kxa=3s1Fmek)ZA zDdvy`2**oc@r)lS!pw`+5bKv%AxZvR-~JF~V%4I(G~_g;(|0k(jwdVD4>zKE32l)g zn}|Ig_=D%pjC1`MpulG8n|?2N>ehnX8(?axLrn8qYh9W^$k}6fWJLj_zNOHcV!0-c zSdGmMJ2QU4=n|4|h;uVY3w<%o=b@NixZthP*ywgTyFl`QyFp7tL2Tebv zGi7|~>zcv2A3%9VRtd_UUTN|_o^)&=nfR>eTiCQwojP8bM>GXgu@O3l<{`r+8(3W} zmnYV}2u^R}ey7s_h?^W&+N@_U(}HAps{|mlytyW=#3rg-hsv)9>r_ZO)4E=6!W*N{ zIb&LfS2L{uI|mhe?1gU_S(FVl{5lk4J8!8qWO(g4t$HoJCw@>ZamaKg*GaiNa;AZq z&P8@9Gp>}5S6o`1&{bs&9n+dsYK+4!dkKsm)C4|bVT_hdpXTZ^P18}k(!n%Vm_Dcj zlSAiee9VVj(ij}Sm?7+O@|Y@5obYtibT{81)kMb0pc_}vFG*W0-((wbsZL-wZhejZ z;9ZCUw`)~b3#^p>;NfC64lUZ4FHhp1?sxKecTxj^#5m7`OD<@-XRWYpy381!@79kr z7&m=(idm#GOrY>y!oIeolDNk1S7x=hGuYMfy!K2)i)+;t_}C3I5K!2nV!JIUXh=g)TV##v-onpKF2;qM$F zbziY(sL?Sh(QT=y#f?4b>ha!R5*Zi7=61NXfLJW47P<0(f?g#(S=Y5H749&1YPqX4uhs|;>rz%XKC&aes}Ry8^Xzv)r?BzW`@RZM zVr~0+_$_tZ42WMpYiNb1)QgiWwn3*Jc72!{174)>>PJ5klh3;pyZSiCtTiZn!#aO; zVbU1O-Wd(>>c^5Nm9p;?*(ZK|NU5Z%CZ+zD%jV%z9}n)IJk-aa^-FS{_pnawmFmXD zZ7(0b0Gq750=V3CQC_KmG&E;IFObgdkH1}~jI z?>Ilb?hD!orSwvq!SyEu|7GmPtn|fNY&W11GukJF;$aK3Q(v%&5FM~Daj>J$@g^g7 zle+u_8XW3JykI1IGxrrI!x4ka0_NwVZ}q#Uj1q%l_uo%smEC4`D+Hzl&hWh-d!kKP zyRkW~W}unAlF2^WI9wkSayu4R+5!&cs3ENYv)Nm5o?6hwJ9>KyCb#=EFFDh;ZdmN3 z#**3=W6+@Ky1OT?cn{Z}asI(eWj(!*am8_3gZ87i^hD2xA&8Y!paSNCx+F<0E&Z+G zleUN!BC!AIAv}5#BRPO0NSTF=oLTVH|uhs5lGT$uyapeBaj>3Eun0 zKe4!=kf?JCuzBBlwR#O)f+=g7itMbaUD@IotmZe(Cm6EgzZBj(bhbLi_^BIzP2Ndr-M8JfSXqMB|Kd*MPPR84bW#UAgU)G!?nfUs}O$}nZTlq7qeNI5v z)Of2?+Frj5bXvrKNONm94XsZ#VAvuSjB|U)n7Agnq`*u^X3y`=N%+9gEOq%bxppP@ zXm7OqOSHbw@WJC|@#ijBGMa_lx6=gf3Tvw0!}ockKlq@^R@>Vaw~l=rYHBe}S*SQi za)&a>05Bu-2%N6w@ofe^XvMCTTe=?R0B|EVS5sZewLLl3hFlxlHj#)~l+#o<%z1jv zp;COphCftg_P~7`I%GM*iPC69LyM`}`MrNstNy{Okrnv$MQ)h-_bGrtb2qyxD(S0D z+%qF}O!!HWY znMc29L|zD(C7%uk+hZ#*Vm0gH;2Vu~oho``pOCIXTExq9S%YBB`PYLYuEJf}dEWTl zc|Q!U%E8Jbo(QSlm+q}|cfGMMMWr5IX&uz2#Ru)CAO#l5o}NG{n==34sY{R-flEnd zsgL)AKCvTyS%;xC)U-+LOTm{1>w?pgSUG?1C9_qJTfwe$H&Ww@nA*zhfK|3+zA*p= z3S7Qf{t;ai98+u#(T@15;QDQUJ0y;={RSTQ#7OoH(AQXdmRiSJfY;wwM!BahOwjbh_~VzUaE^*dnn(BKc>ob!Z> zBeCPXkV^j)aUK%Wi}y{p7dni>K&CZE_+LWgRB8{Ovv1X76>O~Gmq$Y40qtbJW#nz! z1{9AQ>@`KLD@!Zeti(_b*oIe!>!dUNMjX#qTa&Zt!RN9&A;@O-?1JS0jE_t!MoBFV za#OAD&G_^tMAovUBUvPxAa?&JT@I>)GY^_IYO_@HQ!W^Us;5D7*U;R#} zKt$WvAo)k_D!dGN@g8lx`2otbB=@K0p5G+ujG9YEPXf`fRaSbzEgXf2W*A zqL%Jvl_WN`>7B~Cm~DgFmsr9vPZKdH1C(N;!?7TyyF^BM+%LJWqqt+m<5@$s7z$JQ z0O%LN=$a(3_u0{K`F;ZYTF7iau?S`7GUzt#vdZoHIvor-|ASW-3!u*og_Rd~AeBXw zT_zlkB9>ULA1U`ypkA?Zjw7Ge&Fyx5G!`KxGakGF4|<2aV?N4=Emkt2-SfeO`a zb@OU=T4#(8FziC>#kG~SNqUPCPa8lE#Q?WGQj5M({;CZSHrWEcT3)%yx^t(1&_5&Pu+;!qRYiK&NR)8;Z{wat zCddU$+?@S(v;wWBX{kno?gZX>XIgh68}D=Sw|URl8>suzYNh}FgU8X!kGvYmRq6y@ zLu@7r>FG&-9(TvwmB;{%ZwA@X=6*cb>OKnC3Bnr!rVsj+!{8gFqk`E|dnqaIx~~9} z!Fv@Bki?9b&}+TnB^6@Z^F5yjy$JZCtiEg^oe6$!%*-Qk>`R-*psT@yGR^l_NWZ9? zns-6TE;^dU5ayDr&{^h(?;w|fHZeACk4v#_#siuE~{6935&?&E#Dz)L)I ztwjPs>hqxKD2K~Mwf|liL?1}bt#h?2m!+5DQpvA4V_=mct_*D2>PDKMcwPK(ML)ds zHsg>#eUF|<>Z57x*(r((W4y0(K>cXsT#JM5+rpT(626%E!XwR%i}zX12pas7#mUd$ zJUQ>~+4s$K11>3NsgJsnSjd-rNv$=Y(A$awdHrL#8;^|EeIl*Rvp08lsFcsjq>x?t z_0o)$(72?H^Sx3B?Cgv6Bc!Ugc~#}zqJv~5(7fc}5XHrL?se!iW+lDu!EMPlup;Xq zfwW=S-YbpgKO>BF%*OU_fk)jArnr^2K(7~g;ZKpL?ZyR;zi<5cK|govo8V*Qo>}Yk z&#F7YvBKgmSTLR|w`3e(L86Ulk2+mwXA>--f5mHu4E(~MSrY*MGQCoNP5*UyZJ5AI zJ@sfR4l+&|JeN1xgCAViDa^RQs&@re-Tbqh$ z3VH7%ek8!&0UG^z&^w$c31Rd0pXE?!YAc;bR!b$JFWzK6KQ=IQxjQbR9o_{zP!9UI z*%ZR`I_Dn2BR$@2SM#^D{#|P-%J1TzmVO%4l?Z$O(L#n589%aS3#JE zHBRiBMa@MOODB)QIV*F2jfc}z2XJvwOTPmOK95eYXUh0KMJz5_fKBXQZVrrq6up@5 zO1>)S1Xa(8Ow2hh&RdO@Ur$x$J=;tys5u54**PipdLM%aZigQjUdjPyru^+nN4e86 zT|o{#$6xStK{Yhj8(m?S48t3qtaQFi%l$ny=I1zm)u5Y-%@xPozGJW7r&*Rr(UTXS zh1xBe0PqDNV3PWoh;olK7qrzsbb9X9(eQ*PiH!sFqsyGa24-i_@G1%+orTn@HB!pk zNiE|j_pA_XkD)eDYigQZbEQ;D@R#^uBi?YU;FHJ3JW?0HuvCIEs0}c~pqUFQTnH5$ zNR}>oX156OEsI8rvqV*UdXrg{teTBEvk;? z5=gTf(IDR^pP?;jk(RX5r^-XEIZmGV3OVE?x{%$fnuLzJiL3aj0DhO!A01&b?7J?d zR-2Wfea#2)y)nP`q1F%ip!6IPa+b?q(Wo+%O>MPY%JFhF$eOFo94Her?3{G=Lo(&8 zS<6O;frB3pYYqG0a_!+PoFhfi-K}wj81;ifEkvignPL^Cv28X`l|^8OkX zE+jmxqa0@US4bo$^%np~NaY_I{4QOVz|57_zP|c0mDBj3=*zuq&%(A|E)8CZHz+#m z@9dTKluF3E3z5r}?{=xmtAgH`@>|SLWE;Dj=2XuZx@E4XHjAXB*s}e2JNRY|g%|(H z&`ixIG0uD6fmq>E9@xIUF0q5;_*UMqO!ah>>~@IJAG z%Xr+zv!~_zc(c4uhmnXCjm)*w3-O(P-MMz=N&{K?f@b6_z2UHex4%X8{RMx0C=1@#*WwKeU-1znVteLTsYi2f?ZA%N^W_^RP)p=OnT2?E7w_|5g zQzCU`y#l3Vz+xJ2RQq@~J*!oNEKPh`>4&PyeOV^J2A=(b(=^Jcu&94WE3p9KOQ zNSi#p?0Dp)KWY1=ha^5y!HAm4$^V^5Y|nBWdP&(GWytx@xz2x;|NL(=Mp%P_tZNBY zC+%cfWw1y&cCX$SSA$X4+~ehq^bzPD8wej=?QYTv+_ij7M>?og2Y6jr+Tut=VLrUQ zU1@Bjq4lAq*O*C^j1ZO@n_5HWOYTO_eC~d*Y{wP#e9d223B{3EQfn2q@2O>ZPu3#H zKIHk}mG;hO>fr&qxNW6}IJnfeLY|@O1md1&QsMn@?@09Z0)xJHvVw?hIA5oouAfn~ zLV|S);++{kp!pSdZJ6^HTXo!V-6@;g0)33`+WqjFAz36`b-kw;aqqO7(uJ9~eK=lh zSRD}W6UDVOb9fke^fGAr>ZR0V#{x_&TQ6iz(X!t7Iba^`B@Ib|KoVN$p6ACF)b}$v z->J3&;VZnvX*ifQ$-^uc?Mi>iWVJGVYr19_+!vR8FX~KKgCOLRQI9vbTIF=F6UBOh z=99jw;^8j<9!yUo-^}xUv=OWM?54u6p4vG0tl`^cFNf)HZJfABgE;;YP1B>7=wWr0 zPe|4@p zokbS1#9N*pl||28k4ShD8JwuJ8FmCU9B77tgYUrbobVp#zh-^F@PN^jTBZf1OvuH| zsS%QwcdyUAABVTMVp#qJ!o$0>fY-JC?=;H&2U?HARBNYJUbL`-x2AkYOgzzq%{(%- z8KQBT(6cc~50`F&W@+|%qB|BK*J>h2)qNqu(^34owOJ}@H4&PudllKjUl(LG@o3>L zOS$dnm6nu$Sw#3JCnBV@G37iR&HhQbnQ0qpk*+p-Okc^f)%@C2`^gEU$VCXg>&vBP z|7p;!(dY=R#}&=mtc?aVJ!;8Iii;!aC6v}+6ipoX$}kYTfQR=$Vxq%vXHZAzsZBdJ z%96HfHV(X5ThXFqm(%1VZSav4jz`?uZ7%yj=QZ6IFzrCyC^NTkgw;8kxiB=389>;9 zqw61vd#G4D-GMPCK_3d~2m9^3FRlK>`ss1|wiwZ_B0xPgLA%GIG(^HKK}3~=%EQVP=fOCbR7TjPFB=HVCJa6y7K0@xjUb?t0zwU^}|q zj9GC8z(0p}63cyyxF*t3RX^d9_5t0)NE0X4Lu|gLQA)YYJU}NBs0Kq)5lR`RYeO$g zDf(bOZ+vLwP0*fP<)MSCOi3P|59end*GfOqljj2H3XYSG2@W&Gl7knO`ioimD9|>i zuOIEV7S*IyUor}f+G#BSWG0>y)V~=Ok^Wm0o*mr_4#wWIXWI)HG3Wp}8;siMC7n5y zv>8_w1jy)d=>pQ|*W6HJP$m+SnfnA3^(6BVq8hR@0fIArJaBKEfTmp3407ygW!SW9 oRBEFNQO_hr@KErA>xOjN{J+Gs{Hu)K{~!B@6aF`R`t%3&AC+{`q5uE@ literal 0 HcmV?d00001 From e6ca5e12017f8d14a39e89268ececb548eb9dca0 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 18 Jul 2024 02:19:09 +0100 Subject: [PATCH 02/24] Fix some comments Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index cd9827aa68..0f2c3a2cc1 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -18,7 +18,8 @@ When we built the Kubernetes lacked better features to support distributed machine learning (ML) training, such as SuccessPolicy and RestartPolicy (FailurePolicy). Recently, the Kubernetes community launched the working group Batch, and then the working group actively worked on evolving the batch/v1 `Job` API -and built [a new `JobSet`](https://github.com/kubernetes-sigs/jobset) API to manage groups of `Jobs`. +and built [a new Kubernetes SIGs project: `JobSet`](https://github.com/kubernetes-sigs/jobset) to +manage groups of `Jobs`. This document consolidates efforts for the Cloud Native ML Training between Kubeflow and Kubernetes communities. @@ -27,11 +28,11 @@ communities. We often implement features similar to batch/v1 `Job`, such as “suspend”, on the Training Operator side since the Training Operator creates blocks of plain Pod and Service for each rank once -Kubeflow Jobs are created. However, if we continue taking the same approach (re-inventing the wheel), -the maintenance costs will continue to increase. +Kubeflow Jobs are created. However, if we continue taking the same approach to use lowest level +abstractions that introduce redundancy, the maintenance costs will continue to increase. -It would be better to replace infrastructure layers with `JobSet` to avoid re-inventing the wheel -and improve the Training Operator +Replacing repetitive infrastructure layers with `JobSet` would help to avoid redundancy and reduce +developer toil. Additionally, introducing `JobSet` as an infrastructure layer would allow us to introduce batch workload features such as @@ -69,7 +70,7 @@ Based on the above personas, we should build an API that everyone will benefit f - Introduce the `TrainingRuntime` and `ClusterTrainingRuntime` APIs that will store blueprints for model training and LLM fine-tuning using various ML frameworks. These runtimes will be built - on top of **JobSet** APIs with additional functionality for special use-cases. + on top of `JobSet` APIs with additional functionality for special use-cases. For example, training using MPI orchestration. - Introduce Kubeflow `TrainJob` API that allows to reuse these runtimes and quickly start a new training job without understanding complex Kubernetes APIs. @@ -77,7 +78,8 @@ Based on the above personas, we should build an API that everyone will benefit f - Create community-supported `ClusterTrainingRuntime` for distributed training with PyTorch and MPI. - Create community-supported `ClusterTrainingRuntime` for LLM fine-tuning for various foundational models (e.g. Mistral, LLama-70b, Gemma-7b). -- Work on the following JobSet improvements: https://github.com/kubernetes-sigs/jobset/issues/463 and https://github.com/kubernetes-sigs/jobset/issues/572 +- Work on the following `JobSet` improvements: https://github.com/kubernetes-sigs/jobset/issues/463 + and https://github.com/kubernetes-sigs/jobset/issues/572 ### Non-Goals @@ -431,7 +433,7 @@ type TrainerConfig struct { NumNodes *int32 `json:"numNodes,omitempty"` // Resource for each node. - ResourcesPerNode []corev1.resoruces `json:"resourcesPerNode,omitempty"` + ResourcesPerNode []corev1.resources `json:"resourcesPerNode,omitempty"` // Number of processes in a single node. // By default this value == number of GPUs in resources limits. @@ -532,7 +534,7 @@ type S3DatasetProvider struct { } ``` -The following table explains how `TrainingRuntime` parameters will be overridden with the +The following tables explains how `TrainingRuntime` parameters will be overridden with the `DatasetConfig`. All parameters will be set for this container: @@ -724,7 +726,6 @@ metadata: spec: trainingRuntimeRef: name: pytorch-distributed-gpu - kind: ClusterTrainingRuntime trainerConfig: image: docker.io/custom-training podSpecOverrides: @@ -753,7 +754,7 @@ BERT LLM Fine-Tuning. These blueprints can be deployed within the Training Operator control plane and stored in a Kubeflow public repository that users can apply to their clusters. -Platform or ML engineers can tweak existing blueprint, based on their requirements. For example, +Platform or ML engineers can tweak existing blueprints, based on their requirements. For example, using custom configurations. The Kubeflow Training Operator can maintain more Training Runtimes when the community is ready to @@ -762,7 +763,7 @@ support them. For example, runtimes for [Jax](https://jax.readthedocs.io/en/late MPI, TensorFlow, XGBoost, and PaddlePaddle. The `TrainingRuntime` is immutable, and so to make a change, a new version of the `TrainingRuntime` -must be created and then changing the `TranJob` to point to the new version. +must be created and then changing the `TrainJob` to point to the new version. This provides control as to how changes to runtimes propagate to existing training jobs. For example, when training is running for a long time (e.g. 1-2 months). @@ -951,11 +952,11 @@ Example of usage: apiVersion: kubeflow.org/v2alpha1 kind: TrainJob metadata: - name: torch-distributed-multi-node + name: torch-test namespace: tenant-alpha spec: trainingRuntimeRef: - name: pytorch-distributed + name: torch-distributed-multi-node trainerConfig: resourcesPerNode: requests: From f6692c70319dc50d459558c5a646a036c74f399b Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 18 Jul 2024 16:55:52 +0100 Subject: [PATCH 03/24] Add user roles diagram Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 9 +++++++-- .../trainjob-diagram.drawio.svg | 4 ++++ .../trainjob-diagram.jpg | Bin 153020 -> 0 bytes .../user-roles.drawio.svg | 4 ++++ 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg delete mode 100644 docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.jpg create mode 100644 docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 0f2c3a2cc1..46c5d1054a 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -102,9 +102,10 @@ We propose these APIs: to configure infrastructure parameters that are required for the **TrainJob**. For example, failure policy or gang-scheduling. -The below diagram shows which resources will be created for LLM fine-tuning with PyTorch. +The below diagram shows that platform engineers manage `TrainingRuntime` and data scientists create +`TrainJob`: -![trainjob-diagram](./trainjob-diagram.jpg) +![user-roles](./user-roles.drawio.svg) ### Worker and Node Definition @@ -409,6 +410,10 @@ spec: path: custom-datasets/yelp-review ``` +The below diagram shows which resources will be created for LLM fine-tuning with PyTorch: + +![trainjob-diagram](./trainjob-diagram.drawio.svg) + ### The Trainer Config API The `TrainerConfig` represents the APIs that data scientists can use to configure trainer settings: diff --git a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg new file mode 100644 index 0000000000..74e041dca0 --- /dev/null +++ b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg @@ -0,0 +1,4 @@ + + + +
TrainJob
image/svg+xml
JobSet
image/svg+xml
Storage
Initializer
PyTorch
Nodes
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
PyTorch Nodes
Headless Service
Download
Pre-trained Model
Download
Dataset
LLM Training Runtime
image/svg+xml
\ No newline at end of file diff --git a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.jpg b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.jpg deleted file mode 100644 index 08ab3508a1a4eda202a6963879900d1280685409..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153020 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 diff --git a/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg b/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg new file mode 100644 index 0000000000..e673c037bc --- /dev/null +++ b/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg @@ -0,0 +1,4 @@ + + + +
Platform Engineer
Kubeflow
Python SDK
TrainJob
image/svg+xml
kubectl
Data Scientist
Create TrainJob
JobSet
image/svg+xml
Training Runtime
image/svg+xml
Training
Nodes
Headless Service
Manage
Runtime
Fetch
Spec
\ No newline at end of file From aaa88f2c6ff65ab047c5a3b9118e762bb83c1da7 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 18 Jul 2024 16:58:59 +0100 Subject: [PATCH 04/24] Move diagrams after design Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 46c5d1054a..5a1a5dff11 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -102,11 +102,21 @@ We propose these APIs: to configure infrastructure parameters that are required for the **TrainJob**. For example, failure policy or gang-scheduling. -The below diagram shows that platform engineers manage `TrainingRuntime` and data scientists create -`TrainJob`: +### User Roles Diagram + +The below diagram shows how platform engineers manage `TrainingRuntime` and how data scientists +create `TrainJob`: ![user-roles](./user-roles.drawio.svg) +`TrainJob` can be created using `kubectl` or Kubeflow Python SDK. + +### LLM Fine-Tuning Diagram + +The below diagram shows which resources will be created for LLM fine-tuning with PyTorch: + +![trainjob-diagram](./trainjob-diagram.drawio.svg) + ### Worker and Node Definition To better understand what does Nodes and Worker mean in the diagram above, @@ -410,10 +420,6 @@ spec: path: custom-datasets/yelp-review ``` -The below diagram shows which resources will be created for LLM fine-tuning with PyTorch: - -![trainjob-diagram](./trainjob-diagram.drawio.svg) - ### The Trainer Config API The `TrainerConfig` represents the APIs that data scientists can use to configure trainer settings: From 39c23bad88288327b3dad998534026f839fd4f75 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 18 Jul 2024 22:54:13 +0100 Subject: [PATCH 05/24] Update diagram Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 5 ++++- .../2170-kubeflow-training-v2/user-roles.drawio.svg | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 5a1a5dff11..494795f7cb 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -164,7 +164,7 @@ the following table explains naming that each framework or technology uses: - MPI + MPI (OpenMPI) Slot

@@ -247,6 +247,9 @@ the following table explains naming that each framework or technology uses: +Additionally, check [this document for the `mpirun` command](https://gist.github.com/vsoch/9ac7c4448dffe656d946edceaa58bd9e) +for other MPI implementations: Intel MPI, MPICH, Spectrum MPI. + ## The TrainJob API The `TrainJob` exposes APIs that data scientist can override in `TrainingRuntime` to create training job: diff --git a/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg b/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg index e673c037bc..f074f65332 100644 --- a/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg +++ b/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg @@ -1,4 +1,4 @@ -
Platform Engineer
Kubeflow
Python SDK
TrainJob
image/svg+xml
kubectl
Data Scientist
Create TrainJob
JobSet
image/svg+xml
Training Runtime
image/svg+xml
Training
Nodes
Headless Service
Manage
Runtime
Fetch
Spec
\ No newline at end of file +
Platform Engineer
Kubeflow
Python SDK
TrainJob
image/svg+xml
kubectl
Data Scientist
Create TrainJob
JobSet
image/svg+xml
Training Runtime
image/svg+xml
Manage
Runtime
Fetch
Spec
Headless Service
Training Nodes
\ No newline at end of file From 3b43220d5a4b6ee51bb7e51bd3173056efa603b5 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Tue, 23 Jul 2024 15:24:11 +0100 Subject: [PATCH 06/24] Refactor Model and Dataset configs Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 372 ++++++++++-------- 1 file changed, 213 insertions(+), 159 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 494795f7cb..7f34927153 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -271,7 +271,7 @@ type TrainJobSpec struct { TrainingRuntimeRef *TrainingRuntimeRef `json:"trainingRuntimeRef"` // Parameters that data scientists can override - TrainerConfig *TrainerConfig `json:"trainerConfig,omitempty"` + Trainer *Trainer `json:"trainer,omitempty"` // Configuration for training dataset DatasetConfig *DatasetConfig `json:"datasetConfig,omitempty"` @@ -315,7 +315,7 @@ This table explain rationale for each `TrainJob` parameter: - TrainerConfig + Trainer Configuration for the Trainer such as image, number of nodes, accelerators. @@ -360,7 +360,7 @@ metadata: spec: trainingRuntimeRef: name: torch-distributed-multi-node - trainerConfig: + trainer: image: docker.io/custom-training command: - torchrun train.py @@ -418,17 +418,22 @@ spec: trainingRuntimeRef: name: torch-tune-llama-7b datasetConfig: - s3: - bucket: datasets - path: custom-datasets/yelp-review + storageUri: s3://dataset/custom-dataset/yelp-review + parameters: + split: train[:5000] + modelConfig: + input: + storageUri: hf://yelp-review-full + output: + storageUri: s3://trained-model ``` -### The Trainer Config API +### The Trainer API -The `TrainerConfig` represents the APIs that data scientists can use to configure trainer settings: +The `Trainer` represents the APIs that data scientists can use to configure trainer settings: ```golang -type TrainerConfig struct { +type Trainer struct { // Docker image for the Trainer. Image string `json:"image,omitempty"` @@ -455,11 +460,11 @@ type TrainerConfig struct { } ``` -The following table explains how `TrainingRuntime` parameters will be overridden with `TrainerConfig`. +The following table explains how `TrainingRuntime` parameters will be overridden with `Trainer`. - @@ -509,110 +514,53 @@ The `DatasetConfig` represents the APIs that data scientists can use to configur ```golang type DatasetConfig struct { - // One of the following can be set. - HFDatasetProvider *kubeflowv1.HFDatasetProvider `json:"huggingface,omitempty"` + // Storage uri for the dataset provider. + StorageUri string `json:"storageUri"` - S3DatasetProvider *kubeflowv1.S3DatasetProvider `json:"s3,omitempty"` + // Custom parameters for the dataset initializer. + Parameters *[string]string `json:"parameters,omitempty"` - // (Optional). We can support the Iceberg dataset using PyIceberg. - IcebergDatasetProvider *kubeflowv1.IcebergDatasetProvider `json:"iceberg,omitempty"` -} - -type HFDatasetProvider struct { - // Path to the HF dataset. For example: yelp-review-full - RepoId string `json:"repoId"` - - // Whether the dataset needs to be splitted: train/val. E.g. split=train[:50000] - Split string `json:"split,omitempty"` - - // Secret must contain HF_TOKEN secret. - // If the secret object contains more than one secret, all secrets are passed. - AccessTokenSecretRef corev1.SecretReference `json:"accessToken,omitempty"` + // Reference to the secrets to access dataset. + SecretRef corev1.SecretReference `json:"secretRef,omitempty"` } +``` +Initially we will support the following dataset providers: -type S3DatasetProvider struct { - // S3 endpoint. - EndpointUrl string `json:"endpointUrl,omitempty"` +- **S3:** `storageUri: s3://bucket-name/path/dataset` +- **HuggingFace:** `storageUri: hf://repo-id` - // Name of the S3 bucket. - BucketName string `json:bucketName` +Parameters will be converted to the environment variables for the `dataset-initializer` container +in the `Initializer` Job. - // Path to the dataset. All files will be downloaded in that path. - Path string `json:path` +For example: - // Secret must contain AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY secret. - // If the secret object contains more than one secret, all secrets are passed. - // Otherwise, IRSA can be used to access S3. - AccessTokenSecretRef corev1.SecretReference `json:"accessToken,omitempty"` -} +```yaml +datasetConfig: + storageUri: s3://datasets/yelp-review + parameters: + endpointUrl: s3.custom.com ``` -The following tables explains how `TrainingRuntime` parameters will be overridden with the -`DatasetConfig`. - -All parameters will be set for this container: +Will be converted to: ```yaml -.spec.replicatedJobs[name='Initializer'].template.spec.template.spec.containers[name=dataset-initializer] +replicatedJobs: + - name: Initializer + template: + spec: + template: + spec: + containers: + - name: dataset-initializer + image: docker.io/kubeflow/dataset-initializer + env: + - name: STORAGE_URI + value: s3://dataset/yelp-review + - name: ENDPOINT_URL + value: s3.custom.com ``` -#### The HuggingFace Provider - -For the HuggingFace provider environment variable `PROVIDER=hf`. - -
TrainerConfig Parameter + Trainer Parameter TrainingRuntime Parameter
- - - - - - - - - - - - -
DatasetConfig Parameter - TrainingRuntime Parameter -
.huggingface.repoId - .env[REPO_ID] -
.huggingface.split - .env[SPLIT] -
- -#### The S3 Provider - -For the S3 provider environment variable `PROVIDER=s3`. - - - - - - - - - - - - - - - - - - -
DatasetConfig Parameter - TrainingRuntime Parameter -
.s3.endpointUrl - .env[ENDPOINT_URL] -
.s3.bucketName - .env[BUCKET_NAME] -
.s3.path - .env[PATH] -
- ### The Model Config API The `ModelConfig` represents the APIs that data scientists can use to configure pre-trained model @@ -620,59 +568,171 @@ input and output location. ```golang type ModelConfig struct { - // One of the following can be set. - HFModelProvider *kubeflowv1.HFModelProvider `json:"huggingface,omitempty"` + // Configuration for pre-trained model. + Input *InputModel `json:"input,omitempty"` - // Potential output location for fine-tuned/trained model. - OutputArtifact string + // Configuration for trained model. + Output *OutputModel `json:"output,omitempty"` } +type InputModel struct { + // Storage uri for the model provider. + StorageUri string `json:"storageUri"` -type HFModelProvider struct { - // Path to the pre-trained model. google-bert/bert-base-uncased - RepoID string `json:"repoID"` + // Custom parameters for the model initializer. + Parameters *[string]string `json:"parameters,omitempty"` - // TODO (andreyvelich): Do we want to support any Transformer ? - TransformerType string `json:"transformerType,omitempty"` + // Reference to the secrets to access model. + SecretRef corev1.SecretReference `json:"secretRef,omitempty"` +} - // Secret must contain HF_TOKEN secret. - // If the secret object contains more than one secret, all secrets are passed. - AccessTokenSecretRef corev1.SecretReference `json:"accessToken,omitempty"` +type OutputModel struct { + // Storage uri for the model exported. + StorageUri string `json:"storageUri"` + + // Custom parameters for the model exporter. + Parameters *[string]string `json:"parameters,omitempty"` + + // Reference to the secrets to export model. + SecretRef corev1.SecretReference `json:"secretRef,omitempty"` } ``` -The following table explains how `TrainingRuntime` parameters will be overridden with `ModelConfig`. +#### The Input Model API + +Initially we will support the following model providers: + +- **HuggingFace:** `storageUri: hf://model-name` + +Parameters will be converted to the environment variables for the `model-initializer` container +in the `Initializer` Job. -All parameters will be set for this container: +For example: ```yaml -.spec.replicatedJobs[name='Initializer'].template.spec.template.spec.containers[name=model-initializer] +modelConfig: + storageUri: hf://bert-based-cased + parameters: + transformerType: AutoModelForCausalLM ``` -#### The HuggingFace Provider +Will be converted to: -For the HuggingFace provider environment variable `PROVIDER=hf`. +```yaml +replicatedJobs: + - name: Initializer + template: + spec: + template: + spec: + containers: + - name: model-initializer + image: docker.io/kubeflow/model-initializer + env: + - name: STORAGE_URI + value: hf://bert-based-cased + - name: TRANSFORMER_TYPE + value: AutoModelForCausalLM +``` - - - - - - - - - - - - - -
DatasetConfig Parameter - TrainingRuntime Parameter -
.huggingface.repoId - .env[REPO_ID] -
.huggingface.split - .env[SPLIT] -
+#### The Output Model API + +After initial implementation of `TrainJob` and `TrainingRuntime`, we will support ability to export +the trained model. The following runtime can be implemented: + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-tune-llama-7b-export +spec: + numNodes: 1 + startupPolicy: + startupPolicyOrder: InOrder + replicatedJobs: + - name: Initializer + template: + spec: + template: + spec: + containers: + - name: dataset-initializer + image: docker.io/kubeflow/dataset-initializer + env: + - name: STORAGE_URI + value: hf://tatsu-lab/alpaca + volumeMounts: + - mountPath: /workspace/dataset + name: dataset-initializer + - name: model-initializer + image: docker.io/kubeflow/model-initializer + env: + - name: STORAGE_URI + value: hf://meta-llama/Llama-2-7b + volumeMounts: + - mountPath: /workspace/model + name: model-initializer + volumes: + - name: dataset-initializer + persistentVolumeClaim: + claimName: dataset-initializer + - name: model-initializer + persistentVolumeClaim: + claimName: model-initializer + - name: Node + template: + spec: + template: + spec: + containers: + - name: trainer + image: docker.io/kubeflow/llm-trainer + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + - name: LORA_CONFIG + value: | + {"peft_type": "LORA", "r": 8, "lora_alpha": 16} + command: + - torchrun hf_llm_training.py + resources: + limits: + nvidia.com/gpu: 2 + volumeMounts: + - mountPath: /workspace/dataset + name: dataset-initializer + - mountPath: /workspace/pre-trained-model + name: model-initializer + - mountPath: /workspace/adapters + name: model-exporter + volumes: + - name: dataset-initializer + persistentVolumeClaim: + claimName: dataset-initializer + - name: model-initializer + persistentVolumeClaim: + claimName: model-initializer + - name: model-exporter + persistentVolumeClaim: + claimName: model-exporter + - name: Exporter + template: + spec: + template: + spec: + containers: + - name: model-exporter + image: docker.io/kubeflow/model-exporter + volumeMounts: + - mountPath: /workspace/adapters + name: model-exporter + volumes: + - name: model-exporter + persistentVolumeClaim: + claimName: model-exporter +``` ### The Pod Spec Overrides APIs @@ -703,7 +763,7 @@ type PodSpecOverride struct { } // Override for each container. -// Parameters from TrainerConfig, DatasetConfig, and ModelConfig will take precedence. +// Parameters from Trainer, DatasetConfig, and ModelConfig will take precedence. type Container struct { // Name for the container. @@ -740,7 +800,7 @@ metadata: spec: trainingRuntimeRef: name: pytorch-distributed-gpu - trainerConfig: + trainer: image: docker.io/custom-training podSpecOverrides: - targetReplicatedJobs: @@ -805,7 +865,7 @@ type TrainingRuntime struct { JobSetSpec *batchv1.JobSetSpec `json:",inline"` // For gang-scheduling using volcano or scheduler plugins, supported for all frameworks. - GangScheduler *kubeflowv1.GangScheduler `json:"gangScheduler,omitempty"` + GangScheduler *GangScheduler `json:"gangScheduler,omitempty"` } // One of the specs can be selected. @@ -836,7 +896,7 @@ type GangSchedulerPlugin string const ( GangSchedulerPluginVolcano GangSchedulerPlugin = "volcano" - GangSchedulerPluginSP GangSchedulerPlugin = "scheduler-plugins" + GangSchedulerPlugins GangSchedulerPlugin = "scheduler-plugins" ) ``` @@ -971,7 +1031,7 @@ metadata: spec: trainingRuntimeRef: name: torch-distributed-multi-node - trainerConfig: + trainer: resourcesPerNode: requests: nvidia.com/gpu: 1 @@ -1102,20 +1162,16 @@ spec: - name: dataset-initializer image: docker.io/kubeflow/dataset-initializer env: - - name: DATASET_PROVIDER - value: hf - - name: REPO_ID - value: tatsu-lab/alpaca + - name: STORAGE_URI + value: hf://tatsu-lab/alpaca volumeMounts: - mountPath: /workspace/dataset name: dataset-initializer - name: model-initializer image: docker.io/kubeflow/model-initializer env: - - name: MODEL_PROVIDER - value: hf - - name: REPO_ID - value: meta-llama/Llama-2-7b + - name: STORAGE_URI + value: hf://meta-llama/Llama-2-7b - name: TRANSFORMER_TYPE value: AutoModelForCausalLM volumeMounts: @@ -1188,20 +1244,16 @@ spec: - name: dataset-initializer image: docker.io/kubeflow/dataset-initializer env: - - name: DATASET_PROVIDER - value: hf - - name: REPO_ID - value: tatsu-lab/alpaca + - name: STORAGE_URI + value: hf://tatsu-lab/alpaca volumeMounts: - mountPath: /workspace/dataset name: dataset-initializer - name: model-initializer image: docker.io/kubeflow/model-initializer env: - - name: MODEL_PROVIDER - value: hf - - name: REPO_ID - value: google/gemma-7b + - name: STORAGE_URI + value: hf://google/gemma-7b - name: TRANSFORMER_TYPE value: AutoModelForCausalLM volumeMounts: @@ -1277,6 +1329,8 @@ spec: containers: - name: mpi-launcher image: docker.io/mpi-launch + command: + - mpirun -np 5 --host mpi-simple.default.svc - name: Node template: spec: From edefff2b9078816c0f0d0f958954743f969e5bbe Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 25 Jul 2024 19:44:56 +0100 Subject: [PATCH 07/24] Update runtime timelines Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 7f34927153..3dd11026f5 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -833,8 +833,9 @@ using custom configurations. The Kubeflow Training Operator can maintain more Training Runtimes when the community is ready to support them. For example, runtimes for [Jax](https://jax.readthedocs.io/en/latest/index.html) or -[MLX](https://ml-explore.github.io/mlx/build/html/index.html). Initially, we will support: PyTorch, -MPI, TensorFlow, XGBoost, and PaddlePaddle. +[MLX](https://ml-explore.github.io/mlx/build/html/index.html). We will support PyTorch and MPI runtimes. +After initial implementation, we will support TensorFlow, XGboost, and PaddlePaddle runtimes, but +it is out of scope of this KEP. The `TrainingRuntime` is immutable, and so to make a change, a new version of the `TrainingRuntime` must be created and then changing the `TrainJob` to point to the new version. From 38ed8f9aba8beefe3900f3bd93f78c2e68bf93a9 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 26 Jul 2024 16:44:25 +0100 Subject: [PATCH 08/24] Address readability comments Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 3dd11026f5..a788d87674 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -60,7 +60,7 @@ We can identify the following personas of Training Operator: 1. **MLOps Engineer**. They are familiar with ML frameworks and they know how to configure distributed PyTorch settings such as rendezvous backends or MPI configuration. Usually, they are not experts in Kubernetes and ML algorithms. -1. **Data Scientists**. They create model architectures and advanced ML algorithms to train models. +1. **Data Scientists/ML Engineers**. They create model architectures and advanced ML algorithms to train models. They prefer to use Python for their work. They are aware of `torch.nn` APIs, but not with `torch.distributed` and Kubernetes concepts to scale model training. @@ -119,8 +119,8 @@ The below diagram shows which resources will be created for LLM fine-tuning with ### Worker and Node Definition -To better understand what does Nodes and Worker mean in the diagram above, -the following table explains naming that each framework or technology uses: +To better understand what "Nodes" and "Worker" mean in the diagram above, +the following table explains the naming that each framework or technology uses: @@ -252,7 +252,8 @@ for other MPI implementations: Intel MPI, MPICH, Spectrum MPI. ## The TrainJob API -The `TrainJob` exposes APIs that data scientist can override in `TrainingRuntime` to create training job: +The `TrainJob` exposes APIs that data scientist can override in `TrainingRuntime` to create +a training job: ```golang type TrainJob struct { @@ -299,7 +300,7 @@ type TrainJobStatus struct { ``` -This table explain rationale for each `TrainJob` parameter: +This table explains the rationale for each `TrainJob` parameter:
@@ -311,19 +312,19 @@ This table explain rationale for each `TrainJob` parameter: - - - @@ -335,7 +336,7 @@ This table explain rationale for each `TrainJob` parameter: - @@ -343,8 +344,8 @@ This table explain rationale for each `TrainJob` parameter:
TrainingRuntimeRef Reference to the existing TrainingRuntime that pre-deployed by platform engineers + Reference to the existing TrainingRuntime that is pre-deployed by platform engineers
Trainer Configuration for the Trainer such as image, number of nodes, accelerators. + Configuration for the Trainer such as image, number of nodes, accelerators.
ModelConfig Configuration for the pre-trained model and location for model output + Configuration of the pre-trained model and the location of the model output
Labels and Annotations Custom metadata that needs to be applied to the TrainJob resources: JobSet, Job, Pods. + Custom metadata that needs to be applied to the TrainJob resources: JobSet, Job, and Pods.
Custom overrides that are specific to the TrainJob and need to be applied to the TrainJob resources. For example, the user identity. Usually, it is managed by - custom admission webhooks that inject data to the TrainJob after user creates it - via Python SDK or kubectl + custom admission webhooks that inject data to the TrainJob after the user creates it + via the Python SDK or kubectl
@@ -370,13 +371,13 @@ spec: nvidia.com/gpu: 2 ``` -The above command will be converted as follows: +The above command will be converted to: ```bash torchrun --nnodes=5 --nproc-per-node=2 train.py ``` -Additionally, the Kubeflow Training SDK allows to create the above `TrainJob` using the Python API: +Additionally, the Kubeflow Training SDK allows the user to create the above `TrainJob` using the Python API: ```python def train_func(): @@ -430,7 +431,7 @@ spec: ### The Trainer API -The `Trainer` represents the APIs that data scientists can use to configure trainer settings: +The `Trainer` represents the APIs that data scientists can use to configure the trainer settings: ```golang type Trainer struct { @@ -509,7 +510,7 @@ The following table explains how `TrainingRuntime` parameters will be overridden ### The Dataset Config API -The `DatasetConfig` represents the APIs that data scientists can use to configure dataset location. +The `DatasetConfig` represents the APIs that data scientists can use to configure the dataset location. ```golang type DatasetConfig struct { @@ -563,7 +564,7 @@ replicatedJobs: ### The Model Config API -The `ModelConfig` represents the APIs that data scientists can use to configure pre-trained model +The `ModelConfig` represents the APIs that data scientists can use to configure the pre-trained model input and output location. ```golang @@ -637,8 +638,8 @@ replicatedJobs: #### The Output Model API -After initial implementation of `TrainJob` and `TrainingRuntime`, we will support ability to export -the trained model. The following runtime can be implemented: +After initial implementation of `TrainJob` and `TrainingRuntime`, we will support the ability to +export the trained model. The following runtime can be implemented: ```yaml apiVersion: kubeflow.org/v2alpha1 @@ -788,7 +789,7 @@ type Container struct { #### Example of TrainJob with Overrides -This example shows how to override user-identity for sidecar container and add volume to the +This example shows how to override the user-identity for the sidecar container and add volume to the trainer container. ```yaml @@ -835,10 +836,10 @@ The Kubeflow Training Operator can maintain more Training Runtimes when the comm support them. For example, runtimes for [Jax](https://jax.readthedocs.io/en/latest/index.html) or [MLX](https://ml-explore.github.io/mlx/build/html/index.html). We will support PyTorch and MPI runtimes. After initial implementation, we will support TensorFlow, XGboost, and PaddlePaddle runtimes, but -it is out of scope of this KEP. +it is out of scope for this KEP. The `TrainingRuntime` is immutable, and so to make a change, a new version of the `TrainingRuntime` -must be created and then changing the `TrainJob` to point to the new version. +must be created and then the user must change the `TrainJob` to point to the new version. This provides control as to how changes to runtimes propagate to existing training jobs. For example, when training is running for a long time (e.g. 1-2 months). @@ -882,7 +883,7 @@ type MLSpec struct { ### The Gang Scheduler API -Gang scheduler plugin is used to create appropriate `PodGroup` for Volcano or scheduler plugins. +Gang scheduler plugin is used to create the appropriate `PodGroup` for Volcano or scheduler plugins. ```golang type GangScheduler struct { @@ -1137,12 +1138,12 @@ spec: #### LLM Fine-Tuning Runtimes -In the future, we can consider to use [the `torchtune` CLI](https://github.com/pytorch/torchtune/tree/main) +In the future, we can consider using [the `torchtune` CLI](https://github.com/pytorch/torchtune/tree/main) for Fine-Tuning with PyTorch. ##### Llama 7b -The following runtime can be used for Llama 7b model. +The following runtime can be used for the Llama 7b model. ```yaml apiVersion: kubeflow.org/v2alpha1 @@ -1306,7 +1307,7 @@ spec: #### MPI Runtime -For MPI, we can add support the `DeepSpeed` runtimes. +For MPI, we can add support for the `DeepSpeed` runtimes. Example of simple OpenMPI runtime: @@ -1363,8 +1364,8 @@ _Will be added after initial implementation for PyTorch._ ## Migration from Kubeflow Training V1 These API changes will not be compatible with Training Operator V1 APIs. Thus, existing users have -to migrate to the newer APIs. Kubeflow community will provide instructions on how to migrate existing -training jobs to the new APIs. +to migrate to the newer APIs. The Kubeflow community will provide instructions on how to migrate +existing training jobs to the new APIs. ### PyTorchJob Migration From a87177bbb57a182feb0350b152d2bc3db59ddb69 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 26 Jul 2024 16:55:25 +0100 Subject: [PATCH 09/24] Explaination for Trainer Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index a788d87674..0613ab5c0f 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -431,7 +431,8 @@ spec: ### The Trainer API -The `Trainer` represents the APIs that data scientists can use to configure the trainer settings: +The `Trainer` represents the APIs that data scientists can use to configure the trainer settings. +This trainer is executed on every distributed training Node. ```golang type Trainer struct { From 47dbd31731d377bf1b819e3057b4285067d4dc07 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 26 Jul 2024 18:09:51 +0100 Subject: [PATCH 10/24] Update LLM Fine-Tuning Diagram Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/trainjob-diagram.drawio.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg index 74e041dca0..d23de048c3 100644 --- a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg +++ b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg @@ -1,4 +1,4 @@ -
TrainJob
image/svg+xml
JobSet
image/svg+xml
Storage
Initializer
PyTorch
Nodes
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
PyTorch Nodes
Headless Service
Download
Pre-trained Model
Download
Dataset
LLM Training Runtime
image/svg+xml
\ No newline at end of file +
TrainJob
image/svg+xml
JobSet
image/svg+xml
PyTorch
Nodes
LLM Training Runtime
image/svg+xml
Storage
Initializer
Exporter
Download
Pre-Trained Model
Download
Dataset
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
PyTorch Nodes
Headless Service
Export Fine-Tuned
Model
\ No newline at end of file From 57d959178b6242d4ab234ffd1cb4630b914866b6 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 1 Aug 2024 15:45:26 +0100 Subject: [PATCH 11/24] Fix Llama model name Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 0613ab5c0f..790623506e 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -424,7 +424,7 @@ spec: split: train[:5000] modelConfig: input: - storageUri: hf://yelp-review-full + storageUri: hf://meta-llama/Llama-2-7b output: storageUri: s3://trained-model ``` @@ -604,7 +604,7 @@ type OutputModel struct { Initially we will support the following model providers: -- **HuggingFace:** `storageUri: hf://model-name` +- **HuggingFace:** `storageUri: hf://model-path` Parameters will be converted to the environment variables for the `model-initializer` container in the `Initializer` Job. From bc373d9eae02bf6992b3c38723272f470441fb17 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 1 Aug 2024 16:27:54 +0100 Subject: [PATCH 12/24] Add goal for integration with Kueue Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 790623506e..a30099a56f 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -80,6 +80,8 @@ Based on the above personas, we should build an API that everyone will benefit f models (e.g. Mistral, LLama-70b, Gemma-7b). - Work on the following `JobSet` improvements: https://github.com/kubernetes-sigs/jobset/issues/463 and https://github.com/kubernetes-sigs/jobset/issues/572 +- Integrate `TrainJob` with Kueue and MultiKueue to effectively manage resources for training jobs + and orchestrate resources across multiple clusters. ### Non-Goals From 3f5d7bbdfc90405b11e03231496fc0a8d093da62 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 1 Aug 2024 16:30:31 +0100 Subject: [PATCH 13/24] Add links for Job run policies Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index a30099a56f..2ccad884d4 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -16,8 +16,10 @@ This document discusses the new Kubeflow Training V2 API. When we built the [Kubeflow Training Operator a couple of years ago](https://docs.google.com/document/d/1x1JPDQfDMIbnoQRftDH1IzGU0qvHGSU4W6Jl4rJLPhI/edit?usp=sharing), Kubernetes lacked better features to support distributed machine learning (ML) training, such as -SuccessPolicy and RestartPolicy (FailurePolicy). Recently, the Kubernetes community launched the -working group Batch, and then the working group actively worked on evolving the batch/v1 `Job` API +[SuccessPolicy](https://kubernetes.io/docs/concepts/workloads/controllers/job/#success-policy) +and RestartPolicy ([PodFailurePolicy](https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-failure-policy) in `Job`). +Recently, the Kubernetes community launched the working group Batch, and then the working group +actively worked on evolving the batch/v1 `Job` API and built [a new Kubernetes SIGs project: `JobSet`](https://github.com/kubernetes-sigs/jobset) to manage groups of `Jobs`. From 619d167ace58e0c4ae721085376ad1d648b422cb Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 1 Aug 2024 18:51:40 +0100 Subject: [PATCH 14/24] Add some alternatives Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 2ccad884d4..e3d2b99c88 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -1436,3 +1436,41 @@ spec: command: - torchrun train.py ``` + +## Alternatives + +Alternatives details can be found in +[this Google document](https://docs.google.com/document/d/1bha8rB6_iPTi9rXjJMnKi-CLxfL7dwtmQCKH4N6dcsI/edit#heading=h.b6cb7hecqms). + +### Inline JobSet APIs into TrainJob + +```golang +type TrainJobSpec struct { + ... + + JobSetSpec *batchv1.JobSetSpec `json:",inline"` +} +``` + +In that case, `TrainJob` API will be very complex and users still have to specify every Kubernetes +API parameter on job submission. + +### Use JobSetTemplate as a Training Runtime + +Instead of creating the custom CRD for `TrainingRuntime`, use the `JobSetTemplate` API to create +blueprints for training runtimes. + +Platform engineers need to understand all aspect on how to configure parameters for various +frameworks (e.g. PyTorch or HuggingFace). Also, it will be hard to implement custom orchestration +when it is requires (e.g. MPI or Slurm use-case). + +### Using CRD for Every Framework (e.g. PyTorchJob) + +Instead of `TrainJob` maintain different CRDs for each framework: `PyTorchJob`, `JaxJob`, `MPIJob`. + +Given that ML framework space is growing very fast, it will be very hard to maintain CRD for every +framework that users want to run on Kubernetes. + +Since frameworks share common functionality for distributed training (data parallelizm or +model parallelizm). For some specific use-cases like MPI or Elastic PyTorch, we will leverage +`MLSpec` parameter. From 1c423ab2817493701be5ef2fa1953d6c96149702 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Thu, 1 Aug 2024 20:50:15 +0100 Subject: [PATCH 15/24] Fix more API types Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index e3d2b99c88..4f8398bdf1 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -80,8 +80,10 @@ Based on the above personas, we should build an API that everyone will benefit f - Create community-supported `ClusterTrainingRuntime` for distributed training with PyTorch and MPI. - Create community-supported `ClusterTrainingRuntime` for LLM fine-tuning for various foundational models (e.g. Mistral, LLama-70b, Gemma-7b). -- Work on the following `JobSet` improvements: https://github.com/kubernetes-sigs/jobset/issues/463 - and https://github.com/kubernetes-sigs/jobset/issues/572 +- Work on the following `JobSet` improvements: + - For PyTorch Elastic: https://github.com/kubernetes-sigs/jobset/issues/463 + - For PVC management: https://github.com/kubernetes-sigs/jobset/issues/572 + - For PyTorch Elastic: https://github.com/kubernetes-sigs/jobset/issues/570 - Integrate `TrainJob` with Kueue and MultiKueue to effectively manage resources for training jobs and orchestrate resources across multiple clusters. @@ -91,6 +93,10 @@ Based on the above personas, we should build an API that everyone will benefit f - Distributed training for TensorFlow, XGboost, JAX, and PaddlePaddle will be added after initial implementation. - Migrate Kubeflow V1 controller to use `JobSet`. +- Propose the migration mechanisms / ways from Kubeflow Training v1 to v2. We will create dedicated + KEP for customers migration. +- Propose the changes to Kubeflow Training Python SDK. After controller implementation, we will + propose changes to the `kubeflow-training` SDK. ## Design Details @@ -287,6 +293,9 @@ type TrainJobSpec struct { // Custom metadata to apply for Job, JobSet, etc. Labels map[string]string `json:"labels,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` + + // PodSpecOverrides represents overrides for the TrainingRuntime when TrainJob is created. + PodSpecOverrides []PodSpecOverrides `json:"podSpecOverrides,omitempty"` } type TrainingRuntimeRef struct { @@ -519,15 +528,14 @@ The `DatasetConfig` represents the APIs that data scientists can use to configur ```golang type DatasetConfig struct { - // Storage uri for the dataset provider. StorageUri string `json:"storageUri"` // Custom parameters for the dataset initializer. - Parameters *[string]string `json:"parameters,omitempty"` + Parameters map[string]string `json:"parameters,omitempty"` - // Reference to the secrets to access dataset. - SecretRef corev1.SecretReference `json:"secretRef,omitempty"` + // Reference to the secrets to access dataset. + SecretRef corev1.SecretReference `json:"secretRef,omitempty"` } ``` @@ -586,7 +594,7 @@ type InputModel struct { StorageUri string `json:"storageUri"` // Custom parameters for the model initializer. - Parameters *[string]string `json:"parameters,omitempty"` + Parameters map[string]string `json:"parameters,omitempty"` // Reference to the secrets to access model. SecretRef corev1.SecretReference `json:"secretRef,omitempty"` @@ -597,7 +605,7 @@ type OutputModel struct { StorageUri string `json:"storageUri"` // Custom parameters for the model exporter. - Parameters *[string]string `json:"parameters,omitempty"` + Parameters map[string]string `json:"parameters,omitempty"` // Reference to the secrets to export model. SecretRef corev1.SecretReference `json:"secretRef,omitempty"` @@ -776,7 +784,7 @@ type Container struct { Name string `json:"name"` // Command for the container. - Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"` + Command []string `json:"command,omitempty"` // Args for the container. Args []string `json:"args,omitempty"` @@ -810,8 +818,7 @@ spec: image: docker.io/custom-training podSpecOverrides: - targetReplicatedJobs: - - initializer - node + - node containers: - name: user-identity value: 123 @@ -865,8 +872,8 @@ type TrainingRuntime struct { // Framework specific parameters. MLSpec *MLSpec `json:"mlSpec,omitempty"` - // Number of nodes to execute training. - NumNodes int `json:"numNodes,omitempty"` + // Number of nodes to execute training. Defaults to 1. + NumNodes int `json:"numNodes"` // JobSet spec. JobSetSpec *batchv1.JobSetSpec `json:",inline"` @@ -896,7 +903,7 @@ type GangScheduler struct { Plugin *GangSchedulerPlugin `json:plugin,omitempty"` // Time threshold to schedule PodGroup for gang scheduling. - ScheduleTimeoutSeconds string `json:scheduleTimeoutSeconds,omitempty"` + ScheduleTimeoutSeconds *string `json:scheduleTimeoutSeconds,omitempty"` } type GangSchedulerPlugin string @@ -933,7 +940,7 @@ we won't support them in `TorchSpec`. We can introduce them in the future if use type TorchSpec struct { // Number of Procs per Node. - NumProcPerNode int `json:"numProcPerNode,omitempty"` + NumProcPerNode *int32 `json:"numProcPerNode,omitempty"` // Used for single-node multi-worker training Standalone bool `json:"standalone,omitempty"` @@ -973,14 +980,14 @@ Check [the proposal for the MPI V2 APIs.](https://github.com/kubeflow/mpi-operat ```golang type MPISpec struct { // Number of Procs per Node. - NumProcPerNode int `json:"numProcPerNode,omitempty"` + NumProcPerNode *int32 `json:"numProcPerNode,omitempty"` // MPI Implementation to create appropriate host-files. // Can be one of OpenMPI, Intel, or MPICH. - MPIImplementation MPIImplementation `json:"mpiImplementation,omitempty"` + MPIImplementation *MPIImplementation `json:"mpiImplementation"` // Directory where SSH keys are mounted. - SSHAuthMountPath string `json:"SSHAuthMountPath,omitempty"` + SSHAuthMountPath *string `json:"SSHAuthMountPath,omitempty"` } type MPIImplementation string From ca2386790f8108a14f7380b70e10a37cabe11948 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 2 Aug 2024 12:33:25 +0100 Subject: [PATCH 16/24] Fix empty number of nodes Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 4f8398bdf1..23fc70593a 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -873,7 +873,7 @@ type TrainingRuntime struct { MLSpec *MLSpec `json:"mlSpec,omitempty"` // Number of nodes to execute training. Defaults to 1. - NumNodes int `json:"numNodes"` + NumNodes *int32 `json:"numNodes,omitempty"` // JobSet spec. JobSetSpec *batchv1.JobSetSpec `json:",inline"` From 77170dab6375f843929a45e97907293a31287d33 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 2 Aug 2024 12:46:17 +0100 Subject: [PATCH 17/24] Rename to Coscheduling Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 23fc70593a..43586252f9 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -909,8 +909,8 @@ type GangScheduler struct { type GangSchedulerPlugin string const ( - GangSchedulerPluginVolcano GangSchedulerPlugin = "volcano" - GangSchedulerPlugins GangSchedulerPlugin = "scheduler-plugins" + GangSchedulerPluginVolcano GangSchedulerPlugin = "volcano" + GangSchedulerPluginCoscheduling GangSchedulerPlugin = "coscheduling" ) ``` From 9acf8a3084ddccced0351d2f64345081881b115a Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 2 Aug 2024 16:14:03 +0100 Subject: [PATCH 18/24] Change parameters to env Add runLauncherAsNode parameter Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 101 +++++++++++------- 1 file changed, 63 insertions(+), 38 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 43586252f9..a186b76c66 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -296,14 +296,26 @@ type TrainJobSpec struct { // PodSpecOverrides represents overrides for the TrainingRuntime when TrainJob is created. PodSpecOverrides []PodSpecOverrides `json:"podSpecOverrides,omitempty"` + + // Suspend suspends TrainJob. + Suspend *bool `json:"suspend,omitempty"` + + // ManagedBy is used to indicate the controller or entity that manages a TrainJob. + ManagedBy *string `json:"managedBy,omitempty"` } type TrainingRuntimeRef struct { // Name for the training runtime. Name string `json:"name"` - // Namespace for the runtime. - // If namespace is set, TrainingRuntime is used. Otherwise, ClusterTrainingRuntime is used. - Namespace string `json:"namespace,omitempty"` + + // Namespace for the runtime. In that case, user should use TrainingRuntime + Namespace *string `json:"namespace,omitempty"` + + // Kind for the runtime. TrainingRuntime or ClusterTrainingRuntime + Kind *string `json:"kind,omitempty"` + + // Version for the runtime. For example: v2alpha1 + Version *string `json:"version,omitempty"` } type TrainJobStatus struct { @@ -361,6 +373,12 @@ This table explains the rationale for each `TrainJob` parameter: via the Python SDK or kubectl + + Suspend and ManagedBy + + Scheduling directives for Kueue and MultiKueue + + ### Example of TrainJob @@ -433,8 +451,9 @@ spec: name: torch-tune-llama-7b datasetConfig: storageUri: s3://dataset/custom-dataset/yelp-review - parameters: - split: train[:5000] + env: + - name: SPLIT + value: train[:5000] modelConfig: input: storageUri: hf://meta-llama/Llama-2-7b @@ -450,28 +469,28 @@ This trainer is executed on every distributed training Node. ```golang type Trainer struct { - // Docker image for the Trainer. - Image string `json:"image,omitempty"` + // Docker image for the Trainer. + Image string `json:"image,omitempty"` - // Command for the training container. - // Validate that command contains torchrun or mpirun. - Command []string `json:"command,omitempty"` + // Command for the training container. + // Validate that command contains torchrun or mpirun. + Command []string `json:"command,omitempty"` - // Args for the training container. - Args []string `json:"args,omitempty"` + // Args for the training container. + Args []string `json:"args,omitempty"` - // Env for the training container. - Env []corev1.EnvVar `json:"env,omitempty"` + // Env for the training container. + Env []corev1.EnvVar `json:"env,omitempty"` - // Number of training nodes. - NumNodes *int32 `json:"numNodes,omitempty"` + // Number of training nodes. + NumNodes *int32 `json:"numNodes,omitempty"` - // Resource for each node. - ResourcesPerNode []corev1.resources `json:"resourcesPerNode,omitempty"` + // Resource for each node. + ResourcesPerNode []corev1.resources `json:"resourcesPerNode,omitempty"` - // Number of processes in a single node. - // By default this value == number of GPUs in resources limits. - NumProcPerNode *int32 `json:"numProcPerNode,omitempty"` + // Number of processes in a single node. + // By default this value == number of GPUs in resources limits. + NumProcPerNode *int32 `json:"numProcPerNode,omitempty"` } ``` @@ -531,8 +550,8 @@ type DatasetConfig struct { // Storage uri for the dataset provider. StorageUri string `json:"storageUri"` - // Custom parameters for the dataset initializer. - Parameters map[string]string `json:"parameters,omitempty"` + // Custom env variables for dataset initializer + Env []corev1.EnvVar `json:"env,omitempty"` // Reference to the secrets to access dataset. SecretRef corev1.SecretReference `json:"secretRef,omitempty"` @@ -544,16 +563,17 @@ Initially we will support the following dataset providers: - **S3:** `storageUri: s3://bucket-name/path/dataset` - **HuggingFace:** `storageUri: hf://repo-id` -Parameters will be converted to the environment variables for the `dataset-initializer` container -in the `Initializer` Job. +User can override the default env variables in the `dataset-initializer` container +of the `Initializer` Job. For example: ```yaml datasetConfig: storageUri: s3://datasets/yelp-review - parameters: - endpointUrl: s3.custom.com + env: + - name: ENDPOINT_URL + value: s3.custom.com ``` Will be converted to: @@ -593,8 +613,8 @@ type InputModel struct { // Storage uri for the model provider. StorageUri string `json:"storageUri"` - // Custom parameters for the model initializer. - Parameters map[string]string `json:"parameters,omitempty"` + // Custom env variables for model initializer + Env []corev1.EnvVar `json:"env,omitempty"` // Reference to the secrets to access model. SecretRef corev1.SecretReference `json:"secretRef,omitempty"` @@ -604,8 +624,8 @@ type OutputModel struct { // Storage uri for the model exported. StorageUri string `json:"storageUri"` - // Custom parameters for the model exporter. - Parameters map[string]string `json:"parameters,omitempty"` + // Custom env variables for model exporter. + Env []corev1.EnvVar `json:"env,omitempty"` // Reference to the secrets to export model. SecretRef corev1.SecretReference `json:"secretRef,omitempty"` @@ -618,16 +638,16 @@ Initially we will support the following model providers: - **HuggingFace:** `storageUri: hf://model-path` -Parameters will be converted to the environment variables for the `model-initializer` container -in the `Initializer` Job. - +User can override the default env variables in the `model-initializer` container +of the `Initializer` Job. For example: ```yaml modelConfig: storageUri: hf://bert-based-cased - parameters: - transformerType: AutoModelForCausalLM + env: + - name: TRANSFORMER_TYPE + value: AutoModelForCausalLM ``` Will be converted to: @@ -942,8 +962,9 @@ type TorchSpec struct { // Number of Procs per Node. NumProcPerNode *int32 `json:"numProcPerNode,omitempty"` - // Used for single-node multi-worker training - Standalone bool `json:"standalone,omitempty"` + // Used for single-node multi-worker training. + // Defaults to false. + Standalone *bool `json:"standalone,omitempty"` // Torch Elastic Policy. ElasticPolicy *TorchElasticPolicy `json:"elasticPolicy,omitempty"` @@ -988,6 +1009,10 @@ type MPISpec struct { // Directory where SSH keys are mounted. SSHAuthMountPath *string `json:"SSHAuthMountPath,omitempty"` + + // RunLauncherAsNode indicates whether to run training process in launcher. + // Defaults to false. + RunLauncherAsNode *bool `json:"runLauncherAsNode,omitempty"` } type MPIImplementation string From 287a4a4cc3c9b3d70d73c1120f51af01c1d493e6 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 2 Aug 2024 17:28:25 +0100 Subject: [PATCH 19/24] Update PodSpecOverride with scheduling directives Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index a186b76c66..e0a5cc83fe 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -780,43 +780,51 @@ In the future, we can add more parameters if we find use-cases when it is requir ```golang type PodSpecOverride struct { - // Name of the training replica in the training runtime template to override - TargetReplicatedJobs []string `json:"targetReplicatedJobs"` + // Name of the training replica in the training runtime template to override + TargetReplicatedJobs []string `json:"targetReplicatedJobs"` - // Override parameters for Containers. - Containers []Container `json:"container,omitempty"` + // Override parameters for Containers. + Containers []Container `json:"container,omitempty"` - // Override parameters for InitContainers. - InitContainer []Container `json:"initContainer,omitempty"` + // Override parameters for InitContainers. + InitContainer []Container `json:"initContainer,omitempty"` - // Override parameters for volumes. - Volumes []corev1.Volume `json:"volume,omitempty"` + // Override parameters for volumes. + Volumes []corev1.Volume `json:"volume,omitempty"` - // Custom Service Account - ServiceAccountName string `json:"serviceAccountName,omitempty"` + // Custom Service Account + ServiceAccountName string `json:"serviceAccountName,omitempty"` + + // Node selector to fit pod on the node. This is needed to integrate TrainJob and Kueue + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Override Pod's tolerations. This is needed to integrate TrainJob and Kueue + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Custom scheduler for TrainJob, for example YuniKorn. + SchedulerName string `json:"schedulerName,omitempty"` } // Override for each container. // Parameters from Trainer, DatasetConfig, and ModelConfig will take precedence. type Container struct { + // Name for the container. + Name string `json:"name"` - // Name for the container. - Name string `json:"name"` - - // Command for the container. - Command []string `json:"command,omitempty"` + // Command for the container. + Command []string `json:"command,omitempty"` - // Args for the container. - Args []string `json:"args,omitempty"` + // Args for the container. + Args []string `json:"args,omitempty"` - // Env for the container. - Env []corev1.EnvVar `json:"env,omitempty"` + // Env for the container. + Env []corev1.EnvVar `json:"env,omitempty"` - // Env for the container. - EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` + // Env for the container. + EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` - // Override parameters for volume mounts. - VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"` + // Override parameters for volume mounts. + VolumeMounts []VolumeMount `json:"volumeMounts,omitempty"` } ``` From be8177be3ea1de640651e662fb3709a60adf1f8d Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Fri, 2 Aug 2024 17:41:46 +0100 Subject: [PATCH 20/24] Fix TrainingRuntime field Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index e0a5cc83fe..63be539e3a 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -279,7 +279,7 @@ type TrainJob struct { type TrainJobSpec struct { // Reference to the Training Runtime. - TrainingRuntimeRef *TrainingRuntimeRef `json:"trainingRuntimeRef"` + TrainingRuntimeRef TrainingRuntimeRef `json:"trainingRuntimeRef"` // Parameters that data scientists can override Trainer *Trainer `json:"trainer,omitempty"` From f80e7809118ef41fb31bd1e89c3e06373559bae9 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Tue, 6 Aug 2024 12:39:46 +0100 Subject: [PATCH 21/24] Refactor PodGroupSpec APIs Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 71 ++++++++++++++++--- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 63be539e3a..0bf0acb3a2 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -402,13 +402,14 @@ spec: nvidia.com/gpu: 2 ``` -The above command will be converted to: +The container's `torchrun` command in the above YAML will be converted into: ```bash torchrun --nnodes=5 --nproc-per-node=2 train.py ``` -Additionally, the Kubeflow Training SDK allows the user to create the above `TrainJob` using the Python API: +Additionally, the Kubeflow Training SDK allows the user to create the above `TrainJob` using +the Python API: ```python def train_func(): @@ -800,9 +801,6 @@ type PodSpecOverride struct { // Override Pod's tolerations. This is needed to integrate TrainJob and Kueue Tolerations []corev1.Toleration `json:"tolerations,omitempty"` - - // Custom scheduler for TrainJob, for example YuniKorn. - SchedulerName string `json:"schedulerName,omitempty"` } // Override for each container. @@ -906,8 +904,8 @@ type TrainingRuntime struct { // JobSet spec. JobSetSpec *batchv1.JobSetSpec `json:",inline"` - // For gang-scheduling using volcano or scheduler plugins, supported for all frameworks. - GangScheduler *GangScheduler `json:"gangScheduler,omitempty"` + // Spec to create PodGroup for gang-scheduling using volcano or coscheduling. + PodGroupSpec *PodGroupSpec `json:"podGroupSpec,omitempty"` } // One of the specs can be selected. @@ -921,12 +919,15 @@ type MLSpec struct { } ``` -### The Gang Scheduler API +### The PodGroupSpec API -Gang scheduler plugin is used to create the appropriate `PodGroup` for Volcano or scheduler plugins. +The `PodGroupSpec` is used to create the appropriate `PodGroup` for gang-scheduling. It can +be used with Volcano or Coscheduling. +User should add the scheduler name into Pod's `.spec.schedulerName` if the default scheduler is +not the same as `PodGroup` plugin. ```golang -type GangScheduler struct { +type PodGroupSpec struct { // Plugin for gang scheduling. Plugin *GangSchedulerPlugin `json:plugin,omitempty"` @@ -942,6 +943,56 @@ const ( ) ``` +Here is the example of runtime with gang-scheduling using coscheduling plugin. + +```yaml +apiVersion: kubeflow.org/v2alpha1 +kind: ClusterTrainingRuntime +metadata: + name: torch-distributed-multi-node +spec: + mlSpec: + torch: + numProcPerNode: 5 + podGroupSpec: + plugin: coscheduling + scheduleTimeoutSeconds: 100 + replicatedJobs: + - name: node + template: + spec: + template: + spec: + schedulerName: coscheduling + containers: + - name: trainer + image: docker.io/kubeflow/pytorch-mnist + resources: + limits: + nvidia.com/gpu: 1 + env: + - name: MASTER_ADDR + value: "pytorch-node-0-0.pytorch" + - name: MASTER_PORT + value: 29400 + command: + - torchrun train.py +``` + +Training Operator will create the `PodGroup` using the following spec: + +```yaml +apiVersion: scheduling.x-k8s.io/v1alpha1 +kind: PodGroup +metadata: + name: nginx +spec: + scheduleTimeoutSeconds: 100 + minMember: 5 +``` + +The `TrainJob` will be started only when 5 GPUs are available in the cluster. + ### The Torch Spec API The `TorchSpec` API represents the configuration for the PyTorch distributed training. This configuration From 08fec42a58deabb3b9b6b7f2225e199a6c1f2a37 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Tue, 6 Aug 2024 12:45:33 +0100 Subject: [PATCH 22/24] Add note about scheduler name Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 0bf0acb3a2..729cdee75c 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -923,8 +923,6 @@ type MLSpec struct { The `PodGroupSpec` is used to create the appropriate `PodGroup` for gang-scheduling. It can be used with Volcano or Coscheduling. -User should add the scheduler name into Pod's `.spec.schedulerName` if the default scheduler is -not the same as `PodGroup` plugin. ```golang type PodGroupSpec struct { @@ -943,7 +941,9 @@ const ( ) ``` -Here is the example of runtime with gang-scheduling using coscheduling plugin. +The following example shows example of runtime with gang-scheduling using coscheduling plugin. +**Note:** User should add the scheduler name into Pod's `.spec.schedulerName` if the default +scheduler is not the same as `PodGroup` plugin. ```yaml apiVersion: kubeflow.org/v2alpha1 From d1c1994a90d1201388c3030e0a29a31ff6c23acf Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Tue, 6 Aug 2024 13:21:46 +0100 Subject: [PATCH 23/24] Add initial TrainJob status field Signed-off-by: Andrey Velichkevich --- .../2170-kubeflow-training-v2/README.md | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 729cdee75c..76df9116b7 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -319,10 +319,35 @@ type TrainingRuntimeRef struct { } type TrainJobStatus struct { - // Conditions for the TrainJob + // Conditions for the TrainJob. Initially, it will have the same conditions as JobSet. Conditions []metav1.Condition `json:"conditions,omitempty"` + + // ReplicatedJobsStatus track the number of Jobs for each replicatedJob in JobSet. + ReplicatedJobsStatus []ReplicatedJobStatus `json:"replicatedJobsStatus,omitempty"` } +type ReplicatedJobStatus struct { + // Name of the ReplicatedJob. + Name string `json:"name"` + + // Ready is the number of child Jobs where the number of ready pods and completed pods + // is greater than or equal to the total expected pod count for the Job (i.e., the minimum + // of job.spec.parallelism and job.spec.completions). + Ready int32 `json:"ready"` + + // Succeeded is the number of successfully completed child Jobs. + Succeeded int32 `json:"succeeded"` + + // Failed is the number of failed child Jobs. + Failed int32 `json:"failed"` + + // Active is the number of child Jobs with at least 1 pod in a running or pending state + // which are not marked for deletion. + Active int32 `json:"active"` + + // Suspended is the number of child Jobs which are in a suspended state. + Suspended int32 `json:"suspended"` +} ``` This table explains the rationale for each `TrainJob` parameter: @@ -902,7 +927,7 @@ type TrainingRuntime struct { NumNodes *int32 `json:"numNodes,omitempty"` // JobSet spec. - JobSetSpec *batchv1.JobSetSpec `json:",inline"` + JobSetSpec *jobsetv1.JobSetSpec `json:",inline"` // Spec to create PodGroup for gang-scheduling using volcano or coscheduling. PodGroupSpec *PodGroupSpec `json:"podGroupSpec,omitempty"` @@ -1539,7 +1564,7 @@ Alternatives details can be found in type TrainJobSpec struct { ... - JobSetSpec *batchv1.JobSetSpec `json:",inline"` + JobSetSpec *jobsetv1.JobSetSpec `json:",inline"` } ``` From 87ed153f97162d5d2ccca57c47b5fc18c8bcfd87 Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Tue, 6 Aug 2024 15:07:29 +0100 Subject: [PATCH 24/24] Fix pre-commit Signed-off-by: Andrey Velichkevich --- docs/proposals/2170-kubeflow-training-v2/README.md | 8 ++++---- .../2170-kubeflow-training-v2/trainjob-diagram.drawio.svg | 2 +- .../2170-kubeflow-training-v2/user-roles.drawio.svg | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/proposals/2170-kubeflow-training-v2/README.md b/docs/proposals/2170-kubeflow-training-v2/README.md index 76df9116b7..cc1aa4deb4 100644 --- a/docs/proposals/2170-kubeflow-training-v2/README.md +++ b/docs/proposals/2170-kubeflow-training-v2/README.md @@ -160,7 +160,7 @@ the following table explains the naming that each framework or technology uses: PyTorch - Worker + Worker

(--nproc-per-node) @@ -180,7 +180,7 @@ the following table explains the naming that each framework or technology uses:

(--np) - Node + Node

(--host) @@ -194,7 +194,7 @@ the following table explains the naming that each framework or technology uses: Worker - Worker Pool + Worker Pool

Cluster Spec @@ -236,7 +236,7 @@ the following table explains the naming that each framework or technology uses: Not Applicable - python + python Rabit Tracker for c10d diff --git a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg index d23de048c3..bd5f1b1aa6 100644 --- a/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg +++ b/docs/proposals/2170-kubeflow-training-v2/trainjob-diagram.drawio.svg @@ -1,4 +1,4 @@ -
TrainJob
image/svg+xml
JobSet
image/svg+xml
PyTorch
Nodes
LLM Training Runtime
image/svg+xml
Storage
Initializer
Exporter
Download
Pre-Trained Model
Download
Dataset
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
PyTorch Nodes
Headless Service
Export Fine-Tuned
Model
\ No newline at end of file +
TrainJob
image/svg+xml
JobSet
image/svg+xml
PyTorch
Nodes
LLM Training Runtime
image/svg+xml
Storage
Initializer
Exporter
Download
Pre-Trained Model
Download
Dataset
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
Worker
PyTorch Nodes
Headless Service
Export Fine-Tuned
Model
diff --git a/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg b/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg index f074f65332..b48e05453f 100644 --- a/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg +++ b/docs/proposals/2170-kubeflow-training-v2/user-roles.drawio.svg @@ -1,4 +1,4 @@ -
Platform Engineer
Kubeflow
Python SDK
TrainJob
image/svg+xml
kubectl
Data Scientist
Create TrainJob
JobSet
image/svg+xml
Training Runtime
image/svg+xml
Manage
Runtime
Fetch
Spec
Headless Service
Training Nodes
\ No newline at end of file +
Platform Engineer
Kubeflow
Python SDK
TrainJob
image/svg+xml
kubectl
Data Scientist
Create TrainJob
JobSet
image/svg+xml
Training Runtime
image/svg+xml
Manage
Runtime
Fetch
Spec
Headless Service
Training Nodes