From 2c71769f6daf00faa9be40c56e07bf0f1287d9ce Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Wed, 20 Dec 2023 14:19:27 +0100 Subject: [PATCH 1/2] Add FULL support for Ollama AI models - Implement a native client (OllamaApi) to leverage chat/streaming and embedding endpoints. - Add a OllamaChatClient implementing the ChatClinet and StreamingChatClinet interfaces. - Add a OllamaEmbedding clinent that impl. the EmbeddingClinet interface. - Add AutoConfiguraitons with properties for the chat and the embedding clients. - Add unit and ITs for the OllamaApi, OllamaChatClient, OllamaEmbeddingClient, and related auto-configuraitons. - Remove the old ollama impl. classes and tests. - minor fixes to the bedrok test methods names. --- models/spring-ai-ollama/README.md | 120 ++++ models/spring-ai-ollama/pom.xml | 32 +- .../ai/ollama/OllamaChatClient.java | 140 +++++ .../ai/ollama/OllamaEmbeddingClient.java | 95 +++ .../ai/ollama/api/OllamaApi.java | 592 ++++++++++++++++++ .../ai/ollama/api/OllamaApiOptions.java | 395 ++++++++++++ .../ai/ollama/client/OllamaClient.java | 246 -------- .../ollama/client/OllamaGenerateResult.java | 146 ----- .../ai/ollama/OllamaChatClientIT.java | 192 ++++++ .../ai/ollama/OllamaEmbeddingClientIT.java | 82 +++ .../ai/ollama/api/OllamaApiIT.java | 146 +++++ .../ai/ollama/client/OllamaClientTests.java | 43 -- .../test/resources/doc/Ollama Chat API.jpg | Bin 0 -> 290171 bytes pom.xml | 1 + .../ai/autoconfigure/NativeHints.java | 17 +- .../BedrockTitanChatAutoConfiguration.java | 4 +- ...edrockTitanEmbeddingAutoConfiguration.java | 2 +- .../ollama/OllamaAutoConfiguration.java | 37 -- .../ollama/OllamaChatAutoConfiguration.java | 74 +++ .../ollama/OllamaChatProperties.java | 125 ++++ .../OllamaEmbeddingAutoConfiguration.java | 58 ++ ...es.java => OllamaEmbeddingProperties.java} | 47 +- ...ot.autoconfigure.AutoConfiguration.imports | 4 +- .../ollama/OllamaAutoConfigurationTests.java | 81 --- .../ollama/OllamaChatAutoConfigurationIT.java | 118 ++++ .../OllamaChatAutoConfigurationTests.java | 81 +++ ...> OllamaEmbeddingAutoConfigurationIT.java} | 53 +- ...OllamaEmbeddingAutoConfigurationTests.java | 80 +++ 28 files changed, 2421 insertions(+), 590 deletions(-) create mode 100644 models/spring-ai-ollama/README.md create mode 100644 models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java create mode 100644 models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingClient.java create mode 100644 models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApi.java create mode 100644 models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApiOptions.java delete mode 100644 models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaClient.java delete mode 100644 models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaGenerateResult.java create mode 100644 models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java create mode 100644 models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingClientIT.java create mode 100644 models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/OllamaApiIT.java delete mode 100644 models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/client/OllamaClientTests.java create mode 100644 models/spring-ai-ollama/src/test/resources/doc/Ollama Chat API.jpg delete mode 100644 spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java create mode 100644 spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfiguration.java create mode 100644 spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatProperties.java create mode 100644 spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfiguration.java rename spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/{OllamaProperties.java => OllamaEmbeddingProperties.java} (59%) delete mode 100644 spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationTests.java create mode 100644 spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java create mode 100644 spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationTests.java rename spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/{OllamaAutoConfigurationIT.java => OllamaEmbeddingAutoConfigurationIT.java} (50%) create mode 100644 spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationTests.java diff --git a/models/spring-ai-ollama/README.md b/models/spring-ai-ollama/README.md new file mode 100644 index 00000000000..d87417ed6b0 --- /dev/null +++ b/models/spring-ai-ollama/README.md @@ -0,0 +1,120 @@ +# 1. Ollama Chat and Embedding + +## 1.1 OllamaApi + +[OllamaApi](./src/main/java/org/springframework/ai/ollama/api/OllamaApi.java) provides is lightweight Java client for [Ollama models](https://ollama.ai/). + +The OllamaApi provides the Chat completion as well as Embedding endpoints. + +Following class diagram illustrates the OllamaApi interface and building blocks for chat completion: + +![OllamaApi Class Diagram](./src/test/resources/doc/Ollama%20Chat%20API.jpg) + +The OllamaApi can supports all [Ollama Models](https://ollama.ai/library) providing synchronous chat completion, streaming chat completion and embedding: + +```java +ChatResponse chat(ChatRequest chatRequest) + +Flux streamingChat(ChatRequest chatRequest) + +EmbeddingResponse embeddings(EmbeddingRequest embeddingRequest) +``` + +> NOTE: OllamaApi expose also the Ollama `generation` endpoint but later if inferior compared to the Ollama `chat` endpoint. + +The `OllamaApiOptions` is helper class used as type-safe option builder. It provides `toMap` to convert the content into `Map`. + +Here is a simple snippet how to use the OllamaApi programmatically: + +```java +var request = ChatRequest.builder("orca-mini") + .withStream(false) + .withMessages(List.of(Message.builder(Role.user) + .withContent("What is the capital of Bulgaria and what is the size? " + "What it the national anthem?") + .build())) + .withOptions(Options.builder().withTemperature(0.9f).build()) + .build(); + +ChatResponse response = ollamaApi.chat(request); +``` + +```java +var request = ChatRequest.builder("orca-mini") + .withStream(true) + .withMessages(List.of(Message.builder(Role.user) + .withContent("What is the capital of Bulgaria and what is the size? " + "What it the national anthem?") + .build())) + .withOptions(Options.builder().withTemperature(0.9f).build().toMap()) + .build(); + +Flux response = ollamaApi.streamingChat(request); + +List responses = response.collectList().block(); +``` + +```java +EmbeddingRequest request = new EmbeddingRequest("orca-mini", "I like to eat apples"); + +EmbeddingResponse response = ollamaApi.embeddings(request); +``` + +## 1.2 OllamaChatClient and OllamaEmbeddingClient + +The [OllamaChatClient](./src/main/java/org/springframework/ai/ollama/OllamaChatClient.java) implements the Spring-Ai `ChatClient` and `StreamingChatClient` interfaces. + +The [OllamaEmbeddingClient](./src/main/java/org/springframework/ai/ollama/OllamaEmbeddingClient.java) implements the Spring AI `EmbeddingClient` interface. + +Both the OllamaChatClient and the OllamaEmbeddingClient leverage the `OllamaApi`. + +You can configure the clients like this: + +```java +@Bean +public OllamaApi ollamaApi() { + return new OllamaApi(baseUrl); +} + +@Bean +public OllamaChatClient ollamaChat(OllamaApi ollamaApi) { + return new OllamaChatClient(ollamaApi).withModel(MODEL) + .withOptions(OllamaApiOptions.Options.builder().withTemperature(0.9f).build()); +} + +@Bean +public OllamaEmbeddingClient ollamaEmbedding(OllamaApi ollamaApi) { + return new OllamaEmbeddingClient(ollamaApi).withModel("orca-mini"); +} + +``` + +or you can leverage the `spring-ai-ollama-spring-boot-starter` Spring Boot starter. +For this add the following dependency: + +```xml + + spring-ai-ollama-spring-boot-starter + org.springframework.ai + 0.8.0-SNAPSHOT + +``` + +Use the `OllamaChatProperties` to configure the Ollama Chat client: + +| Property | Description | Default | +| ------------- | ------------- | ------------- | +| spring.ai.ollama.chat.model | Model to use. | llama2 | +| spring.ai.ollama.chat.base-url | The base url of the Ollama server. | http://localhost:11434 | +| spring.ai.ollama.chat.enabled | Allows you to disable the Ollama Chat autoconfiguration. | true | +| spring.ai.ollama.chat.temperature | Controls the randomness of the output. Values can range over [0.0,1.0] | 0.8 | +| spring.ai.ollama.chat.topP | The maximum cumulative probability of tokens to consider when sampling. | - | +| spring.ai.ollama.chat.topK | Max number or responses to generate. | - | +| spring.ai.options.chat.options (WIP) | A Map used to configure the Chat client. | - | + +and `OllamaEmbeddingProperties` to configure the Ollama Embedding client: + +| Property | Description | Default | +| ------------- | ------------- | ------------- | +| spring.ai.ollama.embedding.model | Model to use. | llama2 | +| spring.ai.ollama.embedding.base-url | The base url of the Ollama server. | http://localhost:11434 | +| spring.ai.ollama.embedding.enabled | Allows you to disable the Ollama embedding autoconfiguration. | true | +| spring.ai.options.embedding.options (WIP) | A Map used to configure the embedding client. | - | diff --git a/models/spring-ai-ollama/pom.xml b/models/spring-ai-ollama/pom.xml index fead80fc019..0da9e9a5353 100644 --- a/models/spring-ai-ollama/pom.xml +++ b/models/spring-ai-ollama/pom.xml @@ -1,7 +1,6 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.springframework.ai @@ -28,6 +27,23 @@ ${project.parent.version} + + org.springframework + spring-webflux + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson.version} + + org.springframework.boot spring-boot-starter-logging @@ -39,5 +55,17 @@ spring-boot-starter-test test + + + org.springframework.boot + spring-boot-testcontainers + test + + + + org.testcontainers + junit-jupiter + test + \ No newline at end of file diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java new file mode 100644 index 00000000000..517734205f5 --- /dev/null +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaChatClient.java @@ -0,0 +1,140 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.ollama; + +import java.util.List; +import java.util.Map; + +import reactor.core.publisher.Flux; + +import org.springframework.ai.chat.ChatClient; +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.chat.StreamingChatClient; +import org.springframework.ai.metadata.ChoiceMetadata; +import org.springframework.ai.metadata.Usage; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaApi.ChatRequest; +import org.springframework.ai.ollama.api.OllamaApi.Message.Role; +import org.springframework.ai.ollama.api.OllamaApiOptions; +import org.springframework.ai.prompt.Prompt; +import org.springframework.ai.prompt.messages.Message; +import org.springframework.ai.prompt.messages.MessageType; + +/** + * @author Christian Tzolov + * @since 0.8.0 + */ +public class OllamaChatClient implements ChatClient, StreamingChatClient { + + private final OllamaApi chatApi; + + private String model = "orca-mini"; + + private Map clientOptions; + + public OllamaChatClient(OllamaApi chatApi) { + this.chatApi = chatApi; + } + + public OllamaChatClient withModel(String model) { + this.model = model; + return this; + } + + public OllamaChatClient withOptions(Map options) { + this.clientOptions = options; + return this; + } + + public OllamaChatClient withOptions(OllamaApiOptions.Options options) { + this.clientOptions = options.toMap(); + return this; + } + + @Override + public ChatResponse generate(Prompt prompt) { + + OllamaApi.ChatResponse response = this.chatApi.chat(request(prompt, this.model, false)); + var generator = new Generation(response.message().content()); + if (response.promptEvalCount() != null && response.evalCount() != null) { + generator = generator.withChoiceMetadata(ChoiceMetadata.from("unknown", extractUsage(response))); + } + return new ChatResponse(List.of(new Generation(response.message().content()))); + } + + @Override + public Flux generateStream(Prompt prompt) { + + Flux response = this.chatApi.streamingChat(request(prompt, this.model, true)); + + return response.map(chunk -> { + Generation generation = (chunk.message() != null) ? new Generation(chunk.message().content()) + : new Generation(""); + if (chunk.done()) { + generation = generation.withChoiceMetadata(ChoiceMetadata.from("unknown", extractUsage(chunk))); + } + return new ChatResponse(List.of(generation)); + }); + } + + private Usage extractUsage(OllamaApi.ChatResponse response) { + return new Usage() { + + @Override + public Long getPromptTokens() { + return response.promptEvalCount().longValue(); + } + + @Override + public Long getGenerationTokens() { + return response.evalCount().longValue(); + } + }; + } + + private OllamaApi.ChatRequest request(Prompt prompt, String model, boolean stream) { + + List ollamaMessages = prompt.getMessages() + .stream() + .filter(message -> message.getMessageType() == MessageType.USER + || message.getMessageType() == MessageType.ASSISTANT) + .map(m -> OllamaApi.Message.builder(toRole(m)).withContent(m.getContent()).build()) + .toList(); + + return ChatRequest.builder(model) + .withStream(stream) + .withMessages(ollamaMessages) + .withOptions(this.clientOptions) + .build(); + } + + private OllamaApi.Message.Role toRole(Message message) { + + switch (message.getMessageType()) { + case USER: + return Role.user; + case ASSISTANT: + return Role.assistant; + case SYSTEM: + return Role.system; + default: + throw new IllegalArgumentException("Unsupported message type: " + message.getMessageType()); + } + } + +} \ No newline at end of file diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingClient.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingClient.java new file mode 100644 index 00000000000..c9385ebb203 --- /dev/null +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/OllamaEmbeddingClient.java @@ -0,0 +1,95 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.ollama; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import org.springframework.ai.document.Document; +import org.springframework.ai.embedding.AbstractEmbeddingClient; +import org.springframework.ai.embedding.Embedding; +import org.springframework.ai.embedding.EmbeddingResponse; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaApi.EmbeddingRequest; +import org.springframework.ai.ollama.api.OllamaApiOptions; +import org.springframework.util.Assert; + +/** + * @author Christian Tzolov + */ +public class OllamaEmbeddingClient extends AbstractEmbeddingClient { + + private final OllamaApi ollamaApi; + + private String model = "orca-mini"; + + private Map clientOptions; + + public OllamaEmbeddingClient(OllamaApi ollamaApi) { + this.ollamaApi = ollamaApi; + } + + public OllamaEmbeddingClient withModel(String model) { + this.model = model; + return this; + } + + public OllamaEmbeddingClient withOptions(Map options) { + this.clientOptions = options; + return this; + } + + public OllamaEmbeddingClient withOptions(OllamaApiOptions.Options options) { + this.clientOptions = options.toMap(); + return this; + } + + @Override + public List embed(String text) { + return this.embed(List.of(text)).iterator().next(); + } + + @Override + public List embed(Document document) { + return embed(document.getContent()); + } + + @Override + public List> embed(List texts) { + Assert.notEmpty(texts, "At least one text is required!"); + Assert.isTrue(texts.size() == 1, "Ollama Embedding does not support batch embedding!"); + + String inputContent = texts.iterator().next(); + + OllamaApi.EmbeddingResponse response = this.ollamaApi + .embeddings(new EmbeddingRequest(this.model, inputContent, this.clientOptions)); + + return List.of(response.embedding()); + } + + @Override + public EmbeddingResponse embedForResponse(List texts) { + var indexCounter = new AtomicInteger(0); + List embeddings = this.embed(texts) + .stream() + .map(e -> new Embedding(e, indexCounter.getAndIncrement())) + .toList(); + return new EmbeddingResponse(embeddings); + } + +} \ No newline at end of file diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApi.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApi.java new file mode 100644 index 00000000000..c102284a268 --- /dev/null +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApi.java @@ -0,0 +1,592 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.ollama.api; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import org.springframework.ai.ollama.api.OllamaApiOptions.Options; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.ResponseErrorHandler; +import org.springframework.web.client.RestClient; +import org.springframework.web.reactive.function.client.WebClient; + +/** + * Java Client for the Ollama API. https://ollama.ai/ + * + * @author Christian Tzolov + * @since 0.8.0 + */ +// @formatter:off +public class OllamaApi { + + private static final Log logger = LogFactory.getLog(OllamaApi.class); + + private final static String DEFAULT_BASE_URL = "http://localhost:11434"; + + private final ResponseErrorHandler responseErrorHandler; + + private final RestClient restClient; + + private final WebClient webClient; + + private static class OllamaResponseErrorHandler implements ResponseErrorHandler { + + @Override + public boolean hasError(ClientHttpResponse response) throws IOException { + return response.getStatusCode().isError(); + } + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + if (response.getStatusCode().isError()) { + int statusCode = response.getStatusCode().value(); + String statusText = response.getStatusText(); + String message = StreamUtils.copyToString(response.getBody(), java.nio.charset.StandardCharsets.UTF_8); + logger.warn(String.format("[%s] %s - %s", statusCode, statusText, message)); + throw new RuntimeException(String.format("[%s] %s - %s", statusCode, statusText, message)); + } + } + + } + + /** + * Default constructor that uses the default localhost url. + */ + public OllamaApi() { + this(DEFAULT_BASE_URL); + } + + /** + * Crate a new OllamaApi instance with the given base url. + * @param baseUrl The base url of the Ollama server. + */ + public OllamaApi(String baseUrl) { + this(baseUrl, RestClient.builder()); + } + + /** + * Crate a new OllamaApi instance with the given base url and + * {@link RestClient.Builder}. + * @param baseUrl The base url of the Ollama server. + * @param restClientBuilder The {@link RestClient.Builder} to use. + */ + public OllamaApi(String baseUrl, RestClient.Builder restClientBuilder) { + + this.responseErrorHandler = new OllamaResponseErrorHandler(); + + Consumer defaultHeaders = headers -> { + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + }; + + this.restClient = restClientBuilder.baseUrl(baseUrl).defaultHeaders(defaultHeaders).build(); + + this.webClient = WebClient.builder().baseUrl(baseUrl).defaultHeaders(defaultHeaders).build(); + } + + // -------------------------------------------------------------------------- + // Generate & Streaming Generate + // -------------------------------------------------------------------------- + /** + * The request object sent to the /generate endpoint. + * + * @param model (required) The model to use for completion. + * @param prompt (required) The prompt(s) to generate completions for. + * @param format (optional) The format to return the response in. Currently the only + * accepted value is "json". + * @param options (optional) additional model parameters listed in the documentation + * for the Modelfile such as temperature. + * @param system (optional) system prompt to (overrides what is defined in the Modelfile). + * @param template (optional) the full prompt or prompt template (overrides what is + * defined in the Modelfile). + * @param context the context parameter returned from a previous request to /generate, + * this can be used to keep a short conversational memory. + * @param stream (optional) if false the response will be returned as a single + * response object, rather than a stream of objects. + * @param raw (optional) if true no formatting will be applied to the prompt and no + * context will be returned. You may choose to use the raw parameter if you are + * specifying a full templated prompt in your request to the API, and are managing + * history yourself. + */ + @JsonInclude(Include.NON_NULL) + public record GenerateRequest( + @JsonProperty("model") String model, + @JsonProperty("prompt") String prompt, + @JsonProperty("format") String format, + @JsonProperty("options") Map options, + @JsonProperty("system") String system, + @JsonProperty("template") String template, + @JsonProperty("context") List context, + @JsonProperty("stream") Boolean stream, + @JsonProperty("raw") Boolean raw) { + + /** + * Short cut constructor to create a CompletionRequest without options. + * @param model The model used for completion. + * @param prompt The prompt(s) to generate completions for. + * @param stream Whether to stream the response. + */ + public GenerateRequest(String model, String prompt, Boolean stream) { + this(model, prompt, null, null, null, null, null, stream, null); + } + + /** + * Short cut constructor to create a CompletionRequest without options. + * @param model The model used for completion. + * @param prompt The prompt(s) to generate completions for. + * @param enableJsonFormat Whether to return the response in json format. + * @param stream Whether to stream the response. + */ + public GenerateRequest(String model, String prompt, boolean enableJsonFormat, Boolean stream) { + this(model, prompt, (enableJsonFormat) ? "json" : null, null, null, null, null, stream, null); + } + + /** + * Create a CompletionRequest builder. + * @param prompt The prompt(s) to generate completions for. + */ + public static Builder builder(String prompt) { + return new Builder(prompt); + } + + public static class Builder { + + private String model; + private final String prompt; + private String format; + private Map options; + private String system; + private String template; + private List context; + private Boolean stream; + private Boolean raw; + + public Builder(String prompt) { + this.prompt = prompt; + } + + public Builder withModel(String model) { + this.model = model; + return this; + } + + public Builder withFormat(String format) { + this.format = format; + return this; + } + + public Builder withOptions(Map options) { + this.options = options; + return this; + } + + public Builder withOptions(Options options) { + this.options = options.toMap(); + return this; + } + + public Builder withSystem(String system) { + this.system = system; + return this; + } + + public Builder withTemplate(String template) { + this.template = template; + return this; + } + + public Builder withContext(List context) { + this.context = context; + return this; + } + + public Builder withStream(Boolean stream) { + this.stream = stream; + return this; + } + + public Builder withRaw(Boolean raw) { + this.raw = raw; + return this; + } + + public GenerateRequest build() { + return new GenerateRequest(model, prompt, format, options, system, template, context, stream, raw); + } + + } + } + + /** + * The response object returned from the /generate endpoint. To calculate how fast the + * response is generated in tokens per second (token/s), divide eval_count / + * eval_duration. + * + * @param model The model used for completion. + * @param createdAt When the request was made. + * @param response The completion response. Empty if the response was streamed, if not + * streamed, this will contain the full response + * @param done Whether this is the final response. If true, this response may be + * followed by another response with the following, additional fields: context, + * prompt_eval_count, prompt_eval_duration, eval_count, eval_duration. + * @param context Encoding of the conversation used in this response, this can be sent + * in the next request to keep a conversational memory. + * @param totalDuration Time spent generating the response. + * @param loadDuration Time spent loading the model. + * @param promptEvalCount Number of times the prompt was evaluated. + * @param promptEvalDuration Time spent evaluating the prompt. + * @param evalCount Number of tokens in the response. + * @param evalDuration Time spent generating the response. + */ + @JsonInclude(Include.NON_NULL) + public record GenerateResponse( + @JsonProperty("model") String model, + @JsonProperty("created_at") Instant createdAt, + @JsonProperty("response") String response, + @JsonProperty("done") Boolean done, + @JsonProperty("context") List context, + @JsonProperty("total_duration") Duration totalDuration, + @JsonProperty("load_duration") Duration loadDuration, + @JsonProperty("prompt_eval_count") Integer promptEvalCount, + @JsonProperty("prompt_eval_duration") Duration promptEvalDuration, + @JsonProperty("eval_count") Integer evalCount, + @JsonProperty("eval_duration") Duration evalDuration) { + } + + /** + * Generate a completion for the given prompt. + * @param completionRequest Completion request. + * @return Completion response. + */ + public GenerateResponse generate(GenerateRequest completionRequest) { + Assert.notNull(completionRequest, "The request body can not be null."); + Assert.isTrue(completionRequest.stream() == false, "Stream mode must be disabled."); + + return this.restClient.post() + .uri("/api/generate") + .body(completionRequest) + .retrieve() + .onStatus(this.responseErrorHandler) + .body(GenerateResponse.class); + } + + /** + * Generate a streaming completion for the given prompt. + * @param completionRequest Completion request. The request must set the stream + * property to true. + * @return Completion response as a {@link Flux} stream. + */ + public Flux generateStreaming(GenerateRequest completionRequest) { + Assert.notNull(completionRequest, "The request body can not be null."); + Assert.isTrue(completionRequest.stream(), "Request must set the steam property to true."); + + return webClient.post() + .uri("/api/generate") + .body(Mono.just(completionRequest), GenerateRequest.class) + .retrieve() + .bodyToFlux(GenerateResponse.class) + .handle((data, sink) -> { + System.out.println(data); + sink.next(data); + }); + } + + // -------------------------------------------------------------------------- + // Chat & Streaming Chat + // -------------------------------------------------------------------------- + /** + * Chat message object. + * + * @param role The role of the message of type {@link Role}. + * @param content The content of the message. + * @param images The list of images to send with the message. + */ + @JsonInclude(Include.NON_NULL) + public record Message( + @JsonProperty("role") Role role, + @JsonProperty("content") String content, + @JsonProperty("images") List images) { + + /** + * The role of the message in the conversation. + */ + public enum Role { + + /** + * System message type used as instructions to the model. + */ + system, + /** + * User message type. + */ + user, + /** + * Assistant message type. Usually the response from the model. + */ + assistant; + + } + + public static Builder builder(Role role) { + return new Builder(role); + } + + public static class Builder { + + private final Role role; + private String content; + private List images; + + public Builder(Role role) { + this.role = role; + } + + public Builder withContent(String content) { + this.content = content; + return this; + } + + public Builder withImages(List images) { + this.images = images; + return this; + } + + public Message build() { + return new Message(role, content, images); + } + + } + } + + /** + * Chat request object. + * + * @param model The model to use for completion. + * @param messages The list of messages to chat with. + * @param stream Whether to stream the response. + * @param format The format to return the response in. Currently the only accepted + * value is "json". + * @param options Additional model parameters. You can use the {@link Options} builder + * to create the options then {@link Options#toMap()} to convert the options into a + * map. + */ + @JsonInclude(Include.NON_NULL) + public record ChatRequest( + @JsonProperty("model") String model, + @JsonProperty("messages") List messages, + @JsonProperty("stream") Boolean stream, + @JsonProperty("format") String format, + @JsonProperty("options") Map options) { + + public static Builder builder(String model) { + return new Builder(model); + } + + public static class Builder { + + private final String model; + private List messages = List.of(); + private boolean stream = false; + private String format; + private Map options = Map.of(); + + public Builder(String model) { + Assert.notNull(model, "The model can not be null."); + this.model = model; + } + + public Builder withMessages(List messages) { + this.messages = messages; + return this; + } + + public Builder withStream(boolean stream) { + this.stream = stream; + return this; + } + + public Builder withFormat(String format) { + this.format = format; + return this; + } + + public Builder withOptions(Map options) { + this.options = options; + return this; + } + + public Builder withOptions(Options options) { + this.options = options.toMap(); + return this; + } + + public ChatRequest build() { + return new ChatRequest(model, messages, stream, format, options); + } + + } + } + + /** + * Ollama chat response object. + * + * @param model The model name used for completion. + * @param createdAt When the request was made. + * @param message The response {@link Message} with {@link Message.Role#assistant}. + * @param done Whether this is the final response. For streaming response only the + * last message is marked as done. If true, this response may be followed by another + * response with the following, additional fields: context, prompt_eval_count, + * prompt_eval_duration, eval_count, eval_duration. + * @param totalDuration Time spent generating the response. + * @param loadDuration Time spent loading the model. + * @param promptEvalCount number of tokens in the prompt.(*) + * @param promptEvalDuration time spent evaluating the prompt. + * @param evalCount number of tokens in the response. + * @param evalDuration time spent generating the response. + * @see Chat + * Completion API + * @see Ollama + * Types + */ + @JsonInclude(Include.NON_NULL) + public record ChatResponse( + @JsonProperty("model") String model, + @JsonProperty("created_at") Instant createdAt, + @JsonProperty("message") Message message, + @JsonProperty("done") Boolean done, + @JsonProperty("total_duration") Duration totalDuration, + @JsonProperty("load_duration") Duration loadDuration, + @JsonProperty("prompt_eval_count") Integer promptEvalCount, + @JsonProperty("prompt_eval_duration") Duration promptEvalDuration, + @JsonProperty("eval_count") Integer evalCount, + @JsonProperty("eval_duration") Duration evalDuration) { + } + + /** + * Generate the next message in a chat with a provided model. + * + * This is a streaming endpoint (controlled by the 'stream' request property), so + * there will be a series of responses. The final response object will include + * statistics and additional data from the request. + * @param chatRequest Chat request. + * @return Chat response. + */ + public ChatResponse chat(ChatRequest chatRequest) { + Assert.notNull(chatRequest, "The request body can not be null."); + Assert.isTrue(!chatRequest.stream(), "Stream mode must be disabled."); + + return this.restClient.post() + .uri("/api/chat") + .body(chatRequest) + .retrieve() + .onStatus(this.responseErrorHandler) + .body(ChatResponse.class); + } + + /** + * Streaming response for the chat completion request. + * @param chatRequest Chat request. The request must set the stream property to true. + * @return Chat response as a {@link Flux} stream. + */ + public Flux streamingChat(ChatRequest chatRequest) { + Assert.notNull(chatRequest, "The request body can not be null."); + Assert.isTrue(chatRequest.stream(), "Request must set the steam property to true."); + + return webClient.post() + .uri("/api/chat") + .body(Mono.just(chatRequest), GenerateRequest.class) + .retrieve() + .bodyToFlux(ChatResponse.class) + .handle((data, sink) -> { + System.out.println(data); + sink.next(data); + }); + } + + // -------------------------------------------------------------------------- + // Embeddings + // -------------------------------------------------------------------------- + /** + * Generate embeddings from a model. + * + * @param model The name of model to generate embeddings from. + * @param prompt The text to generate embeddings for. + * @param options Additional model parameters listed in the documentation for the + * Modelfile such as temperature. + */ + @JsonInclude(Include.NON_NULL) + public record EmbeddingRequest( + @JsonProperty("model") String model, + @JsonProperty("prompt") String prompt, + @JsonProperty("options") Map options) { + + /** + * short cut constructor to create a EmbeddingRequest without options. + * @param model The name of model to generate embeddings from. + * @param prompt The text to generate embeddings for. + */ + public EmbeddingRequest(String model, String prompt) { + this(model, prompt, null); + } + } + + /** + * The response object returned from the /embedding endpoint. + * + * @param embedding The embedding generated from the model. + */ + @JsonInclude(Include.NON_NULL) + public record EmbeddingResponse( + @JsonProperty("embedding") List embedding) { + } + + /** + * Generate embeddings from a model. + * @param embeddingRequest Embedding request. + * @return Embedding response. + */ + public EmbeddingResponse embeddings(EmbeddingRequest embeddingRequest) { + Assert.notNull(embeddingRequest, "The request body can not be null."); + + return this.restClient.post() + .uri("/api/embeddings") + .body(embeddingRequest) + .retrieve() + .onStatus(this.responseErrorHandler) + .body(EmbeddingResponse.class); + } + +} +// @formatter:on \ No newline at end of file diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApiOptions.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApiOptions.java new file mode 100644 index 00000000000..2f0beeba49d --- /dev/null +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaApiOptions.java @@ -0,0 +1,395 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.ollama.api; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Helper class for building strongly typed the Ollama request options. + * + * @author Christian Tzolov + * @since 0.8.0 + */ +// @formatter:on +public class OllamaApiOptions { + + /** + * Runner options which must be set when the model is loaded into memory. + * + * @param useNUMA Whether to use NUMA. + * @param numCtx Sets the size of the context window used to generate the next token. + * (Default: 2048) + * @param numBatch ??? + * @param numGQA The number of GQA groups in the transformer layer. Required for some + * models, for example it is 8 for llama2:70b. + * @param numGPU The number of layers to send to the GPU(s). On macOS it defaults to 1 + * to enable metal support, 0 to disable. + * @param mainGPU ??? + * @param lowVRAM ??? + * @param f16KV ??? + * @param logitsAll ??? + * @param vocabOnly ??? + * @param useMMap ??? + * @param useMLock ??? + * @param embeddingOnly ??? + * @param ropeFrequencyBase ??? + * @param ropeFrequencyScale ??? + * @param numThread Sets the number of threads to use during computation. By default, + * Ollama will detect this for optimal performance. It is recommended to set this + * value to the number of physical CPU cores your system has (as opposed to the + * logical number of cores). + * + * Options specified in GenerateRequest. + * @param mirostat Enable Mirostat sampling for controlling perplexity. (default: 0, 0 + * = disabled, 1 = Mirostat, 2 = Mirostat 2.0) + * @param mirostatTau Influences how quickly the algorithm responds to feedback from + * the generated text. A lower learning rate will result in slower adjustments, while + * a higher learning rate will make the algorithm more responsive. (Default: 0.1). + * @param mirostatEta Controls the balance between coherence and diversity of the + * output. A lower value will result in more focused and coherent text. (Default: + * 5.0). + * @param numKeep Unknown. + * @param seed Sets the random number seed to use for generation. Setting this to a + * specific number will make the model generate the same text for the same prompt. + * (Default: 0) + * @param numPredict Maximum number of tokens to predict when generating text. + * (Default: 128, -1 = infinite generation, -2 = fill context) + * @param topK Reduces the probability of generating nonsense. A higher value (e.g. + * 100) will give more diverse answers, while a lower value (e.g. 10) will be more + * conservative. (Default: 40) + * @param topP Works together with top-k. A higher value (e.g., 0.95) will lead to + * more diverse text, while a lower value (e.g., 0.5) will generate more focused and + * conservative text. (Default: 0.9) + * @param tfsZ Tail free sampling is used to reduce the impact of less probable tokens + * from the output. A higher value (e.g., 2.0) will reduce the impact more, while a + * value of 1.0 disables this setting. (default: 1) + * @param typicalP Unknown. + * @param repeatLastN Sets how far back for the model to look back to prevent + * repetition. (Default: 64, 0 = disabled, -1 = num_ctx) + * @param temperature The temperature of the model. Increasing the temperature will + * make the model answer more creatively. (Default: 0.8) + * @param repeatPenalty Sets how strongly to penalize repetitions. A higher value + * (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., + * 0.9) will be more lenient. (Default: 1.1) + * @param presencePenalty Unknown. + * @param frequencyPenalty Unknown. + * @param penalizeNewline Unknown. + * @param stop Sets the stop sequences to use. When this pattern is encountered the + * LLM will stop generating text and return. Multiple stop patterns may be set by + * specifying multiple separate stop parameters in a modelfile. + * @see Ollama + * Valid Parameters and Values + * @see Ollama Go + * Types + */ + @JsonInclude(Include.NON_NULL) + public record Options( + // Runner options which must be set when the model is loaded into memory. + @JsonProperty("numa") Boolean useNUMA, @JsonProperty("num_ctx") Integer numCtx, + @JsonProperty("num_batch") Integer numBatch, @JsonProperty("num_gqa") Integer numGQA, + @JsonProperty("num_gpu") Integer numGPU, @JsonProperty("main_gpu") Integer mainGPU, + @JsonProperty("low_vram") Boolean lowVRAM, @JsonProperty("f16_kv") Boolean f16KV, + @JsonProperty("logits_all") Boolean logitsAll, @JsonProperty("vocab_only") Boolean vocabOnly, + @JsonProperty("use_mmap") Boolean useMMap, @JsonProperty("use_mlock") Boolean useMLock, + @JsonProperty("embedding_only") Boolean embeddingOnly, + @JsonProperty("rope_frequency_base") Float ropeFrequencyBase, + @JsonProperty("rope_frequency_scale") Float ropeFrequencyScale, + @JsonProperty("num_thread") Integer numThread, + + // Options specified in GenerateRequest. + @JsonProperty("num_keep") Integer numKeep, @JsonProperty("seed") Integer seed, + @JsonProperty("num_predict") Integer numPredict, @JsonProperty("top_k") Integer topK, + @JsonProperty("top_p") Float topP, @JsonProperty("tfs_z") Float tfsZ, + @JsonProperty("typical_p") Float typicalP, @JsonProperty("repeat_last_n") Integer repeatLastN, + @JsonProperty("temperature") Float temperature, @JsonProperty("repeat_penalty") Float repeatPenalty, + @JsonProperty("presence_penalty") Float presencePenalty, + @JsonProperty("frequency_penalty") Float frequencyPenalty, @JsonProperty("mirostat") Integer mirostat, + @JsonProperty("mirostat_tau") Float mirostatTau, @JsonProperty("mirostat_eta") Float mirostatEta, + @JsonProperty("penalize_newline") Boolean penalizeNewline, @JsonProperty("stop") String[] stop) { + + /** + * Convert the {@link Options} object to a {@link Map} of key/value pairs. + * @return The {@link Map} of key/value pairs. + */ + public Map toMap() { + try { + var json = new ObjectMapper().writeValueAsString(this); + return new ObjectMapper().readValue(json, new TypeReference>() { + }); + } + catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private Boolean useNUMA; + + private Integer numCtx; + + private Integer numBatch; + + private Integer numGQA; + + private Integer numGPU; + + private Integer mainGPU; + + private Boolean lowVRAM; + + private Boolean f16KV; + + private Boolean logitsAll; + + private Boolean vocabOnly; + + private Boolean useMMap; + + private Boolean useMLock; + + private Boolean embeddingOnly; + + private Float ropeFrequencyBase; + + private Float ropeFrequencyScale; + + private Integer numThread; + + private Integer numKeep; + + private Integer seed; + + private Integer numPredict; + + private Integer topK; + + private Float topP; + + private Float tfsZ; + + private Float typicalP; + + private Integer repeatLastN; + + private Float temperature; + + private Float repeatPenalty; + + private Float presencePenalty; + + private Float frequencyPenalty; + + private Integer mirostat; + + private Float mirostatTau; + + private Float mirostatEta; + + private Boolean penalizeNewline; + + private String[] stop; + + public Builder withUseNUMA(Boolean useNUMA) { + this.useNUMA = useNUMA; + return this; + } + + public Builder withNumCtx(Integer numCtx) { + this.numCtx = numCtx; + return this; + } + + public Builder withNumBatch(Integer numBatch) { + this.numBatch = numBatch; + return this; + } + + public Builder withNumGQA(Integer numGQA) { + this.numGQA = numGQA; + return this; + } + + public Builder withNumGPU(Integer numGPU) { + this.numGPU = numGPU; + return this; + } + + public Builder withMainGPU(Integer mainGPU) { + this.mainGPU = mainGPU; + return this; + } + + public Builder withLowVRAM(Boolean lowVRAM) { + this.lowVRAM = lowVRAM; + return this; + } + + public Builder withF16KV(Boolean f16KV) { + this.f16KV = f16KV; + return this; + } + + public Builder withLogitsAll(Boolean logitsAll) { + this.logitsAll = logitsAll; + return this; + } + + public Builder withVocabOnly(Boolean vocabOnly) { + this.vocabOnly = vocabOnly; + return this; + } + + public Builder withUseMMap(Boolean useMMap) { + this.useMMap = useMMap; + return this; + } + + public Builder withUseMLock(Boolean useMLock) { + this.useMLock = useMLock; + return this; + } + + public Builder withEmbeddingOnly(Boolean embeddingOnly) { + this.embeddingOnly = embeddingOnly; + return this; + } + + public Builder withRopeFrequencyBase(Float ropeFrequencyBase) { + this.ropeFrequencyBase = ropeFrequencyBase; + return this; + } + + public Builder withRopeFrequencyScale(Float ropeFrequencyScale) { + this.ropeFrequencyScale = ropeFrequencyScale; + return this; + } + + public Builder withNumThread(Integer numThread) { + this.numThread = numThread; + return this; + } + + public Builder withNumKeep(Integer numKeep) { + this.numKeep = numKeep; + return this; + } + + public Builder withSeed(Integer seed) { + this.seed = seed; + return this; + } + + public Builder withNumPredict(Integer numPredict) { + this.numPredict = numPredict; + return this; + } + + public Builder withTopK(Integer topK) { + this.topK = topK; + return this; + } + + public Builder withTopP(Float topP) { + this.topP = topP; + return this; + } + + public Builder withTfsZ(Float tfsZ) { + this.tfsZ = tfsZ; + return this; + } + + public Builder withTypicalP(Float typicalP) { + this.typicalP = typicalP; + return this; + } + + public Builder withRepeatLastN(Integer repeatLastN) { + this.repeatLastN = repeatLastN; + return this; + } + + public Builder withTemperature(Float temperature) { + this.temperature = temperature; + return this; + } + + public Builder withRepeatPenalty(Float repeatPenalty) { + this.repeatPenalty = repeatPenalty; + return this; + } + + public Builder withPresencePenalty(Float presencePenalty) { + this.presencePenalty = presencePenalty; + return this; + } + + public Builder withFrequencyPenalty(Float frequencyPenalty) { + this.frequencyPenalty = frequencyPenalty; + return this; + } + + public Builder withMirostat(Integer mirostat) { + this.mirostat = mirostat; + return this; + } + + public Builder withMirostatTau(Float mirostatTau) { + this.mirostatTau = mirostatTau; + return this; + } + + public Builder withMirostatEta(Float mirostatEta) { + this.mirostatEta = mirostatEta; + return this; + } + + public Builder withPenalizeNewline(Boolean penalizeNewline) { + this.penalizeNewline = penalizeNewline; + return this; + } + + public Builder withStop(String[] stop) { + this.stop = stop; + return this; + } + + public Options build() { + return new Options(useNUMA, numCtx, numBatch, numGQA, numGPU, mainGPU, lowVRAM, f16KV, logitsAll, + vocabOnly, useMMap, useMLock, embeddingOnly, ropeFrequencyBase, ropeFrequencyScale, numThread, + numKeep, seed, numPredict, topK, topP, tfsZ, typicalP, repeatLastN, temperature, repeatPenalty, + presencePenalty, frequencyPenalty, mirostat, mirostatTau, mirostatEta, penalizeNewline, stop); + } + + } + } + +} +// @formatter:on \ No newline at end of file diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaClient.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaClient.java deleted file mode 100644 index 11b10282ee6..00000000000 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaClient.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.springframework.ai.ollama.client; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.ai.chat.ChatClient; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.chat.Generation; -import org.springframework.ai.prompt.Prompt; -import org.springframework.util.CollectionUtils; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.Duration; -import java.util.*; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -/** - * A client implementation for interacting with Ollama Service. This class acts as an - * interface between the application and the Ollama AI Service, handling request creation, - * communication, and response processing. - * - * @author nullptr - */ -public class OllamaClient implements ChatClient { - - /** Logger for logging the events and messages. */ - private static final Logger log = LoggerFactory.getLogger(OllamaClient.class); - - /** Mapper for JSON serialization and deserialization. */ - private static final ObjectMapper jsonMapper = new ObjectMapper(); - - /** HTTP client for making asynchronous calls to the Ollama Service. */ - private static final HttpClient httpClient = HttpClient.newBuilder().build(); - - /** Base URL of the Ollama Service. */ - private final String baseUrl; - - /** Name of the model to be used for the AI service. */ - private final String model; - - /** Optional callback to handle individual generation results. */ - private Consumer simpleCallback; - - /** - * Constructs an OllamaClient with the specified base URL and model. - * @param baseUrl Base URL of the Ollama Service. - * @param model Model specification for the AI service. - */ - public OllamaClient(String baseUrl, String model) { - this.baseUrl = baseUrl; - this.model = model; - } - - /** - * Constructs an OllamaClient with the specified base URL, model, and a callback. - * @param baseUrl Base URL of the Ollama Service. - * @param model Model specification for the AI service. - * @param simpleCallback Callback to handle individual generation results. - */ - public OllamaClient(String baseUrl, String model, Consumer simpleCallback) { - this(baseUrl, model); - this.simpleCallback = simpleCallback; - } - - @Override - public ChatResponse generate(Prompt prompt) { - validatePrompt(prompt); - - HttpRequest request = buildHttpRequest(prompt); - var response = sendRequest(request); - - List results = readGenerateResults(response.body()); - return getAiResponse(results); - } - - /** - * Validates the provided prompt. - * @param prompt The prompt to validate. - */ - protected void validatePrompt(Prompt prompt) { - if (CollectionUtils.isEmpty(prompt.getMessages())) { - throw new RuntimeException("The prompt message cannot be empty."); - } - - if (prompt.getMessages().size() > 1) { - log.warn("Only the first prompt message will be used; subsequent messages will be ignored."); - } - } - - /** - * Constructs an HTTP request for the provided prompt. - * @param prompt The prompt for which the request needs to be built. - * @return The constructed HttpRequest. - */ - protected HttpRequest buildHttpRequest(Prompt prompt) { - String requestBody = getGenerateRequestBody(prompt.getMessages().get(0).getContent()); - - // remove the suffix '/' if necessary - String url = !this.baseUrl.endsWith("/") ? this.baseUrl : this.baseUrl.substring(0, this.baseUrl.length() - 1); - - return HttpRequest.newBuilder() - .uri(URI.create("%s/api/generate".formatted(url))) - .POST(HttpRequest.BodyPublishers.ofString(requestBody)) - .timeout(Duration.ofMinutes(5L)) - .build(); - } - - /** - * Sends the constructed HttpRequest and retrieves the HttpResponse. - * @param request The HttpRequest to be sent. - * @return HttpResponse containing the response data. - */ - protected HttpResponse sendRequest(HttpRequest request) { - var response = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).join(); - if (response.statusCode() != 200) { - throw new RuntimeException("Ollama call returned an unexpected status: " + response.statusCode()); - } - return response; - } - - /** - * Serializes the prompt into a request body for the Ollama API call. - * @param prompt The prompt to be serialized. - * @return Serialized request body as a String. - */ - private String getGenerateRequestBody(String prompt) { - var data = Map.of("model", model, "prompt", prompt); - try { - return jsonMapper.writeValueAsString(data); - } - catch (JsonProcessingException ex) { - throw new RuntimeException("Failed to serialize the prompt to JSON", ex); - } - - } - - /** - * Reads and processes the results from the InputStream provided by the Ollama - * Service. - * @param inputStream InputStream containing the results from the Ollama Service. - * @return List of OllamaGenerateResult. - */ - protected List readGenerateResults(InputStream inputStream) { - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) { - var results = new ArrayList(); - String line; - while ((line = bufferedReader.readLine()) != null) { - processResponseLine(line, results); - } - return results; - } - catch (IOException e) { - throw new RuntimeException("Error parsing Ollama generation response.", e); - } - } - - /** - * Processes a single line from the Ollama response. - * @param line The line to be processed. - * @param results List to which parsed results will be added. - */ - protected void processResponseLine(String line, List results) { - if (line.isBlank()) - return; - - log.debug("Received ollama generate response: {}", line); - - OllamaGenerateResult result; - try { - result = jsonMapper.readValue(line, OllamaGenerateResult.class); - } - catch (IOException e) { - throw new RuntimeException("Error parsing response line from Ollama.", e); - } - - if (result.getModel() == null || result.getDone() == null) { - throw new IllegalStateException("Received invalid data from Ollama. Model = " + result.getModel() - + " , Done = " + result.getDone()); - - } - - if (simpleCallback != null) { - simpleCallback.accept(result); - } - - results.add(result); - } - - /** - * Converts the list of OllamaGenerateResult into a structured ChatResponse. - * @param results List of OllamaGenerateResult. - * @return Formulated ChatResponse. - */ - protected ChatResponse getAiResponse(List results) { - var ollamaResponse = results.stream() - .filter(Objects::nonNull) - .filter(it -> it.getResponse() != null && !it.getResponse().isBlank()) - .filter(it -> it.getDone() != null) - .map(OllamaGenerateResult::getResponse) - .collect(Collectors.joining("")); - - var generation = new Generation(ollamaResponse); - - // TODO investigate mapping of additional metadata/runtime info to the response. - return new ChatResponse(Collections.singletonList(generation)); - } - - /** - * @return Model name for the AI service. - */ - public String getModel() { - return model; - } - - /** - * @return Base URL of the Ollama Service. - */ - public String getBaseUrl() { - return baseUrl; - } - - /** - * @return Callback that handles individual generation results. - */ - public Consumer getSimpleCallback() { - return simpleCallback; - } - - /** - * Sets the callback that handles individual generation results. - * @param simpleCallback The callback to be set. - */ - public void setSimpleCallback(Consumer simpleCallback) { - this.simpleCallback = simpleCallback; - } - -} diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaGenerateResult.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaGenerateResult.java deleted file mode 100644 index f6f997d64d2..00000000000 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/client/OllamaGenerateResult.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.springframework.ai.ollama.client; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.List; - -/** - * Ollama generate a completion api response model - * - * @author nullptr - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class OllamaGenerateResult { - - @JsonProperty("model") - private String model; - - @JsonProperty("created_at") - private String createdAt; - - @JsonProperty("response") - private String response; - - @JsonProperty("done") - private Boolean done; - - @JsonProperty("context") - private List context; - - @JsonProperty("total_duration") - private Long totalDuration; - - @JsonProperty("load_duration") - private Long loadDuration; - - @JsonProperty("prompt_eval_count") - private Long promptEvalCount; - - @JsonProperty("prompt_eval_duration") - private Long promptEvalDuration; - - @JsonProperty("eval_count") - private Long evalCount; - - @JsonProperty("eval_duration") - private Long evalDuration; - - public String getModel() { - return model; - } - - public void setModel(String model) { - this.model = model; - } - - public String getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(String createdAt) { - this.createdAt = createdAt; - } - - public String getResponse() { - return response; - } - - public void setResponse(String response) { - this.response = response; - } - - public Boolean getDone() { - return done; - } - - public void setDone(Boolean done) { - this.done = done; - } - - public List getContext() { - return context; - } - - public void setContext(List context) { - this.context = context; - } - - public Long getTotalDuration() { - return totalDuration; - } - - public void setTotalDuration(Long totalDuration) { - this.totalDuration = totalDuration; - } - - public Long getLoadDuration() { - return loadDuration; - } - - public void setLoadDuration(Long loadDuration) { - this.loadDuration = loadDuration; - } - - public Long getPromptEvalCount() { - return promptEvalCount; - } - - public void setPromptEvalCount(Long promptEvalCount) { - this.promptEvalCount = promptEvalCount; - } - - public Long getPromptEvalDuration() { - return promptEvalDuration; - } - - public void setPromptEvalDuration(Long promptEvalDuration) { - this.promptEvalDuration = promptEvalDuration; - } - - public Long getEvalCount() { - return evalCount; - } - - public void setEvalCount(Long evalCount) { - this.evalCount = evalCount; - } - - public Long getEvalDuration() { - return evalDuration; - } - - public void setEvalDuration(Long evalDuration) { - this.evalDuration = evalDuration; - } - - @Override - public String toString() { - return "OllamaGenerateResult{" + "model='" + model + '\'' + ", createdAt='" + createdAt + '\'' + ", response='" - + response + '\'' + ", done='" + done + '\'' + ", context=" + context + ", totalDuration=" - + totalDuration + ", loadDuration=" + loadDuration + ", promptEvalCount=" + promptEvalCount - + ", promptEvalDuration=" + promptEvalDuration + ", evalCount=" + evalCount + ", evalDuration=" - + evalDuration + '}'; - } - -} diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java new file mode 100644 index 00000000000..c0120220735 --- /dev/null +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatClientIT.java @@ -0,0 +1,192 @@ +package org.springframework.ai.ollama; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaApiOptions; +import org.springframework.ai.parser.BeanOutputParser; +import org.springframework.ai.parser.ListOutputParser; +import org.springframework.ai.parser.MapOutputParser; +import org.springframework.ai.prompt.Prompt; +import org.springframework.ai.prompt.PromptTemplate; +import org.springframework.ai.prompt.SystemPromptTemplate; +import org.springframework.ai.prompt.messages.Message; +import org.springframework.ai.prompt.messages.UserMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.core.convert.support.DefaultConversionService; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@Testcontainers +@Disabled("For manual smoke testing only.") +class OllamaChatClientIT { + + private static String MODEL = "mistral"; + + private static final Log logger = LogFactory.getLog(OllamaChatClientIT.class); + + @Container + static GenericContainer ollamaContainer = new GenericContainer<>("ollama/ollama:0.1.15").withExposedPorts(11434); + + static String baseUrl; + + @BeforeAll + public static void beforeAll() throws IOException, InterruptedException { + logger.info("Start pulling the '" + MODEL + " ' model ... would take several minutes ..."); + ollamaContainer.execInContainer("ollama", "pull", MODEL); + logger.info(MODEL + " pulling competed!"); + + baseUrl = "http://" + ollamaContainer.getHost() + ":" + ollamaContainer.getMappedPort(11434); + } + + @Autowired + private OllamaChatClient client; + + @Test + void roleTest() { + Message systemMessage = new SystemPromptTemplate(""" + You are a helpful AI assistant. Your name is {name}. + You are an AI assistant that helps people find information. + Your name is {name} + You should reply to the user's request with your name and also in the style of a {voice}. + """).createMessage(Map.of("name", "Bob", "voice", "pirate")); + + UserMessage userMessage = new UserMessage("Tell me about 5 famous pirates from the Golden Age of Piracy."); + + Prompt prompt = new Prompt(List.of(userMessage, systemMessage)); + ChatResponse response = client.generate(prompt); + assertThat(response.getGeneration().getContent()).contains("Blackbeard"); + } + + @Disabled("TODO: Fix the parser instructions to return the correct format") + @Test + void outputParser() { + DefaultConversionService conversionService = new DefaultConversionService(); + ListOutputParser outputParser = new ListOutputParser(conversionService); + + String format = outputParser.getFormat(); + String template = """ + List five {subject} + {format} + """; + PromptTemplate promptTemplate = new PromptTemplate(template, + Map.of("subject", "ice cream flavors.", "format", format)); + Prompt prompt = new Prompt(promptTemplate.createMessage()); + Generation generation = this.client.generate(prompt).getGeneration(); + + List list = outputParser.parse(generation.getContent()); + assertThat(list).hasSize(5); + } + + @Disabled("TODO: Fix the parser instructions to return the correct format") + @Test + void mapOutputParser() { + MapOutputParser outputParser = new MapOutputParser(); + + String format = outputParser.getFormat(); + String template = """ + Remove Markdown code blocks from the output. + Provide me a List of {subject} + {format} + """; + PromptTemplate promptTemplate = new PromptTemplate(template, + Map.of("subject", "an array of numbers from 1 to 9 under they key name 'numbers'", "format", format)); + Prompt prompt = new Prompt(promptTemplate.createMessage()); + + Generation generation = client.generate(prompt).getGeneration(); + + Map result = outputParser.parse(generation.getContent()); + assertThat(result.get("numbers")).isEqualTo(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); + + } + + record ActorsFilmsRecord(String actor, List movies) { + } + + @Disabled("TODO: Fix the parser instructions to return the correct format") + @Test + void beanOutputParserRecords() { + + BeanOutputParser outputParser = new BeanOutputParser<>(ActorsFilmsRecord.class); + + String format = outputParser.getFormat(); + String template = """ + Generate the filmography of 5 movies for Tom Hanks. + {format} + Remove Markdown code blocks from the output. + """; + PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); + Prompt prompt = new Prompt(promptTemplate.createMessage()); + Generation generation = client.generate(prompt).getGeneration(); + + ActorsFilmsRecord actorsFilms = outputParser.parse(generation.getContent()); + assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); + assertThat(actorsFilms.movies()).hasSize(5); + } + + @Disabled("TODO: Fix the parser instructions to return the correct format") + @Test + void beanStreamOutputParserRecords() { + + BeanOutputParser outputParser = new BeanOutputParser<>(ActorsFilmsRecord.class); + + String format = outputParser.getFormat(); + String template = """ + Generate the filmography of 5 movies for Tom Hanks. + {format} + Remove Markdown code blocks from the output. + """; + PromptTemplate promptTemplate = new PromptTemplate(template, Map.of("format", format)); + Prompt prompt = new Prompt(promptTemplate.createMessage()); + + String generationTextFromStream = client.generateStream(prompt) + .collectList() + .block() + .stream() + .map(ChatResponse::getGenerations) + .flatMap(List::stream) + .map(Generation::getContent) + .collect(Collectors.joining()); + + ActorsFilmsRecord actorsFilms = outputParser.parse(generationTextFromStream); + + assertThat(actorsFilms.actor()).isEqualTo("Tom Hanks"); + assertThat(actorsFilms.movies()).hasSize(5); + } + + @SpringBootConfiguration + public static class TestConfiguration { + + @Bean + public OllamaApi ollamaApi() { + return new OllamaApi(baseUrl); + } + + @Bean + public OllamaChatClient ollamaChat(OllamaApi ollamaApi) { + return new OllamaChatClient(ollamaApi).withModel(MODEL) + .withOptions(OllamaApiOptions.Options.builder().withTemperature(0.9f).build()); + } + + } + +} \ No newline at end of file diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingClientIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingClientIT.java new file mode 100644 index 00000000000..095a8f6d433 --- /dev/null +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaEmbeddingClientIT.java @@ -0,0 +1,82 @@ +package org.springframework.ai.ollama; + +import java.io.IOException; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.ai.embedding.EmbeddingResponse; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaApiIT; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@SpringBootTest +@Disabled("For manual smoke testing only.") +@Testcontainers +class OllamaEmbeddingClientIT { + + private static final Log logger = LogFactory.getLog(OllamaApiIT.class); + + @Container + static GenericContainer ollamaContainer = new GenericContainer<>("ollama/ollama:0.1.15").withExposedPorts(11434); + + static String baseUrl; + + @BeforeAll + public static void beforeAll() throws IOException, InterruptedException { + logger.info("Start pulling the 'orca-mini' model (3GB) ... would take several minutes ..."); + ollamaContainer.execInContainer("ollama", "pull", "orca-mini"); + logger.info("orca-mini pulling competed!"); + + baseUrl = "http://" + ollamaContainer.getHost() + ":" + ollamaContainer.getMappedPort(11434); + } + + @Autowired + private OllamaEmbeddingClient embeddingClient; + + @Test + void singleEmbedding() { + assertThat(embeddingClient).isNotNull(); + EmbeddingResponse embeddingResponse = embeddingClient.embedForResponse(List.of("Hello World")); + assertThat(embeddingResponse.getData()).hasSize(1); + assertThat(embeddingResponse.getData().get(0).getEmbedding()).isNotEmpty(); + assertThat(embeddingClient.dimensions()).isEqualTo(3200); + } + + @Test + void batchEmbedding() { + assertThatThrownBy( + () -> embeddingClient.embedForResponse(List.of("Hello World", "World is big and salvation is near"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Ollama Embedding does not support batch embedding!"); + } + + @SpringBootConfiguration + public static class TestConfiguration { + + @Bean + public OllamaApi ollamaApi() { + return new OllamaApi(baseUrl); + } + + @Bean + public OllamaEmbeddingClient ollamaEmbedding(OllamaApi ollamaApi) { + return new OllamaEmbeddingClient(ollamaApi).withModel("orca-mini"); + } + + } + +} \ No newline at end of file diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/OllamaApiIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/OllamaApiIT.java new file mode 100644 index 00000000000..ec60e8a0f82 --- /dev/null +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/OllamaApiIT.java @@ -0,0 +1,146 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.ollama.api; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.core.publisher.Flux; + +import org.springframework.ai.ollama.api.OllamaApi.ChatRequest; +import org.springframework.ai.ollama.api.OllamaApi.ChatResponse; +import org.springframework.ai.ollama.api.OllamaApi.EmbeddingRequest; +import org.springframework.ai.ollama.api.OllamaApi.EmbeddingResponse; +import org.springframework.ai.ollama.api.OllamaApi.GenerateRequest; +import org.springframework.ai.ollama.api.OllamaApi.GenerateResponse; +import org.springframework.ai.ollama.api.OllamaApi.Message; +import org.springframework.ai.ollama.api.OllamaApi.Message.Role; +import org.springframework.ai.ollama.api.OllamaApiOptions.Options; + +import static org.assertj.core.api.Assertions.assertThat;; + +/** + * @author Christian Tzolov + */ +@Disabled("For manual smoke testing only.") +@Testcontainers +public class OllamaApiIT { + + private static final Log logger = LogFactory.getLog(OllamaApiIT.class); + + @Container + static GenericContainer ollamaContainer = new GenericContainer<>("ollama/ollama:0.1.15").withExposedPorts(11434); + + static OllamaApi ollamaApi; + + @BeforeAll + public static void beforeAll() throws IOException, InterruptedException { + logger.info("Start pulling the 'orca-mini' model (3GB) ... would take several minutes ..."); + ollamaContainer.execInContainer("ollama", "pull", "orca-mini"); + logger.info("orca-mini pulling competed!"); + + ollamaApi = new OllamaApi("http://" + ollamaContainer.getHost() + ":" + ollamaContainer.getMappedPort(11434)); + } + + @Test + public void generation() { + + var request = GenerateRequest + .builder("What is the capital of Bulgaria and what is the size? What it the national anthem?") + .withModel("orca-mini") + .withStream(false) + .build(); + + GenerateResponse response = ollamaApi.generate(request); + + System.out.println(response); + + assertThat(response).isNotNull(); + assertThat(response.model()).isEqualTo(response.model()); + assertThat(response.response()).contains("Sofia"); + } + + @Test + public void chat() { + + var request = ChatRequest.builder("orca-mini") + .withStream(false) + .withMessages(List.of(Message.builder(Role.user) + .withContent("What is the capital of Bulgaria and what is the size? " + "What it the national anthem?") + .build())) + .withOptions(Options.builder().withTemperature(0.9f).build()) + .build(); + + ChatResponse response = ollamaApi.chat(request); + + System.out.println(response); + + assertThat(response).isNotNull(); + assertThat(response.model()).isEqualTo(response.model()); + assertThat(response.done()).isTrue(); + assertThat(response.message().role()).isEqualTo(Role.assistant); + assertThat(response.message().content()).contains("Sofia"); + } + + @Test + public void streamingChat() { + + var request = ChatRequest.builder("orca-mini") + .withStream(true) + .withMessages(List.of(Message.builder(Role.user) + .withContent("What is the capital of Bulgaria and what is the size? " + "What it the national anthem?") + .build())) + .withOptions(Options.builder().withTemperature(0.9f).build().toMap()) + .build(); + + Flux response = ollamaApi.streamingChat(request); + + List responses = response.collectList().block(); + System.out.println(responses); + + assertThat(response).isNotNull(); + assertThat(responses.stream() + .filter(r -> r.message() != null) + .map(r -> r.message().content()) + .collect(Collectors.joining("\n"))).contains("Sofia"); + + ChatResponse lastResponse = responses.get(responses.size() - 1); + assertThat(lastResponse.message()).isNull(); + assertThat(lastResponse.done()).isTrue(); + } + + @Test + public void embedText() { + + EmbeddingRequest request = new EmbeddingRequest("orca-mini", "I like to eat apples"); + + EmbeddingResponse response = ollamaApi.embeddings(request); + + assertThat(response).isNotNull(); + assertThat(response.embedding()).hasSize(3200); + } + +} \ No newline at end of file diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/client/OllamaClientTests.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/client/OllamaClientTests.java deleted file mode 100644 index 839c33cc83c..00000000000 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/client/OllamaClientTests.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.springframework.ai.ollama.client; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.ai.chat.ChatResponse; -import org.springframework.ai.prompt.Prompt; -import org.springframework.util.CollectionUtils; - -import java.util.function.Consumer; - -public class OllamaClientTests { - - @Test - @Disabled("For manual smoke testing only.") - public void smokeTest() { - OllamaClient ollama2 = getOllamaClient(); - - Prompt prompt = new Prompt("Hello"); - ChatResponse chatResponse = ollama2.generate(prompt); - Assertions.assertNotNull(chatResponse); - Assertions.assertFalse(CollectionUtils.isEmpty(chatResponse.getGenerations())); - Assertions.assertNotNull(chatResponse.getGeneration()); - Assertions.assertNotNull(chatResponse.getGeneration().getContent()); - } - - private static OllamaClient getOllamaClient() { - Consumer ollamaGenerateResultConsumer = it -> { - if (it.getDone()) { - System.out.println(); - System.out.printf("Total duration: %dms%n", it.getTotalDuration() / 1000 / 1000); - System.out.printf("Prompt tokens: %d%n", it.getPromptEvalCount()); - System.out.printf("Completion tokens: %d%n", it.getEvalCount()); - } - else { - System.out.print(it.getResponse()); - } - }; - - return new OllamaClient("http://127.0.0.1:11434", "llama2", ollamaGenerateResultConsumer); - } - -} diff --git a/models/spring-ai-ollama/src/test/resources/doc/Ollama Chat API.jpg b/models/spring-ai-ollama/src/test/resources/doc/Ollama Chat API.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b4fcdeecf875cfd7878fd6345d4701ab5a14e360 GIT binary patch literal 290171 zcmeFZ2UJsCwR?o^_ucc)jO;zL_g;I>J=a`o&9-weaPS>) zMpsiu6TrX#05H%$fP*oH0Ub3p+dC#knmYO#f1PLs(BbfP0Kmf&;bWq8`=Yr8>>|_m zzgqk{chBDU{;&N%0s4K{`+waX0O%F}C)fPX4l_GA`r6YkSfYQ0eCWjK%yQ6i4(Gpc zkzcsoU%1jQJOFVYLBHnCFWkq}M2(I+&~XvxKXAK0aQpi{zpj5tzedT!-R~EzU+|0L z6ONt`FnxcF{^bSu0!#o}fZM;GpZ=Q;UReOZjWqy(@zvkQ>{0-LiZB4++|b|0gx&!F zr=J4=V|IVLfyF1RFcs8Fo5;=GRRaezjyge2m`k3=1<0 z{pf!X4n6`{j~x|d9%p0_032dvU}R-Ds0Uo2i<^<*FZj3TWje-u^zaeJL&txeN1OrB zDbpE0%EHRReDu&Eb^ya6#=}RBGO-?GW4|QHd|u#|aUuujxf^ECdx+AqUM@i?SvgaP zx1ax$I2^var|+!%Z4;k>_=MN*^Q7&ZoPD3>mP`oAfWnfp)WG$Zwd|jLQa68|{rSt% zm7E4)4Tm4gbgF#xk->0;&egxMMBg3#MV09o12g@!DJ$R*10%!XLnn_j9%DFkgn{`t zQ>;ghvR#tAWz59R$t3_bz2_YlU((HSR!YXl_sM%)kL;%(g3_SdCXn8xWxJMAzkgNFm7?clXZ*<=<-`)`UsjyE_aPh3Z%d0j9vM7IR zWG!AE^W$=nmnK+@P1awFH|i}KL-c8H7^T==JRHGrXx^E7TkxHH+I@ptsG25(A1|c& zwf|bGN|c6=+~+C7ngQB7<{3`@+Q`pMWP(--d99^a&2Jnq#?OlGC>sl$^(YHq7WWO5 zO1T?Xin}pkItj7vO>(-nKeq)Cy7?b^=F^jl+5@wE1AUM?r~iRsQwV!lY_U(Qbn*OS z%g2upy-g4!PE*Sj{l;cWuj3#Xq52;q^dI8t|A>n@`C~J#=lddAedJ);^xIIO!l zVODOWTd>^?=fn`jVoc2%qtg83+vLyr@XFKRw zm&0o{Z0c>07+j{FKzI7xdY2r6V=DN~pz9?snM5ugPKb=V5s;`UAOJ9Wz>oM6r7ur) z96JEGw7JH$R72BzS(`_>g)$W4nO2nh{k+bL}Y8>o#6UjDv|f~<8wR0Wl3#4 zmU9k}LDobbVNJ|LB6lQFK)%&}32*?==Bsfz(Mj|7#ykk$QhTRB2!&xn?4;7p5g>IB zuTC#`aKuY=OU~jnG5ur#X)JG_)0@X9p3(}or{C`kzT4F42$5nTX3uB5Saf>!Ll}@B zUKVgU#M6R*6z^OwqMr=PCWy}aH1F?WR4(0S@c+-Z{C}s^hp^sUl;hns$1#|Og}p1z ziM^gJ;_I`iLvRb#Xl29Jegdb$P<>Eb;9KM+o0$NfWHF!eikpb1OJ$@Eq+N>_N7s-x zXUhS=H*9uQVt6+@0b7-AZ2Yji{X2_m=7!;ej5f4`z9-fBO92VOa}r14?eRGPq>JCy zuG+zBhU5qkzg@razBp7zg*bK6dSk1jWhsBmsab8>@?MX)d22z6PovBi@oE$8Z~mrt zEZ}fK-{68NN#i?*v`Us+8p2hjowNF@CR#_olcl&Di-&dIObA=wpyA-uDD7Fi1apa_ zOhG|R2GZIKGu((qb+OmfYsyi#uG*+YPMRaZBDiY!ykkKeXM6a##%1Y|$f1HkR!*bW z3{|{}-mW<#`e0JilP;gUD$9EgYwK-cg4s#wF*c?FiVw2_fmvBTHPF@weLvd`*Sf)~ zeT`eRdozpeJGX2zMoIfxc=ole8555zH5i6*bNzAQ99{{Qh_B%#b=&E$% zG2ry7v%>-4lZ)~^*Tf~Nl9?d}#8hLq`&{|mKlYyzo@{Adn$RnnC@!p1Cu}5bKQ-*J zP63Bh7&QjI^r9ugr#l2AhT5H;Vsh|z%c!{e{-Om~&DLBdP5uIk?EvuM=E=}!f=%c= zM`h49MGPk)dagB3zSCAf;M!aW`>{%eweH#EQBH~74$8k%zMndeLJ$>m&O7Bo6jaN6uJTPv+XGqfaVdq zQe{`$8gM%9ogpX1rL!^5z685|)$H_i34~tTp>|)Ppj`<2fe4Ih<*ZZAI4l|t71vbu zeOeWVsnBgyKC7KP5+whocKr1L;FhdjLzO`39fz}lNqu*$X6*`dQ)=SX1X&k+f}%(o zyB9Bf1u#9kSeQY%N3gn@$OebW=OH0->b~aawEST;-k{01RzdRkt(b(hlP}u#UoYDF zq8~9gZIJ+FAuFBNl-~|3HR)_WtF>roDot~KGpl+B^J3vO1YI9@^@XBz8V&1whuLVK06c%G`^Al=RBoYp+aC6~j#u?GzL2UuF;7SP(x zTMIok;0}cIjSBcFMt{E}{Udw5Arww^z191z9laTH0`Axy-KeMtRF%RdjG4H1&qyfP zdoSh4SR%i&sw^!R1z+i4sp;2_G1zs9sEK;a*PUzySstzrPxd~N^8K8Xg;zFi5Iq(i z&o$&a=?nXyxkg#EBLoWr*H8s{yvxJ$_`Xo$^I4FiiNM+7cx4$*BFDLIZfMx9?*P(K8-O^9k z)D90=)nS~xn7;*Qy9c~vSX_U{9m6KiiFLMLhXg#sDa74kBag<05EU2QvAOL+bb8O6ce$k?<9_;>ke%yF+;!&T{!K? zT?_8Jvw0!SR^85xeoTgw{w*4|I)P8>8fV85QpMj_l~j8GUwbcBp;ZVokJepO*nDmE z|5*G#Uj2dPYq7OV(%PU}EFWjT+~Gpg-5$ZI*1@|X?mV`B_MdM#=D1bPpTDl-qckpD zZjOEBr-J@r(kwVy-vf)&ZSOABVR0V}*P`!0&xc70@NpA8ovW=%Sv@*-KG4iLmk^?8UoRsQ11jcyeIL|TNX z;G%+SLX*X11%ZCcX~XbxB(yX)EU=raeu5HBE=_h6O4wbS^(=4-lz(gK$H+*m4WIW& zNWt`%baC(TN>yxn6BH8b!emV~45oWLv`XQ$G<#y=UHj~;W)ZT1_tnV2E&ZJ)xD&a@>yQi{4hasb7WsSydVOdIsJ9fFUWF@ z$&%(Doe>lO%Pko~VP&qD`ZsWRYxWanNRX|G7%xT2P?0q;wI2_tQV65?6BY1Fu7(Lc zP1=+#AdWj(MMo*^6Jy-@J-0fBPu&5q2Vqg~ZLPyx_tb$^h3@YQku5aA8n(J`Q6_g7 zP(($F%}1%Au*kMPoG0ob6&h`@LNW-( zjm)}HNw3PYGKx~2T26G!%W2`M5G@e67-1dzGfDqV@>zv1VJ?32Hw&TV4YA)YLv%=d zGw2)q#4aP2jlsB9OjUv-_0g~|`msxAO@Mw`fUakvc`b`)rgDu55a%j_wmeC^s^kt! ze~SY?*p`*Az2;!uEqZd8NGeWbUv&C(T~{Q4!UFj1SEUZZ(`c0I(ree)ic{p48(E9N2LL z`x|*%nnWJ}r1I?*LNcbJCcb=#-rGs^56Dd#M3>tJWWzJdA$hQbr}cwBJ(OF#XTD9? z+xnIDnSiWNL;Fwwx1+h zZ@sSE)S7&S-j`a*u0>#-hZO{4+^Q}%DZ`**W(qm1BDWKxPEqJZn1XjV+44^g9RL!S zW>Mt}qx|Uf{tZ1|IgGFMcPkM>LIy}M^7ggk&=&!DBNCIz( zGx;Xy&ictkMjJTxq$CV~*tYOFpBCmfm4OeJTb#@JzH{U)X?( zaU@sMu#tC$VC6z({r&`2OCEdMBR_?ga!hTYe$pO^odgdz^FB9NM4v$%t3urAZGaM2 z`=c)j!%n3RNiY_C?R!pK4;d`=z(Hefusu)|y7b;;&6n`x-NQY-qBrUrCyv)@W#>57 z?RTrMLYC?lR<12r6BFX7@K8>@aDbAm=;c!GlHuhxanY+D{b=(7)J5m74JY(9B~dg% zSmfqu1L)q6*E)Scj@!;m{CE5n(^kD|<)!$%2eUuCWa4Yi^{t?bnnRh;r28Rxvs!*p z=O#n=)csDzs6*^YF@3Ysdyh=)&X;mfSZr z=YvamiXNs~3su^9fld{m()ZGeO+cvKv!DW`8yLmir@kP+#M0nMD|f2_>7Cts{GGJg zT+4IyJ0>r&g{JHr1l~Rl^W+c82~;esfax2Fz0W+-jB(I*&B7MA_kpA&zLq44ASVNh z?X(*O&{+Zm$eE`54EwJbjDk{k)hVDCx|r+wwPV}u(MJ(79R-OH2Xuup`js-xHYJu;3~HP0o>mjE9=%eH!lqI z8naIHw`E&Gm$h(X++)(87$9`ihF2%<61%}6zAq^52h7|-Lqe z?-ZvXNO1WfLSB+xvN=1xyag?Cp>9!ow)X(w>Qxys-lpcaU4FtdrZ)S0%e1;SRW8i_ z?E8J$-u9@%#9-u-O${75$Wgy#7k{4rL^qLcF5(w_+_9!q4I{S9_49f8DTy2_wO8$a zTaiU>aRC|{h7B6ak3+M+LW-uF*r3WGJ@V9)kRbHRh=Tb{5$N=`0`Vbho6(&`(ZqA> z@qFx*hnxtUbs9-!!30REehenaw>d1BsFFq zLlyY3&fRu|&rRxOH`4dK^SeaeAq)SxRZ~=zoxwUKvN}EExB$)m$k4oZEyYbDAh3c2 zwE_yE(dh>O4Y3}1tBqn}5ybZML#t`!)(wKy^tCy36&iH_04VZZ=#z7mEwER3J$&1m zi?_1D=CzxuTJOrW-E?75Lcq#O@sI@c5qJIppn)c_XIh6l-wXhWYAY73aih@ZYTqiV z3zlEeK|CG7N5&OWn6xLnRE6JLc9ieEZCP(yxI2BUmO#C}GyQ&3UG7&tm!7ZV@vcIT zf@qhe=BXef1NXANKn-_O>*1L|h?!_=T|;nY#cpJMym&%7{1kR{0zQG<#*50{;E83XJgna*R6S|t!tgh&}SoQ}7@qvCxPlqjM zDFJ3wZCCa@^?p*)~@2X@NcIO3o z>x1rGOw4HdR|O<1)M;Bboloo(WZ%fJ-iW*TG50C}uq7YblRi)LGx~Jn0HBb+4g80I z1piED+X3L&ouGb+X0_d^KY!jl<$DM5OdkXzgEH?dS%TJ?2MVDO6TDL_VmMVE>?#;w z3w|?Ux_mXN+RBA})4M+{vT4c@YVvtM-sYe^_F6}kXA;I zTKQ$HITw?y;N9v|Dz$@1%^@-4sGSNX+ltj%D~Iqn>pB9y0L zJFaIWW?=NWSbg`(BwfCY;yXp_&31jer&b2yE~7tm=}uGou~F}>`gU2Q>&~N&T5ed= z?zf>f`BHFMZF=`IQ0=2wY|?vJ^rjitql?E+*?gPuXv*rh>g=xDn?AQ{IJ$s-?{xsc zio^v4#g$JcTS)7b(>2_w(Ij)bwSb-@n0pM;Z@xAcTNKD&lY093Tk@Z7_xo9#;5`m1MN>Af~$MLo)^=MCapV;4M5#;4D8 z;d^tUH%T{TZ=;h^iK#G!p$F)z({@c_CM6eI&Y^Jl4x3yJ!(0tX{ut`T4=#1AC`}S;5N9*Fu>9C3{Nsk$Vz12&>(yF| zx9bBd3fsqq>UL!bC8j?4JET*#8?T$j|A!uHIyF08R8Ef*Qn!>K*)T;r&Nc$dF>h~|HdgEdnZuTJ%2p|)XSMY zW*s$NZ+WHQ=ExtwO;P~F20zlZKU>Fg!$v;3$E`8L{&j!kpf%sATL$Wl4Mu{OHMG%z zGU{$Nv6>~V6arBboi~FfszV>mfDS`Xo$)&=A4ojsA`IW`ZZFOc*q~PY0Mz?#M_s)V z_v#BzPP~?&d1Kz(q)om0GHN$Imc@McycX+_ha=kF_Ami-7+2ClRJk$b9s|#hGmgr9 z&Iqa0{a$RiDta7Gk+QO*Jm^AykI9i%m3kLZ0d#b>qva)g;H*`qnvk@BuVjZ!7uz}z2+Z2}$hi9x{^$szhpOJZ zN?WNWJy>fEWNMDY>Anoic2HkYt}Zh2ZuUL$g7(a~;a20R_n(ftlMTF5LK80&Q)v4e zS8V{YO@tp03#yl1JX0xhOoGW2XHVJmIr#PFcFFRxc!fug zNJ4#Dmgrlo9Wak(@HGqef`Vv6!-evDuwr=2*=~PF$o4~EZs5Z}5o;dv+G)k!{hQp* zdU|?lMtppnGNwzn`y9O0>+R3=EvT!{sVgP#K59s`Krb&Ob!j2+}$diJ9Pi+OP9zBMi^ zGvN^6zLkb6{=%#IaOeE9WZg1Z%bYl41g5GdWhVZ1j4gMLmmP3(C)mL!q?#<->c=Hg z+#zjQUtvk=Xb-V=z`9uj@ko1!aY1BXKVBiBKKSOzmhU!uvRa>=(nf$+5JlmGmk-HP z3Wng3u0x|A2jWy26cg(RqIVE~8VYVKc*(S(7W3giqX#$Ag>M9Q!Kcl*LRIs$x^9LZ#@Tf5t$$Uk*_}bT}smz zD5;QIQsof`>&tbj3NZ8d+JC>>3zL9aJrCjNE+&33ZA5Km)J2|%1Q0@6)7A_sB7yU2 zS4^KSA|VYzkAxNE@5N!(ySW!XqTNt2eC?{%9;Gx;)Av^cOAJhI!bgV$i@C$x`aCqt z$fW*ZmzqP{ut0qN({h#Q*@-T%BIkg^*rK-ArGp_y`vLMU6=~g#Q&!4gJ@?q=)C6`tFV@BDI7_kav{a`Ls7q{nDzH@A+4cS9iiWH1HSZf(->?Y3^grq zR0HQg8sagdCkpWb_~l;7BKT_eI`GPj9W$Z&{&w%0FikgD#_2pjZ}(y^*vwlo?==ar z+{LoOZR0XwCttKwF|RQP_O0{T>?#>{Ue~5)D8om117~I07Q@r_;hx`_x?b=#&E`6+ zu8RhnG!{%LzbK)eJx&kpq9Y>v(eKWGp?Hx(QeL=VYxA+KyD?LZ#nGR` zQ@H3$u?R$CMKUfp^(^JOo$0OVr1Y|Q0ymOVmw^&^^SnX@rsuAMnRHNv55$v zM`gk$RY2pd+YxI8&uNXAJKCuJh_|JEdHb~0x<~`IYFL3pf9fz_e|l-Rm1|B8Dv}bf zK^GN0sU1~da^Xy6?hk482SN2qdW~2Uu#JV`_I#O}JJvVF;?7#!f^XU(d~3b0J%tnO z(u)n!NvJ*YnW+LKoQm1M$;j;|ajdx4`gV)V{&YM3##&F_$Ob`nmhCDhHZUkgT}!yK z;KBXftoi4TN$#x;5*pqm&`;jE0g;!()q?^y003#uc~miSVP6?T$$y8=6@Xu&hflj~R{DphVJhV@se*nb#rW z2rb4f<)q(QVO~z;u%Buck``}z005b(mOFj(NOc&BOdRgx1B-Cyvc9>C}jlu9(P%&V3+8I|DZx#it~;SV;S@DfeY#kwPA*WWfGP&8fB zqLWn_1eIO>Y|1^8)bz(rM}M7Z!))VC9JaCaJ_|6Ep7#+6%# z^E#7H3edAF4nEVmItaf?{v7VL zG49K^zy6V*=TPh12c>DgP7ymDpyWLEa{m?JLToU*th(pEIH`(%Mvu2{Xr=nmV8Xy$ z8rZX{N6lJC8j6TNZysx3$71zj>#M{Dz{<~DW~$973)bbk${EAVTP`|M-Ra1$NKZ?z zQ!Kfp6Jh&}o(0r2T-nLnOi6=?a+`un#K9sN{3=9D=MpM61=k=7E$Ik?7`M=}G7?SU zqHhZ#B8lkD$EvfDdtXEJa{FpUaIPM`vM^qcIQy~{&~SEA=A*P_!>t5NeMIi`xM=KK zQC-R5q$9ap+j>(Ep**u@fpV*5>kd9ZvEsN|#yqbjdkuP|y3Rq}4F}W_O4Txui3yJN zA$0oCiXc>oE%)QlE2#mOKIG;%tT7rp*`cB29t+nI)ZkamS;t}Owt&P;O8Nx0 z#(^P*Yv+$pjMuuv--}RiBB95eydhG+`?;43AbK@-cW?pP90?sODf}mNIwb zLcRG!$vdqcVevX;pS~wQ;r(Egfv0zE3{6gQo!7_p@?@HTDqiVd=C)< z-yFi;Id-f+W}+C|Cb+X+xEaPAKlNw*-OX#C{&Xw{e*T%MJz@yjA=orlgfsK@4cf+& z2_dAJ??(G8=MT9v`84&{F4pQE0Ggj4`hJG#!hV^x#zvw<(_P^e!1!o?bV2P(?&bpE zT(H3|n}7r-(Ty0o_d|tw;-Voh>-Ic?O#2+n{!#8GfFY97t!kt4Zm$YDMZ8^kR+T6` z-_*xn0pBHSLjfn#Xs&@hl66EbRb;by;kZQU>^@I$rw=o4o5#~pCu$!Hz~sVO*iN(agdqxNw+Q<@kN?d zF1om~buvay^}+1b?$(mt`g9~Rf<7|**3dLGy4pn%c_ORC3SSJUa6Exr4=l_epA2#w zj_aeLkwRKtq*g3sbY$ev=NThkJ&QG;2Cbw?E*S5Hw)@CZlWhgAE^8T2gJA(M9)^VH z!+dLs7Hq5&IWnnx%}N3{hLWvaYE5-^g~3Db!?>t|8GCi--$g`3;;uBm2;T}W9hZfV zytqgJ4^xwd0!R>2pYnMQR!Ppzptm*J^zsmfXS~|8kWzKOQsJIqP*2{t*1gnYV`!9{ zrC8);C7)s`ISk6dbZ&+9{l#TQ)b+W2ypuwl9?y7At+it+ve@A5>yE)!KZPSHJm>4G z2>bw#7rvN&ul&)iifI_Gne+eR8Ku>bt3kWl0R`8!syId6NfIj(PsFZnJ__AL3S3mV zvFb5I{*tHV@GjS4QC2f|yQjY*Kp`u=2&&n)j2T0eWIeRWxOqZRob1bDa`i)oP0xLglwKt z#*CTz2xM*DVcg?6^kFHn=~U)2W9(ORA2;lgXLs!EG@x#&hEWRBS)oZezQl}}c?goz zrn77i7O__P5ukXi*myJd$4}k!K&PSNySeBWGX<__lcEx?`t-xRD_8a*aA6_?@DER{ z-PI<~UZLR$3@>;JmRtJG#MuOEYR!Qjml<$bjKU+i=XTN^qB;54t?MMTS2ZAzL4SMh z>1(ZY3kYq^>qTJTdOvv0w&>LCNMzTM@|N$C!9hAg!vxh4SJ{B;GwyV!VHl2Otxv=! z2R%=Q%6U2#xK|^mHUiIn+LRT4byUkc`C|spmkWuOzQd>d9#;25ZQqqC9B&qgk+Gkh zy9^ZudbLL%7xo+mzW&(#ZC(Xu?)IZ$RkqiX6Y}|Ki5JUU?iPB6T3Gse5EfQEn{hA7g;bks#&TJ-IN&TkFexu& zki~k!SI~{Jo`3Vi9-zcZ;J)vJv2y(+bLlJN9OuSeQ|I!B&9K6$o*~(AL>#r$9s;5G zPkBMjkN6#ZxsidX+r4}D0MIkPW4@>i4c+|s=>U*RUjJ}n>S$D70KezUr&_&klQN~C z81sPz*LE#M&m3srReufJ3vCszy13`Ks~kNv%4^e?ASSwWPjR+1I}TkiRZNVEdVDsB z@QEIQmA1L;VHP-76h%(`xO4Kh{4hv3Fncz=0@)_Y!yOb~Ias6CU^U^alI0}8_V~qTG=~4Crz|A4mg4f)oxdXL1mIR)&x7?qWEaL;T^USDXwjS|< z1GV#}j8w-1fNnrBfuwqPe0MH$1|zWzt_kTxZ3^>Gn*!h=RRr-Y5`qKoGp7lUNj*!? z_M%wj%(99`<)uE-ho8UgF8A-j1^`!S`8*5XW**P@5jPzm1ErqWB&aInS0SWWKH??MZiWxKHt>Znv-+la&p%~&%jNQ=WkNWH> z`9jHmo9f3;d#TF#{Lm5ESVG18?Rw=k#OCVMH6E>z;kEa67q*GPf%jPye(S}5navTM z@#$w6wA`Xe zhswUeMcM6C?(M7AM-0UE4P(q5;0sgAG3sUnPCCe`wR+02@}706V8vV>7sPisw`>c= zD6U~!_-f?Pr8$>qmc3X(V$Xw?_IHJqnlH7sp8lhjr58j@{v*3`%fY}0VeiB@IeqH@2p zrj9CWF`Ka5+W%MsfWN`zYZPVGK@Az^#g8G1Ot;qN#_E0YV_m+_^4C>Pc<$St_rDQD zb9dQ~H`0oqF1_X#-z#6LIafeb43UYb%4#wqu0~~8K$@!rvSIJe#L~lon5tq^g#!R4 ziOZzB2ZX;-gTtojD7Ezu4W6sJ-I#CXQse29y&Z>zy1Fa?82_={a%_C#`J+pqQtPbt z)h44oh0^i{9ZkGSYB!iF%?~70C$u;D38s>JY;a1 z_F$$w*TpQ###y-LEIyww8tD{;pz9~eZc!3R67FsBD2J{xk)j(!eO*AtiAi%WM0u^vMzkj z5tIMLUFS!Kff1Mw(rUU4is*F7rpPV5oitl}z(U6V=#Sx)WH|sFukc{(bq~x4E8}nl z-wWgICwQJI)^1YK@~?#ozS-ifi6=mAN*?|P|3qhpV&xEI6dECJTb9Z57$+pPIht6-^Y`w@4w`^KKb5XtY2IKHy6y#ogIIX>kGFF z%vUOM0W-l!la<& zEKzukLPbZnR(FluL`;A(1)i==q5?=C0Y`-c)b}22KU=5Trp_M!Zd)r|DKTbgb|bOf zkI`s#xYzOs$z%UHW_4_oNvHcOxc&fe$YN-9aJfcdD2+<=jEcIQ{x|KLG7^N`dF{si z8LNG{OLFs`03s?!K0Ljo-JQGxg78UCSf{qW(5zue9?@Zq-aIz{geuV~6ZFFJ0!u-; zY1!yi;CyaILihEq=0V_vsR#E7?bbsDHHOv|^Ye4UA5Q;_^DQS27D4=jutKl#WzsDM z;KSI#W!)xGnh>0IXEliFK4!6#vy_RZevZ>p#5Xmp%*DS;%F{k z97&Dc)rB-um7U3>+A6Q4yXKQ0?OD22dOxy$ZEYdu#cf}aehtm6e%M5gVI8pjrMi)y zp4L0Q*7nb{h^JfimpfTNd7SRi4&@M8cx&RQpF^qKgE412V2RD7hN*_#!uR8sEMjc2 z>z4jnw$6q5c*-cPwc`XGi4)>Q#2-lZe(rIMepAGFcuvnmo= zeA6dU`Dqs_Zf>Ho&1GkD^W7%QN|5H1u6|TimY1zXhVq}?`s~ka*D<4~dkXDkY2j}b zjn)oz%|iA`voEq{m03CV`1S4=Bxdj$`f~YeH_Z7^Yuj*H?`3}*Fh}(RZr_lra?P-~ z-|rz`qF{C9r$iQg!k0#r_A7t8uweB53C+fdpmdhd+AwKoFe|wqgK;UK$@mV_I9`!V z`Wk1PpE?PSC&^vubW5!<)X*?BrRU>C%4-8em#l~naVJmKO0!n#P6kmyty|b)2nCw$ zqzs-5P8tew*-3(in! z`V3e6p=19KI((=9^hi4l4_B&=iE36pdEW^VHc}SG-Ezm~hd}fCKs-8vtmnRII|Xf% zo5~v#AKOnOe(GVCiUfr_hIOZgN>fGL-X*F$>%Okp>>RtL)5b&I!-eD&XztB7KEGS7 zb{BNxl%Jlk`gE=ar#sJOjgz_p*^ZGAPPst{Cl{&%q9Ijk7L-=4<4XGM*H|+1Gg>hK z0qK9pogf;lz3og8(h7R1Rk1q>h%OV3+`IRq2Ulb*+iV{d^?f455r;dR5g(A{9&2{3 zl`Ig-97Qr!*MO)GBucByhH?->a6u69^%f*93lzCB=t1Fajvm6sLz|}*cc;+62Z(RkRE}BOE^pUzvCQx+MDDIh0S`bLPaMVE~1ELHOSzf2xG~fE~S`x>$rkxd3qVp zsERz1S9S@RXC-HsnB*oV8d&x1o_4WZ;7nQ%q|~!AwVopQ0{h56s%r6vXdzH1wDd3m2o^Q@H@DHA|d{t)k z<>ez;3e(UxbKwlL;u%(t&|!&m%g}UDaq3Bjmk_%$#ii-mjt6OYz@?c<99?M|7@KEd z!yq`&Md3`v4UnsFa&0Vc$Oi!8q{c4O)=CwuNLDo0F@90!vN%1MqYEn#GRWlUCcxGe zDOv(qd)a$D90@OLr{BWJkI*FX%az?QpVsp1BC~D0nTb_KpSligJ!=&Vyh1NWw5bBF z6idH7YQU}{*hnv|13f)q&)qNDCp+YXxTAJw0G@P3*xr2W%?2Jd5D`rerKMe>Cud_$ zROZ&hh4SbxDjA!U6n78JDofh!6wEmWUj0$Flvq!hH5OSFl#TTp-X}Y!CaUhP$S}^0 z(QRuiF}CoADs2=Z6;!4d4?6%X{Iqh=MH~R|TK%u^CNj2u+@6u~M23;?V+z5&yzM_( zLbBN_hOWI%J}*#dRt`g1a9{(o1)rs}LX$l*rrh1=e+I;`1%ZI?^mJHSC|-J+A*Ux6 zYn|E%l7j*_<5)TM8OZ7S1^wdoZFpdSyhSjf4J0Km>wDF*46$JA_W>un&j_!?l)?SA z-aYgb&p9h>?c+ujfc*#q{>Ynr>MRK4?~)$qGYxZ4U#g&h?SX&H6pzh*I#<2rcKxaR z<7t}@Dt~7F=kb){HJM;hTG-y$aixAb@L8#gMeF@zoyD+Inwrqqbnm!z=c z9&{IJ6*0?+Er7~%|El*wQ~Sc(?E4ixCGVDxn>}FTW-;KEktq?jzZ4nKD7OSEc+7tj z0FdO5?T|5$9*Y*w&(GH`kdiAE$R3o{@Gzq#8Y^iho=j&SQJ4LmtK417>37;D<%Oey z-b>ui;4*Q8+S=2a;9mK@*umwxjDQmK%OD$i5NdZLq+A2g0tW9Sq!!Pvr#b{`+(%8J z8ZhxcZjvPq08dDs#ctr{!PE_j9R!dm2=g-5b#eI!W<5UOdv;icID*}FVK7`Pk3}uU z?3S@xO?z?`qPh$xm%`V=r}nnGREo!kdKO>7sC6YqW^G+Zi+tKf4NY%`PZw>lD>aflV$78LV3R?Um9UzGHrt-yK%j&%@zS=5lt)1-C4fo{EwbqJl3XKJTZ$xzX77FU`NtICM1yW-$ zy_jHSQIlgsm=-Z=Q1BIk!ch8S4*fs#j46ZP=Eenwf_87g_i}n`nGs#GJr{Vrt54rq zsC_-^B3vAzA)IBGnXLnyjQeYSm&f!?4u>Qc7aa2Y#mK+lUlRD21pe1ZfZ;rx%ocb# zi(~OoHvCBWs2LI}MPc6#98~FJrR~@BVvTudiB$r$(iu=q+gZghr+@(ArHQ8*sh4+j zafDH10Yku(n>&jNzSLXsp`OoHPwjNR-MQnCIs9%9z_rA2y7p(jO5b_m^%>Qhi`BDT z_@g>|#M56HLK*(m=>I>0@c!Moj|09T#)qB>?Nb0pc8@U9yR+$ccQTAV?2Uz=NZ3LA zdyilE-Q!Fl(}v0gQbyFT0NamuROpHk^jk6bHqvjbziUygxcP5t@UPqdFA`2H9}PFd z*I*(ReX@OF(S}@}k&!2~10OUV-C+^Ws|~tjut;PrQ2f-_YRnxTX$xB;&9d?`8#2`3XQjUpzi4`A-Bd}V@zS#_ z@A>j&3rkCz1T?`D6i?`M6Y^Oja2j`odhTi0sl(T>cEh(mU^3)w~_P)(@fVlM1A*(yyfe*J@olDom1 zLq^vy)Vc_oL2P6!inF(m^~>nM{PbJOHq+lcoE1Br$)ht#3aMD;YbjZlToWMv&Hl~5 zAOC5?lb_?RO2p#weL;e($`zFysL|i-U-+8`^A9S)9>U3x_0jr(D^2xHeNnT2OOEkx z9$3yYbs=+B=4yvGWBw(=fSLaL}8 zWn9?Cn0$(8auGxZADd)?z<`8Ef-*VFU`&%_xkI5Zuh(I)&8~ihHq)Dx%WzQjyc9X#^J{b)xox|^5+}oto})M zu8orq%JdzYY1XG<@z;u*uNjP?E8rfn$({(MRWLI?Fj9P+|Bd*&)C~0frDzvPKRrQH zCfHQb0xe@!gtX}T%<_00S<9u<;pz(>M~-mrkoF8YO~wc#KW-_8k(O>gR!d#+ob65F z|3W=rZ0+v)(1jhk%*W>IZ`Oe0S%Uksi8{;ix?Zt}n;!lG^=REa83}NFWwS2t&Z821 zgzD-A@BB9vxF27}2HX0H4l!6c5@c6rfN~sTjdzZLNMv}>dEhs#zp(oM zY-40`!SbT<*Q&}!I!2st!9$>xNiE>hqCt?~-~0_O?Vj9V4?L32t}>zK92EhpYwpo=`L*Zo!&h79<#?iM zVA~rHTap=BqSS|#hU=|iq94Cl)M7Hr|I4o{0Zg3m5#-1sVK<$jmNH{%+r3p9DfUJG z&emEu<_x2AVi1tmvsI3BJQ{Aj`}0B6GuUh+e4RL?GC+Zc!Vz1}t1P_F6aVGy`mb8y z7x@|!w@UkEj}AsYF$ROb(yYI6tp#%_|HJG*nFtyLv9X7u*^($)*cOAr6gDWGuZ zKfwTB5`6#ROITb!qY&9MhJE~B!&=|hZ%?%x+O6a+d$csSkdCSk zSXdi$fBsKs+JDU|2l>{o4KKYtJ7sJKEI0j9VDtLr4EQq(=dasGKWSzvbkB^NyhLhD zeRnz~$#+_L+!w>YPCHjK*(yGD(LXd<8$Oenj@xGmeY*0uCS`>^4ZQRH@VQH|WIv3} zW@9_#0d6hTot@o=$IG~$7z9mG|39KW0nyIBL=5}M=6j2|^n>Oxb)B_GCU-bK1RD3Q z#PKc$Ywn!IaRvD_^()?SnjT+851aXxvJ({>XP-R_aIVYDa^C5>X;FoelAEb3&C>if z^fOB#Z8>i!V!8$YkumUt7yc<8%q=yTT~?&Mqvq0B;kp~~u+Dd%2fp)_o*dZ}{1eUt z$KW~a&_y=x)dQlM&zkwS3mqs;-nxaW@*eijq6)-W`rTIaDU zcESvj`P+GtL>OV!8KRE)X1S^2A;u!?n4FJeZ`tF||ve zOHbOT^anPAEuN6ivd2M240hB?NLY$3rutsVfF@5vepf@}P!paTD`!_NQF?0SzQQe| z#q+!_|LT5qZ#7z=DT|Gb9cEF8F_f6zw+RjFDAfoOVzT5$YD>pXF?^&dp9(;)wMqEvy-CsV=Rp z3P|1e0#0Fl7%jboLne9-otwI4K&&E$1$HWN^_Fk8ghmimNbRJ@W~Z!r?PbPe7GMgxMY3G4(y?LmEGDD3Y z?2fdPE^h-Yb1tw0X?4&zTtFAb?N|Te`zk<^Dali6HbmyW)u*h&;ltFtHhPo0ezQ;- z<6u8EhJ$M+bH$F+rFFKpu5lH|@$eA|vE8C81iv%$sn~9s$fO+V8wuga(_WngLb76WV_#d$S~*P*1Cv zS=UXh89mfkv&N#!XImDwbF)oS$%cEneAvKnDU*e|10Mf3fxdd-E}My~cz~hBMYIED zw0GaA%vnbv;qtU+-()4D;IGF;9{`J~HrS7Yu08J0^wCma6FrHniOOhgs*s0xk&L-* z&H?_8^ItASl>x)+hDMvz%X}Rx7fe;xWSkhk#R+3oU|F|O2?5>+6Rg+K^J?<0w_|{h zBU-0qv9J%D8C0HLi!*(LOXyL6`I8ibnYQl6hu=n)k-ai#D}e{R*At4(@()!iuS&``jL z^{SKJUX>z!yC*hI&=jmh=UTXwrn?;3tOwVsUa4tnD!j;Enj5WR=r77>$}a!70ceuw zJw*F&7id}bD!hC2ts#H87Zs-7MGX zVp#2LO~i$>?C{v#G$`6I&wMeZchO&PQTL+6@1o|0>!FOzWC(!}$h#sMBQolkUr|?m z!TBNR2wXcdnHc)4CCQ8UTVWk5Lj-ttM@ekN5Nae|o=TXp5@OZf!I-Y>+t;FVPRwf? zCaucHh*lr4)Qt?<^TMLWlDxa%A$;obEr0eP&)oQF7aY0OIcd2OQRafWU&48zv zA-;X%WUOfuZhH0*;7Q^KjkSrPL(D~oXpGPj_Hr65tm^yyP6g}I%G?4p%3)<81-@oI5H`T8idZ&WU#&?gDPv>moyB4 z{S;o%-sr>3-T_LY(otyC7gZnYzOtVb=NGRoyvSJ;1Khpf42?{$T9&l)RJ4%a2y~qd zlotNXaz$-~btPIOf}rI#I%Ph552SIQmUow|q3*$CItDF!Mh$p0)mO18NnP+d3%8|S zKfV4I?T&Wz`q+PGXgwtfIJv~6y#2Slf}3{48ZKNv7=%}q=AJ6JT2NR~X|O~vO>>Qc zMR7=ky7J+V`OC$92s@1-LluIGoPeC5Cv<6wz@qxpNTU~gS@)31}`K_{=e#Mdn`*dmm+KFVcLXEBIW&P-dI zTv)Yh>D1A#sazLnssVxfFL=yh+`TBF^W#wa_;!ivG0Cmv$rWqTF4{`^U?-n-uTiN(Ij>tC^AKC_eYI zk%e({E8T(VIRph@@uub;%hl$Vzd5b^d4m2MbNq*I{*zA7_lbEBegFPy?)38V(xkwnDzNA03(I+<0$Yd+n>TGF?G_XC%rFw7P^)g+%hX;w~8?-}8Tc z8t2_#t2p8s?;=d*m>##frt~V&1Kn}a6l&Y4JyR3ZsIGnNr-7=+x?}0X4VI}W_2og4 zk#lp>ekxSc7v*mJbdf;(ZGd$JMj3v&<(E0TdXr!NC4u`O;N96&>2cT#{|V3IEcg_Y zv$lLPx%{Dl=EHAzRIC957eS4SdtiC~_jMw@>}rj?5cS-tiscPY>qKx69qtVrfe&oG ziM;pYO^Nmg@*B#fsQNb2*wb-SeY2B^g>YLe0+#~rDPLMgwUGOA1iYGhhy(W>ecmpz zf0NI>H5K17?>-M=dJHx-G+^MFfR$D${h&fTp?W>$#(j&_cj(9YOA+_7tw;;gHlY!a z@B9F@0W_aE)qxxE&gT7-_~PH-yG4`^4IKT>bjq}wgxeyMysmu0B7m+Ae_mJ?s4#kv zK0HKe>wTA(lw>(gpFC9gH&45VxOA88bKu(Bj;OTf$FCo`EANiIDKPf65#f)Sa;dj) z8YmA0JKb8yP<2a*t#C}kqK}^B-ws^wG~tY+$~?kWdSmMfTwkl!7VVx$8kE`W>psl5 zk$rQ)YafkR-7!r&(u=|7-&eN%bY>(CmL63fh({OhHtv|($@G;yxsOJV)hSQ)@>YAr z;~=oQvme-YAa9=I`V_NIipI%zA*a?2bJZDtp2?B4yqDZVv-$?$tO|j6}b#Rs}?OwlMlAdZMl#;$kJ1_1~O+8|`Fqj^S;0 zDQlcu_6ACl1JEg)g5ey9VF}2FxLAI~j|aYAy?`A$$ef5_OY{3q2a2DS57pxma5^_AqCg+wU(u1HWlt=Y?s1OJj^_GuD``v%23w1rBNIST*GQru%szcFT$|9Yv~ zB?BWRHSGStxzJKv$e$}Q{OzVUZJZ!+XD9OpLE}KS^KvU{KlFNMn?<^VbuZd{E;Kg~ zR^RQOUv)b>GVVf9C=NC2MYPcfYZ(%lP_0u?{4x;mpz$fR1}^QRHU$A}>9SUFjf{cZ z)J;CL?|nL0)4Q))P;tmH2e}^Zo!u)xaT@O#&fjlNYVOzPI}*p3nsPX41BaAm9FdP0RPta)REaSXlXm*h>0!WWv)V6L4 z5AtMJ$0dJoILl2KLvK`W05&v49q0qSL-B>+5TO4Xrz$bWoXis&nC!W-=`#a}YNh9B z$bJ4(o(^<$>=R^!1uoq05ke$bkpkiI|>(xFH! zTNRw-XysC9xz3rPW#U*hI=b~7mv7NA@y-#vX&f8~7|`7XK#q-#OV?$_1Nh?0Fpu8l ze;q8$dzl(qXN=QHauK;)mZu#DJd-_S)bALd?7-P8BXUuRgc1I<(%J#+3%CqfBF z!J^{f=x9-gFpI+`VgJC^Ng6^=tTdDTeubuq8m7(gRzYr4tzRC{AWt3kOj5eJb-9O- zRhIi)CbDg{YCT-4t)gDUT*6KIM>|uOBq!L<4EA9e1Nz~T9*h7ROQ3 zZi|2H4D%Q92$D?tWsU1nr1zKGp3}3(RCMZtKbb|B-4Y2`Q^Gq>iXIC9EP{BY4 z-;ml)6L9I!`5rem@J2nj@%>m;Yp3UFac1}UCm9Dp(3?XQ8ZVcs1eI=pDHK_ZE1O4% z=HIc`)nCrPC)>FzkMEab&?Q#cW^CoE^6h*OE5i3fewyWndJPcV0rSHrb;|)6*+;}7 z^r6rw<@&O2{!*XW;N0d1Km5&?(sdVCC1&cd^+ zUz8M@^Z0&HXr^B^0A4bkyd?XROlHLQ_%FkljJMRS(}YJh0YrPZ;>svtuV3X-Qt^CU zvQ=oGate?#HGS_=>eqL7q7YHLnU^lz42{Xuv(n?l>1bWe>lop?i55Yk12#?Y{>%W- zj`*F+KGo^cV#Xoa1S1~48$O)izHNIC!lPcl{Gp7RV88)J2d$u&L@UTI5uUC!fFi0@mMxY{fy=6WNLe|5*;qb1?L$d+px?`ndWPZ_Q8oM_Z zRIImhYXEme%p{Rkdo{j^$J7R3?JO;0iLq~VFL}qiZ1b*t3OB-8 zd%E=;h^G=3Lt4!AY^$oV`#ZyW5~f2{D6S$*3OXLWXom;U$_oMMhO(Am`uq9M+3vm=-N1T}BI z;?k=}{v0u}ojw&f{k_@2E5zLT(kOq6(qXfRO&1A79rUh7Jj5KbQ<4<(6q1!p7Mrq_YN>}<|*jBIp(}aq$T3 zRxNe;9?P-MyN=6dMv2VqT=%c}wETL?)ymDMu`UwtXXPdi|H4r3YYaz`t1e*6e>(p* zp!`rkFoA&|^z` zJ>1#4%jXV4m2KK~_&IQPU-SN8!7mn!_0dbxly*0kk^nPv3ZNIhP*UU#>{pVRfr`<-`S zK~`39sps=c(%|A7z%aI=_tgzDs&jC=l_?J0)jBm(HH7!BB^Swwh7$JHCd$lGhd#6T z@^25OY|nb38zuvn@4#)=@;izM8qTTLUA$}F9?ygPgP{n%*u|ZY2RXQywR`cOPG=J9 z`TEKimXQ7>MOdVtVo|CN5YgvXR7S4$q3GyPm4HL+43R-<><2t=JE!TuR{d{gS)q^lsAcm zG>kPxZZ=qT*Qh!2Oj=K#IaB*}W>Upa3siP^x54O{OT8@>sN3$YKnTN*G}a@u-!1QF z-kowDRGU&>PErvR7%?rh?wYgMr>K-K&SzRcigzC@AspY1S(RI;U3LC-WMVxKpf)9e zL{uq0xK9aB%cBGRQ<@XOmv_=o;Wx0^?%iJ=txIG0x~r$e$$rjqbuZ?xEZ%cl(miHP zfeP$nXMCK3&dM&_n#9eB515`u@Zg5>P2r`~aSiHlwRm=kU)Q*zD3PlvaC6fbbOgR3 zI!zzcsH)(nE?s;H0;{Q(C)-GVuNP_h03`{7` zX@_Ock_%X?-!rD2pN~u}b!XFr!$oVxb<97>*i0nM)@-Q6FI6@yDtfc?#4h1hh;F4{ zZuu0601^@PrbN(NrGx+{l(0BeKCo0DM zVn52LSF`sb%-;EINb~1g;=JGgO}$^3Do@PD9~2n$Ta1wXF)|9HjGJTh+b}67Ba<&J z(~ivmE!XSu{kppc^{zJWVT!?SGK!8*ql=x+A8fntrbf)25AKF|#{algfwCV85Z{eT zTa!(`+gIZ)*JH60Z--fjc=&_}1sGKL1+K3wIHtLZFqn$4Wh;3$g~AZuoQ^!WfN3vE zPJ6&uPxD5gkeM2N+3U%IeIWZyF;XoCC?A)Kk@>AcDeM(fi-PdY0^&|jGH8jmU2r`n zM(SF9Ykt9#9arhI^HVy{%+$Vl_4s;KO<2YT+|bY*ovDZ#*nN+_^D-LehZqZsl{~PK?EcyL6^78!e4>^5J@do04Z2Z zTCRAHJ~tcD&aGh|Nwghcf9EE_Iyv@E|M zlXDu!Op>R2F8(kXG()rYh60O%27XKr1__LRrz>mwJoCh#Trvq6LW4$%ooR9-1NNn@ zOBR>Q9HW)OXP<&Q3srGUe+Ga_B>Ha-jX|CcUnA92!$`q5)?NWM`Xl;R>f%-1W<+{& zS0^T8aa1-XJ7UVMvCk}t^Nrxfu{TBSKFv=x`omG43@g*?jl}qhFo|H3+w1N=ie-s# zjLl;dae&IXx#)U>N1ptS6rJ~gF(WWNPZ)!XIBfs!)o?m1BzT7RzCXJf?otW#10iCmkx{(^3uMQO>6KU(oXTd(8^$;)yCp^I(D1&R*E zRn#E(yQ_Ox-SK>h0;VR4mp8cPZc+BKhH&+j=%kcH2h5@$alpUC0?&Lw{!O8#>VjH6 zJZf&x;VREHg@XG5n_&N3a)fU&A{^ZBAs~K+j(58|2}TzUd3&x%25W3+vUJyt#y@CmPH&Vd{b8 zXO`*6Gp1?~Z-;LBv|#{u^!+O2rcwxX%RVXT*pwhoq|aa?d&CoF)@l^n zW);ICb6!cg(sDXyj!8uR%|bjbdeG$Sq2g?8u*5`%pAQ8D&BU@lU45cR^)3lYwkfW# z8VR63=oFUJlua)wU`={Ja}P7Gs?Eb%xrVktfkF=WD?U1}oZj1t@q*onRB@W5$MK19 zS$QI@Y=e1jQBfT-p8`qd=lEt;hDMkEbc`PtDs;Zt_L&7%hxC!Roe5;+BLqq zG5HnopWY>kz$VjtoX)Qs10qS;tc{*I8)}h+1bwofffOzdkn5T((>F@v7%pgfhCvi)?TrnBB56vAh{wo=|rdDEeyx zBM0vNtQs8T2Xa~l0Emd>Z{zPzNm zp@Jb=piw&zct>^x-5s7Zga4lF1ra6(#5^o(wNW*MAMs-SouWaY#grrq!|&o2KueBk zJ!r40UV3eUfy_AP7DxY&9XP;&@p3*IM+PbkGlRtbQ=R^qPR4lirS>4Lq&{nl5g0>t zRFtG*%RMXHeO_%lZeN;cuN{2gX!oYxg#e$4SF!Z`u|*<)uSnI3p!!`#+%p8GW}$ve z*0d+d7)$5DdN$kk#1fOV1?Lv zSj=d7e0+4{{M!t%7}H)@hi?KfDZ|~u{V#PxdO+?4kTwM4=poSLQUs$_i~f31`S#$Y z=sP$@sQM|?Ex(D7U6+;Cv3O*?57P81a1yRo0%V(BNeiPl} zw6P7#@pHwOKakNEQmONMw7?bxWSQlul25Xy>hui%AUiEmV4*b{{za+|V$v{45D`qR zbsIg`9}TkXVvC*y4V1L+7y?r{Ri{bUl|SiKBBo+<$(yK#RvIzQf>MlhHvo9(nofJ% z2o41x64xEoQ|;0nn9N$zR1Uj&S)jV_e6p!+$lhR$w?_4|;0Qs{2C4_t7p2dyuUb`I zq)X2cjC{=)W0IOY{-WyW5nzsDL<)bcDIdyo1=LvBO!x9M1yyPZdCzPBz8|6?aMVyH zy;yL)*|?cOj{X%RsSG6~fjO_G9GKj+z6Mq@kxq34`r*#>v?pj6_tp!hJPu)=hdzS_ z(RmdNQpLN)xYB#mHgIK6&Td5~d-qI=4{x~j8EQU;=egxxWe>SxS-uZ|c`Ck}gXi{? zsYeMqnA@NrZ5CA(j)I9zjX|EK>K;vj=xoonfh=fkfzJBGfEK?_P}cDHxK>}%iV%WU z5{|UkaFFG21}*7%j|NTDWxFrkl2~qk?|C!Box4|PRPnelWn))m!$ZY<12uftyWUCJ zTPjgXq-~~_HsW5ITTiHBfBiwIKw4#%e2p%u9mMYJZyi38xi@zq*Z0)+kxs^S(&s&S9+>a{FE>c`9_w58 z>36fo>y35nE<_+Z8c~s5osw$Mv63^&+&pNnt?Nu|!hfyHH2ElIV@{C*cXB0J0YzhY zrxZ%wpWufWE55w<+VJa0iLjj1B-P_(4ZD}3pII(8M=P4D31`2~pzBws_0g_jpIOer zW8>zu0j@EL5>TFDPiYRbCC#}mRoud%xP%27%!IrnJ(N(fEeZ}|ALmrnt0$v21 z_~C=LLyLh5a|u@aMQsf&qG|HOwGdS<50VQ=F>ip$fNGnAXAe6GUZgXFFc7$tzx5%8 zZ`9v5M_k+|{#8`a?3z|(pfR?AVJvsD5Y}_T2}=TmXJWz3@j+@~5Qdt>tqqN$Gi!t5 z=YDK6`4HND=*{qlEbC!40duOwg!Qw{UNz zzkpYlf3IK@8ygn*wyTW(BzCMQB;}^+Y=RC%Yridrw?R`32Km-vHYgQ9N2z7Urr;yI z9j(W3z$0O5fK|xdpsM-?`1d9*z?0XX?wan{Q(>*dkaf{n z&U&>py<0qTJH5}_OrdO6^D+6~kcR^R$kD)6au^JWsT`iM%EC0+wDlm1l|#-N{2*VK*#oXKE2k*85|%R>{D}tDs&NseFx8h0Ar!` zG?e;FBO1+Ha=CHRID zYd5MCE}$V)nzCm4G=BNLz{P4(7U`n8;NSry2)p5?jfp6O}ja<)T3` z2JLncuB>AF6}6rjgV0G}6W3W4{MJKqK}p%9Qb&HhM;8-($H@wXFuXGP^J&oTelMBnB@yr#h?F2zs$lu zk{o42x2IdnkeIU0dT$u*_!R_tcwCYEDSY&cl3rKmA^#^BuSE6T;|*678f z>LcxCHSodWA%vJ&&Jx(B@Q2^|svX`!^-a)l(Mo~3d)JX8q{}fFG(s@`{$vg&cR5ht z2L>92EGo;Wt`7P1;;O2Zb4t%xRU(i=!i>f;MTN?gd|!4-J9oO2b^q+Xx5?V>E^#}a z?1A({mf?A(TH>=%`#ydbU#g)MgS>EISovJ{&H>oBzTO39ejz%q#*J4uT4qeGl2@dK z$S;fh=e$q1<0p9QA?gYnApbPHsom0X{WDwf@OM0JizAYX5r-io_-A-aF?RFqed(y9 zjISOy@cg#z3D=l6cVqayiCakykP{$8r-X-EcT$DzCGvA*;!u-y4oUGzGsYx?>rdR@ zC8}86l`Uop3JZvu@tD}IQ;`$n0SYA6YFnk;dWQ=hZqJcqS&3Sz0p%y8ug0LF+-DX( ziIc3()u#D&Y72Dfev~U8rbS&NXL0&j%%T625BytOz6+*@GaK@eZdzTfkOO&tN^o~f zO+-`QkCy`)kcg0QC3187t@WjpUuLG~dx|$&CpG{4&p)m7=NIzl==gJH_+MmJyz^#L z)$23M;pv+rp?KvpC^&gUGU_$INma>Dr%h_(gWT+&Sx)%ZH6sRN5+f^DO%oM1QENDr zK!;Twbbsa~okX=H1$_j|Dy{kR-}Zym$Mu2iaJ33DG5KP(#c_rTlm_7eOX+kYJqXn^ zrE1JvU_JM|9G#pTsI7+wD}i*V5C@)7_|@S=i?Rr-Bwig2!)&Z`#CIzm^WdG53M#oi zg@#1j9lWp^>VL{~*J{+dOhlVnknFV^4{Z+a?eyMFG;R=ueJn<~#>l3s1{p+F}~1_EAc|6vdEKV$Jf2@?A+>FU2e zsr1X5U~RlXy^*pLv5q3%X^$AyNzxL8R#&A}ZDyJKv@|#%TIL$B2TrXGPwI`>9r!I9 z@}w!k47`o~O`-St^h^XJa*8K9>;*K`o$Bckjia3}-6?sv&nz_*CU)%6zrHiQtQM+z^+!JZ#oq8zm_N!O_ z{jpYK`$gcTdTZ8CKVM5R&iI#@@b4;Fz&n~?vrCcn&3wyueGCy2R1?9;gpVKr*j*GM zP{J;@)iYox&rODAOR2%$h`)8`B~Y_0-~0jU8_LU9W9FY+$NiJdWVj$5>&iF7?MOzA zHI|#-`xL056SB5j=@!H!*GWWI$Nj7~0*=Iw651A9U$g?aLQ>Sn%-x0RYc14zGMRU%V#yTp}5>6|;rgy7aOiuN$$zZ$oZoM(fPye`i?@tnI^R*yUN5UbWs%CZfmkp;a$C0PZl$oW@ zi)VkVxzD>~m#c-$JN|xW=paLxy_<5>el#BZnMF}%?bh!-*L3t2{grZPxk-#kO0KB- z4X62g55xXY^&YpodUR!Vci_5u0Ngq0itiu0_{XaM-Fj+&8t?b_@~83s{PO-Bw*Mc` zc?JI%Om%&)Q;$6xh#?r7#ys1j+xw;xvI|k>+Ewx?N#NkugoA^OJB?h2(r;W$izh36 zO!}}hST^?`s6pp9j??!G9N^MNPd-A42V&+0UTGZ}d|b)=Jukd@J0)^DRprcVFqw09 zzkM+R{NpO?njG{M!`}#g5pb;PPycNY+xB6LDG2taC*+@S%_JXsUGgH2sxIV(XkrHp zc;=S&DT{h}0Fwp%@2{`6D=G`?ALBW$Pl!1fkM|46wkC!p7r^>_xtlRpFk-b9B+8m(X>XQg9h4P{u{hC46a(eU$5u2;r_#gYErw>W!t7(cKl50mc^vX$l^1o*U-ep? za#@el7OcxvMN6=bd`%*26tYCvC3P}GdP8Dj3_b^FnAyKzn-;6ucg4h6zV9}X{E0ZatC6TE<@S5({q%rXyv*GleNq9m| z@5SB7Q!Pd+nMp|Sq97{T+M`Qr-~x_>W{eQv28 z^-LB>W}+W{={+T-)+sYM2TD3(eS4-(ddU8;_YcL4Db^Ei^TpHyy-#Ydks+lg=LRX$ zvm^YjS$cEG6WQO3aIkUqee=OTPS6lEl z$uOkw|GarGZ!U9rM_ljs=KW1euSF!Hc6-B$w|Uz}n$6BHg`aFaXC&A374Mjzzx}KgLQDceL)9`cavB4Ff=_sN(_)cPw@ZQ>0=lV7rpKsDqdyeuJ_Y}~ zHNW`Nn134c&oA@ehy0(z{J+|qIp`zQpxRaoF+vVVS^+m((Bh;pr|8PU6-u>uQRRyc z=xK9l!KUt`8v*_bC@;6v-ZVj;EiQa*mAL39h}ur>(Lct@>l{jq!SMax(mmLD^$&X` zoBa%wZDq$E9Y&8OmQErcE8AdBn8D0|v_Co$|K9|JA2RXd>rDK(A_@LGe*Es=Zv)t8 z5;Px}Yi*1k4~X$C5h-0ai@BN_gym*`LS5oEJ)_)Yc8Po2ZiVunfz1^d%3YNRgWYPq#6NP z{=T>=G}M$2b?#c}(_>i##~wbjmM+y$1LEJ55BsPe`Hi&G+d3@#GOy)FI-0oG@Qc60 zjF*otc2^eITNyOv2cBmBYWVAvj7s2SB|H8R?@g(jpfv@%_^{&oM0-Nj{jLLiljxvz ziD~y1<s8@!dmeLF;I zgC1HBOwqj3R%!m+rd4VfBifBi_Atb2t%`~BP{7n_4he*k&f3wdeLfO#`RVNS zG|d1}%f1UxHHc^Ox`hjaPDSyyoq94hDFZWsz_D%*8-KuWFx&{C9JQ-!sxOS+eM~iV z@$eT^fqp_avRUVB#^Q89&^qOenwsD+){6av?)zjhnDgeGZE3D6Z-m_YW9Qpso7Lcq z8L^Ta+mL|mmHoU2a#}}^I_zrb;uiU{ISU65Hm&AL_O(;AHYI(}H-(NAwKbhr2eGR1 z&}&FGXG?^R#qI}DLx7S&IniSrZ_0xrz^XTM$}W&kkrU8HiLmTM0JQR5alvO6Vad>= zC+BsT=yNwi|H_9W{8{hyUVLVWsCQJ9NYV?=`k@d%Otvy-W+PvHFoE;C6f&#Y26uGn zp$8h=H={uKdYZRVF-n@3+Y)~l>wkZ#mlT`3;ZLneQSws>Uh_bAo%=6m&x!zp+gDa# zcdf&<*p&>yhL0q~&~za$us&LG(N8FOLDyd}SX)OY*y>i*Ivfshn;xVyGY@=4CAWP^ zr##B_`8Q&CmhZa^)Zq;jA4-+vn7n|R46ZOVta-caaI40(6F;7{SrygTNjN8Nck0!? zNiGi09*t7+@I%_s!#PSije^wUJ?TOr>A|9OCfmcApm(ppDCW?9*PZ`$3+*tZUNY+D z*rmW<#?B3F>takDYZa?569T)$7s_-4Og^(bs1}u`ZP4Z?7{p)IxZQXAH(nbA?I87u zeb0KkLzlDXj-^df-VNa=$!Fq2=~JbH7-jp>47HL1{kJf>LGp{oiSr@(=5NRKy*hlG zN;j+TTND|D2l61~>V!ZZL}va)v8nCoOii$8dUM{eNlBm5W~ttXAMPEgTw?26iPi;) z!`$An6l7tL=4PTYN)=vJa`N!z+ev(N(^!*s{@wSj0?mW^<*M!hj%fF49*eo9Jz2Zn z6<3f67mT!#5cOgFUTCCV#<06?+0@u-<~LJh;D9&rd+J+Cu$DyYaqLpj`oVT%3LAK; zmn^nJ4Q_L<6;iyx4w zapsu9)gOx=m+gj-_M4yKYM{UD?D15SU(AggwF{J6N{wZ^Qa~Dag8lHCuTk@UxSqIq zu(tdSh%%Bw|Ea~09k4s=TtgPs({sTO98Y4wRBTEgbwneqera`P#X2wM`ozYoRvPC3 zNT|?&-@tD%zl30KxRAPZTtPkn+A-M~vik~z62Vt>rfZjDZ>rYG1DfZlf$=G}6zhY4 zDoLNm&R6mM^wZ=9kN6l!T8!Ym zJGl5U;UlZ4H9&Qy_!Jg0C{gURRT#&qZ@lbxDp0ycz6*zjOCZ?6YFtV7Y>39C_p3hT zcEZeDAa4?Wj~J$EVYFo47Ed&azgHP0i$~)&nE9y>W zC2{%{b>o1+B)LGSPe#TlPjJcceC91R#lLVG{_M$0bh|Pc&yd-Cal>|#en{>!uS><| zD|kG~0nh@Asnun@O!VL0gbUIGXy@(VZ2ZnCwb~Oa{-hh~YSDPlWivjP=GAm~8@HQ@ z9nJOm#OQR9(B*+Nvv0SiO#NN4xKk z-@Na?K}k+z7$4{XddK1u#^R%&x!09?0E~;~Mh`eI^(D=w%dLc9gn=a@MvcwX6k1(` zjE(b3`fY5IEPhnGRxWOG-@SQz&|1+tqlQ>n6W{NnkK5+vm{@0f z*I}$Q&OqX|1UG|7!RqPX$Q|{2#JWmnm)M2;Xz$(C80R4_R1u#V+V6K~5gCB|H=U7Jv$@Uhj-rRse>!=1nz_*LaE&*{qYRMk z{#p@ZQ{pdWZnIE{s02Yi3<(k}>GcqKo^C({)J{tQZy&c|OTipy5A^ydVvN!%-(l}D z=y!c(Auf1Qe}?PEnmj`2b|ZWww%CqaV0CFk(7Z z?!G^-Gz;^!TwUwM{MO5bm7UYN_wwkGB5(dv*>y$%m{-G01xu^bf!REqp1?BDi@I*fc5kUli-t&mg^R@}^)n;=ju2(tmxB6eD|d}}q{6c@WA0EXeGfrTcV zZSCX`{b&73`7tl=k?n&aZ1s7ZIxY4GCBP}8)%{b6QuY()s-J8+_LxCEr;Q~?WY{Je zHLu%6<*h#{&zF)^JE%Wiw1I58#)PXNo$C%7chVlaVT2fq?W;=@23% zlt4hGCv*tC%; z{~Q&_>A6>^sR;%L`%UX-^neIk1F9MP{4JTEz%}*(IUK`m=i~bR{xGfh5VQY*AT&T| z+0N1%zli}Jf1#uO$Bodr>KVRCgge?|IS8z{pIf~`TtSMf59~D z^>3!(A(m$YiezPc74zTRG?_DcHrYX_k&edUdaE|FmFkZKbvB6D`*t33!BDo8QU@Ls_xj z*h%$slf#AKp>7h>rgzi7vVES*W$0+bmyIm3VEYXCSn4l@RCa)-Ufh#w765)BCX7nY zXd@IoQ`P2^q`yji;UIl?HJamv5lL=`X0cY5<`v9W>}7f&&`4*WZ24)S4%&nNvbBoI z%M%_yPHA>eCZdLrXi|J2Y#`8pxM8%f(nGn|vl#WgDrIz)h%bf%mejb?12PiLybP78 z9)+DRwTgeIFH@77!fk*+8L=Gc7wRKQ2d76Z-TQp0U)e_FV^Q#+9Jnaz*OBAW{U1tG zW7XoPj74SqyHc#S0^?FFHw3A1kI%HD%C;gq^1rg}biaJ2uAZz7oA*InxQO%bb4J6} z2`*aFFH9(2vNl#Dua>Ju(q~$(*)x5om2(aJlON@zt9r{3UGj3=%DF%3bkRiP+Sg1G z$gHU@kC9-V)f-3j+m&IS+MJoLLd{15mjs6(;Y04eCjwY z+6G?LwNS0)+HD^{orP{(6}!3&=vk;q5+0~9poLjjS>~HXT<9xH#^G`Ra5LqtfHEYI zIpKM#Swvg$QZB7=QZwu(hNOD>+zL(#t(*SRI_%@}G~cp}JF~EL^P?7dzy4l4RWvj4 zyI~wU!K$fOfP_fO*OwwPmd%R^m zgB*XNqSXK~zb*y{7>@d9iXgL@3ay3#Uot~(lBHoh=m;j>%7`PD$s?p9Ec->y0Mf?M(9<(*us(Hao3F>xgS8kz`0H?7l}Y zjh(w^@F#T`W50?Cp+55rF}yOOUSQm`)BDdeKS^)K5Cvy{B8jM zCan=L7i15D-d#C+|YkVE?f7o4C}uq>ZR|!du;bw6XPXKrg$+dUihuq4}1B(!tBb)_c@HK{gzxh zLmk-P(zRozM~XjfK}cy`yrh!Sa>vCpFVAj5BpI^5`m4`785NsEMg(Tfv4} z8F#1ZkwV}9YB#ZXR6TjN3yV@QFxeBaWXd}+m%JtSnm_M5et)9Unz7GEfK1JYjd={H zystdqe%=f_#LXjyA@Ne^c~AV~MVYuchGnpd!!i>s_96Ak!6f^$cdRIQy6n+*B#P8{ty));QVp-J@jyL-xx*Fth@tYdN3By{rR zXHUmKB~@l8FZNu2d*pq$+~)@y9Xk>I65GIcAQN&pkjhfcmfqgc?%Z-7qW{orN!^jl zq?w#qP0Ei}RTgjNIs5k?`sqEUiwX^E{H z*;qqGz|~d=1nI6rrirkiSv|>?U_DjH{61%pE;JFENUz$HYZO#5b0waL>=eE(JLd}4 z+o$|tpah9hOBisJe{@YT`YW6E>73&4$~^EMQnfK*GDR(Jv)8_c&$Vkbz#QwGa(|+v z$&PeuU-%%4f(X_lp~6o)%c-%Q?fWCEVSye!D6SVPuKybUr2mqH0zkym4JOy$w_c5&xVCXL7`M^ z;h=hdRe7hJpg=F=MG|1Cr)H=x^hitmS9l69Y_KZ#PN#R3-$1&Zlz5T#J?>{EDJp7` z{4LM&)6_NWij%sNxRz&c9peo*`T<;yfST_I zj6?uCSXzr9>2Yz*)2I-Mkq*s$tBh&1#b@uBc|pG2u|!MSMgX!CvF@aO>>o*uA4Za8 zJKqEz9YibIBDNWVB|_mm+KC1(;;$pkH{~0ugl;}94I6u;IjFCQkCYBAD(PUFvFx0g zXkf*Y`G?-iSE({TBF7EANygO)+*JhX1TVkaL5xS6f4UBhFE23?Qx;L&! zB&Km;q6jq#sTP$S=<|8bp*Wp#g>C;F;+-*4THQ()dEczDq{W>Q#5G(dyQ_{zkIvuh z;Loyf;7Sjf9j*!4^&M0cfiWdbW7Pc8y&5+dox4h?=h1e`LVHYYp%O(!rDjX#!7e-WuG^Lf0!Lb>d=B_Wbm*fRbNI=4faw zgw15m>}!I5c*;Zl&ohCU5QeLP<3Y{Bu%boAD@M--)$fnI65GL1ie^I2nMz-uX6S3a|28s zkFuDdY4|j;03=~$&Pvg%LBzD;%f`ry4FWzaz}5C{R+I@kHbu&=Np!eQ$|^_&IpV*~ zT<9V!>YA3ZdyiVG_mvskzyG0R3W}P2jlhW`yeupU;ixW3z_w~+o36#TIb=`D034a! z{Ki2gG(7`YBhy&((yXZ9fG7y$DJ*uJg6Kyz3TlYg-%Hg}yUOtkOvTk+dH%K6M=$~a z9G>>_QGqB(E=@0hNPYWd$L+j*8-0}~TevJI$r?*Lx$5O`o}g{d=F8;`2S8{IJfn)- zr0$yfRLw=%srb5Ob>G80wB2f@#RF-x&1&tdV5f`%I26+lG* zE>&!Gz^P@KQjv@47m}Mx5=Pm+x1{ z>U(!>3S@76qT@2NtI=a5@?&|HR%oYq&p`$X3ASqh+toK<@Jss|@+y}!-Rj1t(^mBT z%1xGMbsZc+=HqR4K~e#l*b|a+gGEKSdYR`gwD1#G!LYxF#LZrgkEZg^;rYR_VcQw} zpwY6@b*HBx`<1PP(yiH%gH83QWuMboQx+f>@s%xGa+>KGd2dl`Gw;9p%=Uu=1{-9N?sWs3IlL>qDX`rEE=YxdhiRQ9I7vT@L(T?IECuAJ6Jx9&TR z|19&fbaaIEi)e45jnlEcr+=0DYc&3Em>Y%ifr>AB>M-9!I=Sqb?U~*F$t^L1#X6u4 z!`J6q+=*DSYzv5_eyfQBXk0M_LZ)>555pupPaE+yk1s_1$>Q;^JpLD~BL9gr)i-^x zlm~uoRU-6^TCi_P^FeJ4U`Isi-?p-&7l1hzcBe#iSJT`_| z{4&o?T6DabgR1=7u$+`fCD}^d-u3OlW?u&Ur4^5D3iBx+gMKQGIpO)%j*YMK$8S~0 z^oS2T<_&^x`<~R*jVlee8jFd_gbUkHL<0(~H5;+p3wy$Q^3y51-=)xbKCEZV?wHZH zRF@sf2Q@41P_k2X$06wkd)v5BNWxU$Zyv|e1Xy{DvAV~ABCx&iLrJ5SMy-}Wn28iM zna}_u=%5!5Hf5gNCdkZ;=mV^BnnrozOOeVwZWOYG1EfoU8iZ)J3{&k3fMmlfYjjpD zAN|@A{BXyd92j}7Vkmu5ayD3sVqxAc00K#0v*p|U$`(pcxU=f;$+|YXP~C97mB069 zN2p)K{T;vAPiC@KJ%0m>fuC;8K-l!_HHk;T#2Y<{v7CO{Zh2OPE?4ZK+(2#R6Wl@` zp2h4M?+?gmZ$8yW_}0?at}9M3NuSJyhC3<-%{1Z#{O)lf0?RM^DatG0R(L|T(Wv*vvOH+~!nHV5cAx!LIdeuOy zbyckG_{+v24YWkV4)hGo9%W}gyj_(92`kKoWaGHGPzA4ll4ch9HRY@MMU-^RB1Uf4 znl(Mc8e5tK-tEdZ>NMCVad)xiOJ7_=9!^S%k1nk{3g{V#&DH~p)>fg!C{tnwD5hKq zm36LqWu28t(wD{mzOyLWe@F5u7F%H_K}_I9hTdBG%#x#`ha*B#)MKGejVmcxhG<7G zC99)M`=Y!h4{k;~oR>ds@)~Y^x@<;Rqao>vFy+ea0l!4geRjY?z7TOoQ;Z_6zl1cf z$E7u;1b}Hl0I)!_s0A}vOY1FJD420}^_ojS#jaBJ>)JA`U41Yo;rpx%5Tbo+$)g#W zVSVMHipoaJ#f7V~jff)K-~80DrReB-Ct zEqL72)KJq>h%$|_eL8=CK=SGAi=N2Kon$#TBc$pOO10f3un79;n+wXn|0}D|-{tw= zFP3pW;ortUf|emHEYuGW}$q9Npo}@+r6uPE(`9g+>&B6}b+m@u(fp z+wXc_>i%70*}k_eo6vd|c9^2?-O#fVIr-uZg;rp)7^&9a?ONARtO2j^rjJwxTAEv& z_s%VWdRX6Wti;3^XcX0JNp5*;z+ZfU5FTc?s~F+>93Q;q4gPN8r&&N*EG^l>St)K_ z4{Qe)8SkE%ROL?9rA=7wTOI_R{q25AohI+q*H-QItHcsqQ4AM-WA2gF2l8@|_t>=I z!$7PN)LY?X80}EX+3lH)$+RqB!Bc-Ho(OJyWkb7zF~X-*vYn7cRC=btm%KN_rIObS z5>ow1T!>|^rC?Lyu=vbz?3z1S&@sy5`P1e%RJvzTvEk{xf|rX)iwiz76(qV{u>%c( z`jwMkwwWwLqGBHAU$iQDKLQHAY5d$A^gLl%85{@?t4^!veQY11rK#z$`y0=>ddF-J zxlH=K{s-kpU_Wfjpxt$?_}D0SD9E%eSP2wh@iBS1f_Mteb`QVbHsU!3R!Y}!`mW;0 zBfx7i2m55l-$>Tcs3_tKpsO=VrZw?;cYXr=dTyRrUx^aB(n z*UlfXG_q>l7hnL!P)_|6zT9rHx}!ex$J}VtbQ#elD3Z5TNeTedv}zBRfAx- z13O%?T<^OdUpef#QTcI3*>^^Y4qQ6q?*;RJxNGaAHyC8*Rd^wya}<5 z5dzw!bX3*VFDA?m7Mp;R7!7kVR33~72dF+n4y-u(){S@Eh7FdpH}i(WGZQuq#YAya zd2R{_&6Y(#kbii|OWOC+?$xa5bPvQ$80ykp{JHBjT!!A&BQtZ`D2kV7AXWLgV57p! z_TXUaI}y2U(~G;u*Xu#XUhQ1B-#YC*ucw>w6%aP1+7?BVpw)El2I2Jz93nfI!~PDO zfB|nNHQa8Eyh9o%-lbR?TiaezwIS2ZO5s`aj=#q<(J~hc2VH?d%#I+0$H+$B%zV7t zm8Xq9PTH{=9mJg8@ev%Z!~Dy3QrRzd_i4jdbjYhtyfw=Un#&~J=4KC^?NaTJb58j> zx|41s9)gAu&e#6N#&#*6G0xf~^|2p^5rM3HaVZZoa>@3v2%)P!)L3q?DDi@S3<0cf z2>VpemJC^&%=dU}?Dq7Bpf}c`^&VqmXO*Zu%QmlkH$Uu_B1D+^ z1$GRUPs9Q$E!3}|F>JHFnrJM!ik?rq z^=aIfVoITd6Fp;ylKQ1x9UhFypmnDw4(kaBqqQIagut)3G-! zy~r5m_xV<wOU2+wd!ZXlclhA!>X-XV(RaUB=++a zFe{#*4;A97?s7XT->0}vY&HZ2hE{zo-VD&$7x}y{<%ym1-$VcW!({i`0=}FPxVrCR>LaHBEZyp91#0+4_#Rn*@5X>= zHW$Z(d(xL3X78?Q@Gwe4=D)Hjj!K=M4Z>V0s+cS9*6;^|)owyXY&!1QC+S+P5`$nzW}nj;4NLQ3hb%E4h`OtZ85CeYQMgzb#c}+t&8mRd52Df74;+}Qe#8lpl^=ST)JUQ zh?!69SGFhkH`@=4sIRB7?_fBb&K$BU9iXBEN8{#c1T3{)m_yBz_!(w*+W}n42ZLWr z%6zujn*oxRzXIsPFw|VGm|o(pY|XGALLRK2kI-=jtmXxsU$Hk08pPF-b+4NhBh3WL zEYFPXi{aRbbBr8qM_9oK+^GWXX6J&)!ORLXC~;cHl$cq*B#-(GkG1MmZ%h0T}lOPiW!bPjD`yq+%Jo9$lAPq6~F z?HqA?Aq#b17ocuM+~C@IV;%ZsHm+CJZaKTyf>MsJbj!m(cc09$96#wk+Y-*LR{s#q zX?xB|a_ae!H9N}9asqxk;r=OECm^SVNdlT)(22zCE`ktdg-v7eVVfq5EiZ z1ftG|yS{9Uejb{6f4X|=@~+c>+0)9sOm1%X1#|n#A%;O*NYG^6`X{%#yYg<`Y z=R{o+|D>j(DV-FVK?<_k{B?Q0swnsQl!nsSg+UIDP$!w=k|ir@vMEh@w2`h=WqIr3 z{YbLxo$j(XTG7uE$ROY9LV>^46IETUcL+g@&*ZMraXhu*IHs8`+3VIPsF&6|O}$NB zQ$rbDrT3XU%2Nw&pT{jmmT=cG9*Cd6$y5CMQ{UxJMW-8Z{cXI@$s%X9p7==A0U-a7 zTyqu>M-!Q(@*IF`=&d{XDGrg(im6c>Y|2IV|GtuckWv&mB6pjJwkW#J7Z3*((vRw= z*f7LnXvXJA@l_MJ+=msa{maA>Z8aE2Q)0T*9PeY-}PT%q@%c0KhWZSf!>%q6q<%^aAdf>8 z_6lxT>eWopN2JR3Z{_TfGH9@d{>z8vOW(cft;nQwFV6dXE1t6H8~i~yOrNW zaNeU5w;yR)*0TiE>z_vmEDE6`0?@B6B_}cRUy- z!@yE-xXvPlBqf2SV36#x>j^Mhe0}i}5s<`jNK0 z!w#rJ;9>D_eUAAr3bm8|Vk${Txn!}b-T@;+~ zJ)-|=iZw!bPtZV~W*Nix32V;32~^>Eg$5;f`Pt65#_P~s9^9>9D`$$G&WPgnfuLIO}HDKZ#~AMjJ85G z9*6BxFz3!eF1AJ$@%v_&5A6A)F1raB^sO?j-u)1?pWWHXxni&SgjvOJUYQK)fUm1A zWLZseCA%DV0*yHFo?s(YKs5;WUmnOFw2k9eJ`K#$%-6-QQd(HQ>fe&6&Ii3z+*5qut7 z62R#U4ybW}?(29T3wy@+{kd4MFe5oGxBbz(m74t<$6Wa|bBq~=IG5284D%h#4@DcR z-OV8cm>bJ_J8h;4`C%d~J+3^bx1Y;rZ(9~7nJ+k?wBHpc^9x)X9bg3GZ(@Xn@v3#< zD*k)7qwWzzM(mCG6S*p$TE(rEfBdakRgza~0D~wc`b%};XRUqeEbhPA-SDv9D%H-K zm%kY94G3qT<a;XRrTs?Epkwq=CYE82Qf*mN4*OPv6 zTFT#tl%+xUW<54!a+`tBy@iucFL&vDRrYs?wKu##m+EuQVe3Txl`Z z>$(U34J=>92X&hqcKdAhA)5FA9oH1T9$21~Kt|10PZV`N&Y&@?%E=>LIm((Pb5mW| z=AIle-G`;YdKJB1;@Pvc=9VfW{K<4V&1(ppMeFq>Yx#`ezW&BW;+Eva&rlG!j(TKN zH7{xT3aPWT^?v_V#&pc+;S(BcM|OER-PiC=!OYmB=_CbH@)gJ0PaFAQd{A+9`g~w# z$>J|gU)eUo650|pY0UBwsbU|yuzlgl?*jF&dFP1ZrdF$hrAae5_Y!Apyr>bxJ$I-~ z1X?db7ZGa6D07C1)5CYv>Yh(v?{lT{rl-43$Q-QUaCzLYZM_4>%NcpaKF{OD&wx#> zD;u{n?8+jvAgfiCB(lw^i;JLTWCA%ocz{gnBD_&MDZ$QIDEKp@IvsjVLM9s~GVG7d zQ=Va_%U>IO*q+_Sh*x%T>|Zw2SVjyNpnW z(nKp&ZzjV+##{oL+F)gIUylFC@5&P#teFbym@zd=ZnF&NWDk~=SMbqJlnz`Tq0D@F zKXEJ4nF}@d+LYjzia4xrwhX)(E2*jby)W6IG}dZZ)8@DJvxuI>hMr01RT^9*W3iEc zzP9whYfR$fwQ(i(??htC+p3nU`vZ+AdFB0Uy1?qsr8XVk6q|2mXL_8yw;jgOg6r(B zO$qFBS>#!Qq(COjkjXK5B^UuX=3-rJb$p{`6xymy!f32HZp~%D22qkF#4e@W&$LsCgff ztQhccv7A9KOzX99Q;S!u>>gFs$L2fn>M4@2*>f5G zj}04jNu7c&Jrty8>77rdBd~%{w@gRd;GZu1P3-4?vOWFh$^U1$HvZGTaAc?3xGR(f zEhjgORcn#5yq7$mme{X-$FRu>xQ9N;g-@Ji%zp^TC)wIpXdC& zv$8Soo_?qqA)SH@ilwXo^QH<5c~nq-e6qv9v&|`?hkNv_--z_YKG%(d|n$d8A@qauT$X#VzWFlZGa}hD%=|cQ(mC?ZQY< zergJAwaKGi3L(h=Tub~l%lZ9KIvRe5?Gotizc4BOpDa;`>l@&aUSkU`msnRd)tmpz zaGIlJsTdH;OD{MH`Ycm5td(=gq@wbcmB^TzzI0&`-1?xqfr@QO<^)P8KFs*{OF#O- zt2_>VEe&sTpHK4~V4sGMb5IW?^s|T-A^E(F?JZ1W^W3GnS6dQY+~UaY54&dq=DH)Cm#UqKH@ExD?Mc zDP>5g9i`jJKW}x;(a+2b%+1Yh7WUSmk;;Ee-P>2pSzUVgw->4BUumVzRQ44ik$iWv zl`4v8p(_zR*0AZ+L@&|hRkS94Z}GEp+F*)mfejMJ91B#?7rBX_wNfX94Ym|%@XjMc zPqnaq7qaxzp&sHcCYF!84&SicTeHi~X@m{Fl7uu;W0T=n^_m^*;<-*|D6C19CCSAt zC1X_J(E$+6)##SXRo3XZuB2{bsFI1|<`JK1`ECneP*hfkj;%fq0-5pWWlGcpHKhQv z$RIu`sdqr8Js;!jwF~);{FQpt6=DjZK~@a$XckGBii)?+j|c$p5V)5Tau~aW{_`0R zsqoVrgoyh{jLxg+JJ^Rd^RJup<(MCnnJd_=&J56%C@~e(uU-gpU6rwVxy z_O{?nFP9XZKV4Ons$8C|j|Yd|TvX-q`h*U#8#+Ph1P+*}NE55Ul;%ZEn4wR)etXxR z-Y9U+i6{D-U0?UBJDE`zBz zXg->uKjw&rfID~Tx4Z7hB|7(%JT>@{Ft-pJG6e2Vab>Z;aI1U7+*RquAdHhSSLF3r+I zT}90qJ`j88h3$Cq%2$D z(;ECGyie`-;H^dQbU*zk6e>R83qe=eIrF5A}ukk3SjL=qO{=Rr1BqIQ^<^a zEoCLex5llmW|d#hTuDf|W@CI&v{`Jd_;KLVM=7fg*0)p#LXT|NIP*3B^)=$pIsf+R}KD0u)nfop<62Uaf(FT6fJTHXj;Z1^SDF6PA)_$wRlZ@&cTQc8DZ#Z^?Q)9PNJ z?b18AV4(0M=Zg1ZayhQEk4X4X|K;J5u!nsQ4FZd z!e|XfzaQFdJ>#5^o{~W=9w*iR(I3t~N{Q#O5MpjEpWTmGL9ahBxz{s|w@*8uVgGm- zep*kfoLW_i^ko6*f-mj&iXEQK$~D;u0FTw&-jp=!{822v-@DW{M**^|8>pHs256eP?(gi zT9@d8nddDA4wjO^{smsCIo1=mt>vZ7__Cu!bsmM90RQYl)-P7-`BYnx56KF4x}#e{ zG*m(xqvY(<*vfb=RV0RbG;2ou#MUqS=R?6id;X3mGS!W<==A z=G9z`doQA;0rd{4zbvBv`-R01)Sv#Y4vrb0Ern>Y=(%T-H5Son8Hdte*+h6YO0ced zrFSVG$35oihO6D_pZ8=43%dKDOGZ02UMu2ub)HH9fpYtBNzy*-u6 z7wcZ*Yc?F(bob3V>R7Z_Fy#k@5UKHHFI|54xEis4Nnju_>^KWwSFqY&^nr1M+FoGpf`@g_iKQZAB2PfnB%mz_=B4P)NFlypV88a=k!aD z41p14u|JHIr&YgOq7+kgbksX~Y==Ju9(!>{hhBo2@6>dTNyvo#5S4Fbjl{7o_#u1Q zH|7tYjLF_TLO*l#Ezy!|WkThu8w8uf35a?n3dI2>2pI>Lc1 z65GG@VrEqllmLxvf-6Tt4UPTN?ip(uFRv-3HJMAA;Rq0v#7533(#(1ZQo@1;ZJqUb zx^#@M0G1xwz4}7SD$jBSU6ji_n9aY~oTT+j3GBDwwWrFJ;+Z_tOx-=g%-Bn#ONIHl zmTM_#g1wFRK#D47b~gz$`jk_BD}v|yQ7L`OG_MzNSHLb1YiK^!EPJdvzGK3QUjN%* zzxo#yi-10(8uvgl!mV`=>nl8*sNI^-fI)gX2NLlD#*#LN^XHz2p*2Pc;8Sot0sS^w)vv|r!6-| z{d!l8$V2r3xHO&vRXW-m&3&S7zhEOtG9T^~-dcY={>1w$TTfatu!-KSJQP+rcb${& zsRC0+Uhi&1C}mW;=j6;%aft_g+g;%~YMq{W2$$H?rYeM4Hb+4D%i%Y72lu^h~C znS-&y4cDE$b<)&^`p1JTEx`=Y(PN$^h-tRow)?t^DfnLU#GN9FABxvaQ2zN{u_~Tm zz`RjMdU~p(HVAOi&)$aM_G= z*rDKIoNvoV*TSceMNrfz{MwM+W|t_w5S#EWz18;d+|n%Eo;>BOugXZQIQStU+og1d z9mqg98Y)~?o-z|vxww23#_gQYhR}fzbkS$#!-|F1>pjnf6C^Ax4b}|!0KeP%AFBSkz^$7NH+i(q+^<0x&oHG#r3;Y z-MrEop-I=H<90AaVb;7XyL;YXT7PXXi{R)xjaYoCG4d0fFyxGQrE-bC!f?rm3J8{} z%W7N=w~r(E2M8YwnT4USW@><3CqhzlEySz3SaL#R7SUcDgGxPDJQkzzWr$4KHM+aD zU1M}BVsYvunRS;jO@Jk>4ji)Rh*mHZxL0rMK)Dx349IE_F;fRyx5eCNhA^`Cj^WK7 zG0Zv`cGXYU4ra>@-h8+(?Htc@5XaPoh15-CV}t`DKQ-AlSN>S-Az0K5fjixK<6oyN zAsxvjJ+arxPgb{~)L>BM;3a%LN%_U_YG|khOso=G?y6zG*&1+h-AQ9(xFZU6c{aW} zv&Kj*tff=y=Jr-cbgr3enZ4P@aq7TPcr4BqDk4zoZ(g@+CwCn5aqRZ#(580lZiJ== zU-=VwM24k|+*#rf&vAlwtM(7+D;=7?z3aRtnRZZsMTrOIoPx2;Hh{qDTODVqX;5)8 zICzytl%#mc)VovOO>FQNdLoE zV}Q3}cJ%{*uEy+wyq&+K@Y))Ic()aS7LKD>v*gjGb_SE3%8&NC{egA1Z?ojmKzaHx^- z@0}b$VR5DQKdH->WL9KCs6mi%BZ@xPq4O`HbJkKVL7KNPB0*rCmCs*lr^aX$ryT2L zmxOuIo0IDD?-;Z3jCec9)K;Q6osc~FEg-B8y@+69bQ&gUuyA8p4!ttThv+j(KhzmSUNu=V7`Zjen)lYhj}5yIB(*$Bi$_wjP*>O6-8htuip?mD!aPI1MqE|A zn1#xjy=*{qBf~e@eneK^TK~nu9;UI+M}7HAiB2}*OrdQpC!UG(bjwWGcv=GKjIRNB z&Cs7!gH`+AL8>*kz#{g9fFT0t9E)HhMO>-a^{OcK$$j!>pW`TTS#TJ;$9i`kA`e+V z?wd2b*{}uVIzqWvTCVEq>I)Z}r@!8lA5VVR1XTo%Iy0AxU+qJBz8r|wX>nZh3PkT$ z@x|QKn`t^nodO9Z?)xcU=Cr*Zp~gS|`WMdWe_Ee5{>eQb zq1AsG=k(`c{VzZBzWXyEEb0G!(r>Dg-@yAcyj<27Xgq2MRh@oe^D^=MS3c|6y3nm= zjn=6kP=A%{(9MR<&a%|I`}B-$FJAAOeg7SWl2cLl1GbX`b%VdF?wb?fnI34a>?Fyq ztr@-A5-8csSv36jX~l2VFR&~}*f7as+;9Daqd@Kb=z~o4dd}xX+W1$zNR2zxh@#0c zgY{XK6d8d-X#?iB>M%0t-um8OxwGE z4-7o{74>Y*YmeqC^VEM^+NgXmm$a4o?gIr z$aEI?Q9m&8ahcA%X%8;NeVip!G#uSp?zn4QW>K;0SUJX#q%kCSeuHDeA?7g@_H>TW zBPH5kT#qO)uDlJZDt)G@O_j_>7w!Uko7b&Ro-XvdAad5cVzKudKW05O)rwPkjM8#h8{H?C|4Jj>hhbY?fa`ju_5TPi?UzP6K>a>OJRIrb!H4s-zScSc>*1?1kumP}7;McT@m z4h+vEAng`r2RRZQV*_%3-`yyS(UzRP=X*I1O-zu+d%wD-Y=BH}>vj$cAPHob5Us_R zsWGAyIe}euT_Tr?NCgn=rjN6j^boO?bn!k0*w1}s6P-U3*@N!W0#}r3Vx8|3LDGd`P5vhhZE~(2Ii**cL?Op~Ch9v|(i#~@b(=cS->j(J(Ii|NA zH~XX7iyI-!Lf-Xu4qe2c#jbRjtNv2u{XyM*o&F6j<2*ri+-mhpZruAhg6oIe70d59 z0U0LanVU-xRgaR1HQG?AUl(PoVd=0AlI(b)vrcMX87l`*Um*244Np+{3|xXYtX$F< zZTn!p^hm<#sF-@>JCCq|zCrghqc!G@TcR~$9WYs7;G$|`M5w>5UW;BsEvdyyvoea~ zg?wN%z|{s zyRsSw%4)CTVS2CZq1G>4tl2fPj{8l=0v@m~>@EJ*#GT?mXcTA0tkwAK7wyymrfv@S z^%ByJT_Sb)Vat1^&vg>??+L7>mBEO#)nxzh0(iSz$wn&fCIB%dh;woEEopy?%_ogo zm=YIFowL`S`1bs_SO=G|8M*hBP^vCUnGnyK zXgBA1=?4B7UYSOfm$@nu2T#&Np3ch2+BZHZKBNZtilFXZmVqx1pg3`F$&wwF??-O7c-L2Pj*6GOK9* zKW}s!2bPYVT;o@FsI1=pzHEMNiML_lM3BpQYGMM}kf#KA4~OFFz1=LxPNU1;RWnQt z7xh)v@^JFUU9k0IA$LC-?8d#6JEKJmwa}0rucv_}%^`!2jM+1F1z~H;iltMr1^Ky( zXKtF>H#N-Nf&<@nlnr-kJ}lGquCSd+>tzDCQ<2dH#S*18DI!b?#u-gNZ_;x$oB4K! z`ilokJ%yjf~&tr0g$FLk_llTzbsEi8r49*v7{{Md7? zlIp%(&8HzrYt4>qYw6AEFciybns8|j?POtSNLC-l2>$abXC{Y7R?)W%g?#FIcb|4? z?G+x7@9iGHJ8}yz?p=dm_4P$52|YL0Na^Jbg_=4(VU^ht2767MJU#8eqfdu|1CIEs z5B5p&9oTr|`rEk+H<|ZRo>J7_l&tack&oPDSg3&lD39o+xmDP9o&D6bXZ+`cM4pz~ z`gh|GUwPeo^Fhxx#I7N^chk@XQI+w<^UlYty(rV75M_$mcFg*Wj)vrBKP#Z{1sWf*eea-)fuR;53`)X}}fHF*=Yn9FmWYQxTx5J1tG)m$2?0 zs&$iHPA~wA07LX=&g-mNdt%n=_N$DFW6#^J+#X|(0*TRvB6ddXCYxh-R78Sc`SvM` z3yV{Dueu=16&VLKZ2z0EfFPIN8|7d-e1^AO45ArFG(h#Vhjo>g)wew~j8xamCNmLs zSL9|0eH4LwfsxQwFO5bwc3Is*ZrhR zG8c%z1=jHO1fO1)N76`%bN=^kCgezXv&g>4fU!khZiIQAYe@sRSGb|(&4{XX^v9x) zPwNJ5msr_s2}s}0Z?v0pa6qGhhl157Wv~O2pdJjVD*>~|>(zb(V;?vI@s~ybrN0G`OBcz(&*l?SD-d@@_X!Cg2D+3|eAMkJzN)?a)co5IY%1p;Tu?wCrzd%vNm{*J$hmdjVF`Y76dYNG08MA# zp?{Vj^b*5-ldR|@x%D(;&mq;ca?%y zNU8lB;l(^J#Ak0V;uO8r77Wjgp}-zumqyxRZu*_s$$1H16*&CusD&25bFNidVQ~Tl zLjbdp63NB_FcA1wPiL?S2Uiy!K&FqOB+WYtIgK)XuB6EmO`o9N`gkHe^n8XR{ez4i zF*(u=x)}NMK5~;iiOE=OVlwisG6@xG-=oZrF$#~BY$r7i!+xCFcW^P1m|C*muLlLc z^T^kg&bezeWBUsD`5S0ojzw^N)%L2d>Z7s8YI6O4cy3UGhX__hUr-E<+Ko3?v^fp zaAZ@(kSHc|o}5isXI9xS)cF%u(F=JIfF2G2;iki|-E7;h+l!!@nj$bxTV*I=YpKApUS{hzg)|KGaR-nEv2MxG^EBvHu+q==g~28zRA{4{WN;#UEQ5A zNjXcB{ktfK-fH_%BVk{{blD31_22|Pp?QpiDq|Roti?@vUhMo0e6d-B*%6_=J!98G zWzuLkL_pMCqoP}%qgtE^s8s&EHXRT(to7c?FpyO`X};io<POX2Xi2n+>4pdY9qm5 zBFwqnK);8&FYovs9gRIskVGYnmWmbu>l_%L13Q29r-N!5i@-?j<_eV}L(A^l-^7mz zy0?Xxayg=YM8hp@c9lay){M+;m^D_tc#Ml-t`ES+)-Qu}l-2wP>i zX9O~EkRIYo8N-QqQxls^si$X33u#r9sRsY`Rj-A@z{dHT<;R(scCo*$jbXe!b;qq^ zc`N}ZnQzCpcnP!=l;+YeAL~gy2zG-nZ0}=X$tH#m7I)z(oVCH3VTTv%EIc31k6rP2 zx7X&R%*xp7aI(7=P8-`8TMpQHqfE{`eAXx$Tms23g9(dhljNjQ!xcYek5X@%pJogKi>N%NRbA;SiDtRhyzV{c@6pyjHR6qdsAP8ANej+zTAPH` z8cguu!cK`UC|{xXKDC<^QeB@!henq0{64TO?=we5WrdwX{|H7`y68OXX^_*{mLn&~ zx;8o}oDAI4GYW3f=&KtBD5~0{)coC{xUsc5vq8zNKtE9Xj+5#UdZybhuoiOFr$w*r zx~z@zgZXGdp)YLn;XWk(=AH)M1}Vw=Dk6#bMUpe7+@riTv@O61f>}~GJ3?N?q63sB z2|y;*{$OWc#A$RCFkaI=5tG=rXhgg)mvTdpX{?)J;XGug| zL=`Ml^>0Q`UsDq?`RZF{-Su2U+=5&?;aDuD{bxS`l5<)`wvka^yN_s;=6UgzzLwUl zFwQDoYDiua_v~C_$vIv)OJBlQuEOQ_`cEYmr@=*5T87&z zIzMe6gTW_arl-Mi5B}^)TO959zw4xYfR;f2{(`~%Y?@Zyl1~FmTfq(jEJed&(+;$H z2fOCN=*MDV)BcPsvMz#l)@}KP&2f5IM}>5nfjlF(l>P1%Wm>U1>C^cT{SoUH^)|IS zb#}>MHg6vGgo_c6-$|*5g+~U0i;4-Qz3|x@-dKgOb~)%&#+HH3WrhP*(OR0ziUBw< z4=Kk?4gp5;?BQ0OwHja8fKKKBzc_bH93fyy=+B9r-q%(-O`y#Rb3h|j-lPUzk4h3x zTH84_L@4savL0qX-(DGP^tqab_O(Vx3leW6z!(5QF>UV;U8O!M_|M-Z#{bmQP~e?0 z&yxzJys7C9twa+Z@Z4HtQtSlI%mVaLs+05pVnCfM&o?6uE)!BND|yF8<+UwDV9U7L zZgvd-ITjX%H=+3%T?8JRhba!QsB#GT3ha98*s%gMVqVVC{y;ghDoTDmfUjn@Ice7j z8Smw%EM-@nOW!2fM7y{o-k>)@^ zV3Zoj*+zJcvPQ&WZvTx?%yjaOi+dbWiTAt%GS}+;t#`4v5*fslA1yT`>5f=P2$fr$ z6a_nP(sGW?v7-4Oez zbjNNk!To*n8mGa(^>6nM(Wx5W4>Z$^vEfo{5}hf_TiMKxdYhDx@kez9>nS7A* zd6s7W0-rZ#4ET6j*9(|dW#ow_&d?U1-uwO#{QM%=hMC97p$f&aB5t1U5me;qSaa*@ zc&b0Y_`~X9>iec)`uYue2us7&cWwfb-|0K`q%uIt7mZFXIQS##)Bd<0B3vqKu7nbj z_gG%Nxm1jFA4LInvqPcnrqZmZAKxu;3x@)igDDHL7UEzRH_Z%fhL)EBo%> zxDy%tQ(Y%EaW^~gy(Y4zZ&Tf}3#|jW;PCFvm^-b=;-yiC!1DUd8T#T<+~_Y6L7(_X zzp%Y@R2)QHLrtaC>N1#dCNb>Y{W3wpJ0XM9p9|@}1x-x`wlgD1`7eM$T7)78VPyHc zHLi_k;w;U^*cBZncjt z`ryd9UD9G{Pr_QG=(0-N$l`38rRcz7IUu|aEEuNp?T&2ih8Mylks~%NR9iu17tLcwbYbGW=v?pB4 zN>&+L+PthN$MadQ0b?qX)Ai5Nt%470Qh9bPQFhWWxanT0r-{D9eYn1(Kw#l{C6 za*R9hl(|N7t!8@0G+UpR9={G(6=SK*^{4<+OsGe5KyIqBP@#VM#zad%`m`72?9bKf z&txH z)&%2Jx+LH?UvWQo91r`div+&W`Vv zyBE2iHOUiCnMFTcfL~2yWBVqXdZ}^$#n%l~?|4dK%N>}wETu5i)kx&nurxh#a_sbi z;vQM+Y8lTOP8#yQVg||5VW>yF$X98T+>W;SI;k^OPNM^2qrzmV7tA|Gj4qv-n!j9{ zPe#0zEvd>eF3CuD5fpBn%k7`XfEc`e7^2h>hne|{hbgJjVK0Y=nG0NAzMc+jI#*}EEiD^EAi?+2LRI{fKEnBk*bJh^4kQ0+N|e`z@HuB@g`B0#!VAF(fn6)ge2e(;hfkXQ!d^e31zfJQ9yWNu zgcHh{AJFs6IY_`jr5VX!d6gx0U=bHqN$`A%=|E&2{|GRMWZ4_Uio&3}Bj+wi$b>Wp z3|kCn;0PKWwcZP<22V5i_}(F-5Cb(P$vvo_(tum!3Rk}tPt7AB`2#^Z?UVH-88;r% z+ko2lhUt3W${3aihhf)f^UkE8JuDWxmsJPT^qJ&w+TF0VoR+Ck#+TV>B#j<1m&ZJw zoJmLvG3wUlof>XX>KBaMdn-ch#5IDRHPfFaiKEc*OqLtqeghW|#)`zn#e=_iHWt=i z&8Jy+HX9b%DL2vd$#Za!cW1V2#GBsqo;-aV={%tB))zJVjHO986Q3GFSWLGcHHfO! zXGG(O!U5~Ny(m5>Pim}6u(Ya?8C(_jL@%lVG@_yAr{{_fcHnR6w-bG`Gz%E%@S;D7 z-`3?e=`w-=1J?8-4DnZ?LZk!S5HW8pX~@UeeddgIK0X9gI9VHqRAl5`vw1yI|2$D8k^xc za>YPwEQuurTY!hZ>#_nF?+lCeth8oA4Ytbn_N7CnO2ZcNFx!wktgK|+$Hl>UcqE`(;U0CDvFWRr)%~`Bl6#>{ac^Jz!VCN9=k> z=@5=((<*nujrJ4&wS4KIR+W3N+WD${Y+wc;DAPnb)owqG2fkv7w-4MDiV!a<2wuAD zbgxT!nvZlZVw7?sD8?naWC0Kx5^=VpQT0OrK~fcoupkNHVBh)ebc1Q=I^T@37c0Fp zS&~kG=_e08s%qlF*f)vrQ{-nXTb2!)i|h`U)67-4KRxP;g%#I??51dTOeJN-DC)PH z7cZ3os8*g*cio+a8XUTJSMGe|`xsoB*RjNL=Q%Z~Ibx!pQ4Ba+KWFCD6OvqLI6+tGcpKCso%1T*F2Y=*02JpWr$SYl@@$oB~1lsM^~1E z%-^9yB-_G?p?65_BTF+oG_n5OYGa;)ugy!NzOeQ4{4!{EN9o~{qju_*BFhztF#aUG zsLJ>4d|fctR$3B&*A!_niq4-?=YGHexPZi>@Z||aSQy~jty^*{(!`EG+yj>(0GRG?8ADku~0{E8rH$11WWE96kmFtp(dA23$- ztc0L{NwHO+(ItmT^?S`$jH%A60)UR804=Y_oBu0%tDl8<3OFiv>SupgS6M6db^6*0 ziO`3N(EZJvYUk-V|Ni8Y)>=F0`@p!TuSUpN;dWx&L)TJNFt=)%F+bLp>bftYDWTG^ zR}#t!Ak|ah_fbukd9X1Jw@^p&~w1(S{B>XV)5fQQEcx>@V9fQgP9oDreBPc|36YmKlb5R*5if+M*tX^gZ zEX0^E;LOdm*Ox@Es9gpdlq6h|l2XsRqNB}GDw3>P-Ze&I{h(+Y@XtI$(m);Od9mSq zcD!B~KQ8@hl4gFo&SSLxHn|GN6R?vvFRyYg=E`s~JDf=5qnM!S%A9Y7bv10~7zA)8 z#=;8E#UACe9L{M3jH_SMR_LwuZ2KI1xU*9ff}e&nG-7l%I>QAn@6V`xMf}+Kc*gwo zqfR5!IDCy$!M6&f!Z1&38OxxOQ1KNW&67$O$&&NYflB#yJ3>FcrfCTVOTFsEuBnpC zpk2(<@8KyjiBvNN#hMfib44Y-589t@$o00@YGB#dct;Lud$6Q#FNJuV3k;g#h z$oHNC#EUK0&aD*GmK5f(ND<|RklVIR>>~yE2?q)3bdVOqnM?_79Pl=)G#&A5dizRHu2 zF9T?GXZkO!CTEV}b1l*ATV7^*_RCAFjnR+Q*z@ryROax2olt|Cr%ZYY_AoOKJ!Pmt z_jBcNbmE(;`|c(53)^-c3s^EIbBQ?$D!bfcsPL^Dfe}c5UuG^e!-gjo^FZwh$HuoG5_t>u1 z8~*a=u>U}%)RQG=)x?ss5}z>ti=5S8#{6^ie?sd?yxO02VxofTUwu%8_TRU(;+xlR zAq9eVR=9LW4u1KHr10kNnDwhz2va>?N=YbX{6S*Tl%My%5!L`^ zrV8ZT*KPOsco)6+O7q@s;{U;V}@7j*M*7|?@&MqL+9Gk!&pGct16IhRD_l+N=EaW#NBt3E#9h4}D=P$*Go~()F?3 z>m6%8?+ST-n6j_tyHjziLg#+8!3lqDGisd^3ILs)-Hl-{#m~>CH_~Jf5g6H znq}V+!?N!%C&vA0-=Y7W+GEbd6Uw^bF5`ZCdIVR`tpf-URiv z3XqdEv>0?2MVJp%6=r_D0w6VJ6nGt)B2|mnCH5ENW`V2Ev6UZWMTD1h=78qWaewS^We z-E4T7__S#F-EAJZLOBJ%ao;6AodS}9b-p^m(V??crgHM9r@uj0K*us;BkAU;a~1A^ zy*6B$04@_Hrog@kVlEw>n7AA6W})ho=`X~1(*cO9x0I_~X*!Xp8GbNveY#(92OB1A zEK@lLs53v;u!ilf|ws%yD@Ys-u&erNe*6mZ)%|>YN@q#4@)Cs>8&z6^}zN zb%d^5PvdU^0q%i}q(N>o8Cn$Z zEZOo?(YePVk2gQ=-+l68qm>)*EF1qP7Xu3JRe5rjWX``$f&>t?lHg$D_riO zGSwYD3HOw2*N%0ep4JLHoue&Yd7v7jg?{xeKM(JL%3(yW8%n?r33?*H%EWLRskML`W zHSy;8%5LpfLA`{nYr%DNchJJGH6!v%KRJow_ng*FQ0@L!WzaV-pP zxYOaSTT@ne_cD)MNP`1;zo%-GG6Eh?Ac9`jUucu%kx^Yr@t^`#Zc>A#*RPKbA@y^N z`DFrp{4*48`-J$6>Vs=pmOq5$6|umcEwF*f5QFFd;<_)a;fk(+sg=mPZj&v{(RzHy zR_CncGY2{E?B?AZ-eTAV$n~nK&YpJ@&6lbm`v<0#4u!)u&%-j7qkgw!WIXqf>7FM9 z_C!b4rHaG)yBdvho+*jWdIpx&yp#4O2hnf+`iNx__6ADM7-4OFF?Wx3r=( z(r@OWKFM2GP1p`+A|pY)*DekltG&;g{?u7k&PC!8MVhFen12kS<-TDE-75h42)*>- zdcqro%iXgwxN$X@SL-Zkvz!0JVS0EFE?TZmjxO=2EkXdvvcu#y#oNO}2g}QS%5IRP zh4qu0)tZfk4$4oXF+F)D0TlmuhnarekXH)NBRM8w=Y2{u;m+%feew4`pK6XtI-r$D71XxK zAQNeAg?6{_o6L^OFCP0z$7QG=3OdHH1auUez2dIg=afgLYKXfK!hK7gWoOvi$_C5o zm6(O-8%1w>sx&r)3af1v|NKTFG{$wqvHl1&Yi8T|U57M#|BW1TU5{R{ec117A>>Fp z%LYK@$xnYQLH|XAYa}hsf#Jfim+!GETQ`a^2)@+}KPSbd;BW%UzaNw8rN<$>c&Z45~PAwvO#E~yH!SVU5rBq<#LpFAUpS}+(*-9$Ybjh83 z>X=*CPNt2C7QG(@WZW&(@8++DFSR_|KWqpWzwCc{5AIgmSTahK<(f&pbnKtrSjj{} zg$CTWl03vywjdu^X9owx88s?h??}`IwQ6pfr`ynD4*BDgOJL z@PG7K>Hc5eqi^Q@l`fbT<>m6pdOG~tFiazIFS*G3F=LSfD8~0@ml59u~(BhBm)C+6?>s?-}mD?87pe{c9DivHz0!^!b`N&03Z~bf948 zYtKXcIHPhjF?&45xrlaVIKg%e@csAy<*&7b~_&3eBG1yJE3cIGxIYs?C8egww$su4^Nj|ME?{Ed;x17vQxQY#p|2f z?>nSpyKA67VIe?WxnJ}1q`r52T1s@Ajhvchhg*1F@DfJCkDnn@h0%HsSGT*x8RCYZS6?rtg5rV+RpGsQg*_jxl zVAAR_yyl~RXh%yj?37nh&QZwx%Jzw8ho6eg>a+QC=O{@9Vg?U43_Cf)>ETlQ;>$1I zbcO~$RHSLaI|T-1;JdXEblKJj9PiL@)g)chNNRP|*(kKq#xlQ-E4D6waozI^TgBs- zG`Hk=8Z^t&8zy0YSk^7!CJr4Y|E^IbQnm=^WFp=fwNyoEQuZ~4+E=d>j(T(L@#noT z9?s@(4YV*(%#6{_Tj~@s#;&M@oVu4yB7F2*uo53h1}*9|;cH36L;o zK8b_R&(RqRA2#Idngu;O`CmFI;sCPHRo~S5ZaY3JmJ2ACZ{Bu89CuH{Vd{q&>F2nG zUuO3kizhsEj;CF$n39D(D&;ZS%bhxy-hs0xScNn0rLiRHSTLVN`Oz1)@6`~pQnl_u zBX)kWg$sL_;JNZ*Fcq4<3gyAChYO2XScNje%`X~Duew#|P@+RquH1JKhlS7I*_Dg1 zO)=NL?!D79`0b`vON>ba34brFvs+^L_^|m_QYkk~qUQY3Q$OM~HVlN08den@47n1V zgW(Vqv8R5%Wb)lykO%^e#!#dp`d-Z_y)f;(X4Bww&f|=qdT!yOSXqUK<_Ot^k0k0= zYNO?07AD7>X9&*7Rem*5Fevjr5ltY;7aXqjfc3A&4T)*F!5+|CpnMrPt1hVi7RMUl zgO1w6A#d=pSReL%rfI8V#JtDTH1XFXc6+=u|0?I1W$W;#76_+Xd%J-H#tST+=h;I% z(P0b_Rb2C4ug=)Y;n4?IpGwzY4GT4w>k(Zuy3!Hh*_H1BREPV<&65Mh4!3rx`7KkA zbnk?+q+BW}4NuFSndH#?RMJQjOuqTxXr67E#L;D&uDR)02FqA}{=O+WT&wz6K*;p7 z2AopURt zx9Y*Pv@;b5JTZZYBlx^rEG(pjlf`jU2V}l6mZc*Iw5+ecmHXmt2g$i+1h^K_cW}`O zI=AQh3Rf0Ib%RBMcyFwkb&v&n#^s^O4g11ndyMa?>;>6x-A33A^lR3dgU2TeJGXbU zwklBDoT+V4;G}c??YKKjBl&R7E_=l~P@w~HH*5SnJ0rmMpZ4J)^rz^2=hl|eY z|Kb-PoA&mzaYw9VeH4le0g2=6xc&W|pXhA7h}*~ebk;TWSD8c{;Y%oBgW5GP9#v6H z=s+))V^DCSfihTz33EeWVP?n`z1hvZR#o##RjEm&qGr^&5=3a(GjDGvt>q_R3rDD{ zMuUn5B6;luWWf>URNCY=B7=LN#M0ZxVn~V(Ghp;0bifvggpk)lyw+<=$b*b#iJkrZ zO5lgntckTEnxy4OfRkx*U`D=Zjs#4yEZeHX+I=kIBWxK0U0X|rLu{WT+FS-x&I~g) z<5!-x#w^|K@DP=0yW1La7M~+Sm#Ve%o&)*%SD<~tQYiaUK3v22q>og3+-08RhvD&# z;2-LxGqNXqDk_R{>PlhWg=;NeOa3J7uTgZvewtkxOc#tbc6>cjwv8*U8%8OS`On+~ zOLN>O9ML%1yhd$NRUi!?XH`$Z(eTVs^rDQ%sie02Th(cS&_Fd3$p&RdZ_N)!ske(A ziWsdc0=yKa`{HdZ3}O^GQiI@_kCgi3#u#cGfS0Wf3{ZlI?{ntlek zB0oaOU*Q^bii|KJA0AF{kCvdQ= z+F+79pPn@UoadczTFX9)86QVJeLkI!nbjJX&;7zC_hLqQ0me)lb@}RKoD^-Tq+UO; z*SiqcTYL!BD5Z$(@w|!MTXVUQ`uqNav+swR-`zd2__0QQORLiK^x@i17cPl?{Qt7P z|2GtF_=otQj>9h69`uMWGDY&`Pd@WAI_m>OhiQoPG6a8}&a^D;l zMtB!zl$Sp-xB;-~7MX;C`I0Cs%#5&b#9&Xtr+XnNlLn7a9mlI6{p^blB3xD^H6N@% zSi`Bl%7qR4l`XsP27md&=Fn8V4h?U`v>;15%3oO7OwV3QM>W8rhJpryhhVlp&WFr~ z^ZN#;MD8lLR3Pbq4j1-j_H^R1e7-ghoTddX?a*ASlZc_K9%l28F;(8V-qVKPHe+ zkEnO3C_a!tPIkpmh}oSD3zm)mElUef@jf=@s3`phld_&RlWJn@j^czECMq zZ2n5^(pYCn$y!Ug$D>spT)iP@eJS6zLr-4jR3~op6MRu+!+VWLd!EnPv9BICJ=o`+ zDB`C&uI=_{H-<)LkGTTSGtxe=2SRj4gYWS*d%+=f6P&r&2LExDFu?wuZ1eUO4n%d1 zSmk;0IGxu)skF{+^{Gg?^&VEZiI1q$HM-(7)MSE&0=o7G_jReHm6T-mu#8t*7X6eRN#i^4nDwQ|nNo*9QAd@uJD+0+jWCsVwMnyamaYCRuj{T8N3-0c(-}7}tfpMmw1f;(gr{y|Bx zqTRiq9y~jFn zzp~kO1)FDVA^T9)&xtd?5xolu!j?Ls3E&|ccc)rQCU}5g!7M~f1}7&gS74xh$XDey zL1k1$|5PLSEh|qAdgwMOY(*iI@tj&CXadW%mI}tVUX_1dKPwQJK&&pb8x(HPaiwiP zCkStr4r&kG{zhdB3Yz6lY zXkzkSSQoYtJ5~}Iwjgrs;?|^R+frXc!UIN%q00?}r0u~AskQZs3Eb+WHjNxU2EWgb z7)wRVqC2y#%K5x`AVQ;ym(%jEx&6cY9sP|%!!9395`8`t=})Cci_t@-)0r4bn7@nQ zr7?cpx}`NCuIB6s6p48<**D#hoIK7#;spf|*W;n(A7u5OtQE&DUK$nO zL;>bK({u&ZqpfWWgKQpGShS#-WwR>p$9RAE^ZaX};^^pNuqj~|p z*$ht1<2YG~=UwndsLK_GS5d2rWW-ffY8hXg`=~=9j_zBTBHr+(W-k;BlFk$LNiRVe z66VaeAFddpJSk#rdUubkuIyvcBCebTm2gBfcp$&{Mx94a z8=`IJ7AehGx$-7OFS=uw&O>taCR6w*(htAyzoi5s%tzV70JKHn)g~`&p;84~@;DhE zDto*W6iuWD+)Ap7SGTf#*1E%C{+E|^nK4YVb%o{V13WjlpTq%2_}Vs`H~4v>5%kGNpH`;T(*|L_cwTGMrBN(Er&q2 zO8mJI$q{6#U3KKtJC>2rgxZ#1o-2WA@xjSDYay%fjMH1~qrp?h32v(QfPGVAhM!E- zgxbM93!Zzf3@!Q5yf_;L&I6ShXwcyOfqmz zYKlr_KEZyJfVwA3^L!x2cVUVRuNJZ zJ`?D%jGV5J#&2CUoCT5Ly|GTIjEYbz_v-)w9w|x5vgp`^Upbf)99#|*selQJ{O>2h zq4)OXOYZ>!Hd-!7-<|5;UXUCq8n`%k?dIapuEl)?jS(IyPQ}brxJs6nOKbfaTy>s_ zwI||QO4j<5(KuvTS$1=Iar#Ibe|d(DTtApY&4z_K=L~{wdA^;p3+x5&shP-1hoBm| zmT?7GF8xBj7ygym;@Hnyl`a=ql41h$6I?uRe|tihX|3k-M-1wrhiRJ1<-1j5$AtP! z_Xjy|7OeeTKa262`_YRPRuwNlTbJ*~zMLDyJj{!^W(=HiX{T_0VG9Y$#vm%8V@=C7 z+p~Sis)y;Tm|W+Uq}9(x;I|tWd3EJ8-(n#sZ@+JAF5B4429X7oo&@=g^o%lid#KLV zmGOOzJQg;rxDq|zuj^TCKYAmBKiOUoXedu%=MftlxI z}yJ&`~)t5bHUtDG1@*s{-AQS@IBC6O( zX4qBjIoLiAmkEK=lGe+Y4o%q0Ba~@51@=GMgWI_XQSS)P_^|E3Bw~<8zt1+y;oiEG zGl2j1k+Yi$Ck1&gCe4MqS4qk$ffj>YAg)lYlJvx-d1srBT>}6OGm80u)EJk$v?s#W zwb)gIW!S{NZbo{R!G3jIK0Y^{TVXBn{0y`Vo}lc7mdN|(Jl;q23<9Y&H2ADZsLv=| zqtSm+(Q*0$?27o7+?^h3g%q`}w(_RNopwpF!Hmz4@s}q~>sO5TzTa#=HW9H$vYgE62&|oy(3oiBN!5T&N7BF)N+jmp zvci5VYj3P<3R_xMmbfU!^_^Ig@?2);cckarTZQaf(j$^fd;XucA)J7~-T`hN-ZK}S;goH1qjvzH>k)mIkfWI~V+|S9sEr9H%dNsNdMm7)JjYjmk~#7EaF^BJ~B^;0Xq- zW5qzvYU28GykF+f(g-3b^>!A*FU~^<{Hl9Ma)1xoSB3zzj1JVZ1zxxP%d+}^++>w9 zrvD@asdl}i1^ijc;CGLr-~YmPsrIBkHY>1qumX5uKE-x^wDa$o=Dgh2*2-+3&Vl=9 zx}hJ(U(t=(D{J)f(|4e#0nC8f6q{YnVQTAtvW2O2gdHUIR8*A^#H_D`?P%Bz;U!H*L1J#68G2X+n+;uw92p#`t1wR;uCM*tcC{nr6h z4oIU(;H2VGm_aGU+~B!~$_-9O$>n9wC^Rx8J*eyK$tnSC6Vm{J;f#oKsGV3`K}0mF zwv(MSa?DTcWlS=n13P)0+{5ezTY6oygceo??a&oJxmFh*y5B;AzP8E-UVPWNKW7Q(~jl`?z1#g0TXK6Cs~YIx%Z z%!nh;?8cqAkkX};^9S(oR{aM}1Cv1sFCJ|03R_i4``3|gN7ExrFDn?PJ~`75o_9G& zT%lO(w*MB@)9^`HY-;ff+vr8zwXxWTp1xF{o+4NJgZ9m=%~L^Qz*PE;y5#KlqXETn zqM$-8{AiZ8-sA!@zKT*iZD64$<<~D^)ZId#fXby^uw6T^)7Bx$RKMBn|ETvV1|s1| z?3T_6mxo#;cASZ}u_&LJDdg5^{LZ-MDK-Ij^&kDCq>Ji5+i$!59E(wB<7fHDe%z&5qAM{Y3)?J@T+*9?rfbw_ z`U6Fu#>}r@JFJKEC97F#4TS`ahFD0`=B>;8eMlht(dpQMQruWf_?S*8@sVw{w$QVi zYgFfyXApLPey|8UnHr!pwQ(-o07%E%Pc@g$F}Z78B7#QkQ}7}vv-el&A-067J6VD%JX%X z7uNfZf3OVu$o&N@5};I)ZXsBE#%>Q$N2o(QrgL+T9I(FNZ5kcQ}y&$vhaJW!c-Y=tUcoq{)0oSsVzLTQ%r5e$VJ zVqU_4=G@&xv6U_oSn5;w3qeI({p_R3l>#oY+UDeP&-;gYOwaBvn7*@39USjOL+8m` z1cSq#6z0UBeDXAmY8cc)kod5j#neo7gFp=LWAv6IIcuqIyS~(U>Nsk5ra5O87Cmi0 zcs+CGsGPV-&jGgk#q{z~B4jFFRiKWjrhK?M?Eo{IIwskV72jRW5Z#9~kVz9-4@tc)g7N$&Td`ZD5 z5f^>Vmf9D^5shw;LZuXFqeJa^I%>ZvgQ(s6ZS-TE-9}i)0N!3dK8qBjYot+`VGynb zvanBXgsm7~oc(O(=QmVjh9GNh3sk^0hP)E|Cb30t__I0tX&;Y(;i$=arlPZl!tYWFDAf zjHn_f;vUWCO10PZQBPdU5ovwDvK_Ug#Tde4aWshIEJlrB*W;7)x;s!p9 z8HrCR>wzb@XKITuULdbKn2sQ0wU09U$kbgUn9}?Dm&XFP?c?V>vk}fkJ0YQ2zy0Pc zyxDZENR+hrqqQPzKWj(N#`Ky=RX5LrNR?ntt*y9`JlWab$ZP<#5IA%IH$H0)bsR1q33sgh#0uHhy{QM1&|UJ_Hn zOeW7~hPdSo4mLoj49BK|sBFE55tW}@04v82-SquyFZ3kwuN1q3Kv#VBq@?F^%I3FA zv?{yGQh;?3p{n4DB}AzGxXKTuO-)zF4vjLVroXUBnZIRz8kD~@<+DCkfQM{Bm3LBg z){9g%UCfOow*bZtzitLi-Zy3_?~Yo7l}A)!Q%XX#2TshG@VirYI+B)S-O6%9$kta} zUr`(x24Yf*gbb7CEMRT&BB_du9gp~b*n97wCeyJ0*VR>bMRXBSX%?!4wgRDpg$@#g zG&(Dtgn$G>FDolZX8{A!HIx(xNH75cfmM2!lF)k%9i$8F$$Q>2XWn`Lc;|P{oIlQ) zInQ6oOlI;V^UQr;*L{7z-_OHI)DI!zoKgsc>@O!#9a0OPzHKSTWA9;6Jf!Z`Wc^;u zfTki!g8^#d1#43H)ZX=?eq$yiN3Xv~-Lra`rRR*ck=v&y&S0J3Kq$jwTC3d2HX9!c zu7DbrI|VlYMkbzp^@EyVEzr4ATHR}et)PYUoWN3vPg|bA;r-eb;JYf1jl#m}Iqu`5 zVn6lH^3m=x%XJB0<{!H};69i#ou7aLKI$4OxZ7jzrq$j-*qcyZg?Rt{Nw`PCo=`f% zBrSOpiz3xYS7I#Ob9&quX}}*|xnbs?j^THg_cNMxDb}xSi;K(C{NnK6w)D$(d}#(G z$=c4tU-RGE*;ga|bI&%slo25|^VJXwN*2Gc2rvP%Fwsd{9b(mrghanZ0%bvCE-RLh zeki%F=w`mB*^SA`86mf%RnwhWSN7+JkU>#v6)lQ~c2a^<{;bjTg*P|0{?|&=|NPYd zZ`}G{Gj9FVxl*LNoAok-Y0)dDsPnSgNGPSodQnYkk}wZh{f}ns$+ZvsZyUu+Vv;1c zgBgnPFt7Lf!pTr|%7ULkx2%h8CH}Q(Z%@3aO&?>tZkhFcV;;RD5+?krU)Fv)DdZY~ z&8o25U}a@Tnh)y0I8QGIS?KAj)3azQINGkxd74o$W4RAy;8#$^gEQpe-=D`J_0q@<9sO68^`~?wWjlGVrE<`uxz9)Zxwp(+uwRZpw&=;3x!oeGbuXem~{OY)>6fK zFjFfLKvgD>Ih2gF-!mQXb1YsaMcEIO-Ncl~lv-y)_tNaq(srOHgVkfG!IK@a-x|u) z_;N*^VuiBRDq03dNKB|6RQLSJ`M1j(g&c|d)f0oht+A4$L=ZUH85Ely5@nJvmKeH1 z#;2=jLD!uM5lzd?4pt4Hb*)GVU0WR!V1de9XE*6(A10u>cn}( z?d=QI;F-Md=&l`l!jxnS3eJ_b3UEnTlDCSl)#dp&mm9C8htPbbyYD5W}^(C6(84V7b zDktiIAi9Z`PEm4kX4gXEJ;A&~CV3I=D?%Nk5@{VDZUyqF@Qj9)94E)Vu=IICykVY{DV!x(o;LJS2Xv(GM866us zqZ?;7fpDyQDf?z(v|KNB{*QX0Y&C9WXQ3l zaI{3*DK_97W4c#PtXi+lPx3i(PyYE{zG9xV%`B!rsf^L>m(nik#I`)dGElywq#=<# zK)C{Xt_9&ZXCd>L~7TV$mD z_b`_^CmZ>!fTEfO*aN(34rw$S%Qf$`V%1eqm~1&d^qf*dk?|?XYH|v2_*MNxpsMkV zx)qz;S{iIlKIm+|h{FNt-(aGBF(Y>qmi%ltl3b;8V&-AEDnGP*;s^H^_lK+FQ;)u) z;J;O`lj9wPEeDCz)-J53bk_<>d4u5EtNFhhJKF^RWP+3%o9OhOs_9< z7yVEe+`jA*I~Isq(l?+V8VTNsNraW1-D32tTt1SNn1$&-`C@x{_7z~w(fuBTDZ`sCOW@$6zrxHOkemu zy?*~fBQ(6C543{l?7qsY=;gjZ;B0=yY&u|b7<$Lpo5xC9IYV&)hLF4N-9=P7t`f(+ z6)lf1F0N8r9Wd_BscXv)y0iE1ISeSFxMpv*PtxzgrD_9A0Y=9E4RXn7w1OIZrKiaM zhsYj&?%9N1${h0sYD*2`~Kj4NnNfIZ0j9Ug!c*8nF`CuomD08vBJ z8T}j9=;2eBdJdb-O&Lcyy1V7#U%bsd70GdVy5~)mGv0ce@BQw3av(Ub;gKEkh|K`9@rkr29Yge}KILVHFW9 z3apWU>-@Ve9cry0UMsfq%XNjE?2r23xW%EfdyCzmpUu({+^(;e`LxaQ#wP+BY*3%T zi~%(s=8#IIv+MfVb?p^Wu6qk0;B9zhR6_d19<;tWxjVNkDxwayP8*xkS=AaN> zJeS$Ky>#Tv`px-N?|aOd06LfxbJy|jxn!8Mg*zJopa&bj?+YHl3N06Uotn^AvJVsa zW|pi7d!43i^gdW2edcNsj&4x_PX`o>LdR?OcGNiT{jhxlPZB8(Obtuk@JFx&5(WCo zQ7TcYn0l*O);%55(yhRme7ZjsbXM^3p{l9h<6}ls`c-l_HQ(ZQulp1eW~B_hS2$a? zJQW}i$IdlA9Dz&pscWNZ_=uep6es*S*lYOht*kH31ZI5VEi-?rR&t5+WW1-RVOn`` zu)SY^B#hlx>9TIxF0!U$@y-KY*MK*EH)#E?T8r&tZqzQZy|gQOc}XGdos{{z!t7~! zhMD|4!syUedU+kfr(*JEJu*G%_Mn+`hATyx12L1Yj)^NqZWT2pg~cH3l5f<{2XN8U zBFf?>fU?f3Dj(-F+lA0AOQaGtTk@i=9mfgnO({HWMPgVs=ZkMvHoks}vO@n#TzMJW z8{9@-o~liSS7L2yt>c)B_NWtUlZ}=Gb=L+RJ$m&UCwKxvg`U+T(D?5;?ZAh-wCZgI z!s_P@nI#N}yZXEBzvos~-TG%X6HJP$5q`tE)lgYV{5K5W--F7;-i&k=pg@w>m=|G# zk@2~5QH>1~Ck7Qm*~;$>tbZ(hEX+n2@0+)OtMZD-Q(H5o50r#ce!N2Avld=!$l19i zEw-?VE*DKE*0$R13O_dKY?nULj?+3A3oo0X7iy*Y3mWzXY^=#i4NN5X=!7Vyp&L`X zvgf~drn=sWDjA<}%yl=m@@{Os*r+;P!D%NuFDM@-%$B?WYG{xe{W$H0gI;1Ibot7i zbqjU1vQ%HRUsA~J%=M7^*D-`Rrq?nlRH$4>wV-e9FwmOy`Z11A0 zhZPM!CB=}KXpw#5Umn9aynBHxXg`;Mn0l5|-M%EGR;CHFFyo%f3@+|#4M$AA!{7Oy zy08(drT_6fdCR7WaR8gH{=;ey44?>_szdu(%3_Ypei3RCTX`#3U#)vp7vvm_@nS+F zRj0bYYusWCy|Ch7sq3+{6&2+x)<=$sd{!(1tA-b&H0te?{e$s=SUIE!S$QUBGmMV6 z{e4L8`s25fO&#TB=0z@o!;%lH641!}fBHVTD(#(E`9Q^?JM9-|>zR6;mp?AAjOpnJ zrZC(GLlZnxQLKfDo~^VBK7!9^1bLM4aioApKEOZN3cMVGO|1{0O9`~Di^(VcC=ebb zcEuzi_N7FNhW!^AQUgUH#_->*u;Q)4Ms*8ry+T3TO<&Rn2Hw0YGB(a$kZX8$R!rq{ ztV%R~>vQ>5(#RtKpw?+~%QAg_1uvGZu08v*bA0)um;|42?*60LTZ~8-RkJM z$FEW#FBca~bjkVx$solAHs-I)UTm%UQ1{(*duuVxa{j>gOX0|O zJC?LH1aBOPl+~PL%N23_J{LT`Jg>Iymy`T`-4f4O$x)$MTIqlVS>^ZR%Cu9uL1wu$ zH&WS|7Ck=8*RG(C;2sdinq0iiGhr6Y4a~?B5}d6V>i72a!UvepK-quwO7;$X`{}oB zxX0iaE6EmhY|f6HbO4|47z#xSiIl)q)@QS`Ebsj{V3j*S`BGcMTJM zFZt=gg4u$D#CTv!0A1_nuTM^Fe6HJkypvlmcn#6(Rr1Z(^1Qp=pwCz*jK}cj1aRN5jMTpq8pWJO6&O4QTu4Q zq`sZ5anc{a;lQbp;^J9x(Ldb%3v4J@l!`?~0Z73jE*_V@63YA6Opb2?Wyt8Q3w{)8 zUjFQJwq?*{XlQrPvH3s9GEPW&eU@$I$U}Yyp!7_1R!aY_hbG04RS-n8qv`o(lvI%X z1R~Pfv;TO%;Up{QaW9N&VVirwp(jPAPg&1V!+FY!Bbw8=f^1#9PI%|%vlPHENN?aL z)ivs&TE}j*3Jd0%Nz?U4g6ubQ4Rbnj#*An`F!vlxs(oh9Z%57saTmm9GigIM$d9GP zRSJkQWA}T!cZbbyK)kvU1^&9aD{FEF&VB)vu!BAC2UoC?GVLt|4tf!8QFncUP;>l& zriG!w*rCoPeWmO;lW3=*-J0FK+lG7w$ze~s{mw?-z+Tqq_4gdDB3K_ElBUjs5p87ElAR#l8m-VR9`Fw zAW>pA>@nfthsn-D(hBy+G{f?z7ms7f=^=pJe z&ninYYe~Q?tVL;Oi`KdBBx3B5`th3=tE1JhCxwApbh4c|oyZ_U&Qv3sd=qXPt-Wu- zO@=AfTZm0)mb_pe-C^4=&#{GBXE14Sc+;5k1kcTQs__UxUG_^ZE4oCx2Iiuiuk(F! znw*WdPiNl)yP&`0#4JQLLU_QR)(-XBylc#^zo#CE*TL+(fYNpYP!@mUnmWkZ8C>!qBieyIGew*2219C8FhmGwn89vD6e->t1@ptlzZIUd+DBmP>@>zzd}0s>Bvb{ z(k2|_n-Gk)nuhRK>(2_ylmsWoc}5*6==3go>#>w`oySg6A$})qoHXGmPHGBWKNQ%9 z46j%Wi0501@%-9s6>oBtsbs-4gDywY;L0%h-qFO7ZvApZV7OLdk!;Ms21fALy@Be;Gbm_mc7yG{}Nj(k~ z=sQ^%`}dq$Q^4IX`Lk6H{tXr)Hg0@WG5=} z8zJ!-%i`qB@f2SPcC8Ja(H0j+cA~9{qhk+j%fLDXmM$O5M**eTeb>zZ%_fTA8OZs> zm(`Ltgivk))^Qq9USLc?d>@vXp+1?Tu-N(fL zW%q}zj!Yh#JALfc?j@td!48V<@DVNa?9dhsiXRnu#*l zlNPUfsJ-2R`0qb`MM}^-Sbx17aHS`Qxp0fBxBxYH^NMMxD#H)SVUv3&zr?Z@5F(@i zXK+*Uwc&sp^Z@1S?+iafUp4e8mz0`|rP-|TC@<-g@ESsST$yyyw3fI;^iOGZrrTta zt*-NxVdP3hsYM(VL+{qJSo{$ytD89Df(4(laBG96<7IWi9b82{s~^>#51AxFofA4; zogB;+3(+dy{7NX&*kJl#RN&b+Zq=EgwL#KM$4R;= ztPPHkC;W9M0^Vz+K7L_azFF@bYw@T3{r`N7egcIQW$K&6P2WMeD*kPYQmj7^(KZI) zzb@gPkzy7Q#q5UI;G_`YnYY%e1r-)68Ek4D*TjKia5TuG% z&w?%-0FcfrgAQ}`T&;QgBCvR-6D*&j=ya4baxrYy8i~onk?qudkpe=#pvrc>*>izp;Ud1O^8y5*Ti-a=8y<$@DR5_dh+V(kbbL%Ut=^;AImoXx z<6(^RsJ=2uil_7H3Tus3GoA`;i;1n}Gv~SOe7@y^+V22U^Eo_J(QwDqiSBqy z$klIGD=x}5Y1uhd{}DOyE{jAJ1*IB%msdS+v{Z z1Xrt^(`dUfP*< zgx~qq^NKT@Am4TQf!!9W=!=!_f^?Xv0vuv0#t`DFbc!uYYa9`nbXkOs^rA&bB0P6X zUsaW5eIX8oB=*L{C&pj$eZOi)o9g!~MYK%%Yb(o`?>)|Tt8qpbkFEWL_$fPUsz{*r z3-6l1N4#}=aP0_5&a{A7NcJ7=$+Tt*v^y@rOa#Y-I9ft!D6bb)&!qcr1eGsCheZAO z4warKgFJZ3t2J1BO zrj5E87U(8|GrJu(g*-V5G=YRgdnnXFpmnsQkiR}*`=_^TtzH{NDIZ%pE(>7t<~F}m zUT&J%w-Vdt2#K{|Diln#uEmM$-4{suMf!z8hun2lRG7|Yl~5M#+fd)=Qe78i5Dx2= zo)UCHdy-hbYET~YU{#vllw&Qs{A%!2(}v=$vemnEhqbk~+kLDO7fFpVA+9qJBssU@ zD^u41n1I+|8gK+?A1^tMoT$d zU5Ra-kSgbb41h~whsOV(6tMi~N+Bds^w;)LfAd2H<7%{h zMO7xOb8GkSIhgG(UF{!_IFOIDV#v_MHVMmGJTg<7;p07v*q#9Uc4mF6;nky+45qA; zllp+4Q}fgI4awGbzERz~ew2=?0)Zq-x+3x>?$WN#9$q8Jit$j^}D6JhF9t`^~@BS?Z#Uu;~2qaBghZ9$cOycOdSa zD%kFT%<7uX?)gnf zeFOdq9D`SFd;=+*$5qQ;RNih!uRP0T2*`Hi-0;r3VYQoc>ErU&QZVW|tv8F9g3<4XDSniU7*Imw)wb_BIC*k3=f+g5=Sz- z-%TAwAzI?9Xtl&&24y{OUcY!~rpLuY*I z7`LJz=x|=oNMKRKb3Q<^rfPj6US&^eud13)TEaZ#c=FzDHlW1K+wLJV(gWRLtMxNHa;x^EHO4pTAn^~S zy!T%T%cK&Cbn>>^Z9m@|Zfd3I2!2BRMsA)D{ynV7s=qPU>0L(Lt@eJ3T3Cv-7dKgn zaL+t3jr-1%>k^eji}l+XP|0gVkZHJ7ox+5)p!JQZB9PQxVUpY90Zm>=Y5U7wAG!@g zP`FpXq-*3sz;;1OT(aXK)|yDi$eRm{1j@|xw4;-j?p~oLN1bdp+t_Jt;eJ%qoRpjS zv=KLW|CAkBJub_CI%aJ<7^QM%*<<9h^hML>KmI(Fbr_{cY0AckqS$kY?2|RAYyI0b zPzK7WXAJb)Majfs-Kgvxl~n#alVm23{}d`MEQLqf&F}FGjt<3N1Mi=8OyUwoU04P5 zUoN>(aVkpsI z@>S2^(U_znyvljR-2CR>YvBWpAeO8bFw>ZP#md~Y=Anzzqxe9}z)*Ecb>SZ?!6D^H zi(5o}bPI<>?57L^308Z~l&BAA_?x_&_XuP_sJ+$TW6yW(&(2&xu}+Q!Y0kQK<0ako zYzp9k(6(D~s2Y1hoRV*Z1`^utK}yM0Uwn**9r5$%lF1Ef639zezl7e`V@I#jSm{}0 z98rx&x#1sD^TYAoh>*LnC+||)PnV!k0jk?vF20EGb;tEb7nC6dxI$xzn$YCndILa& zBsOfI6g=8}qZOP^2HTXt@@%nuzZSK=3nY)rCGjkDC26T|Q0cV9LdQedwQ>iCx*xec z9U5fq#7ThkoqcntGp~_B7Zc=X_y9T1+^)*3Ye1DrbnAR$h%>DUN_v0KlEy-wFONZz zLV0%%vnWlA40BCG5+OGns$LgykK&katr;Lhd&&vS*8O_`{A3cQ-?S}BFQJpltx2S^ z75q2VV(Mqi<{tgH`CXAdI1P!Riq*(T3;Fc+7_WQ2)bGDVwMaE7atU|lGWloo+D)dB z#ffs+M?ziu%_?iG+kqAzc%7&)r&7x3NxlBxduJg*Yn)J=pCg#Ifr=u_kZsp{-^i<-ybz!NMfR3 z&3@juo;Uu!>-OPRvAXWAn3VLfK>=1B3oiNMz@LIdTJL{Gt@v3UovUE)mLXU`{Ec`I{I{V? z$rY(Nkb?F8Md#dsc#1CodhkwbvJeUbdf2AH8sLjY-PI1f8n50S2l(BcQB z$Sd|iYdsgHh$I&SgNEFA4&2A?qo&&2mmZ6jFju%8C<(a z4L`ZpI@>S&vTG$u*sj%7VJz&T3>64f1{}VOmXMy3Nx}yM$q0@ylqABjhY~K@ZPrnI5Qj z7SQJ@g}x#UsY-A(j^tH~V*Pmof9*x<R2EIiiVNDXm%wQW) zaueb4l<)u_FC~eISCz|2`PN>8z?;xPODZX^I149fAajF~s?11sO5rO*;BdI&Wdfnd zbryfFXGi;YKR1cit&+W-UL^6eI(^2#D+_^uxb)fYrNgL}J+MF%4n_g9e=b~j@N@Z5 z)=X0J*?dO3h4+5_+W>>p38|x5A?@v4hu9J6Qd@{cBZ^Q3HZkC}fa*V4&Z?l^E?Cni zJ#acq=+khmXS=kXFU?X%Fny7-&}2PGF*)&e%4(GZpn${a;Q(O9Fl&%*P1ZHJYU@gs z=Zbb0>5J($fZbc8D-xhZiZIhWkrbzPXCH$Hs1f$@k&GDD>jQY?wFe5qpyoYEb71{I zL}{zEd$BWx;)1;&Sx~$@GL4h8t^rS2eA&L&D8btl{@CdEX3Bv*rb`wMN8V7ut96kw>F zU0qOZ!-QB3MkXx%V%MD+9!Nnu>b_po9L@ygw_7} zq{=XGW_mVi=wbN_gv14u*N)6M)3o@trZ*A`xUcJVit@#ICpSe^^l{rYRcG}(OlT_m zC8aYYKTpa+<%}%&gLuSW_l)qY`HCTMYuQvbU1THH+V`5A>RYBQXzukNaS|TK3hw9tYXen0h_PBiH^yb zv(#@X0KyLR8(hEkpmM7eYIvZ^FMb)4nD&N!=A6RYWNl@WFfe9jr^tvj;1HfigLyE`OcDB&O^JO8n<-=cf4V+>8gRKeR8%!tW z^mvHUz5%W7VO5-8;o;cd=2SBWxLx}vA3jtq>MsQpNEfAiswbtVU+xuCpk;hZZ8#;f&*uu6u%Ya&*?oTSOSpD`G} z8v~8@!}lzQOfKZbq$-l*YoTDbs*X4C^33KRa&uS4@?UkDTIEb_t4s7l|LJsEaVHif zx+JzG>*-oD#nHZAg9aO9G^zL>|KJ*;&9ZmtM81^QR62} zp>`GB^(^KJ$clH1_y;BY#$j{U8t{FKdD8@63-gtu0oX**bskF~)XH_OP5gFf)f0p4 za}8N{6(fOOl(M608dX#246p*Fq9!NhDI@a8)|FLja4rV{eYO#T!rpC zr%k+{gws=~@A}&QJ@?%yOerqWVWD>G&#*H=)vw(Yvax?8l680NnrltyOeH_R*Vnxu@>+O5obsEH}hYhCrmD9U>Mw~~jl-z&cL0%(%W zLLP$qY0gW&;|J8bP6|-j;nMbh)}a3v65rsb=F^qWF>V?)E0=WsUbs2LRjxCjr)Lft zw(0xYmfevY)nj%^2|CfqD%p=e$DM~Qom$4^w&X$wvTev^#RIKmdGlmnr2d8mcCM~w zTQTC{Ovuj^AJas4jO@zE58=hX`oM$jO46_)Kj^iQGQ*UZ?5~q7dBhnPf9w`-;d_6m zYbUuz+fLRlX~qnVPYNcvB<|>lIwQ1h{LI}srj%4wKiSnF!PJYW%!rRy{!ZJKlHd$dz2w*( zREF`Z#o7K7^L(M7Y}WVaCmnIa!$`@okKgKa%< z7`2>`5`W@8x;L+PW}$ZNVC4EAd#Exd5ut8dpsw%+W}9llUAMa^uVz!jo*Clq1IDA2 zM#PcB#rI4JTmY7VS^R_&MZ08l0=?R&uOJX{T)O(*1zYbS(Nl| zo?5IP%kI$PoJp8Zj;YaOoyNFOO7(PY1k?&KxLG1OI$yK*s&%1@dfImk_*H3&uex3E z7L9A}L)1#%4c+5_(wO*pXp+`h|2?i6qAX%;@BHlo#xEn}vgG!DX#~%YkXq5l)n!>r zO?Nq<^A#p{3zJ(Mc%CjDR`$9)#ZHDa2nUo$i4I{2xpp?5vGlTohQChvtKB!S6rpIz z#;}H7c4FwYv0!Idfm2i%i>eZk(t{3+Q;zNr5g*=Hmn#w0h~o0x{b+V*fq2jTSg{r&(B`lwgQotoURvYWjWR zNJdK&6ZNS)nlUlaPgmucC2Bv|H78y=FT3o!d{YN@-!Dbab4GabvA!<->qGKAjGae| zoj*f@M|4b|Hzlbmye~*3uPh)DeLTF|0yfPN&qH8 z1cU5Dg_wiK_2msm;%*E2?yey=V9zg{VTvG>c{4q$eO7my@u|kR?2T;Pl>P0))V9Ecng#!yH2%+H>-#Il zm^gq-%4V=J1;`f7Sc`j@Zn%)el^idTGkGE%s!1NWDsAt*-C-d=X>Y_@lO$nO76|l6&Olf3l z+%y)(HDFZ-78UNj7gZ&1IH+szDAb){%+#~$nVOJndqCB@IABZwc$qqiQGcIsxGL{I zfk=@7!HUo1FzVO7u^3D&t?0wZi@Lw8I2pIQfeSC&OXU@UEX*DbSm|RciO+UQ*-A$; zGsg|ve=Tl#6dX6aUX9{gmHek17SCB#{Py^OkdC$!2`?6@9NX>DyuGvD`Sj zd>3U*-Ea?YQS{7aw5{$Q0FK~a&*sf|o>sR<0>Z@=4QCvIB|xFL*b_JNf0pEDpim{z zXa~Zz%LlivAMqcwy!}7z!uOm2sl+OQgu`7|*ZAe*lFy32 z`eLDQUK)w?qeoHhF#Nb?`d(=IX2S1-i8q~``<`D@DPH%NMI!LkpHnhTeQ+I0aERT{ ze;*4R#7vCI7%4)nDLNwBDkx@GtLKo!1UY~+HL%5Yqr6&Vy*XZMMCmbaYHwkIyC9y+ znEZ+}DmcwJNld<|`%O+sQOlW`t$fiTW(4&a_z6;vvviP2Eh&iF1nI#=fPB{3INV-f zr@xO~gq!!i>!NaS0>pK;=*__NnC;NDXyejy!qfo9U9)hT`R}=)KlSULtzOuDY>KFi zky)=9q~QdNg9AD$Dx6c`UwuQZBi&!X7C zQPv%jNGNX;$3#tPtytGXW)UekPOI|q^tb4$ZE(V}wg;klC&6{W#>Dr-E`s%_=@Vbnv+yZg$$l~=G!N!%M&cT6NO3A@EVC`BGXb@4oHujkN12&Oa%mQb$6@biu z8F$*{FQYBCvX_nAy5IK52Crce7$sIMGIi#zso#R!9r4NK);3lgb_W(O)-vmVyf_b*fPO6Aru8$BO{^a9dYq=OmRmAft``XY8nF%5RFTT zLwP%KXrvVIUG-d#TWuUHi)vtR40vJb9XZ__Kk@M2bN{?D3x}WSidTL?-3&bA{i9-R z*3)nBRtF+5i?tTRY8nKU{{!h^8=PH;4B2Sdc_7FA*T3h^SB3Q7Yt!Mf&q;6b_^tOc zV3P?<4v`xvny|@Od|Umtnzct+bT|rFy5e*+ozLoyi2%%OAOCecXT$2uj98e;kxE{Q zjIdFDa8mNNb>(_IhxNS4NxS&>+}UN0M=CMmw44)&eR&2KEl{tzr;dZ+=y3)2^MH^w z^tjbM_;gA$n{($}^^9)oGbpDP{wzMNy>FTpOuc#h(Bf3G`zOay2QT}bq|2mCp3WioL-3uRC248jaP_E$cmH_!b5?pOZOhaiBi0$nEux2&O=2sfM)C z1VKdndL8@qpxhT0fsHs>{goArLqhVXam!QLs;OGyk+ zAc@FzltRZ)?cK)ImsROX(=32Fp5HAkzW5;HT6#^;cHX7pNAZ0t?Hrh#1yUGc`*_oQ z_ud3|UsDTfNjU9+O@kiY=2mX(_bHL??#}jxE!vd#^yXk_+2zjzz{t}Kq?fmQ7E{im z+=WlGk1p9U;>s?{NSSbNMnAe!G8(h6HUgi1dE)izDBg-Z2oZSXLo?9>wV8kRdzYl| znHyqQj?5jRe+PJxYRj$DlK$TIF0^hBbOkzYW-4dg^p=zAnVnU5 z7bI2{STC$OmHk@j+%+ZRC;#mP`~Q|G#z>>|J=1RB$@WQH`fbBb36twMC@)FXHPY3$ zyry3a^~3wwdQKUUO#_x3hlLJ!(k~k!>-))?r0$wo|K;Tc*JVPo)94Tt%BPl6iS7wlEHznxR4z z0!wc~{DZ_3mlsR>T6?8AgvFtbML=Lq>w`T?9>=PFdsHXAS2@cZI_WXiD-7JcOQ$4R zJ#d(2Bwaxn``yTQn;r+JtxyX(%MF zzHH>?dhFhBVhWZ11z3SSr#$8YbZr8RG0k|t;l8Z@$-PWE%Zvnzix<0nOqU!(VR(W4 zj~tzeGAk{l0=1)AZ~Gqmc(U>W^!$XJLoDt1eJv&4*dD54f@U=@7nxQ~;TD(HR@c_F zEB-#P|E0Q&Fzbk8Uy_CQbz|wPcR|<+Kkh^X9YR`KS~3s`w5|2s$VSzapSyXRzP+dP zPx!`QsO=Bo_Im_5_`#G)6A_e82Yxsvm)}tqb?Z-n4|H_ejUuwD8N#NfeND?j=3~90 zJi*5_J*akuZd9tkp@)Fhm+ZyrE7%p z;Ue)rpVEus8%3w4TMe~op%>!cz6I+U#0<0Vd&|7C@hET%5*W^kJ#B-Avu|-{yIEcm zHFz^~P#1~I+Lo!*LsWIb4&Q$Qh~^BBF6d5`U{++qHEw=#+HaFg>}wYmlHur^q-_&) zA&~8d7w-D!jhGVj*WcPgg#_cSeV#923{`>8{EX!9i z8!{#m>A|s5Ue_1@J$HZ96`-FjQnq?+Qm)AYIsN#jo(gUdb2Zu~YRdCn6`;*dPpf4D zsDyclO z)bZagI2xOSZoOyWL`bBE_gaaaNss?MCvf<C0U7?fC2JA6>Hyn*Tqs)4r+KKbP@D^=d| zYS+DBYU5&rHecFc$1%|(*hmDQ8X&jn=c_mKHOY?I1!Is%4bO57gyVcL<)gpmj44gU zYg(m_tri;M8d?SUMV%J)cTcuM7jeoP98JEmK5k=uV!C`dIYI8>)|KPms{k-^ZO?90tgozY|F%At==DJ1 zhpfIv)K*HG`6LpDQ3T*o(C11U!O}sj$2yPHtEK|91hO$3*?)pYd73!!K%;tS=C8~7 zZvN`+r<#TE-Pq?9di^zP{_Q=@Zq{;b3<4t?yLye)^SdgIF;SufnsNE(_c1$*fna4) zZfeKrKxV1$WIJ?chookqT)}adKv(swu1DqZ?Z{kyo6~q<@YhVez`M=ge`vN9g&XQDQ%5qVfn_XwYv-NxDgHss18gMZGf;4D@8ORZob z1&Y2}iavpAL1lcDuKkuH`dvsWNWbi4RnT0p0U)>OjA7vI2tPRxKk|3dv43lDeO#6fqeQnG1>`rd}y?v@MWG|)qSIb^9Z1>ofi??y= z=g-O=t$@Mj6-EQf+Hg_(1;3oSP2W3{kP#l}&FDj?jzH3Ypy|Hp#r~p>?fCBCZtkz^ zu2|xWl#Q0QR%Q1eHnjD{U|@i*-NB??^>$VBEo`?5dI%&;B&?-@h8@5LW?;jZl9O8< zM-rSEEgTj-zrG^LD!k_VEwtBj2T#SWXEso znHad1RGOQ47dsl0qcgufa!kBkaK^<)JmlghR_otu4v&5z!adt1#2PF?Ef~t>3kt4Vjo8lfHm|{$!*fVZ|@xD;CEJHuQXHn7BT5?Q9ScV&M7^WBd#UU~!{M+$99G*_MLy}Nd~fARf~ zWA>KcQtj(}o2b90IF%~@-&+TNXlE$3P7Rs;h1VLtdOR+3_qhD9>+QX@u@eom&4OcB zqkXg0{vYy_vAgGjUM&ClU#h3ejWuqTdRa6R)SN=aH)dm%kr~)0T8f`8QoQb)0``M& zLe;|J5Lt*(_mYPzB6)fK%9cg3%ZrAs66?OUxyJvI*cmnQtpo({jW^msy$X-Ssz6x)>uU0Bsy-;uKQ=rKpfq2$87 zjken*qr>k1^mO1}1^M3Da%+K>mtTcgCkShvZ zGvMUn)pw4~OGB0())a2l)JL(k)x@?&cAs3l{O!N|=Kt~K|9c}cA4+fVkgb}3#0xbT zZ19@PX}DIY7h@Cf`d!Jo#r9R3L;umYOw6m*wZ_SYesUSA<<5^b+3SxS^C1=%l_jN8 zyGYS$wk%_&CxB@HM7A z08^BgM@9$DxV0Kf*H~Zd2dTA03@E3HP(O59q!O#9hu^Kc%RjrFr0ezXIjbUpcUUze z$MD;~`dEg0Nnj&uJS2I7nYk<6B{w?*gX`vCSsVF%w~gZvGy}8tpHo#ZsS;IReFb`` zpeo5^LIqxfrG#W$qgT~&Hi?ig@0>r4+0KskUT(~+rPA>Mm({IWe42rqY7B#(he~6Y z>)hb#YAZy~!Lyk3I~R(418uFwzrXD zoAWm?X%&qw{y`EEP2uG2Lp3G=r`~G4?2h`k-I;n-T8ow%_EaS~kI2#byfe3%|4|AceA#(&>R)v+kHg z&_@4GE|;g)Li--AUp6B&?b>dH!FPqaW3Ftk?7j-Wy4wBS5LEr7T*OzSsxqLG`oN#& zZto6)=?AvhoDRzw`T*L9#u7m08vy^@ zleM4RoLBUDx6nQp*=r`=nXF_PZ{YXW&%|nFE>@mB!9!@*8~1<|7XakM{yP?gXvUDN zOW{(V7Khg_!4qt)?2t8I(*_`q_;}VF000pV0gZFrXzR3_M^@rW12$^aw5U7$ zdUqqo+(a#i=~n*M5onV>WM=ML;$~!u{OD)|7F8L`HHQkcaByD>ru%kP5Xk*3d$xqY zakGnm<|M9Y+l0^4!szs(KK^VLhhQPW#N&pLc8XxRxE7}G8zo#X#Dg$;_P;Uro>5Jw zZ``L-9Gy{g5CQ2URYDt3dT~@b1`MP?ATUxT5LyTw{Es6@OOPNST}pr?BuF3$32hYV z0#Xu$P^9dU+wAGv=r1p%QUHY2-WIET(1#!7P-k=Sm=c5Zn#r z_cfzfAbwk16g7ew4Ko|H)_nKVte3$^T`kTz04Bl_?_cA3kROP4LiL(c=JU-79X{+Yq>hT)weyG@MVd`ZG= z26v!y2`OI!wE#+D5t&4l>{hTVWsGANI=5CZ@b!CAar&HiY%KG`qW`ioNtQTo2PoOm znEAGoI%a$!#rry?SCi;RT*s`V`i4|-x2$Bj8gcXtzsQRXv|S zteMpdVboMk4aZW;WKU#|d_IkR^J;A0O$}FR^+ofHA8yt{?F|^pZa_Kd8d(5o51Ic> zf#4`rGGtHVi|gQ&&u4|WF24#d z?emOW19(IRv8GJ|L+~qh7u=*g59w@m; z5M>ouhR!s+;!G2X5?=4^=t24M!!vpgwsvAq?ZPF4ar!nzS4{tQAV*r~8$v7}oY}e< zJ9Qmw+b*@|PpA}^b#L{wB`YJkS1Ji!p214n`H9%LsV=|laeK~~`a#bb34iECO`tt% z76Che?{9e9NMwYuL^~_XVcW{E)^&c|-;cE<;r%T4iM&@|_M6;WIdYIDiO=}`3N4j% zkU`^*h;&FeGv?aVrZzw3%t%KlK=8DAyFXH;%d3m(y(@u`l}^< zD|7IQkBYuiB&s}j)wjIpNGI1@Qm?KuP(B=m!(>tz~HZd^zm3c+vg0&^ACd&q7WI z5O|fF9|#z^Y|AN7MUSm+JjnzSpZ;x>jDu>fG*uq!i&r)^@*;X;DLY_xb?cEP zb#qK!+dC1Nhx5gRu8c^j4aj&-QRV=5Y{VMJ^nG+1sUR;)MDcV=V-VMzVz#uyy<>8gfx+_@*pNo|C zgaz*&il|s=*V^q<+gJMpF-~r_se4|R*DY5n$JY<6#MlRG4f-SsBHIh`iYUBq+#mV& zXU$(!s$P!Ur+XyqF?ybH2o@UPzHr5!X$)Cso<|fELY0_Y-o2Ed{Nal3d2NrGvZiJm zgui9;<&WvOIWxNuFt)RKkxe+W__GcLvtl<4si}-{-sIy+WtpZKG1v1JGUm9_x8J>b z#8szIeTV9azoZvky&!4qwx7M}toL#V`%6NhB&ocdy6Pm(hpZR7n}pYh280Jxa&N~` z#)-{+^A`SPB7Mv1vUKaNJMTBf0w5F2C3qOgOC|L15q5Q zMrayJGm$ZgJ^yjQ_P4jj5yezuYYzHZw7c2T7;?-N`>85_yjcSBG3+aDE$j^OMcWU_W+#R}5907tDZ;DOKJEmkG*N9$FU)l^lactlH z_Z$y9{&Zz>_l6%^>QiLLla4&2rpW&3XZ9+v(5ovK`y1+t(v`ieITJseJiEQIt~6)u zu_m*vmNscI39E{|Up?xX-l{Qt;fK?d3tyA&q}F?#{O8Nl;6M2WGsWD3H~gYD`?Tv@ zxu;VsylB*QMqs4rk57$ux~-_(iobiK8;85`P9%@wWY6-DZtjt7^jKwnH;3n=1U(H% ze5fyN;r_utGe^-T^x1^}8>|&)3;e7}?) z*9yO+X7BNG*lyXYy>J?FSpa5W4b?G?TPmRV6?Rmoi?yVLc&Qc8*~KLeL?{SmxB~0} z+#U0HXZIYv(l6pCyl#zdc;%j#pxIjV_t40e{%L>c1GDx0{xbS!T3#8bC3^s5-+Dbn zY5O(aI_+BqyzE73KE&6XF;S4_-V;&Qzz`jdy3(AI*&`$@*uRMF#|mL=`KYA|kmweH z(r5_e7v!#$7%J*MEicFA^7k5=A9&A~5^*_7At9aBuFWvR9N|cij;Si@h3(emfJ28@ zvwHD`qapS8Uk*bC>}jGv87)JvIa9L zzr2G?p-^2zE4O>4wNXfD?bb95eQK*2{W-w(!i$_>ewp~nPui&(3bAgdX74&ou4?0O zMtV_E{lU`6@)lojoIUHf+(t+xGk@DzIV_jvrZ`Y?bgNm(7(NwBHnQ5bB8Nt$APCUq zA=|Z2{O89AQF$@e%=F@V)2}1+_a8y z(1vJ`RaayzC$f>K#fpi(Nl0ktJz?CTBTDic5T^N$tpfFZvi2>`@{PqpIutULS27yN zDt_0Q*}6)pQF6WCEWg!}6Jwu@0D*PG?zw2~3?OkKCqQ^#uypFthoq$s%Wk#d%lf*W zmWxW*?!5dWKHfO|r^EH|cOP8pA14$l-m?>uP1Y&B(XP$c;u)k13f27LJ8|m-@vi9< zu@x*KkTQ(INY&P4X4XA%!0mw@P%YmFYGuqS8|_ZNQ^1|aLgTH)5fEr;exbD6mCSeQ z&tqJ#2GH61)yHvvxd9|!x=8L9JBcnW{3X0?EL3A)9j-ERta^X-XAu6*eU4WIko*PF)mc@Q7PfvK)OE z%Y;t4mR=30H1={roo@`;a4)^n7-}RI?eaT27{8IOfoC%uo=!AY(~hcPR(41Ku(*EG zO&$iK-oy})<1_}*wOxIzFCzoIooT4+WrTum&Za*)Mf9c-@@J>^o?f`Q6Jg#F;Pf$< z_`$^P8k@Q*j1iX0CsmGga&qGkUx8-vSn!&y=iyb#_~#R+KI4DSS!{&}#l{Z39W`A4 zDNV&JP)vKs-T_^ChSJax0A}r@tTX3W!)U)XLSj~}UcaWAZU<7Uad7`UjR&L|IO#&7 zvuje30gJ3KMD8$T#Z5MI^lShj=GEq#mpb21un0L(Q1(6H`(w>jdFyB2786sCy1JHX zak4d7SMGh_92F%XOAyFaQEC>WffrTjf(oW*C2|UD#NG26IuJ+ZTJN373X~Lp8+8vTj zl9S!##qgOKf`PW2?e7s=^^B7!=r#EX9geCDv}VDxUTp(#f*8oKV9E~=CL)JW*NPL!dX2`J+9)(pZLcPj4!JnV@rz0)&MZXH`FJLlT?De_bCC4! z>W_WTjTpQAIX5M#9KU?QqxzW$M8QNlkAa`P$z-R$$*MPF~7QnEbXv=^jIDRVUn z;ftk73Q2``Fh*DlS*7gk04l*@bMkj<74yu=En@@b(5SOod2=pLSS3p5p3%p2Q16b0 z<+nhF*?#?#>aam9!5O|{WqiD;Ae}XojE`XjwFBcz8)oe>9`-k;<6ji%NSN9c1&@^6 z0FFf~T+jB$m*@21oYWp^4zESSyaH|HKI2aPEp#XDs>-BEiF~ZSll5~Y%}^T=IxzGP zJyb1AUm-f3;;wo%n#m81GD)@&C zI{dmKww9*}h3e`+=4!rh*OQbPv|Q(g*Zl=`Y^^^X5w0tOkYec1d##d9Mj^3ZiAcxxB+}Ci+CDKL7={E?!%O^=npa>dQ=$BMYmQwxeRL4+S!Y8j#n8EGHNZHe|KfY+8qn^H7Jtf! zPq}NzR2U<&rVvv^ zKB@2yuuJhcrp^PJ+;H}7mapc0rex>fV90Wk5TZk#o-uC;nDyJD@&jjJO%nCIh1vs*@%Kj-PgQ1xu&IbaJp4qj3d#~Z} z!5#O6X1ERH1)$;HrA#Ts;8JsFHc$m7hg@(ID2J6iXIi4G$n*PlhtaXZ^LWX$oONW2k6P zp4S9l`(Qc&5~}*9m(ooq|3ZUn0j1h`aePKOd;5OfvQ`(ci&HC3l&#j~?{P3YCB?S& zC7pG(VjLqFBqFwR{ZjB^EHD&GFiilwc5U;-d4!oRgEsuq4f0bFLm0#!@)<({E1>
    =e(605V!!S+wA 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.6.1 4.31.1 2.22.0 + 2.16.0 3.0.0 diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java index 0dcbb431145..c76f043daa9 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/NativeHints.java @@ -11,6 +11,8 @@ import org.springframework.ai.bedrock.llama2.api.Llama2ChatBedrockApi; import org.springframework.ai.bedrock.titan.api.TitanChatBedrockApi; import org.springframework.ai.bedrock.titan.api.TitanEmbeddingBedrockApi; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaApiOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.vertex.api.VertexAiApi; import org.springframework.aot.hint.MemberCategory; @@ -40,7 +42,7 @@ public class NativeHints implements RuntimeHintsRegistrar { public void registerHints(RuntimeHints hints, ClassLoader classLoader) { for (var h : Set.of(new BedrockAiHints(), new VertexAiHints(), new OpenAiHints(), new PdfReaderHints(), - new KnuddelsHints())) + new KnuddelsHints(), new OllamaHints())) h.registerHints(hints, classLoader); hints.resources().registerResource(new ClassPathResource("embedding/embedding-model-dimensions.properties")); @@ -71,6 +73,19 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) { } + static class OllamaHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + var mcs = MemberCategory.values(); + for (var tr : findJsonAnnotatedClasses(OllamaApi.class)) + hints.reflection().registerType(tr, mcs); + for (var tr : findJsonAnnotatedClasses(OllamaApiOptions.class)) + hints.reflection().registerType(tr, mcs); + } + + } + static class BedrockAiHints implements RuntimeHintsRegistrar { @Override diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java index 2d349ee8597..1c2bbcbbcd8 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanChatAutoConfiguration.java @@ -48,7 +48,7 @@ public class BedrockTitanChatAutoConfiguration { @Bean @ConditionalOnMissingBean - public TitanChatBedrockApi cohereApi(AwsCredentialsProvider credentialsProvider, + public TitanChatBedrockApi titanApi(AwsCredentialsProvider credentialsProvider, BedrockTitanChatProperties properties, BedrockAwsConnectionProperties awsProperties) { return new TitanChatBedrockApi(properties.getModel(), credentialsProvider, awsProperties.getRegion(), @@ -56,7 +56,7 @@ public TitanChatBedrockApi cohereApi(AwsCredentialsProvider credentialsProvider, } @Bean - public BedrockTitanChatClient cohereChatClient(TitanChatBedrockApi titanChatApi, + public BedrockTitanChatClient titanChatClient(TitanChatBedrockApi titanChatApi, BedrockTitanChatProperties properties) { return new BedrockTitanChatClient(titanChatApi).withTemperature(properties.getTemperature()) diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java index c7f290cb167..fe37ef15bdf 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/bedrock/titan/BedrockTitanEmbeddingAutoConfiguration.java @@ -57,7 +57,7 @@ public TitanEmbeddingBedrockApi titanApi(AwsCredentialsProvider credentialsProvi @Bean @ConditionalOnMissingBean - public BedrockTitanEmbeddingClient cohereEmbeddingClient(TitanEmbeddingBedrockApi titanEmbeddingApi, + public BedrockTitanEmbeddingClient titanEmbeddingClient(TitanEmbeddingBedrockApi titanEmbeddingApi, BedrockTitanEmbeddingProperties properties) { return new BedrockTitanEmbeddingClient(titanEmbeddingApi).withInputType(properties.getInputType()); diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java deleted file mode 100644 index 6bbd53635da..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfiguration.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2023-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.ollama; - -import org.springframework.ai.ollama.client.OllamaClient; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; - -@AutoConfiguration -@ConditionalOnClass(OllamaClient.class) -@EnableConfigurationProperties(OllamaProperties.class) -public class OllamaAutoConfiguration { - - @Bean - @ConditionalOnMissingBean - public OllamaClient ollamaClient(OllamaProperties properties) { - return new OllamaClient(properties.getBaseUrl(), properties.getModel()); - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfiguration.java new file mode 100644 index 00000000000..b2c19c7afcf --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfiguration.java @@ -0,0 +1,74 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.ai.autoconfigure.ollama; + +import org.springframework.ai.autoconfigure.NativeHints; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.ai.ollama.api.OllamaApiOptions; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ImportRuntimeHints; + +/** + * {@link AutoConfiguration Auto-configuration} for Ollama Chat Client. + * + * @author Christian Tzolov + * @since 0.8.0 + */ +@AutoConfiguration +@ConditionalOnClass(OllamaApi.class) +@EnableConfigurationProperties({ OllamaChatProperties.class }) +@ConditionalOnProperty(prefix = OllamaChatProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", + matchIfMissing = true) +@ImportRuntimeHints(NativeHints.class) +public class OllamaChatAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public OllamaApi ollamaApi(OllamaChatProperties properties) { + return new OllamaApi(properties.getBaseUrl()); + } + + @Bean + public OllamaChatClient ollamaChatClient(OllamaApi ollamaApi, OllamaChatProperties properties) { + + var optionsBuilder = OllamaApiOptions.Options.builder(); + + if (properties.getTemperature() != null) { + optionsBuilder.withTemperature(properties.getTemperature()); + } + if (properties.getTopK() != null) { + optionsBuilder.withTopK(properties.getTopK()); + } + if (properties.getTopP() != null) { + optionsBuilder.withTopP(properties.getTopP()); + } + + var options = optionsBuilder.build().toMap(); + + if (properties.getOptions() != null) { + options.putAll(properties.getOptions()); + } + + return new OllamaChatClient(ollamaApi).withModel(properties.getModel()).withOptions(options); + } + +} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatProperties.java new file mode 100644 index 00000000000..9be5f861eb8 --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaChatProperties.java @@ -0,0 +1,125 @@ +/* + * Copyright 2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.autoconfigure.ollama; + +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Ollama Chat autoconfiguration properties. + * + * @author Christian Tzolov + * @since 0.8.0 + */ +@ConfigurationProperties(OllamaChatProperties.CONFIG_PREFIX) +public class OllamaChatProperties { + + public static final String CONFIG_PREFIX = "spring.ai.ollama.chat"; + + /** + * Base URL where Ollama API server is running. + */ + private String baseUrl = "http://localhost:11434"; + + /** + * Enable Ollama Chat Client. True by default. + */ + private boolean enabled = true; + + /** + * Ollama Chat model name. Defaults to 'llama2'. + */ + private String model = "llama2"; + + /** + * (optional) Use a lower value to decrease randomness in the response. Defaults to + * 0.7. + */ + private Float temperature = 0.8f; + + /** + * (optional) The maximum cumulative probability of tokens to consider when sampling. + * The model uses combined Top-k and nucleus sampling. Nucleus sampling considers the + * smallest set of tokens whose probability sum is at least topP. + */ + private Float topP; + + /** + * Max number or responses to generate. + */ + private Integer topK; + + private Map options; + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public Float getTemperature() { + return temperature; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public Float getTopP() { + return topP; + } + + public void setTopP(Float topP) { + this.topP = topP; + } + + public Integer getTopK() { + return topK; + } + + public void setTopK(Integer maxTokens) { + this.topK = maxTokens; + } + + public void setOptions(Map options) { + this.options = options; + } + + public Map getOptions() { + return options; + } + +} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfiguration.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfiguration.java new file mode 100644 index 00000000000..a311a230015 --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfiguration.java @@ -0,0 +1,58 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.autoconfigure.ollama; + +import org.springframework.ai.autoconfigure.NativeHints; +import org.springframework.ai.ollama.OllamaEmbeddingClient; +import org.springframework.ai.ollama.api.OllamaApi; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ImportRuntimeHints; + +/** + * {@link AutoConfiguration Auto-configuration} for Ollama Embedding Client. + * + * @author Christian Tzolov + * @since 0.8.0 + */ +@AutoConfiguration +@ConditionalOnClass(OllamaApi.class) +@EnableConfigurationProperties({ OllamaEmbeddingProperties.class }) +@ConditionalOnProperty(prefix = OllamaEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true", + matchIfMissing = true) +@ImportRuntimeHints(NativeHints.class) +public class OllamaEmbeddingAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public OllamaApi ollamaApi(OllamaEmbeddingProperties properties) { + return new OllamaApi(properties.getBaseUrl()); + } + + @Bean + @ConditionalOnMissingBean + public OllamaEmbeddingClient ollamaEmbeddingClient(OllamaApi ollamaApi, OllamaEmbeddingProperties properties) { + + return new OllamaEmbeddingClient(ollamaApi).withModel(properties.getModel()) + .withOptions(properties.getOptions()); + } + +} diff --git a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaProperties.java b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingProperties.java similarity index 59% rename from spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaProperties.java rename to spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingProperties.java index c72fdb5b8ed..ea64f41bdd9 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaProperties.java +++ b/spring-ai-spring-boot-autoconfigure/src/main/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingProperties.java @@ -16,12 +16,25 @@ package org.springframework.ai.autoconfigure.ollama; +import java.util.Map; + import org.springframework.boot.context.properties.ConfigurationProperties; -@ConfigurationProperties(OllamaProperties.CONFIG_PREFIX) -public class OllamaProperties { +/** + * Ollama Embedding autoconfiguration properties. + * + * @author Christian Tzolov + * @since 0.8.0 + */ +@ConfigurationProperties(OllamaEmbeddingProperties.CONFIG_PREFIX) +public class OllamaEmbeddingProperties { + + public static final String CONFIG_PREFIX = "spring.ai.ollama.embedding"; - public static final String CONFIG_PREFIX = "spring.ai.ollama"; + /** + * Enable Ollama Embedding Client. True by default. + */ + private boolean enabled = true; /** * Base URL where Ollama API server is running. @@ -29,16 +42,18 @@ public class OllamaProperties { private String baseUrl = "http://localhost:11434"; /** - * Language model to use. + * Ollama Embedding model name. Defaults to 'llama2'. */ private String model = "llama2"; - public String getBaseUrl() { - return baseUrl; + private Map options; + + public boolean isEnabled() { + return enabled; } - public void setBaseUrl(String baseUrl) { - this.baseUrl = baseUrl; + public void setEnabled(boolean enabled) { + this.enabled = enabled; } public String getModel() { @@ -49,4 +64,20 @@ public void setModel(String model) { this.model = model; } + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public void setOptions(Map clientOptions) { + this.options = clientOptions; + } + + public Map getOptions() { + return options; + } + } diff --git a/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index a67fc127a84..b19a1365ad7 100644 --- a/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/spring-ai-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,4 +1,3 @@ -org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration org.springframework.ai.autoconfigure.vectorstore.pgvector.PgVectorStoreAutoConfiguration @@ -17,6 +16,9 @@ org.springframework.ai.autoconfigure.bedrock.cohere.BedrockCohereEmbeddingAutoCo org.springframework.ai.autoconfigure.bedrock.anthropic.BedrockAnthropicChatAutoConfiguration org.springframework.ai.autoconfigure.bedrock.titan.BedrockTitanChatAutoConfiguration org.springframework.ai.autoconfigure.bedrock.titan.BedrockTitanEmbeddingAutoConfiguration +org.springframework.ai.autoconfigure.ollama.OllamaChatAutoConfiguration +org.springframework.ai.autoconfigure.ollama.OllamaEmbeddingAutoConfiguration + diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationTests.java deleted file mode 100644 index 73f42221eae..00000000000 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationTests.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2023-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.ai.autoconfigure.ollama; - -import org.junit.jupiter.api.Test; - -import org.springframework.ai.ollama.client.OllamaClient; -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import static org.assertj.core.api.Assertions.assertThat; - -public class OllamaAutoConfigurationTests { - - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(OllamaAutoConfiguration.class)); - - @Test - void defaults() { - contextRunner.run(context -> { - OllamaProperties properties = context.getBean(OllamaProperties.class); - assertThat(properties.getBaseUrl()).isEqualTo("http://localhost:11434"); - assertThat(properties.getModel()).isEqualTo("llama2"); - - OllamaClient client = context.getBean(OllamaClient.class); - assertThat(client.getBaseUrl()).isEqualTo("http://localhost:11434"); - assertThat(client.getModel()).isEqualTo("llama2"); - }); - } - - @Test - void overrideProperties() { - contextRunner - .withPropertyValues("spring.ai.ollama.base-url=http://localhost:8080", "spring.ai.ollama.model=myModel") - .run(context -> { - OllamaProperties properties = context.getBean(OllamaProperties.class); - assertThat(properties.getBaseUrl()).isEqualTo("http://localhost:8080"); - assertThat(properties.getModel()).isEqualTo("myModel"); - - OllamaClient client = context.getBean(OllamaClient.class); - assertThat(client.getBaseUrl()).isEqualTo("http://localhost:8080"); - assertThat(client.getModel()).isEqualTo("myModel"); - }); - } - - @Test - void customConfig() { - contextRunner.withUserConfiguration(CustomConfig.class).run(context -> { - OllamaClient ollamaClient = context.getBean(OllamaClient.class); - assertThat(ollamaClient.getBaseUrl()).isEqualTo("http://localhost:8080"); - assertThat(ollamaClient.getModel()).isEqualTo("myModel"); - }); - } - - @Configuration(proxyBeanMethods = false) - static class CustomConfig { - - @Bean - OllamaClient myClient() { - return new OllamaClient("http://localhost:8080", "myModel"); - } - - } - -} diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java new file mode 100644 index 00000000000..f4387f1854f --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationIT.java @@ -0,0 +1,118 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.autoconfigure.ollama; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import reactor.core.publisher.Flux; + +import org.springframework.ai.chat.ChatResponse; +import org.springframework.ai.chat.Generation; +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.ai.prompt.Prompt; +import org.springframework.ai.prompt.SystemPromptTemplate; +import org.springframework.ai.prompt.messages.Message; +import org.springframework.ai.prompt.messages.UserMessage; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Christian Tzolov + * @since 0.8.0 + */ +@Disabled("For manual smoke testing only.") +@Testcontainers +public class OllamaChatAutoConfigurationIT { + + private static final Log logger = LogFactory.getLog(OllamaChatAutoConfigurationIT.class); + + private static String MODEL_NAME = "orca-mini"; + + @Container + static GenericContainer ollamaContainer = new GenericContainer<>("ollama/ollama:0.1.16").withExposedPorts(11434); + + static String baseUrl; + + @BeforeAll + public static void beforeAll() throws IOException, InterruptedException { + logger.info("Start pulling the '" + MODEL_NAME + " ' model ... would take several minutes ..."); + ollamaContainer.execInContainer("ollama", "pull", MODEL_NAME); + logger.info(MODEL_NAME + " pulling competed!"); + + baseUrl = "http://" + ollamaContainer.getHost() + ":" + ollamaContainer.getMappedPort(11434); + } + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.ai.ollama.chat.enabled=true", "spring.ai.ollama.chat.model=" + MODEL_NAME, + "spring.ai.ollama.chat.baseUrl=" + baseUrl, "spring.ai.ollama.chat.temperature=0.5", + "spring.ai.ollama.chat.topK=500") + .withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class)); + + private final Message systemMessage = new SystemPromptTemplate(""" + You are a helpful AI assistant. Your name is {name}. + You are an AI assistant that helps people find information. + Your name is {name} + You should reply to the user's request with your name and also in the style of a {voice}. + """).createMessage(Map.of("name", "Bob", "voice", "pirate")); + + private final UserMessage userMessage = new UserMessage( + "Tell me about 3 famous pirates from the Golden Age of Piracy and why they did."); + + @Test + public void chatCompletion() { + contextRunner.run(context -> { + OllamaChatClient chatClient = context.getBean(OllamaChatClient.class); + ChatResponse response = chatClient.generate(new Prompt(List.of(userMessage, systemMessage))); + assertThat(response.getGeneration().getContent()).contains("Blackbeard"); + }); + } + + @Test + public void chatCompletionStreaming() { + contextRunner.run(context -> { + + OllamaChatClient chatClient = context.getBean(OllamaChatClient.class); + + Flux response = chatClient.generateStream(new Prompt(List.of(userMessage, systemMessage))); + + List responses = response.collectList().block(); + assertThat(responses.size()).isGreaterThan(1); + + String stitchedResponseContent = responses.stream() + .map(ChatResponse::getGenerations) + .flatMap(List::stream) + .map(Generation::getContent) + .collect(Collectors.joining()); + + assertThat(stitchedResponseContent).contains("Blackbeard"); + }); + } + +} diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationTests.java new file mode 100644 index 00000000000..0dc856d7542 --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaChatAutoConfigurationTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.autoconfigure.ollama; + +import org.junit.jupiter.api.Test; + +import org.springframework.ai.ollama.OllamaChatClient; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Christian Tzolov + * @since 0.8.0 + */ +public class OllamaChatAutoConfigurationTests { + + @Test + public void propertiesTest() { + + new ApplicationContextRunner() + .withPropertyValues("spring.ai.ollama.chat.enabled=true", "spring.ai.ollama.chat.model=MODEL_XYZ", + "spring.ai.ollama.chat.temperature=0.55", "spring.ai.ollama.chat.topP=0.55", + "spring.ai.ollama.chat.topK=123") + .withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class)) + .run(context -> { + var chatProperties = context.getBean(OllamaChatProperties.class); + + assertThat(chatProperties.isEnabled()).isTrue(); + assertThat(chatProperties.getModel()).isEqualTo("MODEL_XYZ"); + + assertThat(chatProperties.getTemperature()).isEqualTo(0.55f); + assertThat(chatProperties.getTopP()).isEqualTo(0.55f); + + assertThat(chatProperties.getTopK()).isEqualTo(123); + }); + } + + @Test + public void enablingDisablingTest() { + + // It is enabled by default + new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OllamaChatClient.class)).isNotEmpty(); + }); + + // Explicitly enable the chat auto-configuration. + new ApplicationContextRunner().withPropertyValues("spring.ai.ollama.chat.enabled=true") + .withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OllamaChatProperties.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OllamaChatClient.class)).isNotEmpty(); + }); + + // Explicitly disable the chat auto-configuration. + new ApplicationContextRunner().withPropertyValues("spring.ai.ollama.chat.enabled=false") + .withConfiguration(AutoConfigurations.of(OllamaChatAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OllamaChatProperties.class)).isEmpty(); + assertThat(context.getBeansOfType(OllamaChatClient.class)).isEmpty(); + }); + } + +} diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationIT.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationIT.java similarity index 50% rename from spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationIT.java rename to spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationIT.java index 75d7fa9f93c..3731ac2dc8e 100644 --- a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaAutoConfigurationIT.java +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationIT.java @@ -17,6 +17,7 @@ package org.springframework.ai.autoconfigure.ollama; import java.io.IOException; +import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -27,45 +28,53 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import org.springframework.ai.ollama.client.OllamaClient; +import org.springframework.ai.embedding.EmbeddingResponse; +import org.springframework.ai.ollama.OllamaEmbeddingClient; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; -@Disabled("As it downloads the 3GB 'orca-mini' it can take couple of minutes to initialize.") +/** + * @author Christian Tzolov + * @since 0.8.0 + */ +@Disabled("For manual smoke testing only.") @Testcontainers -public class OllamaAutoConfigurationIT { +public class OllamaEmbeddingAutoConfigurationIT { + + private static final Log logger = LogFactory.getLog(OllamaEmbeddingAutoConfigurationIT.class); - private static final Log logger = LogFactory.getLog(OllamaAutoConfigurationIT.class); + private static String MODEL_NAME = "orca-mini"; @Container - static GenericContainer ollamaContainer = new GenericContainer<>("ollama/ollama:0.1.10").withExposedPorts(11434); + static GenericContainer ollamaContainer = new GenericContainer<>("ollama/ollama:0.1.16").withExposedPorts(11434); - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withPropertyValues("spring.ai.ollama.baseUrl=http://" + ollamaContainer.getHost() + ":" - + ollamaContainer.getMappedPort(11434), "spring.ai.ollama.model=orca-mini") - .withConfiguration(AutoConfigurations.of(OllamaAutoConfiguration.class)); + static String baseUrl; @BeforeAll public static void beforeAll() throws IOException, InterruptedException { - logger.info("Start pulling the 'orca-mini' model (3GB) ... would take several minutes ..."); - ollamaContainer.execInContainer("ollama", "pull", "orca-mini"); - logger.info("orca-mini pulling competed!"); + logger.info("Start pulling the '" + MODEL_NAME + " ' model ... would take several minutes ..."); + ollamaContainer.execInContainer("ollama", "pull", MODEL_NAME); + logger.info(MODEL_NAME + " pulling competed!"); + + baseUrl = "http://" + ollamaContainer.getHost() + ":" + ollamaContainer.getMappedPort(11434); } + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withPropertyValues("spring.ai.ollama.embedding.enabled=true", "spring.ai.ollama.embedding.model=" + MODEL_NAME, + "spring.ai.ollama.embedding.base-url=" + baseUrl) + .withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class)); + @Test - void generate() { + public void singleTextEmbedding() { contextRunner.run(context -> { - OllamaClient client = context.getBean(OllamaClient.class); - assertThat(client.getBaseUrl()) - .isEqualTo("http://" + ollamaContainer.getHost() + ":" + ollamaContainer.getMappedPort(11434)); - assertThat(client.getModel()).isEqualTo("orca-mini"); - - String response = client.generate("Hello"); - - assertThat(response).isNotEmpty(); - logger.info("Response: " + response); + OllamaEmbeddingClient embeddingClient = context.getBean(OllamaEmbeddingClient.class); + assertThat(embeddingClient).isNotNull(); + EmbeddingResponse embeddingResponse = embeddingClient.embedForResponse(List.of("Hello World")); + assertThat(embeddingResponse.getData()).hasSize(1); + assertThat(embeddingResponse.getData().get(0).getEmbedding()).isNotEmpty(); + assertThat(embeddingClient.dimensions()).isEqualTo(3200); }); } diff --git a/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationTests.java b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationTests.java new file mode 100644 index 00000000000..e4c3d0295a1 --- /dev/null +++ b/spring-ai-spring-boot-autoconfigure/src/test/java/org/springframework/ai/autoconfigure/ollama/OllamaEmbeddingAutoConfigurationTests.java @@ -0,0 +1,80 @@ +/* + * Copyright 2023-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ai.autoconfigure.ollama; + +import org.junit.jupiter.api.Test; + +import org.springframework.ai.ollama.OllamaEmbeddingClient; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Christian Tzolov + * @since 0.8.0 + */ +public class OllamaEmbeddingAutoConfigurationTests { + + @Test + public void propertiesTest() { + + new ApplicationContextRunner().withPropertyValues("spring.ai.ollama.embedding.enabled=true", + "spring.ai.ollama.embedding.base-url=TEST_BASE_URL", "spring.ai.ollama.embedding.model=MODEL_XYZ", + "spring.ai.ollama.embedding.options.temperature=0.13" // TODO: Fix the + // float parsing + ).withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class)).run(context -> { + var properties = context.getBean(OllamaEmbeddingProperties.class); + + // java.lang.Float.valueOf(0.13f) + assertThat(properties.isEnabled()).isTrue(); + assertThat(properties.getModel()).isEqualTo("MODEL_XYZ"); + assertThat(properties.getBaseUrl()).isEqualTo("TEST_BASE_URL"); + assertThat(properties.getOptions()).containsKeys("temperature"); + assertThat(properties.getOptions().get("temperature")).isEqualTo("0.13"); + + }); + } + + @Test + public void enablingDisablingTest() { + + // It is enabled by default + new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OllamaEmbeddingClient.class)).isNotEmpty(); + }); + + // Explicitly enable the embedding auto-configuration. + new ApplicationContextRunner().withPropertyValues("spring.ai.ollama.embedding.enabled=true") + .withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isNotEmpty(); + assertThat(context.getBeansOfType(OllamaEmbeddingClient.class)).isNotEmpty(); + }); + + // Explicitly disable the embedding auto-configuration. + new ApplicationContextRunner().withPropertyValues("spring.ai.ollama.embedding.enabled=false") + .withConfiguration(AutoConfigurations.of(OllamaEmbeddingAutoConfiguration.class)) + .run(context -> { + assertThat(context.getBeansOfType(OllamaEmbeddingProperties.class)).isEmpty(); + assertThat(context.getBeansOfType(OllamaEmbeddingClient.class)).isEmpty(); + }); + } + +} From ffddfd02b7e22d7c788ac364f095399ed46803fd Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Wed, 20 Dec 2023 14:32:57 +0100 Subject: [PATCH 2/2] Add breaking changes notice --- README.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index eff3dcf5fc8..467415dcaf2 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,15 @@ Let's make your `@Beans` intelligent! :warning: ### Breaking Changes + +December 20, 2023 Update + +Refactor the Ollama client and related classes and package names + + - Replace the org.springframework.ai.ollama.client.OllamaClient by org.springframework.ai.ollama.OllamaChatClient. + - The OllamaChatClient method signatures have changed. + - Rename the org.springframework.ai.autoconfigure.ollama.OllamaProperties into org.springframework.ai.autoconfigure.ollama.OllamaChatProperties and change the suffix to: `spring.ai.ollama.chat`. Some of the properties have changed as well. + December 19, 2023 Update Renaming of AiClient and related classes and packagenames @@ -22,7 +31,7 @@ Renaming of AiClient and related classes and packagenames * Rename AiStreamClient to StreamingChatClient * Rename package org.sf.ai.client to org.sf.ai.chat -Rename artifact ID of +Rename artifact ID of * `transformers-embedding` to `spring-ai-transformers` @@ -144,7 +153,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-azure-vector-store-spring-boot-starter 0.8.0-SNAPSHOT @@ -154,7 +163,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-chroma-store-spring-boot-starter 0.8.0-SNAPSHOT @@ -163,7 +172,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-milvus-store-spring-boot-starter 0.8.0-SNAPSHOT @@ -173,7 +182,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-pgvector-store-spring-boot-starter 0.8.0-SNAPSHOT @@ -182,7 +191,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-pinecone-store-spring-boot-starter 0.8.0-SNAPSHOT @@ -191,7 +200,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-weaviate-store-spring-boot-starter 0.8.0-SNAPSHOT @@ -200,7 +209,7 @@ Following vector stores are supported: ```xml - org.springframework.ai + org.springframework.ai spring-ai-neo4j-store-spring-boot-starter 0.8.0-SNAPSHOT

R?r&`|Ou)t-0+E&6pGGstuA`JB4C3 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�zP9cus$`87INKE;xnEPfXVOS*i`-&v6(Hxv9(4gwR z5_{O7dAP22W1`Rfnt?UOGJ@|gV7^sb-S2buK7Y?Cy_EiFd#^H1;#<8|l`})qmE(^- zSNqEHKa8Xb33t4M5`b;w=Y7R|f z#m6%jIIdcJ{$D4ozAI)kmujOm*_y$AKLN*onlY2+KixaGUfUdB)i;4RRhn%?i+TO| zV`=P9|7+F%gQx!+e8UVI-w?^hH<(pN{};YNpM&F@`Nj#a6W;1@xeL0XKbbD78V0Qw zR90d;)5YE{SUJ`L*Gxwre!5biVVRO6A~2VwtDM#PtB%Kzg9z!_gG5PsOS}3e7ufAE(^@OBe$HC9#D#X5JnfIt>Zmx_g^Vd4fXB+DFnwOx zD!f~;imu$ahGz6rYXN+dvmZZ3llt<&^CQA zI}d1A^p5?vV%FtrpizS4!b#ok7xx~;CpPgd(#e5EUpY8FM4mXDaNqjMapx3ZLJMK%+ zU-cb13yr!nFd4C|lnF30QpHN>O@K;*GFlc8yWsJ1amipao+^rzG7Ix|D4GxiKqCs5 zy#dT>dA|f>kdd}gdAWR2o^5N#Ul3Fh)*75@T$m&xXn#xb?$A6+z#OHny% zU~})OIq^6Oz+fy-<~XO#JF%li_YPt_oGue~$ME!esYoun-@RnW^Y*|=hF5@ws|q>- zr87KLc>^0h&9r4PU;{7@N~sVY@YcC>b*jYkaSEmLKLuIS4Z5>B2{y@#{%kI^ zWh%mL*&#J>A_!c|3DtU5c@Srb!GzVMxi$0M_K`N$>eepFk-|`Bu1lwjgS=Qi?5xyJeJ7B( z?i8OCiayE7!3E{L%zew%% zmUq9_CI`bui@#iyxZ7Z~q*7%YaKiGYbYU9$-9zB z{hqOAqIn|Fzc6InrDB#cf~?bPR#u`NzEwM$+#T_|9#6TJS18Js{8QPL z7*ySARzl~Gl6&|)`SN^OyjA+FvTVRy4E~TbOvphQkP_M575@WK$tYa)ZsTOqCL!Lq z2P|e;7u2=e6T<92JbGZWWJ4b1mD5|uPT9cAYf&rnWtY=0>ou?rE|;Ip5svwPTKe$4 zW$>fT>zLTZxDi_RaW2b3@+(K2ReJrc_G+((1^{BHyH-H;80F0Jo@a$}iluQ?`IADe z6n)?X7@xgCw#bot@qORy{NZ9I=(XegdmYI|3S|ahP7U{0RL#ynM=1PACKGB)90s8m zgMA=pD;e?K`nvfK$mNfb8v!T0DV@@-x(K%xfDcc^eHc==j1l-9P*_-ax8YYea9EMB zsF6~Ds;bP8oq#y}<1!wwzFFZwwsW<(xVxWit*GN$x5HP$e}2^2x#9_USBizkiRMX) z+v(mq_Cf84K`UU0Y%QdZ#hcB}w7}CzD(dt_c(^*G?5LN;cIxM zB|KNS$^gra#mT_*daMG$=J#@$a7v{D;){p3WjhxSCC20oGjbuascJ&A3*)oL7v=7Z z;16Vm+>+Git#)Ll%JP7^W}E_IWs_!Y?Q{7uwNrSUXjRYnj75^qeX9Y5g2ez^tr5&7 zFo40J5QHhBg@u7OQ?Rj9)e=L;`eH1=%s)-b+Bd8BqR&Oh!l-UWMCh7eOzmcwasLfZ zBX_fK`fQX(GlflC`}2>c^NRD>gy`h29G_KZ!XBRdbYB~`(r-e@@_VQ%s81S?h^m53 z7|``2^|?G`QSPg8AF~y^@|0nP2&(9|CaCR#`umiNslVeL9}+LR&&Uf;Y0AQ1f25Js zp7ki5SKt3$i~k<`QsaQuOp)B5q#9PMTGgHa`zOIvSNr)}X;~>DskSx_!rC>jQ7M&z z!lvZ}Neoa(TeV)+<*%KPwbNQp4~9?2yu@|gcjeiyC*!0sOd-B7X@II}MRKr;+OCvV z=9f;s4g_cRq9(a?T-N0}jmf$TZi+8^NA5Kjx^tMWwVdPvzC9XG3rGI?4Ef#V8kjC$ z$cL>B|G{bLTr;uEee+7VIO2PS5<+{kyj#j*Rtc7`p`uC{xhI-$7rWY{DSTg13h3$s+)xI z>H}|#rAvw3Gm$FJEGJQ@?a=l2{_ zfByG(IRF0(T>0<6&;P-v_a0>bCvDkaf7t7qlYE%6xxp-^_-Zaqt3!i4yomu}qf1mNH(6ih|AvaBN zvW^Yi_|g+sa+ulgcEp^Ole?ZmOHGD7L@>-mv?>;5TBkywY#zW7#~j@V%?%;5Q9r|w zyk215fL8#H?{;JX#_X@Ez^ki&Jza&Lnx0rSidR8$OX(Vt=^>=y@$!xaYLUke7L85!5t5247$GDb|2PRWWLv!_icR$%__Q+}y&bj{ZgK+fpM>8t>3`%TDmeRUqBXZESu~pK=*O{6 z*=@ODBb^(S9+qRbMEl1o0ixY?jKhl6;us{Ird90`sOf?1b}sEkJShRnalXq~M&otN z!}NU&a?P7bT{Op4UY`c`H1frA(+T-PfB9MmJ!=uY^Dt>XC=BzwZqJKs_Xk>tII%Yh zx`DurlV4Y##bX^BCawrnOfXq|!72hTg{ZDsY1O!PtW=V;M@nmpk;+Gu<><0c$#6pn z$gL4k!M;o_U$_-@g>=j^1S#Df<)c5Xdc^c}J3KVhc?`1p%CUj2ve`NUo37oa_bGo= zgyt|r`s9$R#*zg5ny{Mwq(dr_g+7xtsV-dK2dXDVzm(&sn)jQp`Qs);WhG3SKmZTm zGa1O{Vj$4D@+7A$PcHsGe8>nNl2bW5HWOWM>2eU9Apuna1JmO#=@#U$_T|xHOkx1q zTx8>L?Nj@3orjxhd@k~-BT3^)(s_ybeVk?T2u!inOeobSYq^tm%4t_qpZqTem z+DJsI7X>2(+h%}#k+jq26$}2Pkxnl{gdG;$ePc6k6_Ll1pSLy8dOLyJ6@u;=u_FT2 zvH)4O=Ig;2HPd#}cHkOt)#`ylrxUjIX&yS&8qDk7eQ@*-P?|Fa}ZI(=3SmHxV*C5ca}q& zNa5>X7cKAcyY#8>p;TrM)8v}2oc6ZTuc6^SNYj|f1j~M*fDa{k8uHi8-#XU=tHyJh zMadH@S=2x}=~`Tc(;PW7LMl9tg1ceX(Rs}mT%yqT!>;6+rp*R8K`@#NIDX7+x@^7g z@zWSp=Z9qVQd~+F6FRw)o`r~8U4UnmL%axG3&Bvy-qBposvi3g#Oy1EN96PQ=PrSY zMtq_s%2SxT+1?*hHJFkYTZ*_L+ zZMfkmmN}QXkuIBXt$B#KF^nhG40k2z`v;M_C&wjORCaB>`RSKM4aB{dwxwPEYa6_! zOtXC?uSJm{*m7BGT$W`k(VO?xs$Pdkv`#3uVaM5{?Kynbc6U&lfGbB?#~C07|%lJ{2)_cW2b#n*3DA0&amWxl*zzo-i-!u(ApG!>L+J)OjLNz{L#7N zKqNBhkq3Ev>TEH zHBTxkK=}YB%t~JR39eywIo@J6CSzn(0U6oyoDS6apN5Qkw`{R_`bp|<obaZSxe7cNgN8lqB<50e{EwmT>uZ8d=mtfBuB1z#f-Y&vmt;6m7 z{v@C?{!mO+e}_LPTce0I>2S@^9_c2NSpOh>>nAA`OGC1LUt*_yl02@mDfM6kc{jj+ zfNwPAygQZqW0n1G_buRSCr|k?76v*Q@2PIMjR!mp|+F>*(uaXi;9k*Ost#w!6oZ|q3|Zmem2xi>te_Nc1Uxn8AVKj?^V zWOLXpQyg9#)rGGJhOV>w0MR^8Q1HM*f6VQNW-)Ct?Xw*fONt{o;v;*14Af%wi*r4G zywuRCHz4z4Tc>)=uvd+_jB<5nYT(JWo2d_uZ>3vT8~r*{;v#On+hEtTap-{IX1i#_ z{V)A}{GjE%jw^mlK>PVJR}SHYdU>H{p`B+mHyPZ0YH@0BhbHA4!;oJOT42e$fF^B6(WLE% zYcJ_{7Qhi9sp}crhc!omUpZ_mN1Led!;(z}?*3I}o0rG8?%#?cKK34C4X-R39xG2J z^f&$Znj*QHLkq`3Y=^j)x%K{+dnf0?KHh`nX=7ZYdo z{PvE0$Sdt+Gp9?htSQxhlP_C`#oa)p7*|*a5Gd9pMp2mZsy+zKhOJqeBljK!mKM}% zjQIe4h+$$WsKk`Q0&dGd2$08qsqh%n729MXz8N0*0MK*{ySVZ#ZDl_UV%g^I32Gbo z{VXlxO8T(o`jKk#ki)%(Q?Nr8J9bP;?=Ld7Conn7di->{YzsywaC)Q{#aZJr5*N#T zm!*;%E+tSbi#!oH14X3fv4P%EQJlAIgq!bT6v6GPW*o2huzVl;R0`CN_I3^DMxDz) z+=Q#rK10o82EvKmE4SvI5b33zCW5DsaUB~1&)dYAW!R$6tETI{lM&f$V8Xe^QkuDO zR-{*{%aC|{>5v#M6dm!b3ZT-3TLd0)EyvL`J}3z2q|P8hO6p2y|LBA&tuE7y`DWAny^Eej^)V4sG?_hok4EoaLZOT0)=)^I0VGX#U577HwQ>$cRItlE!Cv;;Vq|$r0^!qXb)<^_h zcNZ*3IY!$P$duwf;$(Y*F9~~CI_bMu79T475KbP}cyHN8gf)aR$A~^o+fa79a6|RX zv(yF_4uqHu;jDr!%0@sREF(mMEsQF^4DffOO6;u*+yurglHumdoqEapk`NkNarn_; zRU$ATXK{j?&15m&BWQcE5Z}nGhr~B4Hxnq5mUd3Gd#>OK0oD+&5cRmou;PnJ71z_l zNcVZ$6#MEgHnsD|sp5_)AKY>)^D)A8!@rLsVyQ??55OVdo}26;#&@H5Qj15t%`Z0B zA0Fz2Bu<8P9w0YFv41Aa!?}q^R|P2Yud7KyDhm(H#^|;{L86Tz>2k0N9`6;yopQZTzr**3+qyQ z?(q2UTI%l#kn$s`qMG4ej8&a{CV2QU&hQZ)-7yNGSq7foWIKGZqb5(94iGap(~7lk z_#P#|M#mG$dc~0~eXf~lqv;2keetjia^@yluo|y|yJG=B5XLEzy^Ry~p5$zqGWw_> z_P+JYtXD#fgGoo%y=5C`{oEz?DoxA_1k}@xpuLOBK0nlS95>F+OV@Y8$S^r=m3xoS z9g~x`ESm%HgtmswnB>}`mH0=3%=@S68wg11_~~`JkF$y86SS@)Dt-Z`Aj92n#k8#A zLrk~)Fpl8b&;MnFL2~4YHUH$#=_XDJR2tmkagXqZ1X`%A*e5Z(51D*!Gu}f{cYe6- zauD#KlH!&rLwHvkFloO`vp*WNGT1Z#RHB--VG40&qo%FE;CIi0p&miCne+`SEdSWc zqu^23V`HWGP7xF7ojrMtv@LnoR7A?6VVF@pDMyte5D~4^_8A%%vlYLkzej)BX2 zv@U@(NqZpKwAjtkrqb*{|0=yRS3$iK#b32{UYF(Hqg`(51?d_3HjCQcJ#@$j9kKwL z2>>3X;1%M66p^{fLD`08!0OaAK)t4azve;)5n@*JEuM{~e5xvWIAijpeJNV0DiK};ME9U+=H)<#EW#&U+ zT_bC9Z4%}C)WT$p3ziXmqmw%FrTWbgM;81qm{3EH2S29nFzs61Dc{h0@mwyw!qAi8 z^%*qvOR<#dq;=0H&q=yEz9#0j#mkbnJ}z}Ge}~tf`i1vZD0XP}0Znorkiuf9U_^11rLV!sp)PT%k>|0{I_x;lxUnd`@hV0Mjgd6NK=ZA6oJr2Bp`iMIwlB72qnNsClGoFof#F75|9#*K7^VC zf|Sq$BfSVn2}lV@2@sIbLJj^!o9PC<5k%L=9`oNGL|kDY$Y%)9CB#LajrVGgCGmS-Pdu zt`JH;@cR7AN&fB!AYhlz!qK+%yhX0nG@`gQ9g=jnF<{pn=lutjck~q2Q%&Ruy?LXz zw9cV4p<5|w z6P6z~<=5TW41h1HG>WIuvkRd~5!q z_2?WJtb{6Eknx{0O%hoxsxLMpXdvI#r!T=I6K^8!b%+|sluUP(9M^lXJHGFCSGekE zHfFvxGX8Gy%d*1MCg`|+1{Y>r>S6&h_!N4jvJ%m3sC4Q5g`Z3P2Du5&kp*UF7N5(G z!m_Jo%kuvcmvh8kc|7tp52QWuvUVkn4K}0)y`AWgTg%NR*0>lG>SoD?bGc*~#8ebp zH~ph=>wpDX#KIO3A6O30JiT~!MMvdH1`%3~6ncsA?>9-X-_u*;5@FMS|7VNo@A=yL z8JPt}{}GPUaB%q>7k?ASBcFVIdW$r6V&6OS^LI@AKmJ#1>c8^(KOjcebBNLN1{`Aa z=ls7BqyOb%1|ds#YkT6&njimMZxY6S7i*3ixGhznuBKMU7KX6PWF=T z_%_~TwXg#pAP(2{-e^-|^YLh{YVFfX zjb;;%<5qOSWp@m(!4Cw^gfr#_=)5_b@X3rRy92vFznlE=?+VBNK@yGUnP}-@)#-hS z8JT@%c*d6QF_&gpz|-%RlAizRR$>a&bphG@80+C;e?owq`RBU?9CO805J zEo_px!Nr&V>m?3lirgC==AhE@jVn>!v>(7~+ze0UsV2%PzxG0n&0*9^#!m+m`!?hM}bYa_T?;>L_Jwtw{MC}x?GbnpdHdGZhHTOtQX~S~XW~9{D;>shumtuufOwwaZ z`Sx-tnMaBV!Cz`Rxh_BY^!Hu=cel^GLH@2p<^4}o>f|jH_gBCSYvI_eM^U>9vZ)iq z#X+O|SJwDXERtINzXvhdRGiLIFB5f)gtWPIw6Bg{V~prC=pz((e_73!)G`PDMB%$01{Vb>dym zWrk;5PH(nW-*{WQz05)E)#i%F7R9cYd_8JMv8s9L#ZtJH#b;L2%^WlKY6RG>ww3EY z8oi;{wEAxX*cT8MO{8~xLOv6a?`k)JNWD#eiqvykRR^RhCuT%aqs#9cokzal0wDYz@rTnHe z5=k}e8k#P0OiyQLCyLb!w!Uo0wzWuG2h-oF#>KV-C}`ThsqGT`6wiUv6WhEBm&giC ziw5fv(33H&{rKh5``x4S9@O%=-}6V(_5x;U#_Vm!(46@TmF>D;9bLTTH`(&mSnK43 z(o0C0+MKLB>$osGLBT)D%yU?q#eCCXt34m)gE_H%K?udUgS6YH$%6>eGD~L=*b> zC3TxR@A*Z<(1$_dMKTmx-4G+gA>O|pXX#}ZO2}a%;ZsdI;|he=%Pj={R2kT_hu$r>_&Fq?+F~u-K9xT2^nqyTYG7({&5&)t$FG zErWs^qF4br>$QUoV-m*XGr`}n8#}p^0g5*|#jBPY_gMP^U)!?+@O4UgK)8i&l0hSX zZ&?-Fm=TJ|-ly8szfAP5iMG4BhrKr0lE{ERI!*vhsJY2=s+EU>FxlebROhHltDEfW zffU|%o3Tn61R zt6#e8-E=W+(dQ%iCh++%KT6h0($-`#k&@ttrm*5vW$o*ccz>x3KgWf(n0TFQ9|vuJ zP?c=5^V&6#?{6+#n`Y@koy_XdQ`nVA>wO}pv%0SPLdHj7ElQHlSFa2TNUq|!DG!rN zK?mW6qA>PoM4RU+yY1Cx&^uttWTB?s(}$WFjSkP#EAB+4-WyZ1`hI#%CC+e`&B?cQ zvOPXTQqV$O(WS(X@VZf!yr?!%%6R@=+ISG7RHV-!Pqiv9dfRDwq5x&huW$z*nv!-@ zoZk~2e&IrQqLypfV)l)gdlhBHJzD`56Bf`eam)1(bXkfFVp5Gb&Z+Z`M?#HaHF864 zmBnS=MV4{s_UrajeZsK{w@~WexZ=iaCaCEHbfN(WRT+R-%jv6GNY)5Z^`ybTwHB0+ z1E}S-Ti~@@X)_L8(pCL(S@VXuS0wdxYxj}8V}!Cvc6kO))0U%yggbazWRVI0s!4YjE+CqoI#x-B{+- zR-+Sb0@<)3GX=2%ujL#ltR?FIMT4FgzZ}SS9}*-S2rgL-KF{0ubu|F%nN8Wzan=p< zMi#!|z?%b!Xh5mM>xkG7zA>TW)`&u@4H$sCSvKsJ2@eXoiZPsOW2z#l=oABwMedXMUb|f1RpymS{7l0}%!4 zK|S>)q29=HKQ%%%@Qi!Jj1ycQ_bU6dzG_%@)5W}Lm#*y6^z0wd<<`L)pVofERW-l! z+cSE4W>;)ir<$qrVzNrvhx#Y@gXS$f&9C8|eOU9jB&-`5ek>qs)8AVN7n98zU$Jx6 zg~1ig@Ai7DWbM^?vez~y`8?WiKuMx>^zRZ;U^>@$Zz%e?z5^vcg;Lz0_e5c+No_0Yv(ls0=CqI}4?{+Hx3r3y0n!ZyYe1CZl0f9XP@ z;P&~PE&CCs8-+Pi=zFREX+q6~wCv&MN3F8AN*cs5&S=>Nwf?I&P|w&)MSPg&w-I;C zzHy0>mbw=2A9NIoxVR_coo{-*S=fPupkd~;EaMF)g51?yCx_hu04dDmV?0AL`-*UA z#eK-w`Yfan@b-B;0rsB-a``au7rQ}&hmCbD zgivpDKshgTouFKkyYjY*KT)yp4-A8~o5R#kTRgNMO%znHOHKbt&ln zQ}^_g-Q*(ArkUk6q8g;?c9X1x?z-+Ok|<>kxXt|nt2`J$GIH(qpHVEvNX-ENGZ*j< z`K#bW36Dm+fA&NL#^Pk3$B9Dya7Dd&V&ucr+I?XN(Qe%cdHdWW2_yrm3r&$Zn1ZaG zXzDMra#03I@5PkCnaL`i;mk1`m3yS6-c{ zy#vlXw_+-_h-;(gua%V>ikbq{?l48)FDHgL!;t>sue<}E? ztI?A+G3r7MyiQPIL(u36*#dBM0E5oY{(QOgNl^D9692r1s4S46BUD_5GWpn}p8)?{ zv1*tpkwRUY)Nl&Tn&V)^<*VIke`Gl{nO!#?P?{2Gj~{G_1-}i@*!t=Pn~#*qpjhV; zu~DJNwZ!>HCHqDr9pH;4^|QW$ItB_l*b4Qz5|2j-&O#sufNg}+QPIQPVFTbauQk>W zP%lO@5L0wu|DrH(#Lq1n`gTgm#*>rIFs$eQXBnutg!D&^F8k1W8ET&RNj<#V`||#z zC&qL~*2Tn$T*k~gY*lmT%sa+2E0~Vysov5VYm9cKiuRQPae4O;j?q) z`b2sQ3NV)D%pZf}7%Zhy&J8zQ?<9ImN{y7`8PDg%{Q9_`|cxe zT&hZeKp~@cKFzsMGpM+^zBoa09RnbGAEZS$XCESE0=58EN|vXBCLt(9!hE|S;}5Ju zWn+utS7XaTldjb!_ggkG4(Sc%__kXOHk)jp!aEKF@|p?Q*w*(**__xWqL}wY86;e5 z;YFOhXwB1gm0SzR=<+W6gRSor@wX6dz7TeVpn3-YAf?j3?2iFuaB|EJhN+5Arv^?{ zFh3OlC=N`*07+g(JE)!R?{RTSbKAl0D?Vyph(qDI7y8jY=9&&z?NiH5+)9jSr#I## zr#vx*?p;RA96siA6!*`F?1X|>DAhp~YMTrFtmu-G`6rz_{`yn1TP$2@jAGBx`ef7j zXI2(!Ufpt#{_aU_HHXqfUA@gzcPHE?c+P^88=Y$#RXSpOx5kZ}|Ma)I;0eNS{;Q<& z0Jk0(R0|UpH$LxGA6gQMaNsE*}VYAqVs!AS7S3v@;|n>!l3!bECpd?`ZXg zecTutD13~$boG~#{F`zrjE?7kc_9JgQ>lqC#aCf|=fLTBX;Pzl@;={*=cFPh72-wE z*|>2~P+6PmE75>4x^S0ldZ@=jDJjb`qhu>zdgH^vP$si=$vIfZkt7T0NzpoIaIq9XsS zqqRk%o&DltGrmewN`DW(N7N91Z6tzCp8_7<>ATZ13O6ybF@0O3)i0ZDUlo%T z$qgj}3hO>k$q&U_tWVgyK-gBkDXyFJBb8_UxF$0_se61uPe@9`+(-jaBUYFZUbntG zv5|B+?BUui6g+KvEEv^4X5VJyl@;{npgWHEvBZgGxT0T}fmRwlhRZUo>o?-D0XW zCr{9dpO@byy63(y4Df6Fz8mR5lxHggcMT*x6TT9%`ntCy%*8$(%P`|7zFcQx0%fS_c%RH#a> z*_Hu7jLe#^FuS5XIyr#@C{sYjx$XX@e*ApXJzw$!1XVI_rQU59XdcB;FI*Lw?hfm% zpbl0RYfiGTitjWV&#AId;W8_20qzkO8NI)RN<|9Tg*YCI*?rLIAcWkero8|~hTWGr zLCt8dpchFi*WeX>>O$+b7+7a`KML$yi+{w`$|f#lTHnZ}ZZq#XFn8 z)9v@Ao0DPRbH7dFyNKApoBfJQiv1aFpg)Im(1VNfpLqAjF>LE+(DpLT(24M0{NlEfTm-Z{yC;g8kk1&i$)oXW_IQO>iW=Og3j;nSyvu_z3Ud0M%Qdd2c3Hi7G`5)lkX8wtLE9Btb z4ov@sd;9(07v(>Rza^mrz8&c|-?(wEZk2gh*yOF>q`P)}^+iTTGNiu5_Hg&kZ$d4D z2Eh=2cXT0r>f_8hFa^4?#nL2eBn4X8iiCW5!)6g^Bz2w$zI*vy&bQfI$oK!(60!%k zJ0pyecYt9Z*0aym$vRg6Le#tEay5=sfPJkS1C#Gt#s10$K@6KlO2N6)MngPV9j5Ox zq&j9DXJ*Hm%yFuHwWqRgxP)qc=Hd_3v*)}XzC7c6ixi?d!%%5CRY^E59JgTsB`$nF~w8|Jd`8vL!q@bFTYK(llvvs19~45E3#3!`PU; z50QnLnL#4a{DNK8 z8aJ2dzaJyUZb#Z`U(Gr6xxeA_HgvshN$J-A9c^&wG+QUe{q%F>lRlOH@DO|FlM(IT zuK`5)_%E1z;|jZG7O~X#McLrv`yjRPC;1B0Awc2&1-`wh%rZ`4j5L+r_4b29m|+Mrzq2H&DqEANLpIXQHX=n!egP?VT2doe*FOK{seX0 zu)7$_k<(uG#RDtoy;b!D9^MK#f!}y3aUCPnqFZcXQ1YbSA*lcT8guSwL0=<-U_IrG z9W^c^)Z}y*2G@hhohS5B+42vcg0RUgbbjY)WCk(Nn@_VW{?zYGte*)?d?7q`*}TUy zHhFB+ig{z)0j*|nmy~-j%YXxpXwZ&Ai?N3v+&4xkrRIz4MTgL(tbhf?E4f|FbakrS5O0yy#sp}X)q0*9;M~pYNd{^3L?sx`R*r=O# z$Kg`C{?W|{6&|Ikap=n5i8ePT^LiDVPHa7-^RkJaV}}p*{!y)?dkiw}SAEirYNCi+ z(#TNLPo!DKj2A^)QWT%HL;txfk$i&@mtIB7sRVs}u<5o&(;5%C*LM&<8$Nx-y2H8P z8MnqI-dvLqNOlfi4K6|Q-QDfk;)Is+)_?R**ZsMnPAN%ql}HKdIbA~}>+U3~Q{YNn zYrlBfTzI}pP`yMcd5)KE`#c;aJUGfm^wqw4wRs4|meE4?y~Yn*fVLmxfp4M6D;o-b zR{mMwZE6cLy&^L3gUrOLx^h(OrJxBQOm~ArwA|i)=2(E?6N+Zxsl8P!rp#I%=t9P^`^Th28(YXN+GmS$u-;=ScQi=WdH;>2`!QM&9GaT< zRdr^5safFcxly@9Ri3s3J&M|0fZVXCl$1<+yWJ4b;vc;604%g$)wEeM;tYd69kF!> z*gy0yjmgG)ZtD7}YkRfA?|lyJCsh+UmCD9$Q2anc^xHwF>NT)12pvwZQ7NJBNW|+N z`0Z{Dt#o$!sRjBU>M{I0b?JkR5{UasQHU076QogiQO`01eYX5nx45DO!DL}=CwYwl zv+375eR!#{vUlTm1|WP6+GYGy>z{=S#9*gNz*vQ4>?$$b7=coK#<9?t#QquKuRQ=z{eMc?Et`A?&t6?oz=|EE5AdcgJU(71hfXRT=kO3JU#T-eDkt zjU{lAc=rz$G=D9VU_Ry zo-v~G>hI2x0d!k)Mgh)%DQ@uBh1GY{zy5E#J9nW4?yM>1tC70y@-Sx7cE^)!+~thY zUeD!+J$9X{2KW_~hw>160A9Hf%DxfTjt-Rc)zxlr2nN-Zz9v9uQMSuLl$&`4n8I&? zbz^~V`l4KA2yzRhD=z0wQ(K; zY*Qd!jE+QLZWrKO3#x3G%P_h;QWr& z6DXsj(HAeTzPMuc#nyJMB#+NGz0sNRJICq#^Z#~O{_W4J{$~CpyR2ubp6mN2Fo>RO zlvEbLg5vBao7@Z(Da&RpZ$j1Ye@T}v#g2f4Iayq;z<(Z;vf_4>qP-gSeYijcnAELBur!@QTmrV-Xg$o6;y1lC_q6 zUB59n858-C+i}GngX8rdH>M1h)KkZpOd;DgxB3Lm4BbC%WkR)BPQm24<(cK=v?Unl zj+ix#Kslygw>9GW?wZPPTwI!}(-*z!G_chdDAg9`pzlRaznBd>Q1}CP(0QL=7n}Sb zh>@N0a;1cYFwq@Y=~I~br{lIHD~F0ur!r^BaGUD}Kz<(h+3@r$qEWC5cE`iNr^;9a zVXdyx?Wk09~R&` zpEmGsC;k6J^(2GxSh{T?h<{$XYbSPBw)lr9;lS$iTBA@v?*vio9@+16A{;GtAh=lu zUaysg9Gkn#)u!9D4}=L8Z|m`9l?tl)Axt-*e%y(YC7CV|H_OqcVMlUhiIwpC&UEQp z2VQx~bi%lAnEbk(DM?*VFO#tg(Pn7bK2bz#YVoRB-5uPH7_kQm#)*dZa;CnLZ|#Dd zTc;}yW%ZmTVPUnnvVKdasKGEY{1H~y1BPfOO2Msj@~`GR^thGB#46m6c9Wc!t$PeJ zlU0C@(@Y&_4_PZ)B4DpgJMtLG>~m=3UP!q!IKN-R(^p~2bj@o(HZ+tw@qw#i-jAR6 zi8}J}=IJXN{qzjYa-W_Rx2NKu^W)`9ke#fPq2N;f29&dW$k<~eINwN|8dbhHCzR2I;Ap zqs?>&T(O%dK6t+-P#clP@a1RX+={={n4rv+y|(}+DNiHHYEo!k3bo!w3Zssbp}Ee} zoBvQWHE@fqX}S<8V4ybWXnW?ZsuVP$3i_g{ku=EDM^3h8eXzebm)YA5L&z+l)dA$b z_iK3!?-`5TQmolksXw%?cU3;fwR^i_LG+-_F>IBU70IsP*ZN&kyPl^bPGNDUvt`6r zbH!lS>zugvkndh1Ewb%OUx@x$)GMFnH!9FO!Rk&8Udg~T{_Q` z>|7nk+6t2f)u$x2y9Mg~Mv~f~vS$_JUl{f8_L%tGaP!5O0hxxP38-&QrN*!d=oiy- zP)-2-ASZynGeu3@PpuNk2{VVTLpjudxPAXvy5va6a*cDnbt8F0*u?~W4ltmq&*}kG z%5etu9Gf&xk3T0XNg>lNWnxJXnU{N1;b%VD2!jn4C%5cW!9s%(DPqAwSW})~R^M2} zseb{LO=lvzZEW?vcUx$fTgFy(cQ+1um`U0t1;EwJ0#`uCX$cb}70Opa$eAR4v?Hh% zrzvB!m!!O%GBaB)>4D*sxkBX#s!z0T)z|V8epJD^14z?e(M}~jA<0YnUDT; zP^DSvAqf|YloV-QaP|~DQGqz)d#g4QfCn=#<@2)elJx3(q5PWeEc`y66+dAyCsyMn zSYs>ICwGt0fQC({(6#gmKbY$>t>D7^J1SD$@%8tUg*fz$LY!djX>;DBH7WWfZDd?) z$hqbYsrV0m48x)82V(5uooJxN`$gWDXEA7BhZo`IH0m;lLL~{O zSM(VYsUo$tsgjyJ=s@wjgWl!O_E$8W$9n@xLAyC22}yZ+c>(6d(B3Rz3Es5IxvnRUSvwtS6cuLTzmYu>gO0l0B2gx7Oz-1UC} z6=e+_sN0*f`MLGI>Sk7NHA=1w+MYvQ3E;=^(SFjpEmGBbgGNS{A^|cXm$w$~^9Ek% zJ~zW1z{-?MX!=kGzdIl-P)>yw33fbxAzA!XE|Y=N~c%1n3FpHJ{{N9Au8+tcX4i?r+^tZvsgj90pA z^n(GKz5s$9g?CoK~889O}B7pzH6BPUe;g~R5<0_qhxzMZB_ zs%9cKhh@dnH$j_sskERM{b_#n=hN^e)WPR@k+jup;X><;3|yJ*YM?R^^lT}?0{+Qs z--MW+R;V5}i*GwW;7YX4NMZ^ITIDWp!$IB!VP?Jk($imHPRZq7y{kYCjy~srXU@I* zZsM~W6-g46#0DDF33_kVZ4>&oY9IT@X(En)t@o?@#2GasBimUs$1h~2S~2WH7*grp zrMJ0a>2(0z6Xdz9iVgURurGhboR<*txRUn@o za!}cN=<&eoUD4{Nu5PtRgW~#OZtmDvOmNUvs{tzU-jKb4K=vM6qN#7|5oJ$!asV{C zgSBK$tf63+OHxNRv1+p`dqJ8>7zb4ANnoja*J_TRo7a_qvg#g4P@9Fh;hL+7t&psE zGO3zkf4@*~Dh##q2wi6-H=%DLnl+;LYhV7T@w9cIZc;>V&XE2;6Fcs1EQ^z(Vxs8^ zZSZB)k3QK~R(3RT6n<5;PpBuOh7AANq0HIdxXnoy&+H?td=%*X66cm+4a2D>PJ(#{ zhQaK58;{~=H(`arm+l!CK{$SwtV6k_316Y`9*cNaOuuJHaYjxExmv&Dhl~f}#+Y8l zR0UH!lyhn482sl0a6o_fHl434ResQggp#9NG&1Fvg7AWv`Y!K6dKa4WVZ!CaER72I))% zL3HcbV=H;|bGj7(+?gx@AG<3L6VA|VqYT9P+DXvFAh#n=JSE* zZ}7kC?{(A%!aodeOlgK2qMF61;?3lKTuY(N34dGLCl>4R#mAUv@u*yu$6b|}-TdSO zCg{Nt;$DwhxZ1{^2FFksgR?V-GckGgRbHW7YwEmFyk1VP(X z)Xg|OZWsrF+LeiaeN9zwdx$F1v*?^uRHj^;i7+fQy~sM`QBSQ11dWqzhi(%hObe=4euZDn3_UNhks$SUdPR6o0+5xc$5B2A!^{Kf&7?<=M^(R zPvWbG(#ALE>H6g}#BgfHtQ7Va+WQNZa$aq}VY)e^ z5aGrtDAs;yhjU7%yQ%FRpj|e8W<$GfQC;vi4)I0Egp)Q9?qH@n6DF6;6ssDhn{7FW zd3Nm_Y>xW~VY^r2-1j|DX5+Jdmst8umKA3AKL3Hp-fcCYR;-u`0TE?XlWLZ4_{cl~ z3_NU~kAD)_BE`83L^JPdBo8J%wV1EI^rIIJw$Hbj0yWAWH4x^X*#(ySLtHkS@Wg$> z?y$ksiD)**0Q>;#pR;N`Q2{opB4lCvv!g>ETwxHKqJM~2gA>#mF?L0C*iZR!kLef3Jgwh(c2k5! zYsaivsR+@Ba7htR%!qJzC3cHLl-^vU@z9$!oaddU7kC2Y>ODX+T?|(hsA)RnXUK!YOX2lK#k~RiDSB5G+<=S}Z_P1T$ z?`i&y-B_Z1))XeH#`@$svGCg=EwbB5Q|sfk;=y}|`(vM&!$xwqlFshm={Zq} zygGLB@hme1m3GW-9XP~?bKQcfOaF|x|7cGnG|sce+Jm?WemgJEDlUmr%cDr|8#`^k zDc8q`F-{Zhd9=QFEnTk{a*`b@NU(VEvbyF|UH;Y5w1zkP6$L&EGT*pxjF89;uJ0|K zZrN0x30iFh>qr{A&yIiN>Og;gO0C~Ta+k_^W=VC(24{-H$ff{A_ip!+1SUDD%jX5S zs?FFcAi$esst+|Cm2+Em{o>k&YNSuqy8}k|2SPKrsj@f>TrIir1{nr}VH7sntg}U>>_^GU z=z@*6dCL;3;DAE}ettCG-2Fjo*j`H4U~Z>E1l(o9x-+dNCec*3s1o6@!-GXe<;~-d zO)Ne~m#o@2x6{Le{2)0EWJ%{TTQvg2Ic>xj{wXVqs9-u>c~vq&!3gcku^{>z zd@aFqpnM#6;OM|#KF6;35XZs+Ut6{AaA}+R$7{nUC_Mv{5&zxD^yIJ20ZE@{!jBK9 zu72vALHW(Q1E-I3i<}CyW@RMuU;Nm$dWGy!ne1;=n~N=yUss+URzTQ9cvZh%ifnz% zsqk6fxU!~gmtK`{q{v0%v1q^io67@ID@=u331zm2v10bQvd0qJyj~?IRI00&3JFm^ zDdjF3)E7wPV`_c&O}n4|cK)j7{g{=<;M!b#S;=ISnvo;n8<*1SZQG3$ns>d;&hD}^ zht+{;YozJ?u$0%%hCiv@lWcZAinz}VpZhXI+2<^kQL>s^gn1!8JHa|@JICAiF%T9| zyU$L2O6wVYXeNxuWfT4H^;MTJCqEVsk|sAPbUXE^7N&drC8G9<$MTwmZGkU?p{fQQGCN#S?(nUWAB^s zyTA{`LfenA;vpld=9|pA*X|RqM(zbuzb2pJG7=oJaqxN~BjaaE9~jbq5gYUjm;53TJJXRaD+- zn8m;hw@n@lBt7mQ=1+Q9$m+x0+!i=Cd*#6YxzleW!X(+^ z*W*wWKhcRWhbfgs9QHI@PZ05&ZAzQfVwFx>vlDTacgNpI#qRV8O2x_>D~nIA^EKHel4l+&5qKhdZO)?G1`p*<4(SU6p*9Q)Rh8|W z-xl!;axFcf^1zsc1?`*NL6UyC#Wc$7x*6Rk8?>rs8?+YTfZ+Ox*Y9t4iU0QIcUgS% ztykR6(5P=*Ig2X2ozwqmkPtfa=o{Cix|4>8G~a>Ya_EWa9M}2rp8v`+=l^c;`Ttq# z|L$=6^`8gt0Sa^cYW>M-)fsLz!^fvGMQh${X86OZs#G`O zT7$??qQz{-^RIhX2VI9BAcvQF?9IvW8KQHTd=z;jz%$gEouYLxty=Fir9SC2vpgFF zS$tvXvBsqISgeIh7G)Hz5sIvA+gv_JCHDxb%#>6mvYC`7AgoaOg%UB2P`Gu$}j z{YNjs8^6T{3$9{IV~1eg8DwX0r4VXST=d8G+udLy<7Rrr{KjfQtpr4g{=;l+?NEpT zx8OIf7+&G)Tm7$y#5htDv4Z_>yCo95qv0YLKPsdLHN-%M7Fp!CtzWD12_;f zCsJFZSKShw^j*CftOJ$B9j;5eKOhF{r8xn*l36f6t=_gj;8lEIH8@HEGmX`GkZG69 zwPcg_z&a!))Z-|XW-+_Awv;>`*c?Xc8zaGl4*jYhEO81N>q#{TDL|4VfVYwPP@&nd zXoU_ZlB=ut<-3yVO(c>fz|Vgi;dgQr%nr(>)y)9VU+w`pu_NgNv+g*`H5{Vpb!u=< zVWQ?8nVs}|nVOPa3ePtys7A=28n9O<{ofL0R|hTlemN25gf+lA|WM zqC&>ma@9(NyGf|8;HXMJ#UxU{-D0Efopuwn-|6{+Pnq1lpWAcA3htXFKkb>v;TVd({h7dwp^V+xX)8>ptN4y6DfjlKWGqiu&fsqPfKo5& zC|xqRk5yAGWMX@H-;a9wYT_Oo)q-sHj9r3#EYB)_N4C0EFi6bNS=n*KARCK`WhG_l zhL(MK&D3X{p~_zo8!cYQ`ihVP+tgLnXfG+W9X^Xznf31bs#h*fH6u2Rm6SppMwj7a z*3*_ev;wtjg+Yj%aPae^>!$Yb?NZ~C&qPQ{1}ff2MqftGb@A8f7aqQVm zY0BBuV_Q^HhkNhl<*)$CeSLCVQ10Z1fq?}v@urd9_<`o841e|3F{Yvy%X<~h36`k1 zI@y{UG*^6MRpiL%S^Bfm*+VftXk_h+A@!ZRr=2TL!=LrJDJf{}NXzeE$*l7z#!ty+ zb0UA8S3@zo6ep;?7{2t?h8x=^N##RNoQ}2p>zNy!FGh^)R*jQ4>zIlK$7tJTRX>F@ z;vV>0+IqQd)&&FRkMDziYHQF@ban} zi>$l-6AhLAWe|eeDB(wGZ(x^ys=LJ8FNHnvd;Ig`&Et+gLJFjdrR#G7v=cQ$c8&g{ znR)-SPxyv+J9X1+hmcg!8Te+N^1{fg;T9175adJ7$}(IgCx4E*uJ-28tK5#mll)N!(62ix$Iwh>_=vq1<{wRf_doNE1Agw z*@_mM2E>w68$5qol$U^yyv4gh8WoThCvF>ZLp5 zRlF(BD)=;kGHLfZQusBAePuECx8xD>Ft)dB#c*EmKF86fx=tswnVIdh-fU4PZsj)&zm6Y)~&9db%4QXDr%FXJ3e8^8(f2OEekvv~l04m{`}m+u9=6;(G)#-MZ7Cz1bw4?~{&QcLo!#PBCd-?$o7 zuf?~N2iN~N-4=(W^gx4xhNR`eO(x2_kn#Stq9|vKax%JVXYhJ+yKczc8K4Rb`QVN6 z){m2FwIuoO{Z#onJ0;=IFrTM`m+*R~d})2c)@O!qVi)!RyA-;~k{!OHGB1~e{ApU& zq{&NZ)2d{bs8@WW^+vaV(p>n>l{5D^D&>Nsd3OI?XM;jCUw&Gjca7_ zfeF8pkS+auWBnaW0ipU*nJGVQc)buKGP!<JNDKrVUPBr6kI9BGX4tmsdWEonfH3g;6786SfVw zZW16M6!H?9nwqYzE@&4rB-o^}FVo$6WV7QQ&r|d&w%F1^3>~prF)xsicvSu2YmM!8 zw!Z4CS(GvwDhMSfPs%ta0ak=ZIo}DJ9SV{@aqo^Qr z2S5@z!h3MOr7jFK-ONeh3c{W*E}N!JX~;^0)ZY?d{aP}b&)SSKAN?Qfy?0O>>ALRA ztQmX8_FxZSz$AN2&WtfRd2A!11r`c`NMi#A1Ok&pw%4*v5(tJMFxe(5ATU9IB*K`S zqXY&aFd0P78DFh^@2#`;u2bjiyQ^;1zE!vXq6O9csk^%QzW05e=NDpE@> z!o2_Is56O1#p(x&W8u<6m|0B`pcwQLL!mIR+twN5Y~u2wv!Z=}k+m`rljSpN_Fg}k zDAZhW=1nyz#FODGvM<8T2ptBpnH?MzIX@Ux#>`iqx{F6>kWm)h-Fz0M@=(7-Gs{~( z!?I8DVrC>*z2L2xlN&W$ccs7lZHb1BCQ|s8@bs+p@mZx?nmPte zxMkJsy_2j28_Un}Rf*Mk^Uo*8pVphg5`33DCx^iL4{L9HYFb4h?&9=I}NzFKbhg6GPUr^IA6;zRll(L~FJN5+ zcmTe);-L{BO#nv;?>5D7@!WU$pN;%K^VxrAa|V}xs&L#}*8QuKf16GovP`new$`hh8F}tNE`!LFeAB6|XBiy!)B7{6)=~_}4-uQ92acJQb??U=Y zxZo_j94B`?$`%^rgTY8<)bs=9unH&7YVr zOK>^E0L81gDD!;m6X-lLB!r@-{ zcET%x;C*M&^A|;LkE7fP;x1bz;}S`@1AQV@n~;^Ce>Awu@($22cW_-?diq6n`PXDZ zzBS62Pq@rKebNwMb?26u)l>BB33rxm!FNd3A1RM>oN!*X@d+9&kGdnh zc>ZEXoz3v*V1+x#{CeoDgUnavHC4{u2M-4^lXEgq&6uUAd#SrC%j#5byd`)#AjM3j zq>$^Ukg9)vW6t({9`Iqa!~6SOiP9g_#lux_b^%uYy`AH=stqDdG6=7PaqBh?+O?2l zyHpZ>Yy44I=JGhd^D|cmh;NN4Q?WB4;a1YrHN8v5l#MlG@%&m>tB3hseHXM45uJN1 zZ)I=r*7FaPzWRteIs<%HH!d(mGB6)K-^jLF#){GhIdiRNb2@~}EVo%{8)X$kzmYP) zOQZW|3|LkAdcHdNweUgmG`EJM^qRHqdbvY6u#8hE=Towxn#e>LCiv|(NVyI0lZ^7^ z&0=T`8fzM%X+5^K6Bdh1s{&|?5Zccw#3NX){92x|k?r%Sk1!IzqUegTzTUl~eZDW^ zN-xJctD_}8Z==H$t#x{v7bi5;cS~PIy)DGVser8mry%1xwd0{Du>lx+k6Mj1y7#K_ zFNDIcN4}u2@@VyrXg(eO6?!(lZ9C!qQRxS+-^~BwT+g?4A74IK+?5NYaBd%Flj`bZ_r=c80xWm{jLu9*ed zIws%ul0f_30EXmOkf_|m#(GQnl=+wgzb7u{`_H1f8D^m_z^qy~6WluWu;<=UM!M0g#=%y{#_~wiJRI?w-BVZ#DCsOi2V)#&vi8*gSx=W^Ua0)7CdEuV@T? z>Izi9rc#C?54#+QMKDp=BJFuLr z(u$tM>fh1mEDo>xn(OcX{(zjlO96A!qleaqu(+Mn72Tw1kbTEy(JQ&{`nES$!-%Iu zz_D3CPUj}B%=vJ*>E_?}UqADip+u}T3~Bc>B0?gto33mwv6q;CIqrXjyg9%jZ-#Nm zo50Gv|3Tga7=%-9>;F*xCTyR|5%iMRBEUR-kaYmSu}Gey(^cZ}-NtENQLgqXN*j`} z)h$67Ei4qUjeRQ1tuCZ=?aTj;k?d8?YPa+4+F2%S23?Jd-~J4Jl2mD07?5Bj{ucoQ z@LQ)6*5|CK&+1kF$Pm0K1dD}Dl@E<8Laq}^@Mw1{{DxtPL+(PX4SshCbx)UX>p&@G z-)6dVA^bMR}d+O}}%4)so7$TE< zCuw{4=d!*xvtv(M?&6k}M$v8zi*H=QWc;3zr3e;qJG1M} zb2UGbLc}GgqM|XU@+fI@knEvt&){%*ry5DMMk$G6{8+VmZKu2cAe0hIKSsG)^6CH5 zaRC<2dv_8p1RAn>$&4oPs)wSWeF{l@K_+B>f1d>iGksnCN=>x9oqiR+`bj{6ZtUp# zQ-5^wo2OHLrdw0tb$iYOInW90#)r}(=??|7;qJWbx8p=B;#O>h$)XOngs1TnMdB9029IzA`QF1tOTI9-J0>7vlhSEzvFS#iaYM7K6?Q@FE z6{NLk7X#%u@UUgahMSTFOG+O&YZfu`jVq?isBC&edx5PPW?N0xcupoYW;{x@#|@`4 zON6v*Dx$G_FR8!nFuP)lzbHN8m+{rsvoMvCuIQLvk?;6P&)9XmZE>|wxNQD>Wc=2C z2|g)11tMuVpDCB5lLk{}d5q34a=O-(XBIl2kVYMwsX_+McwVRV^sGn(9NECzCRQUr zv>%lKh46>m9wi3UwrrG zbcePht_gqQzQXi;=44qS9I)x$URprq^q{0C;ymx!qF-IV-{$xA`6Oj**z-|!RzTrw zu9K+xKzW|&hzI9QFZw&Y?90?c-`N-YcAf>eg3{cHV|I4eSLgSKzt;~F^tm~$_D5JZ>zk(36&ZN_hsBunzaQL*Of8)~@ zi@KaF?G>zZ{+Vgv`N#EPHA6^FWA3+j$pVWq-gg`XYBLV*F>8*rogo2Co+`At_8qB2ryr%!+_Pq%Vc8n4La_`K3IK56ZL@Le9mp6%3Fbv*qv7If{FFW_*X>$~Zq* zo-LItKq%|%dX9w-NziznN=ZgbbeKbchz-*oM1D+viaR}e@ zk6_iVfxr6R0RWsnP}ca@o%4}VWvBv<`AGufBz)e8s`UwaF0~QFV9?zoy05--M5jyO z6D~Q;mfqZeT%_b2b(0Z;6PWZgvaiKGN&)m?_dU>bd>U-W#;$8`|BliJ&Jzc3299L= zrG&It7W8(?50&WwpsSaWMH3N!jyWg?oh~?VQyBXe8EJLTa$WsDdZ9}(ylSfs)Xe@u z=)wemwpGvuP@;xMO}7U2Q_tEJ8{fGO*GPA6Fr1~V*T+U<(5*htmAl4wv3*vGt z%93~-Oqf(7bWTDCKF}`hD?s75KS)Wt^r;y?g^}1 zVFE!WRxs=93a_#p+40s$n#PGs41JAVNB$*MD|ZI5PB2Srs?S&y%u#UrwhU5uCW4B{PG7XWV`+u;E-MSD#`00tZK#)t3_jUK-u1d z&ObXD&V{}nvx=crOhx$_AV<#F(W?AAWSqBw4}1a{z7MN%`zf4c5G_z!z&~`p^aIuE z-YYw+;`gMc6VgFbN6M@Gd-OgX6n0*RKbrn{XiQ37sd=>6zxg%lS)ANwk^1~6>4$U#j&A)Yq$ZAw3k%-4pU-*^wL@&T9zzR}j9 zo@lht9yDy;wYvw8N~#LQ?iO6d%0Y@hHt|bld26?@fz=eZ%cB?fDUBaZP1{xDtD@ug zzApH$3(wLXmGZHbwaWy((3zvT=(^9#U6U2VYNS}btBCOT-u|k5R6e6XhA}#^B!@VNZpQuE= zXyAb_Pcn?fH)qEog*kl)bkr!DTSPNLMXJWayVW?KE*=<$Z`w1HpCWx4kLzKwUs?-P z7SreWf0U(jf&*%;EN^w6=^dX6JM_}!tO{f(Aal8zt=TGUatC6XPshB#D=kZ+sitzH zbqlF+UQC#7O#}{Aylx~NYW|wxx1p@{;kcjA-9f#X{rb$nAX#mhO z+-y^5X`oJK;GSN;!_y(r%&4W8uJ+iqnkoE8f2IV(9@k;Qh+L&nDHHvUbks6BqBIOM znfMd6BX;{v(V-}+LGO<7(C_n{AUtN?$I$)S?xU$ahm%aNJ(hU;Xt$=Fl7(QcR&S2+ z%;&w0!Qg%!sf_v^8%1jh$%l%(W+LYl0E54K@{WSC7$06bUu5thJ#`&G*qhbn# z;{06VV98_#LE!j_0vjAR1F!D4&TFo7&(`#no4-h_>3bQWcGk=G%oEcA_x-3^+?V9+ zb3f=p<3eg;@hdg!?+DkX5k1aQcj~TDLGBl+<2Abj$s}F3_Qtu)=&{aw%cr1G7OKn3lIl4DP1?VfK0g}C53;M- zCTeGGB#R_`(mQ_M>P*VC$%F zT&@A6N6j^)s-Ww>g|#JS`E4eEy@g;^^Agc?^YE+gY|WdVMiVDjv|n1q_1Ycg^UTTs z$>w)P>n-{+*<_=~;Z4*GdXS;>*S)_r7CHMEwbR^($}9qm{E9C&Ic~=C-_?7r4Io1_ zoLYg?Qq>^E9QyA0bh`hX~k3XAJO;A-Hn{yvL zDiUU)c%b>ImfsX>EBwy)(I>uRz0D&5C(1jtkS&*r8H3X8xsL5FBlXo7uU!)@9K|4N z-M`Lu1sU%mpb70-)`XY?s=aNJP!QAX4rLZ1hNisK_%{00Z|d^WFKlzkj5#d1J4N+N zPvjF%i#CU2n3hI@6!S=l6{cO|aB!R%=U&hl^mr|m<4ZNM;*hh*eJuVVP$7vWc(!;q zw41yh;nfzESv_%+5t_EQpxu4dQuJlA=QWj(t~r(H+duZ`YQBay`DE8hXiKJeCZ4zJ z)a7l*n|%2)WRIg80{k|J2V?E82d}G{JAF6D_}HRS z5s}v#UW!`z#>EtMzx(hdW#s3L=*bmj3m0w*%X7R>qUIY{16aoG!G2so4BpIkhNb9!|mZy;yp@$8w|m}}rIwQT(4 zBY7L!=I*a&i*_XWOw5nD*SWv$Bcgv8JuL=+ahaN#_Ak$hJ?2Xx@K`ZR$xS~>zZb?a zjo&|;KvQ7WTHX6)ku+)U+5ZOG^2aRLlI@*V7JybnPqcgQZL8czMM0TI@)b?(H2edE z+b>i=VQI2r%Wp-lVSE8K!{zx3qK%R^Xzzy zhhe?<`uhRviz^S-)|?asi=a%ro)Pm=F1c*NNN1ti)3)sywDc7G<{Q_D-HQ5R>n`2d zQNd0JGXe1>aAcwU4e3jXD!y(3tFXOI=z3$u*AReM9|@u3F1%qDqxp?%(QrMtze%{b zXBMin^J$Cuxy|TL*WcJ0wrL%9uUx?Qs$t7kI$BhY!;qF8Q_hBt^OPDMKCS9_Fkz=J z-|-YHCQKt4p97t56uDgsyTfj_Bo=LW$xlM_ivqdF17APT{J_QiUFN^k7rD6p8^9?3 z-FW`XJOAH7;(XVGh;$5l{0|3qbu-J-Db<)yfMuyuA(3=00qU&Z@Oa8+?X)Ic6<+H z)*VDi1fIFi1I~W@{_~=1s#~UnPiNIN24HkS32EA534l zFt>cavVhL~tdw7oZknH*`ev zl+P(ZkZ4K~;`daq$iaeKTxrk)2y>kpal^+6;*9m36RoAvU`Z=L=Dos?p_O)VPLjS9 zaC^I|3=JE4;EyG4h^7Z{L}wKp7rx)P278_r9`R=Z)lRx%Y-I~d5)u+5bNZgEkMx&X zBwG_?>?YS4)>|lXF=34`{rojnRCx$u)tbbFZJZSd(llywwHB1<$;~0ig-lJ@0sDeX zme2Y#YExADsLVd}s8RAk{+Z_t{9|&*yZO3v3yBDP(yvA6;#Zl%v9-*6DN7BWU` zt=d&HXIgrVIV|Qss)aoey;AK6sZJl2oYbQ|{+L6fFZ2GqrZ46#jI`|-UpeG26u=N_ zQ5)?oUP4bz<8TqZ5wc#m-CHJWcA9h}rdRf+o)rJD-}CR$HyoKQk) z+pK+y>y#=-tBexN98JC)OK~*7EkS0Z1vHTGJYXx8T6^^ivYKC07&{?v^@7&!5SYkw_I3v%v|o7 z`zum?Brf8?kU84f+#K}heD2jQWI^ct!F50HsWbq|U3SSA7x)-_AL!CI=i0yeSkVgHh?1C? zAf$I5cGI0c`tz!JqSlPdm|l^bbV=rIJD1W9RdZMUW~LKw8^}_Zr#H-c(y`5g?ns9K zEUHz>2$B00hn`0DRYCmX1xy60%a}LW3c-^g!0Rcr)U}^#$7xq^GEVW($vB@t?~>1Y zzCMX}?(GCjTltDvx5-tBD$gxbuSVKTCip0RGRyJ@NW6Zt$I_u`Kp;>6z=jDsD(=_| zf+@m%lfPhPmFYazbVpbfHq|S<%6N>|h;W`Jc9NY37-x)KdT9xLIl_8PR}!$}AhhJp zg@$S@X9i3mU$Vqyo+}iDVNvS~K1mu!XTD!Vu-gybKHp4QL(UF)eXzdo{i3k;YMOV} z(V2vF%kzNlFl(?G#T(V1N_e<{m#te=iPGvw%$P%SIxvhfsS*WrxV)S!c_@44r2k;O zqi?n*pHO8Pps^oXVWmAeCRdacvsmJZt!O=H&qMZX+ivut) zyg#*6^uA#=G2_z}P}xyJ{oH-03LHU}jdSr5ycS_bb}dfoqFD#9 z{lzMGXv9}g7RM1NDKj`^YPjl^`X@DMDB#-P+T(;fY9_NAvT1?H@d^_yiQ+hsSq1PX zrhka6oH#K-!<$&;v6`$kQhqjuCmn0Nt%fVD_eJJ)v6-@6>Q-Q@xHRFkL$f99$f8Zq zsp|rUAs-PaJApuB40&iIIjZ(V@G+9@p~FUF>vLXSv22VZ-CDsKS&I;L3&_;$ z2^%>oKu|VI>eO*L1j3QVqdAX7?&l-n8jL9CY7ltX&SRXHcnf1&XjGzCKCUyh74J8;#y|bfjD9R_J)Fb|87w* z37UAjxm;7{w5_bfvyg{iWd|q00?I=r>NPfdF%UyGaPpDEprUjfPv^GMv$g_c%{Caa zj3_C2e$NSXL-9`w8mco(TRWWuD!q_%-jCXtjE+*wy!9azR7W0l)8llnE}yYJ^5$8fm-%(XkPRstYrGl(Gb6ZhoHJY zX3b@WBee4btCmT-ivKt?C5%$h9wH+4%X0t>=###t1;lZBMg|mCy{S;z|67)kol_$H z3tKthTrKSc3r)@mf-LwE;k139J-LbBSp!ZufYUU$(_eqtRymD}A2iog`9F#zMB329 z7@G5wO$SYvI5BUyrjJ%65x9TOleUgG%{FHtpSZNU>hCs0%*I_Bgnjm=fGvZY7;PgD zJ&VF@NQoT(w5?zOhJeH6SU|^7z$ED1FLmdgUYl=fwFed22t!tTUV%tLsB+KP*TPQ~ zmC8(l%>A&R{C{R(w9?UDc~Er%A(X0PMks*`Pe5_bt}b{ngEh;WFY|Xc@(eLS2mzJf z<^&^qmu^v>+wwOrL4BxTgWMMeBjRfbz@$Dl+uz!i^A6>_M_cN8oYwCcgGf`e_Z8G*erye&`Rj5$wO98 zfevB{k~Wg*`2bsShY3OlS$Lxi$^vOj2Y}~ZuD4zy#)!U{3ooeD>9h7M-BSYav6DZ7 z2(A8-i$=BhDPa_O6-C_UZ$ zO21Nsz-;DRd@a3B=w=|C0VVg=Jqn3Whfr^aY`=O1SfDw`dZ7qR#xUx$u}{grsq0jw z)$Ny5CJdo>r$p53bhjg4*O@%N`TW+K!XW9df!MvWx(fsMeXIE`-m7gCXCf2>fs2|&4<%lCTg z*LR$HXVqmAu31QB+N*uzx-oL?0vJN3cbQtX1%1pKzQ>er$G9YhMNGl+i@P}*!tC>c zM2|pOeL_dX(3HF zf=yZ`uYD|rqf0vJMkSWZDDBR9Lqm%c*Kxj9*lpz_^dQT1B-rac3F+#3Fzt&jPOw$l zF~q#+_rmwj0}NpV-Rl7CKznf5A+ zFt(%WjX47t|=9(j5~!N@x_vu?6pZ$;tXPMR-I{wMsQpPJo}_ zYW(nr1dFLi;f_YgA&PUoytCxH>>U@ze!d?)Sv=!G3{*$DykzEcx<^Se*!UFJZ56{x zFZ^iSsPE)YD>-pOL*0t2gFHHiDP4LaPy@9U=MtB)1TFXm{rO(_X)xnFBDVJTLA5^l z9z$ZaPMeG^s?97%UFL@cTK#0^+&hYMk=k*Ad6=&+Y(oQ9$qJrIt;klKk<8fLqhZV! zJ#lFf8eIX73$Eq$JwwJ4o}z?SLu>5~w8{H=4iT7uTX0AUP0b6Gu-aOeX_xNt4`F!GYOzh}VSr6k&44Qz8A>=50jWU(snB|sQ2^Ew+08GBPr}BtOMQgT0 z$kde9gzpM0>&(T9Rt&o`g!em?pypYMS;36Eo*L6t<=sVai@d`1D6$2%p{dLL5ii!T zM6RYFZPK3N`ph{&t5Gj8UA-)z$JWe$Jq0PdAT>~aCw9=h;{Xt3>-ihzZ?wtv)D6dE z{Jx)x^>NotWlzDXBQvwiD{VDb%G7%>MVE{oB-dz~q_H!2jrvE6H-*r8^Ud7$!ab(q`mMX5(y`qP4H>KA6KUxS?3gC`Y!W=9803*M(YK3{SQ zpS81|K(p^VvR7DrH+Ss{pC7}?_XsMp;PtJbRb+F+CUlz;vj7wy*1anR_CI}{s)JlO zzdhCv?8meNIZvdnDD1ckt zA@sd{war4@8|^=^oY`O)sMjB=0V8n!q6F4j<&Ik`>$V5gqOR8y!0#3^tI!G7vU3TJ zqFKnI)b#6crVv6WUdn(~mzrsV4ry6Ad?`Wtc`RGk(YI^Urbk{*e);y7GJ%s^$F!Uc zjsu8{@)xV3I53*zH)3!&u%jlqdpD0U^arrnM?gV8a{(-YCUw`-;*G0#j;|`7! zRMSqo(1R*4ZB_Nrw3}a|3D{LX(x+{iE@!~4xMLsOD6O>L7uF{XbyL);H@}wmE`4U~ zucY4`Rs8kJ6)T@JvUOZ)aLU*}L0wLYJ5-$)4V?^ZXLX+iY?FFqO3x|EeDMBt*ZpI; zZ(I^5S{D^z&%$7;pU4nid#mh{^sx+Ir+-M3i{Pnn5;)?7_mJzm64k%|hho-$G_(YTND`|EogC>{j1%3fB)|9j#@d0k@sXb^PQis>{QBm2TUK>IyET< z{_JPUm+sv_`NBHb_J$aU)TJgyXPTY!j$Kn9rZa)|l~xviDkc;yIl8qj%D^k^%aY1{ zR8@42us0ix_0v2Sf6VC+4apUAYbcb(^AT}#8AF@Q?j>>J>%VtjW92cc|6B!S-stU28nuP*uerwsap~p^vlqw=eY2*nm zV6VgOai$T002raf>f`wHOi*#Kk~#6^+0{08f}a8`KRHU{39bR(AKO<;Y3zVllaNvv zpsJ2^oDpQ%$ET~`44hpNnJt-Y{_*9?%*f7Ydu3fv5ZEgBw`3dB*Wi1bl)i6VPl6kJ z_OG{j;3&p_G+IL@J!S#pbc>Yy^bC+7)*v({0WvO1vKkrPKKwA~JU|0MrsTc#d8xYa zK?7|Vu+~TiFr@}O!Gd}g46W`B)~Gt_?%$TP8LKp6O&m}(jm7Bzs(kQZwfP6Q_$r#^ zP*|5qr%bXJs+&pHA)GDf5G7;hit{=t_b|4p$u7BiGZU+g+msRA=u$h9$yVEK9a#zR z36i%M^^nnaHFdk8H~Jt0cBI#`a}FMj+vFXOytzj&i!di`hVcvO8+I-;D&)^Oc+tMw z7f^%`Rr`7^RVmJXgX){;vInUIS~^oqx@+%gniS;3j5bUy=?b&X$}QzQS3Er2J@O0k zi_y8cmnD4xd_3{aAPpljo*olB`}l%B0)~zBnA%#3ZaryBuqk@3oroyz9uwziSb|fd zAxvu3gqhBshtyTAc)60#VAGBut)-}=xvYhR%fmW)(D=2<%7wO`GW*@czsiMe+Y{nl zV4^R2{Oh5EE`gY$T2t@99|k7ylNCp*>O|oRds;p*3FTM~V2k&wM);qA4%RsVFOcd0 zVeb4ITB#-tg`M4FRPWTdyC#hDg~|!j$h{U0nK&F89ZSbk#V##fZuV0slG^;WWi4G7 z(}eXUAd_X`Lw_A13Cn9P{@Di&^_{qLY7!6ZKy=Zz z_~>$Q(#6^qO=)E?zeZ*ZWUMd;ST~|{^-lj)OnWq8u8Y(ujw22QB1@#ysfTV?iZIJH znIZPVuBSc1WQBIlV^?J^3IjVl!HJq~2R>uy*-jYeS6kaPzyK0*1O(IUh_St!zxPW! zzW-1k!~+Fsc(05#K~rX`%u0q>;#ISnKT4GO7+c$;AQ0pen!h&Gvi~A+5 zdsV$elIcIBUr$*m!q|-c^NGu{v9U1?K|lVySym2vu=}7N$O+g{JksDxbUx$)vu2dpv~nkpgI=-HF^_eD59M+X+q@rXy*_!K_L}z~ z$4x<4pJ1tHw_l$c{dU^HvGn!g>+DP*Ji6^5XT`A?=F#utMI8wh{z(Seo~tpyyBBZl zwaBUG)tm-O)E-`WG4S@8*8XVO=^rg?X+1eDSwn%Fw3CY5u zn`t}29y{T8t{XTDM`HSlY7rmRit4BNQ%9B+Ue)?yTBb~k1=kP^5GaMgT9zt$gBcyq zckyc=#B+S_B*S@BKZ`~~6|*ATSYJhc?%dYDg)i-tT_{AJtV^|{h2SK=k=V%eHLWWWekcX|c_`u(7X;8r8(Imd4q47r z5>6_yLik}#<@7p|&E%w(!lxzHuZhGuDA4fI!_6QY`%vaAEaLmQ>qrlVdDQpHLSodo z4>)`+!}#fn>(ugRC*YS;Biw-*beVqn_f?;U)a5n=Hg#olG)&hXealtos-Hhpi*B9l-1uo3w{pKywR#yBUuU~J+eb?TkUnTj-lrw z;4BW&qv^%!f~s1dUrtoq>!NP%?m6@YOnLLZ&oAz)sGDGCu(c`da$DPlh;ER@x zV8-e7v2feXqVf+o*B|zIY6BD8C#$TwYT+tyGc+MrTE^)aJ?O#K)hyJN5Qgrsfq9w} ze6d9>j>ZCB%SNA%l?U}!ZZ6Ct()>;n=8l1sgYe8YAKIYFB4v-fSBi`5X0QmQ|AcLY zj^NHoD57if^rhk+@1hSMi=G=_Qdd+$%f8RScnZg0EPa2O9Al!fHEs|Nh2`s&6)8bYXiDVSHdsF16Ue z$&lqlf*ms9T@%Nd>PO% zXpq6a*!@QKI`OwQ;$LRQ&5i%_%x9>7{joJ_MZ5?^~EdH{*?Hy^!C@o)o; zWoH*Psm+P4ZE8tYGJDKJwz?v%%^K@!j-|{hCQYT@?QHkxMRcf#?>E{T?7AMIQ#Ie^ zgreR|Dy;eu_1nWANMNgz86zFNsr!GHsA}UHEXI?MfB<7J5@Z^g{)nt|%cGj8SW*(3 z1Q6gLCg+?%BxkFP<(QZplbBrbs>270uqWxpel!h$TR!zE@b&S6lB=#XXOVaiOtaa8 zIJH_=jvb_(-ouYJ7BJ;3iqvIGqNApS!-Lyq%A(`%s9#lg!`ZdR*SZua8hA!KW#nRz zbLAFApOpoGa>R1Vv^RaT5dD!}39gKlM39Gl#KkG=fGrRYI09=;bY<5G53TlRc#x2% zG9PoJHnDW$r)<;lF3Foi5?NREiK7XQA$KYdBqq=?xI)UaA*DO*3K;>PJkrzwwj#qO zY>Aq-VWWA6A)5v7^)nGMyeR!39avOo4j9Cl-DI1Z6%tI%{8%UVz9yR*JlJ2-nQE@* z)aB+!QeooB&9;k2dv6z9>Wc4Yz~?Jn)2?1?_@N14Y5TqFiwlUcj8#c2n51XS_(43! zbSM)KBujObafb?#Qz2<SPDo^!vy>lMFtKt3)03_~JEkH!mM-v0pVSt#nw4fU&cMv)9?g3dhT}T`V zKmO_z zVwO}*BLmWfucqw)&8@G!K*NqjJ2)vl%*SaR)nJot-TI(2PvABa+0F0Q0=0Z7;t~tx z=eJp}eX&f)u?v*{_&n@!AzMd`Ti2?{4~YN@ZRJzGB@4ZviR#9&iF^9!pA12^j}9Rmc` z6Ks7ay`#3FAyFZVu1^vX?V}V-B36jmOO)Arny18PFRugvv+xBaWy!gk^cE3HhA4q< zO(rzp5?DMD%_O&zhZ%@kA&s#8T_IB3wKfkA$L?dhYJT&pip%XPTeZ0mL`hP@jzE3) zguJk8ZdS=)wdq*EB)dy*JFEBk(TrA^r_e$&D|JJDjHH9vkclZb);#(IQC1Ir-R+Z( z;C?wG505R^NHa>m8fvup6n~BK5g*G(8gP5giNjP!$9~28JS-jWd$sg}{FBqf3^{dV zLAKHNmD{nN>iIs0XQ_;_{Jd8(3L&X&y!}J)n%>RO63;qYm8bWF!1_|E1LpTr@b+}T z$}Iw|T$~Jg5MPo7Ir_%cnmnYQVyvX8OFp19TvB%hY65<^@!Cqe6uKfAs^T01(uAx! zwpENvCwLe=vsq2BEYVu;uK31f4A!U0JlU){r=)M;Pi9Ym#ack)f_sX8`|N=?WDeb| zIm*zOvPj~~I^__BQL5^Vc47v_-?$7$*~*OE(z&qP-VV1ummez=<|cC7=g#dK1)GF^ zwYYK=(zw#c{i+yoNwWG_>_RyzGwl@x?_ob5mZN;`A(>!AAcsz1fG3R3?12EZ5JK^Y zTaSlo>RMLje2dPqUvQC)iJf!kc^^((ltRz%fclc>G>Fw{E1{v9)*xe@5mUxYdpTe} z$SSb7ho1YGcL2G1wj4F=)DcpAc5BPjTdQ3`FL_|DZP&G%`b0N(&Ar}D)Tu~g92Vdd z->Z4O)qQW(?pK;KClr+r>ECE3C+*c2s|_zR5^pFsBJ*_OE6d^Xo0UePtArp|T2sdd@_=aAiC;EbQm*B*Ygp6)#c34tG;=?VraM|a$b?LVZ?q z(ml`W?8Z4dW(MzHM;XF_=e!M_S*RpU|H`yrHKTRCQdnh)6h2wXX+~WRpGiELm_NIe zrDTOpmW5(1@^tTYHa;!I-UQ1*5%{E1C0qU{^tfoc8>$N%s8uSN_%` zk=OlaE&kLWx!dNa%v^i7YHDiw5XjHZt*A!dA`9L8t>RX@x-JjNqR`U!2K^V3Ih?K@ zE9V4DJq%WCyb_WwbtK{WXcR+0#9IxV&vIS<)cGH(M_m7Jd7W?3@~f+Cj(WP4hwo>Q zK@$oEJ}=f?Z}O}k&4S&Y^lXqlME5cT6i78kxz%G=Ur(NQfnUKag&S?e4yHQHrZ47m zIo15aPtC!z@NP4lr^hoACxRBrQ)9zg@JtDCYAs>^ZZEVdcD;B-{}Q_L>)5#Z6o4o35Pq6SNJ zm+$l*rVlRc=Z zH$O5Q32+iF^wdqSb)9z-mRo-HnF@4QAX$0-68tXwXimlY#z~CDn0?y;EwInE$?xJt zHP?+tzkK-55C7-wjlUw4JrbMB@_w`ks}tI0x}Q??qozOZCOcgJPFFmx~6K%Jb#C-+#njkNM|0e-t7?ptVY3{iIR0DS^PQ zpr!uy@CU@PR1$qy!e;dUVDG)dn#}sWU#2(~2HlE)Qgj9oB(za_AEgsRq=e8>ib4W} zl2Af>EFgp?T?j>iKuAcC4hdxx=~7dW5_${0cbGT(?DEXnd%xFpuJ?V;bX2wtlVp{)~|fN#dg`8m>ltzfllAZ=E60dF&i?8=6BjNaL$V}8dV>m?TCzH`9LcUOsVjd?uyQKQ zWaXJ7ms&Gyh+;WusbuVz_g( zIq_qP5t9j1R1!hYANAVxr;g=sFrm6F#$~NHk5Cu;D~k;XEkK^@hA)KEd6ei4Lxu`c zHVDcPP#D>hx!Bf3NZYz^gl!tF?-W&QvWySKI~?yG^~4S@ZT5`GEyC zLcDE+<`~Xf^lSMtVbRGWhW{gS`kYz(>>{&zNYHxFz|t>YjNg49p^z0FodD0Gdd5;j zMfJ-j6*M};U%pbGzP604vZ&{iV&23#qLyTJum!vR~oB97!9ugEbJmN0&{ar~1rX;B$JZ_OXYJ5(Wdx=filvOATO{p88y^bXhl(iv`ua zX$kRz5#PfoMO_{HD-cglv>Xdt+l4(FvqbM!WgIHs?xm#a znbwd!cGCR&YRyF1$3{dA8r4f<(g`Z2EVDE~FsR|KcRN6Bdg2x?SH7?a?SKxr`r-Da zkS_30MxSuZ9|iP?CI|Vgyu-K#@!MB^?i9GTJ}tQqZ@y1B0<#g%cC;h^%S9RHex{KbqxXM4dQrQlDwes@)wc+FB zmieBgngBsZoR_brX|-w_H_u#&TWR6o)X<9vFRSX-OK)w=QV>0Vya>Tv_Lo=v;oBS> z3-;lV_|gP&zn}3K_jjeo$uNsH#DFMx!*;?QbOlWem$IjcnZXtl)`yruSHifD=) z&1fM;JZ3x&{;e?q)(xh}kLngTY>1&MS+FH!h%F)rS5w}#Fv@Uq1f4j@_?0`dC`rN$ zhZIux2uN;a2YZ?{=nhlS%J;DHNr_FhUCq7jxPJXC7JOrp1E{o`Pbl_RzrH{8DlIi{ zVDjKh@(%0A9;y2ciB|_sp0a(ZG`e~|A@{skcIW(DLN1@)N>ZTTR++8XyXMa_38Zg% z&!#f&wm)$OjQ+NSaW&ZU;t|bXJrFGB{cv)_S87_XFB1lfnOt-(P755@ zd#=IQLY2KedkIRCz=& zJhQNqQQ$r{HsU*xU0Ar0cRl^L%JxL8ymD_>qoL#UoOf6LXZwxh&ofM`TMMYq2?hGz z=?6tHy1A=DY57`q4}3DxcC{h4GD)C|vBm$kxZ3{5iOq(W73@OvR6v`Qw19VHXZ13{;u96-ZHO|+_hz z3V0iK_dP|!^N%VTCc6@>6f02C?OjKQn2$~b7eu)~4Z#_E6zZq(-53^iNU~_#6FtuG zRW#IRsDMO2*Brkv-g+)gKDp;{)}YUanklNDVCNfotkI(}JMnzbf~45V4i*EV!chss zff)R}i0{!k;7hi550dLE2I+I2QsBqT`~a_kJBISlDJb}@Ae>WC3vngzXB7wEwo=F*x^59B0S~m&O0;3SIy8Vn-1H%53cMX) zdmVR?yx)B(%X}4oa@hrDEj%9KP_d&&g&>RLPT$3|Y_UOUy-r9r%E@$fq^!8M;rj)% z#h^9%sW3`Jz^H0lspDX7j-^)b$Rv*zEn=`mv(F8gi=Jn+hg&&;wl6~}vQtbSC$rL> zw+gF%wM!Jl*;FxLiv3>Ev>4liMD>teDJ@NgcY#8BN>{sT!%^CuU zFVu82`P`NkmVZC`=Y-8S?nO`Ex+EqGMe-4xbd9fAyoY-BCN=3htJ&vus+tPbfogqD zL#VUna}yN6alG{1$&|r~hiE}LZx7y+((JLNq(kM|&2@&Fqb&c|moyvahJkkI1D_W= zjNgo~HP*QdcvjPNehIc(@GQf^tfGb%QB_fGW~|6ObH$lW8|!eVblFp4)x&bWxI;>u zJ`pX{wtYU&F}@aQ@+>B#&wtZze_W}dbQy#W8?@!b9q4!rhg~Z&rMEh=(CA2pstFJ? zyeRwoo6FjnPe%}*pEg&*KRpPo9}~lSDq22n6<17BI_YyX$gk$>YAZVS53)ma6|d`j zcavWMO)MMqLQ-c^(_*_m?)X(aYdiC#?Ue?_reuyaHfDDj3hQhP^S^Mc$bM-*Rr_x1$M{}2 z=`7OZS^1V0#9^=*yLb{miU=f#fE_+sWz9)ie6CLwQHlvNhWLdEYYOCXi`e&Mmo5j4 z8oNX)?$?oTU2;mimG5)@6K6-1+vBP2_h$Fa+VPKj@Tc3UI;Fp#>HAO5Ej^p5X*mTl z4H}%M(}n}D*y!IOCoznRwF$?q*H`7d?g*ERZXKfHGK6YN^cx z*THJIp_~~`jS;}Bi7DHWc}#IHK=18x<_P7-T+o1R!vQzXdn5oG|dGGA%d->Pqw z0~!*?Q7JQb$*S;l4i$g4vV{7#Yqhnia71`c}H@y}KyCAH6Pzr z44Y96s4vR)qsfL^?++QQ&gW>LK#VYOSl|PlcxOTGPA&ZnAJVsn} zjB?LN3pF(=GHB$a@~zL_5ji)-dtpE$e-0&JlAS1Fr4?6a*_LEznh44**Tbwq)%eWp z7t{hEdc%By!;8B$2p2N0bi|R0Nitu3Y&j>;C_bG%_VHs%aJx1f-%g1?D+bxparOMn z?Q!tS;K__zk|#3{2iGkm41o{(a{AGZvxvk3H%r;GS%*KlzB~0Xd~1iWSD&duqRcui z+>^xX3eX8DNFY!67AL0{oiBbRj(}D7IQ@Y$ zDw*UzjUR`R)xl(yP;^#Fz@nAZO$D22cu|xUG8#jySpk2BBkfM5&4-t=E*JZbNDu?Q zf!a7lt%3HAYqrasNhpK)$fbtbs3R5&E~V72HXU}hC=vL)%0uP`fZ4WOebjVO=+RJq zW7P(saZpXetYOu~qKiNckosjKc-fniGiAZanfjbk|0mZ|LVKAL<C)tBv7-9#ayzvjc2x3V z!)9ktT%eA;qeadBcv_j8)*``jdR%bk#uQmf`^v`BePk@Grs~cm z;uSP_1M$^tO`tI(tMY{SC)a{Cc$8xIWA7`|C9GhnS<|Xe&a|PL6d&(Kfx|&e8L;lz zAr>BBSDHsfJc>X``#1r^WEaDD7PD$BBhok<+3wEn9iEA>BkEwj!ZYxvvwy}R|PIDkk%uiMpH{0oh54mx0?{*c4xjP#_pXypr82|&)>^|-WzPRPJ z%O|-Tvo-|?Q{9zEApdy_9}|O??D(SZFC+tN z^+PZyVzsKWKlEd@U(93(`}KsCQVe}bJMdXTe4M|-Ky@}ge$$i1aT7@Xpq*YEXfTM2 zRGUsS$S!D!O_Ut^qY`j^!AdD>Bi%ea_X*b%fxrF7w*TdC;-MjztylUpsAo;{{Z40K zYv}$(_Ovx`y0NSOc)VX5RV7evG@l?D9|FAiddhk{XL{#Gz#VTdKJr+r>piiwZYE(t zt=F+ut(POJwhGanRH5V!E{*hDuycZ@vRf8gx2&!0`R@--WwbM&j()SV?V%U^h@Jm~ zYvAU8?$Q5UMWe!Gyhpmf;jF*xXpnW(=cgBt8}W zrN8|o4f-2B~9O$ORBt;#gnNH(yjrSCy-0o1$Pgbp#NHzPqm6B6NB39yy8Brk(B z-_F9D44LbhZh>nC8>OaM>bo4;i`uE(j(_pXn3E>RvD-$kkBo--W>$lSX1n`(0Blw- zH<`0Zga`!G^C?@^3y_34)QjEx4+hm1^-?ho@Y}uvr@AHO_tscmL(x`bepJByX9O+Y z2;QXSp^=AsWlwf;$R>flzJ&DaGm$bV&7!QGtwp%RkSS9RIevZI`RKO%BCtw5vuNMw zTG1%}2Fo5eEG}SuYoaYd>o&DiY&br#_qVh1M{;3Zm&Hl|RvH1uFNZ!i>xy~v-7A}d zmmFoR0!}O2$BEPa%O{e(m7yPlPt!i@;) z@U@SL&y;mkTaH@AImxqXyJx%$Hch_=5)QJDI1lM|>BKLg>sJwT6&wS%H5R5b%8mpO z`>59;_sS33ZZrSVD`O2tsA*Wl>q92ut;kZ7q;~V?&}Eg5%bWaXcJfcdr?#8IrO+G= zb`H8B(Auz4=yvwg)2GLj&sy)koy=TWzMj$u{jxB00M2=K_}$;X!QcM7@&6w7|L;9; zH^Iq^63;P9o+Cgcp+KX3)W*1}p*QxWD`5axlH5|gde-kKd(`?Vvw)6WJ+=(VA@g!uqONn%B3gg5pg04ix3c2QVVvDOig-{L?Gl+vJq~2JBkN=s@$)oeF2bJ$xfRI-=iuy?SKm$gL9cQBKQ{ZbprLE8wu~+KD^@EYyUv|Og9?c+3s;`*&h5l4| zp;g*@V^oW8v6i;AdPVWAba1WZssVMA|LYHdcz9a1h&l~aa=pO2D4*%KKi9C`E__?& z$(I5TLB1s@IBqlV(-SV9U(+vuEmU;}9jw2?6|zhAztltTO8^&bneDd*+L$WOhysXn zB{LF#cp_Q0$A+bAG60G{{AO%R`}xF9e(6zjO2V9biCm}&WBjBaeC7>W;1A8*|ET@5 zVxVco@-uj1(@Cw+BchVJB~)p1TN={DYZlXNkSIM^7a%nt#pLa5b?Ugya-}Mr@z3mZ7DX!`X^j*=k4AToN z$l`sq=*83Z>LRMunbIxHxD}5#hGs_N#~re;620bnTnUa7_AtmCDo{l|d47Wbz-26M z$@0U)OF2rfDO_Bwa{t=7|Jmg`2i5)EM#d>4{{*LQIvYrb-aBSHVSe`y4LKTLI$IhD zH_wsu(^!&zce+#7`iqv+H@gFGrx1ChseiSTqmx_6F#2!j?ZtloyZ!HS|0iPLQ~z~5 z{<6++B)R6wl%z+@4b-?;_XMhk?J?{JZskz@5TF?EWXx?OsyzcDBLr4J_z* zl9{+*HF4N0=9w7c?lfgJ5qM=VK`nR}ljm{#2iM5E$$vnr|6=01B-_#D`TEnN{u3Dq zN+utvsR^DpLAvt!GaUa9YvkVy{jZ?WCpc*IFb*0WToLhiG`imZVe!gz@KjNhNmgd& zbu%R=@kBqRQW%H6OypFS%;*4wBF_!x09MoJyFO}=Yt|eO8N`&%BH$rZS=Ne=w%hab z@43vw{;g|&x!z85b5LqZMjv%z`LqcWB zkYF1b+qpO0nKMkv(Isml?t?YaEJw6H-X(4PhcxA3_ROYKhH2Y0scLQNC-x_tWPf&L ziSU;pHq%Nbn#coc%o zJfkhHBfS6QDlSl4_@j0!@l34ByUC_k)xS-FY4qd=tN$c|1U1zJlw~2_8g{w6N612aI zTyO+cM+6QawXBw%f&|Af=i-s@4KC#()qh;`&(ClhE~H^YUIv8-dtasAqHPTFcbV{k zyDi>0V03rZ9Ir5z6#sGU{kx@qXmZwNJImje6W%|8hHBH2=`Op0cQb{dcLf)WO-V^) zh#veKk)mWrpIwz7wJ5f#l49h}+8KBAtQ8$J$jNgj2=JS!+-|h_n?3!Ik$$W@lX#{{8K)BT8n?^&06=?78;mKYuAjw^rOf75n#l? z$+M=Gw@V@cPFikg=6y0*rF`I?iwj!Ouv>JM$`@j>NWCaCTf1}D&b~LT+Hv&917k^% zb?w`H2gxQ1*^@YPjWVKI`!uGr&71OkM9SxnXD!}6xIzlZ{y1A2_%qQ=SgvRoU!eqP zG&jOlThxx}#^HK`hK4%w-m$TFe;cz3qz-;tShTyN=iX=v?PzaYKJyc^ZVW+`Zy*0% z@7un?k*52!jid~8^=&sse0Z7uQyW%E%;hRc4=mB~2AnpR(C10UMws@d0WppB2-8cz ztN26m#qKzBgsO3&J0D<(5|6%5y!%Hng#K)ei|q3YDe2)3XPzx3r#txP z?taQ~n=TPffqHBMT<2Hk!?^96$8kC4T`iUcIC#}vgA|fQHRH9_FC0#QW$>Ll*<>dy z%8o%oXvC`Zbo;5rhHeZ2xB0gDrk9eo(^E38^C2Y!b&^W%)g{w)mwV*b)OnYD18Jg>d^yH1>Q}D z9FD70ii`KV`nc*_gjp`8YqB1DdCWRLor{o@|ryam>Aq#GHe@5+dblkyEKcrWty1}jyQ)xoOMJ&*wFolS;99GtM zMEr`STq$C*72r8%m{WbD2|cR;+9#k{r(nRgLC3o@%T>o1bV^xRt&aBmYEe3YsMWQU zHB6RT1QD{4uE{zC_o!Ps=4{EcKV_Z#DDKBHyKp0JiX)T7H9VQWKT z9&4#G5en7|5-Vxg-5td6D2IeUB(Yqxe9c$)OK)(#;6nU}SDJ_RZ^w!P+>zx{Qwt^j z1c3D_&L6U}6rU4Y3w>^z4ZXOb`(`r|U+0z+BSIok&0Bv2Zr5egr!u4 z$lSDc)V96qLX30uX^+D_5RmUW-OfQ)XJHV@DQx7TQ-17ON!uHs#h^r&WvNtHjXZPA5fG7eQivTfXrv({^pl|-5|O528W?0_TI z<7RZlB|y$4bCO8M8t_=TK|pc8urOCB^k8>`d^R%uX)x{5mS1+Nqa!qumH<5ez{z_J z)8mjiB7f=}HLxmyKUw_5(L^a(OzVC%#~s zC?{C|VJYrrO;$>u;ZKy9 z^Kl}fy*psQA438Zaem5vpVCOC)YCM^J$-SFauG3zHDO3g1y+nemWXhK<-RE5344+oRmpv!G*OAu(0j&qN8`Z1xaN(&suTYa&pl04yk;52*jtU zA{V79a;am@dTw0Y2p8E+C&MJ=dRd`-Fk}0tMRgkA*OPOGZ0~Lck@(DAubDLOb&Aee zhWf5yq8Xg@i5$w_2f;vNnSgz3pRXDDF7SfVk`K`00d2{9Wy7KPgy+zd%+NwsNru$A zrlgbH?%mle>IKxJ=ry`O`)YSHm6Aa`iJ=cFC-;tIiv-u1=B|0H8<=PeBm}u>;yM-U z8)_eEc*}Xh=w1)pG!Lxds-6Vl-)vPY%V?SN1DZwc-tEb31t%U)A9ekb#hC>^|IfRl z87b}4j`{l@V>e04yzZ~e;8KJwD~naXtW3eACWj#sXAG4`y}vyCX$^h)5O8(?JNxPT zo-ET&!3Od!7At9xZ3)o1^qYy_;s&nQiC6w%jpeEbV&F{t-5;p-MgxJC!S?Y*^^*jVPD2QKbWV?XGKPNc!hhRNa^+B zF9E@GVM5PJ7Hk9x;AzCkEmS_oZra7QVvOk>X{otF!j#0Jj6(T9NBd(afFt(^03fwE z5pMpbKF09bz*83&FRM%UP;OS1`wNn7*5k=Oz>_-1aB&HN^2Q00Ey<{%k-;Y;Uhiig zI$KbDG>jZ#aW}e-`0d&F1Jpg5#p7+N=KcWw&Lgov20o_f5%GEA&}sQSYJhWAa3c_rm$Hv(MGM=Nsmc!{K~k<%9N8 z?s-CMR)-~6@uVipVWOA?YD9km;j@tMyfM|TBhd*;d^YGg!HX7LKuIRyyK21Fl$vCF z?lAj2%9RPDiT5`|fNY`%C1oR{Ta0}CO%zWONux6Dr-@snvW+xp3BWU3?~YLxfx zlNai)rolN4o*crwx;Tgt;xMB-wg0gCd!T9Fa20b@EXO9*s*rKDT*bfSy``mh=ZS~I zwc?BdUsdu^uXd$g`B#Pz%2eN428(H(n*aC3|(9c#FhaMRT1x52tl+p6R!pLGS_% zE~Ya4U%gx5#8AZ{n_pwo3Ab>r*}E6kP*w!QK;<*?B9Y>4n3+J_%xrN$)ohmxNjrj` zl5&3ilS`8OL((yz)Ir?0!g`_$LxSid%*nmOkCQ5HX_Qvm{P>QU$mXOnYY}4X8Ohiz z3FC^@9-*7U$y!ZI)rH1im>-wJgK^2D3XSIotukfg;3lrVGe z2Um`Ge=wgO={6rEm5laXO-`RC(5%PpXsg)anYia4P+1`(JC>4Gk*&rcw^FzEfluC( zjX_1m-d}xVO>NwvB))l!;8HkpxKp^)uv$3xj-ErBCQkY95Uy^a&)eB&w|yY~Y0$xF zT3H7MpEm}T`#Z@C!>;*QK2Q_I6n@XvNAr2e&w5JJQRGsBHX`_FI<|pJ%|lc>TsORW znkgM+975o*orXYn93Bx*E_`G7XRsVnD%;HMOzSp1zL1T54>1*aH{0>zvuqLJyKSPU zmw=k3eiVplwWm8)GPc|bF_S!})%-^Kz18DSJ;o1CbBc1zkN%DG@$E)$*w1R2}ojfx^!c~eHS5gZ>67@-tP)yuZWZNd{}cJc%+4DkRPHe(|O;qgamzUbTfh1Wd{xgps}NQ1KO*0@^j;9;eP0a3kb zi4xyn3QUBWL49%%bYkC)`kzwl5d)pE{W$0YgH)etn@(QgiCnSZAriEDTw!UGSSt9U z;9HTJKkb+%%TVEtduyphF9-L2NzCN+5S%q_7DOclWY&|{BIjTXeekg#D%kud(Yz3f z{!UDE*bsKoI89dc(`rBpY*DwmH&W&98fjSNV$E!M)ToVDR=quQ&8r8r-%u=`>uBCJ z8+yd@ntl}>G6&mW!+`vf-Wl(KIgfm*8SOQKV} zFaEYn>{>l%31L~RJUeVsD7NnLcFJIhy{~z!kY(e*Btw?qg7jtoY^tazitska-?|{e z%>4+Grb>$&j1tSLY;&$H&h8FT^FU6?8H@~$AYHbI7*Z!$E&LLDvR($2W|dB*Tq)@~ z#<E$^J;(CcrR3zXVKlCMEaAo{$~-e!Bey`cLW)h@hw)+Pvl^-(&D%|hiT3Sb5x z5)Z^V;UmvvIf!BVtwnsi_5RB6Xc>&JFN)icA9dufIUbDhi0;JoIi-v!=xj()e_(?V9IJfyRrnyP5`NiMj+|i@u-!Qv;jZ$k?uR~R( zq})_8C3}I%Vcai1QmY`M%ygpUDvKG}?N(LIk(iZ=)sRB(KzMP!N!GVt zFh&#`Y3KMQru5a=2889&ZRBFmlU_eBqy7_rg|E`1c7b)W&X%U%Y_91P5VMpIWb|O3 zOeOV{FQM8>jh^)xXAXy--<_!5!<#q?+=Jnq8-Mlc(uW0*84T_UK|$u;zQ#>i-D-VE z+Ki2vF`i;K8nbQI$0s~>GbwwD0MO`ZHSZN-kGF-XvQ-^?ri*n_%ti7wwZ7f-?|6dk z-$kv(R~ESGu{PVd8@Gf^#xkB~!6nz(ZP<5PRzX9v|;iU|{D>{6a6Is9}Y&b7yT z++eG~q9bB_QK`N*3{0Z}bGp*1){7xqVoNtB&JI6*941Lbjhfe5rc{%R8IO~Dm(tWU zefuP^;H;^^3L8>{zm|l>c&kx&pmdaN^8QYq_e8Sq09nzi=eK&XoFoEMfIyHgkcUtB=cr3Tqu0&KmEkw&!z8^;PJPt%j07uXtb=0B)c1at zq3lM{fR(N`V#KxjiMUV0jpi+Id6;{3>0KI573|w~qvZUJT7l;D*#qA`mHA1Brdm?5 zInJmW%3n` zD~-SZK)(9^-|ca6_1#)IKREyH_=vrMT%f+lvx|H+!AWer`F1n#iC}X*>3%?W1=Qgx z^iQsOTJHEyd;)K{f9f8Fatb&99}g56PX#_82{%Uk$pvxO(CW?(!McWwKKzr5yXLqq zJk__muhjAwJkIqKz5OrW_kZK|`)J?qS`!Kvi}_SyMfgAt^R0aOHx^|swC#Y&S(%Nz z8LkVKYzUv30BXf_ysY^p`}VDRE6|g^?Neu5#prCkIn!R|DzlS&STDH%_a;AzFGgfw zEt=uCMx0U;KygvHh$l{)pd=63Fsw;cE{msKt8;)9X;07S2PLtE0pEs7wmQySVHzcB zfqnph=!R_n_#!f$-YxQl?+5uX0U-M!L*5|AZU+`~{=*UIh^nS?c8m2yAgJK9KXz`7 zRzgwXA#6J6i|D&OeAI=0(>AQLdOc=J45G5?I3dN_h-sCxD9NC<#V?Ccqyxg@l@<@L zmRuX+sDWmR2nNY=iaUs%ll2^8gB~oY7U{Bt%WpcxAGH2*Ztc7nQ9aFhkVms|NkXrI zo{n})`&f`f#%Ds)@7fYiBpYq%PW;DZ=GQ0AM+j?L^;^P}GR)bE`fN{X zWgIHD-l1TrV?e>k90W3~EVuE$@$>%YkNz(NE4=o!j6_tRXTt_Cgozu0)*$ zgWkJuX2KSoOFHQpw&#Gg0(P(Am348sbODKbl^K~jB6+IyjvT&OsR`7mS{fz zg^TCuTk~6N&h&6eJmJvVKP30Q@%6&pl=}`={MBD5T<5J_i5RYqW?yK63@tAgtT0#z zl7rW>m|ZcB?2tQMthceV0`;TBGi*=g{B)(q>{81Jc-{JrdtVTiC$>)=53)6~>zD z94zZja(%DC`cM}KW0&J#gtFn+aqpH<`T6-T1v`)$Hu%mRdl9kBLA{;fo_Xhj6eLHj zz+8do1&TEOX5&#cCuC=X2(q5Q`kANZsy=^nE*mXy?qdyYS>KB2XiUeKx2OVd7$eh$ z{!*|kZ}ubPu`x*F>gJ=?_*Ew%h_dC0p;|Eo9_ayz{MLKUZHGK^^oF5+MGvUG#leRL zDw6#v1Ei%1?}8$+Q4qnLiHeOkU?~Zv_}P4hYXx~d?;plKMM&FOKh9Gv)$~(X(5u+n zK#_+Ha+Y)fQl$cE3Chqylbu|u(!1r+A*_hp;)vxh=p}5}F z+OE_X2N0shGzF}|DLQB9agM4(BW0tmCl?xf-?JTamvHsz4aa;1)Yi+V+;jS_{Tu>` zaH(a8%CO3u<%H{4JjtGSV-8m4_UX4^7>mPj;e)j0TPKAvrT6?o5?B}G*ZMu%2CbrS zBpONRbv^+QlEBAN4VVY1)+B>V{ARu|Ie}Rj(M4O;I=7h+wS+L?n^!k(M!5!GhQ9MX zmu!%9gg(Nkqh_sedX=WbORg~a4conHd`Z(%8F;c}`vAYY>>bIUt9y4CIpR=qf`Ht8ZsREu!BswdB-gtQCuVBg<*l*Rnq^YWEqX zdVYYL+Q3XeO}T1e5iiEBqZ9YLac35Pa^1^#J$*Aj%jH&)hP6%HY6dlIO*;<1`Kdo5 znXN9r<#?q(q_NR8#BH}b?5ZO%x^r(ComxQ2xCp+1kPXsQoss|gmGy8i&^vv`@y8j- zTwJcBf9>5rxh~{V!>o^?h+f}}zfIp0xlWV0B1c`YF1nwp(!CB`JSsD=1k#Wdg=HJJ z_U};}uZHp$v0^GvJm>9e2X~f_O$JiZg6_6oe5xdKU;}^i;a;$Z24)A=TKb^o)ZrXx zEmf(nVe)4eNH0q3)77gg5XYd4RKtVDL7DCgwU9YATun<@agi$&U>8>cZdiqhO$gQp zJGKJ=wQd~#y`}!I;De?*;fq0^QNQF>E(j+;?lvKMf5ULakaTxQjilfzlfKrL59=44YL|Tic{>q?pRqPASFV z`ubz7OlvZX%^OqsR5!r#@LvoE~$kk#8n297X&n zT_0(M^h<5hNrbgp1cQz-T=sm{KT1o3)u66BW4&6Z?zGk}D!34AOik_)`6seTvFNhN zWz1;LsMvda-u15ZBE9qrwNP`gyvdLO29G&#)q|&m9hyOSKYMsSosNAoyt-Pi09gUW z^voM*b3_vu&GshIJ5K(otChk+SLs3un=7>21=P{;*$7?po*WKueamtQ^z+iZz>zI^bzTF99Jy54T*C=bwif?Y?5ZpvBUZ zxAOl9iWD-PZSr80nad{COP8Bexo#;S{me~C2xayV)y=48ODr1~^Qmg#JPimeeJ7!$ z|EwS+Y3qItu}3;d*-&c@;y>g~8Y2`Bc5IF++dVC7yAR-J+R3G^Y_0pHjCpUl94XSrH z@YR3nnpm3Lrz0%}tM7~F4Hk^fff2r-z1DJ16$g0a1`g$}v6(WXk23V)s}Vc)9QUNy z{2XXLsGI%M=(p)iWn<{gFm6 zt0^&^w#j+4&go`LhPZjckGszeHX1c3-~1k>(-J3U>$QuD?BYs`cPxeDjq2UPJ7&H6 zOhNnl5QhfYq3O-aFIHmsgE?(1yAfVyNrybDAD2`7>PKs1N*W5guh#fU&wH;OUFZ1y zArLbeZSbe|D{2rXyyw}45%sJ$+uiIid-{OdxK_SPQv9D>C_IusS7^t)Gs^xWcfff= zk*uw6qrT5UfF8>@v{v@^HnNF3D}e)P5#95uzY_wj_&8)W2tX~^bQ*uQ zY<%qbeXvHK)&lZZwRIcM3A;$Eh1shs3?Af$|ChDO8PWo6GC_`74=^*9+OMide>IYN z!oDqO@MXpHIiWrz1OhPyUmf(48cGz%$b&Dk_&-<;g zsNn;GxTZCzg-%m;u%#713kb}5YiAz+$fMxfkf?Nz~loYrG%Tsu)`gDK? zMCpm>`WWqm#1Ffb;_&HN#(bKH#j$wwDubE?Em7~O!Is#v)0OsIJlyGVDh$2p^i#Dp z+>YC8T7r6z95BI33C$I3 zco=fKPlj>LqN~+4sRpX%AgD&H*nv&RBW%7su?=~{j?(;U@l)lI4Lkw*^_$jJnNh7} zYDN}RjTPZp1{sm%@m%g#%t8t55sFUs{pHUUr{=xt&rc7MsZE)yPMhcsxADJwDj+Pg zF_YGpXKDg|H%mV{-|pu4Je@{=@RU;asQRKH6%E6eNvoF) zTOD7x1gIgBVW9lUxWrs_J0#o80&tL(R7>K69*l7mitstlq4+Fdv27Uw!ztt<-5F68 z$hvupoZud~I-9NpABnB-j$X}ho$%8t->_@JVP-^nHTmGKF=HzU6iV=v{zSV_PS?)9 zFedUiC-50+Im9;W3*4Yl(6@-8)qb<>w*EZ$9-{co`}~}o)9fV!M(bxkzm3Y&32pnX z>d&SipB_~z`KuhV8^qZ=EchY;u~lA~Y9sWCYW$Fj+h$RhN#me=;UnF(hKcX3yLbd? zcF*4T5CTpd)kAZGgdQDzTaqx?G3IqPDAYXV4R8@0FOqzoda5L5w6hI$zq^|CCK2rg zdT_tbv`@e9yf|hY;xH8gK{uEXq9AQ74@ONm|T{=fIb+=`%5I2uvLza=4j##x$3RzNVn$F z-r4~?Ye&75KEJF`!sKTai6={0H%Th7OkT@BWX|L-BdZ;H<}R+gkTe%ITc#G2htd<4 z2Car$;5UD9;2I)*SFuQz_kQO4%H5F641n@TetI^3j_9uTUtd;MkR{(ik@(_11%B%kG=*i72BIa7vJ zy?O?TPv^Up$q!e@?oVGRp#a9rIERGprOQVSLNrXgf_GwHBJy2|i>u?`Z0l(O6|R}h zT84#rb5})n92cIO?fsT5d4pE^Eb(%SS8m4eqB>ZYh8zTT4jQpbOZ8e+WuMy8+~FZc8aFKJ zBilv?nGM_+z%}C=qM_PLH9PFz=}(0Lb_fyH=a`8SERV8x~w8q)=5^jEBD^2}Ry0 z*=uYU#1b$5^I!$)2dvDZI@k@03GVzZ&^%o^U1fjrey4Cl`F-4xdF8 zeoHdH6u^c88(FzHR8k9r+ztXP}p>Jd{gx{l023;OC_#<(QA{yTqw0qWcd@BAgN3 zQH3MLF^KDGQoT>qeA|+f76upgH*X`14X5ZD$`fYNn_sjJ`o=gwCVxS}`xm#;|ALGG zqX^ts!5&J)YaFP2DPwHc;Ot_+%@bj*kKF>;szePC8_1eFBybe)lDx!>4R< z?lAprbmOG#3%SzOyyw1mrts93bFKiadX3&Zi-FD5KkciVu7G?Gb-7rGt2^W~){I%_ zu}ClMDBd(FU2G2(bhvt`5j6?xUuwDhvDf%~TU%g?ow+~xVeKW#JO6qs)nH?R9paP< z8<@ERlZvZ(wP(g}RctX;Qel;xg5DUi_9S=`;t&t0x0A9REjhj!_+JrLe7WtjlL72y z1=$`Tcur18p&SK`y5L{U&Tfx-uLsc$K>Fi9NR-l&@IpiRb--F$;QbiFv#{AXWmah_ zBQ1h_Frtx{*iD-cP`Y0$s2)NTNRjn^vN0VipU_cCT3ZQy@OD_CVtHE_mj01EZO*e% zbHd+i?5~91JA}$%FZU!R?=L3ytTV! zOVR{|%*;?AZ-_x9H9u5asRTCF`qCM?4_edi)z9{@OqB{qG7RTGn`vYk5D+=W!OwZ; zU%KCadXu{9@Aj%??@{%kV9JG@t15YTf!*S)lIIf##SXdc>8V&0=-z4ez0>4rlWIiF zzQ|XOt}=ztb7#w~rZlnULsPaRu3YBQV&OjdHC=;>mW+jfX04>yV`=y66TpgVrQ# zmJJGBYMWX=w~RcIR8X}#xq1{zVsb3{Zg#-dN^C`(p9B#zsz*|uc;&YYi8*3Xx@Wjo z)^<=WOC2M|pr|AB&7}Lw8!;sUSp{&u^<+8M+Fp1iS-h%x@Zm`6%8=rdW$v_%d|p3q z9(D3$+QNz+$SI$34dh@k;E+{cUp&kER2UO9MW`>jBX`SEF;2YucyjCeUb@i_6rGrNtt_7jO>M1`wubcUzZ)k@e2qg9D$?$GMUcGJ(88HkNK z{M7u5Y`M2~n|?iE{C2KeO^pJlj_(%-T8BL2!47yu4{#~XKjx1OqH8ipEq=)EF#LX# z3KQ${q%ZquEn{_0JW!Fc+EINJusYRD;y6Xf#80Ua)8*T@nsx_LtTK%>I)9$? zH5%uGa7W4^%ga5&%r~Z%_*%g`Tq1Al`XAH)#(dbQAF#v24q(f(vdDzdp6a&Do4qjX z+9Hw1r)Kg$-IxAcz&|+K=3k2b$rPaG-Q@qn(I49w$>O^3yGv791GjWcb1_RQbfl#> zneW(Tdw3qE+LvXki^ zbDXJE`jg(@d^_V5NAIIdZ5rdNZlZ~*HwG&HkkVn{*V2p!*Xx#W75|ek=8=c z(~I1(+IP+9Osw%)1VV!K^mNALE$|kS9(uAuQV!5XJLmr- zcj&AFnLk>^acDn>Vxq8JW&WjdY)UiDK-PNaIRoxOO+(g!tKX!9SD|9us!sJ$KVI-0 zF0@haoo~spHw3ZU_3rkc+VyW8axQnY;@7Iy@ci@AgCSxq=*IMEqhpJ+`LolsJ?NfQ z@>ce;X2!I+eaCufwDcL~Y1{O>fTQsUbYLO&aO+5Bs(YA2*eLX$Xv*K;EHsCW*KFD0!xn4Xi)_a1l zjG0&v-qM<$nCLhmIO|1$>;XpxvoRyOJMrbXSSOET-$Tr4HD=wt24x@ui)rXu+by1T zs))R>ww|$YN~7tr0xuoh@MU>BpN=Y`b6+e)?$sU0^H zODF11YBrbek20OkYEtIHT8YH;Bl~wP2Kh&J)?Yb@Js#?e-*0v-xX<3I817Q?54MW<-o?QTsDVtwhZh~@0guDp6YkiO4Aws%Hj9V z%K!7t|Fhfw^PB(YfcMYQ{-3|P|4RRPkpjk`?7;xma(U!gW@y1-A}Vp8+w#;c>CZ-k zNHhO;lX8#1D%gt`J_zjwi*HBW*5$f^9XXcbcQ(m3(-li6#59CNm~U1Mw|r+c7YX)P zAdIBEQ&huXq9Uvmj5cA{t-^nEEM?GJ9LT$lP*KFrt0$ok);#QC*k#1oM1k|>LzdLc zfte;&Ad`IuozU-qr|d0xJ&=8{N~L<4*3?Pf~h8JgS{ zDrH9^UfG^`+HtAIb)MVKrrPF)?n8sqg?UHGd7~E7cuC1c-PvoMV`H;VfT?tIV?} zZTIddo%rF(2k}3|EqZ^zqL?OmV9S7@ zI==^BIWAe-?=aQ_b{d1HUB*@J>vNo+w=_1k;~b({g0xIoE|mtrm~VDO$~lfbJ(i`= z4?HR!V^TG*^KhpgKZt(wKiz(R>%o8UeE725#EMV##EL>lc*C-X_l6hkT=U?{QsDk~9v(2F~60S9DxoyGIV1w}KU1wF@=w>(7MAC}eCu z6Y$%?5j7Z?TZ@ojHN29cjW%G&K!ZB`V1y^y6&AccCtiE=w7um8!lG~fNr_-ej^#W1 zeZmbiL*QdW8Fnbl#FgVroWuX9!oPj?4cUKvB?5PZ105Iz6?U$d6P))3TX~-@?Eg)i znDExuq>agzUB{(@MOaHy3w5t%hvQO%{?mV3!vBR=%9HY?&sh55&>DAo^@e*Se@sFh zMUtSy;x$<9oNa_=<4lPU{Z5DG3u@x%XBl(z1X{^qAUSnMo2oNwb$s@XVo~GX%A29q zT{c{1KGTG($p1f{|E0k^)^nd*vQ*p7I^d*2dF4**MOxVYUSA zV-|A781pOqOO&tA3ko{2+Q zP0B!=b6%wc_$ojx2#Z`5_UAn11us`Lfbo0gn*@Z=xKk!s=V!@}Jt{du{?hYQg{mOs zi^wJxCbi-VHP&~d9s;*b9wr2zc#MGJWrdVCo%1HpJzG)Hl(8ycicv!O)fQZ6SXL1H zP!jli6|xeBj%xn65c;XSlewSQhNl4@Ut$qOKr)41uIle6L;#Ixc8&yHl*Fyb2J$1be7r!*X1lJoszJVVq)30|ePE!cWx>_QMwh;*i@=FGtZZEN3J(S@t zv7a;fOdV6ZBxOqUz|fd1Qx_|YBlTXRF4v^_Y%rjS-22{jYcup!>C z>#20rk6L$N1USy~-B*swL>~+`4pdfERTgL`n?=MfTW3}sNX_Vh1GC%%fnBXu-2q7o zZ-&Gu@U@aTeziP$5$Mqxv~2B3w@t5n_wK~7Q+<$dJc;<~-jQ8n36|m^`F)q0=9f?t z0#YboPwTcZuCHWKfAESwD|Ma_YAmN`Weo)I5pVTKePw4R^Uhxv+T`n{;r2-OvNo9_#xOgR+Z*8rA)?U+t zFik(`AAFH&DF4h^^Q$a&SRkdJH}BPJ_N)YLn_%8eF0oL8K-&m<4n+bivKNk)iYWh_ zmX!4Com&q)uC=!xDc@EX$d@#{xtT~*RyAj*wrNOxZW8Qc}jV6a$={ny*o zonNkQ@2S_oO!+ja=-WKmHAW)RW{9>$@;OL z^W@%P%y8@6(6QEs*kZfoV9ooUyd~vinB3<&3VeAfv@KNT0K6t+1NIf9njA?roxAfX z;?eDbe$`Ov#8EqieQfRa&3*>olBcHUm?uwnXt?^9h0 z;lrlc%z8a)^KXb~&zn?$lv-o3+x&y??d${2m zsN=b}EO9}qp1Z=9^)9E$W;@qvi(HB7h%SGAZLz#O%5<}DCkc>Hn!A{)-&(N>p}SFB zoX)++x0hWkAHVcNQ0Ho1x&-E0tt~^YtxL#g+MqMtVPp_!4#AGV0yKly7`rQCjv9F> zv|hOviQSS<3%ckdRv*j`s%B+uY*NU+$eSCZH2H8}+k)wwnEI^ZT`WtdzP> z-C&kk-V9mfo1~!DYD!%}eu^4FLCd+o9oGX+6R1L@Og z<7|=O%fHvgl)?N>xV1~Z=`nT;Cx)#8)v{#GAPN*H(t_MCIgdNyin-Xm?z)!P7mQo! zUag8yc*L>t8yg<)|Do+XmCAzfPugxemqdD@W_`;`5(n91V&gJY?myWA?CEtSC?w0@2fhfbU$cyrgSHbUsguyjKK# zL+G-(dpk${+V)&t9{5nI)a|HxnT%iqRsq-yG*!Qx$*>O&Ut<&2+qS9>2{2ut!YE25 z<-n?{ce|bZ^voQ^0iPq|3SsUznccs8p9>3s!Nm0qE_jnHYSC2Y7XrpXqD(xrji>HwD%EDu@-l})f zmPL9=lD8>3x?=R5#*K`;A4iGjnW^>P+;=~hdoLf0BYu`hIrxL)+PN9b zW`A**m9g2AkseMI7Q3E&%q-)yK3I6beZodt;K5s|e(_029zHn|z!aNOUTQ#tJ1SZ{ zGA3oA4aNEpad28W=EYK>Z>kL?L#R2DphvGo&=JJ*JW&I}H@dLXeyyHqw{4(eBU@md z@hiq+xkUSIm`p2Yg;w>1xBR+sY01j&R)Gg;V$sy-c2ZV%GS#zkt6yFpMU4HRnP@-W zD=F(MEsIG*37HH3(&Xw%C}kpwOm1~U7O=)7wC-UW`sUjUQM^}7hDQRL=_Rm2kE!YF z3X9grR;_ow)~+MEtE9Z^9#brmRUpy)25N=vJ|QQ>T&pko)NtRiNApt6xQ5eK^4+99B&tUS$=AY2A*C*=ojPc|LX5xy;pdWI@= zZ%@`ksX|-%!<1b_;h^wmV@J}|uVpl{>oV59P9~nYLWst%$ ze+=6QQ>G{s1fy@O;=ulv*G*P*8P%sDDzjz>)U^ahf?BQvUd}P?Ir3b8` zbGgPfg0=W$PB~YZ4AI<@*vwEJ&fP%P?trOf%NgI@Z0c8zvgr|J8vR_IYW8D)efq6D z3$t(`OB=J4+D>XkrHw`YZ;K!NB1PWRyPoM8lKHffm~`?WsS6tLE+7#TG5LPpD+8=q zlKE})BtA!)=LOyg4Y$OrBP|evYl>1tRW0H#1D-zjVTgf2q71-3nb$r;$As|-<9l=3 z+wgSRljtPnN}OV4=W?oNT(J!=x05x~a~OI-0D)GvUgcx#9an`J#wJhb;mFV@L6f=H zR5pguQv#l|2Y#@TPz#zgAZO_P%Po|;PNkNg49iSJNawAW?LK^+$g{PUZB7@;@||N) zGuBT}JB+cR?}bb^7MtS=hl#3G&WPSuNTcDPK(u&@^9Y~0dWM5Q)ssN%ei}+%L|KWm z-{3<@Xug|)SQa}X;PE_YPq3R>^z72^_dk`!W)FX?kwU{1GunsQj`CGKJ*M6*pB)E* zHar);sMLbbv)3%Vq*&hG!bn=y9Tl#|?@4D^r7TZT<>j2YO`^4oG~b2r?G_4mFp6y% z-sA~@|8hxOUd3=<#(<(z&ubF_NevkY6(1m$VOw5kC#gFBzLl@O+3hu`*jCbq%qVRg z1_?uqEL&7fX{|3_-xt7W;0kECg7Sn^kV)=~;D$!G7t0I5`|~{;$r4QK{B9v)onp5b zPvH8y3)rWz9ikWfH#3n*Mt3DbamkV9J?Y+YOLbl<96 zUt1@P(AC!irWQXt=RCZzFuhxpu{%F;;C|z(M&oSm*-w5)WtRsp-mHGiXDLqnsK-p& zL!(IpN{vopwiOdJ>=t@|puALh$ZMxSbo1vw#=aau?1PQ#G7ScY+N%N|2X#vT@ACvL zx{DR0>8*eun?zgkPmx-kzg>Uru<3O62DnjjWP0rO5-kM^*o+rMu zff+m-Md3%kKDGgQOLX6Sx0)MHJ~x$#ZkfKQmwn>Vsu?(e?W+SZ>G;d_E{@(xIM1?y z;tQrj5y|s67s{F^jijx8MyjM+_!Rg3-s-98%p{ux)tapYedVx#WAQwL_7d2#LaF%| znKgPon^^r(^(uJY+A!T+(#ay%`A6z%V;|6`yLuwN-5Dyk>)uy^|1WU$jtVg4xHJY9oD5 zhU*8+{^naI$B(mrw*`JK=x+z0^=|&nrGTB7$G)E%qgI;-)cZ!F!lIDtu1pSLztn%M zmH5A-wC~>~6mr&Vp2q;MY18H{eaq9pl_bdfy?}RMTI024F_2zHzIrF#=?WH&UM)d! zC@x;;*~xu&;)*5Ndx-F6s8=)O0v@#dMzQc|s?lfFJK|~T=Blu@q$2$fBiiC4O$xTJ z$q#4GHX~}D`mos~gZB8?o4GkOcSbc{Rx_bMon|*=2MR~Si##Yb z+VdsInCI)W?^#(d@^^LsUUQ&_!|!fuyL^hVf#F91=Rb&>dW9I$v>MO^4i4(GSSr0z_Qd-69x8EvK2KdQoF8bQ5W?WhMK525KX?Jz? zdi^tBIn)|vCQjbVo#gqJt>WE;g)JXH|K2$St$+~fOoOgzS7<`T_#IQix4g zHgX}af-3@>XlN%!>{iB4nMu;4FG)jyVzQ(dG{+EP%Z79d@}aA?FNW^l{?wOl;IX_T zV!rel+siCoz+i&=)A|Lo@OZ}#({hUX^6)SO9^P26@^^n0e`gQ;2QPH~ol^hK+y3z( zr+=s5{{y$Fo0yFVi5T3PnB03*m0`=`)dUWz^Y!N#Ae5xWP&`xft1!t#b_6oyVddxz zHR4fX6J_r_dOPGuIE~m>R$OaiyDSg=mJz8weI=01gd)hF!A_-W^>ICGsU+tdl6@Pe8Gm}V zq;T<~@$P(k%xiFT#+2W1tB<|=(K&-<4oWo6=h{j0Mv>;bLxaCQo0<8iQVsqj>>JkM zU)8wr*Jq6k|5U2*UxoetpQ=Kp*o>ysr*8Hz=taUK-Y!)I$wjdEgB^ahk(O}!L}}ZY z3GV9YJv>CJ1c;WL`8PD+jE^K4xKOMnGS|Ht>XY0-OWg=NfV7+5YGeQ~*or+4{$O>WQDb7n0HA>YjrW_Dp>ej9K=ny_ zMB2p5&S@SXMo{07blW1X*p52 z1C7pcCoobC^eT^i@5#J|xnHxt=rU|2v!i|3btf|@(YcA}P8`)A8DHiiS$U5o?K>tF zI{YFC{@yrtP3H9_$<0Lg=0eNp?{?SvO;(YY7cyTskj2JMG9(fqeB7N06=QR3c-Y>T z|H)zO`t09cZNKqvp`gv4oQ zTEvEy%E5)Z#FZGI;Kd;sN0hft{=rIeEO~i)YO}ftA)=zy-v{xtS;~ZCR{eR@v_FYa zKGQIPTVC;$H1)t>kTnLPVYUlcG-g7_o21&d4oyl4@6R2VA=DL|CcG+Z0Lkgur_IM` zc?UE$5x^jZMs9@>gtKPqz0ts-Qz{Svblqw`Mqi zsIlsX@}VZP!%6P8g{p~N3dWjfAa(!Q8$Z^g+GXL-@{Xu!?aND$q!+^H`%40^_nflV zd|>OtC0Rll-GZ)(tcV*43ynCkI)Al!q=$w4pS&>!)rWHRjbXO2Q~m;wo3A(9Wn?y1 zZXqluzx-a+g&%zhtY&6HQ401) zq@mPZ*A_z&L311ThE#u_pZtX0fqex)9>%#Cnweg>v}>9E+b_Aq^!XSi>`tQ!^Zu$e zFyAmBKUwbDTB$QsV3|Kh0~S#rp99(gHqj{?J`nA1clMd8r@otiB<94|`Zw0MR+Qg+ zR45?tZ>Bh#-B8w03=N4~9!8hf4VT6beRTK~85w{3-KNO>Q|1;$J9i**DxU3-2KeOX z`uLb;boG*MhtO+-wu&C}u?cD!yzx}zgS+5tTeGZ=^J$?`YAP_p`mC9!Iy(1XJh_%+ zNq{29S6h-7jA9vOz$HiCIwWR%h!%wJ@di8|mG`)Df5|QNzN| zej?d3TI~%I=AScHlEv&AJG-Cf;rS{Gq*s|FHBl8YHOHPJvLFzq9-#C*FYlhC9H2Uf zDM83JE0?Rn7>Z+`Wg~zlsW)oG`&f=4GCb~HO>yrGJ}Lk^N0C@+>3Q|Qx$3u%b$?iV zzC1f@O>Qdn_=MFh8FWfFdr9ojPJ`XJn9Gn4ws(@LcaT{f41x@A6E8-53TC3NNRpHC zF;+_z6Vdy-zOnQDC|OJSnyI3PsX@J@Nzn@H4EieJ!DJIR@zX~W{y|~QVWC>F zHwaF_lfK!0-fhLvw@UPxpvg7oe1R{%eZwY<8jL)Hg2e|N`DWQucl!8#L4V426!c9y z`pN<5kheL`D}@!-opOv~xNM#IFa@kNsN{>zokAE~EvYaFAYYgNC^pu*sG1*q zDxB)tT>4>>LnA=n3!whOdeiaOT^$21*K0$Ka^-uBd zx6r4ihab&y`bj*7Br?<5YRCGMB|n_ug* z!H*V?21eb0AA!E4;U|?@)MhxZX^7oVPxj?t-o4bcfI#U&Mpv&UX}(E+)OA!NnA)S# z1@s1}mzPg8qQHRx5pk`oZF$$%b-3Whha%^i?VOd9Z-Lt@t#-D%Xq@nAAT$^oisY?ejN-LO zQ$bL{;W$f7nKfgx&KLkxwKXbd^o=-9Rfxv>-dx)%stPEUschMp^?OYlX>podGlUpF z?9hx(LOpo(LI9<=EdC;f^Qrxt|EQ|}{`G&P!F2vz-)-aXP)|q~`lZStS4TyohrNEkK)t5xYo{Db*++)Ai~sXaKiX9?333=YC?H=nsWvl^@<;_Y0kCV zmxMp>mmg=fWiMzm8@KN+)HKgC+VJN>oGfg_aGl00W1zx=Kw@OZ!ii*cYow&kgOUdtZQIdHKOSgxV!S zx@}#I8rgQcio3Y7xI^BO4ZP!8miEBaRXGhlHs{6)0EnV7wgB$Ma}$s+1T2 zv(WGZnU!mY*cC7jb)nuQFKLembuoQExw5;nYqvlQ(@%{aqQ646USzSl9%Cpe&g#~E z4|+bAhur&tDo9U%HGADL+GVdaul3gzxg2(o%5x|fVm<(o6Y9$=+`t;8z<0;H$YuSe zwRJlB!1$R^SE2gj``3sz(r&qBnSuzRpw-BH(LfpNgd~dS%~QSmD+M{HRyB?J)hS5X zeSnF&bKjuxmUuP<^ewh-ekcv}Xcl7?U@UhrUVkHu`7_0}&j4b0_TUB+5u@KJu+DEN ziUq6{KBQMuBm7Pmchl*cp;EQieRAz4Gek$M-dQhQ7fLGh=)S9nW zcI~^&q?vq=Z3f#{M{MJhUevU@p{aeLl5kDIo67^b-Wd$|Xsubd&6AKz1+L>jl|oef z>$xG78hqFAd#_e?JZK9G*k(klk~TudNM}X`uf7}uezSrf8O_59Q!_u|%j+nppyyW2 zVm87S^DqSk`6GGyuJo|~c-dDDiZ_3*STSZzAU(>+;>8sZ8)qZXH00{ zSn*&L8`ay=2hgj4*BYdBg~sZ#|d2kt^hPY<#swe~bpz zE`M+88c<~+nH%%-{cQlh|K;|pcX50sK{WdSD9u8KOs|dh*JI=^L6JBG=ti-Vf|C>E zy>Zc-cL53pl55Ycb^WPLry}U!xxhWv;)YVXQ`$ni+vVTwW>=Xs zw~<-oV;g)@`b0MIbmYN2GSwkvfNkj>%b1$dZloc^oBE_5@4O(w4Zsu<<}y0hE9O*& z7DV28XR2E@DjUu2n^_KW*)*RQwRa7uEs5|0hzfL#rcTjpn-9RMTfUFy%GuyT@BC5f zeO1ORh~$`mmX=1`=|^65F&WELoZ@7E7mi@iIMnri(y)UUjo~>em=^01wV)OJd`NkC zgmkr0P=mtb*;u1?sFx|fasl|m%}w-I4nAQnB+rK)%PSaug)=j8aw}crH(7bj#Rn%ZS&kCd{wG^T`VG z-7j6QeS-A99Q8J;voC=YqAna^34I|3Hr)!)t%7%@UVH`^Yi9U|Zz)j%{*OZYRtjFv z)edHU<*2B=Uui%ZArXr{7N8>cZHza?n~I-a6eM)am%cBfjQc8fG|NTcgf+v#E1--t zCU}~Zi;Vp3`ddz?@%OB?3s}$jrlEhCK^AEq%-PK5UDbWjONtO!Tws^S-9OaqR+mo2*0XIavMXb(?l)_HTbs(#UK9{kF2+97h#@s;Dg{D|(!l){|qDM(^17tO+Ok=Quo zc3(NRl~xDUt4d>61Jntr*rdXwe1VI_r^-^h)M;uj|DaOPO61FwWiNzt;%YRJ6<d4c7_Jix<3r&xZR}H^?_UZN>4l(m{r50}U^Q%A&#HZpa0X%z(bp@ni^rZZ2U>6>DWudzUJR#ie&t|iX~6E?7}A~Q z?A93xd2{Q-ps##T^L-C*FQyUia(h$pwfbzAvP@5T6Zs#$ybV}DY9?KU06wTneoJ4r zp6ga9)i_g@rvUM~}&!^XT15TDL@2l6C)eg|jHV~c#8(zGb0qJKR} zT~Zy@$ce{KPJsjSV`Zr(^_yDq3cYXonu<+h8KoNLhLZAJAA<_~nF|j0{W|Jyn_*$g zghmYmIs5Fv07GSq&ZWm?@GLy{y1|!V1h8Uk{{HF{;r?FX`q|fmt~>m8y`MKRXcKJgt}^1H%hd@IoHuRxPF+(Mct9N+FfB7ZW#+Z2I^p!6ecgM zu*x)K<`L27Grg8yD51r(nWu)_ODN9X?^xmL+!Qn#AyyEZGiyidei1W2T_ByHOSZH$ zmYs<3PQ79@Y@A(ycbKH9duC{~_E{08yDZ#iIR%n@cx%GL8`T$+xa=fCHc`moPTYPk zKD-LtFy8AkuaIq3UaXqp8%!QZaoHS-|FFHW^q}LnXfv)AqnLY&)GxlEdUn**^hNWP zJ{hwYu;x>i`7gCNmX)T!%%Tr=>_4%F^l z-ChilNgVcDF0e<4fD|9LZEBb~+2}7}OX;qe)-I6>;YS4P5h%mL;HR}8n!Wbpw+JF4 z<&r$PEMT*yiO<$l(tBqsv~h)WU2ggB)}|0SX;b^jCto?lIlfEj{`aQ<9RFof(9Zm@ ziNzKGn6_wa%#PU5SB?n7*T3!4cCav~NrO{64uF~eE1o?Qtm(L_5toJNSB^cSU(Fv< z)|8`^m_<$Ax<6RJe)f>4Iv-|)6~#g)MzlX{yXXl|#zPMB7g>y8V}=ro z9hmh)H#uxYliGX&-(S_cJ{fmd;Qo~(c)8`w9feQ-v50@~j(;fCFUR@kY9>Zh}IP1xAqu*v4bvkHe z0sexB3W6f4$U(n!LJ_lfCn{QK6Ip4FEAZ!`^Vuk+N6T;f>y=53?idaZXXNitzDW)F zrYCh-)~;oxU8`vkORj~GN|dBz{MpF_ick3n3@cAf9!rD#?B$d&B@=`l`c9(A!*%-S z%&F=7cO99AV+R7mp${E zt)jQGB5hZIPyu(Z$~7r)(89jfW6biy$~?`=0#jymnQfNnpzDX%35PKcT~SF7TtiM! zpk(*H^2Ou5Vza{9cFK+~F_UcPQKd3L(WVyG4vgNF0P2~pW~vfx7pfY{vGFAW4$k1> z^2v5$X_NOXZ)VEvkMt>a!g0eFrg3>Uk%Z**;k&s&UpSfiRpIgHR@;*P*?||;1%-+? zUHTx6hjsw-pokK<%}_u9qKz?BMZ%HFhsc})#ts*OHPdH*DJ_Zp{VorWTa5}kz8}+& zkPyFiv5)3mIz__*W;i+XVhoN4L#ML7G>P$>3|4qjj#8V~T7GL3jbHdfpSUsl9<%~w z2i%;;Qe{;Sm}L>3p3}Fj1aeDi-iqoa?L#s}WgIK0O?cKuUXUu@ZYCmuDXqMCd62W| z#yA30Ms`>k^e)DPSPn>Jsts^k23Zja;po-;;9M=i>)xv}?MOELCPKafqz|;qJ%~=u z=3!(xMx#>vWaWh4Qh8U5l;`OF*2|0Wy`m+4KbJM4@}>|v>2T>!oXJ4(no3WS@yRcPO;kKisn@+HTLXWi;baZAMoyhOKE&&8B`Z# zMYLvQm_rdv(7n%RuSNt0TG}?y=8ZIWD#+fhpWV3Qpha)H{5^SR;aniegr-yP*)JS~ z!wTK&tNlKygIL+{hc;J5j2Ym%69DF3UsgUlF?Xxrq(v^xa=>9gp?VCnU7>5;UO#?5 zP@k{G!CQC^B>|C^t^8c+2hVc2&}eDN3iM+EZ)ku+qlJv!ESmiWF4_;Ky2bpc!Q~m% zr!mejxA880=AMz+$-uy0`o_vy5Y`->eh`|c=eku$EF%mA%=+a_MgX$mS`H2hWtYlq zqmhCGx>>myRJJ08DAD)1-U>b{0tZ-#wEevjfdXf_!+>OOweB2|3kS8s6Vf;%fo2g- zrC*b&-jB=3&_BwELgt(I3kEg$+SI}t#@7)hOIJT@@l*!&IhIBbws+2gH)YenAlCHj z{id5sWu=}@SNN?1R?c;8zqYxVx|dz@!owW}dd3`M3JrTDlN&WdAaF7{yXk39&g9@L zSAUFWz4Fpv760|eR14o%>xQJ?Y7@3*#yvf+6k0>8AbpR*?5{Yc$hWjAp7BqAMPhjj zF@f)$z4j)fOGm)Ngb16Za@3TKn1Q-EH{)S|4@CihN#*IllHy&Co8uEaZh3^F~u=cFhe&u>N!3;k13Mw=j!T&U)6}*Y##+-?KM;^yP)J2RQzGYJ zd-Iq&{>Dl&`}2fBSpEFi2(1GuZ=kg~G+91Zma&PKyKTNS&dq0w9ld#yPmGLxO7-F$ zcT^1du;S2d7W%UMC6ex2E0Nk0z?x+S6g?EscDKbq0X+ zGHC-OjT#y{JlwzeM57D@!`(=jW3X4OOzSMTM(ug5l_L_BXU>{z3N)oL`~ux_0JhM+ zlz_JbW*6}3Aw;26Xi0tmy0ICXFZb!Yybdqi_zJ&maq;!`#VByu7xJuXPHnIMTn~1_ z9zeGwS$Mv?21h|J{9gYIUWTaT*Q~s*lRmk@1aO8W^zwGmc=vX2FNUXZi#iq})ivz>ZDfxx~Jnc9*ZYR-@*9P)T zWXY=YRG)TdjdYK&3UAEdOLHuN1ju);xg@O?fc>?fPmCwKYn%;kc32w!sPcKqHX#RL zS`tWBo9u%AH}>8;uE}iMAC5Z8jDQUhq=-^Aw4nr~t8@^Ml0-^C>4YX-x@ANu0RsZk zl@^kaASIMgEc7mr&_nMf^j>^3bMMS}KA)L$&YgSiedpZYZN{>c?o<|WtQ}rt z0a_9NJffg6(in>`VN1K=Df!B1Db+#7@r_5>-5RJ!t7ELUZlmcpUL5 ziuF@pHK8lgi2E&{kk?8*OY7mcn7DY|*h($-R${_X%+vtQ=i8?%ZD(?&TkM`En=~W) zusA527k(Bkh#vl?V-3CVHi(Z@15fmoqQ%jgAWySjEBTadoKAoQ!rCNmsVh!}Hop~)mH27MMTY41h6Qpr79ocv!nNjnK1v3V3(G26{CHx#F+i6T`m+6vQk7VZmC?y+l#yE5wytzlHSKtIevKHtAp|(`$o%ik&}eD@FHN~|^G2lirBVCE zO!vQA`6U7{!jG$WiJAc>)`oV}nx=g7@p;|5FGZd=!<7$qN+@bC*ODYWqI4Er^0bZ_z$8#Iv?!HxxrRlcu5v;g*pY;Ind5lWA^QTZNpy*Q6CJ7~$PWT-Xw| zG^>U8Tsn(vGWJh zn9HMfOC5@ie{Nb#0sCcyD0wwRD;?f;>)qnbnGV0@PMj{WM>X>y!Y3j6UBJWBj7k-_ zgARo|8D%gh6MaW?n5))ciFQ0UHNR~Ndj$~?sU|};TGi-W-BMidoXj@+-paG&HHF#x z#*X`UmLAObPy$CK6EvuDm%k1>0UoIF`vS=4Pl4+7g}D?|qp#_RN_;XeDyV3gGSxH( zq(H<(bumU^W{XVkhW=exAx-NLjC28b*^6xx9diakk{ku8#1#{3Mp5P1f z&*XsD;OPNOHS3fDwFx5+u)KW^CPc!`wOZHa(ewhUD(ZMi%(;jPCftw|MIaPN{(%a43b^!Ick9VWwc8su%-ZEL zZ)uCNtv%bPVO@bpSpVIbtgwd(^5>*9Cg2KDmed{)4Rptla1x7yH8u}2gM4t`wV*Mx z$C=Zm4X65vb0ZPD@YZ`^mGkE}g$x|v?7JGuv5gBk*0 zy-&|i_sD%`Y!3A*B2vSGCmel6m75%VQ@1kX`kie|?%XL2*-DXDsz1!oe4NDf{V64d z2)IuQ-;VwoV0^8&4&~cv5zBKhmM34JSiPN)CO7*KHE(fD^W*R3<^0dAQ7P*ch8ua0 zGe=sZUej@<)`8^OqW5!l9=Yu-SQ%E#iZ(^AKvRvm?(eI&?V4ZP?fKC8z_z~SSX8?e zTgtR%kWs*g>-(Ex=poPeN%e==cA=epBn1=qXquH zhW<$0e`@GYH2=Pa{zTk=Xy{Kg|GtL)MBIO9=ub5NzJ~rp+<#crPc;9&$^RwLKd(S} zH_jM*+D$}fgs>*&1w_lRbra;kU_a!^jyyA$d#{gIWjAJTkP;NNCOn;@Sv)>>%Hd?v zxVN!2sSrQ7$LBzasp7^qkDI5BR)B5Sg^qWJ{# z6z$W8j{c#`&RYC-aQDr9wg)A#ZhGi0yM%SG&e86XbrcZ@wVs1yDr4gL53# zNf?!xk%iz1W9`bv!My~&01DDn7FQzfGqdLMsth)5^HT3>G(T!{~?i^_%>ZXr;kKpmA|+k0MG)-4}%<6%(ahQ-;E0Y{f^ z=$*_nW*NwJ>MZukj+qaK&7F`?4l2@g$V(u3<*(ID7f4RJqhh7!07-6<3obbZWU;=~ zmzF(17rgfXaPF!F6(bZb9>nNd+78T)XUkQ(N;W4@MAU7MASn2~nw zh=%z6s>hhXu6E-g@Y1|Rz2)V$32D-}(q4(q@=4v_d444L*Rp?w{>u_L%0$~jN27z? zxOSZQKYbMepkZHkG~!F89qY}Qpp~M1KFyp*zqG>~{&mk`CGr|x9GoFz=3A9$Em|-% z8lvS5E=au=OT(P>_qB0M>Q0?HRJJY83M$zD0@(3RYkQUL>m!Ut&y^My*BXA~A<=0X zz1l!>ckMuh-na}i=&7{n-kG()m^}AxFx6O`eS?n8MLlaK;hluk>Uw}8O%retidH#W z<>2;6aS(@7Eb(bFRP41(Y zs*Va0gLz24sMQ)@+g9$4zPu%L9p1$dqfPCvO&RTu2wODui5qZnZbQcE>vw%>Ah%h& za}#(yh9;oSL{QF)oUjRVu5zYFgJ_T-9ck*uv?-qUi8Rb(QjwdJovKOmMe_o0qX&)8 z@Oio5AD67>;Bqb7$C-m9-`0gN%b|7-E*4PWecH#t@+}CCx@PVSS(=kiQIQ!;ln&C{ z`-6HVIf!$8Ph0eLP`X2#*v+Vq(YwH~X=T^P?+pF8&m%gT8j=cG@s2~0YU$kAv)&Xl ztcVY%1U9xu&*MNIo6u=s)gvnx%Pr$Gq172)g*q31mgtX_-dEQ1 z9N>S`a82wL23H0hn9`h0(HB?i9gBou^5?q6nkL~GS8o2jjF<6yk*|fDdLGT4N(X=B z^-MV46gHri=hCpAVU0&FuA)E&(m}1g=>D)HYS+K&)<_jw(xnc=9+pYKB9dZiF{eaf zr(sLI(@Z8h6NPf@r$Hs!QdpW^*r3=il{4z^jnZydFR>-0jFbp#Qk@MfrTpwjJ$l)3 zenflLA-h&#kg$TX75w4gF1%{y>@^HSkjYT^CLK8%7i=4qa z83}TVbmXW-@=U|=O>Nfm!VFK+!?Zqm9$n_`2_#;-0DPXOi)!RZa7t zvi*Mc6RIeWXife=NemiTLPPd;eGfH=`*kLD6uqUVVCM^cj|=8}@l@{Ruwld(0F@&B z;hN0vBwRhd|4Xm&SKz-cfv*?!{>TcSas_N=N++*Eabj2hIkbOBy(*3@{<3;2Rik0TVEuUM{u2y*jSU0B-9RGwM}L^!I}Cyd^-$&9YUHbdY{Q zml}mg+!sEmmE-`p6SJ~=tMX^N#eL^kDVQ?XFZlFsSV5=OCQk(&w#;lwKmx4a+Sdl3stO+bp}SeN z+omgboTb583-gXh)U=0pNbj;pAXhf{DGmY_76xoX0P%2bxtAshZWSN(b7dwYTWzg6 zx(xfQ17S|By4@LR>{e01;}89VnROICJdiiM{r$Y|u^&vhi;abf7HOB(5MW=E6gbT# z+u$@1n>-1I{y5z-ngN`!Tsb>f(}OeVUT8MRuP8r)Dz=7dI-)J{c{u9@tKz;(-3FC8 zmF5CK|LhkIiq{@|lq_WYNbTxsg+-2U&Vz5iqI#qUyfYLRC<~iVgTfm zcVd`XQ1({gs7CANEM!GMl;$>-hR;;j3^?ib0d=%biJqmo%^|@K(oE>wa&j&sUFi3f zJ?W`w%3UcC6Wb~JB(y}0Qh_mh@Tk!!1 z*Lya<*6@3wlPHS(M#`l5Az|N}n}Mnvs7r&GDEAx&WKRE1!W))f$MWB+^{?l@FM%t% zG&k!HuxR^kOkSqDsKGk?W1$Xig5#8Le6ui)D!_yO2pnQD zk=F-`;E8>aV$Rg>^zQdb`Z@$hfB%xO=kyqI!wq!=*U9TRm{h5lt{{N5!Shwnf zPhSi^wcEC6S)Brsl8J_O&pMXsQ)`RO$juUOzEI{kOo--{srCGA{!BKAripPQc+>hY?clAE2M1Zj!sshNtZ1i}D5sQ9o4@`D?Bbc5VijuPTxIHP;_*iX(wy zIfl{5Oo?l`XnbLCe)cxS6yNv-P_Lx;KilxXm`7eWe8mli_*1W~)?nHd#6&v5jP!IA zT+`S>od4kbSqw^|TpA3?FHbLP)h!fQQXmD1EG>9(7Hr)sYLtUW;fRgwnW{zu-s{Z* z7BM+Hy>=(%@2%LpycutYuToYuTAzMz6MIfNn$Mi@S?6=;{F0ZFD5EzpbpXR)&8f~ofw3S@2?S0MmqnMoH#VA9m)IO{9 zkSB4HDmobm+L^!s0@Rrt0LP$?RljHSbFGG4UT{3|Hh@5=WT*D{r4q3bIMqJ$$_Ojp z<=OGaWXt z9*qaM!x4jkg#JgT1g5yshe)h?hiRERVr!>6T;U9~-59;jfP?|SpDmF&Evgc}6KkKj zO~Ift-rFe%XUDtr&dL~exMwdKSsYmmCvb$znUR-`jwx(x8M(Ej!R8ANuGb4m4F)wD zb6n6eaWrGd$_Yu?%j{I{AQWV_t1FoDfPF9ZQiz~4T?f}{uLqKGvhU!a=jzLG1{PNb z^gH~NwI-h!ft}uA<9Mg;PB`{r3%Ie&hUhyjl@g;dLZp;)ts5cz(ZxbA;~Ai}?Yub> zrC?4m-KT;aV`%p$Vfz6@d{_P6=jjj7^rG2#FJ5&meS*xi*N*g)) z(Jgi_)4%`v1-#yQK2t(C!Sn@ynpM2L_=t|_PnlZxZuG7TaLCN!T%mDS9_GmtAniIq zFG;cCD}DSc_^*+G*jgx~YK5D2jpwUve;AB*4e;(1h{+J6!Ol%6I5-L9jaFEtPEc@u zAgJvXzwN#5yaY&?9-<%PC%5U*+3(=J7#S0*zyfq3t1e&aE!S@-B(z!_*E$&d+##wf zE|*#|e03|UV9nHNaB(isbYN}P(DU#c7d7r38z00QmJBV)w)!kKN9!*C+xm@~@C*$; zzkH=d@p7+3s6gzJ#~_-zU}JGs);D0(@kPDS7<^9F58hkA0T0r(l@f_biRd%5<8^h+ zpj{x&FbqPmpM;1gd1_B(WkgRx{1oH90G@fqv&yiSPh}YCsnqrnw}my&%I7bR1ConS z`cAt96ogUj9g2@{6+z%+5ih$J%WNtHoK*Q6tDI|@quR_{WceQNxwQnAGaT}zcI zkn7s_R5T00&{TfjP-2GZXC;@CMBu;XrTkUPZ%g24k=q7NJIhZ{QQ9GA;=LUwt+%$G z|49KwO~EW5{4E#Nx!Za`0nC8(WDU6Rc$hg)CaSuBZcYY1Rxg&5m|}3Fj~N#~qp#14 zT#EPMUv%uilz&h2^4jIEh@7o`t|w$qMiq8S2{a-4>=FX5*;sfjLFJYgEaT`>CKK&q zI;ZaHd@SB;J*jXFlcLEm&msrLLy93XITaXm)j;-qzVI$_J8!c)zNPyM;3c4!X(#&n z6rw|`t};s1F>!*z5#Aq`Dk=5_Kpv=td(Tx=*_G@+rrj2X1wi*4wWl0|8vsE8DzlSo z&+t5);81MN>@3!@!4175^SYO)>n&lUlZ>pyBTUMv2%X(zc=xM0;WS9m+{c{m^Anj> z`o$UPQ&6FE=~$a*W;w~t90-4Anx{-lj2Do#4`VWq+3k#5Ck-ZuYQtw0PHdUZz6sDc zH20hekpiZ#mY~6gIRu54RtHn?;r!cp;xnzEMwXT|WhlGS;#vMyu=&H+(fo4=*Bb}K zp(E*Ue)}E$_4HpQ0S3SEj2>vp7eMjb?PoIY&cENX5AG{DR8v~%n8&t#0Sw&Pzm?p3 z(qgYjX@T}7b@}wa9)R#)#mfJkdaQalFA*!24hW}fuC+d*xr!)PK5TuzN;B!mD44m= zVgK{7^HU#ahvq47zW{89cK|_e{_imVC*|ZD(;Am@E8?;2jXs;U^zTFp)nr!_+P zoDCL23%pk)5;(RVCZ>YnS1;PtQsz<*YVdD*I@|g(Y$&AUMOfEE)?Tx;$5uxBC*F^+ zBnCu%Q!jqfctBoSP>0XV9ps~4tYI=?vGjdvaWQ7xSm6`VN5>E>IF+dGT}h?w_5_l_ zV9CO=o*Lm2p^xJo@=pq`i}sRSOf59|+w$H*WtzGL5TBO{P_Enr!yqW|i2H{>sTlu+ zWF1RwCD47_<*%IAH)QCN|GC6d(@{Xp1LHiB|6XOw3uUMe9h5on>UQ$Dxjr?THgVf? z{uF8byb~(P& z&&x8l0H{A>T~I&fnZT{~KJ*$50azmMgWT&~JsXr0@#(9f0+U*}hj@ZPNCI}e4>yGj ztew^)Od!#v$47O)?TDUDCY(Byk8geg`~pz()T06(%gtNNvFsau0ciXhx_kPL#dn8f zrIqIR#bYFvPr(GeefP<|8^?o}aKSkiD|!c)e-2!^r*JbsV9$uQC?#T1^i??k?QCBa z;qYy6tyiNI;cn0FvoC=2UjUt_ehpsuy8W*UAF{Oxhg<~>w@p?A8M$dzYS+xtbGkS>A`2&%K7(H&w2SW1-9O(E4Ba3pq4J%dyUF%pNFNXN4q7bYEEP#=Dhw*_WL1H_3UTaxE7Jj-T+I~8RC80jspjx z11=roN0gJZw=@aeRBzkrQrWqblcJ;QKbVus+b0bx;S;&?P?%JCuA(v7Ay=BcO^_iX zH;d*WBaYZhgOTNPl=6908C{6ARy7CD$sEcCdiD9N&L|3ehbN_NY5X|Dy>ZbFrO?sp zQ|&O|(lko2J>O9hTL7(j2bOkePpvJGqd>))Dq(@;jjt-nVRh;Rmyl|qw7PJfyIm{7 z67Q#A4CN~8&lO_f5}cBCRPrfUcX~SITsw7tgDGvVVYB=(o*B>Nxxq&BeCd0c2)#8t zQ!g&C1%L+q+R^>h=lwO#(1yytMo8Mk;Qz+h9(_KxKQ$i$_-wIR0Fq%j`+dvE4Kf-)&F; z?HY2P8YUG+Jg61IzjC9?H0k*!va6*jt}6S&nvSv{?6{HUL^K9dHT;IOb@|Y^;iA@laSw z8{BoA!h^u1>LLTOK8$i{I{Rt9?VYTmxAyFDtUWJnT2mgds+Djza?)>eo6*Qpz|tL0 z!C+GY9<=i9g_~7HOFOUad7by)j=ehD|9&slsORDR$W+#m&~kC944MOFl|F#dKXEeS zH(0#*UA-Q@T;vc&S2GIgk2#z@y+?Bj+R%{tTLUCl&TrK4j~>zBaoxf%IYgS}%f~&D z9f0*GtP}2NBxUqY^aXXI;G%FKH_C*|2w>F~Gbj=u>E^8LTn5(u1|lE2sr{7ft!bZ$ zwDgSBt%c{e#wvCh^;%siUCHvohAmX3AD=X?6v5aI3HY64?Ag@;gW5u}2t`I45jsio zw_}+G-GB6Z_Ce|1KO*t}Ui!sjweRzo1o!flm(Q^6Tc5sgSaCa#T6_A#4aYxt?&`!X zx2}17^ZWRlE7x_rGiiOwPb*O30+DGjZ`eNZbm%8Xg1|v1*Cq`q^d;TgACl=YUjH|T z#M?1L-b-O>@J)p;fJdf*)2An{yi)ia4CB{alJlwM0r_A00{9?Ywf21V%(0n2)Xu+m zp@vJs2M-f0C}CWW9`%f0eps?GW)tjvHR$Lui${NqGjXQhdW%S;yyxyb4JrC_fG!gZ ztweoEa~9&d|48Z1A8O?y4~1@{(>isnB)~udn!mJvbYSUv@D+x))Tg_%;(ERVRo5lLX{KptO@-q3i-eE-OII0I0 zA1v~8>_Ot9<`;nHa~gWk#F5=cf2f(pOEXIN7~ZXv@-bv$WmNFUg<;?7oo{VUdvf(? zM*Fu>Ry118>)$WayHsqAZdpDbxeVI=8xtP+W1KPk@SE?@ zT8~qaxKO_1$;I?T4_t3A^S`xCb3$Y5=7DE|K*i$l`3UlY{}%wDc(0ACLHX)$_tcl^ zKL0Up{%uN~3CUVPRjb7erdc;_D28Y!YoYl#3$8g%AcDg-9^;){wm5P!VPJ~xXi%!1 zDueGcZNmZ$oRC^x|8y+&-~$Wb{B#w%nydR_N#ffbw_&5vsCkBg);s&9$Lo&EEMXqh zZ-h8cZK-9vwScF|r@@0Gmp= zT<{t01nKXORjcP5iiGn6G3newogi*iia+y#&66h&fo~$S@si!&pU(k|WD7(#e)+rq%R%6D5v53R#k$4of-zzDUaStCW>F94S#?l=F$ zw)amP`4>Pg6}?pEWmzBA9Bzs0AQb*ern?!F1tzC#Ky{K&1zfiSOijPW$ux^rynZ#!>g zBDQw=)UKF$aln#6&K077Vb0Zz=;CzH{2cNnh{CoJeEQW3tUo$gq_ZXe=3ZVdJb2|w z5s2-5*N+|Kh5i4fe(Rr>-G8?yX0{-np3iJln0DFDw9T^`-acM3^x*Io>-$L zIY;&${jGZb+r|`wZoV{j)8-7)Mh=dYm@Im(g1f=G)VrghFYq48RVpgt(6CE#Aki0l z{j-r#`Y`9~IGC~ndS>SCmf4ctR9~fldN~q5*MGvbXI+b$=~PKE?}5*O^X)Gvcm~`d z--wTRay_L$YbX$X-*2%utiAy^OhZV+q-ba#v|c*5m}rb5B@V}buGNp9TzASTSaVnaH@R@tRMu13K$({y(4orkfbF!yzZ zS(a(tV0g8Fp?T}(E{k(Z9p*@_v`zDuSa|xw(lRcBZx_Xx;W65t>mJ?)<`+k5sKdwGAVPvA@Uo9(HG0Yn>yQF)nL7(|uao)u9|&P0EW2;CL%$zPL z(AZkX4;^%+lz#!N*t#^~b&C-CIq0_aJC_w$soL;58y&p>@(14m zTxO#A7bE#7hQZ%8B>{olaYreG{-c{f+k&MWzvqT`(p33CUv9!(G)Sz?+ZR9x*(zFS-XL*9?>NlujXU=qdWL4r@yP&N zsq8II%q*?|GJ7JI&&Jw*T8f6gp@rnFglWW76S=pE;{!O^&p0;UTr;%?Oc>BZuT2X0 zyksZ0*-FwYnxm2iFx26Vp9=!K92=uf1Rk7IIBVkan86KNEyY)J_?mowD+fI*`s&48 z`0-JzA?-j&Bbn%xtJlZQBgZUdq-!hIdTi_Sfn7CWP1l)-{DCCnAm|g8o~Wvu7?zdf z`BE#icZy2e3Nz~wFhuIE*NYt62<9980tmfcR4;%_jBI^5m=-ydW9{epV32J~m7!eJ zK&Fse42u2eUovbhCHad*A6vy>vfgGT5{cPBKlnq6P?y%a6_1snk4&3+riuy}Y@Vqs zSXxT`!KOdY8{HYim04=)HVcP5-jX$PhYoXK8xYUfM^)*`0T)p1m%=DJK6e{4h-rCV zuf0z@bli3sn-N^?CgQ32_%>%kcvEkz59OS(^l(#eaySW9SmyHymcd%%a6P*9YC7iq z@F=o$ok^vKj~Hr(GYMI$>ZGAjM(V`oi!{8KcL&@g3J#`rGf=-3-7Smmynh}fq*-|a ziL+_+jR|H~k^j80UAWg3Q@xcFKQ@hMn;JUT8rEG7JK9-V1%P`mP% zx&FJE>)-2c)mIP4zW^A+>Un+JvNDRz!KR3#>7vBcr#j7T00|z0y-30t(}~Di`!jweVSr<5P8MOUG19H)pFxlPrxowl;Tbke zMMi@|yJxFRjX}rLr+vIZ$j_Anx0+u0zYX)6(#1!D_2{u5JSw!D{>WD5FINBO37imK zk3qz{%qr=;c~kY+WmGoeT{R6~Cm*4c zNYXpU&3z@5C3sjY>+oStuxyRga!kXr1j*%chn7!b*$X3K}PDagQZpX)o%J2ReG14E`+_RRWmXwnzT;TOl=tU;&n>c#{cKp1lXlQy{@z)qlrV5rsJKa60TcU* zWOPPdM~7Z9A#i)j}h4UGI;??3S`#zoYOkoabtiMy=- zvX*3d_07QNF=$ykmF`Avf2^bd?aZ~IrBlguSBM{dt0ILtP!cROu$^Zqqf~Y~g<7;b z>kzbYRgvut2`9OmZ28{pYS58KoR@!Yn8Aknlx#GWY&XHWK_91i#T1;HR+mi8el{Sm zwk??vlWFXvXv&FJqxA&^>`3IjnYe;<;&)-%PLvJRM#MHwqhQFye*yuYv^=e@G z=UV@Xe=#UA{CU@yyzwAjQWAZ8FuFt8&s;atGc4-y(jI)y3p`Ly+)Nz!VW^9*TIeF1 zTvC@QOxRUAJ}Wej_WkD;PwDvrFe?UaA=FoP*EBtq=7b*w&i7YcW2JNYCtCmWXE}D! zg?3EYN_&6h&Y{a%A9_;{Vox zI@9+{uW8;*<&Bh5ETz_K1pg-bUto>Fl#2FSbm4k{d;fCWbR{jT8Cr2~TPooS#bBd< zP;t~W_)1;LxRQ2U-ouZ}&Vbz;Ki4f50}T#v37)>xxAK~?N{sI7*w1>5v?dppGJnHE&Rh>(TwV%I-9nu;@@0U9}NgY<8Mq1eD5m`os6fGJmf1NJN0a z;Wpp&625)eGkf^;<66asrP#@@W4}^QyZz;Hm+U`?a5VG+ z!;ojfmgK?9T~Xb_Rf~D7LSSLPy6vO@6tbgCPJgCely(?O(DIqj-RqGpJgqa^{ z3wzAM#lXFJhb&K5e5y;32A`3|N&cD$A5p6mfgi#fDA?|2K1$agjnN&8G7w{3*>jG@ zX!5*`TQb|WFzu+kyQR`Qj`Y=E^zaE5nIjJbeP%>gd&%h#E?nd9I=E3U4!QNB0GB>{ z+(LaHk7#b*)_q;aC{6WWkqdX6V!ziU7M_*fuFw&MZ4`hxZCKLnIqem{wv^c)5 z^%DbA;R0~B@|SLmZ(hevVL6(-uyjQ*dvhfDPLIXxy;M4<@TN_LnJIizcmXQn=qcuc%}F$jM>#1HPOi(u1Wr+I zTVSnKa0+LZEb)(!j7XSC!rm>AIolN4okJVFWjF+&>lp?ZjJ@ZYL4H7DdYEKfwxDYN z$&ydCFl4*NAch27`yEE((#Sbxg7Bp(3p)~~Hqut|epo%$W698_;NffKLKB-z^- zxyfoWH;xciK%EL;zcNZUTur8i|EVnt#>|zeJA!-78}D9_7()9Z*H%zzQ^UqyWWR)W z&(MdW<<8#V1q9a`(LP-J&V-6z65h6{b#X1U05zX}QY^6UUd!1g6DPe?K$vGMV?&Rt z4!E*@Q+mqoTM|WvMAXCrf+Fv81V1oPhJY%nS2n%qCgfl+G^Z2*zmIkI6FV~55blZXsNJm43Bvla zuo0;^saC-(|5KzRL|t4OlcC=RcR?3ZRaTO-_QKm(^RY#7a&2W}XSzRaMBeRlvqrOb z5%3<;jx^X7OcFr*!*(y;;e{PUWA(P+Re}Z1fEs}-fvD@B#CW6Rm<>HwQ1FKhb4#_; z3{rySxlkSNYD*kqo+HA!Q-+;AhJg2HHX-ZQsv7m(;2R0ZwG*t9FqOP`i4$om8i&E{ zvJH3{0`JAx^!b|8E>Sd-Dg(6w@BCt@|C62hv4mEFw60|5NfVq(yW74c+cZ(uSY+#} z{eWEJ3%r^T&DEER(XdPF=N;Cnsu>s8094%rish%g62Bt9uFs}P zn(g7-Y_=t}j~kgYC8JOaPd{YZ{Ba#6JFcLZwvO_UwLn`aPfZM=LNS{bHQ*LN+)%os z>~l%{I+Q@pVl=ND4F{GPuZ1TGSc($2cM{W{>CV%UVdA6)zMQVgoAvIHn`G%M=v6p` zZ&iVH60(Vc3)s^co#yLba(Fj@5oKx4;v+smhV!X{%@#vgU#H+{w@A8CM2w0ThwU<2 z=k6qtZ1N@ z|LZ<$V`~J?F}XgS8;HR|u`UJotG(!tk+l6N?>IW^ksTmkm;z>$*^sSDUC0F%KWJW% zymjNc)8_;0)?AqjRy8id*~VaDbWy0DKN>ZOd#jn{aS2&vKNuDjfNo1lUqFvh00cil z+;#r<_aqaeP+kP4eoSUGop|=8u!sDX3$)F}IU3lY9J4;{2WIgozpQ&wGDAnwN9Ap8 z(R%~uok@l*U|9d&WR-p9lXOBWB1(-{&;KsM+D$q>rI}33Grl%$l9k&e!5T9y?vK+2%tkFBYpz7_ZcFKBV_9Brc z+&Q6J{3Tz9I|K^Z8@!FX6a#JHsw>A~w z7R2#=SmR=uV#$4yR}p?9HC7~FTVD52Fau#mL%2nkev|#}{IN07TOh?z&a@-s3X?6j zSj_f}173gk+M+I51FSz^5{1n{-T;i?+4kNRCnL9=yY9Zj$gO(`X9O1bFA4&a?o6s^ z#PJ1-D}eQ7yobG%Dph)PI695FQKXdH^=|#4eVwX0Fbj4duiZ-0h5fnV3o}UopBp3V zd*+fBU<{`+itR1J8We%B4di32lO`2Q_A$?&I^dS}(j~Z1?7T4uRgc)SOgQijr5SPM zNEcaxE@Lp!O78L+Y#8oyw==Wu+%iY4l56s#+G<}-j@y&;ljt6 zatiHkJ=XKaW@RIm@#^YbifMrH66y*$|)mhxmtfLrFn0cZ`E3;&JZpmx|wyt-oPW^Bv6! z(Mn86I4=gW;Ei$z<-+;rFj&%y(DCbnK4TLej2MAjTReDR1oH!lp&{w_RX zGa}8@?WF83blsyft4+q1cD1$Ep9d;~r2;R1gE>WiqNkFHL@X*9kQh&77Z^w<@XN+WLH<6s}4+Ejto5wBk4GH>hLbZ=?B1*nmY@2-n{VMkB z(%T8$EfY_Pt3`9prz$?*sX}p7br=o^Vt8~8=wK&ha-CAu8rdXbhwH35yqA5(9?H`8 zFwA7eNkpq;E8WHii4K|3NC)#?>>>_1x5LgQ)shglCDTxk1v68ZH~Y}}(gTb!R|~tX z`uNf#XE0?$H8!5p$^y z)!BLdYyLt6NojgUpPTL((-1x#S&dMAZJ>ao8N$fOyq;S|wm&QhTo;0nFyDUAE$0v3BFgH8QOEshQASnV!+t9V?b0cc~q6ki6mbZY8Rs&>bCD5|G}WRjE0W_!9_ zU-c_I1>5g=N)_}LSf(Nixx8c*?oMVoX`XYMm{(tTQPJ4b+HLJ~rm|Jor<1Lzxr)&# zUa>X!TVpa|c#THz(3N3lpb7>k@=i8*ZZhHT|6s``ALf>!^cLeok`8_2x$oN5UP zC^8^}2IgudxnL`Ds#FZfD{>!$Y!a6H9?u-6!H+B82T_E4vKbxfiCy@XKh*Ko46<9)Tk% zeUV=REv0k+^Id`*XPCY7&IJXK)1B55&6Byh>UE1Hy0&E;Vrqu{hbc4lnbnprSi z38`8S{E~7__>PX$0f)Pugr#Fj0dO_FlG$5lQ?foJbqbPgA6Yt#do zE|D#U4}~^0@=j{pAu2j)>=pJC=0$@&&UZ+%!X_hzqNMUb zLG=Ab$)Rz#b-CooyPSOAgl&@zOJWCGhwJkbd<6i>LAKIdy5fuSL<_-PsoEKA9LyP= zge+ee@&%Fy_~#2;ON@h@*n*QC>^vm6KY%Xv7Vn3(Ke2X$7~pOju4^o*R!OZRWmHlNOUJ$LB@u$7u-170NDXzMzm zU3opx*|-7!aIr3Ks5i~)&5v}c((`(lM1nn?onG|FoZZKiyAnM>%#95X*l+5&jji2A z&)to*5@}C4YZ!bA=xYr>q!T;et0*>ZT_HG^WDS>LV!?YiPil~VBFffB2xN7odOJG3 z>jhriPdTX*d=sp(6)+3DhYDD^9XjU6s~Z)}rjb*=0dy++p|ah=TrtUiwQvk{V)54@ z({lJXm!ca_&Bf!pN4HK6?3@CO$x^SVeI~V=q^>WH0P9 zoAC8Fm>KHD#oBib-Q{+EM`KMTo07aX8fUzL-h$>6TL1}ZT_@=w{?b=PCV3(O8+}y$ z8QQHuOjz$!f(^z$z#b8m>F$pZO7p^Mj#Lw{TqIL4{k0hhdO3&5nZ5!)k?=SHZ!dv1 zPOTSdQ)nYe)4QvSC)&{Ff^VI8|5W!0mF0+MYW)s6f^`ftqKwkh6 zt(Id@juI=j*UjI&>c%XocQz`!&hT5Ou)oGlO<5e*AHX>Gckcisx5^T*X_7;%&Qh{- zsnN4fjg+`jII7Nd<)2;04{W392iW}ImEtJ9I=5RcH!d&oX5!IVbtnRH3wquKQg3Qd zSS7`qRyPwZVy#@yE5j+A@FR<`$|XSelw9(rbRXQT478W|STvEDHI7HnQKq@*HE z@#ufHHg5IQ)PlK}P-W^oCMa@0%CjoAN4G~d)qc33D%I1~1Z38YQ8)|6gcksT>5mgR zt}bg-7>z?62^q$21C0HB1~UpgsdRdGXF76?Qd-psrcAL-BzGD#IMC~Y)el3{7jX8| zOpx3z{plj|_+1iHPluVX*I)}4JCG3~pf=%z>*MtdA6Z>ulTPrN&+JE4x1UKCv$$7g zd%bd;D^T(aV3U1=XeXOseMp~Cr3)%7ykp1Q-|6U^s0? zPIb-}m2qvZn1XCO#3w}cnM4{vGh)jz>D!kd9CTOeHsg24T|4_+nD2~3=ygC&k{T8H zdQfTEs<--z2>puu>@NW2ri0=s?|nT+&i36ZeowMTvYn}07=03d+_eQgQ~>#Wa-N3? z;baeYeH%hu+O~`tuUomLQpMr*;2PKY@03&SOD8(2x!Gl!@M^WW-Wo*fxA}7;O^G#| zWlNAsw(<-zUZ)IP22FObI1?ajQ?y|WisAX>(xHJ?_RdIIsRyE5Z$jzIxJXGD5DhCM z9bhkTRQ}jpo14vwtM_x#iFD{@rSQHq;_-H*bP(Dc zJI)5sd3XTVc%>;n?7kmU^8LK;oqLqD1-z8MoEQy?^eeeiTE;fi&=V32m_UetM|v>`B(xBa4xvg%L0`_j z*K@t^p0nQjz4d#)wa#yy??1DL{msmGZ`PjKGqXRlg$Ijn1I@E#HBtvULck-C zJE3vet8OG?36K8qDSh*kahoKyxhgNuK;tkyO>L5vD)C|SYE_LeHj zC7^#QE}HOo`ilwe8`}h>F*$Lh0mDjsY$kK+-f~z8|MC3-ya~iFUs9@v1%lq(8Q%eRtQuk*XOLAB1eZi6}bBPnmp#-9B$;*+K0W(cC6|Cs=Bo#u-8yply z5@rlNPPid|$zqMTfJ)DO>gKsJX<%oQXr`PEPX`8r#Hy8Rc;2+c_pdD&b@#Xx`Bg## z6^(ssfJ7$jyq-bQ;4JQyX{U%`E4P2sfMB0rg_onAm@LBzDJiN=-o5^%=y>C8WyOa} zR>z)4Obu#F^Rr_t)*=SWUIs6S2KE|CVUp8c2dqDB+3Hp=9_#~7`=O&Z35amH2Od#uel;0MH<1_dD{)E95{EV9EVeAYwLUf@$!|{Km)DTU*qfK1 zA={Rv-eU%B?gm`}9~aYxx;PA@HwcewkDDe#f+nqZdZZIYHE$0u%G3ucDpvh+b*g&Q zq;iw)NySAnsW9Csy$-T$hXW5pQ$On#XD3&tspGuJk zOHY`D4yy@nF{;II!-rAp>7U-h@Q&*AdR>j@lk2lK5ie6vojz!~i_w689f`mJ!=35`}6=~c} zC)?n*Jqr%=k>KAE6t7*Im@_TJYyI_aue$Vju^b5s5a@#k18>v|*#e3J`-z%@d#iUg5f9Bx&_f z3nDAHnM~9l&cd>mPki|Iet{ljA;lbrfldKUf&QNx6wH>^>a9j+ zg=!6zn)_EK2ZMkE*V`76x~zXc71l(BOAXqThrnq1=sJWMt@fanTe{um0l7Ax13WG- zvYhv2I^L9dhZamP^_w$y%XST(nMlfZ0Zyw#q$We-N~*ofQ!9)#o_)p}`!}wJ08~z{ zDVcWJ*c@>vF<%i+lOkvyt)ydGNk&^w*Xx;yBLz$2J)$#5_J1~LuAMXqKXO_7dP(o1C!T1Oy9WOhTN?K0`3gA_3rLn=8bT`l@d$0b=Ahmu^T)4*wioo z{fBI9{LTMz)VKXu_{W35yWd~?TY11>^Y=Gt3fvbPu1E(~94djy>F!t|aVsQ(zf{rJ zi5;itMIFYhw5oUApoO>=mv=ilMSmM<{Uj+R`R2OuNvXW9OHW_&aox~%$odTog_80n zc7KwtUzBO6O*Wq`1e;25F{Ir+Qx6VMn1`nT?-LxIXA;5L8zgiI*>(a1pPy(J3HccO z*!EODnr!FmCda=Zo}xR!YYUHa*3EL=hH&K<4Jb1l;Q+o8;hL9R1TqPLb4QRFDdK~+xYrxi8ThqFl;;Dw z#-_7cg#kclo{LyDJQ}qwg@26jMy|*QnSpe)RV^0dm|vev@U|bza}3;$Jh*Lf)S8bS z3-aWUrk0ytpPaU}=?YcBq+`9MA#rb7RX3d_(!JAu!fT1@iOVHAq>~90yUXj_8p`zL zyU=62RX3@}$&ZG_`LW91D?P^O` zX>@L>)!vjll&Y`_C$&vm$py%3C%8)GP6mq)bWFz1R;$JJ;l4!m4hPJfEL| zA~2)a&8eQQYd-}?8J6GiyhfP_t?ve`b4q_s0;f6wm&u2u&wYGW4an%O*GaeEmiU^T zZIr_AmDaf5R6LUI4=9I8iOr)kifrEs9vNC16Wnb$_MqIO4P{vRjH}cN@UC3Xi`gqK zxCIv(pN459x77h>hL%P>()1b{$LdavjYF0;N~#6v&VjzAh0nHh1~~jC$6^+HLP{>B!m z;*HSXGcXpe>FdyhSXsb4zqt;bth6MFLc&S3@|5HyJ*fbn(gcvdK&6mt?Y5&9#sE_2|*XUpyPv#Em_8(}Q%b z={>Q!Np*+3p;$Ug50j$~QOwoMn{d!iNeBPMpxOS4`}i;8KK7kfeK&T^ZcX&b{O(|2 zaWEOcQBE&RxDTD3arQ1)o52}|AiHE2^~6ZnkpSD858D8(UhVVK_)b?RZJzztJ7CJw zA}Bjx13CvtwMdcaVIWM003)(*UwK}xEGW{f_XrW;vgsIfC)5g7r7uY-!$_PF-IpFb zJjFXZ2dmX$`-KP$)Qbc~*NKG7O}p?m0L-kCc6<^ZJ+ zn66dn0^5SL8BE*z?aXO!D%Jm41b;8SxCtQGTi6oY|M*U6iqI)V_xr7gfnrY>6Sne; zo{mw==~zvK1E(PMi#{l{y|MSM>j6FESUAyJB74EY+mn)=l~P@uoy4xcHCQ}j9|nPT zX(>aEI>lZdxblgSC;MShV#OV>U!iAU$*)kyWzq;n%r2n#zZenIQveG}B4a1dCQRTG zzRnR)OBfX?+fa^EF{ph13~J@!e1E}`G25Fa5j$}ka!((r4vxWP&jmgja7vFZj2B|v zuHEN+zku^>z`1FyRsF~4$D1{6WG^y+KdTrG@7!Z4WcqSPwcjHcEvMtiH?6*V$G)&L zA*AaKQln*N)Z@Belt9_a-3W@(I{U?Lih!cWm%VSQX_2o%z|ZPU^}-mg9IKzame07q zSm@t8+ZI1~gF~9Ur*tFqT!~_YMw5b?m=P3Rlw^6xY11~A^8OoJQd3ctI|u~OvOZ}- z`$c%Ujpm4Kp|Y~yEPy~vGqJGdgF_cb+|QJeT$N8UW39`OpDadWvf9XKv@QY!wWZm9 z;LvBSj9OGPd*h=6b?$e6uvsy<9W4Y-VQ-stbmv4cfm12weuawzDt0G@tlrfkZIsHQ zFK8Gl^sWrKVHJpzC)N0JQ_u#IDI)Z0IkApX1`i}87)&-n>V&-;sw__j2Q zE(3_i>tBqOo_v+gcYsigea+_IUZOw48lvXAEUFrDpCx)vZwXh~`(-LQad5B0TRb1qB~w!_XRm?l~Iil!kfl z)CED#V!`wI>ZMzSRD@E~iowT3R5WVbE6#1qnY9H6H3}-+4HHA1(iD$*&(Qe$px zj9|lD7zAA!$?(+0(>*Cz%#Q5lWq?)m^`Psg;yOKBKLw_(E3NS?h5JF;)NCTIO~#Ttq|=Uw-jk;O zfZ;yIcRn|w@?bOmjg}Kbi|?mnShUw}CPtyuV9NnIPj>(XGKs{=U$TRJNiDO|Qm?0K z;W28(w19+4Eo=1S$FaQ_8lHMPT-{YUYe?YEJEbVjiXr=NY?4-Bw?|R}J89523-d;e z8W=3PFMC}(X|w7E8y;J$vw7YhT<2D zWaFf=Tzrn@A|_&np)I?*bW@4_s_(T%Wu17}LUxzxE;T!_jd#<`Ec3J&bEa4}9(zY}ZE18p-8OsC~BR?;% z^^L4w;>zqBme+C@EZM}^EgJ^(Z`_-KNrV)(;K96a=PNBGrAsi_tw|98@GusJF4rH| z13=Lw)S9^BAij7&-p>SRf7u3FBa2uoX-b3iULJUvEqRvWh^%2@Jc~?FD3)A_{(XIk zg~L0gTZk)Uy+a8zXQS=;(mfKny24Mk2BFN=(`y+CkRG$EI5?rLRU9GA7@QWHuZb%e z*Ld~YJodjAsIe!urbo+qyYQ1nApQd_fLJP+m2x=1y%J6ZK-Z1v4HLO;8j#4r@ppOx(P_l}x-e2;KFzCe z)>Z~->xV|iSDdY}D4COpPPRr~5fYIW#@d&kN#<0q4MpFyj(=z?Sk}KwX+HJnBk$&r z>r}p{%~^mR_u8B|Pstf?57#Lz@?ruA1Ol3wzzCMuAZaIwq*l*@N_z2WCxC>+1(`U( zJ1l=d9DxA33-+SK0GzDn#5!A4CfOzun)|uJ*tV%a8Fb&Si{hd%KUl4vcqo1xwyKM@ zlk##c6R^I+Y(g@fvnN7TA}Xo&7Pg$Ar=jM)xsJLJqui~b?b?j*q`w6boIxuuuQ zT=Q}DeMlSl66rwn>@H=}PPzzPTH54Vm>ptGCavgi(I|dpmS{9O$7CTt6dKv&c9Gnh zZcppq{mG3-0vD#GF?;?+RxGz6MZZhax;TT)sVRhU>pg%STvl~-4kYi=8u>DPL zV~j-)Bx@*xeq+-z9r_vTvzRq$Ig%fob%8uHrJ`S1Wg>vdflBDy9%!jK15qn!7nAbp zlkQ6n-7vkm8X?nTV_4{PHuo0)h5>ifME9&`bb-Uyt2Jn>U7)fmT=uxCMI}|{y5PPC zq`9%|PL7VRPad<$)_J zUI&giSCn}&E*^GK3j)ytp`Y$TzfOiH z#y>P~7o4B6!+F8Cd4vRRydJ4;Zg3Vi9OUSwCpzO5%Tc&ASLViw|1a%=>vwtqc2Xs{ zn}q@~AA_F1y0ul1AwoQpkaiBM#A$LlNn<9ftD(0tEePD_+2@ehzU9GM+iRCa&@XnC zYR}rqZ5xuXC)QS?q=0a>kw=&1^WtmeyfQ5q__^eEV^99R#n3~eh_xPd6e?E&CY7Ir zu_6nWGO&|O^O|5=hpS=9>54Dh65@u-pHTWB?m3DiJ#!ts8;y=7dfe9dj;S)MkfCiJ zPSY97z96+D01`%O=Tl$gJZVc72u$@T>o@_ zyj}n*0evc9KKRV92(mt>1)Y24%c=FUTGs8!MOQDrK-)(d2q#w5OW}tlyfw^|O&cq3 z?H67w_(%%!EUY#zyGTzdOgUm=GIFNKexcGWM$1~l7Pe4l=aCzh1J^i>qgTz7Rtw#>IF}d#fhBwucttY?}ek5pcXlq}!)Y<2o z61(mIyNE#6QL&NLk*}Fosms!%ok}F6LlYV;K8eaWwOtXFwkz0;L+1f+ms$QQ0BGHLN)RVLiDC zg&GYryebD})`%J4qgp&ixi1tI78b?g8-KbE2O#kXpe_Lm1OmZGPENLqo7LbsD%EZ$ zZxt+n(L52_qg1!ZVfTEzvNb?lXH|n{bnS&}@6iZyuV1Lxs9&=y6YV@&H4)+d8*9{h~#XqrbZ;^zWXZjs}OD}pST6`m7o?8|v#-=RCxJ<=O# zzE`qMZ5CFpT#I^RHnLFRQ6mD`mSBuEV;5wJ5b