From 6e3f2d3ce2850020890b517f168f163aa5b1622f Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:38:06 +0530 Subject: [PATCH 01/35] Added support for google palm API --- main.py | 8 +++----- pyproject.toml | 1 + textbase/models.py | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index 65a75016..73cb37bf 100644 --- a/main.py +++ b/main.py @@ -1,12 +1,12 @@ import os from textbase import bot, Message -from textbase.models import OpenAI +from textbase.models import PalmAI from typing import List # Load your OpenAI API key # OpenAI.api_key = "" # or from environment variable: -OpenAI.api_key = os.getenv("OPENAI_API_KEY") +PalmAI.api_key = os.getenv("PALM_API_KEY") # Prompt for GPT-3.5 Turbo SYSTEM_PROMPT = """You are chatting with an AI. There are no specific prefixes for responses, so you can ask or talk about anything you like. @@ -17,10 +17,8 @@ def on_message(message_history: List[Message], state: dict = None): # Generate GPT-3.5 Turbo response - bot_response = OpenAI.generate( - system_prompt=SYSTEM_PROMPT, + bot_response = PalmAI.generate( message_history=message_history, # Assuming history is the list of user messages - model="gpt-3.5-turbo", ) response = { diff --git a/pyproject.toml b/pyproject.toml index fd2dd53a..8738793e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ tabulate = "^0.9.0" functions-framework = "^3.4.0" yaspin = "^3.0.0" pydantic = "^2.3.0" +google-generativeai = "^0.1.0" [build-system] requires = ["poetry-core"] diff --git a/textbase/models.py b/textbase/models.py index 814ed533..96c9d36e 100644 --- a/textbase/models.py +++ b/textbase/models.py @@ -1,5 +1,6 @@ import json import openai +import google.generativeai as palm import requests import time import typing @@ -26,6 +27,14 @@ def extract_content_values(message: Message): if content ] +# Returns user content if it's non empty. +def extract_user_content_values(message:Message): + return [ + content["content"] + for content in get_contents(message,"STRING") + if content and content["role"] == "user" + ] + class OpenAI: api_key = None @@ -143,4 +152,30 @@ def generate( data = json.loads(response.text) # parse the JSON data into a dictionary message = data['message'] - return message \ No newline at end of file + return message + +class PalmAI: + api_key = None + + @classmethod + def generate( + cls, + message_history: list[Message], + ): + + assert cls.api_key is not None, "Palm API key is not set." + palm.configure(api_key=cls.api_key) + + filtered_messages = [] + + for message in message_history: + #list of all the contents inside a single message + contents = extract_user_content_values(message) + if contents: + filtered_messages.extend(contents) + + #send request to Google Palm chat API + response = palm.chat(messages=filtered_messages) + + print(response) + return response.last \ No newline at end of file From 3072aea13e5d1df8ea1ea5cc49fe076a383b7167 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:38:37 +0530 Subject: [PATCH 02/35] added palm API key in .env.example --- .env.example | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 54430edb..5580e660 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ OPENAI_API_KEY= -HUGGINGFACEHUB_API_TOKEN= \ No newline at end of file +HUGGINGFACEHUB_API_TOKEN= +PALM_API_KEY= \ No newline at end of file From 9797c8270742fb8839c0cc76b79486a200030bfb Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sat, 2 Sep 2023 17:41:29 +0530 Subject: [PATCH 03/35] added Google Palm AI example --- examples/palmAI-bot.py | 39 +++++++++++++++++++++++++++++++++++++++ main.py | 10 ++-------- 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 examples/palmAI-bot.py diff --git a/examples/palmAI-bot.py b/examples/palmAI-bot.py new file mode 100644 index 00000000..bfe8a0d5 --- /dev/null +++ b/examples/palmAI-bot.py @@ -0,0 +1,39 @@ +import os +from textbase import bot, Message +from textbase.models import PalmAI +from typing import List + +# Load your PALM API key +# PALMAI.api_key = "" +# or from environment variable: +PalmAI.api_key = os.getenv("PALM_API_KEY") + + +@bot() +def on_message(message_history: List[Message], state: dict = None): + + bot_response = PalmAI.generate( + message_history=message_history, # Assuming history is the list of user messages + ) + + response = { + "data": { + "messages": [ + { + "data_type": "STRING", + "value": bot_response + } + ], + "state": state + }, + "errors": [ + { + "message": "" + } + ] + } + + return { + "status_code": 200, + "response": response + } diff --git a/main.py b/main.py index 73cb37bf..a7f74890 100644 --- a/main.py +++ b/main.py @@ -3,20 +3,14 @@ from textbase.models import PalmAI from typing import List -# Load your OpenAI API key -# OpenAI.api_key = "" +# Load your PALM API key +# PalmAI.api_key = "" # or from environment variable: PalmAI.api_key = os.getenv("PALM_API_KEY") -# Prompt for GPT-3.5 Turbo -SYSTEM_PROMPT = """You are chatting with an AI. There are no specific prefixes for responses, so you can ask or talk about anything you like. -You will respond in a natural, conversational manner. Feel free to start the conversation with any question or topic, and let's have a pleasant chat! -""" - @bot() def on_message(message_history: List[Message], state: dict = None): - # Generate GPT-3.5 Turbo response bot_response = PalmAI.generate( message_history=message_history, # Assuming history is the list of user messages ) From b7debabc06d9de2f1fbab84136180c5ea5ea9b0a Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 13:57:09 +0530 Subject: [PATCH 04/35] Added Meta's Llama 2 API to textbase, updated docs accordingly --- docs/docs/examples/llama-bot.md | 51 +++++++++++++++++++++++++++++++++ examples/llama-bot/main.py | 41 ++++++++++++++++++++++++++ pyproject.toml | 1 + textbase/models.py | 38 +++++++++++++++++++++++- 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 docs/docs/examples/llama-bot.md create mode 100644 examples/llama-bot/main.py diff --git a/docs/docs/examples/llama-bot.md b/docs/docs/examples/llama-bot.md new file mode 100644 index 00000000..7bcc5c22 --- /dev/null +++ b/docs/docs/examples/llama-bot.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 3 +--- + +# HuggingFace bot + +This bot makes an API call to Meta's LLama 2 API and processes the user input. It uses Llama-2-7B model. + +```py +from textbase import bot, Message +from textbase.models import Llama +from typing import List + +# Load your Replicate API key +Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" + +# Default Prompt for Llama7b. States how the AI Model is supposed to act like +SYSTEM_PROMPT = """\ +You are a helpful assistant""" + +@bot() +def on_message(message_history: List[Message], state: dict = None): + + # Generate Llama7b responses + bot_response = Llama.generate( + system_prompt=SYSTEM_PROMPT, + message_history=message_history, # Assuming history is the list of user messages + ) + + response = { + "data": { + "messages": [ + { + "data_type": "STRING", + "value": bot_response + } + ], + "state": state + }, + "errors": [ + { + "message": "" + } + ] + } + + return { + "status_code": 200, + "response": response + } +``` \ No newline at end of file diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py new file mode 100644 index 00000000..89bc11c2 --- /dev/null +++ b/examples/llama-bot/main.py @@ -0,0 +1,41 @@ +from textbase import bot, Message +from textbase.models import Llama +from typing import List + +# Load your Replicate API key +Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" + +# Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine +SYSTEM_PROMPT = """\ +You are a helpful assistant""" + +@bot() +def on_message(message_history: List[Message], state: dict = None): + + # Generate Llama7b response by default + bot_response = Llama.generate( + system_prompt=SYSTEM_PROMPT, + message_history=message_history, # Assuming history is the list of user messages + ) + + response = { + "data": { + "messages": [ + { + "data_type": "STRING", + "value": bot_response + } + ], + "state": state + }, + "errors": [ + { + "message": "" + } + ] + } + + return { + "status_code": 200, + "response": response + } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index fd2dd53a..4b88f6b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ tabulate = "^0.9.0" functions-framework = "^3.4.0" yaspin = "^3.0.0" pydantic = "^2.3.0" +replicate = "^0.11.0" [build-system] requires = ["poetry-core"] diff --git a/textbase/models.py b/textbase/models.py index 814ed533..bba6f93e 100644 --- a/textbase/models.py +++ b/textbase/models.py @@ -4,6 +4,7 @@ import time import typing import traceback +import replicate from textbase import Message @@ -143,4 +144,39 @@ def generate( data = json.loads(response.text) # parse the JSON data into a dictionary message = data['message'] - return message \ No newline at end of file + return message + +class Llama: + + @classmethod + def generate( + cls, + system_prompt: str, + message_history: list[Message], + model = "a16z-infra/llama7b-v2-chat:4f0a4744c7295c024a1de15e1a63c880d3da035fa1f49bfd344fe076074c8eea", + temperature = 0.81, #seems to give the best responses + top_p = 0.95, + max_length = 3008 #same for this + ): + try: + assert cls.replicate_api_key is not None, "Replicate API key is not set." + client=replicate.Client(api_token=cls.replicate_api_key) #creating the client for the model + + past_conversation="" + + for message in message_history: + if message["role"] == "user": + past_conversation+="[INST] ".join(extract_content_values(message))+" [/INST]\n" #Llama2 paper mentions tokenization of user messages with INST delimiter, otherwise the responses get ugly with time. + else: + past_conversation+=" ".join(extract_content_values(message))+"\n" #response messages dont need any delimiters + + response=client.run(model,input={"prompt": past_conversation,"system_prompt": system_prompt,"temperature":temperature,"top_p":top_p,"max_length":max_length,"repetition_penalty":1}) + + resp="" + for word in response: + resp+=word + + return resp + + except Exception: + print(f"An exception occured while using this model, please try using another model.\nException: {traceback.format_exc()}.") \ No newline at end of file From dd8e110933eab7a1d2b1a1a037a2232cb02db075 Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 13:59:36 +0530 Subject: [PATCH 05/35] Updated Readme and docs --- README.md | 2 +- docs/docs/intro.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 92866b41..cd0ba031 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Coming soon: - [x] [PyPI package](https://pypi.org/project/textbase-client/) - [x] Easy web deployment via [textbase deploy](/docs/deployment/deploy-from-cli) - [ ] SMS integration -- [ ] Native integration of other models (Claude, Llama, ...) +- [ ] Native integration of other models (Claude, ...) ![Demo Deploy GIF](assets/textbase-deploy.gif) diff --git a/docs/docs/intro.md b/docs/docs/intro.md index fabeec56..91e4cd88 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -14,4 +14,4 @@ Coming soon: - [x] [PyPI package](https://pypi.org/project/textbase-client/) - [x] Easy web deployment via [textbase-client deploy](../docs/deployment/deploy-from-cli.md) - [ ] SMS integration -- [ ] Native integration of other models (Claude, Llama, ...) \ No newline at end of file +- [ ] Native integration of other models (Claude, ...) \ No newline at end of file From 428b3f67042bb72cce303f04c72e33d7c1078938 Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 14:06:23 +0530 Subject: [PATCH 06/35] Removed replicate API key --- examples/llama-bot/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py index 89bc11c2..d9a03307 100644 --- a/examples/llama-bot/main.py +++ b/examples/llama-bot/main.py @@ -3,7 +3,7 @@ from typing import List # Load your Replicate API key -Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" +Llama.replicate_api_key = "" # Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine SYSTEM_PROMPT = """\ From bc28bcfd1b9f768221d3623a692031c6bfefe05d Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 14:16:27 +0530 Subject: [PATCH 07/35] Updated docs --- docs/docs/examples/llama-bot.md | 2 +- examples/llama-bot/main.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/examples/llama-bot.md b/docs/docs/examples/llama-bot.md index 7bcc5c22..012b85e4 100644 --- a/docs/docs/examples/llama-bot.md +++ b/docs/docs/examples/llama-bot.md @@ -2,7 +2,7 @@ sidebar_position: 3 --- -# HuggingFace bot +# Llama bot This bot makes an API call to Meta's LLama 2 API and processes the user input. It uses Llama-2-7B model. diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py index d9a03307..89bc11c2 100644 --- a/examples/llama-bot/main.py +++ b/examples/llama-bot/main.py @@ -3,7 +3,7 @@ from typing import List # Load your Replicate API key -Llama.replicate_api_key = "" +Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" # Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine SYSTEM_PROMPT = """\ From 3e2a6884c965490de4f7fb18837d75bd583818ad Mon Sep 17 00:00:00 2001 From: sammyCofactory Date: Sun, 3 Sep 2023 14:41:10 +0530 Subject: [PATCH 08/35] Make path absolute instead of cwd --- textbase/textbase_cli.py | 51 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 7289f062..76c75339 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -18,7 +18,6 @@ def cli(): @cli.command() @click.option("--path", prompt="Path to the main.py file", required=True) def test(path): - dir = os.getcwd()+"/"+path server_path = importlib.resources.files('textbase').joinpath('utils', 'server.py') try: if os.name == 'posix': @@ -26,7 +25,7 @@ def test(path): else: process_local_ui = subprocess.Popen(f'python {server_path}', shell=True) - process_gcp = subprocess.Popen(f'functions_framework --target=on_message --source={dir} --debug', + process_gcp = subprocess.Popen(f'functions_framework --target=on_message --source={path} --debug', shell=True, stdin=subprocess.PIPE) process_local_ui.communicate() @@ -51,19 +50,19 @@ def validate_bot_name(ctx, param, value): @click.option("--api_key", prompt="Textbase API Key", required=True) def deploy(path, bot_name, api_key): click.echo(click.style(f"Deploying bot '{bot_name}' with zip folder from path: {path}", fg='yellow')) - + headers = { "Authorization": f"Bearer {api_key}" } - + files = { "file": open(path, "rb"), } - + data = { "botName": bot_name } - + with yaspin(text="Uploading...", color="yellow") as spinner: response = requests.post( UPLOAD_URL, @@ -94,25 +93,25 @@ def deploy(path, bot_name, api_key): else: click.echo(click.style("Something went wrong! ❌", fg='red')) click.echo(response.text) -################################################################################################################# +################################################################################################################# @cli.command() @click.option("--bot_id", prompt="Id of the bot", required=True) -@click.option("--api_key", prompt="Textbase API Key", required=True) +@click.option("--api_key", prompt="Textbase API Key", required=True) def health(bot_id, api_key): click.echo(click.style(f"Checking health of bot '{bot_id}' with API key: {api_key}", fg='green')) - + # the user would get the bot_id from the GET /list and use it here - cloud_url = f"{CLOUD_URL}/bot-health" - + cloud_url = f"{CLOUD_URL}/bot-health" + headers = { "Authorization": f"Bearer {api_key}" } - + params = { "botId": bot_id } - + response = requests.get(cloud_url, headers=headers, params=params) if response.ok: @@ -129,19 +128,19 @@ def health(bot_id, api_key): click.echo(response_data) else: click.echo(click.style("Failed to retrieve bot status.", fg='red')) - - + + @cli.command() @click.option("--api_key", prompt="Textbase API Key", required=True) def list(api_key): click.echo(click.style("Getting the list of bots...", fg='green')) - - cloud_url = f"{CLOUD_URL}/list" - + + cloud_url = f"{CLOUD_URL}/list" + headers = { "Authorization": f"Bearer {api_key}" } - + response = requests.get( cloud_url, headers=headers @@ -166,22 +165,22 @@ def list(api_key): @click.option("--api_key", prompt="Textbase API Key", required=True) def delete(bot_id, api_key): click.echo(click.style(f"Deleting bot '{bot_id}'...", fg='red')) - - cloud_url = f"{CLOUD_URL}/delete" - + + cloud_url = f"{CLOUD_URL}/delete" + headers = { "Authorization": f"Bearer {api_key}" } - + data = { "botId": bot_id } - + with click.progressbar(length=100, label='Deleting...') as bar: for i in range(100): sleep(0.02) # simulate deletion progress bar.update(1) - + response = requests.post( cloud_url, json=data, @@ -203,4 +202,4 @@ def delete(bot_id, api_key): if __name__ == "__main__": cli() - + From 6ddaec7af0ccbf0b465d063e19e420908dd1d26d Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sun, 3 Sep 2023 16:11:16 +0530 Subject: [PATCH 09/35] merged changes --- examples/{palmAI-bot.py => palmai-bot/main.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{palmAI-bot.py => palmai-bot/main.py} (100%) diff --git a/examples/palmAI-bot.py b/examples/palmai-bot/main.py similarity index 100% rename from examples/palmAI-bot.py rename to examples/palmai-bot/main.py From f6d73d9898d849f66ceafe208e85c789a64fdea5 Mon Sep 17 00:00:00 2001 From: Kaustubh <139532137+kaus-cofactory@users.noreply.github.com> Date: Sun, 3 Sep 2023 16:39:52 +0530 Subject: [PATCH 10/35] add mac zip software to docs (#96) --- docs/assets/mac_zip.png | Bin 0 -> 139829 bytes docs/docs/deployment/prerequisites.md | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 docs/assets/mac_zip.png diff --git a/docs/assets/mac_zip.png b/docs/assets/mac_zip.png new file mode 100644 index 0000000000000000000000000000000000000000..760eea316d0afd390fe13df23ec9659ec49a17db GIT binary patch literal 139829 zcmeEuWmsEX(=Meglv1Dy1&S03lw!q8aED^WAy{z<9$X6)cPLOKK#LW3x8e@L65Js` zaMy6sSHAaozH^=S&-wZ0x_0);-h0{1tXVVn%uetJc}cwcB=<2eFz}?M#FQ{FumKnt zm}>X1&{rtweKIgG9tfC=ihht56{Y-OZ)0L^X^ep(6&$CIt)bjQn5w1pvH}BBNyNri z3XhWJGog@M^`jV!Z|z?ns%)))_XQE*PC!*3b;y@fI}vuw5#he+thG>?S zD(>MwsPJalExIi>r)w7jx-P$ICbVi2>b;E-?Efy7W%Zem2L?t%2wnVBOrbA_@v-+i z>>n^d<9=eiOl9ese6LN@mH56vQa|?jP(aNyj50t1Ll2hF^5Yd^@dnEu--dBZLxWhJ z-b(NJG|`;?5tCx+LC|)3_;Z6=0ro>|$X2tt3BHAW?WCUu50UswY}~9RkDV_!>|{6f zPgnY|JSKkTrBdTWCJYg;ZJW$}mf}$htdaaeOm@2zzn$WeC`>32ol<29FPf8nG9nb z)R!cfkTTjoI4h)#APQ>r{c@q982^ex*H}-DlI$x>6{}=-u-c-hKTq&t@72dbz9K5G zcSKt;LhbKKppT@KGqBcLiS7ixMnv#G35t2F0-$L37vAqJeW#j2kzdxubmv^(eh$;X z*<8`rf-zP59#N(e#n5A-PTDui?V;e>N2R?kdo+~yON8Hk#2_w6{D|3oxAi17fZQc# z3+Jvj<*i8}j1-mrpFvN>Bk$=x5n?@iLUk(&KLS_j=)TaSm1g|1-ux%sN=JnB5-UD* z4~afWMG@>8hbVp*w&_`5HTrzBH|QUSy*v=8I(M^se(Qv{%~$qINHm^{kr}?mW6_|N zc3Xqj!{pqp*LHe*_jPaUJ9Z@2oc`o%ntqb{5O9wG2YwIoS!>y!CMNCsi@ShtUO(Ot zB?_)#R{JE8yFA>%9{kKf|R-YyrWe~m5k^L+`SB}Q_KQwi?YZM=oI?{3Na;VwL`!P@ybK6+R8 zlkOhAhs49rpP>%{20>q6!h)!mLf$^|esw2UWGR~C)$JY$v7iTu0sX?g(Z=0CqbEv! zTjEJkPr7+BZ`bs34gQ zhGoz}ao0I3o_PA4=wm3i9kGJ@aSRPC8L?!#%HHB|-DYTeQ({qo4+OVkDw!D4K$cw(-kSYI*c zMyb39icU!bB+%z0B-V7b9&ZSUq&O!x9WK2Ra%{MAUrl^2;+po3-w*9bl+BE$#THs%E z6>}Af?KGFOXvIf?u~|IwspU@;DSh|iO!1%itmolY))<3JAfVg9Gy3+ zkSCiP>$ON4q#P`NjQ2Y{H*#Zo9ei|nOoZGWZ7#Yo59)acd)N|nS9CK#oBUwz;}79< zpP%XdAFEq9{S*Qov^{L&Ys(723pfq4rN+*9mmw{I43{T9elSk9$@_)7!g9UoTXndi zA@;J%a&BjG_;lE%tgKwCY&$JTRzB(I>t-@m(ppl{TYifvD+%sH?k7owZ+T5lQoeP4 zWIZ6xCoT-r1sfjPf)mea51kH&2&)LC326xHnRYalm=fbP;~5yW7~Ko|3nVn<%JVAg ztmH~ffC!D^G6BQuxlR~uhe@iO-vGPTZLJ8aQmevk9o{6JPqSk67WMfjV(!_Vsn>u@ z8T=o9fua$jS#9EyW5c70>otR=hR^lCp1vI}+0^Gw8G~rZi_2Ha6QmqNGE!txNK^Fi zt4UG?JT~^&+nQ@#YF6qk?P}RYOvT!RVjc}p>(&Em4zw9`itC1FL}pFuIO`hiogIj3 zik+J`gioKZvJPc*Ea&GWGQMN1VXWa7qkBbfWYvBBAr!g=or2E2jV#I4 z?`p$Yj9!#!v$2(Z$0v`M!`;eY;3fvjbTblJnd%Ny#8-^@v8K5GBS^7NayGmwf>4~h z{nK;#{)4aXrB$U*3<)|OEgLMqSx#+_3`!&Pru9jEE1)mgTHl`D-Vy8^vlU|`&D4|B zV;BR9na{bC!zi;MOO^`YKNd++OnO_$3i*v85=Ku3_AJ<*=rJ4$ zXD3Mz-05~1*q_sN;od^9QoP`ddv&MpjzalW zS-dfS-$|ct>MZ0*lydYawGl4-zTRp8!n)ftjVQL7saQ~u#@qQ;EoDZ!bS8E0lS=uw zkhiWPffI__Z+24F+3i-_b)_?n@}EXW#BmXBwo;sPB|^4{CjF>xzW077h>fA!PAlNo z(4nj8ee zeR=vgA;y@-29eoso(f`fhRsMef4)}I%2Rwp-^e=TJQr|&=COEna@QIc#(1XI$-=9* zqok{dGJa{Zc&;aTRd)eLiED;V5xFz#Hh-=Wt5~@h`II%CV9vszdt!F}WA&KfIYX~n zgAR|^YVG~g5WM^!`9}Ewb;&|&ZNo~Fo+K6!7^a*5Aa6#;Si3TP^BRDv>qFj#!>!&< zerQ@8m00XdPHyEISD#i4@ii!Z0Hg#p z)FQ_ea(At|&DSkuL0e`aW)|irRst^F=g_LQwLpf*buvwlFK!My!zja!u8WA!$kUW= zf&CxG9(|D5T)N__&dRE^5I)BfhxLtEQw`Gy$T6?`S;|mt_F?}a9uXhQShZ^f+12dw zso!?$_AyZ-Gnei`)7T7a+4B18r#`x(J9<2xap2?D%5@MKJho`Qfptv+A%_|;tv;}6 ztkZG0JcMXE<2d*2n9t_d*myKw5L^m6IlDQLyFR>1-_~z!n@OXxed(CiEr@~5VpUC|dJDn4w>2j@weQ8*|$#Z(^epi2Z{x9V)m&~`IM zm5zsaIQTdb?NEdmYe<{O$zi-fm+xWRxkZ9;7hSrAJ_K%&{!dxr)@zL0|G18cfe~nq zapzyp$fM7{K2hl7SDk;JZ^r~+V55IMMjtNenE!qn8<2kc-(^fS^gRq=Wl?Eq^jX=^ z-q_e0Y-Z!I8=X3hzJOyZr3uEsAf)+q+>%y$wTEsWZmy!?pdlv-FlKhK zvi;Q#2A>N6U9>WG(5G~N4i2^e78Yk`XJ%)1W*d7`7FHe}9+tOkENpB{ z=qH%KuGS9vE=<;7>VG!!?{>tD!G`wcwhrbt)|9{6)i&}0A z{7X%Z|I}oC$NBcJRsVA9e^*rn8{3Q8SfTrL5cm(j{#E&}H~&?UkLB0Y|3Zp?()k}( z(S#Pb&&TpVOcS{O(IsaE&Bqt!VhSqgGg``ieQq(Jzh3|Ij4t02smz*&sAFIVVMvP! ztGL|Sn#E3ex_aHUKYuL33-IN5_T}oyv(k@WzD{)LmV6{~zv~{%S!xh|mtlfa$x?A^ zc%n1|(<#LF$f*(K-8`9W=xk%sw>?+teoCxY!n>VlI>*i%dN_+n48vvNYnIQHCuG)U z}$!2O>mg}4#%;nZEO|#?HjA-*Nd2jM_h6zIakYRpVV;A24<7gJhW(L^jFH9Qy3)ohlm?eBk51crc9--NxD*lSwfs3^|JpF^Rg?D&nATQj@x~i7 z?eXaw(z7pn*L}@`XQzReiT4@~b_r0|k7@v1yUopYPDtjgtSlvEv8dDbUR`$0;Vk?D6ox1}KAagMhEsHLP<9;$B8wsT zZd`lUZKnkDf*1O>O|Ligjyn!{JFe&K^sIPDE%{tZ$~Li^yhQ}`Zt*mEpP`0_u;&Fm zZVq-MqmYIR?%hqi4Nb~3yJV-8DBe!++qcyau|6Sc}YN?#!x&oRyQ z*br}}lh#bm&mFb2WRP1}SU6w$Q>HWOrC&;88viA>Y40bLrzqjaJGbsU6vFu3mxdnZ z^##F~@qBd|M@L7|X9cGMzJpl!bCjPjFz@~5ODGS=E+pVG^H ze7S$em|ug6Vn+A8VW0Vf?oX59xcAV3>%$(_pZGT-{wbYZC*tX`*q2kyY~QE=eJBw|G;^(a5N1H_kWZr{GrJT zd-RCaygp6x|3N~48ED3X`0}=%{DG>4+GsY#QG9eF_&r&DV6TOslO&OEE-?pDJgbJ_V?vJB*zqB>og$3?Km9_mt##g@NF8d^)fKgsb2 zkz{%q6&?Mue!Hsv0Wq7{mM0`2<)U-)h$zjQ`Q~z-mq{@^)7mecJvZfPz#l}>0!O2y z7OqQe3|(kZ0xD54s1-%wU0S|ATpNhhZFG~?^=k6CK9+Sw4sa{yFDY7xLW%EoLv&PB zUR_@tCs24_3BQ+-neA!#gMyD5!K6N&)55|dVSKi_%4WRzbkghWq-?*Fw68#O-s0zZ zoAM_}Qn-zydt1wzzGvTW*=>;q8gy+2R~skgAA zEFZU3VCi}?nOkNyOvSVC>2{X)4eDUl8N3pwt~=c6b#2sqO%PQHf^}0z@-?6sUKrxt z17rvt@62k64&J8Wrh~h_W)L=g`qqT{w`(u+i;%Fek3a;wvO5!#-DYKTK+suH z6KKVwq?le(@&R>}Gms@2Ngk6iH0$8YT)5s)3tlZB5&-8}>cH`#>0tQ}p@UY{vua#h z)9NYA@{YN^z3(*}&YTg%sku|VvFW4B54MW2o#s7H9D(+*jVslBwVpBh*sPkG2}5(* zKPave)ZLH}K;O4OGFo}{N+6^TAXmp$Af48|r8(aVDsEhBaIPoTtLsy7Hsb@M+}zy#f=qQNaZ|dZyL_8qLH+`QAo{4W-2Fp%vM2fk60WqUhb<@2g7h7gE5T0G;u{ zvopidazBCX$uYH1@1OSmfj)!gF*4}8aHe_y<9&3(Ka#Ua=W_u z!HgL-9>BCOzqnyZYyT0oM7LU7l@rk6vBL#h;XJXcD~S`iL)6jwi7rcV({d-dju9_D)X?7U@n1}-Q=u@!wmXy()!HS^>p^82d!m16G-)k)-%O( ziWPeMy9Wm1ZgXyJje~CINZVNHKpOThkZd4WHNCRr8{gkE`cv9Z9z>X<+uLy1_febc zy$x#AcVPsyF!OtvlG!kEQLMo-p%c07PoFa3-8m`}hs{Jvo2K&skHY~ty_#~~AG{c$ zAD{R$M%ju81TQ|AcwE`7_tS=Hh7RgaeJ^kL?wekYkn=~km^qyfa9W>4!jdcj{bTRC(>tZY8uM_xzeWDOP;$5R(0sT z+d!@7vG00+JSOiqUfeG-mB@e8fu8#aWU%uv0bC^zfcXm7gt$1G%bohPBZ{|_&~Ph> zfQFm7`h$&}wCn+a4~oC#q)!!f3G=##p5Gub&hA;zBWk03eJz>0I&fOc$)&qSCMLZC zBu@A*-a#jw0#MiZOuSlG?@EM!-{d-`;W04;ro16Z;q@AALMR?R`_5Q8D$m;!FIpY* z9uGh#TSM17!X#L)cjHs$c5H#(LGdSDe)+=#!X`tgxkT1<@A;^^Q@v8zRa-OeD^inY z%W^64ko>2}=s>#4xLH%d-xGaAY~hG~@JmX{i}U?Jij}McRIF_wfxy|r$r2kq&3dOo zS&#LW&wVmZx9&h#gMfX5I?l7IT*MqwXaQiIg?E1Jr274S!o={_V(i;Uy#j@4h9K%J zgHf-k-@IErXMpsWKHQ*q@Z;>)&5tZxJ+6h`Prk;zmzMp#>avy(wx>a^_3md>t|1z6>i57C)!PP&yL7emnR$EM-T$o=NN3TrV z*XobUzg9FaeFuVsrxpI*rlE}D@IjF{S(gt~jbum?EbeC3UMS-Z@HF*UCXJ zEW#U9y#Vsi@O-;k&u=YzP|J64jE8XSj}V2yQ_A(QMYq={|luLq7ke@!RDBH& zVDzv?5%dSfPgS6MP8PV@;`;+}Ht5kPRBBf^@DJ36W}|zaK3X(I{DC-93TXK_;v|ABZ!ej9wJ{k))Lpzo+(p zMe#Sv;J>2yo0aunQTz>Y{;L)L-)hI_zgqD(#QEqPd|VFajt}Ra zYtQ|8D(Jxi_C7bhR;3-N3e!mvoWU;e4zf^!;DRnJ^vVS0hk~yHnLREcH8eTCpchd3EpA3V}2X z@x@Vb4C>uW9idr8MMcua;z092GN-7WS$7V`k$iQQU+#Zyeqrp!s9t4CEz&gYrlx249s&EWTsstRd#MwmdWHd}OAKS?bYA z$fW&RlETxdRd9U*jUcT?OHxFxg9;~{=9wz|wc4M3oh-oAvgT2-u07_Ox0*PO^d#uu zZ8(QbH{~~+?%b^OG8FGY=7A=B=VPNI<)$n{vx$PdM&91R%ZG1;(dw4>aU z5h*ZI;@04#uICxP^=^p;4~gA;et}G6J4q?`quc+xFCoQ%Ha-6x-;hcb0?$TWF8H0U zR%zM9J!6QcQ<-c=9oyKSKU0@rGFSn56q>RQI8u5O^+% zLAPG5sCF&ybDenOMUr=S1aCx;zJeHY!$JeC6~j25B_g>z0?E5xp;kYd>M3t;Z_giD zUirmszk`Sm!OF^YD=dSz@XfR`O0MrK+ zXR^M7Yt-ILJvo``#dv(&Z*6w8c@{q}^C7Y}+ck=5Zhy z_IZWNfxzR*x3IG-O>ylsFZ zgRE)t8x--BUkqhwTG_G4fM4#`tNVS+A(b-~*}{A-SsilBuBNI=9~c1;gB55#Y5WjL z5{@?vVo*1&XzcoUUt=qIeO#0%CL0+Qz>zOx_Xq&X zmDKB&ApqoGb+u3(I{KX57yXZ@uTae0q{Dy|t?_xUYt_y$9^JgWycucM#+^#I6wi$> zt|1UcSoYyK%8ww-ofkdy9S<-pI(<~ty0Q2UWH{1_FRj#lr%5JT9`g9t5R2+}uzo3z zNS<%8_W+{&u+!(lriWxc1qF;erwxb3L;R=rC%a{CTord}mQQFMr74s?;6}ECnS!e= z7KKe4obEvOL(2c=C}zf@-A4c!)8;Rw_)3v-3a^$%hVYjn5UDa7^4}cE3O(8wl{`2& z5M4VD*Y>`yJm^FgUk;q4c#WPV8&8xJ@*~dW8V-8R03Yw7W}SEMxUMC7a|4;w&?`W~LH4f+ z20m)9&`Lf8pSJ$-L#X?!CBBbpdfScR#$(N3iR8TmE!`(-;jVG<6B7M#`Yl{9A8rSv z@KfxgHPUfK$SwFPYKg1fv{JH8d@JwnRMVim<9( z+st3mq}e=VfhP#>$&2yI!&>`y-`!1EK5nY2Qrp~w&5s8@97O(jX5QSKz z<6oU{%5k)7u6%t@vH9zrEuw{ZYm+;un6QA$6UUg`L&nXq`g7K})yk;yCV1E@x$;f; zru-dDY*UsP6}Aq_1s3#NwKJoJn8sVXLB;jDRg)%K&M}C5M}~U))%QcLi%$sn)+zBm z4B@A3g{iB2xvY9s=^FULBkD_hyju~HlT{VZ7nu|Wz)DDXzpDlKjGSw%KiZyF061>G z>Y(X37>yL{33=8>9i#E1xdp2+>&FkN8;6*aZC)vJ&D?^K!^y#odG8zk+*yXTwYB%v z*0UWz45y7Laf>`q3V>O!NhF?G=dtr?|A18rdOMyS8{eER1aX({c}$jN0pVF?mgn|` z-i~7PVkTUxE^byVQ>Kg_kY8J9a@YJ*fl22Xpq&7!J@%KXpEve3Z6|f8I^rSGhF9$g z==co|LU?70bxGf)$?;+%hSCrf@nO{r=P=u_dZ+EptJnFI%|h|(jt;}E{&HS0>sOIx z@E8r0&a>Pru{9dr_5PtDI0&e)Q3OW~ibIUIrz!`X$6{z?Qci=%;{L`W3?COXkCvYq zo_~2#5(WJ(TtA$ksg7)b6NPfk(n5RyT7w(155lrX=Hpuc!a3u*NDb2-t5NWz$`t2j zOe3e|0mAE(bdSx$YB`oyBlGJ!a%=7)ckf-Njyy_Qm1Ur(j|O*z#~mEl4;gQf zc(jFcZ-hJEyfwX&`xRlE9Hn?@5=je zLCBe7L)3Xn{x@(rp%{Gnn6iBXX z;F$)p#fT(OeXezaOfoDgn);Lw*Jo?O9Z#)UK_KxZ;RCO;#Xwg7)B#7n#!ZBL=m{}6 z0j#(EE)1};@YP$T^cbeq7tTGqRYZQw2}@_6M3~9w+-^eW8T`P?tq{t)11a_3+A6PE zj-Xyi_alfO;GX~fCAX)l)2BhSwA_Sg}0d`00Y&sX-Q(@#ImX~HMRJ0Df7xfD5)y_2c1G*J~CZms)WJv?rP z?$xuWW*mYr9J(|P39pNdoPZ7r_br@_!lAHZ5?z-?*YjQP`I!A>n@6~+ZP>->;Jt+w z`wL>z-ZWH&>)DcGm#Nor))i9kCPvTeoM*Fa2a`}L#kMurK;M+FjR5TgppAiytE)o* zuJbk80C<(#X3Q090YC!DLO zS0t(aTHJHCevH5hC|J?`WH~dC;y4997K}^SpRgRkpRMnRs}zVoo2SorHh{KkUnl6e zN$k4k2Uljd864Lt+hb zzE{2EaBk4lAcGGOwhc4qP%p*;{(hwm1COw#H%xLrlctghqf*j@t9PgyXB-5&=+ zysnSoEwQAH)z&wIyf>JopK5YNE1huN(Xn7aVYzRgR8?slBsP}X)C{Acxax=X=12HC z+W1qVl}lQmCgDu%Vu!g&T!y*Ev74S)9={s^sdaN84<=H1QVP9F@uSgpuYjc163N4S z(LBZkX5k#i)rRX6?}*Ssje1i4of<>F`gjF+`e^GI`(V&@?E;obS}mzfgYKNia(K;E zD^Y|KQ}FS;$l|J7c(n>NF(Corq257~?mm88zq{70s;(=HlxKO7{a1DiDWRRQ*w%>y z|C*L8y^_fTPGGZE|8R27WF@Ela5t(9p>}vYB}RuYq$Kz$5G<00cCIqJ@kgqM@Vng>@zRPbg2YUsmpY13qDP(H6;z$dxM z?Q9#K6VBN;Ca}P|O1wDyFN>VBCmlL0CrqVAH9~AQ-I_!eu#pj)n*9LeY9(CvIC=K% z^|wIUU_I_k1;Ohte6}~9Q{lStvdJeYHlby_*3EJSG}&~!s{^u5+nRIRKJKrQ7Q${cjVvmH2rO~;nNZ-wvf9|brl>SJp* zn#4U>7`GrkN#ngUXS`nLbDUqvq+c1Ye=|DuO$WPYtd;EzD6_8WecG@gjXMGIeZ~1V z!#U6^)4Y0`{6qo!QJhVVVuuq><$AZu>(}{=&OniPRrUAcFq^XJdAHsGQm2F$c#rxx z*BLDna(r_56_}xUBdvqk52^|^0s{;exR%GB%~mHmCi)OUfZ7o9=CV8sJY$(G_eg7{ z#wytZ3wGlHUvjq9ah|DT>(o&ZRzY?xxE-fKVMiUcajpJ(;v;wB9*vPfq?DVgn;P5< zQ#(1DI+4eJM1WV_g5k*JeO78Q=b+u-z+kj*fp#wQ=yGA#clr9(JQ%p@ef=A*>7}GM z=Vcag9{JvH97sehF?$+bIwN$P`zTO*-c6+B+$WZaJmBnIk7QQc1&MJji}_ zBUphAzi*d2?F<7t z|M~Y=0=k_^aMx+$z^bLF1WT|Ji!7L7L z)4*#Fsm}ceEbLP*nL`tif+)&lOSbOvAk#Dmt+RPTSad*eEO|8Q`jQ)Hw7)c;rK8U~ zWZTQIZrKB_s4cz~{#MCD1aJou{BY{rskeuYbJL!e%x_Tag{2Pi@zv3&eE8Ych}3kD z15@eo2-7;>N|fS-2a=s?+g|$+t*abscj`dPz(D`Mx+oYv8fZ;qsA%D13@{4b zT)en@#vcx~4glo>8OwS`P6^e3KQ(i`Eshjwom{6%OBx-9ch1xpbv8c>0w!@}{PIDg zTMCY}f2-PL z97|`wU3a_P_+|G1P*iov@7VG8Q zWXxrb4>_=>-&A=;#(AfZfhhsV@6B$3%mhZ}UYEvZNJKiv38?QiGa!1O&@^{XCG{@I z?afJ2YI3jq6PLK45YWPr6}T!MwCZIBy9@{vr zQ8-O3+8@y8TriWO7~5jy0h%WhU>4JJ%f^UHM+Ok?M5%VAg{tV}NkcKZJ!LPwiXZww zHeXic&M=Tsf@DjQ9qoz~_NNKz)tUd`^*B389lCbtE2#sXJx5*DqtRIn(eX>FB9O6$ z*?DY$C2TeK`d&I1F=#!UTC7YfNd1I%X1QM`yVRcyofRcCMyPZ`e61+z`v4DZ$UBS% zb&bCtC;gSwKmEnpL$&KKJJZ!cSwG(akK}upVJnVcw=2p z$id^DqTKlJzI=tvl?He-Z%?O+1IT1YNWo>cFr%4me{9H_Y7X}q+zeisuU-_7BDGFu zQeb$+qJ`wG4lOu)Bhv=LYdDT<1m;WSBpdLvB(Y7n#^;F|n-m5l#VIK#&?F}Mk4O(8 zH$yCP3m9S#HXr9gAC`Lx^V0Y3QaVnJl*?8x$Pxiczs2DhX5R7 z0x4X_*guy(V+`Z>tMBBu9mqaI=pE2E`e|D4(+V>eB*^j zTaG7UI!wdHO)DV)MzgpzS)O7Vb~38w^eZ?(Ab2Gt&wtE8?D(VF|8B}Juc6@vehU-w`7i zzaVqI!jXp$ykr=Q)X4wkBt(zIT$u8~6%@uMfcEH|-R2gQoW9O`tq)3Bf~{rW($j?^ z-WgQ9$Q|+s=a5Z0i{e9_8NLjCwd@k`^m&_9=FnHNW?~9&Mj}1?TvKVdZhqI<0Mu}c zd7X%GinWTuP=kB86bqe$83DZ3+9X*3W*vY4cOfT!ex^rB=f9!|L(NxIq(_^p4h-H4 z!q}2m)gNrR=j8Ya31=kTxYpG5yy%IvZFRdNPm|c!uU2A-4?gSaHC^uTA_8en4E+rw zdF8PP<~Wv^f&4@K&X(=QS0)m5@e=@aB%#vd+#i+18qq?&@mBMOUl|A_DO39oa{tn} zhWbQ@AC243Dk6?kN|%kA?+qDMA*^+6QRm@x-@{=#)sSRFnzMCx)$_js&bRJ7eujqI zRNmqs2^hAR5zaTU8mB3>Q;(^%>fa1NNdr#=s|b|EbJqylSN0;z`J59BfkFzFX13l?Fn>2S7-Lq zAQQ*KFLy<%e%f<&w93%T)LymZpl0GsplkUE~mB z&3zJjiv*VQ$-0sx9>szHeJ1vTatAVaW8PP_+&m!f%D5W9*lpBfV3TvC_!LViceZTJ zd|jKjSW0cEH{k(4t*e{-L^Yq700?*Ofljvkz$OQ@B5G8C+UJn(p##k99)P=C$r^Z;+h43bJyIXzG#%z66-wdjW*4)zAoJa?DUddQ#46nqshZCyWm z>YC_m0nZ#V4?=KiI1j+A%I6<8>EJTv$a})d>y@g*NQ;`~b-k}S(fAhU6yD0=AQ_#W z7qQzD{zr!HFS z=BO!SvctPKr<>QLkdQv=TLSKaWXyXDa(oYiT_3g1dyRt5qr+jLj=ql0=v3Y63)I6l z;Ey!>UTHj?ul1{)q_9c1Qf+F+nnsnI*^h$l_sF*-m7eT0Do}ujxzTWp`=xLnI(9L? zE=m0o_dHCjF8-|G@u<0tJL z1gUe;R{5^ij#+m;*%Rby+qMP25iRw9qOa(Z(387YeuD#Cj!NGq!A;;0a_Ibx_r2sA zD>da?pj_7$EUg}{?K)6*;_B7X1TcGif}NeS9Vau$=SI4C2-BRT5xGvILySEzcCwnz_=w zjI(U;G~Iw^NU6m?l~L@%v?2xF`if4|c55|PG{WuTF{+_APC+Kd^45q?u!~qxq&(zh z7{y6r;8@t2EDTjC7&i?uS$jWzMWxB9h16B1^Vf8Hu-97r+P4UyQKBh}J*WiJBj1G5Q`1z( zsyPk5*B)i;)=cC0d>?NlW<__(hnm=SW)At_rNLcf?iGw0B|n{;2Bc_iH-~VklV#k6 zIL+1`!=^oM3pHQVjZ%0XJ#t-Hl-~J)08zb6(fU}CJf|SAU&D6<_1jrWEl##+sy!NK z1~y`W3f0xr);MLnUw@%zK_O@mU81_UvJf`SdM|CF&pRb;`1S*WS7{0+OrC?hHYw_g zc%ubbR(jXpeBcYm8NOm+h3<3c@WUKPd9cE4sI4-2^<-w&>-yp{-fqe~r~7njsh13G z;LVm9c!nPlm#2>c*Dfk8E4{Teh&s?1En!)$=P~V#M&slzr$)Cq8u1f0m4Rfm99sp0 zg!WFZ=B8bb5Q4i49&=am!5r7s^ImZj-j)~5I3sA#Zj9y!v3$x=iOo;b!m!gR@M#n* zK3dif;kY}e)7EzB>F!igHY9kXop?U3-jdI=yNrjl%rb-Db4L|kL(K=0IK!(U2n;=hgwhzc z&MpLkII>k106m?)&->eo{`PHH&5sO+Xm=m7~UNjPKBh8ulBX z7Hi+BXj`m~>N?Yn{i3n-Ds8{o_uFMv&IF#!t5a+}eckb!^L5=LHeilBLt}4&w=H$X zeT}Bk|NLTmKV-MqF~CVJ3-&SEI9#nnrT)hN6kIB$75^CY)V$Jcbq?N2iSs znM}InS??PkwBdv@ZNUyda3pdsliX?2@}`JXnxhxk4)c^F zA}PN(#H}1^9dxawC3DU{jpT2fbjg}?ctEkm^PwtL58fWhcTmEY=S_u|YfvJv`J8FJ z0&oo9(b;Xj5k~MtM{hnCutBGB*pCDolGL%`rR_%0J#MWv7OUUz>~6shaYRgLw=G8s z(vu$TY-?U|G)B8u&p{mnrG~y$8l&t6#t+bMPdE~tdQ|R!BqL9(T{+E1L=V0=(Y)Y$ zW#G|@V@TyBNSZsXR*gRl{DwkCOs}3J(!fNKBnBK^`(X}bwtn)sk_Gvi#V@aF{i?z$ zNe(xuz=;B+=!G80d*c;Mw|+EbT`;=DBiYtxxdRe9J89_L*7S)b_ZkDK$&LzKtc&KT zfBH&zqVbx{R~{tXJS0F(tqVqjaEztQme&E<9#!^7^X1j^D3(df?uX3=G)hD(1CJbZ z?f1pmM710wNFsPn-tnm2oZ*#TUABN`rQnZ?R}CRtYoFus0Mt5{g&oK_>Ql>g;H(YB zFSLEqJg3=h5a0WS4?;xt?{8!;q2FQ;yPeNNNTxO+H;80cxnBtye9<_WraZqi)cRI# zJw>~Zst$l>pU1iNrf`HXW$HV-LYnt@E&8>?@%XTgxO~nB`CqmQPGT6gIqv~8^5doD zoxWiS#>bAE2PM%zBOzA>osW~GIKJL|MNIO1RbwJ|n>_zLgZR`28_z|5-vJPBvI04_ z^`@sg4_ZqMbShGbS9!0i(-e>bprO-C$Q==!Dw6NZA8$?}j0LJULtC8aiT(Ty)(i{J z3sm*|Q99pWPL5337-balN(EX&GHbr8h#GiGm`bw$7=fz8b9Xzri5-J-A2`}!yQ}4e z0~gGOlPlQ^*|W=^=YTnL_nUMH&;D@%=q^b)^HtJg^uwYD>ISNO>z0TPIwI zCaJfo7wT{(#3jhkK~fX)XBk1E@^XT= z5uZ>xSv5`)MrM6)Z~-z$ff#+gA*Waf1Jd%(BDfI(5Q!!Q{Rc4`F4@kLW ztx3E?cMZ@^OJl>yRDSB=Zj-z3E*?zJTZgiX99)5L+i6!}wM8x;PiZ@b(X3Zoh}A7_ zsOnuZmmrc|E9Y?Z1fm}fGBGGY&6(U8RV;cx&i4O$bH+S+M9WVWcWK&ropQTUX2j{@ zdU_630b*&qJlbaxXb{htXD6M->`Z~4nN;x>=N1P)*MfJzJagx552OuO(62xqByY<` z!q~b~zj50wiQ*Y^!1paDK6NEarLl6aSB&q}A<2mk0tGqV=y!xXlUENrS!N*RnlyS+ ztKdz!z{!W2$Y3)c5i?c$E^G=;$|Ggg{wba`T9EaI@#B`O!@Gg4NWe z8Jy;F-~aj^_1w#m%2#t`z6qxn)lYeFJk6n&{GqHdADKVE6yVvBV|A~(=DqRUrJA#TgK+K0Rkkb zl`4iWa9o#?$oq%1^BJtF=vf0+JEZT}5QZ z=TqY(iR04FoOw_TCTL}mqupi^WaajTs`j-V+TkE}7$tlMd~0dNhpc#Joi+EAiGgVp z5xjXwcbu34yK8q|3^7_&@Sln+t=b$TOx1L2D09R^X2W4&HuqFoeaDY^G$wWg@6`Pt z#@;e2%C}t~rb9|VK|+vLQfY>kZk1*Tm1by$mM)bBX@*9mbLf)Jp+Sb08XD>5fBU@8 zUhDboz2CL=r&+_A55qO*ea3Mf$8lwqP9BaoR@fCRuv4zVC(0PZPn*Ye`n+tpu=Yl! zN6dX{ZH;_Jx7@(HIKQZnr!EP#^YAj5E<|M=pQ9})g@fYKAyEXF8j9f=-iHC#>%f@P zn@77BicEghD>_nj%D&r|8%5@Qmb~PMEMyxzU-CN;5;Z6M#PNeKXF(V)HM5gq8#_?r zsglU)WPp?fa|0@Fx=)TDyQFyPBRmXjn1P}&7XdxKhq*7h89Z(p>^ZVofbTcX*;nn= z&MAo!36N8DfT4>X6CSf(J9c8>H8Hkp#@@1aEUOL9!C$^SS#n%es~Q%Z^GdYmsx8&l z$Tx~-BK#|*V#~a$J0Np|J@K1}BsvDRoHP%j4q3-7IfYU4kTu14bU`I8)^n2HpCQK+{#4C(T(Q_GUZ399)3BQ^|)M5S_3E-VG|({ z2UR;|)ZDk?W(J3f&C-^6`zfV{-us({1sP;$ew0*ai)CF44sZ+vXDYa(8;I?u}yshqIOpBt-mH?FUav4{TZyG&+wR!37F&U^xthuA!+7+s=HsB^e5n%rW{i*=NH-LR>jQ3x*}k;8J4 z6tJvUv3osDWpi=k8N(@su80aLJ@DqV-t+W$u65*<O(ml5>zMOR5mxu`I*T2Bq`b5Kh?Muy+X3IC~8R`J9fXxluCj)53}GO33DV)SQD0W#k1woHY@#+!Y4=BZ@x{ zcJuLxp=!!BN(r>eSL#gs5=^5+0J7cd39?sFT1#>Slml<6k#aP<*H`&T1=kWJ2k{yf zechC$1SIjUV!2Zs9=>@adXA$hnVCHC1*-8KuW!$Fel5F2+hi~EA@ghDcSQ6Z=K_ma z)hvjyLr~M|uq%<{VDyRdDAlOaNp3 ziJ4#;`^}WbpZd>xIV;6@X1Uld1jgZAiPbwB8j=e3*z|@O$Hw=5n*e(tcB&YTo0-L6 z+~i>ZUA%7(0_+{qu^_>S65)lmspSt+U|*FC8>)Gifc1$)?O+0) z28Ja1cheeGzXv}SR#3Q1CzRs6mNRNn`W|Zgu8hG_z2Te1xBl_@1M_I|y7-|EPBm`K zQZYGj|CBZa5B!~B{P$v&$H4i!W_hsUG@#=)l3&$j3$A{K;FyG-Pq?&^C0hxp?@>ig z2bRCK<75WMih#X{`(w^vqJ3WlAnDWTo{b#ZjY|RhYtts9)^GE#yR?ey;M*nBXw|PX zT{KHqPH~XG^Py^A+>Fw>1XLRPsEI(Oa+d0$p+l*O$h+w+U!+&5U4={DcY{oL5mzin zO&W53-f(NYAzbU5-gzgmJIqJA+8Il?N`Pzoh<|A9cpW;<^^(= z`d^ygwd%2s+&03USX}*b7GkO``-jtnc+AqKALN*{-7!oADzKmSlK0a3eB(4~+P|XMx*O)b?^$&&aV^L`dk1@U z^|>=W>*lu#w;lfyt6}~KwXbfb$S(08EEtz-RHG|_pIsTyz`Hf~Xo{oK`TsC@8aBO; zvaBd8&-7c7Y%TT>PXmpO$X5lbUstZRoG%f3aBPq`G+N$M42?p<{f|BWP3XRzYKumy)I)X3Sh4huneii*`3S{(=y|U zV_{huGfdocKRIQa>Rvm@Iy)X?hCGCP!QZhMU z{E9^rG~+qw@8paVIE#%LW^Z--&ccWjBMiA@!H{Vy%?=wPkPAO*==sbhJ@*z*IO|AK z9Q9!Sa1hq@o6F-!zZ#_N>8@(Ka|z(S7%l0 z1o209rB=!>$~AF;;Ee&(c~>^lmTqNkZy}{`1=ebGzO;C`CBczZd=pn}#*1oSH{B*< z_%!dWuietBc+Wm>ES+!jK`?wf6;q|G)pCaKPfc& ziQ}8R+MpQE%KDLZt6q2K6xoQ3)LB9xweKF;VQ&dFmyIm7NN0BL5PzZ5s7v=SW&&8R zL5QD0xP!so2j`rN7(Ct^hZ|tqS*uo8z@PU+?#a@JE0W49hG`%xkG!q3Un!48gdCc$ zHsA!8?+CO46mB)4IaL5#HZCs`nfTa%2rd_slF19>S3ROJ_CD3NlWW^|`7p?GHLEB; znvy@l-3kC&YXJ8n-eig;!w<8IW?IhWGu*sc+-24){*b0Q(4x&es6YW&COB`ALFGZ* zKdEfZ7NFKO&_#QHaEme&eJ?uuLxp4qz4p)W>)~cwNAR(> zj;?TkaioMswabWcRn-RWi+-c$e&T05@4)r1JH_@grc!+jgbGuxw0e2%Zdq^5X6KI0 zwg9^A0(Ie(C3M4T2J-al*F5>A^T`uU<DUNDt`|Mu5 z>P}^r+b}-Ix5*@R{_ouZX zwTt}Qzgl76D3S`{UOWff-NzuCaD?qbm{hoWu{(qagn6yAsrL=?-fq*ou597dqQcF* zxOXfN@qkEtr;0Z(94CtcI<2iG(z`ef-z>A(7IEmRwGa6SK1XCGa3$flecBMio%+tl zPhqu9B+|Ay(g3blUdy!gKlVn%aWR3&_x4SN~>ck5TJx14ylO5KeC;cI@G8O@b*A z2z*3)iY(NtrEfJZnejh7ZSLVa4RejYeyFGJn95~}R8B?H-{p)DMD+=Ulz{_W6ac+BG=vOsm=^)Z-WZ!ir`q7U|R~efA zpT5F%2NF!D?&(*i2)rQIxAt>qG>o@RKOLT?(E)qu;|Ug2vn)9OpmAK4xw`uE{jHgYmNhX7mNjDPaRkuGo^I5&~LzAz9U+?v3Zu7#m3*1b=)B52w&r}vO zI0jn{ryfE#;E+w|l$O3u$;e^Jx8G45YhmLeRl~+W zsP2>a!)*|(ufzTHfipj9lH!|JJZH19@$|63aK_kHD2(ElbwYX>gsTLO$EOSCn6?U^ z6C1nY-eb=v09p5?lqE15LDqv4h!l;?5kP} zgXO}s_+1w{DdvElfy^#2)j9XGBzaDArI62*=yQe9Iy)+=u-Dz3+AU8rjYBkdo)ix0 zZMtqxDzS>+e1=xp=dL~}(H;h7%^lq@cV0{#F^YJb6f|4k-8s2R8C^Fmvu_i04Y}!k zF9MnxVss(a=esUE7ZRIXVkohHi;D1GFnO#UBpGctak)3N$VZ(JQtujE9p)*0T#-7A z`TR$T4aONp{|Z!JA9Jp2?AZW_r!SMHa_2I#R+!c(e5?LxKr*rXs#BxxICM4FfD4uu5(}X ztg{s~`+RUT%@GKXAfzL^wPmJ;{!Q)9KSL<7bziKt+@h`3XllfU5SZRq%2x%c7mxmB z$(6T7-Jk;hGG8?{M8)&&elkT%p8Zfw<$vYzPW6DvNTtLdiVxC|Sl6-(@U7pJ08^e` z?~0G#$8uyqUXlL8n84~U@nYjNQqSwHdh7hC17vHyENIQ9uG;?1uZp-(L5ir^VU=r5 zW9^N3enj6ymS*PIrA)uV_^C!p)o>YD*=~b+(@(fmuAp{jl989CS~U}-9|s+FgqhOCl_!?8xuzYM$xUyS-!XmzUD-4>#!W5ZG? zpf<&b^eLJ_63tCzZR^4wCmo@M(AJ4F=oQ<`UlMvoG)=E4xysZ;op1fl z0A?7iR=Q*0Bfkmkc^l#-Hs2)`mW@&PH>MM9Sbxw{A)zvuRdsbDQ{PM}MpkKJjy!1j zVysgXVB7TCZVJqX?WL~8z0JHH4w}J*T}1%>IRqKph}-C9*YQ&HhuUjN8;&E~iW5E)TuO|%J+^VxQN7O_m?NUpV@}=~>-e4-|@p*~&nIi?3 zcLxM`KP+xmRT+Z06@Imvv>-c9WbON4Ufb5Z+oPR~yfDw6Ene?4&L#8zk}@q_3a(xs zw1o>V!9+X`zwd)bW>k0@^dtbc82RJrI_ca8o~nv@QFPti0$VxZ+_4MihYkTx3M&-o zJoV_NBx6IZ80LdW7I^^9j#(Zf**@Y=04{x8q#*K_3ym>@?qT4V0Y|92QPVM^sqZf_ zr2ccv`B<$b0l=@vTJrB2+a7tQ?_F!lzVt?lgDE)m9y(F(E^$#%>{s??kS0}E0pd)mD%G6KNLe7~ zx1L9d-aW3IyW-$(Q(g4Czl{MY&;T$ZpF#1voxuCnYx)>~%5>-2k%yZ1&_bqfXw>`q82 zf-9|?S}RVFGXHX{ z(3b4J>h_#nbTnrIVCE4NE7! ztqEpiWDIavyu@S#AFlpo5a|LPlCj5F_uEc(_v4wnWBQNl!6g45YY1nilBEp&=bXy= z`IrHk!NT4rI?=QA&oj-H$kUxx(nepn^Iz$2uNA@jolpS}#gl4Mu4X{ng9&RF^hi5f zY&~F`_s%>)jq!cb>8#hC86x6iY6c#W3BgVGy;{qN#WKm(i%$Bxkvbi>r*y7;(is%3 z98)8IS*&uv61c{1P7QWea^OD2BYDqh2^rMi@$7b}KdEXPzj(#>QC2p;P>$i zOy2!jYTghIVLSMD>6i(dH>>>NVlFBGC*bKb0)CX?>4E`~2%l>MXluTq+RZMla0JQe zW?)hF{6d?;oGV6Lo+N3=ew~`u+F7e`0cBwh0wzz_?8!uPmHn^iygLoRZ)cT1@$MbR zUd?vR@@Qbw1~uo<1LA@CKT_|1Fz6Y^aUB%Z4vUALY=YFOTn*vl!uV=<>5 zYSbXND+75YK%|`x-;aEND<$e9MF~KIHIH-Q^1D-|;U$Ju1J<+PmJ-DQO1J6rS%4P{ z&bxes{`q!XeUhZ7JQf8zjyu4$qn97-7N3H__7!y`ll;??emy| zAh)p901KrFGoQsLT7H&8z*qA;zH${|$G-r3sFIYsUv-uW$RflJxHU#-%72z&;?hH< zaw)KOCfbWLj3)rvD*z9AP1tPm4-EXm> z>Qr#9FH$J#+^~lgShDaylf}6+b0Dey1S<9tS#0&drx?E58Yqb+`i$W~d2L zt?7UIgM>S8q!b9*ivC}hl*Avbyia zlJh|e`Rna8)E~kZoISC?CaVqL2*rsW7@Xf|x2fsR%mNDLu4J;!q75Y>!LZab`gSF4$3d2XUDmlR<61-Q2WT55^( zn~NBfW$p{DaIV`OJ4qYR{mpS#<5iTqRaw@=_Mdr|kpW<7&B~!$;#f2V zAh?zLo$kLr^nRYY*>4hYzOpWmH|%k+03f5%ctH3vb^4W~JPzh|Rorq)D{+6r=d*tz z7fDC(ekmG|Kt<5z``v_wb2my!+^&(g&Hn${o5%+ZBEp;uVVeii@L2D zXW_LNrDIu|t1N7&$sA6_iK@MWjVJs#1TW@#>;T?@P62$1y2oHt{{;sxCu#_QGg{n& z47e^uC>*90otz3Eq13Ju>2|3Keg?tCY9yzRMxzQ{jlkbWQilc+<2o&S`5xw#h#4QF zS-|ejCR}}o_7{$OX3(I@`MFo3NOoTQ()MS#;g4yT`9Q>Lq9X#AW0+L6!H5v>ZH`M# zd!ynC0u)1PPinGtl3at{iRZ(91|k5m`K9z+sJh`r&e_!|G_QD%g=`K2i&PuAF0q?qfY^IL>NxCoc1+w(;9C4G@v&7jMYPZ)= zqILoq-Y9$N^t*H1uN}?3W^CtociZ4el1U;^?Le9C1Q~%%%_=7w_fs=BGH&xuvblSW zrrk%ge%4wq{S4IKxpUl~Z(tZ? z2I|#=a3|(*%OM_AO-^nDl6R%l%Pv*43m9omL~KqW{Sg11*zIylm`@ZfAiV$-4A)NG zz?7bS?`C(i8YL@918jc*H51{b-`OIjR8^7cy)Q>W+5YxR5jNiBhjK5oFuuk;#=>M( zmF+AmqggodY1)u=X6b#5t()`p`7`N$#V4$r87YW`go%4kL@C&(sj;Z3vB}HJ;uDG6 z4AEwW%f5@ccJ#UK$aThL07;bR$WZ_M!h(Rs(`z&Id%f!YC}65i%u8aUJ9|*2xrfF@B^dB|36>iwWXvt%@QE(uHmoW3WG=+Yeg)M$aNs& zIItVZZ7dkG%$?$!z}Ogcn8V#D`uHo{OTiUmre1Md?HYW41y&Sh8GuB;i-zt!K5 z-s$5&y_~X%K#?WWT&f?JWxsmsIz{zmn3NTW(ZZ~6ut*UNFP;cyO`!RrTIO@Q2+eX(h(4eg!%kB_S@2jWVtM?!vJC#c6c5O#@v zcLjd568@zr`T2S_f6%~H*q6c zOEl!zuyXH(9iq>+C&RucO!VA-I%-0wbkr|VQTIMJ3EvE}hbQU#w z9s~db#3R#)IF_z9{L*+f_)Dbi6d%9A)(InNuj=cKiaY(rzOA(8J!u=iEVZX6a zC+m#Akw{j*2Jf_bH2T+$Qz;L%QPJ=FL!+nm12zlZ**>(Wd)2I=z=rm6|LX@IZ#0mo z4zGe`JYiS7f4Xr%;lyM%TbwDMy>?T!wbxU8&=wT_pxTA^lO3tOo^NgoDx{M_$j$C~XROW~!5 z>1naNs3EEr6fH4Bn~`R{QXHOXN*K-bTHd-;AzPVH+K;5}2G{)v!==kATe@w5-qRT? zZ0bK!QJ44jt(O#E7_r<-J3g6i`rMeVA6i(#Tx&m_xn!1W8_|6_bZ32JG5kP4{UxW6 z%j^_}J=FEn@(`cAu(^eD5Ov*~(?bu_60f%~Tn=eANeADT9G z)l^$Nxw_bxr&X7r4BipC1N@x^pbT)0#DNXz`%I|S;dQDAHcn!|uvmjTRhE6NWiJu# ztt{?KuDZkDzZbm{XuLV%FrPhI7r0LD!*BF!Jxbt7xRZ!(b}o8pX$Cpni#(;HA%M!~ zz9mOY9*}75eJ-01=V`3i7NIMlgzonXfXFk^1+b9>8i#{{Nk+aQQ0S1&1 zRvge}-Pi1DN-hJ#ncHYxB^Q^df|v~5{~oOY{p>)vRt*R&H_8RDUiRF~Jn`tYU+C+F0>0KZ8k3&?u4z79n^9(cY1L8O_5NA=kH;qZn~#WU21_F0ZDisHYRenLrJ-%BJyXd z)sczdtZEvOfsK(5pN+9>h7(6s@gvC%A2Z9CL3%Z)e0hc4FaXwSZUzivV82lew2 zpgxt_Pj?wf(D1wBGkt*iRPPR~$Reqxotxhjn7W?a(%-xxmf@~3$RAgFsYyLaZ316i zjjTipoYECz0bc0NMTX8>ln`TM4nj7g#u;OGap!!Uk=TK@50r+7o}R9!+i&go_;<{c zjEwm-EY`7s0JXgzl_5!R@Y`%M-H0!t#XZO8rQ-Hnyt$lGkEW`H0!BkeBlkB%A{Q|- zMaJNRp8)^GxU6Mk`&F@qwyB_cduO_xX-iuVt?bqsd9)<={blC8#BTyz#Lo8zF6nkt zP2$tuww$B=XKi=q_s{D4orJ0;*gt<66D@2MF`)Iak50}%!Ty8){Nn536I z%`=Kwa2!!>G zP;)1`PUT6~@$7X*e202^5BxX2BB6Z)|1(Q=DxM(3a#1twZ3Ywb-d3HVvnt{XZLB9I zsPp$oC`$u3b20s|kWo0c^@CtS6mv2=hH&D_YTt^G1qs>|ns$?bH$Akt{Y?SddnokG zQ&4&CL3D7I29MOQuPnzzLu!l>FX+7-BZdM*_UcJG;nx)yA_kA5Vx~gwh&~6|2hOMK zTW!geA!hgN##^ctJ|)L~bSP%7mFp(?G3)~dmjx9*_SVvbn6vA;h|hJu>t5veY1kf< zZEMiccl#v7g%75v#2epp6uz%#8~d+I%=s}gvEp1$`ej8 z7dm06X*_Ho+PU!x_97j-#@^}|AFgaE#JEQ|ZX$Q=e`pVXdbJWUp;1h=QL_<}Pi~oc z%WyelDXCkH1j^_OziT0r7nzy(MDOruBw~3NpRkSVm>aR7Y$1>&NLfpn1wwlx!qk{+ zqp(Cr;&$tJJ>5mpaPON)t;KM$^G`|%2RY0iKe`X=mTso&b_TKqpJv5(dQPM*a{3+D znLKrQI@h^jN$m2`_n>JhcBdkP4HGm=(TVAY{^0`~Idw%-6S(yn<}e8O)!C3hhGq(_ zY=w4zw(&?Dr;H5XN_Zst{Mgr(52(Lugsfz=jD517X>=@lS)kKo`jmc0T#yb`;>xwe zW9f4^M0#n)(fg8gv>#I79f?@8l*$+MzLr=b0Gjt&{Dpm)Z}I&UzBqozX-k}8&QFVB zg{?w8m`T?JsOH^X$v6U@X2r$xyZFKTP&yS|-;DdUA`UiK(!{J==?G>Mq7@G$;?_7& zxOJ@|(cPNRXwuZwc<2ybync7Rui2+xXJhd8KO2vKwIQrUKzx5;pKiYjzahQc^i){B z7wgc)XY9GpHPXim^*ZSPUCx?0&|3V0m(_l$l^Qe15nt{@A_c%Ia6yf?}_jfT|yCJg#!BJlKjHi zwOF-$P5*Q#^hjD|6a&_`q9-dJ)*xHO&HrYe&l8J{h=#l%cWH{Ia?M>6&q)ONEDI|@4RbLgrZfTcM!Xm1RqfIam>56w$~OyD``M3;;Z08M0~ zYdd)GNd5|lnK|(2b=nAv61pC=HYI8*FW05>MKK&p_}*P^4){g)G=^>hr9^lm*>uh1 zeowNDBoJhvDl>_p6eT9IXc4@QzlZ`ui6ej)RmV1 zbC~_tJ5@P!Y?$U-hp#i-@+hQVx=-@O@~%s4Xe0)#Q#LB=tJDa#t_431Dp{?stlh?Q z0+-}rQqnX2aQbw%yso;Ta5;YjmXxJ)wwTj-W|wGida4|cD(nL$h&%|>U)p+-=NWWw zkoO>x%lTLAAj|3(%v6jY7^RP;Oj0N&6GFl#7a0HOidSur81*r2#XWmwNXHhAruKbV zk4j2sdt3@f`RT9dsU&QF(qE6f+Q+sQ&_=&p+v79NTg!JyOTNzrSK;~C1hkH~N0boJ zYOUWQ7qSS7Iyqs2re@{4bX80VMc}x;1mrkb!ZYXP6IUil8@lYkFeFPW_DbN&!0B(v z`4VgFkE^a2`B=B#VY^X$%-)aFM4nH)7d5P=)Lel%&qMS-9@T9mp-iU1G$c%jPmQK6Y8XuT~}h6b3NkGjy=exUo^+ zJ|=604w{w;B(l~wU$z#6$9j@XIBsiLt~>$!-X7o{*?uC$ZzyV!n60%dwwx33A^~CuhLhlfwkG$3juCr4i_Oh@57UX`(-$u_AvLXIx31Hve3nrqdX=wH5q6!HdNet-hl6gM zE#l%E$Ki*Y>q#bM+qU;RT6VwPjQ}VJY{6}`L1|nIO}PYjjO0HRtxX$Y^{ur@smHhh z!_EGX?KnJs-$ogwA?aHyGgAt#8#uF@`+n-M-lb5Y``>|+qV~Hopb$`{ujB{(_~b+J zdV~>LILP{esmGKdC&!7Kf<@+8a9HUW#oF^BLS_At2%_miz^N z@1~-rO@NpikJM%s3VYlw06!7gS19{t6|#AGLz;5gRJ=DPBEB=^aZjR z9oDV-wz($YtS6#4-dA0N^n|$EN_1ruzMdv9qcP(XHB%;jkHB3xGgxU{xpBO#rrUXl z@_y-HH~gxfm9&vUDjvcW_CR7S)UI2oZxs*UDnPy6p3vX_ky^^mEY6%E$*8yY0fl~X zmP_-C@#Ft|j(5o)0F&50xln$P)__~i&PzpO`)e*Med)4Pad8f~`E$p% zj5?tj-6E;g%W|n$GL*qZ>CA9cp@vJVwnwoYoftD&(o^ZA5RCI~`e@AVJ#3`zs$@H# zs;;tOWL-}T@p8fKaO25-^kg!_KLrL1pHr1z`BzQ4tqabvpj4Tl4sG7yU8*R9V83Bj za~;T#|2+S^&``+M%98?6GXDH$Y>)_fACZk(eghJ%g>3oc{SkR#4ZmE+>rpD`H4B{S zSqh@!qGFE=4f=7k*@xzr`g=TYIqk)ABf?Rv&-~Ax7EhK?VVLN&tC4}fSKiHEeD@H2 zt!R<0#)v(Nzsc&8Nf&%(2eD3Iem!Hca*_v5gak&ZbILXIMpR>igrrU~&+S8Ut9$p2 zO|<_3u$+Cs29CcozCh-G472Fk?^7SW85L3Mn4Z|Jdau=r^nIAcxRn+Z99jS5A?~9e zcr#`=QhomFt0>yI{bi8n?F*I2Ts{*t+nO(AM$YxDamid`T^OD>Gk#?5^SBDMud|U+ zh@Zxo(S~R;b7pW(ER>;V-zWcJX2&==OryTj6ij|+^PBNCNJ6%Nz5a0@HztTByaIkP zG6?G1S;dNB3XOj1t(VZdvruk3hf^em_$Xz`z!bD-hXch)!z9z_HlI4`j(eiq_b~ex zA%HSPJC5M%72*caS*EMYWiEw@2@Q|e6`R~}OCGu4u(V)$z79uQ^8U!(sAGirk0)aB=u;@ zXBF;v-t43X!g`7)#&PBH;7K;rjrl#XerXgUCDm(B_di<7fKUJ(sLpn_G5yac;NQ7s zm-4}LRQgYAX4FmEG-eMP%wGuSE9ucgv{&U!uV;F4{3V0N$qjhQB|Y&Y9J{M>CxT={ za3V06L(oBK@!@M;$uSKEo}GL7t87RTy)eo9_=aH4u&2^& zzlt7JOIRP(4z?G|>7S#x@!t~;?I~TX9Y5o@wVuO?iA=1aK;^M=V!`?i2mBGWk0tOK z6gJ=Ua^sd7u(ueA$H_+_XnXKFm++RYxEE#G*rf{s+LGsGG3*gmdIn&y*=FJbS)l2w zCXV1yIQkkYICmnrjH@HkKsIX1;N>Thg)XzE7wC${_B-wHj>}b!<7Q`=%T$VM)b+`; z5e*Iivx6x~?bvb;c9V?Kw>t@gUbX29i!bD*KZjDzWli{-4V`=G8s9l&X&OJ(QYau* z@+0+P7(L--;qRpS{)B_^8p5snU$xO-&>-JwEe zNQvwl%g~<=BYXumX-l5hGp%Pn;lps&CDvpO5e2rax0*JI`~?*Kt8KT{=&+$ND#Bhu z)b7C^4s>AR0UHbprqFHHkM6QUZ7%#K7@aGCt!Hw$Kzw{RlVyR&+{0}3!wvC`&-5e{_2jVWwfC)2~|;)Ta6Y&6)YKQ*Q8JFDryH>OwUG zw5hA>#xWXNnB&CWNl8M80=z$Gy_(tRb6Rs64o41*(bpM2x(3T)aGz4M>T=6CSj!dv zFb&wd51q)i-8*l9(8Krt%_I8;&c#`NR zRkEsO7EN{1_*>!bpQ_vPFMWF_se2jb7}VtPLj!+fe^xtTSzbO-rpt19UyU23?vG&f zed&m>3wZBE&nXwNWK5He=`C@Lm9AK__50>X*w=$I?3x*6>jZo-3p4|tBTy(H0!`pm z+Xksu%X7wZDX`7=c9+bHPqILM`&?()fXx1Zb_XZ}*;t1?=lY*V|L=DXK$ea~523yd z=K1I_h3ju){EnuMGe) z&75fbT;t~M#f$G~pkr=)IRh37d=--=Zp@`8jcx_rEklw;aunPn2nrz6^ORosiVCk72-QzGf3sJ{z7qj=2&xAYpD zQldI?$AIFXftYx|DJwpb5~3zn#_*)$6KUt0j}M`kjl=F{pR-+)2%sTgU=v_>(A2R? z!#y?a)7}s!!YX+Q?o(=^9IaS{ccV+}<$@iHcR zRw^V{0=@y&d73Yj@-^S}nIB4^8RMcHAR)PYvEK+cl0_^cJ1NKggL2-hExXfwNSQIc z&JdQ`d~>h5(0Eq-kLB2?6maf>Z&dA+|07-hyG{n&$^tV6pKz=SfN*_0egKT-zbv7Z zFneswkfUe9+$6N&ct&Z;m{6RVK~gkWPl^)W*JCVG><%Sch4|_`7R=GhFt&WO(G*h@ z@{OuNE~zlcJ?$p_y)>Rt6Gb)zZ2mLOO=mB3AAB~_*q1VliqcMIc{yw6siNHM%l<2K^g zsB&~6CM4AV;P;By#biS_2uGkNayBbI<=gCw|MCJ*(&UmXoRW;@gW8cI%~dZ<%K1Y& z@T$`~($Q?(6qqaVT?2$XVRMWg@&~UPX^y{r@Hd@KZjG0#rsHZ6Ar6Er#uI@mJ4!rX z5HT3_p`$v-^l@PLsE;C`?!BbiWNc716dHvOazTT&R0)=4xm;Q3f_46*zk5IOqT*xs zgD>45wMFNfJ*#&CBkFAt@gM*ARsOxethoORs^e_B6-qKDVL%%f@I=9ZZV8;BpUh*Vke}qg_Cdo4k5fD{kLRS2Wg??rfBJqUL^LMOdcwTeQ7**6Ws2%z1 z8AgSI?Cc-)@J}&v2Q#H1}wJOaL96KMg@t%cD za5obFp;r;mWt&T}p(555C3{0wvSBC!Oo{?Z62n5+|=-sr=7K{zv2YZ!q_a2Z(&c@+az1DkB`dzKZIpXB391 zPw4*;jZlwnohfOmJo01<%VVpNCiXu6B$Y)AoE|^NJqO0sat`C~1;KnIOQJrf#?2q4 z;4)XHdsb&C2DB%&LnlhT{h3hI9@HVm)8X?#vmBbD$l4bu(@QQ8b5_nV0*0SD3isJ@ zuG%kD|8q@MPeCktqC#vV0z#K8ApJgTCo0V@bLE_w#h0KFP7Y<|rP6;{C-eJOCJsk6 z&%1&UB(i4B$zrjI`suuJ1l%Uv0fI`t9vIn5Zi~rjZ{~Gz*LkE#7k9sOi@H%<- z;KG7m>sK&_mPK}qr6~92<3=H5mIMevM$i2Ew(;bxL&}JNhte%u>=LEvXzs;~=}3Vm z4-{*5%v4dH%+iKb||wZM?>T65DeQq)Iv@y+>>R zlKdcRB1UvFJAN`Wc7maB!L0>2&cO~AszgIx(~d3+eAmLv?ztl3O5xvYTJ2fYBbUvq_>9n|;)^g}q1aFN-MkK!hGY&I~IpECuT*d3@~4b^Db=G(#8fYjSevgJaL% z7mj^q?drAGQkLrb8l+HS^_^Sm)&I5V{f|GsC$s9Xg2=gV zZX>w@PH3be#CD%66ZOHq6VGTa)r3();*OBpjYgqB@?q@s_aDrmS47WPZg!w{-)0rs z#~Oa9@iqweV9+ywn01(#2_7+$9kmT~U`dx)`B>rySSc!S!cc{!L4s5c@t1>3bwag-aI|&p; zL5p~^tw_6L8`+X95@;stf~~5<{1B^t5J)ff!DUa8pAG7#F=h)qBy-55H?_ z2dYvuzEnHY$1tRUQYS-1K(Tl_NHkFO7XJ~HHO8bC3lv)rAEk~lxbD&_yjaabPAbz&1v(gH`F2^g7Eb%N%3&t-{{BC@Iup_%NYiG{S~hhwC{Uv z4vA+noxBdx9L`3p%2K1$Z%L)t-w>+wO>xc|q0b)f+W+wkSU{tE#l9-Y|0wZct$ZO7 z1;p^px}&Q?fj}td$*U|rsZlC4R7BrTp+s9U^${)k^lXSiR4+!Xc4PVpL&2lq zVoqWl%eCJ(Yfdq%4{$LZc?4Bv5cc>Nfqi3Cyiw|*rSR7n;7HZsG3!WERzLFn)DGRo zmw&bcz3V@vvpI1RZL(W6)(F5AiL)l0p&KkCjYDIzykt<`utMuj243mS)Ym$`@pRva z3hSrJ@BXtr_y+^zpB?h8^1tF17LE_e6eGx}ixJuI92Y>G~K}WOiJU04$?AQ*?`uK_8nS!$dWOG3z_U0+HDk#wG zr5*v4IIL`shBhuphbtlbPI_yP=23K512?`EkqTe=iBgqbOi9<`5b0e`)N~Yi1W3=I zfwfnvmt~Ii7c;7+94=j8lrmG@Vn{mkzBMkT1X=^{E2(vxt#GTxqH1(Ydfb?pRlSSq z3ZZ55fsu1r+#u4DtuP~t9Kt)!(#d}s-RSKkW zT0xmb$<(nuv*WUhQ)i^LvgwnWwx4Af4!^B>FM{@tI0`X-O6aFDx`nvT@1J4p-v4at zm95fFI2OH!V$Q1aFIjLn)oq&Ewq)~pbjV4BO2z1pylyg^9>~JVk=~;JI=B*6^6f4I zor*d_h1gToh}NU<;RBaRGY1^#$250Yx;|6vb})s#rZ$IOvcO^&cgwo$JUL;@>zPgTZ$5Ymgtuy%Ph?yN zY~Z5%2P@w6bvC&iZ)BU^B#pO*ta8CF(%>lh@44|Jpt%*)P1LNx-SShKbPr5_Q8#`@uzOJ-qa@qy~kbL9RnspZ%GznTdb&V%X>l*^E+M#kaCe8zZ=Rj!nc12D?CwkWkXN~U?>*<9b1tU!FBRZ;(Z)*d=4*k- zoN7#3d^FKh<`CGYr)S<|IaLXq8w==CnX%N7x?ye_ELeciuVY-2EP~5ixS!~mKQkcb zcnLWPa_YQN$aD~B#~~?p#64;nFO8{EVOo#g34uRzoZx8*&5(g3{kptXmTgt)o3s>U z#?16e3Fb@YeS28duXK##vF1#Nh{ge$aK#0h;oq3Hu1)t0pVtX#g2SMG`2EHefw!m?{eCc7Hm0D&>_V1uW=TXM0?v^->#BOM z%1Fn22iV>ZV&csncwLDOy!+b7EIiGGn}z~zzyU@943m_Mc|*j4V83NqL2xzu@7BCZ z;*z=)7L&UCW?Q8=JHRzLG|!k^(wFCro&)!xnO&r({cip_&15 z>iF2vuUHLAy@su-0N*jtL~itgLX!#Ls0`KwcP!GXlLoay;{pL0orY1j@6GDae&gRKc3FMk2nMZCZ4M5- zgzF|aYkdew`~oIuVpJ!z!7x$8Eu{t!?xC%sR12`>i!Cx%F<}j80iZYNaHECz!@)Vz>{(ir{kr~)VWT^0{+jjP+Q_>|7A ziE?5yu-6I~L*2Df>p4{xcb^mFp?GLvf;~{d%H1@tbY|?8$za($v*-$QJt$7{?WYv9 z*NkB1CUja+XVSyhavBi{!|Ri%Sz(qM0XKg z*@D$KgQ?XEa6rTHz-0-Y@E31fGy}HCB)~5j7f(rQsFgdQH!aUSQz9!w$9E?meb+$E z;3G$!m|`NU4UQ7t_K*p03A_d_{9FVetOU>KY*O&_i5B2eW}>nlj~ay6w8FYAsT7uN z-~9(b{y%lx|9est2xEOPE7$M?7^4Jby(VXtr@|E=FeOkdvqGT=1;}Y&FVD_Cadr%g zs{QWA6*GWMFz++#2s!giGP`{zNZQH{cvtDtF-A?FsWSH+1(+Bll)4>BSjFz&?dYQ9 zR*9WcwK7<)9y%=u2;mKSw|QlMs=|`=oo6p=F}!x?I&6J3rcAhpWM7C}`$hyBtc3$4 z?Hipvn&ZGFbP$b$33uGkR@?r;J11aNvF?!T=I+60!JWbJv=`;0-0TaRAFmU`k#&I_ zCw8~JIW-RwCRDiiiCZbmff_ef)8EjEp+j*84mjo4$S&@5t~LrX%XaZZ4Y&o!@0@ns zm(#hfz5#O4&cVLbps4i(}?@g)$N;fl}qLb8-XV2p0s1fC6n4y!HwlN#G| zeq{Wux_TV|=)*&jWdLZ%nyiBaT#FilTp4IkIuBi87R36Dn+|1E$ZtvajniMVF^T`k++tT z#RK{ixAyONwSDa#o0g^zjbf$_1~gL`M+A|=hQXM}F|q(?lks3;RAZ0~*oZ`-0Y$vt zL4waae#$%KUB_!{7ly9l{-dZ+QSJ?IpnFE7P!L^fHaxi$RA-?f8zS|`W?c#&^S;tf zB|U>Y1h(W(N!l}oHPio5F7n_J5BQ@xgD#>}1I3mEp@JOU>&0U;Nqb#&W`b3tU!lnt zTW=n|F{K5F;6qpwHaWS1L4F)2JO@Y)` zNH9X;z0rRFaHpW04~b6Ei83Ml?CiDT>lK~j#-5%gqg}uatXA?%1VAz+GVo)QoZWt{ zbi4_jvqE9l0%U^Uk$gJs^{@|-{%)oSx+B|0pmz#ut%Loh3VZj&V^exDv-Ugp&M0Pf z%vDW+k^)=Y7%@L`(aa;xs{R(y0nO+e)#E@zsnZCVhdmT1WpVR!YUt?ZCmZD~n3r*O zf5vx|V&-i;C9^R+xQ(l)8I1DTx13~JbG~X8yv@4^3E(se_>m;1iu}Ol|L2>75|pXl z{Lbd`4uyJWmWmf-|5=WWNT=ajs&EdzytRHW_v~zy(N7+u_1&R{HKvX~NZ6N=Fcepk z;Lhim@+uHh4*MAYp;~!90e6fLKFdZMRz<^!r;1rGL0)42LX%WsY>mRahHU437e%yg z2&{bQk|#Aidm+TRkgSWV4v>1RNTOr0F#6IGxCq%7JishQ?snT2S#SyLh-Ky2Iu9}Z z+UmZ1%)}_yV0z;~BD<4c( zB;E0CY9g=qUSdFQY}5j9_C#$GFA5((g|YEz_h0s$hT-4=fU0Hwhvh+ zTyX`dL^5M0k4?+6tA%~h_$7o1dT-oHXQUSP%Tj!n8WO1V)}#YO)-fVcHP0M-yC{uT z3GSD2TLdBCi2AfmR?4qz7AEuzgK03a8*yVFZ?x0bX0)qA8fafOi5aIgf^0RpL@7kS zJqdIb(h;SZv;RDL3y;6Se%%zPifR<3Ee^yILjenR@kCmD=9+GM)GdZrIf{!ak?6!X zZRpZe<+o86{$Z}x%($-xGyScuRtIbeoiNmiCc2Ro!nGk-a#j>pbg=viGOcTYI8c*p z1omOg|HqyX@V|P(d!GxLsDyH?u-v2(UH%B7xNgj}g7NhY_X&D${Lx_LW)G%eu%=BI{b;c;{eEBD{v+9v zwfE;#Hnw`%m*8KPa7pA9G-rKY%>sG>y!O0OlS6G)feT=AZ;eq`2|Nm3%cI2~OOFM4P#>QK`6^lMSGNVD~zusZ(mh5_m`VulY`G#XMT&!oC!$~4` zqKfk=UVwK8dtNPa>O9YSLG%L)(EY|5iI5v?b-G(2XSagoAdqYarhbeYg$sdG#;?n0 zW3oQ1@-D_Ga~TTW`sNa}1R;hS;Z2_8p1EN~F2paS_rpvQN|BcoH115l4h#X2Z$@#E z@gP-PNt3fN3m@fpHG7Ds{+VF!YEYfL2lXvr3-z0{biU{BcJ}un#}6%MhDS+E1hNVZ zjg1?~%Lu89jh>oyvHlmRkBfV4>7m!**`=ktXP&mk&FRWRki%KJ z0T8Dx%=yPn3VMfkMr$4=92@>()ud!70q_fufh0w}HIS>ubLD;}X5^T!INhNhiL@5y zO<_W(zFarDgzHisB=u0N!I8_5I}#4v7I5PJ!YE6l$Hn)A8dNMcnhY64-_R=UGeF!c z6Z8t)P5KYE%*^_=hv-dR{;Q^ZboZ{Wv4wD0ciP_M3tD9+B(ucdXL~GCm!6I0M|qf6 zeBsuul$$DD#CvOf(S6I>#dD|B+l1BuW5KmjfBwVX(_z^`u3-PXAI@6c{fM7y-nKe6 zQJMHq{1$78wHcx&ZXoUK=uz#d%1YUL%bXKIN^U0x*mARTqv{|oV8Oy3fVbW=Y;&9Z zbVWahi^lU|nDii&41CLS@V^@RI2~AzY20|kNghIj&dyjT3FOC)0+Muv4(={q;X zD)KjS$U6qHn=4Z#`WrtYANeagjAxg;>7K&=NsC{&Fl@b*^+qZ^+42CU6Kt|Ke@;dC zny-H@cyG~cJUqCYPZoYe9$|1IUTXcDA_+|H??bBKhQ6=OeJ>rGm|*_LLcwiVI|Oz) zL*5weiKQwiYE-L{oOJI7A!F|pE6p|rT%WWJ0_xAt!Rc4-ivI(LVPg9aZT~$$tL2tC z-8c@v1`tF{5yy-E71fhf{_V4ROrhT@ze%HOI%;&~t|w@1pf8?(Q+PM5ZwqiHnO1FQ ztN0uVcGydEY?Ik6d_xS5$joP%$ z3iCvhJHAnPn`Lcibc9w{y=u)&QeCS%YoIA*SJSO1QKzb##+MQ8ZJPw0_n?I9?w=39 ztzyFCU`d%N>+T(fZmW-{xVIb5*_1)0DJb7jY#eM-EvR`d<`^KJoDhktrW#+htvL7@144MBl1+2h7k4nf@!hVJSDVqo z@4(L3`qCI+ar?p~*$`Wpw*~Ru*K=W-ar5-h_b_cM+t+cS0rm`OSg#Nk6O$yItZ8;U z(5px4p$FZm{;1cFzNA8zj-&~wlepWj8tFqyat(7g`#O86eT$nO4vzS-#GK}skwWXv zzGs1!zA%YQq!Ytl@@j!F{bP{<=?3ZDC?>-l4jV-0>`WlO)yDJjltA}kfNR`!+9}{{ zRDrz2&?w-BrGA~fwcPXS>-3*euBEPC8ILS(gX-UYveO3sHTyFa%}r%g|BitEJ6NQp zg*3KKoM)a+_5#3J&+Rc)sd0b~Vr*ynB+G4$RtnBmfRM@{0J{9p*^KNA*N+4hGM)%3 zv{DXKiHPf=H53+ky*8>OFXLAGr6%GyF$6FAHXc@H9)8=G(mHB+w$dNt$*Ts|BaZ13 zZdO9`_hxg9zjz+DNtFELJi6X2D@6m%r?rJG6XAb-o8kEy*bE=jXS)yg%i-((aO;in88Exk`#t47;kql&g~uSk{AK{#v?@hJSfZy(6B~iAoRS*hP-v#Yo0E;UNNYj`P9wIr8QXYtr?Q(<|kx>C`l32C-e%NLHhcy>EqZ| z@4;xyTV1$)Z!|Kt$f_c*qV#VCo(R3pPQe~|cFutlPMlW=zb~?*9<`3MjL5Va!<$Ow z5YRaL=9!~h>sFR;?Lw~?6}gdDqVV797;T4%o7cZ5RSlKhKe@=sTZhvpFSx^IE#%l_ z=W&4Kd`2-+gEsZ+agr9D5f{nS!%Km)$g@ft<6D8hq~On~r}n1HddYtoAW!8z^CJ+V z5`64gJ(}=ry`y<0q?)=XYP;@tE{nTfj@!O_)%vt(vom;T{8du0Kyk0=Kj^~#pR7{M40-2 z&fVids~e||Rbzgh7W`-wL`yw5THkYv_jiEnohrxZGt-w;eLobQ)ysuqqs%QW5a^_Y zND`DvbcjuuQq0-Q@cc08vnMT`bB?X&rc@SLxs09`SBXk-rj_N!^hmpPS5S2$X?@L9 z=~-~UyU&DwWkbDwcy&IokM?uznU^I|y=aw99glz%;i-*a9=AqmQ@pA$It5806e`^} z+@J7UChVpLV9|`0J4MQY62pO;&Q6nq4hasz$j_jfAS8O(h4z*YlLF90aH*W<=}+>* zE+dx|FtYs`(D;O;Dh~bGGZp%D(~-~HJ4$poH=vD5g)L63vz9tqco6@W!OBM+R(rj zs>cB-G`>LxkJU_0Pg@(?E)jzNl)dumMI)&0sGECOcs!fmn4Bycbnl(}Y-iU?E*oP0 zQDBSW=UFG+&F6aBvrPfET*H@tq8F`7v@xJHDH$^-$^ec_)wXm+YzIlF%P!@LqY10S zeouO^h&uJ*4f60$3pL0c29Y==Zjwcn-)ru=;#y3L<=$V{%9aWIkbJf1TPF2zu9X`% zG7+p?!WFQ|k1o@RYWF_@(a*(5@IzI!6{eqw%kOPO&pEszESgizkkyT^Hi6BM*hv(` zO_-7#)LByh=fz>|Z@lvh04B;UV9gt)M`sNCV#nid#Y<83lC=+ zG%TlQ)B8tpawfNSQ{z5YQahU(jYb4OAQ54iP5 z-o28&*T`nML}{oSPN>1yX9ci#CXz*o)b!C)Lv<01_93_|ggNO#61dWsUo+AG0V_Dd zn@9-+I(4i}wy{+=unYe>4TMKI{R^v2B-&1QKKl3%*!5JlqlWRA)0FC|N}(yOCz8NE z{)bEK_jl9R;T|t_A;bBJTEa#{s@aXkKh-tCp3>xtUhybHSoVcn zv?u^hKjrB6nW$lf^GkZ?{V0o~f60sJD=gvpte8P)Rudjd*qkx_%rtmbzehbCQ7|G) zw>Nsrh~efYXyHH`1lN6u0i3mBLBE0hZJjK4PHT$iGjKMYg#r_szQOKFw8^(bCTk0D z!DEzE5qsH3vB-n1#1dg{*y=J^rZDosd+#%r&{ifxL&HkTGb_K7pH*}4fnF(RO+KA+ zIjiCC;n}k!VdG^*jp{(peg0_zeEifspcrRwTLr)N>KKbUF_7BZi?p8@q<5!x*$v6y z!B*VA!s3T5cDVmVTYuB$uT$~??ft>Q0k%@(D>7b#&xe8YmkyQggHx4m6_qr=ubIaf zjA_Vl#o1zs()3P(D%anq*SLIAvbG0jb%qqbgk$(@%kAfy)O>t>_O&)s=V)B}evC~m zv5tP82PGF|iVqHGtbC_S4Jigis|*jw-3W#9_;D4vwB2TSbt}7?TFrR`&b+1h#pw;} z%8*}7fAN#;fvAt+$34aP|0uuy&ux}}@t=|3F?{dylY{d`GZlSgfEq4~Ucz{Yc^HH{ z2fY8%xj1gm5pxIqj>9-b?EgbqanS{BQkZ1aQi3G{mbw zI^;AHbCwJPU9NBj=Z>+z&D2$(L`@ebJ?wbDs$;LR<&~2R>ry6Lu&SRyrie(hx8KOS zct;EJr@YEik)=JqBc396e7!Kw5Xsvaxy%NX0j(WnD*tuLVj>ZT2q5!J^P&cy!k~aTd6fPX|qImSe0gsylwfICh^2Wh?@oUV9tseSY7q6HgI=J7#zyTxCd7K;$l zQOhO<4f5^#vGf-1_P2fDz_VeoewQP05Hcr6)<@i{RVp0bjEw1+FXRt%K1U>LCeC`5 z=s7>25lYc(N}XK)9)}4m1l)}vx=5GJSF#Kf_jdG`@11rw?Cdpt0jH*8W2%Jn=yD=i;T{9 z-B35bIuFAq|G{sk!k1xGnZwtyj5&b0T(#t=4Pr$?|&A zNmuY5Q@pt1v@30C!|5|h3JU(zPsKW>29u6WPr3mSkR&_)TICn08&$B!1e-X(qwn%V zoF6jJful?_WF(UIR&n?c5@!!1mfxCRevBi&pu0YB8nmmVJ-GAn-LRIuGe(nw;v*}c z#-)q+G@vO`2NE|aG;%NJ9ZOPY-x|w4&Od${oYdYObApAi>@#H)I|@-U29tJ@MXxXV zU=sBZP#cZ>BKjE#X2%$TiZy0jm;oz6q<)JnUsn>k+Id7JW=Ks4@dgX(+qoD6NCvYU zhdf&w$)2ty0?k6$F>VaurSb#pCuN0C1Mm9D=zEgn0c*;Qs-6MCLg^d@LaZy zRoy}M)I8MLPYnUH6$oL!!3)~yBu4@MEOBn# zWC?Dn^m6-FJ^;~=XxzAktxC7Ot<|r1z;1gIEwP-z1Ke5#;sM0#iTko)WD+@2R1~+W=0}gI4*WOCNJw_0{ z8}EEKPTsZ`RTu+}8p+r3{eT|;P{c-08LJK5P;MFR7ze<>( zHRIYyLPkfhB4YFh!<6mkhL``b)WuB)Id8&Sar;82#fFcLC`7XN$4rRDUOHnB=cBOb z%Z9zul4tFEI|X{s@ey&w?P817hb8Y`zM-v{2Mlze0bk>OuVsSvYy>IzyW72fTq_!E z4H-`X4Zt+0{uBrUrp_D0qpyH|&wp|Mhzq6#!`oeZGOW`gPuA%k-rnBb4c@`ec#%d&yM}loRrU=NLl&2`${1_H{?#if<=YlO7 z&Pam6t&uKQ@DcaLWxF7{3SCIXK!RO*m{lj*4kx{RiHg*GDdA0N^1)0IIIGEVYl($p%hwbkU zGfL~aaD;?(GHF}s_8KT}v`DcDGg3dibc?vTXxE)sT42@PXB$&Hi(9!1mVHG-xf|v^ z(*AHGHRp>C7s6%VwXII|8d0s(KJS1hY(d;Wl=S=`)@WLH#HTy1_oF|PbUaAt0 zu4w0EG(KP`tfRUta5bDfOwQgUXF04~dRN1VGZL_wPS_Gl)EO4z;iB;Tj-q|mDr^ur zQK0-DqI8BGmv3c1QHE7HR2B8}hPkjf&sCT=^4o7wEqhITIct3wc0yv|c z1sj#>|D75-fy}zaFu@4ghk#FK$wgrdiU;p;!7Vq#Dua^C7ra`rtDx4a=A%#e#)Au$ zMaWo}aR2d#{x$TR1?%g@$s%oB#T~&R_Rd8hO;w;Dg7~JBE?}f^<9%7$2JY^R_;U$y zO(kBKUicAy1D=D9e$mpaI3e&6OS)ghzE3j^?|`<4pw4Qh7l0&7Hy)-&SwLF(i`?Rb0>>sLnL? zkq543ea(_?pcjz>61M~LJ$%Pid0>;h*g5@SS61H>R=;tPeS3a0HfkE)YKhU(I(@d3 zg9SaoqVaR4)N`Yi$cBwH?dWK41n(kEbpMJG_f|dE8KTFQNRm)bKt#0M-d z3I6S>A)q+GMbF3a-iyFY%qBIpJJZQ@4D-0`h?*XqVo*F`Q2UjnEE!R>QKS1g&HZL& zhv%DLR$y>JRqN-;+3~Xmr;)DX?Hw;>udgYt+b8YfKZxkEra6%ocu1Ao%3HHIL`2};8rs_86LD2%`G@*Af-xqL13jxU0! zbjZ?{yg_7V4otSG#QgbW9rqb`Dg%g%;k8Im?_L~mSEEO%&mm141tky(>jwj$ykZ;; zO4a5kdlu5Q4P3nIK`aTb4NG3qgHj0Ahb}gmcM&$J1RF@>u>=`k!}gjWUJ+SK+TI{# z?Ild|kiY)j&8$B$AnU>CXXE9ZT^UUx+XNbX5MDCGVw=w8;Ov$&FKtna)e0q^Vcdk*Ksmd(KQja~1=8#!r~uBfiUayd_~h6DIv*`J2?x zbx5{tJ_&dX#pjGiEdJRaLmZMDUDrG*;0n+UNcd5~Yc2jAs{Y{>ACBcZK*Ucc z|9x7)zgs;y{+SUt^7poT_fFM|e1BBmrFT?pcB3s&6Oorhg3lP#S$X{V9UB1Bia}Zn%?M);z z?CcE9|59>azWxno8P2*8lub*iWjE37BOw z@87CA3G|~PGaHZjB|`82IJ1&9S8}y{nA-oww}$@`i&x&7*d)!)bQuA;d|mtt9e_EN zAAf~)mCv`GPPC%8yb|<$wa48OcMbnoXQt`0O-)()6usM^>N9Y?!=Mul%1)pfcq;+f zqZ%ci?$63vCPtgV@`M5R>~-sHQ$<|2J;yb~roh^>f2XnGY9>9Aw@yLha9(s?Peush z!(fGze^JwcgOk|s2RFW{@ka|VW!a)M3XpR5qITYqM&x-5pUmCth#HjwMisJ?w~}|L zHu8t@?;T4c!W=KXTYw^e@B;V3*zH#4%n7<|H`cSS^M?2~2wD2-Z+Ej915dVFZIJif z1muW91&0kT*Xh*g=*go=Rb7gQBy65y`Cq(lg(*Asz33zEe~+VR7Yv$`reg5RXiUm~ z878@3-ib)j(iGa-u@x!RtV2ylU4Y^SS*K^77!_jTbYe5yQHJ%^baFneUJ(w^JzcBZ zRTAg8aq|q4$5gd1leO$zRk&PEoXF#&INIpwWOs9PX>uuQ|l`a4I{?9_0(`vqjOPed`F)Ke3G0Sofw zoz%%mX2_HUT^n)AD%6=5tS3bxlQ;NM7Kd6@0_Knjt`id;z|tK=6GnNuaY7NdlmFg4 zqQuEJQ{s(b#`3sF@zfn{iM`g41Q~{z3w>W^eC+bE8GceC!}PKEB-C+>*#w9L zn4%!%Tx(gY2>!OZj((eXo89#){lcSE1}c9UzSBH!VzZhc2{~F&+uoZ|CMwsm)Gc2^ zv@LsuI#byxG=tyYNUu^vik<9Z%S3M5i>e4q)txxB3&~exDDc&f;Pht1n_Xz|9khGf z9=#Eh(nb`ZG(5JP)WvRC6J_uPwQ^FFVG^~MykMv%FjK7DTyx~;3(CH^B%ZZTN7NBV zd;^J5s^$lKBqu63V(MhyY)n_r%yL? z<3$^hlzXziQ+>CLC3S0UV`8uO5-;+i#czm5!;8(-(xIckCts$HX<+9R5M>F8tq3GG zXUsK(z$zp`Q=FjB1~@`{qm`c;k$5Lf=B}79wX^qA)>aGYZJ&Geu3DSQI`L7a`lWpvzX2F}oYYOx+7aQocPR!#?+lS4?4(EZ7@5!*{>V zk3#g0_>4YL-d@_u?StCv)09iO#&aIu|4XH#3Fbe=i}q97L#=No!yR%>o{jTmy%$Z) z8s9fESUoYBKN4OHFwc4;AHt(SBA3!x*!K6%EJ7ss&Q4Q#}Elcu1K&7eeVM z_GN!9Ocs$VWO@4LmrLMC;}Y*k{xU<0GoB|o0D5Uw{Hbq|ICM$VW8s@J`DUaKe3bmF zk|n(Wd-rqd;r?Rp?O~z}RQ84OWpjB@DgK*38JZEiyjJ-M8fr38dmi@&m7%$GaYt;f z8hZ}#jf*Hvzd}5@?S+QN+r0t8hu&R3#vHd|k9{|E3NZ#vV{Pqp|IcG(pqZ}Y)O5p3 zCdyY{2%o_Z$mcm8S-MUwH>|UDrizn4AlSbhBtI7gg91ch-$iia1~Dp4R#9zi90l6G zz5TlS25N%Lp7MThpZWWCiP>abYd>qY+x+yvHb`9N9Xq>O2BVQ2m`|m0+ZyJgE5tM3 zMSovY&222zgK5g72#|D3bzPzjxMm;~oRf&SJ8ag@3YZHSKazR$A~pM_Atc7>mItba zztgZ5!97!YJjPlU%f5qoK-%hD1NME)kvx868C$mBSL%Q+;!PsA!S{co(v*vfPUH%N zJdbM~<`E5cWgLWOG)Q7*$#qD;D*MQ^MONqA-%EusEsr!kyJ)-gBhyB4MLscG!&!&D zqJKTt3jMRK%6Pjt%2uB(Im7T6`lMlCR7Y6lauWGH!Y-wamJsRVXQN-hbZojs0fv?g zk4;NrTjO%gn2^plA$Lc&b#wUBIaGurU3^7hthg8|xRUT(+qSoD+ziv-nmK8i-bnn$3jaZk;M{Wn zqLW;=+T-kNIEMahep<|e_Sb3f!xAb`A|Rq{c;i_mxLc|XBD14-J@=ft03AAF9Y^Z) z8{_RrqMYxc0oD| z0{h&l)GGhQf91aZ!HA)Pdo5Ct)Fi-(ac? zXkvzBaq?oWj6OsPlK>^Wo}ivFoi|$8!GlII7=$JR-3f(38g<0D9&`TM-aPpE0~vFX zZ=R$y`gA!7;8EP^01FqKEwN}{lbRuvZ7FUzhk!Wq83w?VPhr%w3*DS-zfk5&2CAvw zuYPCm;Bw8%3M8=A2vz()u|+a@$Ef1zJKIcsO!J2sQr+kmzY zZvV6IdB?mk%BTj|$D_CQphrnh(f--TK?P_#j3Ru^iqjUG(M^R>rW4vXs`e0qtp$l9 zY@4lD6NGxIS6uPI73Hm)qdRu?*F`*0gay0oo4av>ArgmP(!sOcNVMztwY;J%MSoPL zZ=oHj_d$~Ir4ay7qoMWhvHm)Vg2HI&IK48^F#>EqS?EL;xO}(FSLQuzH+;CMk%>^Q zGlu3H1-(P=L~L#Z5L$=@3EZ!dLAmBhpMkvH%LdwqUI9>x9zhSl%NmhZX;x1%OzM92O0f z7;y7dyl3m?qsjTw;{DFe*Qbh#j~lUQ6OfaDeb=gwe1Q=6 z*{-%xV)oPhCGo*T)i|=R({3ZgzcGP#DlM&4!GmKWdwBYTd|CXj_?Vo_#YbGSO%rcg zia!E@z&CyRwTiuGtbSJI!nTH!yV~*p1L?)~59!7Bp>#A71-g{urR}fgr!lzl`;}6M zTI5|KFNiE6O^Nwa8~rOmr39`1eC7oieS`Mj=biHJ8xzRZ6y(qqK;)1dUO*f60wko# zOYu*2P~e)dB$hp+e^oo97>@J-s+?_X6Fv+`A#Nx;QpQBADa0+Ci|h_mV$Hi13S*V=Vb0OSq#VVU7oi+hHe~ zMF{Mt82!kAexy9xluCQpi%Z=cH$F;VrbyFZ5I`*iRD39>|KYT5@k5}2YY^1Y4=u=4 zkja5(ES(|={A};r5pf6zZGMrpx^Nn8#Ev!iZx4uhe}R2g1N+3fgG$V``p#Ov=u=4& zVV1kc&E~&LZ`hBfs|1MQ-m~$6!q31{W({HzrkMju6Z4ZD5Rgn6zg;7;wv49ec4J77x`LP}4f9Go*XbAM9N5BmdP@<=QBGZko zZl^PEQ%%)|+kt_TlG)}WDxPQLt>+uAsRPs*mpC0;@u;uoHS#eIuR8zPp4!YjNrZT8*{`9iFaSKi147qT&?U1(`nP4OZ>-} zaqak5CAe|s5oH%ByO?^b^te7O(nMmVpa!E1P2RcDXZ+bIAHFg~@5t54v5~QCO7hVH zV+D@D?hURs$Q>cyKHE$2v4<)S{D^*Xx=IVzlll z^|%cZf%oflanC|^_sFR7)k`i9)J3LF?u=UJN&+vv(|{L#-rLu zskKR*M^-f8&Bn{P$p~BXa5Ae!MFNSgu&Q6V6FZ#t=m~{bV8LEyH;u}-=^9jG1Ahvj zj+cM!m$=0ioSSEB18Mxv^$~TRE#v!}MCOmk4cHNJ&P=J;l3nwe#3xBSjX|kgkNUgP z#xMrMq8AO?Bf*34jKSm!R#Mb72ZOafr`Nq)(6X9=fmE)I;wsq>GX5e8pFKT1(ypLK z85IiCwC)p`Vf9KH?aOmW5OqfqACDJmC-%BdJ)L=aMtO)s7EAYKMd>aIR3>}mvjsh0 z&+BhPS0?(tjg%@ZDVyT0$eRJtMAz4UQ3j6a?x9k*+qqW0jIGFzu#ROHd7&``6${QP;u5rpqk>Q0U@~Y5jV(;E>Pit&y_{h+BK(0a7a!dZ zbm0lItOz;=hhyI-pai{V)X$BE+n2R^C>r$i1D za;{MDxh!j0{H3Ze@)aD9r~Zci8QqfGmuXuVE%YAAoK`mS1uvv9^4&br`8uJ}_3LKc z$<&;;*i7#iIW(<_6R8Fv&=s&L2pAZyvXU2kU6Yc-dFs{b7P!Cp z_fnXXwo%NRm{YCKP)IFV8?)3*_SYfnM7HxM7Qdf@Ain_=6FKo-)8d)RCAfp8(+w{iAv=VZ|_TJ!QYgk z;>=;M3b$>ZWv;09k$_7fWl^QAD5LDa?iUFunUsE?eDB0~BNOyuwo}GR89g_S>^O`Y z?WTDl?XRk1>briV;63oQUWuO7`!!x=`5qrQJ*iyzAB7k!?|v*AE_9fuZC50eo_O%8 z;BJ&0sybFVdRi}S@>`2yI}RTSj0+Sy9a)y>k=TMnBa`+;gk&VXSJpI3zu7RMyW0xv znE7^(R#G2%@BPG^)&LR=<}??r>i!CHD_c6jT1@U6>D!XIn(cg5g}t(T16@8yvw7@) zxLV)LY_+-6kK3{p_^Ab&x^tt)fgvdq_>ifsYtobIIvqiyrmGWzwm)I4CcEyD)a~*^ znyh)LkIOfh;~AZw|3d_o&W^%k>(8`O5u)=u(HW&28@m#M>#%qD03t zL_Q4ClJeR340DgiX0GPSVa%xnQT=3o6_+NvlK0AbPE>(1^hlnpKx zpSGI)^0wc-cFty?gF4B7>nCw>u4akAI~Dl>2!v z@%B{8iICH?(qyPEIx2Y3ptC0tjRb83orrzgJ0$+H~DM#M5-zT;LcHrLT zQa@jdTj;}aong(J#C}A9_vQ7y?)?w!SI1gyl76hxb8Ej+{z`jE->;!@0?F%=s|J&i zKv}lU;jh0_u=M8BwgoA)*^(>$`=$Yi_lz|25#e4I_)u-Xxyv}17Xg! zW*1Gf!l&;C%2tpn=$(MuJ|@|0hL)d%h%AGPq$2AfeHpIwL1eu>$>d5oRgd_UoyKz@ z=?Ghyr4ftGR{kH}d87KL+F4kMbMN{Q$SRlUrCK`9oT;3)>pKDx@1X<%hJ-Zd`AM{Nwpqf8k z9ARgaE@ozB^zm@W&s%7!+~x$?sEbYY$OYouT`h#3!75$4-69hBx;VNEzx2BPPVxUx zM0q_NumIkpAV{t4sL6omZO7y%_g!wivz(pdR4N$fWw6m+O>YU+ep=(7!nauA7;g?bTlRcA6wLPDAnff;`m8t_rHt#6Mhhdj`0*YRVr)sM ztCcpT6i^x?yn zRr+mXC@L@sXVLwP`+!y5;a_ZxHx!F;ivjSzUP7pc5>Rz5Se$^?kAD z7dhe#!48t_4x3AHy-|+d9shuz>z~-`m{&Qs_73LRvjdZMYM_#y%9*_CQKQ{oVaPoE zFRuG@hxL}Lrk5|8gCCT(UcM)}7*2sU%i6gfUB15+xw-n|N1IP>8MqV5c?x{J*x%5- zq&e&HLqPjUgE$H)8S8FW#A5K5ii}htAcZvdrdY4|oRaT&=P@vzK#%S_OLJN-8kfV* zeWk~~@wECT=cyAzldMw47MfYSSVXwbw)uiBwOT9*m}M}# zqG34dTkq)oQk-vG5$vzGIwrX9Ty7%D#rO*Pg`EjXHkPuMRIcAytN5e6>hRR-5kn`{ zM_Ex&khgPfTMwa2-=b6D*g|-^oxaF_>cSrIRLy}BEGqg2nKDB(d463Q@1zX&!~)*IEgb7zkOZfrlb zhOCL410Sa^sgCVl=yW%(9^EM)9eHVfqUI9hOXPC0tnV?W418#PEaWoxQJPdFl=(vC zbnkNoXOw(Q$Y;-Gi2BKB2|Ib&>_)81yrmzLl6b={mfmfY`-MhL^;uDOjB>8&>-^V@ zPNfw(0;1X5DbH(C#-y&A&NhKfy3;GN>_qalHfL66k2eQX7jHk`xjo!l5>m|azZA-DN2c4)O6F4zx*EFrH+MMnU_!;lsQxd;-ZQER zb?X+kf*^`Olp;ks5fCX-LQ_bnAvC26QbVr+>4-=RO$gEh8VHE=F1>@H1Oq4{y@w{f zx0`*&_uX^ueeW52|70)-@RYUYoNGR7ZR@V>NS!QMmK}H$TjEW5xg*VbSyKYe&MM?V zr?MC4jcAH*Rw9w=LIKVPJ0YhRmqj#}Kh%9siH}_@J3rr$2e}w7PR=nbACPaXQF{8| zo3|H)(lwGeK-T2Ie!)T09yuYgoGDTz<@oM7XW8;3zIV$+P@DktsNe3P$E)nCeK9=V z$4kto&HtWfiW6H@3wyNW;hD3uy7d2m75_T4lBU<5BUpvXl_iV6O80urI0gzOT)j`2 zMQWW#^rf>dqE*Cs7$FEXAI)DHR(v~39tYX()BK0u&Cc(MQ{4kHk8P&iLWbXSAC<{n zxeC4J+_vOWzO^;*JbKgelyb|2DOKT~E@{rX%c073&Br_kS%;xZ(KA8kS;?IE?N8Ms zR?9|lquTo*M{Yw(i4d0lk=co$GJ5Guf8=cBThtfr;$RoP3>&=PF=ec|>U=WE@V1PE zsiJhwuHR}Jes8<>^h;TzGJ*&E+PwW(du>eA8615&SgBtu=&KiRB7?^aRkJ+**7z(} zzDB6~>K^|c^;?^@DxsK)_GJAsVt&@c`#n!^3z74H_>Ei>EAooX6~Ux@Yc@Ui__6mu zt2>(A!cvBdvLABFWSCBCUFR>)41`h{j?4}`ZES-dUlw~E#BE|HH|)}QEr)7lY_e-I zSox@ef8o`|{>FK3IP*R04-#wpB5B@kL%_8@2Nb51_kOF&OXsoP+! z;Iz<8nc^<@d{V+Q(JCEx7{Ke{bw=9Ec-Iy-S4J7|IrdW*`RErcJ!N%A5Bj=7(CcCN_zN#edGbRdp0|+nb=T4mrW2StO{Lh7u3@l&>}8c z;KwRK-70l|wtKS%nvhFvQd|l|4_YILJCP&8$i;6 zSQ{TnO*92a|CtqKzoP#q##Q>_?ajLI1i6H%!>*W#0}sL7q@D@fWOG&y^UF2wtrz;w z!1+`(Eo}x$8?uQf0tY85iV5iC9Vz*Z1~~qGzdPwMcVHs+JvL{34SeD*qdy>d;;8Fo zxF{(t4Dy@Ig>Q@nHP;^}rMq;U9cc1Cu4mg7P+{AS5~{s6&@?~FK-~QiBNzK8+r-%A z3h3CsHmiX6_4vzwg7W_e`N4FmPf0u`XTswVCkV||ShS&77xV$B!4OfKDw|_f^s7ma z=f?RO3_Qq=BXgyIjSa z-oH=oBJr}n>K#ZLQeFg%CiAi%!riTvouYv|PDR9BdDJ-8{JKomuH`&jym!}#hfsTy zF^KoLt2tc#n3rIt;&yUR+}R)oS4PVuKv>ltR|_7(#w@Qd1Tv0QS6&sccX;OU#|J)L zd{WbzCwX3bA|tcb{08el4g`tv)bcGuR1vJ#J0bm~_HvX9f+aBn8NDKnu!paFQJ4yv zk0!H1r$GI@TV%KfW(waAmA458Ja}zBV2cn%abmWKE>gOaRuWLX$~cO$>@CO~b}RQgHH0ca|S+ zm*6}8EQ`+{3C`b~$3J9j_!-iG|9rZiA6UeZEqW@|zjHjlq;%ewk|E%A;+DBGlDDJ( z|Ke(-W6|PI3aNPIMQ~va5HxUV$t7|X5DEn`ri<@%bnQj1^n5; zxPG6t>*Rd;hl(`$GdM2sekV0Hd(McjYNXv`piMq#wPxB?&RHcoIN4ltCiWt!BHk5np+wGjudVJgb zwIBk1fcYE_h6hn{bAljVQN(#&c5CDUgB8~Z(4t~lp9ZQuy>Y}umw7W;PbT#%(d0k) z@qb*!|ARRPcmBnjz4dyVuy=dgL33vj+`n{D)w%lTeUgUK0JON@ou1^xWr5O~B;%uN zroPLUPygI6Q7Ej9V^kv7pi~Q|kO;S{v3N>gl%@{45R!K7EmGb86YU|}%c+Af5+?7& z(L&Nfp09>Syx8anx+u|~-M*PRZ#60t-d*O+s;cDst@MeFJZnh<<;GF3>{`4Ed$%n6 z4kaxB4IL@-CpPS4xe2R#4|#e3V!Nb}{j=A#n#iDOzdyEMh*0nP_%G`nu1BmUB3f2P zoVSxR!pLv(u{`{w{1Om~ZC_)^v1v4Y;~-9jz) z0$YY`RSjPa1&K7U%{*aVj>!AH)F7TJ0)Z>|Hg%;M;Efatk(IofxtJy>W z{nWs1g?yYbpeo!6g-X11+enU%G_}p-SgQ1Z>{|a2FNN2a2}5+re*?b%dsBkv{tAg( zIezafjd9wqRy}iH=UNLhO2uhZaCNHW+g7XEUbwp6e3eONt3yuASe%vArRiias0bfEuv&Ltynd?uQ-rkiss(Kz~0LwKL03{Pb!T15U5wRSKZMEPiNg07A!n?Jtk zus!G9z3TpTWqaq<$n7#^UI=f^Ym=U*Y6RdaRBV=hy5wSpef(@Luw(9#3C}fd0?=K9 z7X2!&AG~v~P<1lA`FNwGv#v>Tvylvy1`ShFh~55dUZKoOhmM0bF>jbJ|Mo3Xu!p+p zd@+Jft73+pe?U8&celL`V_9nu#-Ml?adTc*gC(xlY~5Jf9w==(yOt?BY!#%F94W_k z#TN^z%f*q*f}p?4NDdQ(<+&%j|%aX^}s`aE$Wjdi2 zS=7L@3D~Fp;gVgz&8%CjR+)1dlpG#%mvYAoWn2)4I(11~R#ud%a=LC2M5-Kk;c0Ry z6jPy7l-)MiF%xKx(LGKcBn@p-e_G*EkOLaSb_WMYaBOl17b^afb)Wdxx=TOAR5UJ6 zM0DoQ+~a%6-}o5f1xl3CNw^!^J(x+ck3E%~Jdoz}{yDljbIc8ToW86EXX!M?jx64pl(?H<4Lez1%?-pepTsBl&T_ao3GvS*-LDN+XDy1WNnvvjE z9LGlh+KIHIJRmmKda@1c<=?p*@kYP0b-|7g&ZMweOCoW0dAvXvWBjL_!&%Ib%o{5Q z=Hdg%*-2f7y_&i4E4^7fmZd;H(a~#6o@zp@pEV45mYb`^JY|ps4GpzAugH*Z^voP+ zrzG0_QL7)3otw4+H(4K{uM1UCc)otZBH4R&r-4IsX_esfFbX!Q>fy9~gWI6^X9V8= zZ2{d&g5A!sCGh5`LJt=LfkjAJHC4|DhF3~gM2cN$|SoN;k>GIgfY~fxz0R1Aef^en< z(AFX=;^A5Mn9dXGHuK*M_x2vM)koNnQ+}3^g~F0*8`TL%+$LYomkxL2eObzXUOoh* zB3z*CBVk1b-Q5yn)T9cD>dmd)t;SPN3PVxzIk1~kuRGvO4qI5$8o(#24P-eMr<#R5!X!K@KGX!g1Lr=)^T@N%O{##$)!Jgjy{rWI?(O zYW00=QhlASeI#KQYh|a88bS zZ%u+Hgw-$J%AcGG8r0NL>s2^g#aTy+Szu5crNoSIqZN@;Zpf0QX0Z*$^BxW!a?v${ z;m%4*+80;0q~fBW%gIgwSJ=M(8M))KVOg#P=DF(00m34Rbf1o~v}xWp36nosWmy!J z3TK?XW&KA-1c5*5)$8VX=Cj9A3y&S}C`$r5_7qhfa9QY5&-BF@Hta&^IYu9mX2yG^ z7n(n`A9Ckv9evk+2=|WGa#!j`rKaL^v+(k50oGZz%|y@hfHuv=C1DTE_>v<>Cb|Wn zfiOK*iPgIKjj#h<(}n9@`KfC1Kxw!a2|Ay6mMx|EEYck~e>w^s5ZDkMsul*m>>cb| zcBCo;-|ox@83EEC1yN>rk0n;_`R9J9m6NgI12I~O%Yqhsl(gU&RJkd5DfnXA_%53F z4{SB{e<#KN1DyQl7a5XQ9)dKPSK9{?O+tSjzh=5@r`y#p7?J}J^kjxuMBfxvt(MaL zW@D`KK|b_iE4Jdhd?NPCj)qY@D54h-Rdf$oc2f%`Lm#x)I<_?*TO|a-rJ*@`o&E9Ikd+K+bpb#@~~q`~E)^U#GYP>sj3 zxbq5Kn2f%`e9~LHNjFE#P>wQpS+@giD}7}^(lnNNmo2#B!ufQjehN9|KUYxdu>^xc zp&tphk1yMyw8>JTVZ90at2rPkWho_nKtl4nSCFutJIms89u-aoOdrUK>dn47eT^F} zTQc4VNL(N`CibIO)!(_N1Akl8zT??&8=9-Kri_R)dFwJ&L4L8ynWfnKa%={cJtB%( zjldIj2&z>K{i12lH~aL?+o20*KW0YUD z`Lm%&w@%M$pwP;Ep78Z|F7DHn6&kc0WsK15z*JM{g3Qo!S!n4KAP+o4K&>;)L%K?7HiSdJ6@<3z~qah&GNZ}qNCzvh5jC#HY0A7fIeINcM` zZMM)sgYwcHXz)6bA9#DZL93$FWB6e`=poUM`+CV0ZxjUB&HP?gvEt6T8 zeP!J=%l}?L>cF8KQ@N?qE>lt5HPhXPt9}c)g~}MJEuczCP+) z8fpXdK2pDKT`P1sD=_|tU{cfFEubtZp=GRhk>CH&fd&k41|_fcsZe z5ln<586+P*0mmabzjaja9++zjulZrTYAb<$S!~nWSv}Xk{uz4B38aH zxd23#`E7-doXHh8?$cA#qiZYU(Fr&1ZjIi}OiW97e`^8Tfc#E{O^xVPu~#bj)R!1w z)6+k?!C5Oc;=m=nM2prbuQDw7H2(QM0jMC6j1wXF2-BhcfFSu>(zP~t@DfJbYq5#A zt~npJP1H3-exxTXmoGWIU7kZs-N_oFJv9nZ)tr>C31#+6?a@PZ(q@rU!lae9aD&z3 zO}M2WTry*~)kJOy4YSwCZF!N+&c414C3G0k7X&J0Sq}qNBuw^3nu*;op z0MH5kVjie#KqdiL6BirjWb1) zo$UgR<=?51_)6eQeuY79OP{-V_h@32@6cxQYWzTUi5+f~CPRRcIe;gbv$wHi@m6y` zw^X)g{94ADz3v@}9&6~2b}&4B8P7cQdCQy!6jVvic6y@Ojv)g6h)iWO68z(Arsf*s zWS$AII)ZsOqG`}>lX+_`D$0nThro@HUO!WnJI|;(BY|@DgC$7=`MZt_4k-Dn34oGrcwp!_bCUaLgSDu;%?UYO8 zBG_q~#7+5s3O76NgtvcTd&T}emS{Ej-69S)AlL#w`px!7hW_F(l~z7crd znlD*lOF|x>eFq_9#RY=YA&H4rJO*jcuQ^m7XQ{xn5KSAPhPAsw(olq25DaL>kExU( zFsk+~>ziKBqmP98JjseQLFu%xTzVTEt|;FTOi0`QUC;a>A1x@g&=`UL{hWfE z2AxqrgGPh%XwYnD0Os7FI0#}NzeSoVs2r|fJm1hhpG*4n2sMmHLV#7HeHAAt{oA~5 zX~tI?v>;NWJ7%Z$Rldc@6YeNZ5*LJxOoi^tky7)-*-r}KzeCFZEW7^;EE({SqJA>P zyf%xCHb(a}Znw>fDc(Y4f#<#23t&j@WBZ8+dEX&>P9|(bVU83eO%J!%)_86LVJ=wI?J`^j!7y=L@HXwa%q*jPAAEU67RpEFqBtln#>* zES+QaKaG0fk)H%S011MYKPLr61Vo2HLoq|x@03Q+Rbl%yfr+@j;WGewqw9xIvyC}n zlqN|hSMMFRzr&sj!~(SL)rD+u#@ngaKCdw2l7J&&qt3-Ns`yb%g}&GRKFM2AwWoI7 zdY=fujax;U(o|BAsB}F&+wnJEjb$U%QPwk}xz8@SRF5oupk$vemq0BeNxZpIN-Ic* z2B5i-cr`TEp)<5Pnpk-x`dC>9tzv zW4c!+?j>66H*x1>&KlH*HxlMC(kH=;A!fLe0;HETPl53r&9AO>!a0gkD%=G!ACCptsf9vA0ln=%7j zl8}3(+@Lbc*rsE(R7nJM-|HDz-nHS9<|HtxY1MY6j`ck`Ank`lCol_ll8UJaRl~f>GQst-tr$lw;!w)FrP&lc74wmb zQH6Al5na3+il4S06rao;Om_;^+utUP0$)0i@-eACr_-ee&MUoj9e&7!>rchOXwqi_ z-4z8;+ll(MoP^`$RZ?v6n>wHzn6$2i-;Bgllhix_deQK)X4~!&EQ&iMApw`= z*BU7nJr~A0n2RnOeQSwS#Zy`nDIsh~KgZ2(%PDux*s!;9DcQ7= z;#q)xdf8#b{xCTSsH!+khg_mPGi9YLy5U;}90A0S%LU!&sObDt)Su+->Y@!Alar~jA! zQsu!7iXld8Bh=pQe+I)<2BFTKO`#Uv#Y5?%k>7d9qXsBEx^k7_&aNqu_%Af*;+!x+ zYAG7@78lYIfEJWH7&l@qBFd#K#mkzEX;5$dbgn#@>Pg%#u7wq>{(ZpV3)ao}t3KZl z{LG%E;f0Gxqo`mmXFCnD(RGx88AVKFML*K-`fB*78x{*i6uY^!dX}&#H1f3Z0??S5 zD@n+^=HiPo;R_Bz?acwlj}q@Y%#;#7ae*pG(qvur4_Z|?r{O7c;A*I#%*oqZrKgy8 zlFM;ctTL1kcnnEtor>O&ZMvOxLf!K`nRa-V`Rl|igg36Xg9bTi%L{CL=>B0ThlubF z{7aYJkqz25ZP-ks?;pw*wdDF`f)Pzf)1Ja>S+SCUmb-5C2O0|To!lL#Mr{ZutawGXKO?R#3f!ac;@{%J#N?69% za=hV^R*km<^LFw=mL4MUubXn&s_b>eZ1WIB);&LwL>Z!KwA+EZ|Mrf&0xkkZUL1jM zr$uMw5qDiDQwz*%)NEBdU>y&f9MYFTH0ab;(XDl-f~^l@Ad&+Q1e}N+H1GMr>b5z! zM2CK)z69e1X*v^tBaGaVOKM)*9C7tT8IIMv;|~M^1O{~Yc4LTE_L99|c)oxvsMpmg zInJn^3q-=%TOyD=q5ayE8)@hHB;x0fA|lf3fgqPq9uj|ET*?1$9WbqW z=VUo{B>?^2SxZ8^!W4Dh*$6TtmFq{9`|c?=^sc3D19RO z-$QQkZ{`b)hma~AGK``aQP~1zxcjWA_mGg78=kS?m7g`~j+d92f3Ao@ez3%#unt)U z;rE^6Dy}_}etfq@VP8%3?%uV0af7Nzih#4kK1tQX~}%rkfUqHJrY21!F2EbnC<=4`q?Cb%Ncc zWr@E}5P6LMQsfjvhK=@#{@JRC!R?fCQkNtFS~Q0%AInkggmbGoaMVN(48N7#+JD&S z-~mPWo|=Gp<@078-TY|K zXzNbBuRJXVd{4suYW3S6+^cNprx$&NzvxjUn5~m^|uo+MwEv~CJ4SQJNu>CDgW+ye( zgJQsV~k*k4Z&3_Nn%RvxG)KB0ykuhSz`YDq?F#iH5#XWn zg;AmmweozxisN^F5LP+w+wo`RC4l-!8W>(ew8D5~U@Cshc8OrJXbh8gT$GnET;P*49+`zvkM$#%f!~(WAQs8k8wPkB7sy(aRoM#F@aW{#K(VmdQZ25D#hWRfATf3QgWlJs2V%+`kv2R$>Z#(LXcJhBkA4;BN34i)!qvj*<8DTx61L$J4yWv9AQAiFc(x$`rKq^YD_4f2ObwlldHF zI5u|WIiv7Cu`=Uc`4M2l`U>6L8uysJJAP(|{p7y*Hq~~)5670h15$x*ed|T|--6`J zq-HrZq{{N!8ZnjPXJ-+SFjcSWm{S^po%XEtAk?}m`21L6vx~kn<^i27ctMd-OD9Q0sI^UfGC5-*PGa5K;1yMcxDl7r%>El+68oKe zB6d>T)bP-~yhGGMz@?D}BK_8U6L0D2cNh{+)|nEcAQE!^Jn2N&v1d=~yZbEv15f}D z+~*d+Rl5W~sXt(k`MIlAq*ogQ30~qY@2J5uZkom8#eDh5>4)sxFun=k4tTBk95ubv0RKK2krCT9FrWn+sF12GoJe2 zHGZzxn1yf0vEC7M=I^vRkY3_osHHSJ{vD@*L7hjCAoaJ~x6CnO*PH*O4)O3bA(Q1R zB0MCD!d?gsvedecOJbST-;gv-RuZ|D7evS0|MNM0plu#Q{Nb7cehK#(HLb%89U5@T z#1I`N?&R%~aBHr;d^`E%foa3;7kZ16Kj>dRu5A8OaLmv%xew3S1u?qwHqj&8wFas= znZLliJE1&`q*|{dx!g+s!=5K`4NjB|Al-Tj9#B?{%Y`kQ92aJYNzMrZx9tT=OJj61 z*=W$AGbF=IKrt&AfG)r6-+}iW^^&h~3%KmEgZe zy%{F|!WCyXXbb8i@x{W4*LAPxB}6A=Bnqj)Kr96s!pr(V5RhM&V!n5(rR3#LrAAXx zeRj-Hd^uX?U1Eu>ZPrzXy&s3$G4juTpun$Mz&iF?!FbjdRa~1T`KiB{8*fd4Muc>oB^=)P(Sk7e2Sd zA+P#!`wC^Fxth;+&w}10Hy^soG&-<(ZLo!OZ#N~V^s6oZh9=pgd{MJQIa>Np5o&gN zs;+omP{_wvz3jKRx`9W9!p_DDk5(VZotpTsW(t$q@d><)YP~1|=iN9u{qCxd0J+j= z)_t2#fF9J5;O4+64SL2>QV?|YFO*h*+3`Mqvr_i=(41Dy4BM zGhhxV&@;!Fgm!b;wg6sQY#Sej_LIAwFKTl&P~=hq$$%hkJ3ebm{%`D)&5Us;OLM(b zmdzdDx4PC{2naZj>*7~7YH+B?S+Vf^hTP`)>uGC!voN%DjpfB841;{DUTlF{?O$yY5w8a1jTrOSFcblwXk(R9rG*V%c z*Sk)NlP{_1-ssfr3vi7zCt`L2pWjzZbb2b2^pupckqH&%VECJk;n!PhKkBy%MU~=r zZ);b!CgwS5^C88)7#Q+^BrK#Kwd%W+q?ThYs~4uFdYPbd?j{H9@_>MsW=atyIUqxw z5t>gg`~b^~w@*j2UWONx1U||f-@lXTzYA9p-Ac1q9s>0K%uN9PDjelsuxHtJlT5r+KADb=0kx5Ao4W$8C2s1 z;njvt9!bL@5yA>dJtLB7ofSvedlgT*_m60Yw|)sk+$u+`r_Xc%xA-1% z*51>yQ6=%Nvr8)KU)cTzXbv`O`lVQ8G_!yCM9-a{kpo3UwIaHC>$(7KkP5s!BGd|xWOlj>F+Gg01>kpwNbxE9xsFrAyg&=w^(@TMW zr#|Z)w=Z7;nk^K(R>_|ck2B60R+NriuafH+F^M*M94+L(?lz9-?Jqry7FcL#?3O=D zUKm{p_|$USKS`Y@3-KrlVScI8fsyK!M9|$z*sgu{d*z4CER(3^7#!=k_i62h)pNZ%z5$S?KymgBF&Ey+V=_26ai1 zZ4kV`>ZmFkvy?dz9^EWYs(tlG5&?Po)$Xo0SIZ>MW&F<`?RQyaX@+e?a{&mz0GWDD zTEB_A-PI4m>D;(Eca1XcIP8c!2m*AV7aHq|a@B0Bl%8A#)N`{jx5Fxgx!#i1L}{mS zr$%69EPZ}eM~EG5@GUYR36Dn^DVDJ&hJ2DFm!e#=^0W1FE(h#9JI%oC`LW@l+cI>x zk@RYWpMn<$wrsHISkuA#d~xJI(5J<5fW}Ni8qJNr-8+8YL$8&=C)zSLyR%+yCDKbH zN*KiqKl$wQ|Mvpe&1B9J!CCHjSe(Cjlc;mAX}jSudoL?mr|zc|m@t|q`9g~*^Y=lU zFPNJoy47AY=xwx{zDH7^wj{AO5=lyibdQu*JLXcra7&~tNF9I%?%tx}l=7l8-Ri4b z-XM}`P|6bI5@jk;f<}X9zuv7aI=IfgX6>?ax+9pyt^M+TK=$fP*{&njL>wt%7<9=Y zqucFh^!jei{-;qJcOBY99_!yqKk%)%qW0k3ovpokL-C~Lb~;WFoQF+O0BWvdQRHxnRA_bP9Fc#=)hil~L1k_EB(b8G1^f`(3B0^1yJB(5d|B<8WtAIB2p!uR z`%IZqdn?^*Z#Ct7pObE#j+0dN*J}a8ou72= z2z87E5oFkyiDm!C+UwL);5Kg7N6+GV$~KAgvKy!9i2HE)xy-pAny9(cLrLR5(t|5H?QqB+LHzGqHG z@bp{rjVbRHDkPqHLz6O6Y=KobhHRez!^;>e*Y9ji3`D?&vQXI6MiEGTXxn$Ajs!;N zJ>VP=t4Lt9#E9OCvrg{Cy6Yp5^I~phawQhkP6ev@W|kNaiSe?r(Sr(vztGdT;(s6? z72fy@p1hTnv3tc!UX{=A6qf|O=!YlLq=bD za_*fI4bnf(Zb3~M0V3Wv)Fh-Txixeo^jU09Biny8y9zmWMG<-CH8?llcsU(fIJ{U1qDP zwl^YlF&zH6mz4SVPfoMUi_XNVqra*gLLZT?GY=>=C_5TaRwMf^xWY7IEJ&xLcuNaW zefE&D;3s?P{nq*CxSTnie%@bsJK8cXx;N8N;lDVw-_dYq7(nfZkZ8zz*5KxSBmZUb zMj5WuY2p>0=b;4T^FmqI*U z)J-RN>DHj*sgsVIsgBYNhBepko#0^Q%6Y3_ zxvaGPyWW#ZR4{1U0d~#x(3K%++eBqMmD?3N03~f!6$e{rlrJ znDbu((Du33y`SMzm-waJQ;5;I+=GKx?rZ1_2RD+1{3h87u5uPUp8o@>-Ur|f2U@T- zQR!L?p3!NX7*U3f=~1B$^o3#9zM?=#4{MeNGUv*Wdur2eMfeLjBqydr)%p54MdKlnJWI3 zKD*l_vj@*k0ZCSw%6c}oQ)WK*xa)RowvnZa&i>t)`B@PtTs7Q4l7M4=R032Ee*LQ9 zN;0sE?Ri$Daka}644v~m@lZ1q#S2FEQEU_}RZ$Y=Oc*WJ{6r`(v!6?a(n<4a=*5sU zH4SjyE|FPY%=y?`Y2aO=e$vvU3e3=12eF+geeTtvUb6$wo2>N;(Eca>rvFbBbN#v zwmWFqh_F079?X@bC5*n3*FK0g>y9}f+mwylDUT+Ky;WTtg|=Ij3Br@Qwm!H=VeIXO=<;N1$zuH4;yK@>|ygSidfBxTYjZuAZIgR#Hd zm{(f_o(I*r00e$mOWCdhs^KMj4`W$CR+-Jtru{v!$f~p@~)mEyeN! zCf{Vpu%OqjvkyZ&QL)Jgx?*U{KuC376UXe(4Ro;R8n1@8NYnJ~gn;X{SK351uH-3N{)a znOcJ5$j=!Qteqhnt!kQucl}#|KRxRJPCosGg%5;)$$TgA`$3l1JJ-wvC zDYd#lVRfSX_^Zv$FEOCFg;r~h;`Jw5wx z=CHO@&n!lq&Orp4Z>0KVPeqgS3z)b1;buWXkK=>ZrkH|}qGwp6XTJq!2X{u?U7~Oj z4^CD;dp5(dT;-*HO&5hBk{2Qj6L)|*P~(~;#IQaCg)9+R zoN5n9qr?|TtwEx45l+6Z7!(~Ovc)>#)q|>tglFcZSqhb*vyy&@>im|4r4Fj|waq#K zlmaP$SATaNzEj{&4GZXY*VK>8`v=f3gX=GaZ!^ZWZuL8Jz%6LZ3p_Wi&!^gWu1u&F z7yA=7^}gd6)kA1)ExcMnM<$E0-_L<(qgBeyO~H&xa3&?0z|1Eed0f6etEfUI) zmO&NS5y6vB^B&=2Y0_Yovp{51>*Zks@!IDZ89qQj=H-~Lp<2I(!bFBmlncFYnp{lx zIqjkUNqGMKS9or#DR;8gX7d#+v}zKii#JTvsYE30F04hse9B1gtQLd`xTesgsjhFi zqBI>9e4uDr!VpF$X3MN?ZeKt z0rw~sq>3{XP5Y%l6{f_6&v%VAGj#8@1AAnAG+q*xwGn@wl@nAEUf{fegoc1KAaZ8& z_*#CSAGXT`!TIR2kU;vtE5|SRYjEb*BSI}B)kV3)J_Z7iy0r`mt34+z6m+q=k!b-D zuR5OwEXY{955bCE&*F}7>V?Rpf}2X>20-c(qMhR>(4L(;DZ4^h>XQ})FBDK04<1Mz zu_V1J&L~VS+R^z3xFPnhdcWm0@4|X@g|hhOdqr!hfOL*oFvp;pDzo;y1{a{VCoBR_ zONaK{U)dE_BiQNck>+cd4+n{;StF0c0;nJfW%G9F0n$Z0+=O9v&Qm4*A_Zh4sGDa6 z>e}-HTJTkc15#2^qW$yr(vy>Rsj1fjW4pk`@s-UF9+9fRt=>HVn&Vpz!l}H9Ue#qO z8VrvDj>OL}cN*|@TH&1n(b0-FPa3{ZOCP|>^&M!Zvi!-MeckDHrVh zE8z^Nl<{CeMJK#rTatFc?HPVh+|~}#ZOyzUk(Ua(IytQ#BLhH>vM6~C z&S<$t76S;Q`@KpCwWHrNw~XW0%tAx_4)$^+^AkBf!Pj(@g|%;B44$cU6UBz|0|0hK+i4{YG zm3`TI)}2|JYejU=Q|2=ieBRnwCK!r5HqyxrwW@St%1y;9{oE|75y56S&5cEYfzEb&qA(lT%W+RE zivFC9Tqh^4SsYFdlZ}@aWeti_NM{DG*SR}*k{|o3Zih46gwHc85ql+D%AnK$`#w^Jn?oi z*K3-Bq;iY8|A}q|vmlX5O-%X_tlsukiDm7e4ECO%DCr4oriL&GU;?%I%?kM(0b|>< zV9alQ!e9_Y_7Ft}fc#*+3}6)WxhutIr#_Pip7c(My2oesuV8hm3*C8HFU{8{!) zt0y;muL-~PmRgJoL1{^1upA|_mtqv1H)|^`p5wbt-FWM8yPZNsh2V~A*hnyO3>$F- z!x4#`4N7srjyxxOP4aEUy+>|bTuah6cPghVpiWVZ5_7czbm(-gBC(^wpXTwADtLov zRd}uh|J;f?Fp0GhHDb}om7Kk&MLbYGkPy02UZdOck>)w`cAX8Ub< zXLnJmNZ>wxE%6Lc(#?@)>+4C$Lj8k+XM{}YaYLYJF3)XYEMwAg1`q%#@#JFjV?p)- z*neBa!Bo3%xr|4LjVKkFSJ>lZsJd-Sh(Q~qG5=@@Mj3Y9?w)x)E;6YpPu)Nh3vu-1YfIQFR4AFEnLN1H&9 zF)Ktq>ja=Kn0NH#g+SU;4ZqVuQ}wUrB;3IMbBfM-wov`G`2BD+RR6yRwts&o@8(}( zoi{J{5Bf-4F#mDc3dF&%c34;kpF`hy2X_$-oPGNlmMff|sVV$ip*qU~VSA(Mp>8H1 z&|(|Bm|FSKBzdjvJeKxdqNfh!bE|~4tiBwAgh)pq`j*&NnA&I>od>4PBFff%LiUVNW^g3jK<;u> z{`2@jLSyPp+}a%Lxv9VrVcqAjEY`iBd4!Ec)rJQf#_ykNnRu$`pqIK-WmMc!BJm4_ zT8PwDt!R>w!ohz^B)8{HIEGh8*-XqJfuv&;F2umwX0jDPg5 zaDr&Lef$_L4nhO$-b_tIf%8TsvO>CtP112Hqe5#})i}AwcKF>bIqtU4dBLA}u!E-h zs%Gkm4?F^@Q#=VzzE#VXLvK3}*2N7m_reX@y!07s^Rn8aDDCFmftB|KzcX^Cx@s?p zKccIMO6{?zHtef}I}goBcvvs7YzQV>xY6HTMyEy3>_eIV7h_);)#kRfTR}>JLV-eY zC|OHR-naQiv%cI3c-U*DQ(v`%*0Uej+S*Z4r+-RkrsOI2L0n*nT!6hAk3eOG2O-VOB{>SM4v$`rA z+b+T9WiolY4T83w$xAP6Bks1=^n}$aL_4h7C#k=Xr~s$dDGg=yyq0+#h%Bj%w}Vk6 zXRMd1>V4m-{PC}*=s5~w@|0c&SPxxK02nbZBdsCWm#5pQqeD;d3c3MIy zJWZcPUV?l0g|Cd{?0S>dRFj5~%ww>|J**6SXF<1L=DO}N*e441iOokpmQtWIrI5fq zvwM>+#%2WKwc9o=>`=?r5qn18ZpjHCyf&o!%9AAx_Bt*3gO+7n`I7QDSM>62rb7Za z-k(578}7%CS`l~OUOjUTP974ewsNtyA7o7{(r{wT)m8;XMN}TXtMKz)pt<3h`Tp+5 z!B6VD^J$r|`Gyhx4j4lnkB5V1Z}lqo+#9Lx>;FQUg$=~Kf1PT72XYowNAFc5RyVtu zBy?fF>naA$W%j*~I0LKGOCE<3r&*?2p?;ztkVUdat%h>~y1Fe`pRd;xTNklDscO$P7fp=$Tb+GZ!dNcM&exqZcrIF=He;=*o|4Dpok3gMoDpx5+sME0Qb+7IbN%_iQjv6iVbIF*swdxQXTHX$)wV>z_ z+9$N+r!lL)uP<%Ds!PxRNAU9>DsQk0`FCY9NQ|X=%InQtTJyHYcXhLrLI5F<5q^;S<_1g=@H< zKiLh5s3uVU3hMQ5-m7wm^)v|6?}E_*eHq{%UV(a7UZnV#&%dSfvLeU8Gn9P=@Wc1m zT2vb08|uDKObC}v#yjKYdNrV#g>EA$R%tnf*xQ$!BNQeAMmaP|$%#TBiIQ`yy9&7h zT;g+A2Zj}mJ!-vjkk|obtYmf}$lte*LF|$5`~TuD;yo8O0`q;D5_IN1i2CuU%=|^v zJN7&L^I&i#gMm5@CtCOCL`Y1uOp-=aFQuxIO6l_#?|*5zTV!6 zR9SrEjQD!Yj<3JDKBxu+VFg@z?P9PUWI=I))P@$~2I;DXsz0N6QkuwdOOWnNfn=r# z%&`!xEk(>NDW`hOb*_~e=})uj<}zb&6pj&UjE297l{ z&@;SneFQO-(ghtfjS?TR==Nt}e+6nCsM3h1smiUMU)z&QvIq>E>{XvRoxI*J6V3(v z@8T%VU_=r&Xrwknj^3wP*E;U_S~aX~l4ax+4hvU~C%>S1whjo1`yxIGl8N-e*V!3{4C4GDLNl|Oi(-VMegS+fUoYrQ|rC*F6u2)%nR7a-?!};7(me^>8$xi zBd}7Br)33AwGqLlEzSAlfuH=@KU~DCU!y@?l?fby1;q?cC)HqP^fok@cXe*J?&B6T*J zXXS?(kZR?UQQ?}Sl#%1p>TajlQA1XMk0iTa!Cw;hyv=VTxrqzri=luan(hAzOl$uw z(QTilFvtq>5=!dgVtL6n!0slfMm0DwORqpVs9r3_6{xt;O>Rd-xndi$^J?7X{kH9+ z>vN*7*9u*yOnpCa_@ZL(;0I(?)~gOr4vDaGN{45l%cIWyY}DX zJsO(9qsVw$a%JH%_Or7vS!ra%U7W{-yU5w@-6knZWaF?vtR{H%tChvtQ|-AQmsP#? zw!4{m=y|Nb5nH#PbC^^DpKv<>A0Jci_TN z%@-SP*(5f54z5EU*!iQAjVtlw=z$w7n#N2&_lPP`;PoIY={|828wehK-$oWSuncwh zb>!A&lk?^=c)*bccQD}b^|Qcr#yejb`k#`k0I4enxPO$Y9?t~>F3RyRMixJpr<1&gEX@os*?~O$@ zj~Rmrf!seb~)(@Sh)&i}b zB7?eYELx_6YA!!wJYIg5xt;`mOTbCep%TrIEg11Z+6iZ+xWFDrUmW|rDb=bj;ULe) zWT9(>EBa?Pn_yo!)Q;d&BhNPh(^H3#Xe%r9Rew}?s$z*0{4u!Ybmhkl5#ELPk`Xxz z#?_Gb9T(ZF$uLVJ0hm{s0Qhk)oT+M%ljM+eCMMmkRpgaAY!#Yba>3b3Tm0|c@Kc&#)<|r#AclZ01q!fkN-Bc| zg$A^mAbSqAsvUT2(QPO@iM?47wIT9xi|W#&i=QbtL&rV?sM}O%va=Q8e}C{?b!|kf zI62ns#i5JX(hb~~h4$5t!H0p#QO)ddakJ0{ccS}#C(B#GJYfbG?-YUZgF9-oDN1h( zzawKWPt}HyEAA(kANiZ`g-)ZV_>X85Id&Yab}dl{)<~Nqy*OjwL)V37W(9sn`=!!X95Mx!2Tuhr zr-pXgFSia`QQ33goXw2Q3^R5xN~3wt4Thbq7`SIAeRg<$>(jZvu~30Pb%54%Z(GkU z`oyCJsuEv?+i4zwdE;W5)?BUYV+uKPwv`YA$BB`y9021Hc14bZ-uL~$A9I_=B%6z} zpc7^#3B7Z_0uCxOXFA#3o8<<>0IRLLbAE4;syHIZA4oB<`Pg zEoNXcB8O>Go{an0s%IR&`B5J<$K4*jnmcZyqtZ2S0|5`sgUKu6y>knK;xb^YSxn_Iq0w`)bajAxM z+JQ29yH54ZdYo2{c-LHSl%GbzVx)FTctaI|_t>295eAaqR!w#l&Hwn)HhkdKs%bj^ z5Czs_0=O%5rNO?vJ@Ci1Adl2~fE~1z7)dZ4UH?Y;fIL5$)+Kf_<(%iJvnCW;f_7}5 zsp*Q}l^IBd8voPM|Fto{C)H&0-S6x331vVbV%i3R=s0lC(2YQ=ghp4&qJ(LgtY z)1!O26kuw8VAsffPv=(WptC<-#x*)&M6YJat&L3c$?t2Hs7(#JG`Kv2pN}DA+>@$e z$8&mKs1!O*Jzp1(LDpIo*lVi%GOq0S>FkR*k#)<*x0pXo*ikebYmd(rRzx)h{5dhz zgUEu4SNIImkC;~GC8>~IY#R4f8?SEI!WmCl_#a1ViIK_hQ-UvT95KI_gVB!f=IR3+ z2(Z0crsO-6a>#AuLS6A3yIi|QcWKm5T;*H)5bAHk^os;~J5;_NknzDI{cPo*Qo+rk zF%uSaY{85?g--gCAFxu08tPFzP2S|_ET4k%?!$#wzR9B>>tEu)GisG^x2J6zQ#jbf zUU7&|mAyN~9JqXT2<@9G689qoJEc_Z{G|3e?Zy0V<8Qgnq6Y73{x1t|R))h05c{}Z zTRDWB%Bsg>b6{><;S^IRSGtRrzFIF^h0Dmv*3^MTn42Ni#b$M4+Gi(OjLonWs2UTD ziStE*M8L!RTElsp+k^hvle5~E&CkE(FGcIDCyuAGbHP2{=u<;5^yEh2B*VC}dK)&> zS;{Q-Q2gtDB2f>|Y`|#qH+1U`tfX8ItehmYoa7n#_W4&1U2tL#VR3tN$BWb8&#aFE zJ>3Y2)sY2>D*KDL4%j>Tz=0tjhjD1_sL0pB`K}FN8gjRnpJ`Cex5XiciO_61-~H`9;Op4 zJ2LNC`I8T5MrjRdPq(;(CQ^MW-aYruLHY@kfxY9+N*3_Qz{IS%5(H&8bvS6RfHHmrbV&dj&4m2YxKu7V2jJW5iU_pQtpwR(bPUPO>=(;d z{-HKKx0=L6++xqSZ!!&&AI^L#M{&&D--7=YPR6fX#GG8=$%?>|+zeS~6sU{vl z=iOnwF=V*__@NSBUvx|Wknb*Avljpg6ctcf3ptnNUv8K7#u zWdYYYeHdhVyoF-aL}6+I8pFh_Y}hT>w1|=8hNbKr<~G7%e_n4qSt(s`Hsl$g_-5Ef z)!@wIH0o!(Q!n9ZSYYNMh2`kelC?BuJ9{k7RvlgjF6`wty(jEteyYNIvn|(e@u=D` zMO4b9etc2kjdcT~;O zhDhAdwhX&cxQvf%HfK%voDLzPzEIzj*V0b$7O`!uE`LB#cTF3#f+r+4*VE}fZp^0> zHEuBud~R*=_pE-=mNA&8%%#Y2>0VDGvei3P42xa)F1KUuz(@XvzNY2w!B zJee_Q2L2;?e>G6WMZTTvKic@+$1e#VsDPY*Kcny@LZ0!*E2w$iPsBwkzz0Tr#DOID z2_}>cwK*7=`z*kX#Mbbj!@i|j?d$PZo|CC4qmp-C*lt^#i7MkUNPp*FgEx%<>k=e$ z@g&2t>}))VN9C`dGq2Cc-3~^z=($~dik(5U0 zWUL{{Hm<2&E*D9_a5Gb9|91?19%Kkta(-I>)YqMTtRVRyfh>;J zpX!Qugc3LZP;&RB@R;zZPMY>QGr$X(8?aAY@8mFG>qYhw8VY*<@Zhng2qYU^l`*V$ zIS4+TQ`e>Vsu}@HS&zcyNO%U%_&N(j9nYOKEw#Z9c6_`{A2wQXnr>g?s7>2oklkMw zPL`IwWGncXC~k7TOHM>vZI0RI?>^F7*8klR5-iZJZW`wA%c)FT(CzpvI7+cZbK24N zRIcUxDoGtnJ2)}#84{7zhx+u2H@wQC<-X$cWo$dBLQ9$JH`8l_+}=?IjUsUbu|R4V z9y*3u$zw=rJS{NUSxp!+V_x+I;gQI`j84@C79q^9SAA+Jl7^g2@IMxp$KVL5KLZjP zav-u)NF}(4;G5^(C*jHo=yKUl@{P(455lA(w2J`}oThU>mZ^FDL_L<6x4!{P{&yEY z^0$kh7H%l8EfAB{VNeE*yXt@d%XoJwy(lT0!Tjzk%HHU3$J+(V==uS^W75* zi3~opF%{C1R-aq+KG!Ib=acz*xU+1tl;o{h$n21@;XmoZ-4d=ycKt3|TxCc!sn6Y; zGVxcBQH>1ngZGSmYUX63is$D1>yValsLChornXE$&BX0$N$BJ{^a>^Z3vUki+nX0s zfV-xtz}>3e6h?A`{F!9yIpm2S6*cO5o+7(9IQ)lXJx|Opf&*@f%bdJf@d+kG-)0tx zyJMTh;{4X|oVOXD+bQ$ft-Jr^WHH8=EK=)4+>wcRx*Rtj@n{E{%XqRw&e*;vIAX{l zz?Hzc;7jTXF&JzfXq7_3X7%@c$48QjK&BZcDZgUXrhmEdaRXT1sM`4q&RK|s9a1Vj zPs*k!!$P@fY>|3TB+QsE53M-+q)45xiGmFLl>>(wvs2?Pv3_2D5NtwnF%8gZEHI7| zeOFP>HNW9r7wDt`tUw{z>iVD_adoY-K$6{Y_>w;7+03nA`s z>OcO4l~}xOPD5a8quFDe6Y{y^);MHdz%%4VhtGy?9fB@`#b(An;;rzLf+_qMbkc&+ z*;SjvqL*9r5<8q^A#`2pMI)m&Cdg5nwp|^!>-&B?vytTinBr|7#8;0ZGfUT_!$S0D zR!6LEiyx>hj5r~Y=-9LARpdbAU@kYUcsPcMr(f<;vOn)iUuCE{8nO)gMYYSwCpQo^ zl{)3b1UGb+2f^m{ce^}=$iU>JSlWmSLMHpi)J+*`}YqlIlbtOCmS=gmb(=O{>H zIb5kDH0Cq5h0lHX`GZ#_WZ>;H+ijg^O!xljsdC1`=4s;NYN|m6P}-u=XLJlU*a)sS zRK5BAIhW})8{JJ+`cfx@6g<#2ip;&*dWU|siJwni(#s4Wk7TvdUMhB5B?TvIfncDJ zx}sc|(evbb0PCAFB$47)XWPltKuExvenl{v$C&(AL{hR04`f#DVrqb5=a2pT&G8M8 zi5Bep1&xsx#9iep5TkNl2QBixNbXcNBQU{M;0ya|f}o$#!mNPs(|pj*D;CkXaVT#D zOkVWMkDmb?&MlZt>evSMWT^pSrR}E-O7M*L;(FyMy77|pZ$wGpga-8F#p~XN%jcxi z-_SVwKgS<2ge99ekYlhO3s-X5lmlQ{HQO3+g2v9}`D<1bIC6nuP*nM^Bj?>g1V2Z| zcsy4FIfp3AH~jNDGTrMVH82C2)pwO+5q14A&;G11nlUB3KPG0={qEc_K`zR)|B76x#mF&%X* zDY&i494m$-eloAAH&kojS0R3p7M5Qd#{d>N!mjIDZD#-lSS}aF=R1Zc1wb+8LQfFMGsSt87!2`bL@|Uz8VYImVzkBWth;c3wR=xVT@^s z%&22}0ptWEqUXIR^4(|H09oiEgMMGk?})e0yLksY`LctaCmUp0K7$W5fnEnrcQuRc ztEn&a-Shl&9h%^C%2Y%X31gV9BjJqh*_+kaE2kE@ONo?!#I^Amd%ecI&vn%Xdfi+v zs_&7XJj&34g_K1O%&{$Jn@pQ?3h}V>Jsr?+SfNG*2JKLKR6G543SFyoiR1}TX{PR^!@{h$z9v4Kk~-}LwNK%O5#*w-;p3S{PtO{oI+K>eL$r{ZELofxEav(Qq$VuRI-VoTLWucs_Fah`fHr6-=P*Z*mF zJZxFikzT$&jzGGkTI62aHzn%UCn(oEts%=#zJBk6b2+pTjvYQW4n134Uf%u2m{Q?% zN=XJL1K-URIipu6HnhK#7?wdP9kMTlS^4@BSL8EKXWn50UjFQwn)geGo-Bmlq7n~` z%ym|y{~^)-`Qvc{+C(IUn~@VAZs@NLBj`FKgR8>HUqYA$l;G6L{MzjRIP%cZ%CjM0 zYeyoR!Xh*FiB)MpbBb?OzOtL8sPT-=t@q`^l&pNR<;7-vQTOp49)*r!(yV>ivOwIn9FSMa(fJZ@rVPP_GKl$IHZwL;fioT3Hmfu7dtOCV38 z)-l^ZU>%fImKj@Xsp+`O6-hbDagdK2Y@RaAV zOTS6H)=4HNkHq>O**OC%U@z0z;Q1cQW7O8;)$S@u0qyzEv^kFREH?@Rvk{M9m4tUh z9~@Eaem$j6tN4O0e+EZ>tz5y8{3CE_vMQ}cfgcIW*@h$eIa1Lkp+L4onQ1}&!0~ZZ z2jgw%Dx~v?@LJeoG!*iu*2VBT+`Qh|`ZP>afr|1U_@iK5HYT{wkHV?njhG&B?sn>Y za`{9l0#l0@6d!io?$_eyhMr;RU1_=ZpxP!u)e?2nHe1Qpf|gUoM4_bM zL8odr*R1P9Fez9C=fH#mJH3v`57bOnrGX`w+c%>QdEn&$_`qi_!NLkU+xtb%EO4J` zU70VOn&PTzn_Ginf_6SNJD{uil@G4c=Q!g@`Q)cViX7t!6yQIl&&j~LC(G)6j&%8l z*py67Agwu;Xm((udFwJX3ss}2`*F`yUW62kn_>s?n4Ri`?!~d~W( z13zyQPpvR5@~}~z#ca!1ZbmzI(tKG7NbQ{x08-yQ>UO$1qSf;|iLU70F%*^1RQ@L_ z6c3B%@HwY$M`S_r-f#9_ukoh3j)^&2%qvF@P!usL+zxv(0fJD?(f8q9IyI!P2{BVQ;L?B8);JTftb~O zPyX%-c)gw+9H~Ket^cN(Qpcy(x$|OWcV7~FzjY)g3m-sz3=AuBkof&YSV$4r{&O z+aFJ>Y_K;XZZtUZF<88$Ctv99WBSwz>-@vH@Upb-t7P#duzT^<)McRdx$p0v>#hd- z+%N|4)u+9h9&8T+?bWB!E-IjBvDy5@hQvh<*n+JZ(!L~Z#sK?*ai}S4HW+=yposFf z{CS;%D!NY}Y_%!K-MY@t`(~E;S>=a&3rH%*o9a+zE%vE`A?w0}si%^?5x7DbTC2IB3s$Tmqvnn;nV#V7x)SrN$k>HV=mJ>qpu zYQ7NtDes$YBzjo-5+au4LVv;!+Qp_1Z52J703o(AS#KbCYINbt zm>uM*BI*??Mh+wz14|ir^N1#twfv$TJ7gw)3R6vW@?lBd2hOJkX%^m!#4zuo>R!>) zKP`H0kZ@P`d)(u}!`@5P>EsurU=dmwVJAkU9Ne%@31aufWRMNeqEV6awx{AcR2I*9 zch@rny5hx~QbA9zj2!}lNUgZm;&=Aa7U6yO69AOlc6HVEBBWp0%xULCy&4tI^@~`1 zACQQqv&ct;rj($&n-xC$qN%d@pS)?V4^c#gpw|xJv{?C2g*Grq)NYa^1MT>zv2y6z zF(i7e;-=iX;;c>cBS-U>N%q%4yF+>b7nOQ`2C*Ffgv?7`y%&d{-`=@%=k|78N!Z~3 zH zwx_ivZC{>nr}YF;5{#*SN{}1xzb9yWr4jE?vbk&LGMF`7E_^DPcx==5BsC*7wYXMr zn@UH!S-{1gh2^>6&7XFcwfe4bxBM$y&$o21IX-A?y{;dru^#%wYLi@3+M(M=VC6rh6K#*ajN_n*#i=-% z&Ed{vr4l6Di%_4fuayquqfOQ}%SrWi3Gem=faYl5Q!lx(Rl3#e^MvkwI2!?UJetxK z^R#khMAOneFe$ExSDk7{G?RcpUPC|k^M*A?`>!TUZiYUrzaGQ<3b`3lv0y`VmZn zbFx@xj%_Z%2FXa5QG5Uhi0hSX$g8~#HUl@|eWm&MDnE11_AB{kwY1MopI$FDB=Bcd z%a$u#0Q}fQa}yJ{sn&TLcG9x(3QIxK!|(?>p@ZdX!V#^40<7*?BIv8jN<2BBxZtd0BnidwKePGjaTR$W2@6$ z=8Rk|6&Gz29v0zIraDuiv8Z9_H$&<`aYp6m6=GG^!|^OG^;Fl`!Y9y}t;e8pe(1yE9@F zN&}_@dGaV)oo)G?GeaUvJ!Y(!Yx5qL#C;E)B%*+L_!PM$54#}QaxcOw)s-Bq?M=mr z0e*!+wz{MsK33h%v+6^twM*yO=VE*FJc$#n)>s8cl)=~UhY#&Rj~tVLWa8(u1BB;p zy*!5FqsKww#7d!dAx%$i<41rap;^6@Pk6MFHR;Qzetc=Ctl216Dw&!|-gd9q8UK8R zHl+dW(oB&$n)$Yfpx=@Sfj+Ee4!u6aIj70)w3)nJ8%iQM;^B$2y9?Z)62{H~6DQt0 zB0hIyXU`qWt98(=Tw9^U{HS58KYpq=_xjjC3HOk*S&FiQ6*g!Onhkv6F=7we@|@al zD=5?L=!g~p0Bu6Aiv%jmcL^>6RJLWxChg=+{&)WTScuH71X-OCK-DTmUJA% zGNFezfqDhCK~}GA>NbrC0Zuva==8M~FUPd|eoAaVG^e+W$>6WKyz_^&?Rf!6Vb0N_ z)q_-Weg|~%T_EY8kpS%^seNf{#r(04NoFN3xHB*QoZV4`qK*bkWB;n|#AfZH)v-mA z`St+DTLV0;8a9fB?SAz|+6&8|>uOr=@OL~r-=DfST$*9ku2h0IBo_-SpG0TF^JLRTLIAmrUa^fm}$x%?GDxWF7kwbW8r_VvF2m! z8b9<4{Kki_6A)T#GAKZZm^u{LezMFpl(h+!!ulU|2a{tZk^Lrbv%vi+)1;}{Y&nSv z(WJ1r%wRRx1sb!HzIFmW*q>%dt(!vE%{qg@Qi1{i)>>WNq)hEKl+R{OtLISFe2uXK z$Y`u|sG0^Vl_+*do&`Z1X%eX1zz3qsL6RMnWnp;<2!)*&TBE^L~G z7y~SMIaq$4-Zm*{W;`NxewbMSZY|cFHe#yWGeki33fu#2*wH0I0#M`oM-motz%gZ% zMXVMfmJiBK#wAWVT!lo_|6GCaEG=bLHVVz^5G-ix1* zVi$D96SG(%0$>~~cHsRvk?8$A1?!g5c5<~MTt$aiPr@Pby_Mj7kSS^T;Jz^f+N%PqAypng}@fyTYVm2(6 zPt-Iksr|-T)pjfcv2*#6oiE7G*$7Y3p6~->W1VJvf(R*Iff@} zR{yy=l^tmI^{tCX-rZ>sTFQoKlCSk$JjDSU{bgg@_Ml?mvC^Heq{mlnP z&+i0J;uLq>941L#M@}lOy8oLv`B&`B+r5Va_TYf{hb{O)sgd}8Av7t0W7Jl%X%U7Y zma4hZMq_q%`M3$yj&H;2ZbvH8NBe1AkfohkI^`b5v~G6vl`PMx0|H9*vw9Y4&82T+ z`>dtU1oDGzHSijout`xXD-ad(k<;@}lz+>~oX>U+uN(qOZJL(KfyUQO&m{qf4OH9e zlY*2WL0V;#r2+2tdL@Ssq9}Pf)`BR9^bZd68D{`3BnKlIc$zy#wk_CGMFMCr&q!fx zaoE;DK&7x=3<2eH10C95S-wPr)Img)8%TC2vu(4dZhT?6_FMge!}%0Euu-z!CAyCJ zLC%f@yjX$M?P9w`I!h@$^rM%Jzm8Y1|JdBZGXj}ORynZgjat;hs|*N zQe6%hxXx044Pxi3B4nU4*B&jR%&M4lDinDsQx@j{;%3M zXTOV>mdOEGZSz6ZuhSCkK3R$Yc3yn%`7VcjNvB67PHAZMk~QK>FO{hfE&6wd%JkX} z54Zd&pHVl>BKX1h&Z+#;H-*EtdDNd1o4&?i=8H!bimjaO*&i4dr1K927+oIjS3t&# zM5G}1tfYSu*>DczXhk}7M3gl9t(BFSJskYXzpTUgPG$9gk>`4P&?OYol^Nb+7rJQ@ zt3}KU&9o5(8&ZOl`p9&iqlq4Ptn5ZJBx zTBepXwL@Iu$q}3yKHEggjIQHNhVOZhzQ?E4=<+9CLtM0h!Pz?Zwh2YK1F|lPhC;NQ zV4@F{J(}O2zSblZ7a}CQ;OE%%xegrmu#eRW(PDcJ=)O1|+^3a>NVL#PJth7AM%G36 z>FtD9D0ZJ|B3!3XPhq`-wV}N zBlZy_q$c(Nv5tHU3sYkAJgIB-oVJOyYb0;*e0^*l9$4|@9$P9RuU7x^PwTPh`2o51 zK#J&QQ-aDSQ9+IMp7Vg!xS*8uV;+9roo2f6^(ClZ3&^1Zoc6N^BpJI9BEUB}$^3%& zD~#xPKqg1B2w|}Q1FqYixn}YEt!6?Kjh!@l7~g1Cf8FA>-G?e%@MHY~cTqMzw13~i zd9eekZV6_#Q=n@cLOh7Fe^^o9trXxqghfU*5jJHOnmBU+O?yN9@=c?K-p315BtQ#n z7=cHDIZCem56#BnyI|QdBgLQk*q>pWlR-KoDoZfdT33Z-j0U-P9|0XHy(ucJP$9) zNm7M$W=xO{gp4Pe&WY^B*e2(Z)95LQu+k;d)8tDxx-=Y(V$sMtK?ux$p-(Y9tm=M% z+lQe%|MfKj$Qx=B`|u0762g6d8vRw+qC0cZ?fKTIJ|0+9o6zV`1mN+=ju>Br6AMfF zCb_Ef-1l-GXMnXRLbM#3MO6lA5_{5&BmMsnTAqohhW^%(saBo_L2$uSrQavfSKGDZ zx~|wZ8F7f+oCZ7D%Ov`dQ#OebsNnIXlN{>z#+yio zeP?|yx!yjJai9X1f}DJZq9X*m4O07s}Elo~=dOE2-d1cPl)zsFqtOh0~^_W^MK z-Z2>#X=7Z>d6C`6z9Wg}{|N?K<30ck9SEOv#qrXQ-##ycm->X_rBvt1DDlT4O3vTA zlqv!F$|gBQNahOVfTu--vuov34=3%TU5P#GqVkTqC0L7Ccx-8WAr0CWBujkeemCOO z>a48d>0{JNRw`LIJLp}aOdROBGCPO$M;kLUk6KY{I}w1$8qvk&aDxZ8`>czVUKU|n zF;w~XPxl`t?0l!Sxj|Fmn(5tA$ZLAMvSTz}R?(N5uqQYjG`{PC7dE7zVph?1NpyBr zb)Ha#2mo4aP72z}u46>dN`H@rgr_crXi@1kV-Z*#G|&CLZY8S|7(_1vj_NnhrA}|e z17pw5oEW-JGaHeht1oF=FUkliE^_&p>^LjWd4M2vjs&p<-?^ocf1kxDi@*P1ekSeSX5Nc*HY=JVTLVfQaY|5}%F@icCQTWd zoz1kFRy|8ZRf%z^)^@H?(at9<>7bWh0uEz}e=uk%TWNCt{WSOmp{l1Ts% zr4n55TmzmMu7<)YMWzn>Q zU-^RNprc)o&&5}u_-@JEuKGGut;PIhW@5*gy-|(~uz{kSZt=v)^}JfY&-%NI-9;qw zO4`J=UB*s}BB3 z)Y{B%>x;;&h_y|wmHS#Uz08|Um?<`?Ty~v4N!l+zn5U{mjLrS%GQml0MypPjKR0{?P6NX6We9pAw;kUb<1ae*dkCkHr7??b93H8cIWjEu}a zWl!RmT>+WbuhwG1(k`wU=pWsTXlSECVJU&k9#4_gyfbM+Mug%&#PDX`^POKSICO7G z))*BCl`S2fyAvjfSA4Z@&*~%+oe8oCXt6$vHMh-xwg+gxT|7O}Le`W{G}zj`D?dgp z-L!mR+BfkPyTz1rv?v4~Nu3Xa~6q=y>CUiDi&q=SPgg9jM96F{s zb*b6uEq$5nq*19_3eO4;hB91mJw{t9G12@sLXU%2u+Dx={II`LWo1G+s{FAF^S`o! zf5XUQEH71FiOSrd+>Gcio<4DaB_jgyA)7{!HejiNbO)E@tRFQ5UR?dPa6>p{Le^IH z5o44un%~Fg-g-9& z4t750%~Mx9k^S3yagic_w!**pMx-#FgA22p9hIxDNFQ-^ltV>iDn}M(-;W@TzF)MR z+6VPDn}}&}xE;(cso;!g&G{|+%p7Su=r$DLInbO6X+s!NjCS70y!JSBn9LLUGZH^I zEEb4_;Kl!^M4=1k0f1Jiml+H~J_YJSB|0aU_LqrjxmW-#Wip}H^fwHyACqqlQk_;1RwNS!A zJLVievu6>9OMK*BPk!ok`vC3};$cxL4UIiDi!RsZSB*if9pDl8)G^tg5nQo3+w;lQ zm7zX?mKubYs^ig;87wkjA9^iDgRKS|u!w~@s~W{>L)tPb;Td}cLQ9|>3xVdBZ6gK8 zVS>hH*b~dcUKe#X}(mg~>hw)8VBB}^l92!I`5?!^yOwl%pU>3D_f zjMA2up}GB?rdt2ft&8F?fcV$LrMuR3H>lK3TCDCB3od+Zb1P4DYY^V_gtn=x~r zJk42*wG7@ezID*y)8vu4fMPk(_L~?D$t%hRU&&|x;Sdv(V|lu#PS!%Z0k7h_mGX@w zu#~ou_jk?IW(`hnqH*m3o{|yzhp(pE(m-!?kTYAL^NY2H;` z&~_{F2x@8+q;N3qd#LZYhTp*s--SQyb6&LF3sO#RJ;T;LO}nA zy*Ces`fdBiKgm{-q6i@^C|lVkI~B?vvhT8vCEM6d5<*hRI@W~5*vDWnmXKxa24l}2 zW8cTj{N6s#_rCAvevW$XKYz#ZJ-+`r#x>VWUf1D@I`ur`*gBNB-T(_;Nra`wq4w9}1x=Jg zdp@(>R2H|S6WRnX4dx@3>yHNGM7)CnOR2wwr4*u+6M}8 zP^L*2X)-%`bz^RR-|cg}Z8Pvnb1cwUkN;3-dHa;TG7~+WjNsDh#Gv5q0FLN(-UW}X zJ~z$BwZ%Z@Dm0}qUdo_K5Ns#1jXC=D&__Qa~N#D$#I($u?;Tfl^NIx4Q zcthmt6lV0cOSgXL@z*usN|#VOAl=aAG%o|L#JZk+493r|Mkak}Q~hGSa&}sonddqT zdf-Q-5Tbem@>q@+QZu=oAWW{Ar2Kh#dxDKZZu2A0=q+l3l+1DGgvbc0qWr+h?*8)~ z`EC2d1-HmfVbV)xOZNkqO8*uYiH9uv&5P3&w_)RZw6RDg&QKlB3eP`$Mkss+c%9Ed zc;VP3wgZ*A4cr#n?^370XJ5^LbRDEQW#Piq<-~U;vy3Zc?{&$`Lq~7SCy;hlf|TVc zagEu}w)>{rnmVfU9Wg97$~3@rMt3DZ@^D2*)6<-FSBe$2B62C02VXssmcEtzm>Qu3 zf70W1J>HE?&mQ42#Yx}y8JCzNak<7&RJ1^R*8eCVr#w$BvEYW0ZvIgZMc-G6NU%~; zM*4uQu}9viIJ58O=hR>2K2&=$QoBP2b24wAg~|BVe6pb2_B>?}C@09F3s@l*fN^9^ zY%})yB&B810!tNd#ZXo0U?CNHrjhGrF`D+4jd?Buz?DcG)~8*BLhFhgnd=djjz_$d zNxyP{M9Pqq!{=w6?->HYd|m!&gOxGjpn@rQAQPgl%zH`*j>y*-blON}kSZ4`3xJ(_ zd#-(M#GAtcJyjDsvfu5ri`!A`O~%&CiBn>he6AB;b^8=~-K{j2WHTyyT%oH>MrOyD zJ~CUVv-f;NI$EsISZ`58U*Gy=FCf*95! zRv=_lUbOi1weL{HLcMbeT~d2!f>yULntLu}o72NElet}7|Ka=*i+9F~fzjk{z!Sf{ z`Q!ac+fYrjtQD?$-F+=5J(Nr59|CAGWkBBdiY{Y@UKJcTnAWVXeS8BEW*O4vcc{TS zL7d)Xb4dOQEWB+JH0Tb0((QbQzudT4FuMl{HgqIjd1rynMNkVqEq~%=oEE!V>NwCQ zB~^j7SB9O!_mU(RZ6RGwZML>!8YuCr`1e4JELieZc~-GE1!IW0mG*)9vC+zXclQ#u z4CZgj*~V(Fir^S0`kuh*!nXylU#JZqvMg4%MqFF&5^l@bQl?6a*HadRWgRIYF%<{6 z2lS$;eRlewm>owZ7>=^Q72T6NyG2f88{RM(6T#kB>vi}>vA7P>6AwS?ud6Hi<% zxpvP2R(_YCzUew!aCHh;5?*a5E+vXPl@_L02RpL$2vi4~{mN7{9Bg__CnY{!;q)FT z@EEi4HzyRpQn7a*=K(=AipJm8&Nx&vP3ZHfHzW)G7j|L~`$2`|&ad4=PMBqKVR$}0 z^A#%0(yx^_w;;gdZseyMe);6NLSviDp%~oI^PT2z)3ODaJkERYi=&cpAI*mI*mbf8 zsN&|MEZln?SC|Up`j>6gk^89-sVjXhZsfw)?g&witt^(J$9kcf1kJe!C31@ae#deO zuYM;RGuTZvwW47HkHmcda4oj9ZCz2eBgl^gS!s&c5Qf23ojgQYbcsS8ea8CaCTh;OSzOcA7 z0U2vM2O{6GD7br7CwMFJZQ!Ouy~KiL#*ZwHr-zLZKR;U_nlc3~JHf#=a`(GNVKaW0 zlm#~DkaCD?P*QwOiLeY1+1VE@%=JJk)hZbTIUdU&`YMwqRCM8EUU2^lUI_;}8xp_2 z%nm*SY_TYH2vfNDIQGY0p~O8fX1J9ZoVi?E$dgAZH%>Xs)D4xTzXs31RD|0+90P$h z8n}~FlFl88RxEYB(g883g&e=X8>ilW48V#%)H|matXQvb00*cj8}&Oy#0% zUU$NRgfA)BbmwI1ioy%`MpGmU)?<)inq~%{pQRMlX@R{+48_WMVIgiL;ez3%b0BE~ zH$5xVq* z^yA2(yFvTl-SeMX8k@}Nf=sM3mvQnvRqp-r5U>`a^*u&fV9|B7l5*1 zz8jZZc^-WczMQC4{mM8&pZ-O#aAqgYeIq_~(ygRp+p|>)72%NlO7(T%xo2`< zZ~ly7*U`wJoJ<@WkKj#~FK!MB%9UQWl?uZnmgL)%5zD$ z>-f@1X>cp*+5N$%0$xr(EVr@q`K{JCWYs04I=ysu&Dw+~>!|2G-3sNrO{I#!XZm*p z#l%gViKZLX*vtV8f6+{(xRJD&)HNI3ZAIN?t_(~&O|1EQ!`NV6vDI_V9K``%q7HE? z1zD*TJoe(cY@^jmKPS=@G4s{8iA7+Asci8?6`$4K^@1Si;`Y=Nx-pmDbw8dstX9p2gX%dck&4;Mi`dKQr1(zBfi&e4LgykS`?sSo#ymohgButEj`WbPh zJJP2V+NEl&G@&fBNZw9r=UiT_8|~f*=t;0rv_AM2eAgp}+}AL~O4TXCM9)1g(vni7 z@g)cJA>OQfVCx2ha~v^1xuSaD^*OJCe4h7;g0}@>1@YBb#?fEK^y>U7`Omz>Tqo

R_=#C5-Z#mjRxbR?R@t_VJgwALAX(cKDYMq?%kQ1KK|?e-Hb z0m`w0PXYX%L&kd_xQ@N?L&3bT@nkIObjZRIDHZNeENUcU0Lo;Ns<;@xZ0=sQ9oMi zv>d#Pl`@hUJ4YS`<3sP}AVA`)%S*pLrq|2S2Qz-GWOKn`KeL0lI;tOu062_5HbQEE z?P`m-!V3G9_hG<;B(6qxkyvdE`&5ROH)CgBnM`MRW`<6uu-Fa)m&^*MatyI|(~9-# z0&nDCu&zK>EyAMOY)!K2*~d6fk&)q?QzO;~>|MGb&i=C9JEw#Esi82v3qozP?#pZV_~+LzzD_0W3w-Rq0M*=&F0FXf>RFb_!C%vZ zNwlhN_&-QN0=oLV1u

-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 TWi{gWfzP$eYD$F)cOU)>ZEY?J literal 0 HcmV?d00001 diff --git a/docs/docs/deployment/prerequisites.md b/docs/docs/deployment/prerequisites.md index 8f50b16d..bceaeed5 100644 --- a/docs/docs/deployment/prerequisites.md +++ b/docs/docs/deployment/prerequisites.md @@ -12,7 +12,8 @@ Before using any method, you need to ensure that: 3. Zip these two (or more) files into a `.zip` archive. It's important that it's a **.zip** archive and not anything else. If you are using MacOS, please read the note below. ## Important note for MacOS users -Please use [this](https://www.ezyzip.com/) website for creating archives as MacOS creates an extra `__MACOSX` folder when compressing using the native compress utility which causes some issues with our backend. +Please download the software `RAR Extractor MAX` from App Store ![Mac Zip Software](../../assets/mac_zip.png) for creating archives as MacOS creates an extra `__MACOSX` folder when compressing using the native compress utility which causes some issues with our backend. + ## Folder structure When you decide to archive the files, please **MAKE SURE** that main.py and requirements.txt are available in the **root** of the archive itself. As in if the zip is extracted, it will produce two (or more) files/folders. From a88e18eb3a690ec879c32e8b7f5470ef02761081 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sun, 3 Sep 2023 16:58:27 +0530 Subject: [PATCH 11/35] added script to zip the requirement and main file for deploy. --- zip.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 zip.py diff --git a/zip.py b/zip.py new file mode 100644 index 00000000..ff0079c6 --- /dev/null +++ b/zip.py @@ -0,0 +1,20 @@ +import zipfile +import os + +# Define the names of the files to be zipped +files_to_zip = ['requirements.txt', 'main.py'] + +# Define the name of the output zip file as "deploy.zip" +output_zip_filename = 'deploy.zip' + +# Create a ZipFile object in write mode +with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: + for file_to_zip in files_to_zip: + # Check if the file exists in the current directory + if os.path.exists(file_to_zip): + # Add the file to the zip archive + zipf.write(file_to_zip, os.path.basename(file_to_zip)) + else: + print(f"Warning: {file_to_zip} not found in the current directory.") + +print(f"Files {', '.join(files_to_zip)} have been zipped to {output_zip_filename}") From 5cb2eb4d5465d70c96b93b6e5d42c9c6b61d8d61 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sun, 3 Sep 2023 17:05:15 +0530 Subject: [PATCH 12/35] Delete zip.py --- zip.py | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 zip.py diff --git a/zip.py b/zip.py deleted file mode 100644 index ff0079c6..00000000 --- a/zip.py +++ /dev/null @@ -1,20 +0,0 @@ -import zipfile -import os - -# Define the names of the files to be zipped -files_to_zip = ['requirements.txt', 'main.py'] - -# Define the name of the output zip file as "deploy.zip" -output_zip_filename = 'deploy.zip' - -# Create a ZipFile object in write mode -with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: - for file_to_zip in files_to_zip: - # Check if the file exists in the current directory - if os.path.exists(file_to_zip): - # Add the file to the zip archive - zipf.write(file_to_zip, os.path.basename(file_to_zip)) - else: - print(f"Warning: {file_to_zip} not found in the current directory.") - -print(f"Files {', '.join(files_to_zip)} have been zipped to {output_zip_filename}") From 056edb14434c33d08ff19bbf1dc2b863953df20c Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Sun, 3 Sep 2023 19:29:22 +0530 Subject: [PATCH 13/35] added zip function in textbase cli tool --- textbase/textbase_cli.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 76c75339..71c3a688 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -7,6 +7,8 @@ from yaspin import yaspin import importlib.resources import re +import zipfile + CLOUD_URL = "https://us-east1-chat-agents.cloudfunctions.net/deploy-from-cli" UPLOAD_URL = "https://us-east1-chat-agents.cloudfunctions.net/upload-file" @@ -35,6 +37,25 @@ def test(path): process_local_ui.kill() click.secho("Server stopped.", fg='red') +################################################################################################################# + +@cli.command() +def compress(): + click.echo(click.style(f"Creating zip file for deployment", fg='green')) + + files_to_zip = ['requirements.txt', 'main.py'] + output_zip_filename = 'deploy.zip' + with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: + for file_to_zip in files_to_zip: + # Check if the file exists in the current directory + if os.path.exists(file_to_zip): + # Add the file to the zip archive + zipf.write(file_to_zip, os.path.basename(file_to_zip)) + else: + click.echo(click.style(f"Warning: {file_to_zip} not found in the current directory.", fg='red')) + + click.echo(click.style(f"Files {', '.join(files_to_zip)} have been zipped to {output_zip_filename}", fg='green')) + ################################################################################################################# def validate_bot_name(ctx, param, value): @@ -44,6 +65,7 @@ def validate_bot_name(ctx, param, value): raise click.BadParameter(error_message) return value + @cli.command() @click.option("--path", prompt="Path to the zip folder", required=True) @click.option("--bot_name", prompt="Name of the bot", required=True, callback=validate_bot_name) From 877fd151f6a04d9add919932b28839fcd6ab1a10 Mon Sep 17 00:00:00 2001 From: Ayan Banerjee Date: Sun, 3 Sep 2023 22:26:54 +0530 Subject: [PATCH 14/35] Update llama-bot.md --- docs/docs/examples/llama-bot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/examples/llama-bot.md b/docs/docs/examples/llama-bot.md index 012b85e4..19a294e7 100644 --- a/docs/docs/examples/llama-bot.md +++ b/docs/docs/examples/llama-bot.md @@ -12,7 +12,7 @@ from textbase.models import Llama from typing import List # Load your Replicate API key -Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" +Llama.replicate_api_key = "" # Default Prompt for Llama7b. States how the AI Model is supposed to act like SYSTEM_PROMPT = """\ @@ -48,4 +48,4 @@ def on_message(message_history: List[Message], state: dict = None): "status_code": 200, "response": response } -``` \ No newline at end of file +``` From 9e431ae3e8c256d7c44e8337c2088d2ec29e0261 Mon Sep 17 00:00:00 2001 From: Ayan Banerjee Date: Sun, 3 Sep 2023 22:28:03 +0530 Subject: [PATCH 15/35] Update main.py --- examples/llama-bot/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py index 89bc11c2..c0edcdbf 100644 --- a/examples/llama-bot/main.py +++ b/examples/llama-bot/main.py @@ -3,7 +3,7 @@ from typing import List # Load your Replicate API key -Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" +Llama.replicate_api_key = "" # Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine SYSTEM_PROMPT = """\ @@ -38,4 +38,4 @@ def on_message(message_history: List[Message], state: dict = None): return { "status_code": 200, "response": response - } \ No newline at end of file + } From 2caa2a0df05f4fafa46f0927e17561d63d21b353 Mon Sep 17 00:00:00 2001 From: Nakul Gupta Date: Mon, 4 Sep 2023 17:31:43 +0530 Subject: [PATCH 16/35] Custom port functionality (#107) * Custom port functionality * custom api_port * port fix * Remove unused api_port variable * encoded api url * Docs Updated --- .gitignore | 3 ++- docs/docs/usage.md | 7 ++++++- textbase/textbase_cli.py | 10 ++++++++-- textbase/utils/server.py | 3 --- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 22be37a1..873856ec 100644 --- a/.gitignore +++ b/.gitignore @@ -125,4 +125,5 @@ cpcli-env/ dmypy.json # Pyre type checker -.pyre/ \ No newline at end of file +.pyre/ +.DS_STORE \ No newline at end of file diff --git a/docs/docs/usage.md b/docs/docs/usage.md index fe6d985a..67cdac43 100644 --- a/docs/docs/usage.md +++ b/docs/docs/usage.md @@ -14,12 +14,17 @@ This will start a local server and will give you a link which you can navigate t ```bash textbase-client test ``` -If you wish to run this in one go, you can make use of the `--path` flag +If you wish to run this in one go, you can make use of the `--path` and `--port` flags ```bash textbase-client test --path= ``` **If you wish to use the `--path` flag, make sure you have your path inside quotes.** +```bash +textbase-client test --port=8080 +``` +**Port 8080 is the default, but it's crucial to note that it's frequently used. If you have it open for another application, this flag lets you alter the backend server's port to prevent conflicts.** + ### deploy Before executing this command, make sure that 1. You have a `.zip` file which is made according to the instructions and folder structure given in the diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 76c75339..1f9381db 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -7,6 +7,7 @@ from yaspin import yaspin import importlib.resources import re +import urllib.parse CLOUD_URL = "https://us-east1-chat-agents.cloudfunctions.net/deploy-from-cli" UPLOAD_URL = "https://us-east1-chat-agents.cloudfunctions.net/upload-file" @@ -17,7 +18,8 @@ def cli(): @cli.command() @click.option("--path", prompt="Path to the main.py file", required=True) -def test(path): +@click.option("--port", prompt="Enter port", required=False, default=8080) +def test(path, port): server_path = importlib.resources.files('textbase').joinpath('utils', 'server.py') try: if os.name == 'posix': @@ -25,9 +27,13 @@ def test(path): else: process_local_ui = subprocess.Popen(f'python {server_path}', shell=True) - process_gcp = subprocess.Popen(f'functions_framework --target=on_message --source={path} --debug', + process_gcp = subprocess.Popen(f'functions_framework --target=on_message --source={path} --debug --port={port}', shell=True, stdin=subprocess.PIPE) + + # Print the Bot UI Url + encoded_api_url = urllib.parse.quote(f"http://localhost:{port}", safe='') + click.secho(f"Server URL: http://localhost:4000/?API_URL={encoded_api_url}", fg='cyan', bold=True) process_local_ui.communicate() process_gcp.communicate() # Wait for the process to finish except KeyboardInterrupt: diff --git a/textbase/utils/server.py b/textbase/utils/server.py index 6c451136..b3aef792 100644 --- a/textbase/utils/server.py +++ b/textbase/utils/server.py @@ -3,13 +3,11 @@ import socketserver from textbase.utils.download_build import download_and_extract_zip import click -import urllib.parse socketserver.TCPServer.allow_reuse_address=True # URL of the zip file containing the dist folder zip_url = "https://storage.googleapis.com/chatbot_mainpy/frontendUI.zip" -encoded_api_url = urllib.parse.quote("http://localhost:8080", safe='') # Destination folder where the zip file will be extracted destination_folder = os.path.join(os.getcwd(), "") @@ -33,5 +31,4 @@ def translate_path(self, path): os.chdir(destination_folder) with socketserver.TCPServer(("", PORT), Handler) as httpd: - click.secho(f"Server URL: http://localhost:{PORT}/?API_URL={encoded_api_url}", fg='cyan', bold=True) httpd.serve_forever() \ No newline at end of file From 8d80bdc9d9a61e68bbaa3c9a50fb6bd3b13ec335 Mon Sep 17 00:00:00 2001 From: Haleshot <57552973+Haleshot@users.noreply.github.com> Date: Tue, 5 Sep 2023 16:43:12 +0530 Subject: [PATCH 17/35] Update README: Fix Broken Link (#142) * Update README: Fix Broken Link * Update README: Change Hyperlink name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92866b41..5f0b333f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Since it is just Python you can use whatever models, libraries, vector databases Coming soon: - [x] [PyPI package](https://pypi.org/project/textbase-client/) -- [x] Easy web deployment via [textbase deploy](/docs/deployment/deploy-from-cli) +- [x] Easy web deployment via [textbase-client deploy](docs/docs/deployment/deploy-from-cli.md) - [ ] SMS integration - [ ] Native integration of other models (Claude, Llama, ...) From 658bf009e7f8ed681308c72b188eb5613bd22495 Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Wed, 6 Sep 2023 04:10:05 +0900 Subject: [PATCH 18/35] Fix typo in README.md (#141) documentaion -> documentation --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f0b333f..de202174 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,9 @@ Path to the main.py file: examples/openai-bot/main.py # You can create a main.py Now go to the link in blue color which is shown on the CLI and you will be able to chat with your bot! ![Local UI](assets/test_command.png) -### `Other commands have been mentioned in the documentaion website.` [Have a look](https://docs.textbase.ai/usage) 😃! +### `Other commands have been mentioned in the documentation website.` [Have a look](https://docs.textbase.ai/usage) 😃! ## Contributions -Contributions are welcome! Please open an issue or create a pull request. \ No newline at end of file +Contributions are welcome! Please open an issue or create a pull request. From 52506a9621516d884223e0945c663b262b3e0466 Mon Sep 17 00:00:00 2001 From: Nakul Gupta Date: Wed, 6 Sep 2023 16:49:05 +0530 Subject: [PATCH 19/35] Error handling (#104) --- examples/openai-bot/main.py | 28 +++++++++++++++++++++++----- textbase/textbase_cli.py | 17 +++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/examples/openai-bot/main.py b/examples/openai-bot/main.py index ebc25837..b0fa48ca 100644 --- a/examples/openai-bot/main.py +++ b/examples/openai-bot/main.py @@ -1,6 +1,7 @@ from textbase import bot, Message from textbase.models import OpenAI from typing import List +import click # Load your OpenAI API key OpenAI.api_key = "" @@ -15,11 +16,28 @@ def on_message(message_history: List[Message], state: dict = None): # Generate GPT-3.5 Turbo response - bot_response = OpenAI.generate( - system_prompt=SYSTEM_PROMPT, - message_history=message_history, # Assuming history is the list of user messages - model="gpt-3.5-turbo", - ) + try: + bot_response = OpenAI.generate( + system_prompt=SYSTEM_PROMPT, + message_history=message_history, # Assuming history is the list of user messages + model="gpt-3.5-turbo", + ) + except Exception as e : + click.secho(str(e), fg='red') + return { + "status_code": 500, + "response": { + "data": { + "messages": [], + "state": state + }, + "errors": [ + { + "message": str(e) + } + ] + } + } response = { "data": { diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 1f9381db..e0651009 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -1,3 +1,4 @@ +import inspect import click import requests import subprocess @@ -20,6 +21,22 @@ def cli(): @click.option("--path", prompt="Path to the main.py file", required=True) @click.option("--port", prompt="Enter port", required=False, default=8080) def test(path, port): + # Check if the file exists + if not os.path.exists(path): + click.secho("Incorrect main.py path.", fg='red') + return + + # Load the module dynamically + spec = importlib.util.spec_from_file_location("module.name", path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + # Check if 'on_message' exists and is a function + if "on_message" in dir(module) and inspect.isfunction(getattr(module, "on_message")): + click.secho("The function 'on_message' exists in the specified main.py file.", fg='yellow') + else: + click.secho("The function 'on_message' does not exist in the specified main.py file.", fg='red') + return server_path = importlib.resources.files('textbase').joinpath('utils', 'server.py') try: if os.name == 'posix': From 854102c11e9b8215003b7cd2820507efb3f09141 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Wed, 6 Sep 2023 17:30:38 +0530 Subject: [PATCH 20/35] Added file check such that deploy.zip won't be created if either of main.py or requirements.txt is not present. Added --path flag to take the path of both the files from user. --- textbase/textbase_cli.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 71c3a688..0f096354 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -38,24 +38,33 @@ def test(path): click.secho("Server stopped.", fg='red') ################################################################################################################# - +def fileExist(main_path,requirements_path): + if not os.path.exists(main_path): + click.echo(click.style(f"Error: main.py not found in the mentioned directory.", fg='red')) + return False + if not os.path.exists(requirements_path): + click.echo(click.style(f"Error: reuirements.txt not found in the mentioned directory.", fg='red')) + return False + + return True + @cli.command() -def compress(): +@click.option("--main_path", prompt="Path to the main.py file", required=True) +@click.option("--requirements_path", prompt="Path to the requirements.txt file", required=True) +def compress(main_path,requirements_path): click.echo(click.style(f"Creating zip file for deployment", fg='green')) - - files_to_zip = ['requirements.txt', 'main.py'] + # files_to_zip = ['requirements.txt', 'main.py'] + files_to_zip = [main_path, requirements_path] + files_exist = all(os.path.exists(file) for file in files_to_zip) output_zip_filename = 'deploy.zip' - with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: - for file_to_zip in files_to_zip: - # Check if the file exists in the current directory - if os.path.exists(file_to_zip): + + if fileExist(main_path=main_path,requirements_path=requirements_path): + with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: + for file_to_zip in files_to_zip: # Add the file to the zip archive zipf.write(file_to_zip, os.path.basename(file_to_zip)) - else: - click.echo(click.style(f"Warning: {file_to_zip} not found in the current directory.", fg='red')) - - click.echo(click.style(f"Files {', '.join(files_to_zip)} have been zipped to {output_zip_filename}", fg='green')) + click.echo(click.style(f"Files {', '.join(files_to_zip)} have been zipped to {output_zip_filename}", fg='green')) ################################################################################################################# def validate_bot_name(ctx, param, value): From 995812cfefe27024d2535321864ad989c3f7e457 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Wed, 6 Sep 2023 17:42:39 +0530 Subject: [PATCH 21/35] resolved merge conflicts --- textbase/textbase_cli.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index bc7161a9..9eb7b8c4 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -8,12 +8,8 @@ from yaspin import yaspin import importlib.resources import re -<<<<<<< HEAD import zipfile -======= -import urllib.parse ->>>>>>> 52506a9621516d884223e0945c663b262b3e0466 CLOUD_URL = "https://us-east1-chat-agents.cloudfunctions.net/deploy-from-cli" UPLOAD_URL = "https://us-east1-chat-agents.cloudfunctions.net/upload-file" From b0bf5fbab38b1bdf3c6c9846bc029685ecfe1234 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Wed, 6 Sep 2023 17:46:27 +0530 Subject: [PATCH 22/35] removed unused code. --- textbase/textbase_cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 9eb7b8c4..1e9efd49 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -75,7 +75,6 @@ def fileExist(main_path,requirements_path): @click.option("--requirements_path", prompt="Path to the requirements.txt file", required=True) def compress(main_path,requirements_path): click.echo(click.style(f"Creating zip file for deployment", fg='green')) - # files_to_zip = ['requirements.txt', 'main.py'] files_to_zip = [main_path, requirements_path] files_exist = all(os.path.exists(file) for file in files_to_zip) output_zip_filename = 'deploy.zip' From 28316fa983782a245f66fb846373dd1d18ea8255 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Wed, 6 Sep 2023 18:21:02 +0530 Subject: [PATCH 23/35] added documentation for paLM AI --- docs/docs/examples/palmai-bot.md | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 docs/docs/examples/palmai-bot.md diff --git a/docs/docs/examples/palmai-bot.md b/docs/docs/examples/palmai-bot.md new file mode 100644 index 00000000..26d73128 --- /dev/null +++ b/docs/docs/examples/palmai-bot.md @@ -0,0 +1,49 @@ +--- +sidebar_position: 2 +--- + +# Google PaLM AI bot + +This bot makes an API call to PaLMAI and processes the user input. It uses PaLM Chat. + +```py +import os +from textbase import bot, Message +from textbase.models import PalmAI +from typing import List + +# Load your PALM API key +# PALMAI.api_key = "" +# or from environment variable: +PalmAI.api_key = os.getenv("PALM_API_KEY") + +@bot() +def on_message(message_history: List[Message], state: dict = None): + + bot_response = PalmAI.generate( + message_history=message_history, # Assuming history is the list of user messages + ) + + response = { + "data": { + "messages": [ + { + "data_type": "STRING", + "value": bot_response + } + ], + "state": state + }, + "errors": [ + { + "message": "" + } + ] + } + + return { + "status_code": 200, + "response": response + } + +``` \ No newline at end of file From 891bdb6517ab5ad1c405d888d6500dcd005bed34 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Thu, 7 Sep 2023 00:19:32 +0530 Subject: [PATCH 24/35] Replaced the extract_user_content_values with extract_content_values --- textbase/models.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/textbase/models.py b/textbase/models.py index 96c9d36e..33ff1692 100644 --- a/textbase/models.py +++ b/textbase/models.py @@ -27,14 +27,6 @@ def extract_content_values(message: Message): if content ] -# Returns user content if it's non empty. -def extract_user_content_values(message:Message): - return [ - content["content"] - for content in get_contents(message,"STRING") - if content and content["role"] == "user" - ] - class OpenAI: api_key = None @@ -170,7 +162,7 @@ def generate( for message in message_history: #list of all the contents inside a single message - contents = extract_user_content_values(message) + contents = extract_content_values(message) if contents: filtered_messages.extend(contents) From e54e0ad01855d9e386d26b02f07f063433b5bd10 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Thu, 7 Sep 2023 20:19:28 +0530 Subject: [PATCH 25/35] modified compress command to take directory path, check if main.py and requirements.txt is in path and compress everything from directory into deploy.zip --- textbase/textbase_cli.py | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index 1e9efd49..fce3be7d 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -60,32 +60,28 @@ def test(path, port): click.secho("Server stopped.", fg='red') ################################################################################################################# -def fileExist(main_path,requirements_path): - if not os.path.exists(main_path): - click.echo(click.style(f"Error: main.py not found in the mentioned directory.", fg='red')) +def fileExist(path): + if not os.path.exists(os.path.join(path, "main.py")): + click.echo(click.style(f"Error: main.py not found in {path} directory.", fg='red')) return False - if not os.path.exists(requirements_path): - click.echo(click.style(f"Error: reuirements.txt not found in the mentioned directory.", fg='red')) + if not os.path.exists(os.path.join(path, "requirements.txt")): + click.echo(click.style(f"Error: requirements.txt not found in {path} directory.", fg='red')) return False - return True @cli.command() -@click.option("--main_path", prompt="Path to the main.py file", required=True) -@click.option("--requirements_path", prompt="Path to the requirements.txt file", required=True) -def compress(main_path,requirements_path): +@click.option("--path", prompt="Path to the directory containing main.py and requirements.txt file", required=True) +def compress(path): click.echo(click.style(f"Creating zip file for deployment", fg='green')) - files_to_zip = [main_path, requirements_path] - files_exist = all(os.path.exists(file) for file in files_to_zip) output_zip_filename = 'deploy.zip' - - if fileExist(main_path=main_path,requirements_path=requirements_path): + if fileExist(path): with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: - for file_to_zip in files_to_zip: + for root, _, files in os.walk(path): + for file in files: + file_path = os.path.join(root, file) # Add the file to the zip archive - zipf.write(file_to_zip, os.path.basename(file_to_zip)) - - click.echo(click.style(f"Files {', '.join(files_to_zip)} have been zipped to {output_zip_filename}", fg='green')) + zipf.write(file_path, os.path.relpath(file_path, path)) + click.echo(click.style(f"Files have been zipped to {output_zip_filename}", fg='green')) ################################################################################################################# def validate_bot_name(ctx, param, value): From ffaab83a2722bd99e92ac8cf419f6e9cd0025504 Mon Sep 17 00:00:00 2001 From: Etancher <30360093+jahanvir@users.noreply.github.com> Date: Thu, 7 Sep 2023 21:47:44 +0530 Subject: [PATCH 26/35] added the condition to avoid deploy.zip being created inside deploy.zip --- textbase/textbase_cli.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index fce3be7d..19baaa84 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -78,9 +78,10 @@ def compress(path): with zipfile.ZipFile(output_zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: for root, _, files in os.walk(path): for file in files: - file_path = os.path.join(root, file) - # Add the file to the zip archive - zipf.write(file_path, os.path.relpath(file_path, path)) + if file != output_zip_filename: + file_path = os.path.join(root, file) + # Add the file to the zip archive + zipf.write(file_path, os.path.relpath(file_path, path)) click.echo(click.style(f"Files have been zipped to {output_zip_filename}", fg='green')) ################################################################################################################# From 58fa7f3659f372da9578f0714d745ea997de9f9e Mon Sep 17 00:00:00 2001 From: Kaustubh <139532137+kaus-cofactory@users.noreply.github.com> Date: Thu, 7 Sep 2023 23:36:57 +0530 Subject: [PATCH 27/35] piping out logs in the cli (#143) * piping out logs in the cli * add loading animation while fetching logs --- pyproject.toml | 1 + textbase/textbase_cli.py | 44 +++++++++++++++++++++++++++++++++++++++- textbase/utils/logs.py | 42 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 textbase/utils/logs.py diff --git a/pyproject.toml b/pyproject.toml index 8738793e..25a024e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ functions-framework = "^3.4.0" yaspin = "^3.0.0" pydantic = "^2.3.0" google-generativeai = "^0.1.0" +rich = "^13.5.2" [build-system] requires = ["poetry-core"] diff --git a/textbase/textbase_cli.py b/textbase/textbase_cli.py index e0651009..66c55534 100644 --- a/textbase/textbase_cli.py +++ b/textbase/textbase_cli.py @@ -9,6 +9,8 @@ import importlib.resources import re import urllib.parse +from textbase.utils.logs import fetch_and_display_logs + CLOUD_URL = "https://us-east1-chat-agents.cloudfunctions.net/deploy-from-cli" UPLOAD_URL = "https://us-east1-chat-agents.cloudfunctions.net/upload-file" @@ -71,7 +73,8 @@ def validate_bot_name(ctx, param, value): @click.option("--path", prompt="Path to the zip folder", required=True) @click.option("--bot_name", prompt="Name of the bot", required=True, callback=validate_bot_name) @click.option("--api_key", prompt="Textbase API Key", required=True) -def deploy(path, bot_name, api_key): +@click.option("--show_logs", is_flag=True, default=True, help="Fetch show_logs after deployment") +def deploy(path, bot_name, api_key, show_logs): click.echo(click.style(f"Deploying bot '{bot_name}' with zip folder from path: {path}", fg='yellow')) headers = { @@ -116,6 +119,23 @@ def deploy(path, bot_name, api_key): else: click.echo(click.style("Something went wrong! ❌", fg='red')) click.echo(response.text) + + # Piping logs in the cli in real-time + if show_logs: + click.echo(click.style(f"Fetching logs for bot '{bot_name}'...", fg='green')) + + cloud_url = f"{CLOUD_URL}/logs" + headers = { + "Authorization": f"Bearer {api_key}" + } + params = { + "botName": bot_name, + "pageToken": None + } + + fetch_and_display_logs(cloud_url=cloud_url, + headers=headers, + params=params) ################################################################################################################# @cli.command() @@ -223,6 +243,28 @@ def delete(bot_id, api_key): else: click.echo(click.style("Something went wrong!", fg='red')) + +@cli.command() +@click.option("--bot_name", prompt="Name of the bot", required=True) +@click.option("--api_key", prompt="Textbase API Key", required=True) +@click.option("--start_time", prompt="Logs for previous ___ minutes", required=False, default=5) +def logs(bot_name, api_key, start_time): + click.echo(click.style(f"Fetching logs for bot '{bot_name}'...", fg='green')) + + cloud_url = f"{CLOUD_URL}/logs" + headers = { + "Authorization": f"Bearer {api_key}" + } + params = { + "botName": bot_name, + "startTime": start_time, + "pageToken": None + } + + fetch_and_display_logs(cloud_url=cloud_url, + headers=headers, + params=params) + if __name__ == "__main__": cli() diff --git a/textbase/utils/logs.py b/textbase/utils/logs.py new file mode 100644 index 00000000..5ce7ff93 --- /dev/null +++ b/textbase/utils/logs.py @@ -0,0 +1,42 @@ +import requests +from rich.console import Console +from rich.table import Table +from rich.text import Text +import time +import click +from yaspin import yaspin + +def fetch_and_display_logs(cloud_url, headers, params): + console = Console() + table = Table(show_header=True, header_style="bold magenta") + table.add_column("Timestamp") + table.add_column("Severity") + table.add_column("Summary") + + while True: + with yaspin(text="Logs...", color="yellow") as spinner: + response = requests.get(cloud_url, headers=headers, params=params) + + if response.ok: + response_data = response.json() + data = response_data.get('data') + if data is not None: + logs = data.get('logs') + if logs: + for log in logs: + severity_color = 'blue' if log['severity'].lower() in ['notice', 'info', 'debug'] else 'red' if log['severity'].lower() in ['alert', 'critical', 'error'] else 'yellow' + + table.add_row(log['timestamp'], Text(log['severity'], style=severity_color), Text(log.get('text', ''), style=severity_color)) + + console.clear() + console.print(table) + # Update the params for the next request + params['pageToken'] = data.get('nextPageToken') + params['startTime'] = data.get('startTime') + else: + click.echo(click.style("No logs found in the response.", fg='yellow')) + else: + click.echo(click.style("Failed to retrieve logs.", fg='red')) + + # Poll the endpoint every 3 seconds + time.sleep(3) \ No newline at end of file From 2ac3f3518836993d18c25bec15329d0c0a2c00ad Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Fri, 8 Sep 2023 21:16:22 +0530 Subject: [PATCH 28/35] Updated repo to latest build --- pyproject.toml | 2 ++ textbase/models.py | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 4b88f6b4..9a08b92b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,8 @@ tabulate = "^0.9.0" functions-framework = "^3.4.0" yaspin = "^3.0.0" pydantic = "^2.3.0" +google-generativeai = "^0.1.0" +rich = "^13.5.2" replicate = "^0.11.0" [build-system] diff --git a/textbase/models.py b/textbase/models.py index bba6f93e..4131b84b 100644 --- a/textbase/models.py +++ b/textbase/models.py @@ -5,6 +5,7 @@ import typing import traceback import replicate +import google.generativeai as palm from textbase import Message @@ -146,6 +147,32 @@ def generate( return message +class PalmAI: + api_key = None + + @classmethod + def generate( + cls, + message_history: list[Message], + ): + + assert cls.api_key is not None, "Palm API key is not set." + palm.configure(api_key=cls.api_key) + + filtered_messages = [] + + for message in message_history: + #list of all the contents inside a single message + contents = extract_content_values(message) + if contents: + filtered_messages.extend(contents) + + #send request to Google Palm chat API + response = palm.chat(messages=filtered_messages) + + print(response) + return response.last + class Llama: @classmethod From a02172004b247811f03698258cdc0691e224242a Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 13:57:09 +0530 Subject: [PATCH 29/35] Added Meta's Llama 2 API to textbase, updated docs accordingly --- docs/docs/examples/llama-bot.md | 51 +++++++++++++++++++++++++++++++++ examples/llama-bot/main.py | 41 ++++++++++++++++++++++++++ pyproject.toml | 1 + textbase/models.py | 36 +++++++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 docs/docs/examples/llama-bot.md create mode 100644 examples/llama-bot/main.py diff --git a/docs/docs/examples/llama-bot.md b/docs/docs/examples/llama-bot.md new file mode 100644 index 00000000..7bcc5c22 --- /dev/null +++ b/docs/docs/examples/llama-bot.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 3 +--- + +# HuggingFace bot + +This bot makes an API call to Meta's LLama 2 API and processes the user input. It uses Llama-2-7B model. + +```py +from textbase import bot, Message +from textbase.models import Llama +from typing import List + +# Load your Replicate API key +Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" + +# Default Prompt for Llama7b. States how the AI Model is supposed to act like +SYSTEM_PROMPT = """\ +You are a helpful assistant""" + +@bot() +def on_message(message_history: List[Message], state: dict = None): + + # Generate Llama7b responses + bot_response = Llama.generate( + system_prompt=SYSTEM_PROMPT, + message_history=message_history, # Assuming history is the list of user messages + ) + + response = { + "data": { + "messages": [ + { + "data_type": "STRING", + "value": bot_response + } + ], + "state": state + }, + "errors": [ + { + "message": "" + } + ] + } + + return { + "status_code": 200, + "response": response + } +``` \ No newline at end of file diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py new file mode 100644 index 00000000..89bc11c2 --- /dev/null +++ b/examples/llama-bot/main.py @@ -0,0 +1,41 @@ +from textbase import bot, Message +from textbase.models import Llama +from typing import List + +# Load your Replicate API key +Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" + +# Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine +SYSTEM_PROMPT = """\ +You are a helpful assistant""" + +@bot() +def on_message(message_history: List[Message], state: dict = None): + + # Generate Llama7b response by default + bot_response = Llama.generate( + system_prompt=SYSTEM_PROMPT, + message_history=message_history, # Assuming history is the list of user messages + ) + + response = { + "data": { + "messages": [ + { + "data_type": "STRING", + "value": bot_response + } + ], + "state": state + }, + "errors": [ + { + "message": "" + } + ] + } + + return { + "status_code": 200, + "response": response + } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 25a024e7..0946b9e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ tabulate = "^0.9.0" functions-framework = "^3.4.0" yaspin = "^3.0.0" pydantic = "^2.3.0" +replicate = "^0.11.0" google-generativeai = "^0.1.0" rich = "^13.5.2" diff --git a/textbase/models.py b/textbase/models.py index 33ff1692..33122276 100644 --- a/textbase/models.py +++ b/textbase/models.py @@ -5,6 +5,7 @@ import time import typing import traceback +import replicate from textbase import Message @@ -145,6 +146,41 @@ def generate( message = data['message'] return message + +class Llama: + + @classmethod + def generate( + cls, + system_prompt: str, + message_history: list[Message], + model = "a16z-infra/llama7b-v2-chat:4f0a4744c7295c024a1de15e1a63c880d3da035fa1f49bfd344fe076074c8eea", + temperature = 0.81, #seems to give the best responses + top_p = 0.95, + max_length = 3008 #same for this + ): + try: + assert cls.replicate_api_key is not None, "Replicate API key is not set." + client=replicate.Client(api_token=cls.replicate_api_key) #creating the client for the model + + past_conversation="" + + for message in message_history: + if message["role"] == "user": + past_conversation+="[INST] ".join(extract_content_values(message))+" [/INST]\n" #Llama2 paper mentions tokenization of user messages with INST delimiter, otherwise the responses get ugly with time. + else: + past_conversation+=" ".join(extract_content_values(message))+"\n" #response messages dont need any delimiters + + response=client.run(model,input={"prompt": past_conversation,"system_prompt": system_prompt,"temperature":temperature,"top_p":top_p,"max_length":max_length,"repetition_penalty":1}) + + resp="" + for word in response: + resp+=word + + return resp + + except Exception: + print(f"An exception occured while using this model, please try using another model.\nException: {traceback.format_exc()}.") class PalmAI: api_key = None From d80de505bf74133b993b8dc67ca6d97d06d2d9b0 Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 13:59:36 +0530 Subject: [PATCH 30/35] Updated Readme and docs --- README.md | 2 +- docs/docs/intro.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de202174..a265a8d9 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Coming soon: - [x] [PyPI package](https://pypi.org/project/textbase-client/) - [x] Easy web deployment via [textbase-client deploy](docs/docs/deployment/deploy-from-cli.md) - [ ] SMS integration -- [ ] Native integration of other models (Claude, Llama, ...) +- [ ] Native integration of other models (Claude, ...) ![Demo Deploy GIF](assets/textbase-deploy.gif) diff --git a/docs/docs/intro.md b/docs/docs/intro.md index fabeec56..91e4cd88 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -14,4 +14,4 @@ Coming soon: - [x] [PyPI package](https://pypi.org/project/textbase-client/) - [x] Easy web deployment via [textbase-client deploy](../docs/deployment/deploy-from-cli.md) - [ ] SMS integration -- [ ] Native integration of other models (Claude, Llama, ...) \ No newline at end of file +- [ ] Native integration of other models (Claude, ...) \ No newline at end of file From 71171fc815953023506a3897eaf77f38e054291c Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 14:06:23 +0530 Subject: [PATCH 31/35] Removed replicate API key --- examples/llama-bot/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py index 89bc11c2..d9a03307 100644 --- a/examples/llama-bot/main.py +++ b/examples/llama-bot/main.py @@ -3,7 +3,7 @@ from typing import List # Load your Replicate API key -Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" +Llama.replicate_api_key = "" # Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine SYSTEM_PROMPT = """\ From 03fda2ca44a20fa60e7e928b8a4dfd345c4d6ef8 Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Sun, 3 Sep 2023 14:16:27 +0530 Subject: [PATCH 32/35] Updated docs --- docs/docs/examples/llama-bot.md | 2 +- examples/llama-bot/main.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/examples/llama-bot.md b/docs/docs/examples/llama-bot.md index 7bcc5c22..012b85e4 100644 --- a/docs/docs/examples/llama-bot.md +++ b/docs/docs/examples/llama-bot.md @@ -2,7 +2,7 @@ sidebar_position: 3 --- -# HuggingFace bot +# Llama bot This bot makes an API call to Meta's LLama 2 API and processes the user input. It uses Llama-2-7B model. diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py index d9a03307..89bc11c2 100644 --- a/examples/llama-bot/main.py +++ b/examples/llama-bot/main.py @@ -3,7 +3,7 @@ from typing import List # Load your Replicate API key -Llama.replicate_api_key = "" +Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" # Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine SYSTEM_PROMPT = """\ From 1d54f5b17e63876114dfe034b6b1c12731f16329 Mon Sep 17 00:00:00 2001 From: Ayan Banerjee Date: Sun, 3 Sep 2023 22:26:54 +0530 Subject: [PATCH 33/35] Update llama-bot.md --- docs/docs/examples/llama-bot.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/examples/llama-bot.md b/docs/docs/examples/llama-bot.md index 012b85e4..19a294e7 100644 --- a/docs/docs/examples/llama-bot.md +++ b/docs/docs/examples/llama-bot.md @@ -12,7 +12,7 @@ from textbase.models import Llama from typing import List # Load your Replicate API key -Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" +Llama.replicate_api_key = "" # Default Prompt for Llama7b. States how the AI Model is supposed to act like SYSTEM_PROMPT = """\ @@ -48,4 +48,4 @@ def on_message(message_history: List[Message], state: dict = None): "status_code": 200, "response": response } -``` \ No newline at end of file +``` From 8de7761a5843209537e19bc5d7d310d85f855aa7 Mon Sep 17 00:00:00 2001 From: Ayan Banerjee Date: Sun, 3 Sep 2023 22:28:03 +0530 Subject: [PATCH 34/35] Update main.py --- examples/llama-bot/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/llama-bot/main.py b/examples/llama-bot/main.py index 89bc11c2..c0edcdbf 100644 --- a/examples/llama-bot/main.py +++ b/examples/llama-bot/main.py @@ -3,7 +3,7 @@ from typing import List # Load your Replicate API key -Llama.replicate_api_key = "r8_8xsgb2mpX8GB9Iz9BduNR3vwc0vs7Ei1zFi3u" +Llama.replicate_api_key = "" # Prompt for Llama7b. Llama gets offensive with larger complicated system prompts. This works just fine SYSTEM_PROMPT = """\ @@ -38,4 +38,4 @@ def on_message(message_history: List[Message], state: dict = None): return { "status_code": 200, "response": response - } \ No newline at end of file + } From e1d3ae97b78f3e552e62ef59d6a7339dd6275216 Mon Sep 17 00:00:00 2001 From: AyanBanerjee Date: Fri, 8 Sep 2023 21:16:22 +0530 Subject: [PATCH 35/35] Updated repo to latest build --- pyproject.toml | 2 ++ textbase/models.py | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 0946b9e5..b7316f85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,8 @@ tabulate = "^0.9.0" functions-framework = "^3.4.0" yaspin = "^3.0.0" pydantic = "^2.3.0" +google-generativeai = "^0.1.0" +rich = "^13.5.2" replicate = "^0.11.0" google-generativeai = "^0.1.0" rich = "^13.5.2" diff --git a/textbase/models.py b/textbase/models.py index 33122276..e9d7a3c1 100644 --- a/textbase/models.py +++ b/textbase/models.py @@ -6,6 +6,7 @@ import typing import traceback import replicate +import google.generativeai as palm from textbase import Message @@ -147,6 +148,32 @@ def generate( return message +class PalmAI: + api_key = None + + @classmethod + def generate( + cls, + message_history: list[Message], + ): + + assert cls.api_key is not None, "Palm API key is not set." + palm.configure(api_key=cls.api_key) + + filtered_messages = [] + + for message in message_history: + #list of all the contents inside a single message + contents = extract_content_values(message) + if contents: + filtered_messages.extend(contents) + + #send request to Google Palm chat API + response = palm.chat(messages=filtered_messages) + + print(response) + return response.last + class Llama: @classmethod