From fe66d9935081dc13fa41ffde590c27189a7078ed Mon Sep 17 00:00:00 2001 From: Nicki Susman Date: Wed, 26 Jun 2024 09:00:00 -0400 Subject: [PATCH 1/5] QBusiness IDC Integration --- .../src/lambdahook.py | 146 ++++++++++++------ .../qna_bot_qbusiness_lambdahook/template.yml | 20 +++ 2 files changed, 121 insertions(+), 45 deletions(-) diff --git a/lambdas/qna_bot_qbusiness_lambdahook/src/lambdahook.py b/lambdas/qna_bot_qbusiness_lambdahook/src/lambdahook.py index 42f3d82..ce4ae05 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/src/lambdahook.py +++ b/lambdas/qna_bot_qbusiness_lambdahook/src/lambdahook.py @@ -1,28 +1,24 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 - +import base64 import json import os +import random +import string import uuid import boto3 AMAZONQ_APP_ID = os.environ.get("AMAZONQ_APP_ID") AMAZONQ_REGION = os.environ.get("AMAZONQ_REGION") or os.environ["AWS_REGION"] -AMAZONQ_ENDPOINT_URL = os.environ.get("AMAZONQ_ENDPOINT_URL") or f'https://qbusiness.{AMAZONQ_REGION}.api.aws' +AMAZONQ_ENDPOINT_URL = os.environ.get("AMAZONQ_ENDPOINT_URL") or f'https://qbusiness.{AMAZONQ_REGION}.api.aws' print("AMAZONQ_ENDPOINT_URL:", AMAZONQ_ENDPOINT_URL) -qbusiness_client = boto3.client( - service_name="qbusiness", - region_name=AMAZONQ_REGION, - endpoint_url=AMAZONQ_ENDPOINT_URL -) -def get_amazonq_response(prompt, context, amazonq_userid, attachments): +def get_amazonq_response(prompt, context, attachments, qbusiness_client): print(f"get_amazonq_response: prompt={prompt}, app_id={AMAZONQ_APP_ID}, context={context}") input = { "applicationId": AMAZONQ_APP_ID, - "userMessage": prompt, - "userId": amazonq_userid + "userMessage": prompt } if context: if context["conversationId"]: @@ -31,7 +27,7 @@ def get_amazonq_response(prompt, context, amazonq_userid, attachments): input["parentMessageId"] = context["parentMessageId"] else: input["clientToken"] = str(uuid.uuid4()) - + if attachments: input["attachments"] = attachments @@ -43,12 +39,13 @@ def get_amazonq_response(prompt, context, amazonq_userid, attachments): resp = { "systemMessage": "Amazon Q Error: " + str(e) } - print("Amazon Q Response: ", json.dumps(resp)) + print("Amazon Q Response: ", json.dumps(resp, default=str)) return resp + def get_settings_from_lambdahook_args(event): lambdahook_settings = {} - lambdahook_args_list = event["res"]["result"].get("args",[]) + lambdahook_args_list = event["res"]["result"].get("args", []) print("LambdaHook args: ", lambdahook_args_list) if len(lambdahook_args_list): try: @@ -58,18 +55,10 @@ def get_settings_from_lambdahook_args(event): print("..continuing") return lambdahook_settings -def get_user_email(event): - isVerifiedIdentity = event["req"]["_userInfo"].get("isVerifiedIdentity") - if not isVerifiedIdentity: - print("User is not verified identity") - return "Bot_user_not_verified" - user_email = event["req"]["_userInfo"].get("Email") - print(f"using verified bot user email as user id: {user_email}") - return user_email def get_args_from_lambdahook_args(event): parameters = {} - lambdahook_args_list = event["res"]["result"].get("args",[]) + lambdahook_args_list = event["res"]["result"].get("args", []) print("LambdaHook args: ", lambdahook_args_list) if len(lambdahook_args_list): try: @@ -79,6 +68,7 @@ def get_args_from_lambdahook_args(event): print("..continuing") return parameters + def getS3File(s3Path): if s3Path.startswith("s3://"): s3Path = s3Path[5:] @@ -87,8 +77,9 @@ def getS3File(s3Path): obj = s3.Object(bucket, key) return obj.get()['Body'].read() + def getAttachments(event): - userFilesUploaded = event["req"]["session"].get("userFilesUploaded",[]) + userFilesUploaded = event["req"]["session"].get("userFilesUploaded", []) attachments = [] for userFile in userFilesUploaded: print(f"getAttachments: userFile={userFile}") @@ -97,16 +88,17 @@ def getAttachments(event): "name": userFile["fileName"] }) # delete userFilesUploaded from session - event["res"]["session"].pop("userFilesUploaded",None) + event["res"]["session"].pop("userFilesUploaded", None) return attachments + def format_response(event, amazonq_response): # get settings, if any, from lambda hook args # e.g: {"Prefix":"", "ShowContext": False} lambdahook_settings = get_settings_from_lambdahook_args(event) - prefix = lambdahook_settings.get("Prefix","Amazon Q Answer:") - showContextText = lambdahook_settings.get("ShowContextText",True) - showSourceLinks = lambdahook_settings.get("ShowSourceLinks",True) + prefix = lambdahook_settings.get("Prefix", "Amazon Q Answer:") + showContextText = lambdahook_settings.get("ShowContextText", True) + showSourceLinks = lambdahook_settings.get("ShowSourceLinks", True) # set plaintext, markdown, & ssml response if prefix in ["None", "N/A", "Empty"]: prefix = None @@ -118,21 +110,22 @@ def format_response(event, amazonq_response): markdown = f"**{prefix}**\n\n{markdown}" if showContextText: contextText = "" - for source in amazonq_response.get("sourceAttributions",[]): - title = source.get("title","title missing") - snippet = source.get("snippet","snippet missing") + for source in amazonq_response.get("sourceAttributions", []): + title = source.get("title", "title missing") + snippet = source.get("snippet", "snippet missing") url = source.get("url") if url: contextText = f'{contextText}
{title}' else: contextText = f'{contextText}
{title}' - contextText = f"{contextText}
{snippet}\n" + # Returning too large of a snippet can break QnABot by exceeding the event payload size limit + contextText = f"{contextText}
{snippet}\n"[:5000] if contextText: markdown = f'{markdown}\n
Context

{contextText}

' if showSourceLinks: sourceLinks = [] - for source in amazonq_response.get("sourceAttribution",[]): - title = source.get("title","link (no title)") + for source in amazonq_response.get("sourceAttribution", []): + title = source.get("title", "link (no title)") url = source.get("url") if url: sourceLinks.append(f'{title}') @@ -153,26 +146,89 @@ def format_response(event, amazonq_response): "parentMessageId": amazonq_response.get("systemMessageId") } event["res"]["session"]["qnabotcontext"]["amazonq_context"] = amazonq_context - #TODO - can we determine when Amazon Q has a good answer or not? - #For now, always assume it's a good answer. - #QnAbot sets session attribute qnabot_gotanswer True when got_hits > 0 + # TODO - can we determine when Amazon Q has a good answer or not? + # For now, always assume it's a good answer. + # QnAbot sets session attribute qnabot_gotanswer True when got_hits > 0 event["res"]["got_hits"] = 1 return event + +def get_idc_iam_credentials(jwt): + sso_oidc_client = boto3.client('sso-oidc') + idc_sso_resp = sso_oidc_client.create_token_with_iam( + clientId=os.environ.get("IDC_CLIENT_ID"), + grantType="urn:ietf:params:oauth:grant-type:jwt-bearer", + assertion=jwt, + ) + + print(idc_sso_resp) + idc_sso_id_token_jwt = json.loads(base64.b64decode(idc_sso_resp['idToken'].split('.')[1] + '==').decode()) + + sts_context = idc_sso_id_token_jwt["sts:identity_context"] + sts_client = boto3.client('sts') + session_name = "qbusiness-idc-" + "".join( + random.choices(string.ascii_letters + string.digits, k=32) + ) + assumed_role_object = sts_client.assume_role( + RoleArn=os.environ.get("AMAZONQ_ROLE_ARN"), + RoleSessionName=session_name, + ProvidedContexts=[{ + "ProviderArn": "arn:aws:iam::aws:contextProvider/IdentityCenter", + "ContextAssertion": sts_context + }] + ) + creds_object = assumed_role_object['Credentials'] + + return creds_object + + def lambda_handler(event, context): print("Received event: %s" % json.dumps(event)) args = get_args_from_lambdahook_args(event) - # prompt set from args, or from req.question if not specified in args. - userInput = args.get("Prompt", event["req"]["question"]) - qnabotcontext = event["req"]["session"].get("qnabotcontext",{}) - amazonq_context = qnabotcontext.get("amazonq_context",{}) + # prompt set from args, or from the original query if not specified in args. + userInput = event["req"]["llm_generated_query"]["orig"] + qnabotcontext = event["req"]["session"].get("qnabotcontext", {}) + amazonq_context = qnabotcontext.get("amazonq_context", {}) attachments = getAttachments(event) - amazonq_userid = os.environ.get("AMAZONQ_USER_ID") - if not amazonq_userid: - amazonq_userid = get_user_email(event) + + # Get the IDC IAM credentials + # Parse session JWT token to get the jti + token = (event['req']['session']['idtokenjwt']) + decoded_token = json.loads(base64.b64decode(token.split('.')[1] + '==').decode()) + jti = decoded_token['jti'] + + dynamo_resource = boto3.resource('dynamodb') + dynamo_table = dynamo_resource.Table(os.environ.get('DYNAMODB_CACHE_TABLE_NAME')) + + kms_client = boto3.client('kms') + kms_key_id = os.environ.get("KMS_KEY_ID") + + # Check if JTI exists in caching DB + response = dynamo_table.get_item(Key={'jti': jti}) + + if 'Item' in response: + creds = json.loads((kms_client.decrypt( + KeyId=kms_key_id, + CiphertextBlob=response['Item']['Credentials'].value))['Plaintext']) else: - print(f"using configured default user id: {amazonq_userid}") - amazonq_response = get_amazonq_response(userInput, amazonq_context, amazonq_userid, attachments) + creds = get_idc_iam_credentials(token) + exp = creds['Expiration'].timestamp() + creds.pop('Expiration') + # Encrypt the credentials and store them in the caching DB + encrypted_creds = \ + kms_client.encrypt(KeyId=kms_key_id, + Plaintext=bytes(json.dumps(creds).encode()))['CiphertextBlob'] + dynamo_table.put_item(Item={'jti': jti, 'ExpiresAt': int(exp), 'Credentials': encrypted_creds}) + + # Assume the qbusiness role with the IDC IAM credentials to create the qbusiness client + assumed_session = boto3.Session( + aws_access_key_id=creds['AccessKeyId'], + aws_secret_access_key=creds['SecretAccessKey'], + aws_session_token=creds['SessionToken'] + ) + + qbusiness_client = assumed_session.client("qbusiness") + amazonq_response = get_amazonq_response(userInput, amazonq_context, attachments, qbusiness_client) event = format_response(event, amazonq_response) print("Returning response: %s" % json.dumps(event)) return event diff --git a/lambdas/qna_bot_qbusiness_lambdahook/template.yml b/lambdas/qna_bot_qbusiness_lambdahook/template.yml index 82cc9e5..64dbc3f 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/template.yml +++ b/lambdas/qna_bot_qbusiness_lambdahook/template.yml @@ -10,6 +10,22 @@ Parameters: AllowedPattern: '^[a-zA-Z0-9][a-zA-Z0-9-]{35}$' Description: Amazon Q Application ID (copy from AWS console) + AmazonQRoleARN: + Type: String + Description: Amazon Q Business Role ARN to Assume (copy from AWS console) + + IDCClientId: + Type: String + Description: Amazon Q Business IDC Client ID (copy from AWS console) + + DynamoDBTableName: + Type: String + Description: DynamoDB Table Name used for caching QBusiness credentials (copy from AWS console) + + KMSKeyId: + Type: String + Description: KMS Key ID used for encrypting and decrypting QBusiness credentials (copy from AWS console) + AmazonQUserId: Type: String Default: "" @@ -81,6 +97,10 @@ Resources: Variables: AWS_DATA_PATH: /opt/model AMAZONQ_APP_ID: !Ref AmazonQAppId + AMAZONQ_ROLE_ARN: !Ref AmazonQRoleARN + DYNAMODB_CACHE_TABLE_NAME: !Ref DynamoDBTableName + KMS_KEY_ID: !Ref KMSKeyId + IDC_CLIENT_ID: !Ref IDCClientId AMAZONQ_USER_ID: !Ref AmazonQUserId AMAZONQ_REGION: !Ref AmazonQRegion AMAZONQ_ENDPOINT_URL: !Ref AmazonQEndpointUrl From 5a767433a66ca6904986b3bb9ffbae3a0b7db976 Mon Sep 17 00:00:00 2001 From: Austin Johnson Date: Mon, 8 Jul 2024 13:34:08 -0400 Subject: [PATCH 2/5] Migrate to Identity Center compatibility --- images/aud-claim.PNG | Bin 0 -> 69754 bytes images/token-issuer.PNG | Bin 0 -> 129899 bytes .../qna_bot_qbusiness_lambdahook/README.md | 36 +- .../qna_bot_qbusiness_lambdahook/template.yml | 138 +- .../model/qbusiness/2023-11-27/service-2.json | 3427 ++++++++++++++--- 5 files changed, 3021 insertions(+), 580 deletions(-) create mode 100644 images/aud-claim.PNG create mode 100644 images/token-issuer.PNG diff --git a/images/aud-claim.PNG b/images/aud-claim.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f1c991ef173f9f9260a20c740444e30a48255e0c GIT binary patch literal 69754 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 z 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

UuAye%H#$sBWp_UJqE9gWItOD}AxoxwqB{TvP z{kURMq|c~}j-yFE`Wj&Vl^7n;cQP`Yi66=I|GxQ!;k;4R)LJXlQ{=laF@i(}ChkVtnaA5ffuhk)^ft8(nH2#@B=`*f5g0?NVB= zy_{_O;dB%YaZo-oHvkgA*H8}RbM;EQN*|xSXtupSsKW1R-6S&IeVkZ#Tg>P?1CY|o z99O1*5kd_XVU)GGkAhWlY8Nsb)#<+jR7@4o zWMRwwD9x-dL?xO}%A`+utsl&J0rl>CuP}v7TmyDF47@c_2sUYi#E!H+w_Pt&zB%O) z4DGwJ1O%82qtb2(3EpI1)23`~s1}(XC{DKT6ZeZI1$#X;h!O8aM0`vjlOFq-Dxaw3 zYz{VhZwODNx>qi&-K_X|h^%n=vY%F%tZ!&ypPScI)jo^YSK%CJcKZ#i$hF(OG&`vu zm&D-dA2Pjly*wQTXelQ&uLL0kEyT7RN82Mf$^^AV<&Cq)hXyinRFQAC*@`&LWJDBl zC;jTxy&Xw;Q+i5 z)1_a^<9~>G6R*%?2{>58l4SJaJ`(eQAoImRoc=E_l0o9 zLG7fU&q+d#J$)E&aJ;-7D($JbrlvuzqwG>e8-Lc9SQWc8sP_T-rBQRri;h18sluSN z62n}A`~bediisXa%BO`rt?XGQmPN=UK_C9oF?ibUkQqXn)bgBbwIZN`MEeL3{@(#E za)VXjF@{O0(>Tn`v|13mG0A!rkvZTh*TO{XyQJ1zF_RAc8_uM7OXI0oayf(VEkCVV zCRAWpKf#ut98G+-)(y6xL;b9(m(F%3>;+pJO$1{{>5SWcI`aBgcp($sdqN@lbSQ;ZqkQ=nz1@C6nLkTbl`O)lh@20fynjbi zQ1M{Qq%tto!v?aix8H^Fcr(d?5%dU}jkq!E^-8%6=HX0cxeWXF=X(llgO(2IEBpz0sUfw@+o6CY@Z z^r#J-i1+r?JyrJjBJ6kr5$|9I9Zc?Uw4+>KCGVC+}jep)THNGp!vY zp58aV7H(NbSS=Go*_5gBIAzOfZAx6MnD}llw_Mn&yeam6&U`-I8Tz9{*?esO^7(})qzC4m7>Y@| z1iUK%%sO>%tGFBJUx#iOv+&Np)n_}0SshbGe*h{RzY_i3x02j9e1=ir|G~t*29^A~ zG=PIYlh;E~%;tBAW(H?Pj%ttMZ)0Dba;eFz9D>h?IjCh*JFt`}J1|4~L)3n<5$w@+ zY^j*yQx8B8GU5`VbbBWjZ<%ELOtKbCt%ZtSdgxLf%zoCXg};ZPSg9D*jC8k7P3`Zg zJ`6TsQfvi@XKY4E+@z;P_PJluQjz9D9Jt;HuP>v0)-7So=86_3P?wp_LzvZc9~!t85E);A);;%1!+TFNlL z+A4Z+9u>-BDXa1(SN0Yfug!W?5)dHPXFr4-|^BzVNgD_aU&v zvU(I>Sn@RkR9*h6hGQ=zv)S5Hl-ULNldd5vRPq@pF0DVuTno1eBtHwC$B)itePI9f z5~MEA*7}5_DGjsI{)a+4(b`dEgd@MD-2K?p~c z`dQMVTMrAuZC$rvX*k->%)glrQ&kt1v$UpAE--lT;x;jYR%_6W1yT$&)<5&zUT6YfX|3JIPiLaUp z1!q|Y(pj77@W(#3a)zR?AeZjcFLkg!=NwnEC74s8v^RjAzc$_sN{U`qOA=VYJGkQH zO)j)S3pS`Z2U1_1EEP^sCywcWhc-$B%6ZEd4HMH_WtE@g(DSaIX zx0z!hXQ~|gY0jlooM$xktHE&bZY*CqlUk~ha z^=iAijjdZcHE~}{cXmou0E9u4+~uBJSXDl1PKaluSF(TD)UzJn^KQSz(*`O>} z)o2=1(s9sXj#r*4dlAESnt;sfnBx%6*ObRAIMz{Re%K z7D@%hcDu@>a4fI0N+-qZ0*x+wsD)e#$SC)oO$iEc{vQb}LRV!aZDVFeQtBo3PJT!j zjaUr?SxO!uKLUdU&I#YiqKO)CEw7^eN9!Nco8_SA{!TGC^IS?M97CULWPBHz&OY4L2pzOzk|B28p2 zabsvNQW8vS^xpc3Dt;apFy`QenXnCB?kTg0MDddzPBKrb7SXT%Qg+`>=NR=cQaeqR zKafZa+5KPXdZNYBo?s=HjVTk^UlSgCbIVSEj{y)WddBLvCb@x0+-k}#0S0J4OuBT$#sZn2?`SWLvArIe1cn|MkIa z=u@HPN2KA3o%{DQQItYf(c%5Ds7H;niNSC$?6^uU?PoGYB&<}@DP#4f-KulwXtpP| zx$PREBu!TEcc7vR-vC88X-QunDkt)lpmoSgEwnOZhE1idcUVeeuda}ftcrmZI zojM)UBYVFzRI~us{NR3%Cp3f95mBwyRmU zj(bG*LAz_lMLlk-}>2H`K7$CxM*zh0HJ%pK1JASP@bLf$$$wAtK0;^>Q66c<4V22X8rRF z)}6Xf`cp=m!moRgw(emWVXLrj>6hfXknOMcTaAWP$44luJiW6Dre43#*m0Z=Kabe7 z7g}Ut_P(w2BlGr?44Lm=D0CE$k>;0f0_Bb$2HTD%LExk=f}t$1gik8jf3&xnWjhnE zf5lqwamd{V)){B;fqkrt<)+1xXq9j02x-@>H#hMGtJAt7G*}3&-zd%Y;H%s*EW`yRjFZ76th5+CSFRbT~PnV;B@v z6IHz#Y)5=r9f+yHfOhm#LiBUqdM&_W>rDXLj^%MyBTl+@loYSFdIem4_*+AHNV%lR ztFZNNP0c~_%ena_BSw8}w|4J++Ae=}IjyJqHKc@#&O)t&z((voOXKbu*bIOh>R$4N zEtL6Q*Eyt!M&`~OcJU{We|wTOLh-($&JsqBA1($A?G`rA`+R+K?&t$^(nlE@o$ z?!&Sv)03sigU1W4?ujC@7KDs9x73}zZHxHzYpfyx!)x3asitw`06wuAeKSbJI*@wD zrv=LP3Ut53M~%v0U+7pNjtKbqRRnvJ2PA9yc}<#J${y%j@F~g<^@j6K{Ev=j&N`=? z266733bI)PMG;UQL7CY>9}bjG*Cffc1ZsUkWq&xn>?~Ge zkj}}$@%W@7ww%^?TC3rhrc>J~S3fclL{*jaUjZSq%RAP!>Ku zhvg;MVO~+3Og~UK_mt@Q5L{Vbe_TK&^OwQqBT|OV)?%szWqxfs7Xof?ssznvPd1<*MYfxyr zU>H%7DeIcQoih^H#ivwSBGWvz@qr<;M(1JAALI!pl_@OuS_5*9sU2w9MQoJVW-1$9 zD2FBt5`5St6jz?Q^7L~CD0jiKlI;yeKZQORFg}6c*Bgrx1m?AKTlVi9hoA&)`b&^?lnQ)S=sU_)fC8%5m z0vKQua@xCku!ReSi^dx;&M@kv$nBxb_d}WMgl9YV1-B1tLLU*BKssy>E0XauJN(-o z)ZE`eM90U+WPhNw)<@R4jFZZ4A)|Sqy8RD1SS2u9^6mG&+fV1b!$&uQ3)~ zsIL7(MbwIoV9&6euk)LP-D3P?*-^JCi;H#(S-VL?Y7%bMV>TG=2Afz|ir;=J@N}8l)@t?HU1Nd5- zvf=RYo&IghYR9H}IVSR|mGg2AgZWK9t!RZbfLe*ACQ1f;TQV$G=W8vVG`&-Ul4~f7 zh&FUJX-F67%~H_!sP-Q%BJzz+HaDK#_8OB_duCJ)*|lFpV;iZiJk>kYgvFT%JI2n; zlxe%p&;UZ*!1jp>`M@jAzuw0T`-8UiL(l>X-crBiPZG|Zv({uC^~GG(WrjCAET7C< zgzG_>qrFSg9@ zJERgtxwlIkf+&-t)Xg;l~SE*|cyK~w|kq&F`W`!dm%Tk5eztt|$A90JP) zZ~o))&OzPkh88TAwGZW)Xv=y{hS#}+eqmL)>XvedTca2pd@hVbW%qa2%2GJZBqbry z*`$?ls*-K5PT$NS;?XB~qS3?R+fF&sD-Eym@i=%u7dLWeKOnPm0@%{0#3QP7>1UuD z9N5#hJ#t2rEi^~J{cuGTne+uAGw6jdZ>N@+nDeOE8p)FzHv7H7IRVncTQl#3Eo<|0 zLoYU~rv(ZLhFxif%w%u4mR7dxazt~mh|9*FKk;A7pTbr542P$hh-IHbBF7__lk5? zNDZlOpX)wedSUnVP6Pw#h(w64)DLS0(OuxFR*a7B{7fupFRd)u{x8qsFe zi59t(b1Klg&N$F|r^Mjog1FYu=F~;_6t=%tKYEMQJ(fw|3sF&#=}TzYn?gO5#Gs~8 z{lW;3pYz6KlK|FT2EKXyCe305qTGuqMW{CP!p57;Q8C%F9%{Tw1|u?T!ivjhJ~k^1 zHGL2{ioixF6Lcv8bVNN+85TbvO-6W{=>hH{^Mz&-WjuI`3cyT zK73nsw*Hp!XvMZZ`UP;oGVwpx%+>%1k8E2aya&d*}6~Bv3S?qi(AcG zzS+0~B-BFy?rXQ{R{{S4^nXnEAt|eD{?u`{M3tWqMQ2o7Ev~#)p)G28Au#H}Q;;Wq z7C1rL!MkA`_UgPdt)vvQ+LmyKJx3q;-ddr9z*swLEYxidDOvi$?!BE^MubSN;IE{W zXyAm{S9^zg>B5;iO=FOhQr1bjyMM3W_;Sb4Bh6<_Ih~W&3Rd46$##bmmPwiJJYOBr zO`6x35cn67c;2yi0T{j@(Uz~sDwJQiz7F^a0RG_3xl^lpOXmCb=El{`GNz4uNf|I) zY$AQOwFUU4=rAbnL%Xuxvy+2Wh!T#V5L#oQ3FPX0e2mjFmv~i6L9Ei2L5x zC-QhkVqdb`wAuQQ=&j8^LMqaS&%9Q`5CWITvpUybA8Db2vbEuy4GXP|{bpWHkHX1V z?h;*jR>;Z|*7eEP3!qy&zvv>?iZ*kogt3X9xLOCh zHt)9K#TH^xUNX?YeIc9832f(l5S|SDmRU59P7}`m!E#vIgcM;f%*9Li|d zAxNE!9qGDPo?x?24JKh+X4E@vtL6m&s;)lAwhCUE(=s8HB3Mx)3$g9dNO=adT24M} zrpk)4o|mru6F`b;-b%9N=kE3z6MOLyBR-rpXVXsmzAh-Y2w&)}8TQ>xk4+5NFwJCD z6MQk$E%ohGd&hQQOEuoZjb(G}HlHejyDjOP9aW)=2X>>| z--d1lHOqX~Fd0nxmWCF2ZK>OYQna-ocCcQ6JJ+Sk(_6}=^%c{O8oIVmb7Lj53zD@k ztBC>@xL>_?P|4xUr5n=GP2Z1{!PDlkxS=!gvPbi_yp;n~*H+2#t{VLsMd}Hg=?8;Yo*X67hKq7}f zaAfC%dPJ7ap`>c~snAPQ(iC6i<3XnFNG8{r5gW#W5`k=hZciLZIC6VcN$37nJjoev1D&Lf*!;sOFw$`%aGSR>Y2 zS05~7nQ82pIpVqXbHiVURX^m8H9#x9Ai>*{mF><1dc(gwVh!7p*siT;YCvZcu#~s% zz5#lh|88tQ^b&V%!qh>0MvAB3>m4>Euux@;e}6BSyveH4h1t>k{nY_ef)~K}Irf+J zSXPhK5txjsHd}d_{6Nog(SiJHa|;kOyu3Shja!neGvevd(wv~?q6W_z^lyN$xW1i?! z5w>tf<-v$z2|-Fv(w5sOTYp8J9&x({89LmBJ-yuEbc^-CeN$Kb6jg{8 ztQ){vm?c~C5?G(6Rt~wpW?$l57ctU&x%eB+>BB(1h>&sQb_Ri}#*OPWtVCHR@>p2b zz&7p} z(-pNXdQ<=20!_#UI9Z({rd#46U6w^}1~Vdc_q4D3wK|WmD`!REqrqJ8h>nxuu%*BWzyJvzOjEUv3D5Xt9IHnRD;DIdHGimTXK#5 zX=QZp=ErT&0}3@{hY*|4^JEWxi(QYFJSBqbjx3#(Ht|qneW5sdLv5$4x0h>?y1L4W z9eHFxwlvLFJmC+%NEnCC%=q$ zZH0O#ayxtP8kerJ@^RlO_5H~1o550imm+M!!w^39oul{MjHvZ&hAcni=dZCZY(=6V z;D_qq3>e5-f2#m;81(_^%=0?$T3{c)_4kv73_ zsF}IR71)tN^XSjERu{B^eM3eu59N;$I9n{g)@Nc*a4m zHG7rCd%j?Eg6j8jd0_%aE;`{~dLzBi3x)Z(G7XK06Mvepm4Qk1qFQ7{}Htnk& zX74@9-}EWJ;cJ9lw_b%EJ7y;&_zvM4<9hYxnZMom_j)68{^;1PuI69v{O5Z7?%soo z|C2a&>`KD-2mhOT{^&&K|E4a_oW1z}(t{OxpSzYZ{R-M+h~QvXA=!7c(ww-UdG~?6 zkJ$8$qm?uHckVt?G4NMX^1q#U_pupBD)!6&5DUN?^2{X~5%qY+nw_e)m0QT2L|8PS|~1Hawgo^_TkCa{;3rIcIyL8~+Z%JGIO&J0tsDqGVVRGAH>m zV(`cV)KZTs1&wr47fIKcXxt}9QxxK;i@e$+y?a=M&bZLYzBU8FEOPGr~=;LkB zTS|v>BKbXDhcmB5=h1_XR*P!zH*s0@>_szs z{X<)rzWa1-)deP+APKulMNh z8{D7`2-|}A&iNFyNux9jyC=#7&U31UW>YwK8YP-sDkWMDC0Iee$uHu=2kF=4KDrSd zT+WX&ty-Sg4OkQddI%HDfd{9({+9dqx_rq$cx{MSleSc25tpoSL1qDqbVa1RAS}oE zq)q^W?oZSscTHsJVA^s^p=jMsG+&*dnq5mUQP>O8+-6m82&Rz(imKacoM0o-_V*ry zrKcA)Ofz2>QEu(9eS|EF>(U=tjC^s$F$XF+ef9u(7yeW4v19KgU$?cFrJ~qc(boKFWqRS3ayO72={VVtz?h zXZtzCdhz52RSaFc_M7R6+{`hMu(0&(PFqpUZL%&KUnpMxB=fHf9tlzB;3-+x0+pl&sLr06 zMZm1pn$k08n~1SOMHp%gNXdZV4i-Qgbq#VJl&7v|J09CN-pFwIW*0$pa{Z-vOx7b0 z?2UZk^nq>cqnTal@dL(@46ds*Sm)mu$Wk=wJ+vKoC`vwmW14}`-}bXi4dVUBFs|ER zc$yn-si>{r{y=-?>eK##{_3~78yg$d9NOgP`kI0wbbsZ@YtE%w_T3oKW&6lmh{+8# zN5|JUyP}rhu9TqzGoV4Xj8}2r-X!~v1T}%~!-)Fgi=9d{&`(u3$dp#G6M1V5_>uaNiif=50kn3ias|P=`ZO_e}rj3Ep*B+u)~K1>EFq z+crC-sgY`?LvRtnYC1QJA1zWL1X?KMn4~`U9R*L#ZizxhB(+w3vt_Q|xQj8CWjMlp_t-*;jdlFY^45x3&q-TAuE&?K7!`NS zR=z~o^fYll6CEV#G>FRF#cE`3 z0b*4%>Rw(jb9Q4M7P*hr7v91I=$bZqS4?Z$mLkQK%DnPZsfa3zTfV>QS^kVQ9t3Vl&U!TJNCyerH1{jAo5?$ro_CcG7^FleFp4B9_v92kA=dQw_xqF`G-2Q2IxKv*Gl;^B$$S+ zzjyIb){4nVFf~r7+eb8~GCL7z%b2_%EiF%qEXmW0woq2*_$0Q?woVtvCTom8$V$m= zeoEeey#SlQr?IvXhjXd9Ax#?22qdm;Hr?8a+R+0S>S_PLBoY772SeC%WWRW zw*5a`khEqiDI08QV2(3p=cUQww@1KOaY>(3)zkc^bE9uH*OSWDmIo4zwidqFjW!!` z)X812bt7}|S>T9j&=oQ#wJy+zhkw5UX_hGCv(~S3|{`&Wzz*Nh{KW2<$~9^YF-2TA;;B%5(V)XA76?^=Q>xKr9v2 z=UVXoZcfgy%)AFwT0^g_%vmINZ)hxI5OA+H3^o;(1Aq6&^zo5-@|Zu$;>D3=@_5&e zr~#*wcMe(w~~f5NWk`LEo%jOu*Ei!b`h@SDn&G0B5l4RIb$g$Pl5>uc`PJM|Ea3fr)4FE3o%2(Ri|Hf1H${R1*%3Vo$$$QZ&+~qfxfmAS#Ye@}{2hi{ zSHM?oObSN0mt$1|%2Y_($#at;sh*HRfyKdkOP;_Lq}|@ECiuIWdC{PTc%^&mbFCLn zMJ+i+-37wiEW{rtCD`m7)-b#IjQpZ~1t~`$-JkNGaH!^A_6=DfHs+)U^xdFhlr*Mv z*b9AIyYvgjJ?lcfC|%tNuINnBMYG&EnF{m54p2gCSMLti7yn5KOq0#b`Lu55@T^VK z5vYQGdZne6h?db-6sIuvUW7{Lh8~6suZzt(D4=X+{GO&hq(cE+yl#doDwd~5rVTF*6PDyVxCO8jFRjj;25(aKE46-}`(f8@JK zL=40fIS=Kenz6tne08W6t*(yj;uTK!3hZ1*7AFrmZbGH-`CLWbtmM9NQ9j6uK0IkO zh1F*pp+j4HO;fM7ibg9Hra)Udcde^Gbv!3qWL2wb^(G5d7yL}rp2MNTJ0XO-rhDcY zQ@~4R4L_q1h@$GMPadvz!fnr~D4`0e)`+F&_Gr7n*&%K$Le2nrw~v7M!`mKTY|Np> zU8p*0irlf$)~%0I*(CHiHhoEIYcnefG~fP;K`gqjo?K)BBf!Q(H|6QeK488m^gL}> zF})|tAb!5OFSWN2RoNwZCu8-ifuyyIEoFuXkI=EaQQ85n0;z8%Ij&A`^k~WWPEA>X zA*=7CS92>7{p1LJ8zF3aTnys0dxZUfifTflNPERK=TNO}gWP8f=adL0{Q1qPAQmRm(^ZO3;uF9`> z;1&aHI?6@o0lhjk^NC%`X2)W#qv(3?dCT?Y=ruWt|I-Tjh&h0(s}>MCPL@> zm=R3tb^^^@CAaTk_;Vp^$m6o~uJzeUa0qFaP>iETp8@z4FW8G8=!jFv)3(sr328fl zZD@jH@3#=z3UeS%nXkZGK(##GU(FTFt?Re`%4d2|4+*_&PCV6hrY}kRrC?yY@l_-0bJl9psB3R(v_dXukx}1EV6n9=$i{JxT2JqsQnBMgjQWf>%zL!^2jYGL zuW!@WUew*`9NFp6Ofu?JPbv_kZIhA$<)_V%nKMHaTaia-6-W8T6;0=o=n%)%mSod8 zsV_xYmE1aVeCpT{}Ho3wp%JGRF>RgzWO+~T(2R>b zZUoc6JBg04O@c;7@3yq@I3sLd3{`eOcj>p$ZqEG5Nqi}AfAbyl5%0}7LrKg}S$XTJ zsf6^4c{m~y|HhLk#clZ}t|-yv&#&_l4UKXyb)~hRc`dR1lIFVtCz3PVE{4bcTmlqW z?ezA@{zu3!%#Y%Dv|_qP?v1r?tyhAisYxhPQjCt=y`bZkcI&9PH0gq1K+$y=D3Q@G z6Z)JG;;TcEPk#*Qosy+bh!RF{alRa=&At{A2 z&^R1=K5ng?hOw?6U(Dz{grF}moBW{YK+%Vas^C;_JN4tQ(M#&FAuWiqgmBCC^9e z^UhS8Ng!+JgH8B!ho(0FFvvDzUuLRym2cIB zeix5oU!sf!^{0H@4#y=GMw8ELk>yul)dAzQFc7r=LYtXerzix=s z=PTO(oh$*0&8nR5*s7u)U2+#MUwG^kd-AfPS88X3pmvA=oINDb?mA9-g5SjO&XrD~ zbBh~TwZv&*Kc^V=DD5<7Vr7|!Yk}7?aufWNQnH6y=!3djP!t-*bu9d(jx1i7^)ZoW zI@237g6nq`Shu-CMEaLZ2J~j&!XAXw;Q9LcPI zV`Jl^gG+F$4|2J&L9vlNY^{yvakX0g`!2e*y>P=fkDWDGCn$ zTYT^?#e?;300u=p%G#xss8|rRPSSGj<0Mu$N_}K=YN8(Rj=L^$#Pjc!7M~xk<>xnY z-E%CMrZ{IP1Z@d6Mi6QrrVA7KB}uuCA~#vj?RXY0=votM#@9z&p1~3#?-;Oo3UWOh z%1cTI7wA5#n=TN!4#C97X5I8{xn1XRS6Wi^0}3hxP1qdmb&x{Ip=iVo!>Km2ghMm! zREQ117@kj%`RaSjNFL+;Z032qaKQ_ma=XVoeRV0t3M0#AqPb`2E5~3Lt{-_ngfYS- znkAhl}DV%zaRW^FM^y&P76?NgoL!{{tDVTqBk@Nt+Tarbw!o)iAl zV{`}6&{2`AE^CDzlAUP#bHK+$lBv=V6VN9`OAFYu9E^TjF`KK9vmS1hTF=5Zv7p)~ zwcRpga>)yqBcEC!MOjbV3|8stC=KeBu4&zVk9kpg!F>C1sNYZHbpif&C<_n~8-}8; z2+qVOC$!6EELd5Pj6Sv0T?f0z6IY?U^A}BA8b;DHwbsV+B8Rr=$$x__1qFEkwB-)G zRL(8=i0)~vJSQLp%w{RZ6AZwG;MQPs9k`2wa;UUWceRGONvr>Dgl*g3_q+|lean-U);CK-s?>SJXP zqdRIkW8&4r1~V&1J9^*ntIVzG8At}2fGosUUF#Z8T2A>@4B50e$v&x*98(|SNIrqj%^kUsw^{dcL3t+9Enmn^d>gj05231KmdtnK#)baaWlXuS zSbzBag)UHHc=9q<-Q2Z5SYEOrzlW_8zug6_k39ZLu6rywmi=dO?*hoeAG1zx(_4l8 zv&UTMYlT7#e#5s%UO7WA_nMvM!QaiQW9og^@GMNWLaCfT8o#*brxPxn;A2uOnnn}S zHfQ1?xtwoYxbxO@&=7M@Nwy@&Fzvbg@?FwpPc?QD5>`*telAI0G{5vU zwzGYiwfDYAGjYdbkbcXzeEtv%g|A9ONK*^<2M*WSwwKoTw-_+=#sYx?=f)MlKCk0I z(8YZK(jJ;d|D<^IgPK81RjsyA86Q?_DB1a(h*{;$vyX-qchs~30%79UQWsc9VQDF! z05Gl$griK$M{bgX_SP%JuStsH%>)njpM3M`D4%o!k^SSy=90Uus~|FTK74bB7>xm7 z3ToG#<}@8d9>I{`iq2?4EuBU;di`wU>K)9C=GX4UiN_0}ticxU+oP*1;z6Dt;HFQD zFL#~H36f)sO|pgrOX=Q6jl*)%rfvO?D$7$o(*EQWy24wylWXrUWwjW@oFPRO;K~x} z=%{j(l@48L6oOKl zyeO1v0e`lRO3nGoQ=i?<)6pH)1WfG3$LOWv5YP5ImhIz6gsJR+le_dW%Nq;}XWwu$ z!yl%rCLa&uaf`ORcywAP~(=s>V+1Wa^%uCFYg+A{gp2u|>;iMf4E3@N; zMsQ^$WsM%XvF?;^-2>gDOeXNkTGIf~e2+Ku3~fiDamdysP0EV9)UQt~^ty>~69o z0X0cW;U|bfnj)V9vey+jB)Rt0ynaa3c7N?-s=XvULhZDS z_8grPXZCX?D#K0A<*iB!54Rg#WpMbug=eLM1|7@>i~6}yrn~WVi>U#!o=i^bTXilcAeA{m$@9#j}t2ewqREoy(qkWs;yzXcIu8hlgJoI-*nF zKA(x)ICXr!a@l5eg?W9p^AM3`^wX!@@AR047q#e!XYiC+C)IVOt6wn`HYgQmDcR>t z=IhkbdXkO^f9SBDuD10ed4aFAc-E5cxo;x^K0g&-H%s#Cziw*Tfb-zk46LX}UurS` z&@j#(qPHwDl12XH^b()w0K1F|Z;#;Ktkr_kT)L=l`Bev+^SA+QaNk;1=lp}U^Zh~w zMZ>kBc+957afLD6!ED6|z|8|lk?R0*O4xmU*k8^jUYzB@cDrNM`pYuAfI>=9L!Lq1 ztRX7i*?|9Uy@jvW=82A)5qVdKjF!&jf*<0YWl;1;^{BEFt=b;$m6rRMh?Uzu0YuP! zl4ACS;3b1)@ExoqP|HnCkuOtLf~p96 z@>njDPs;PgYkLCec;oQeYR~T;)hi2ZF*L7S8a+FpPU1VeGe~`L9IM1=+GZxB!BbqN zKeiKKJDM}El(9eXHxx(fs!bxsqpMX}+-Guvojoebc`EHm>Zl?vl!kns_3}_u!&iaM z@63*Y9{7><0XYqdXhl3qjg9!DOO0Y-9%p2yh)h9klEfr4h>h!2#v?b;3v1iR^!}PS zJ9gRmUEeOz53Ro>fT8#7>*hu_wR_gp!Dl#TqtRWS!H%!g$D0CbB zC3v&rXjG6OJ%-|SnX z4`EaWL+#?Hd8njxmSyQ#Y903tD1Y?{iqPA#b9_Oo-r5+1ug$ zSimQ>4c2$7C9F$;bksL+sdZzq>X7?eaToM=15Dn@*pN7}X|)eY(<$Q)=LfgZ^{RrI z?jYao&NMMoYT%Hyvw@?0Jcz;(@KYY)mKt5;>3QsQd!J<-TyQA{u{bAOmnJlm-IZJr zjoCC7=hNw%mDV@1pUNB*)$UEkHQ;Z=T;Ssou2|`oFfgcj<>R?%AJ`=gt>ejQLO3qS z%@1iKMPI{mV<3s!=&AZmh*5Z07#hq;; z22`oJY-Y~_&j+H9HbeRRYo*jAQZ;1!Y-H zP_J^AgiLzM4u+!swp`@-lYhDeZ6ODaHI5Ys?e8rd_v(Q{@=6(h{%_MR8$`C#Oqrpr^m^rz{cPuRiwo}f(vU0WCQD#die3rF` zJms_I)^cOEacr7@M|*iF(weh6%g6oIzkGmOq(Ia^{G{lJSbd6en z1xWpEGTS@}p4LN*ZpiLV_bX)G;`9pxFEf ztlbkUt?s&HG|i=w9KA5b9upQ1EOivt5%8ED}*f)ULYcz@}ePHn2v`q|S3Qcd= zb}CR&lr-k$@9d38U%SDV4?sxZ@0a8Ag&mqI^^Aw;zT?1{^jLJW#0tC z6o#&SwRO7g0i4iy7rKa#zhQJ|NPn2+1)$JM#$xNY=RVp*eOxJ%n21T*dSM$MrBIb0 zch*>ap{)lhC@$HV{r0=6L6KjDq6!<`_8s!h_oP=kjJ;R+v;jQS{%b!{&avllKvd-j z_-sX$k>c0wKe$_32PvE)a!(Qcv;=|1;w&rHKG1tPL%jxJurE9LF2v8Tp86v==W9|O zt*$eybY)^(M-!%y!Cv-hDKw&n@_Q);J3rt`|In@NuqbF>OUD1gVl>8;G`VG8xmxLthPT<##m0 zo9K)zMwpK;Gn$LsTk1Hc`d#w}&OQrs7$05VDGN+rITfv+)kBq-Sa&t)W7_VWeLzjt zR#=YtUj5b%C7`Ys=O+!G*6`9ItIP}+uptq7D$m_E;zA&=<8ndRA$1Yo#iuHseL_igB7ywG)S>|dru{@bS(#)8kx&G$5b3mjs^M5lrh zR$ez@lclOc9F??MN9=MtaDWjQ8r;Squ_Q+HL(k(2i?z1yQUX`r5-IJY6tof>jYK;A z7O5Lix}{Hf7LF@k)xrprHb3jswU-5UaU_hRku_&*|&tmwHA+W=hGW3UlE+@;_`4lc8|j16g; zS8d{KkY(WG_|xGwWO&8C5@L)=sc7%*(J`@KZ1AdE3L}TP+96tRWAQZw^J8GMUQpZK zyA0DAW4mP7RM^?)0Kl5XGUb?NS8p0!6AytPLip1+zE2YJwsH$+QPci|#j~ZNn&P;? zA9;-y_!`;GA3D2}nH<(R`Hof!b(0MXWFAlC-t1R7=j^xLZa5oog5yY&QeBEiLYs6OFhh-y?m((z7Z5D%q*xR2kg z?^OZHVs5B&Z&*{2q5sap!$^K3k(4^bU>A z_Z~f={Ikm;AwxKB&tAPc3OQMFX=S$)e&WLYYt}6w89!6ZDT$1|V_u4o80 zh>LB&mT6(fUd_c(ik`|3)?EJrYaPwX(M?V;#y2tJU+lW0=HYf)9uA}B3q!?Pm!x}n ze0E1RkLJ)z`$>?Vyv$T%KCI@Da@nE4t)SfcG(bHVjgS%?ryt zv|0r574(zTWOGeflcQDc&V9Xhqtr-=R=4A0@yz&94q+cky!+K&odftgb^BGPS8Ju7 z{*!tRX~@qAWry6*#i+$6aX%EuC4DSN?0|Vz@R?MF7@fKKkX0?nPea8vEl*g$rp_Eh#zBb8A0W2AQ%K{~~ZPyj;5XxaKg|L^$EF6+o_oGwmmM z$r}z$8bB2t@ZwJJ04%p3wFati9kYbAOf5z5orB6TaIyo0wAfH${Q(v1@0<|kQvLaA zCp+J-PNjU6^_YDx4p2*h8b1}^r~P?}+deh;n_0$lxH)bXSV-^)^Hy@#mZU00XB+nO zKq4-WCzTZo9!V}Mv2JV0jrdg!9iST4X>S@PndDQin8frHH;6~tY< z7)a$-9c1xF^l)>447&aM96%HlpDehuGabwBLx~ZMtFsI8nk465IAA1Rc1jXM2ohjo zNWpoSSTQOWDDg|K)2|Y(Ji~5kW9&Lj3j)yLM=~-m$HqG-&zWHpD?i`3<@@m<(aU$X zuxKgCw^uWx<^!GO7a45q+rN`56QBo$+?~u2bU4WH;F5P0_VIwL_v@!O zNB>V|ss0Zl)c%*Ms@5dA$NR|s>gJ6Wc^2T?8_@r&-qyu=5Kq-P6uu{#rD zGAF-Jmy^s^lEu#+mNj(^NSNSQ>ia300eC$bO!Ay+qm5+Dmb+c7^93bzs`0N=05CQM}P*#UhFKdjGmca!V z+#n_oWJOSh*CXQvZPLYu%0M=z%k*m$a+Vs0xE~OvX5|7=&MQsqtgID~sZ7(kiz?p+ z8=ibHmZgj2tDBC=)pA&Wbh(J&cU>qvWHOQ)x{hCAt~ItMX~ADs*oFM+=9lNnoLjZ& zQ{)hj#vJLRy+rYaXHz>>#3YTQvWZy^%@o|XSWZ@%tZV^E2j;AShlP$8rXmU-eHlr% z|1lhQ!I{Im^1ex4#3m5lWQoO=ne#Y9M$0o{HlGuxdB05B@0xfutLXcsj9d7diGh=@ zuAI{qRgp*5t0}q4>4a*Rt5(`>PitAeRXymH`#NnYZ`+1brcQ6VE;1=XcA@PlncvF& zcdu#vCFBwOsh1|oOY4Ta&XxDKl8B+k>z&D4EgTJ07VyWg2XpAq5h$u>oEEy(qaF@b zT{Zf|d`0B1jN{h{>uVy3NQfqoy#$EFLd7NiZO&2KB4ElhmxUKA9a z-D+GnCtedCjLW)CiNa%#q{7vaoJCh$v*W!FSKJuQ|A9Px9kZH^#E>rZ%N;-4{j;0L z;a(N$rE$Z!ZE4+i+f&!PNmL21jdK>0a@TF*DbuBbL%N?F7Cq3Uj)_-Yh$9Qgn^>uN ziEpN98d~CN;bHv_s=;=FyB{n!3Th&ACudS@OX{RkYwC3{SlnOWx@8RnjR4Da=&Q3L zr3O%P0WZv9yZD(blhx0Ui)kfw;m75(Z>NI=iXWIIm?dzLyoP+H6@SoE@7s#f|BBx6 zECHvn5$R#MIoo-r0k`@qBjrifTE4g#SV?ayDCD5iujD|B#aUTBW5p*iTeK`s7p8Ts zw|~X#M|YGzgf|WhFznjBa}P0hhj(~RS+H(ZhNp=<^1$e!!=D5?pSr0$2yY4llc5b^*J4`w= zkv=f#hmQ&yyf3aG8DGgZq~0~!)b?HhfYCbs|Y6B6q9MpY(&xf2fA_HSLgYZ*Et9j(i`_AsU8s4t4$ofUK$m%|S6m-jf z=}k+=cTbhS2B}uKM8K0%jNmAL^H}ctjkyza8ZQO@w!Y7H<%ER?P5|UAPaOp}*wD$9 zL7wzklG(=(lq7KDv@*xuQufEUvTz4s-%Gwd%|))T+^B%Rloa@74z|q9B5XIpa~;tS zQqm7PPLrIX&8%X@(K>%akVIcDrl)8Z>w)ZlETt? zg|RpOl9>Ml3W@9u905W(ou#>O&&o%pTXE*yG>)UZ7);2OZp{@S2o^oyPl0DP2a~@4 z*(|XW)$U=JJT5(O)T#AqBzx);>2xk)X>pq0ApU4?U~nqJc$x|Xkl7WYyezPBk1vyN zf0jU&E3Boys-SQ4#5((!@j*U+^~Yx+;;yZ7JLt zmpU^$8xW|M8DBIqxvD|C#0lqSvvkk`_jrF&@CB#vo%QT%{&?Faje6^@;CA-It{qBG zM)vq7n}D{zOFdS5o*!LhPP%U~M97jDaWN~b^%=RX&*Q&Z)sP~gUp+v*VK`*Yv+VIp zC#nHx5_pQXLN|G|8qhf8w!?@NEC6(}+YM=K(@M8_d*V4++58DY4UxD@PS$R&S0B@! zcofY@pQ1HStCQ(~W(WZUy#f&Q*>4YXN!pXrTPY&Qmu|@-bA<2Qw*Cq_8d4y-!nM;i z+DCk^1A+KbK5mU<^HV%RVoy~*-GzO`UIG=Ya8=h+K1yPVPWo_1S~}PT_tMg$H_Mle zR=c5oX3p}_(#hVnujLhA&dNylyac(F{h_YsRj#^>M)rP=TD#Wv5dFP%B^9oxQ=2g1 zbY@2*@Vacey-ier%zL> zB172xyy6~Jm;rXcuS>~$ciHxN@TFeLS1Z4GeXX*m6>R}!{pMLCiiN?!yWsiw!usja zZP_!J6*&;XcNMK2)alV;PS8q&jX0=p4h#NF^@<~-W$qz9A?opB_kxD0H#RIC+X9CU z7MgQcgB9HpK4n=jo!$eMcYt*5gc?muOL-D4uBpW=zW8UBO+=KZPmu6Uvewa}+Hv%Z ze@SowAF!sJ2PB&dkZiG@>1&|IF9I~hcCL&_y?&S5+JQjGFxv7p$Q`p(pJ2ciBlT1O zM?(B{d33Nu1P^d{R~4;F1L~_=t=N;pMoCmmtQyB&0V)}}iMhiwIptW5Ge`P#8$YOK@2^irc{_r3aA<~i$ZIQ z?zijm)1=&^S~0I(n0LjM&8v3ppvnx9&fvn}$z<=z3e$0nc99Yz2>xE2+H2s+nXAo8_~f_z5Z%zI4aGF}}DW zmPKoOn20riq2gC=3-=C@&N%prNqF`?wvccuaS3oM;`Uy;Vj*k)hOY>!P<$rY0NwLr zPLAo~mpmgaNu2|4l@m8`r^g)NDNgIjxyRE3#w1bh(x4YZf@-QNY_c&F|#<%A~^~P~owKr`RI(yQQWT zVOHj3I736ZZ?t!`v(`JkJ>L$Hx1UF#_Dzu!!9|a-+#q#k<3x@oJ@xt}zBASF{u^BW zalIW$*-|N9ITQ)bXUSWf6PgF-v=iP;MBflNdlSV3KA36^aT>VXf931Pi^X2ruF8iuwF`~E>cokdvJJE0FLe3BKSkfBOfGkO z7Hxqd9I>wLtE4~RFMYP0eb&+%=4^z0)5Et5U5gw&A|3kfr=<@N9xkfG(}_SNf>+|e zzyjhhnUs5s(m?Y8=M7j$TR|r!Km$ePK55gdg}UWdzB(FmOaw-qFT=@hAV9s+(dkhK z>%vouEuB*Wem7xa2?z)pn?$zDX7(85l6J7qciF&$U!>i|CYNhEFs2?7O%f_vHm4dr z_BSr^{*dNv^MR@s>$9eyrIm8U)o3%yeCLioD`j;?E6|cxQO%$Q>9 z_tep)0LptBC`nS+UO4j}8*Of}Xku%9b)zu9Z3$vo_*f@Os;H_3zxsT?7Z_f*N!*@w z3I1`5p0JAg%r1Lg!enoLyD&~XdsKh*oACPl2Wfo?Ux$MDL=oG%7L0^(5dZdzn%%!@ zr9Yq><1QE{>;Ul>p5v4_(x;IYTyS$2`C^$fhZyc6#>~h|S8qi$BOjCGuA@%zE`#$5 zqv4WSsI<&9ZHyNd@5h5xn?WQ3hk!GE$_b+x;p712@<8{@2<_XQSlOflco6a_Kr!4EyjxCuI6Ih`PEej47-x?rI|SdFo&|9A zi^XG1!&4FRuRZFF_Zo`LpFJ+Wtg4Z#)05b3LwiSR3Cwn|%7HX<&jh!Bc;Py}9sS6` z+S7(#RDVc>Ux1S<>(JiC{Ci|LeZSX0&Wu3TR|RjGL_>{{wW zFTw$?aX-xgvJ@n3_2bKoYN2OgeCGhKh7-k?);-@Wk>{I2S>KVeMt~~8eVJ8a zVHKe!(LkV%z!6S(CfrDW9~|x#Ku(=a--nv4eq-_H!rEEXG`H&B+Q@7CJ|QsYD_UYvY34M`^Px z;9}8x*8An${oo=9N1J`J?BVWmJcKHAtcFt1m!9ByemaTPeSb^U`;||iE03Qwh{p97Q zKQAgY?FT!+{rd5fcl$|6`r5 zL-bN*J!gSWQ{54UH;n%d{LHbKrUYP9$_?p0P-yUdB>@rUf)M_1z=(x;TSNic952hd zIsg~7NisxvjGgbwZaGlNe+}#d8OZ67m(HN)m3DL$dTde-0^{7DChxnr9C=CFFgeRS zUkL?(F1>mHx?0^D0!n)gs5SyEF*HC&@x9K_#5KjipehSFou$urd8a#K&}Xc2Jx(kz zKVZ1R6ktVqev=J_b*?5qn-&)bB4_|fn*@AnSQ#B+qYlqUTg-`PC z-FMeq|1YT)2Fv?*M~l>K@Scb3@Yd7a70-B4qw=o5Gh2H5pFW~f_ z3~4v1P?qBTqU+MXvS46P=LLL0WTA7jt7^b_>wvt-&w~$x8yu&{rvI6bK;%9JpIBC_ zEq|wx{bNH)`2guu$~qJ)hy6#5GUSd1JL*x~QTf`bvR->bXA}j!*Y2Yf&+W@#a8g1N z|L=kg-vBv^N&1Rz+US74;j>p`buep%rVjhU4cGw0MIomSlg@=gQ8(TCVK1eE_W z1Pm7%EWkdqCkNs)KV6++9;EO4x@b-y1)UPT6TN?T(p}qsOlmepVWoQlA_li^>R1%A zTZz6mS@D%{>>1d_`04~Cb!kz%b93Ef7~c}H4nWy=6^a=T0p^>x|1mr3fY=lIHXFBY zzanN~s>)mB*z=(_ng zYtH+A(RjqZV=smstRRj{bnu4%UPfNt?T(dzaAA3YCa`3E2W$wR(dQY)qMo05$;Hqm=^5`35Fkme%Ji>TZ7TECq^*P6($%*?S-hA(ys4aa~ zfR%;YE%;yefQ?NeQ6@JO931qX>9n+yt`*?7|F`kzAkFWG8H1B0T=Iy%YybPaf!or~ zMZ*@}oxc$5gQwpdXKs~P?r_tEe;Z$QoKDG^>qnsgSJpMM(2u66J%dsAK+3P+4F}0z zHj7RX_U2MtFb2)XyE_wqupXyej55v&rqKv%kH81e)UTRzTJi-rj3+b$lre1TW=gaM8H2X1*wOeuxLY3!A zsm?OPC6?8ht4~W?vtE>vO&_py3>e7fs`dW20!{f8fKb$Ymh4eYBDaR?9c)s4o~!2M z=1?1~fA@i8=a=hRem!3Vwd%z<-&#B#kRcCb;eo~5taOX=0J&Oe=$d&Ue74`v+tF4vthpi${g&xE2%nKJcj;9*#(_nE@=&Sf8o*M6iZ2t zUc0acq^|$Dxqt%|s!asLs%4Dk19wcfPyLaq^LyrJJmG7wACKT0u^*4(+qEBm|KZcW zM^}+sB${NT2Xq2&h7*Qd@~wD6sOalPz(DDLGfjcI-Yp%inz`XSFXi01tF`PLtrs$3 zgD<&PL3NmXR|CA??4EUISpYHjrXw$GZbY@(DR&wR%X63rh5%H=Pgzktda8K$+}{Fq z?)zCznY`CcN7_bFI;iypBQjEsUS*TOAz4&hBZXjvIyowU|LK72OR#tDxJ%3cbJxVtpk zpHWXeQ}=#%{>u}}|GfKuns)j>O_Ba*$3BSs$MpLDU(x>`)Rq6Ys{dDV{$nQn_Z)-& zzYw{+U1PxbLukJTeOLbSVKTAt)*bsnRXoFz2CU^pKpvi?jD1|e)0#;&V1HfbFQ^EvG**EPaeB) zjE9Hkq{-b|Ry;g>$viv`s>>{K4Fe!n;! ze==A^m|a`gz4BGv?SxzFPVeK6^X}f>s}$fUc+^(BvIT*}%rCAPd%i%eE+LUX+ieuT zlK}VO{=Lo|==%4ThbQVcUhXsgdl|msQU3RyhezTDkI;Wszh8_x@t@V7zZ?Dq%0Jhw z-y{zHd(Xpj=}Z(}f+ojX%~8{h6I`y;!Hk z#e{SK6S{Z6?wNbjiQeV|d}UpERQp6zr^hg?tDuj_-}`30lltrw zU3s48PeXZ_50d1%Pyh?r?JQ>B#>oxM%s>Efs@~8SM|*77@)(sTq5*>)9%p398Xz;% z*}VrorvEqoQ66W`7>bdJ(saE8olK90B7b4F?=%r~kcTH|{a=aXC%$2LdtXbUp2Aze zdEVKTpqXf$9R5p5YsujO)ZDlFS|dC9ol5g;as&W7id@`Ve(4RBXj}6P^G0QBe5u!r z(&ac``8NzcdjAwO6r;$>;?wcJ+~L%@$u))K+y#;c&LP#_Z6o?@V%+CL$x637nsoE3 z!yV2PUO&*qTnh6Dr`6lpy}$ACncI=%hCxoQ3nQPltQn9wRfls*{3XxHXhE|P#c1Ei zFv@7q?L*1#pU=ns8_m~qpC3++6U<`-we{||pVA8LmP-rqHBUUTWwtFqa3Pn#zHF2S z?cY>@{NM^hkaEm<0dsPuA3J12uA^$4knb_tnnZj}LTZU1|~Q9{mf- z@$?IZmM4O>4TPQzWE^+ng|$arSqNT6G#WQZx1-lZ6?WE@Uvcmy%AASP1?~C%otrB|aab+wD@$2mvs?X`F9x1qM zY_oo?e#hWrh>_(gfzy_ABr*NaGkqZiIqKx}V$qaxOh>OsDjz^D_3)P3cVb^=E-9mX z`D8euaPyQZatMQH;xh9?Q}M=jnXq{QSwf={rq~<^f<(%`hK^Il`78#Kww+%%APP%b zS)}>&`m=y4jf>6w@r4;Lg0Owo56c!3dyt z)##i>shsePbHutui~|#~^j&H`>6o>XX8CgRlFA2GvJ3&zb{3-Z3c*hwx1HRB z=s~ek!%gSPeHhhFSIs6zHedo23CJjA5fAcNedoI*6eJ@1a%e$6GHsz&=>_hiF^~f) zqR3@zFBY{8)j4h}<)ee`cPkk;#Eao*W&f?dIai7`Ga;$Fd)gJl<)mn(Q?FmkhgDTQ zn{F=<#R?8`z5?FY2Z3Js)paV+@>VpTB<*?KXPKr+ zoOn~+GP_N~rcF?3^}X#aH>Z5m0zwHGhKGbIHrD~e0y_IXYy`D;8YSuflbo|8#duvh zo9LUH9AB*`8Cl7LkL^NYPF@F@6B`JVpGMm0Ku!SQ^zLTf%LDgTdHP?Tyh^zU0k1&3 z{fN#O*Lg&Qu7(_WANyXLe}gUlG@{0AviEf`s^Up_KlC0xX?5*gIL^KMww3x0uc)w4Mev;Hd`p<#8Fv)2g%qzj(b^wTx}in8C6VCTqc_q3L_**Gg3K2n)4BugGa+JcIxY4 zh9)-srBLlqv+Rt7cf0i6oJPxuu%2BzBSW6h65~k+4so=}Z2M2Uj`L)Se4K92c21*$ z&@(8ott!$odD3%(~qio<%G zuHoNLf^tI&mX<2F3T}Kae}IH3BKSJ3h580KVt`WKS(~&Xm5(+W6&wB|OG_suoRY!# zUjuPJXMfu;_ve{lHmL#i6+1vVVALQo$JgP)g(>s(p5o#mve@q@dPjtyz&~5S&G4zl z=$`9WqNZ|i@23v2WsOP9`J9VFWIHPZN%^QL7pB^<;@q&-;Ed&y)2s|-d7;aP8#VO6 z!n-9g_9#F-JX2!TDCl4DTMC@-PT#3kFAi!s|wfXlwPe@~@hMKh|TO}o8cKvxaa?js`a^C|Em*JG}zHnpU-p?>+uZF$`X#mmEq)IZDJ8tY${TJ5n~6*7mFI zmvPTq%844!zC8>00uFHA>}!jhfGpO>&li3c5>I_`!x7QlI;mMLrwQrX&g`D-`w|df zP3zn_ETpG)g?yF${aDFJ_OpBwhiAARRwZBXEheh4wU>uw*T!z@1B~|BFz2Yg7!&E6>3&3o2a*J$UrKefv1^bjk>3F; zVXTe{ICO8tt4X*_G0NeboM&n}DY2)y+H0X>wyQwQZel*{cGcxBfin^D)JIB%8;oX$ z8FpQ+OX!c>CJ4n);b_z?RD})WK{~a$Qe29^0;1zII4Mb;)<7J)pKFX6MGHA;M#^+|oipp~QB$`&6RZO^N8k_je^uX4jSEcdD`j0$q{dlo-FrdY$6FM5b zzFuFX9~I#e?R??`A@t^6hmbA%E&FAB;1@0`hZv(6T{#5B7G^)W`P_zv(9cMq225;~ z^oEchr257cbI?}|_RBy+w&w+@Gt`=uWtt^U_|)Ib>Ah0G>vHwi*+gQ!p0pk_?tAP- zyL|jpN0!ChPxNc}6R_Zx)M@Xx=8t(WD<80Ft@;6<**0#dDme!cdB>XI)i2RHy;FJX zq5*(NJ2mE!&les#xaXnJV*ss_XB9Ve3a)tl3aym!3K~XFZ4jj>XZmFI{W0b&t0XG+ zV3)=%jpJ2R^2LLL?S3lx7cwqO-qqA|EyqlPl<;NpQ7b2McH87Ab^*Y6zk7q2DH%{k z#YSvdG1?2dP8uByVpQIE-&Wu*p+e*MVzinfJjBvkPw(XdRM*c0_&8#>+6~^@RMAIi z^&gw6E=Mw_dvG5C&tagkU?gTq0V9R6`#MG$4!FnAdWbmKC7@u?K7mRTgEgEJ3z0k11qYSd4*pWaRIq9g^iB;E`$0nAI!E@N%CdUl0D%rjU$W5<5QaGjfv?Ks(d zDuBSTwqU!=aBw4}gy1i5Lt7C{MN~Qe4fV&~S#iU$J25WR^olI>QdlTi#}#$l z#nO)Snf6pxT4q-C5r&6`3kp$%H$)Z0oJEdA-ftCx?_BXXOhG5^%!Yfh4;WM*lOXc> zMYGN)@oc;z0FIuLX!_Nx;sK50Ct@obX{{cMVRpFcE92GF^qI2E6|XVbWyfw=IswN3 z_Yxv%wA*VHvx8obtzlbr8%!oQ=wQFIf8)U8)?CAb_D63r-mXgTA2M05K;Sdxa)$vw zT;VvrI>I@Hh&PTRjGw1?%tLu57}{UU4)EzaupL?->4|>o%phjp~(S{qRzRuS4LWfzhB*#UZw>)%K|hil|=`rV`xn zdKa#K3E3Ld*7wPhgVwF{_7x#6^8`#Fdhn5L4(u7J(r`c*-1=`|qLzlOd9>EMYc}=T z%;)zLs5)6o-7^*4$rVuG)@S#{_WO#fJRj5elJf<@x%|_&DYsW>8FL|xgg(09mEjM3 z+OCW+M);5LiuU7U!+%70hvwJzV-y{Yf$hM|liYv_31xAuR}a(;)DwR~!s$Y4G%3u5 zb}+&g&pX6;p0gEtEQ!AeONoi50Lo&`{Z6uSF{az_GfA) zh^Cg~o6HOeHleVQaE__|(PZ-ko}^SiJL8Crwg%{n!f$(~+1zU9{{WYTcgs$Kr<&{Z z?vKiFn4-q??6u+Ck;c4F&VBir7lHFWr{wu15RWq+b}+P8U6eKSMAkzg2mVIrx`pI9 zLrWpO5k;@H2j3%a+_kVRRTw&@`^Uxw@6I&*ci}Mq5wq`yod#6R-FcXI{koe#vhbg` zXO@1GXlm^*S(G9nA-jDkeXb~~`SBB75onWhXEXS-(bNJD-q}GY82ugl6Fmy#W*@02 z-Pwqf)Qx<%#yG$C?U<>P0nRcX3-}vRBwe{;Uep5QxDU)?)(FA6MrjpU%H(?Ckl`Ul z03E+|rtp#O!nV*GuSsoJ+r3yD%I0m|jkb0!C=()vHj-A6rcZe=kj{LQ75j+hG0VVHZ3p=P6J1`_%H#L zt7Swzu2gnO-5jEi(*k@fBrr_CnSb&}DtwOD#pnCcPQ(eIpgvgeLUi;=j~9Z*oMuHU zOJg3beGcwB@e7V3Pp4DA0dQ56i+q5IwL=9N(c$WSm9`H6<^AVbH$p*=I2}$WMjgga zp6t@hC^Q6D9b?^93Z?RY6k zzZS-B&-V$i_~AFR)B%s_OSwJMxn&x1J8Ge_w8Hk+kdTFl3(XLAo0HugAh)PkSxN{g(M`zQ8qnw#=WguYYf zZ1(hnUNh4Lt*EMjMkt&AiuXf&$&|H>Tsi>;&E7m5p)=GJT;vEt1IHmMC9Uk^neGtigPp0&co=j7gaP6&9o4=7jvF};@;`s?m(@zSm8=K>vH&}y6Su(9)lJ026PxW*?B zt^DxUN(-M(*YvI*f_fTo%jVRzYTEJL-fEtJ&+y%}Z#)6ANjj-xO*_x35tRm_($e&g z@Rxq8rg&!Yht&$27R3R0`j*1HD-rE)o!>K26pw^d$|sG1yf zPSmhe1=`4WUnU}6LWxCA?uGj#YjRK-YDH}*lH(}LmDwL0klDd5SB*>Ns!<{p(p(dQ zL%eL3*IhM#Ncs7t0okK8lw1`&<)8+GcJFlBMG_a5!x??Yu@wKdle3juKbtba(2-rY zgEc@A!^CFa6IIxE|26=QIP%V>a_jRHV{EDWKuw-Vb#pVcV)p2DHP^!DqNxR>w}h#k zNBF!}mvhpAOE2RWGW{K&`lL3*^zN25ALQwe>trp#7j_Rg_Qx%Ul+TIS));R?dLlZ3 zTBU;i`3}6ZyRX4s561ex**<8(_Q$U|T&46@Q*%AVJ4S<9t8zzf`Z>%*=8Qq_JERW= z&Y}9!KlOiZWN3&JX((2|xA(3?Bd2ec2hBFoBc7COk7M+6Dw#*zuMY5_|4PhS8F4Sq zzYYsFDy1Voqx&TQve8CHQ?4PS2PbUVZp|;%l5~)xLa)6R&zy=Q{xSRriKlF zX^-eigC6ez`1ARTBcB%=ALmBsXw%NqC-Jjkfw64TSL4za^1A5E4H#I|aE#qbtz}}E z>()DWYE%>#2pfH3fS3i61=mOx=4D*&xAlW-PI5HNI?w-2-jAEVj!Wn$U>yU8x&7_P zupB4W$sQDxYBG`DvVl0r-+sKq6YGnU3wsY7^IgoWCI#OD4zMikI3K|Qbc^-vnPY-K z06r;=yI~)e!Z2Gc39635J7M>1@0kN^q1y^}xX9E^pGB)Bnf<*FAv{`KaTfLqe_&%! zv<0%*-rXVf8%8iwqvjmg{-E$Ck$S;CMR4+E64qrf1kASYty?SNnWaj+NkbCegpX$CYx#`<`J`;OcdKbLi!+YJ7?0`Knr755u@D*EqZQew z4fUCmwAW0h7LWAJeC6YdJm0=catkfik&>AwZ7Sd2^$f!gDmJo@B!je@^cQ`%8w+mx zSdUf>)wxB%*oaU=;%5XR4nWX$ z5_LR%UYG{aleWoIW;<;4bz-G$;oSU&Sy|G?cl+1kW~IknWGuXnuJNF)E@-aji*R~X zk0e7$u*Q=ox*sl_yb1xPLeu7j4Nv7v_ENJ62O2=Yy``VU=v6jyZdb}3>UH1gyKFPw zQ#q>2X;=sUE94>&yJCMoGKW3d`&v4+NnQkDeuwh26r(h>IPW^Aam2 z#N3Di0Wi4IAPiPIGbZ&6cN57?t$zyEM*-%(JWOn`oz8=^=I2wZljMFoHKY#vLx1xp z^*%ms?7zB(E9t8`fp{H-Upfavh~)47@3xNEZ9Yt;?9khIkXz1!KFp6EN(0>9K$S(+ zUtv!>aUzLdOVP5$$rZdcVjbMGM&Bv&wX-oasRVy=fKJC<-@#2E~Bujsfn)$M0EyV z@&X~nqH*BFNkd0PI>>$izw&7UrdjrvPbAJi`Hri^S=1~35*&9@6E;-9*ugc)62}Y1 zWubuCOp8pYR}VlooEGLLGwVa`kda@rk5JRPqmA~kgGQE?dHDvmrP$L?NO-w=^xl;| z72F{l2q|W3boZpxJJC5YrKFkMtkDh^q5$pci)HHEJd75*J@Z$Uu7Y}Q6dHE0tF~-8 zo;o_(4MESi|zi7KY~bI6PLmt;9DnJ&n|L=kQW?EvvDN5Dd93vD;PlR(p@*iVn^_`c-f_6b#LM;Pm^I61=B&R8<9( zMMQr@RBD6-w?kikV3SsMy(gL~ck2f^dUKup9PK5w_BE)NyfC63?RRu=<$T5RTJM>; zmTI;oFRx3f>Ni+wPjnEj65Hwp1&f!$n;lW)2-R?BBd)AuS{Gt4hz-!zx(llhyLR=T zf$Z>C#i+dCzh+&NYf3qOTT9X`u{lSr=atK`GZz*%n@)s$rJPF~^TIg`LT8j8wPh-F zEiOLr%rVS~AG{f!8dOb9z`JX#3P}JEC#SgM3X_KFMG~}#O`DmzFLbxZ5@sAwzI$og z`&*^<@Qs;ltj2uAG34D*I}Y>~y{+S^)0p4eZnSZj zt-l;D=RNB0j%8)Ib>6*CDVSUWjL0DIWO{-*QFYPCro%eDBH2eoK2Zw?iR| zt<1xzar!!OyIHmUV#&6}=n3h|^Ki^uPi1%@hNFQ` zWR9=fjlL z-X{yLgkyR*I~hfbCGgB}16jLr)j&|3D!A=9p#i$0ky%C2aqf6r2ZHcuVSdf4fQ1B8 zW?IbLY-%D*ht53PQ2AhK`oR^p`BvM4p`<5OC&vKQn96=@fc&_^_ zKNYm_1^iXT3Y7hZND%UlKvl&rFBo*Ao6vxF)^nfCTX&|9amzZV9&zoT6nx#2g_0&B z#&)}sh3#IebDypa4x?Wl-+3Gg=1&8MJht5wuhux+*;@&{8l@YkcAp=1|JxMflfUS(-=q&>-&MF(MwlFx-V@V zzXOEq=56u>fM6@C4bBa*S;9WryID$C*|fm?A0K4{%+i9@^qQ-8-}H_!xWz{}f|}N5 zQtV5zQE`6jaZDm}``}q0g=UWW!qg9aj6LPSnYmKuoX@yIXNH5yP2{M>eS6RJ%HZqr z&S(#jkiN72*}iFHmBrob`U*a&KjP+NGORl3ud(JjbNn;&@MF~k@fPxe>$WR>IR4S_ z+2B)3+wmrp=*Big;9!M*L!NUbS2gfyf$jtDWj_)KGrjwz7oN?}gY)j6bPM<@HLXIu zK~5`?o}FFT5Ynn~zy5u7@K@@DO-*#X8cf+>HcwOaS_}W2Vog@P<+_Q)u62gTv$nj6 z{sfU^^3BdU2PCDsC)z`cH|s#D;H?3%%olomE-uGjCI_NcK@3PL#eJaFnYKA^d_DXp zcxa5kN*c?3>FhR&QxB{SvB`b`Q8aw2msjBYz(Q0(tKV8o0C|0NJqY6=jL0KP6E=ed zEB7verR*aw24Y%+G{aBnp%-r3iGUY9GSgw^KJ>JF(qn#!m={4uym%>rb25= z)8fYipG)(1a!(n!nRiEqJGh@;^tL6)y?ag5<{(N?E8VpvZOcoz9;ufrCoe!qmZ~ac zS!Fx{bDG$yKDFVZ z=WlU?Uc>OVYCyYEou^Z7GmlbB??%$BxS_A=aGxb<3`ts9sz_AsJdp%%9Y$h@ztzdgF(ulOWm7j z4UB0r=^V)Dk)K!iV1G_N(^YXTU4Yr+A9fEb239!U=M^~5d5)=yxOwuC>{`!`mE{Rq z8j)zAX!e09BA;>9%Q1fFUF2wth5hCl!QJJ1LIT>VbZJ%Nr$FAjCNu%AwEz}NB`a!d ztm_y!T=FppcXTwkUgpLs?bfb!FP5{%UJ>gm-?eM52Ra(8G!HLtgbJ;~99J7%;T!G~ zgy`k9gO-siA@L$8?^r^2$xRx-LGcIy;N}x{PCjwp?Z=aJKGd0It324engyJ{i|S=- zVvpuWlsJc9mM@IFehn(@l;#?;=u;{1%~+T@R&KkcV>aI+JX5LLv~5PrIlE4+i>$w) z-AnmO$h+@)cAo^ov2OV`O}df2l!qYKfN--d9TRw{#ei1&wqi91;sQhwakeB&=`8r39Bw?vlNlx@)K& zFA1K^&9HsUP3&fvMO$}0tz5M2!}6+CUF$=bm0z#&Tia}#5wm@L*<6a$-iUbm{Z@*M z6No*valh3?n#{KZ(Zqd9j)*Z!w;0O|_}=#%#yUkM%1o|dR2?nmQ~9#@>@#y$oy;V?$es_-|%19x0P@XN+xYJkzH!N)_DWwQ|9_Pxs%@O>dQ%eSQ0tH+(XM}$xjTRj?= zhx;ws9>6<9A<%aNxH3h<^7XG>!TFQ~{lzik@W9YyA9vSI>$PAncHNaVVC6itUS-&J z+B4BOyVkOViOm$8iZsXOQrvFqS$9T~L&!PHY>4)oaM^yNh>q>088a~SSJfBhj5%59 z#|Lfhi-1q3`P}yA|B!}#v9CN~?s#=3GliaGZtzpnICdxg^~(8<37AY_MPtzdH85r| z#-T80?3Pw|{y+)AZV*y$Mx+%oT82eDTE`%B;(-*~YHYGlJ^!enGNIAgAljdB92C;W z7Bx_rDb1mm-nF(}?)(wiDW!2b zt8^jMx#}!KWiiX|N~ce*(_mvC6Le=Q>;6@5yxxEcVdRjVV$S<@GRITyi2*Em&oVT} z$2gzlLO2HAGs{B_h)?|PWbJ@??A+QqpqAK!dmrm{O~14Hy|eGQ8lpsmI_dWe?{p(Q z(AwbObouY=7o^@KSUe;n+Y)O*IlVLAy>yX#&7O{yVIq~C2?;C&{XsqvR&{QO(qsuY zOG0V0Ts7(P`)_NFCR&r|wA)E-?765&VWY0ln41LT)u!DC=L7r9h+25+o7?)d_e)e` zM~;20hgb+^N8J73GO%DR3lWcmEd?hdVcns(x760Os|U}!j5ap=X|-vr#)&Lk+yX5y zp?g72xFqj*qC$aYvWGy^)P6)t*^TK6|0RTIg?6B^UGF96ssQnY>oyhet$dx9dzOf4 z-H^&qya_$A6j;)pIH*Db&AfP_@spuX@8D&sw*8!h_O`t-@HF0TU)uQr^%s7dfhc0R z7joWC4hYAnXiSbOI6DolY0uk^6n=v$j`Th1oOxd>6!_IOoo)Wd%X;o>1Ro5TWwByY zw*@8o3|U+U+mmCUr5z>Ga*{|M><^7`j9tB+pt!eqN*Z?;O8C6;;%DB4`a7sz6ZxjE zLA}RE_tG?Og@5-4Y*|)c@lo9DHVq7MRn2ZiOVN-zEpO=^y(UTe^HJt^C3WDihR z6rK|o-7(MZm_uzW8G#CxHpe-;gQxAvGfXC*dA?8c%k<9ydRV}l^qTN9e6!iN-3m^* z-6nKKCxjZr!v?A-Bc&y}jI>QDQFMDNt`}i$w(R<#(3RQ_ML(}_EPDqx(P6%;#W82Q2JZtl$a4g9UU*?hz$$>sOt z?cKFt(rc)dEADIkixO1a7^Mq9f#%&MnOoUk#G6wFs&qmaUX(ISI zj_3er00nrhl) z5g6>?+=JfCx-jlb+sYSAB-0g6wOKj9g3LW_J54y@*r}X~aD~45!dMZ$hLo`K&d6=j zZvD(F>(Hf&Dn-x|N`ykv-5(6FbFdZHr9Ru!1csZ}0EW_AUot*ocMjY=b4}Wn@UgXD zO`~84R%n1S8L|sV{AqAb8TB3r>1T*ml;BM}KC4$(1fvdT27Y9k4>dZzvxQA84j=RA zs&TF>ZMU74ggpMhzGt;iEdWK2H;9sm75cTCEvRlRIaM!ml2wt^e&5lJbzTqUk2|A8 zvdl13%)Jo977d@;@VTq=>xP4G0^0GcINfvX>^e8UDP7~5rve3fAZ#UmV?IMI`o8eS zg@uNi$Rnck%Vi0r%a2%h-n;shvQLx5%$6USE=IzW4mX}W)2~7pXU)htu{qi#_sLv6 zQyjvVZrjxM&Ji=(Fg+05qnzIXvstib<-HFgX}Lm;!gkZNkykozb+R}pv)3Yl9M+2) zxd2OsaI-Hj7>`8j$ z>sG7rxOzhR%TgdYu^Bqqw0?yEAJ>nVu%Eyw4jV6XMj>A!oGJR`)tn&>?}F#l3QbC6 zvo6-Rq3kja>C_w<`2?=(!Wv(^Bj3>1VWE0;=D-(Om^CG5Hct9W`WCMyd5ym`I%$jL z91Ihokrme5#1a&6^Y z4G4)*kR>NoLWfEG5AG1xukrXTo99#;FmoNFx7td4kLdgkSJCpVRC=82SXhz!8}TO( zy6q8J!7Qv!v>yX4yA|gO4*;90c%WypC39qLNMT`aSeIjoN@^v1+8nj(%`5`?prY|3lfz~jy#a;49+YzmR3ZwEq ze5e7)!{8llWdGYA;`L}L*#rSO+fdaFHI1wq_IyuF66#SFtWyw3s^^%mcgzgrqz<;*=enabnEoF0p8(op49XmDJN- z=iI(lh+yDd057fh{DoZ^{+54rYS&M$~_(j3c|8Q%O}+Gq}DC^rwFnbng!fzbh% zpjYZpH-Pl96WJ8g@lUprYcyV!oB$f;S+aug3EKrDEBs_(3Ndg_m=cSc2RXivfBlbp zo7^fia2xk=j|4atmi0v3Tvd3$*`KFeWRF{u&4%u;2pEU;MM)1292(PGN3 z*#>N!rR$kE-_@5*XSxl)YiUNZ-jKb5#Fs)|T4PWqF!U|4p^*ME`ed2iLUiPlOHT;s z*{lnb+%yMfujRQbN}Tgc^G{0uOf9fip}Bt`1rcxB7tmL2eI&q+tXHj<^@FuLGxcZK z-&yai$9~)itD6Hs%xfs*fJ3pgz9$VRBHFd)fej8KNotC01=`%1p?R}SCSw(vK5Lnd zKPcCI@Mv2H8sF&Aw^dOzCo<%&-eV_^-#k09@kwYnQI;jZ=FHe@yO{08?zlh&NHJ(_ zzx*1&z^tP8`0+dzsdpY8ppGY#e$#V0CLE)&@fEt_FWY#rjz5uJ!CE&P_rHp{S9UNq zjNHf%T(CHp4WFx=4DzD7r^MhocjFf3fX1-L2Y*bktic9vE4OuabnDDP23~%jEfd@o zSCx$-Z9fjp`&skhts#z?;aeSl?%WZj=Ynx1NdwoGj=w||9Rg>fUC#ydRx2z#$&CXw zP&S0;z#N>}%pDJu_8&(*2Kr`!)JaH6NEkbj8m0eoqj`dB)xyNS9a&MD%}Df_@Ovs1 zTGhx7@Qo<#Kn>nzo43@?&1oagE==q~rX4b;Z9q;|m!{!kj%G+tGuNKU()pZB?=NiZ zZ+M8w4y%H08dPJ?mX61pL@G}s}zI0y_6zo(^%clQICk@lSP9IvP zhy7gMttH-^CsT4my*^`TWmPIrGvAiV{RHtSuS|7_h^dqN=5(hyQ@0Q!IkSD|!}zLN zSlg01`RQ@gyiVs8J$-`e%VCg)Pze#adB7rx^OL8_-#CxWcuMd--a_3NjR`U=gK z8u$4K%ZYUbruWs4<0rcGn&x7vFX_K>_zQCrbt@(VTkb=W*JYfeI-<8!djNL=YqZRow=H4k&B zBI<24ulBu^P^^(j<9_RkLK?skLN34HWjppxq{VxpncyyJ;}3Qd&tufy`Q=}_KD(GQ z{l~;e?zu(n^Sj6!qkk0YP{D^csR&4^mQGgncd;Tv^%M(*wum<$B_cxP-f0joj;$F4xmY1yp+x z`!=D6r$eW1kr0&&ygu)D&s(KuHhK@yI=JxWxzmXlyvIdo$scQ}><7ND9nE~p^wS#5 z`qWSX!u`}Yu9ZDVHywdhim4`hQd%U08Bi};$U0M5>3e2^J~+~Rx&6rgF^!H}-jVW( zM}CL2#4lTW%6a0oaL zLKp9%`8gEH$!2MgbhlG#h{U;3y$#1Y`6@k#5C+XG25A`V1T80y}{^Wt(1RU0xnM6Jl~b z`tgw;LPAyXt1lmc_?B`q9lqH&TW7Sj0^f)lVXyGe$FeX44K<&nVX#xI^&F8@Arzl^ z@{IS*K+&u?`UHjmc(^?Y!yVosv;e zTfJK7J8DTsx3hR|MffQ6$qe$-yrKkC?53&pSj^G-gQ(rAhp@Idr!1d{BES*a|IWlF zo!m0(uv86+X5YyG#DIJ0C5rccIQ7k!*SeY^%^HzE`?L3|dZ5)S0EamnP=-aledp`f zubds{l+-ob)O>1R!Pwc0>WJkcoqO{#UiOlX|IiV-?O&!Z?!BK!wuy*N8@LUxRKB;8 z@LPqdZA0p>+T^z9`4$M3Z!?uQKh24ZxsN4W&a2$(P(#IHbC81lOEHAGY-nQKO!t;q zk4`bx*E*pAvHT}Rv(-)X>RYPkA>(=Z@@dFvDpGcy)WK=Kd9E;e}`OekBrN{}KGX9jkv522cEjzylzmvY`Ibo1k zq5fXc5RQvm>4l%}MhRNY9jwCOa5quMsTQ z=9LHHde@3G0;f*63_w*nlZT_xlE*sAd>8AWQBY^DJ&w7$pd@sb={)=s_m1cvUrXZH z!I?pyQl93$TWCu%1u>foRv~Dgs{%EEgldNUpCZl&@vi+{i2HIK{#6#sfZ~KkPs+`S z;0J%|NiwgY} zeeVknd~OS^b$lh%y^f}9fP*5WME!nG`TN?&QjEu$h9J+KKt|HVtoIR7Qsq3OjXU z*q-}OR}8JDuLE0nk+Q%~BP7cML^o^stxpSwy8sbmQgTfalUdAD8D zKN|SGc;`|P5G`LQ98pQV0}`J%5B#Rtic`RhUCkS^`h0F#xDjUGpl7E*}HPQH*69YN)<;PH|t%& z5zb~mUe@f#p<&h6B0}fLy{|nl^l5$)3CBe3adD{9CDa|%_!xCiV`fF}$P6{3 z_LB$E9kOC^#DwGFMloAxgW{Y4Wblr_V4$GgEASD*9NZ5oV*U9L_ zybWbp<_o}j}u@k$9N|lL#3bAWy zLuu6WdK(ub4}3WiPdlvEP%y~?*>e4Eo@E_?nVD8W_47L7)(w;~VXc7OS>ZQHA6{fB z6}=^RAmo3HrT6a ztx_W~bV~ueZ3255=EZtlUp6^#sA=MsUQjyZ+m3#-{tTf-WXz< zIa*z{9G2t2V_J%-%vTNBbMwox4y~XQM~Z%e+1!?yF290%Lt>PEov+A`w36;We)F&9 z>gRG5UH|149P9fkU-5O~7X;N#h^^6&g{{Y*XkCxE{PfVa(F#&W?QT18DEVYiN`8#pcUd9o7^6mk^oZ9g`evL<%iNYB}G zz*T|!>aaj&W&{H0)Mf6ZT2IK_To?Ku!bz{?3MU;`)i>JY6b}BfnOa5}Xbr8tf!@Qe zC0zJ#^&HS~(*Iw)y@y}Y{rCUh_9{!SE3dLLHM2B#IdehV+*@;3?t$b$MFp)cvouG! zH6eGRLhcE)6!+e!l!_BYQ9wZSOV{V~{(L^S-yiVfFL(jxd7kGyUg!QeP)Ex}N2s}V z-{HwytQ&<=N(I~Vlg7U^%6t$gVR1?-S`U=0z|pHpcUL>RdZ?H z-W~OFzUwCgL@!mKpx%oNUGb9ElV+wWt;wNIxt*1!Wo0eee~S89l6^X#bchgozFa}_xxf6iqG~m&L{b;C zS}-17?$`R1S{r4ntIxhnkPANjoHK4TUH$wr^S*F1U?e2A+qB|SL@!V8;T^Qh^q;(g zhR@M0l@Xi!--0xa^;ht}t>N$cF*tk#aE~yxq8dZ4wnzh?!Bn3x|Nk7Q$*3_MqD>%a z^-WCiShb5;wl7eK=mF6U#-|VbZ&S#tLfe$YDKYt+`H>{b{^B8tB2?!kh~ym<$hs~? zs*glDl@cyKr!}utmpYvHF;HMtWwq@u|1;i!Xr*9rRoh&qnI&H}?>d|a)0ZpM47=!T z*=LYiA-CE>aTZG2mqj}I%r*pmX_*O|aEP_m9fCOFS8n1H{?iA>H1#)pvJWfDTRmrK z$rEB2&2P54mC;&=$nQaEE&l#G-KJ5GgqX$?wvyRv3tN4-)2fie;XkrWuYPbBhM&4h zX|l4;N=q|^Xqpysi@~W$`y`k%)eRm0_lq6(7n4CMtl_4RX(N(tF(66$Spwld2S`>4 zG%=r;7egvXL1m=bv%w`ULl=Tus=t3pZ}7p%eGA=96YtS3hNJil=rj(fV4 zt+evwVdXnX)%RKK`Qaa#WuM;Jc#<9yI9HdiokFvn?^cm&M_9Q!_kA!2n>)YM(M={S zpgs8fL@ApiRbmtp0Z;Xzh|ZL@0#OOOP+IONv@Jrc|c)ky$MuMU~!zup*Mk5qA3_-96i)+#J-YO_;! z)^md;F(#HeOI8V<2|hXt^~wxLIJ#u$y=?^RWEupyT1`dMwf5<)w^hm>ydSkj&2?uy z7Y%cB273)Hi~W7o9i=t9D|&}aF%e52E) z@JmhKJEpkE)F*)%Pc{|H-ieLJo$nk4aEq!9QEY3ZeT?klUpOmX82()~sUF)Pg{?SG<@ka|C+u+rKrdY~Gss z1a8iw;k(G(V zSaa(Q>2N-zXL`U}_xI8`l%f<0AD^yIE$DHv-D?~ttFWx{3n~94m!f2=t6cpdK(o<> zmPw2#AH*+Jky}_k<|$m>cGQD=#f9{6Pha8t!V|Lye<`H>7`kk7tyPH6jfps{JR5Op zP%aCabxsgN0hsb>6w=QPnowpw!=29`W}04Snxc z2=hHI1l8tbmq)OR{Ze(GKYzF59G7wsD#cDmXD^1C<$cnMqOdk9Si9!ri)jf00z_^-c+3bihFiWuRN}0= z8nZILfVhp(T7ui*XKGFr+fM&&=GZnN?kJW5+*JmwyK%P9t~H0ST23;-sTp#v zhPcgIMg`whjVF0lzK7cl0vB7q717N4dUtf^xCvwD<+pbbx!8~SN^av2Kj_>UyO7wm zhQZv)^UD#zY2}V2C5P?0R|4%{5TJ#EDYpO9i1)0bl|PM&_I?E}hkY+puxCE7V^v?J z8G*>&N7NR%+cI`rQ}I6G&g^c*5psg)QY+?&6;n1OvK}6EJAM&PB zpg{X4E47oPM6w5rHTHBoI33c73R30Ug&MltfHqh+L$9-;H%=GT_UPRz3~c%j$+_Gv|r|4Y!$wZchNwAA7UwRjU*PFlWqR%-{1riYf}X}5Tg z+6@?XeQ^$O1GYPOXcfV{QFzbYMfl%RKohNb1-Aa}%wR3|^W-Z)9S}L3<>%rLrVXq{ z4Q$6ZnV_$8&Ee3ZG*;fxi#a(y^^AF^T1@j;_O|~yRcV#0T)orREWDcv?rN#~$9I;l zYNjCwbKt~SUgeMl_94xvf^H@8JKGR>&tV)+*<6BEQF>-?U_bh}7%JZS@vo>=`7tEt z$buEV7NsOsg3^IWLFtHWntSNCMA$4{!O_hbHi}M6835y!6-pxno{%TALFuF4-6$o* z2cE;R_vf~)qTYe{5B{rs4Uhcd3DNX(Lq2bVw%My&-BsQR`@IbMK;wJZbmpno=hL{a z2d7v$*w25OW|bTeQm<mZ=A-pc9>RP@~Xw2?4XML#+=@?OiO^c|tK@}nVrQ-u;K z6M513_bZ^9ydk37M4whsSB<+ad}4Y(Uw#z2)&!L%a2jYarIzf41uN*%_7c92&qJ0N z%)jdC?f|*CC9=GdIu>iSuUptwqg2w1Q6XeL5XWwK_H|_=X7BH`baDlB`{XUhF%Phq z$XOjto`fV{%W@bTJ2Ot+B0SBgs^Z7JIvwcL$;gx7)n)LH{R{FK2JumSkSIj?>mO-2 zait9R5C_q+LgOT;1(Xal@%!%_S8>WH~v)1$IfsN#%?`Y zOYsxT=}diI_fDZlw~ea)*!!HDXJ0uTHXYGaV>xNa+l~m_Nz(rcC0mS+t&pT)Q`YlQ zALtdPipFmnPh9xA9s?v^gQ1X)1(Q~>jd{b2`)HA)HS;;RV&k^O7i)vXD|dq}^|T&x zN^IY+da<|M2FmJ?@vF`uyM>c@P>L_R$TZEC5SKWg3Bq*sG)EPjyayK1ROGX2Dgcv< z{iEAcZ_9!VwML@oRA&uetHmU^P$sCp?vxa{#VnU8{xCt0(j&XPCdI8Xutk+eGAmJ$ z6yi4@yf~V3D;K?;pvLpWlL$iJ{OFRfH}Go~avSNc$~jU6&us=sF~Dzobr*Ga@`LX^ zU*)y)72}}_thZ05EjO0y8?%s(?{hx4fM;Hf(hgKHmT_%IW8DUYugsh))zyEKYkTIJ z+RxD;L261Gn>upaV1LFddC@)8bMx+&IUk+&i^5PWqvJk^rK(E7Dr=OMPsx24myxsN z3lNR|j7cr+5t+`rB7Q}KXwAp*WPEsYjKC&!MEl+oy=eKI?8ds!6XbW>(U** zxeStumUp?RNLj6#pUv?7D5AY-<4IF6*X;>{n3Udb;=IUqct5JPa>P4VbT>=irFFR6J<3%@TOPiW7UFpx)da$0|1?GQhHQ6zHpmfsEZo_QGU{3>nkD^i zYewE!zL}@{CGx*4#sra;ZEu`Ix4+yFI#8diEQlU59{##?`LTtm6(TbnRPRI)wi1n$ zBqq`eIR#_JvF98yIj9INQByS&0OjwgQBjD}{5gyK77Ra_?<>nL)KTuH5}$MLC}wG= z3Ve^9uWb_qYrJrUlw0O7P`O@X5EcCNuR*59gi@GTPL6NA7BG-NJQMI|L)HFHm>EK* zP`{{T2mt#lv(I4qMo=Ms{OlZgI6T(J^%+OkNc;?;@8?!ge?SeLExlFpIWrSn)H}9jxtpc#Fjnkf1$>#rlEpd%E<(4~mr}9X)KF}=GPpkjUKM=8A>tmbnQOBB_ge!WvbvaM&`X*BvP%% zk0W&i{347K^n&b#Z`mB`ZGB+1ca|6@My1H>(5a9L#T#~G@4qL-3G=Fi@ z89Ds1aauXbDwiY;sT+VoO)TRKzwaWB*lRNjw`J zFTvg9vhnzxn8{u}Ua65cM<GK_b9 zoS05}&fX7wn~bDKJ$tShFFe=i`+ZP*MsI^!Izq~&ZAlYGSbr%}!P<_v@SP)~yq8~0 z$ieK6zJ6Cw>OLZ>V90VzTB}ALD4**=at*qcviNnihV_V1FTwH~Cg&i4f!A>HjipVK z6r8$T;WTP@Fw{ejGwL_p=;u7L7*=c7rD~2&ky*j}tQbGAk`lT|vh_l(=|SxgNc986 zo#J%Ch#PeQx8-kQWR2*LuH9VIGLMXZ({f& z&>zO)q(lAS_bnk>(nY!sDI@5$@t#%dZ!!|li-U~eDj~6?y7y>boVNyDx%9Bwvfzbk z^5heD)~lL{rn>o`5vL+8&?2L?FU=&NXS}M~oYEpW%w+cbpE?VHuW2P&Ed$>BURQF~ z)zSwf!R`B~;n9 z?F4#g$eQoq<73S`CBkzh=3?a$FAi46!eU&PQvPZ^pltsmvTKU&)FBhfYH0Zz+nXGC z?0V1-)18gATS^PwpFijPXm=gXVXVG75G{A&pxZ}l#i;Y7=UWp`wm`_MbWCP@*4DxK z@5FrSo%^8)+1jhUFx6{)nbh=oJScu5iHH2{h|KK9wcvE&v@c@PdW>;feoj>1NtLnt zy8Y&^Z9+utoRc=EZy|Jebj}6XFX!4?V3BjK#wh@-Ofp<+n#=V*kaGu-&bvle54GPa8wW>cdgoo}9)T}j_Uz?L7HpZ_k$R1oB7Oc! z(c`g#yP}V5cTLPxm%#%#G7~1##^JA zGLB+m$40*i6o&0B6D~3YzKeVzjaoqc)Y3fz`SXCs=Xf8T8=tW*O~W?=dxAs?q~Duv zgePjw8fsQ5DH72d$K2=3S(>je=-nrD91eVX0hf35Ktoj|`>Q%sKS^KRKjrXLgQ`rs z>pz+Q^N0K|miYg_V{u?Y&|O&7LZh&Ij{~7c$mrgs0a^Yq()Eqm8GQ5&d+H_Ba} zQs=>_X)g{0Ch!2mWa<>nl$P6jcp;-yrN6YUtPVS$pt6v0exBkCU5b^30V56SB0b=T z4}kgH64o8Sb`lt*`hPvrj;_F>ZGLgl^jaNmo`^2I( z^7n;|3o6gVJ6HS9L%Dm5n^=Bfy@T^Hzz?|~VMSCVb%eVK?8pXYA+yz+IgHZlLP_G* z=ufWkvFBlM^)i@5Gv^N}XFHS5xzK&Py_NNsRnO;I%ONXFKI`+SK*y-TU1dmd5Ru;7 zUM*NwGu`ZhfKjVhrw$x=%-B463Hc6Kj`TL|Ffz{mrbw$%H&$UEYJG^QS&nRUuha=@ z-+d+bt(7e1x|av}VckuQdv-6~wRS@89=Nr$>E`x*@TM^^{62a8qVT!M++Fyp zA?t1|y3fbHatPC1EEDaRCR_wrx`&icgh!blYdEIP7jrDRj4gereR5k2_$_z5*1Twp zJG^5h=HStJu38o-#oaA0a;=zfvr^YFxxU${eD`p>aBur7DTI%1E%oL3(8E8h3T0GZ z6FXIVmJZNjT&v_!q^R`fkjN+SBL@y-!gLO|FFfr(8E)W#8vHxtT}iEX_Ht+g@?W$r zfXPj3t9$bXSoDwGVlZBQb6s$?`+vTV5Fw?@bN&nBw&t^|j$x-x;!O1M5JtmEismIr z9A+(-N3FR#r;g;E->Ffxmr;#&90B(1;$X5y)J;jp$X;^`56dvWtoOLdyVh_cHp|YC zU|)TlXFtrdAGm}Rdl%(*`C4NHx0{$z`q0wr&-yg)>TSH)j zhYzT1HfX0DIi~9AhF3GbJyA@1ae&7AM{c1h$UiRm4u$Xjp)Q3X0aZHvJhn$hST~jz zJrzWKd!%?SlR7G@(JlL*BPDNMgW7~6Grc*=YThUKXX|*;p#7VyzOG@#mrUqu|H2a} z?5pqi4@g%5?IlFnY4!s(mb3Noq8SQo(t=vZ;)9S*LtkyT%|T)J(Cxnyvyk#g8)fR; z?d9;`M)_gVxHU2Nx30mQglm4p*RG~X%~4)&S2$e-0ppY&baUR>_ch(t{1wifC970% z$O4UO_H|DFb~OfCY(2MzvAN5pUfH9iyQ~07<9PAuYt5pEmj?O&mSz~()~q|TzQ0lG zN$OmV#3^K?f#0?_cJFy~t^Po=i{?Dp4zJkYN%voUhztesRzn*(ndUB6bHF5*(<_+q zFvoszm9MS)P#i&765PsKjBNF2Z4ru4@2n~^oaI*vk4g{eT#fC^X{_XBsRX<&8L-jz zz^;_`b6sP_@0H+YX1PODzv`(lHtT z7arrLOtHNj1;WE2*P4xy!QP7k;CKc-J!UhoUfy1@%Xvmlx~=DsdoN0dI4%>aNBZ@4 zNQexw67x7OiB?)r`{y^9)}-Ud;Z*u861mQQouh+9SHQv=j4p=Ig!<^mF53AKDLV5G zy=G^?whDCHyIjM$c+E4HHYncLeqRMROU$sQ=ce~5Ly-yX>wC_2TT8G3QsiP{Vj+be zbKRP2Rs&S87+}YfEzY>z+|=W)Jgi+mg;Fe3zTALY4bSIf-;XcAXZ;rumNxUARu#Dt zE_L8%V{RcJlROJsN=ECJ0s!-2?@LxJY8=;VGkWT(H{d%w!4aqwO5_faI!8Den7%l$ zxI{*eR*HJr5PD@#3?J?B2tOi1Pf$mmRYd!fpmpoKfv{nK(YMO)a!NGF!+M@a1Bj?J ztfw0ix4(vx*7~#B0Tk2|v>sscZR@60?|e*kLTdNc8b63tv`X)DmMN4ADu0t`-dD!8 zQ}kurT!9?L!0%{B+;Se_6m=OC1-Lc)TNdx3RA<;;m@Rtq=A%uVo2KsGinh*W4Esnj zmR;gU0+hODOL2A{ez}=n1CnDwQy{yqYg%0X54Z>~TvXzLix-xSCxbgGufFdjgk7vQ zu<3nqUi1Xa8IblA+{)90B3l@mE<-vTyis#-u5Xz4<>=kb04T$jk4#-3 zieh>;GQPg7qA)!JO*zXY2a-DY@o-xlvmM^3e&W%d9gelpOxt1XRv|k*xGS@`l$9m- zz4aL8ytp_}9=tlX28UZXf5xcqt?;upas}tn1ZI~8)q2%xNDvOWcMQl}iXL2TRF!Rx z0?LQ#>@HsOVkPix10vr!AWj}Eg~?4k}*GwldPiXr<|>&kaTA!fmg90 zZs=V}T6u4dwBG#pus2?$ndzB_DKqs{UEYD1GxT^aE5XV=aS5p-_fkvzJq(goM8@M? zIePOlwRk0p67EjJbuh&h8o~JsYA_;$?Zw-(oK=C@`C7jMZ<}BvjMQ7y07MM8PyqcO87JYT`_@I&_*GMn zCGQ8y!cRe&e6pq%gxEgo9DB@4@kA_G=d;WD_%lZna)^edvp6#K6dP=@wh@3C%gKlw z!&Xtsw^{=Spr0438^C5SRzmL7=Qfb4KwDHXTO#0t1G*0R$yA(oA!+lNaK;(?-sSt} zU!PSLjyucCk|H*lDNx;skI~pM}uND8}WExMCJY5B^*3z<;bMtkvB>=GfQQoFMcTA$v3SLjhMwfE1kqsS_M51 zXxb4@+f`#KcN>A&YoLz%-xo*rLOM?ey?dHx5HXkkvS*9qwrQd3LQa}+i8!dhZhNxU z-e-+=t#Xg)m=njmPwT^86J=liG()(uADQk=Xdae~$gQc-g|PJTEFiK=EFn&%l%BctCiWvm6ltAxpuF7FPP zGC)JH)j@JV69qmAYjLkMuw8j@QhF;m9rw(mzC?iQ7NECOV9gIk(Bxpul=(n<(vCS;3x=mBhPbN7vI` zH~Q+8hUdQX8P7<&rgLVS@`+}spR>E5j5LvO_cx{5;hm$gS_tkx9-KIFg^bpCs|%L& zu2Co3=_+qSn%0Qtaw+Z6pMlOF6DvSkPHJ>z^;%fVSquSu@s~fba#sf#;<4YhzmsQV zfbS2ZO{rale1-T8SkPrkqXqzliAo5Nb`1vc;YP6we7t6*NvNoG-C?3(us*761+1F{ zK{FgaEQTtc9o)aVc4=cuR_?d4e()n)$;((D_E*d+a_Rb$#*rg2d;Z)Gt3SV&+w$EM zn?M@r|J(!)fqIUpQemdfOE3+AxA#)?Q((25w3oCb!Bz5w)tXgK89{H}s--HhBYc>& z^0Qvx(lUMg@!M>Fr!D`#e-0c(dm&D#m)5jA>n@iLbPfrnn(nPr1D6{a9R;)}TAzIC zxjTHcJ7e%_6J62t>F_;Uq&_ue0W2PAn+_3AKZDouIs~P5zDj`{&X=M&faP)peGFbW zWK|7+V~ia;x4+3GeYY3o6~}{4D`f%O-&d_6By{5B7|g zfbwZZ^`>-A1>W#zxT#p0c6X0d6w__WbBg|OmkQRo@xD}}t_8jk_Cb6M;Kk7Nj^$Wq zD`ggSjl)cs-VpZ^r}VG;Z;8dYym_>+K$oRfSQ#hQO7|p+`0fEwAETjo7Yi(P^>PRP z$^h`{xzHW#w@F05mZ|ev%n3+f32k zOY^Q0J`g8d5Q?!Yhl4ZHnlDH*LUOj&sVVQa)ra3~r3+wN>@)g~KXcEfbc8p{FZawO z!2C(^oA(o^j;cj`Lpt8nth5x1GwIA|?*tapJRQjeI7>jNGG<5|XdcL8G<86aw_2Re z0yQ$BO{TbUIk|%P>uXhQ0=$m4bHw>kcR{0dGy@8R znTM1h$4%GfS{7F(nZM~Ly<}*itv|1jcqzFcy*5;@HOud}mRof->aXr%?Z$@2JIfpZ;CNCNKNCVV5JJ2*_&1- z)YP;Ap^U5a%NP_u)m*8hAW87NUc+P^88J3HM<`_SGr$Hf%Fu8L&4n^{jRdp!*l!Z8 zI^eBchIm~CCsFP$r@j#0&}M)2MdBD@@u|8ffa~(!!-*Q%S8>AeYx-$nUI)yUd0?B| zRbKFy8}^c`YvQfG_Pop6nu_NcaIr%fj*R9<&I& zJaNl6}y)Ich&d-y8how^w`odN|n@lHC^4BFuMli^$q- z&=ETdu6|CuW5*?@>eL!2@#;!zwI6NpiM^}B*G32f!n4~Yt62&daJiN|cyaO<5wE`0 zw8|J8D1oNsc1TX!41(?$rh)CaBaU0!#v1003opolgN5GYcWsvIY21HY*gTnJYT(;} zz>fQ|Zg76Zl_KjR??T(j?Uuy0H=x;mxdDBuLWj^x0@*sEvONGH7JS+ztvHUqT&rP< z`O)M%u%i>Gu6S=;h&TB^Oo-?aoo@VD8Mv90I}ivGi4*qf!;bvbnwu#XHZ{n0hRS!9tqVHTi4vpcGfo+lJ=vE^ zD}Ga>VjEEvw`Byi0eD}qNcWj=X#@SRb8)aqS0ifvSzk?+UpGD^N6 z6sPfu#ot%|Ib8XjtBVuds+Qha)gx18E3x|7kv=Nhy`?40zq+5TAM`Hj05q~M!u;`E zMB>8=fm_Sa(6wv0QMInWGRuzptG$r5evV^r+oB18qpM->G3Wknx&#hgrtjLVk0apR zip_OC^Dj#nv4Eqm961}6Er061VDfy_c|2;+3Y%NGMr|Xq=#_UKYfmy< zh5=bQe^h;Sb)SD7sl=>*!<-G@sxK{>E9>lviaLC_{dkHV`T)p)7rSv=R>U`lNE~v^ zw;S91TUOfMZ6s|QT z7f&Zm2sv`yylb$F?)7u|q5a1z^|Eo*ZLm(rzf@De!A}9-@L@1yxy*4fUrCYl2VE7B zzU2*g;@q0LqKQ?SZTr!CwvCgIcYz%(|AI_fa}9Gdo>^b`B}(HjIsm%X@Y!{{7Ja@H zu!^vzK+B)NH|tH0=9^xNSn<8=a(mBU(lR=%wNIGD%3_sQKd^cY&}@6ryiL*GKt zey`lacXN=7fdL8n@&p|uuAf2vjb{y#|1_4Q4VqT3mTQfw7Sti1z16)C$J>{4(cV&t zCcApq3;O{LnAtd|XEkz{*|M^Gayqty$}^~X5U|b9$fPzwN4#wkZj@~mEC&>M?%Omb zo_<2`O$w^~vWLl16=v}z11Sl}bB=XeL0eXiKH;7>vu#hJ9Md>{) z5&1$^Y#HNdYIb1a*ufEXr^<3nVpp7(HsX06Kfx^vQEw5|rI}VT5d6UTHG&en)@;a6 zBOYN~fc}NUKe=6($%VD?W*%>q!L@=Psh=bxW=wd}WMTPQRj6Q>KOy8BtxMAQDp4Pi zYCQcT*{^x^A?-*w@3$V$F@bO7s5HW?hki+JhFdOUWR>>05V|+OeXPNJRzwgl*N58* zV1W1@{2Ri4#PjJr$OVRraZbTn(V*SL7^_H-ClrdR@Z3~Ch)iZi;x)7yu?2UV81p8B za)YTKe%Ki4f2^Y&a{PI`(lpy(bS@igy0aE+NSL9>nI!B6qP=;}@1s2DKQzaZG{pJE zo3kN*rIan`q#tko^XZU<8We!F_~t(Zscg57eX;WRSyoM0l#+M`PGHNpdRP_wWa=1K zX+5UMP-K~!>aeE4^7qbg;JGZZX_%mp4xT$7bF=9Zd z+48Bi`^=vAn7gH;z{XbX$d@4+pq5Ye*$aaSaMpQX-D;b*FtIby7skDY>1DQ^bHC(>jne_re0|QfRB{Rntqp0Qb;k%VlmYORN@Q#c70a&7m6f$&efY zd=qF3>qCPbvfF(4uP))?c3^_N{W5ou{z>Z0|Y-;M>|B~M68Pr7dg5$C_?Z8qr%oa!`Ou-;g% zxw_WQyn~E~*@J!s+6_gGM-pib7srR>LiM~&YF}mpu6k^t%1LiyMhaea;)XWtq%g90 zKcH0|;;E+U3T#Yd;rM)voCV3Z-u@9uF3BA_!hNz7^1dXGXPIEjeA|9J*B=rH_{?JM zj1;m|j~0!5j+!&De5TF67Hg@9c=ucb0Y0)gY3=YDJ@+cr-B`q%mlSJTALv&2lx0^4 zWod~u2&P0(`cbP8Z&6x1^_>`Z%|_(9I(PeyHKTUy{hg${it0*^T>p`lxZkOT5bb8uXBgtt+Heqa(p1>Z0DLNd`fWY@^%9vO;C$ zm%NdyQO2+N#-_CVK_Y#=r!)iURKmO-n1a8li6V+nUqhJyaxM{sCi zsh^7|L}P-%FWDi~9#y~B@Rt0dy`=631|PzEo|2`A;Yt*ZMj~YcDyk@N`H>y#BtZ@T z_I}ddo}o@z`JPWJRF+gwHwQnYiLmGc*)kw9XO?+xyg`Jw0+*yswp*nuOSN<5hE&~f zU1YY+qvzO5zu>KI{l^1%zEm2Wor*qJNq1q@n{g}MN8{#2+FNfWVL#6^FEpZPCmN%d z>_Rg7+RFyCgu7H?yTQ=J-=X`jDTF%CI$9dF>jZUNIGq8W<7qLt5|vWlR-GSLqLw zo&XxB(&u@;Ko(C4{icHXY&;%5r0Dyq+q5wp8F?6*#||w{@%x`d_=LzBjBFk-pQ+n# zFOj)c@rs+1&8Cd>rt;c7@^7?(6e)y1Dp@Em0xEPxvScdU-Jvs)+ST(p6P7D|Vi@9*yk}*E|J_{CP7UCDycPz390CFbed zMv^xr2-Ef<+RRDmu(T%F>la37>MYxvS0hvHG;j_g|4ENFN0KWr0G<~JUWblgRVW+# zAVTek?jzwB?M|n=SbHmzoE1CnPOImagdlHb*Cce;S(0w;Y165^O^l@7idB(z0n5|3 z>OQz632_5MgJZ**r??&~PhY~cXus)*$xVA}XpG~nn$=Pn z?W=nXZ>?umsV;5n5fYC>SuK8c)<&+o^FzQ61>a-7iYL^d?_3?%z*g{0%by)W)53l2 z>x=0GGNL#Bqt-cRDFq^F-g{zJv-^pMyv3#>a{Nn8Ee*t_dY6&$V73UIUasIJrS`8l$ksU2! zQ$O`C4p~8`6n-_dQ|E_zQ~TlLt#A@)=HeNP^tyzGna2SMC?|KY);VJfmZ)*!<`MB&M?dG9!19T( zz-Rg$_0vP0Nop>gZ}M(W=mxhG_wq4>@(#`q->lgLmnsR2-%T3pzz6K@Ul`|&Mokh*po)DoS@bKm5BR=0ABv_K zG|M-;ysqEefp1y5^CSa%^4hDLm=n+K)Tq;>A6qSl+l#ynK+<%riCSChjkhO&U-9g@FFl zy&3Ij^lw$cTXonG6CYx?yAxlvpsBV@z3@P#Owr1V@nV+O0U>eMU=hdMnFtWgf^eeo zs(lIKf-wG=bAxGm#hO}|X!7&CT-pk1=g|7M;d(&XP@#$2NJnUJfY&bzI|fa?RuKzO zqcaT%1wJCn2g-4Ocn&Iqy-Qk#f!7>n#;?g`v`P04%xg*Xmgx^Q0w>056w_kEL$bG9 zF30!yeplv{+*C6A@Y&nxvLMzyYTx1*B7SR$=OU^o3eJR-$xJ3872bKik3ZJq_$aV) zRo|)MV)%W3*f#6h{&pQ74{k_Dl+42XHJ(c%-BYhLoW&~Nbgl!tdM-r7WT~zk0B`?O zr}%x5Okdk1QD&+won1&Wq5C^&S8~&YHD#}mOG;wmi`EDM_6xO2Z;)Q?PCw|Fm&U33 zU5qhYoB0Udh0*mT@4NEHNzbvkqJYVfRQzXmrJu0hD8iB!x;TT8X&FWh&V7f|v+d}l zbF1$6+0t);Lwigih`KJGUvtJ0Ws5bx4t8$fts>}en&4sWSg`X^rzN>}EjGcwPApHt zAAv0ED;87g92%mLQ-9~vekBSlkALcPDXQd+;`1ftl#J6`BXewdL<8*(J)uumsVm*z zs`m1NLsBH$gt}Mz7HfB(4h+Sp!KPk)oxfAw+jp%3B_7^Z<1mdQ8bRH=Mx3ZAkQ(4s z2TBalW+asK^M$$f*xmY}N46y`fWnpjRESCk16o{g z%-6o*rs{gnm-v;(K`(5WqN#+aD5Dv%n_|W}QTxy3BLeX{?*0a1B#nzeXc)DbM$z_k z+t9^!f8H&Cg37f&+MV9WdVX;JTE7pXsfDrmeNcq_{RZ^c1lI#^jVLOMbb7qBZQiJM zqK0dSt6w-=4bX*MQEJ&h>^?T0TQ<#D;O&uwZGM?wZD2%ER8i&FvBOG1{=I&xQxJ1mcGdPJqk9mG*MhpDgR1 z?yC^E6s3qYoy6C23Td1%YNv*=of{3b&!_La%$>mQ7y7~HbXnTish8sIk7*a?S5%Lt zL3}2B#p}t1liA+Y1M_EYq4iS)4gk;f?ax%}xmD};S%zq5apjIL6pwDc+}BAv!Xv>B z28f!I*^_!6E+aME*X27Sw;Npz3;cLXa4D7{vKVT3;3I?@H`{q(Z7r6}r?o#s*RJt* z@tTiU{C$+cbc{OGhD}^e#?Cs1x6Ey%nBi#00 z+H-AKk!LR&M*&nQO|C>~D8dsy3H7(N;@W7SB&xg)))G-X{xB*8?%H^U)@`=F9G_Iz z(K#G*3EShK&351U4CTS5my_-~Wdo+i{x~O{B5)0V!{TPCV)Lzl^=IJI_nfQyC$)#}3fQZjDdf7C-!zHyvhsOXru?Wt&Wh3Jxc;s{R`UFK&CdSt|Rg8H(SE@$tB zN+fs+KD4DJRBsn{(gr{sz9;0ArbY%r2SUr=*R>iJ{hkJSe_m*^DfzuyPG6@)SlSON}L+x5vKIb~qY=WiLE6#&LrEqS=+@U?fOPY~{xRqFNG2#R3 z={;v^`{K)WagGXRWV=)k0P}pfzf!y<(VPgC8^l0>O5edcBY%X9>+_{D$$e5?D_DEN zF_C+4^AKWArh_>N_LAS`zLVfg;>u9ncywXb!t{U)M%;#e4|rzjq2=^u;m2q1qMokF ze-a01U-MNan5mRjQMHn_XTsCn3qO~i2YxUk4$;exx}P5a-LM6O4;~~>)4}a;$Fst6$oKU>wl}X`F>TySnab@YY2^_lGW0L_o+ZS33=(pMFM!c9x})Q_FmsTO zqY~VELI>R{%zD?VcDmGr7{D znsdFB`@-jCRydkAcRr`33NE3wAUsq!v=wggxElQSd}({q&j9yl`!*V*fq!T^a}e>~ z2(Ak>chvM2A<8AH;HhM^BcSNe4HuZiOH9#Wzl7yUy_uAm{Tp4SswZ(FW@zJ{{kFr@ zPRqmMhT!dc1#%xX<9Ty;E`an?>e1QR!O;+AN#jd<-p(ZL5Ucc}7iJxWH1_DePF4g> z1M_AVKL45m(7D`Y)IV-QiU_$k1JQjVR)uc@F7+xzkZ#*CI4a7;H2Zz$lc!f;?V~)$ zt4J%MTQ(-})E*5w(-bSxhZ49XC!N$Os-LWjz_IWGT}1IH4`{eOMaq7QS{WtAsKPR0C=U%m~8@*jFosCHXU0?V-=N+fDEw`(Dv?XJYk-zBu z9+OW&Aj?cRYviIu>vhEJmv$FPS7NVPYkoG5aevd(HE7JM&jy`l=V zL}<+LW^3|n3fd8N%Ak2!`o*A*`2e6yrtst%$*M@DR!L~3i+2kn-B&UpR#a0V(3oEQ zNr}3O5+CJcq?-27B-|(N;WS6miV#$7o8u#H6Q(Pb z1tV)i08o8DwK)s=m5`_7G$!p`em)H;TK`XB0M7${V}2A7ZTqASh0D0X0pzu)OHBdE zG28q?XEFta@m^0Ufa7a^7M!C_%&bJq z)W%1J6MLrdi~=+!YFSk zVww&JL5aP5nqdWXjR~-XhB~)dn!-nYWbsN}JHjjAZIaW*C$||+*;v_X`+3%NH(-7f zJ?3q!M^SIR$I3*}W;9KOSBaGPM?k!3imP9gQM2!gEhVMhHy-iVr3L7>S+jwW)UcLy zk4~REI$b7#(;@F68s-Ew%)fDR>1OoFOIQ;i$fddQj zTPP9~EiH#JlN8z32-L;%@n&g%f4cwtf9$aOio!UIVxu@HC{;i}x{d{r zrcxp`D!oQ(q$EKdWmKd}Zz|Fukx(K85-Tkf=_No^Y6wXrAqnZv?fIWGGv`_B`SN~v z-}S8Z?vJ_e?7i<@u6^yR{C->0C3St!3FlB7`Ra-YB0$&2MH9>cZ^`RCTP00x7VD?VG(KpOw17BT>ch~ED%fGO@3q|8K3 z$<*gZOze+xvTzR&&p#=5l75o({rl1X`?2Bre>bl3`~QVx zJsBr8xHSR%CJDhgIYQaj*FXNsCMqS5_gs;hHQY<{?DaCGY;M0q-Z;) z=c4E_rst{{GNw0CeG*{LeFBD`P!8?s z!Lff#ZBAvu7}iJRTlj8EJM1L?m< z{znRf*zU}SRtLq`p~deSXA)U_)xrp~o1)Z^xRNnhbRf5jw|r9Z%cQwmARVq9RIUG<{u3>ktdO<>kq%n z{#XmQHu4Ne7XPf?u`4zv1=JM}ivu!FcBOR>`Be7d|Ngs#L2>H(>UESZN`mo87oYOm zNUkoz5B`sN?Ta?;to7+IU7~!@OcHz*7d`tbXQlsNJ=|wHUh9Li1kP164mDSIAgvJb zj|%){6e(kRVC80D9?mX`6vd@ng}*y+qh&}BtjMo-I&{V|mf>TvA-c-c{rmCT&@vyK zDchscC@JyAo%6s7?E9~;C$8k7QibEyyH)7i5iBEjU1sSYvzIh=u`4lV4dW0d5l1w; zAIW8a{tu72_!fG$n2+eU`nzq3#?(~q>LjFiT7p5JoAVI?jKwYLY-) zApWk+N4vgq8GTdJoczxIy8K}C(m7lI&cg=rfvC_~ zqoe8p@pt)Cn%6yOQ5-Q({@2H3FjrV~FJ|51=zx2EgqC6qiv!GtI$ zCv3E`0n`6g2Uh9K!ATf7DA*Rs{G&qWz{%Qk@;|8zn$w|#{#KY^ zTFT5{ko7gH#}lBiCcCH4Dj3c-9)q3R^0(+;%A8U>V>zxW6M6T^ce2ftpR2KEN@>pB zFf-rU{Ozgs%&c*=HLJuG& z9~|%>DVy zxIXEZSxxJKd{T3ibrwXHNZ%cRpQ^1m=QBh<&=H7{;Vni3$l|9 zr-cisVRD33mT=t|r2gv}oJtwL4M1M%upO`9RBDk%NhOD8j#5hQT;G?Uh;0qa*Fv;a zn#=tLe}`Pp=%_xG*OLL7?|S$u09H8@<)O2i4tjPDJrL?O!m8nuUC^(zy(jLOnUyCv z8W{gn#kgGQVGjUuDOrr77_S@pj|;DMoL+@TPK`eJLFKwljifNsdKsYd(Lb3DoJ&V_nvb?hwi56O|i~nJ+pYTmQ;_QWLw9*HZ7y{UdO-U+-x-w z*HC9h*#*-})o{1y;sp3jjaPnlEtcpr$VlywirRhAy=P1VON`JqIj?Ytg5vP>ZDC=p zB)~!-6@v51ujq94ByGM>YF)-onB|1oO*F;y>I9tmtU4Lvpq)ip7C`?P+)ZdBhIi{^ z6^46Gm-1cfzEy>k@oPED1w^C06He7{(jKUf#Ymv*O@&}AucwbP8}k}**50ChRpFd} zP`~c$JCWxS{PWQ_D4Q>61+gc=IiaS(IpN(%#NE0Cu&}BZ#RoT1e_N=YQtcotbdHkz zD=5=`?>JHT?6r}V9G5ZJ+p#co{K>u7XD8eeEf77=o^kmW!))U*>amg;E(nqJC)gx; zLis-$&MWkiLV>YZxod1vrsXTzFstMA}DSzNn$u1EY76C z1GwDn>5jNq>~g4YJY@^7$trl^pQ;lxl=&x0BOds(On5f26AoW9l-Q_(+v}MDK#av zC*z$xI`XX1m9{El#aD;3aAwSR%ap}wAnl^IbS0%CA-u3O?su~iHNB+7aFmwV6)xJX z55{i+RW5g>Ru;(I#n#-I*p`jt=Ew1>`?3>;C2fS%sZiWXWpM&~7olfpB=WWgl=g^< z&mFtJv$zo z_%Y7Yi7AQ5^#m+P`_6TM&^iqqG()T(t_Po}U;W?h-)Ge7ukk78wubA|w( z&KMXi=nEvqzobZ~4)4p@se%~RwPhHe^sJvIOGOm^$@r>f&0XY>h2i<7B?#7*)&LlO zS4v9HN_YB(;H9=lE`<0iK0aZK|8gdWr3&2}-o3e0Fyr)AURK4}plI6e#dPdymCI-!40D>``Y1jk~!`it*6h{g6vlP20W#1>ojVVQz>!)bTe z#l0r5Fky!x`9*`dEhXQwi1&*b{iFK%NkyvrF|mk$aVHNj_jZSmNiG1Kx|f$*7a@1P zYtN5wO=m9BYLcZK1+d`!(9d&w&y2rw7E(!LSHGCc7H}3z+hdN8pUqZyP&sp<#WK(P zqJ2KB?fFtA#`}pHw7Q@4#)xdrx~B%l|sMZJ!S?0%gNOx#~DD;(E(InT~Xnt&!oh z(@mlH%TK(7p2}lj%)y@TdHxdF9D& zO*f>g_=kQ2`07UvC(m}bHoJ^g{_-;4RSEmd^iqd^x|g3FFa)T zF+A)G8;$LpxAlEs=pTD7>$*LiM9(Q4VJfZZ($WfKWBo>o`?34Br!!$LmI$@OXTn=V z|B;4C>|1FJ3L3aZ>Qvk zKGP@fkOF7Xd88^hu|lonOv$JO`VEdXlZWJrKA^)Lk>15ll)glwiN&l6Q+XxFtFjNh z1FsUWh%@b-4X8=n(hBVBGm3S)R1{W|22TyCr*|!MFX^}q=Lo~OhQ`|I+pNL~b5~9R znWjst|2+pJm5QNE33P05a$Pv~NV8pd8%@UzdR+L&{88!jthYniif2UA_Q7$>#y*9+ zR4SPRQ3!S8q`Id)?{>=(`u&Xc5{2=t+ziF1Z!t!uTC?Id6;AQWXf$h!8}67;BNnf+ z3<#DHV*Vk?1+{xEInVtD2w-NKxsl#Ye?-WJWOe;DR$=;tH6BDkSk$KNHmX0@+~8C_FB$C>U6 z2b9m?>In^U+@RBk`Z%&GlnLbWy{?I7f`wzW?O=;Nn)b-SP56bHCEglY02Tg6dzKiv zD}i1*^zoFt;u!~^xw~^N`c?{;ym2FaazCjo-}g6$DjG%!oVULn4!&<|*v_1@I^ITU z@O)bbbJC#FZcJqC#we7ev|r5*5i#qyi6{8m!%qwfi_sF1y_*e+Xm-m?ZM^|0Z2+sH zj*01cIaB*cA)45>q;S1%ZbD$Hlv96~)E5TqnJQWTTtcV;$+(Y>?4H+$$9YVSk7{hb0%#HwZTZ*wya~ z*EmmwDdFxpQv(yYIW@|hvB8MD(iv};OpebmG$7u@uyxDb`2@d3fOXOD{<7aYoeAh& zRBp@eDM9}-!3Bv%>ED;?&RAEBbXnV~U@*ZRS0$mQJm{K*| zCV?)Kg_9Ho^*BkNORfQ{D}ou$Q`oP}mWVQ&%Q##s8#cYAyMgiF-S0Q33fOz^92k<@ z%s+Ite%R7*H3bT;TnUM zK|E{d&WKQ9Qy=KQ9hBrufZ*{6XJ<>LIE7>y)eGs`bMIz$L4nX&a zIrrlz-CNQ`7{UF)Z7SC6XhNnZkpPLhVUH~FhUV7IMonkn zHPRe*6LiMFzEWf7(E6N;d$rRpd{@6`O@&uoAWRn3e`_OgL3zrMYkjQsUwIDz5DYMs0^hPGrDcFjY z1%Tn{TaS#999nX@v`C$_oo97WCr&1rPwUziQ5u}$VWvqXa^GDYjYYSPD>T)_xig9i zO65deFl=;M9=A6G*|L^s2Hf5jD2c6Vtb`>p>A=rt24*BOUbW_hTl9lb_v5BmUQt|@@u|Ls(324Y0xzE|pb zv1XI~Y}9u9NiNi!;B3^o-q~Vg?8j!_JG`a=Ct{*C7BVQ0W@e&C5?l3{9ycW1s%4#* z$1A1Ux$3UA6^C-!X5PAg1KJt^5^uubdALn^eX6hNanqMCnwJ(1>Y|UhB2%*NC4#M4p|kml3y@cKio!p|8ZQ$Z%uFh44i0|lgDI` zwqkp8FP1Tea9J4d)of>UJ6pCbr3YD=+mqNuBHBnl$2y@t4V-R1=PKSLeoE>eBjs?t zKKQ?QI3%=)9ON(^dF7S=(uz;al0n+)&hDjeEDqgxTyeREUcn*1B^@5iU_lpqFJ`Y7ytv~%@{g0Q+2r7v zlHYgp#+VC9HvOEabc(}d-4N*NbUv?~}yH7VpC)+yV;i50& z6x4vR7(PxO+3w!I^z}Rj#rq||ZF6a))fs$+ZA{jmG&*Xn=Dgj{dCIwoRPm2F*Z62y>9HK$F(c@fJz)5x%fS}v;gheajsHtYN@`7!U}#OCB^WWx z#U-vx-zhM%0bfh*G(5K?cj_MwrMI3JB;s;H0DXponGc?O8ap@U*sH@d``gqAq~#O< zSWrW-*~r0r5Q2-pXaXr}nMovO4Rb`>8vp3tyo9gAX$wcGyCZ#w`fi1Zx|>ZK!djRq z^lsg30DRnmMX>0}!g}f7fIB3jLF02%Y7^eY?wqhTGIxmt?Vecy8=6lH%K@fTUu)bQ!|HEIlRA-`iMrpRGZqMlfdmELQ*NyA1!r+(h z)$Bbx0$ey$xP=>8ZM~P$nvUI_pNVEshb?a9I348Q&aLytYh_nNe{TuYm+IEcYWioT z$gNSQlM>zIr~Bz3l1>QcaQ4uU-T@0kEvyme5+<(g&KHG=LVU3x%cCXaE8%n}_DG*9e}v#-yQRuw=9(3D8W*Z)pNEGe4I6)1XJYLo0K1iOHtg zGAh^#x|Q3etHFP-ixElR)@bK=QOwz|X5Bw*Ye>gFeSI}4M-0KR)ep&|eHeyyZ!c8e zcSfgp$=G|h1yypvtj(9wqKJ-(3h+VT%Gq5wAG5RnJr=S5xRMx>lu|4Dps;Mmhvjs# zpT4+lR3C)OtiLJ|b4zmJ!XWj}`;FWnQqZz-y2qh2N`MvU5Cs=tySig769U+f^GgMm zcmiB{`nMm*IsYzwE}-)gCK2SSI@^1t)L~ekphQp2Lpi9OXX*{U17zG0KJ+m1E8(`M z4xJf4`(EvGqLbxIJLs=JfVL3`MT^5-k05&;b{Itgj?JfYjFU#3cj_XmbR8V z+YfG*3?((h(8e8KO& ziD`79(shIyAxxY&L545_!%Kx{He2_EX;_ZGe;LM$iT)M}VT*UD_ zQ|T}dZx3;efKM^=U65xc{3#Q#@WnfO+1k?BN~PO*iL`Qc%xL@KmmjW|rctnL&%Uu7 zZ~lA)cUa*37@cRHHC$ntyQgD7Dqxk+vh8$gzjN+FpQM+OwO^k=zpVM&eybA|Ef$g) zGS+^4+Zt`bg!CwON1-3=>-pOy2F(6@dWQ3DCeQc!Xbgze29L7Fq8g|JQ=&kl7Sw?R zJ&@$AF8-F+btqa6w%3D_F_u*RUwx zQ9=5AfwJ7_A5sba@DOaPclkw!iwxn`H11HK;z66NE7+*IN3GZsd3Gy0^kx4gpVz z5edR?VnJ!?g`{d?27dM~N=H+_U@p+|@ zYp2EEtKA~MM*dE{VZ?eM|1oZ$&se5&v|f3_zHZRBNTKG!{|x!7BC*Ld?P!VEKKq2l zpgAKUZbMW`kQX{#S(cgx+4A1*pc9=-Ywa5j#NrH%UP>iaE{u9&BW@uNnrb0pIHilq z2&?L|8T$@o?@klDm2+ON8R0!mbgGb0gtIFmh6Lx%-LL5DOeM^xt>r2UmThA8&6-xi z5htg|=g%!AU#YZSP>yk*C_QDR0*RGQr`~w&kCrA@@BjIe!gIKq*fJ2_9nqgQvRFbB zj+sR+X*NE;h7skwc?~KVB8orB;<3J|I8`xD#EJY~$Hf@BD7f~vSh=W$@aMQt&p9_> zWrqiDf%f)2%Npk(G{rADac%dcvu;Kwn2d87KpB_^~jq(1b-ukmxsk>ADb8e&oMw|iL;hc)Y;Y%3+0g?tm{jrx2( z^?mTZe&g}LU*c0rUzahag*aC1<1O8OU17_5RqYlpvwKsI9bpA*(b?5&02SH68EZGb zf2w2B>vBu0;+eXr#2av%*5|7m9U4N8_@ZoOC(~g1kIq|nVPB)uzN+8S=pq|*e@x3& z+Cuphs^o-$dm3k0Hcmy%`Hrt2fbWt$>=Yp~2C%aQgF~_E>jFs4A1rJ6TB&96Yn_8; z!dDL_cB;?e+@p|YUtxuesAijAqH%_>Sk#0h?mqf!6IarJ*aRfuX7>Y|>46ZOhXCbo zlUxvUFO{q+Wz5!F7J*Nz5u(qqduHt2tS!^=BX}#z-|Eeq0mED_RabJs9oS(-AcK>6 zDKhl9e(CfmGLI3(rN^v$1(1dLfKij9LY%B+&Ss!qP=Z{i*p*Kc zg?W4>ufr()_C+}6eepog>D27;3%R;oi-IZFInC1sTNm$+Xzf&S9BVM4-m5WQPAtI{ zy_AUj6oI|7O9PS?_@c(=5mcC;_XfdA^tkjeNDQ^qq%VlZQ;DT<0kN#Y{6Y*2V$**;jY^lR6bw|aY*5hFLQ4TukiL4O$( zS6se=IQ7-^whhjl4^STrgxm0gds=B*Ibo&)V`}F1jCU(sD9ANzu9!v71^zK$c#MlfVHqLIi=im1uowL!N=db4H zY)dyxSf0Xn6wfs1eU(5@S2n1whrG7s^vGT>nXTRKxcU}Z`S^Z9QH3m*n&9u2@V-EK zQ?O`o;J`47!F?{kYV_zQ1417!Pa39D7`AdV8$C^myDmzd>w2!^-nq^PrxL!d7@k+| zUZ2?!M`ml2;-g<=SapeCj(;_~eTrZ)$~@Z+Yfb|%IXYx+47+s%Ad zKfhBgHEGH2l`4(R@$X%0pA$D7g*fvDPjBDY%Pe~rgtO~=j@!ikf=0wzlv6)=JHwlA z|0a*&vltG}{=sN|k>(TK!F==~Qw^VEG3sueW^VsEv2skxsW*sn*^;xx`8gt zCc6X14B}L3l<p`Fw3OoE+`Ez{;i9fmq)H7$1$&)-Mm_u1>;|c|_^>)B^CY{EdhgmI+M_RegtJ zs*vG9`Mh%G;Ak3j@D-2tI6go$7pL`FXrD<-vL)Fz&u@5LXTJr<@50@3 zjF(QC@^l}@6_BNvYHg5a;pH+*Q>LpeM0Yjh5T!e1%!S|J!?iOZ3d34vPuyJgcxY|0 z+hm!!2MDA%rBiv);UdX>)*{lilL-V6+_rREqTV%N+=N@<+f;l?5l80P0nLKRPF<9h$%g6H-$6J9|L z>~$ie=1XP@B77Lch62jDL-N$cMdJ($PUX*|DZQ#3?2c0+AA0^B?`z&VtrC$Mj+aLY zrz9G^7FUF8EM7)zqKS z^XfzP_?LK84tK+6s<>B`BoRp#ElG7F8e-HY;KP}I4!zh?*HOI5x1GCGpxt-~@2Poo zu1MUuk!48tRj#!Xr3&cMXu@WDyqe{umg9gjlu<3?7(+otirzwG_(Jgv7s8+?P@gXv zOfev>T>r==@?Fw-l>Z4W$ViB^We8l;1I~g>`HjVb3A>(mEq;HfEVx{&hhUv zB6*LrUIgBEBFy0@JFlK)A3a3Z;uoIh^w@^H(DYjyHKc^KBKT4piNYBey3vlr-C()5 zg2V`N&%hCGT4LNqC*E%#55%dLa)Nn1x^p@6x)X7uA1roeei&AsWD(;JmNgj^| zb}pq;b4VSn-bz&=0dcAFC z&6OQBJT!~Z_$%hyFyFj-!6;?wNbHNK0^;KnPy;N6|io*oK{kGpCgTVCTo z=_Mp8SM@Gh$$o4M^WHn1&b&j5D5@fQr#dQ)Dw`QvOSp}Rweg?*zB4<~l40N0#WP35 z>yziE{Gz%B+C+MU`TcZLfAU60zD3|R)_r9A5MX?n*nAs0uYk{{)+o2CMwz=1!cU_1 zu@y1r7r`S+V{OrIzsq)oJeiNZwtlo$dp>tgYk}kFDgg8je0d1(op>^#NiPRY-VMYl z;+iV2=ZY_|4v`(p@36`r*LuzHDXby&L;A38K4huWc>UGLeh7wk{TtE>P8}Y18Pw}J z;3UGw#(p-m%!R_MMeG3WPNvqYL@ENM3!4{`$V3|3;caYor1wFJ8B0h)-K(Bi59T9Ue)nx z_2YRWs&;Tg%SSu32;|h&A6x7rXiQi{n2A~BYz+Yk(5k-0w|G|=W6$9)5F!-Sq9j!|J{Ow4o9;ZwI(6WcnrKApPe zK81VFd;5z$pgy{y@6KB0C&sg_Vg~2@Qi5P zvLn=o*ZCpY54ze;ot+aho{lD(%{F{W?f+H2sx5@yg--Zzw$;eJbL;-HFDr1jb?hED z_N8zOPKSCS;o#YiTQy6~f9vRp?~kSfm^=W4*r@ngkb~I!`f}WXL~RZx_%WNwy!G=~ ztK4Hp@4bm|yPQQ)Cl{)gBoSF> z{FH=Cc$2O>^bFp-(Uayo_2H8rZBtn3FPYmo%s;;lcyJbdEU(mV8{;$4ShIqT+yTr_^%toEF?kwVd`oH3S}!eyd$fTzP+RN365+6Vr61s1^YhrywxXYR0p7KzG}IepkCkFNGlHLH)TL` zrtZG;a=biI$nWh#XbJKdXs2h{fgHr>!A0 zf@5m08O7||T@bk^wKeN|+Pb^}5^FV&^>X2jwXY1E&tA%?r@WN^P-FJ53I}%crxzW$R~BoPb3_ITCQS`rj4^fTaaJbI2tAvnX9GO1sXGSGLZ@YF zaV(S?Oo=+GuA2&2Q$Eyqslmpo>Z2%rrNa6J-}3GV$#*RQ&0;)kVr>vmLElZxv!7Ml zmJ?f#@?VO+kuoifQFU@HP!bP=8eIHtc3(fTVjTmnksk=y7`aWb7dwFz6nA#j)>vM9 zM0uOVz?Q`p*US}}Xmn90XBJ$(zM-Bj;U88H#^i!>rAxX7UZEOdE`rTH%0@DGDrp`G zd&!=3BZ~LBD9szh%#7CK4`)+{;J)B@heqX=m=|RN9pUp**r&-0FJd5svwY{y15V3h zEn*LGJ^jt6rrA~Y9Zxtw{vezqb$<;E`mpTL1^^_WvPipYgu^oM>giC&b}+Pxs*VWZ zpB=Nd+}J2Ydyz5_DmwFTEV;__2=uqHi};AMV?zP`q{``h5V#<50$Lnub!+-l>pX*m zj35jN(Oy_*OUrYDw%3JG^ss{*QM~o3i;u={rj5K{-BL@bmg1OcP^tz&U6gmmiwFuYM+s!# zBy8i^k@Q{Pcg7jU%&-q3^>7*(*s6H2%1^ZhKD{v$GPiKW_}@}_6KTBCW+U@2jq*LW zl=~uOUf{SR9Q%N3C-@;{%0r3)O7hGTYnt9cs^0<~iC@<3{5#P4H`^Ww@!u^^}xv^o1r z6s;h_Ujm5fpR|sg=s@J)g=1H_pDmx>2|XX~f`^q+?)-9!cY8(kfVqE3(`YAv;IEdH zw^d;GeD%;O1dmyI9eT&w>fL6~{vJot6`ht#GZ%wXD8iVx@C@^fZ2gA0a68X9kYloC+8b=ej>l0H?(}7Oe3tJH=CV}LL`$Jy-5MR*DuP{)CE^XaY>=ERVJXl=_>5{3 z7o6=)d)|KXm*vGtHnfaoVd=|o<-RtaWwtDbHv)eUD^dQ}W%y=$|xPVJe$ zYU#2y9e_Bjpy2K^-h`>w^o1!3Y84JjKR>;@rZ|i{`b>C?`yEQZNOsTIWw}(M31FWb z+_irlqkmAr=No8J*#7Mg(&QJXDA*B;4Zm_y}+nMwLFL`wz@g$3i7cxUwOl z6Lo3do_LW}n#C$+t~sc3iXO=}$Wz5q1Mh_tdEE(KO&4GX?iWOlhLc!FA608|6SWpl zZaOeY6;vo6$Es=yO(eXin=5=W`6;nkU9b97<#>chxM^mQ4?rZgFOx>~KdINqA}1)p zMS393bBT$++xXA}#6~7&XQ5>{t!F^OlFqWy9sUj6r3y{>Vik_)#V+cRV6N%Vuo- zIs9`5UPSGICSLJ=7*Rafl8=sE=qp4su5`An&d0UDCtQ3w7 zn@tcxbjd8@llq2qBY$RDY|-j9SJ`86p4Thq>GLuxsph(MjTgd(%Ii{p?c53%cGexN zRLDDYeM6o;Fz>axJ$L3p*&Rd;!R*>;@JKIV;sj}&YFR0@A$ykfQo|k>~hNRGMjbu3l1et}rOid_Pz0u(w#Pf8&0#d&{ z`v()>rXRUAy)X!?Z6%he%Q7kNdYz<~#jH2;TXcSTTXuDmkEZgAms?)K45y@*?4wDS zSAP!~80%&9MA)BWhFU#{t$a4F-eoGJ1jU(PJM%3Qw{%A&(Y(n0hTqcnJS1 z{TpaWje@yb<9tRVW5@N1qUf!&J0nrH4n@zpSfq+lt+AbV+Z`7lWUrD^ljf5lAMdsw z4RmXelkchB!tA&Sdfkw24KB{CjK1PpX~jE|hyc*eFHW(GdwUnqYw)w;xhjQ-g2Rq7 z%4WY=T_N%x_TO(Pi%jNmNTSNH>UAR=20#}mhdZ*#@Acd&a*0=FReD#&o4BvXRpPtY ziHNe^^U`fh)(O-V{H_W591GWO2Ls>qnw}#Jhfr>y@yY}l-U+fg)A+ZV*b3$`F((Sh zS3HLJwikTVMmoBGqm*~gjU`$AFBPo_`7N3bgok9zXa=p0)7fzXcZ=l&G zf2m8qdsfT%bOVa(B_xKz>9a??cw4L06u%Nd|GI%5K~Oad0d-3W7L?4y9`qw}YOQm9 zNh3VEqTjrStRHJ`Mw`4-=c7W`HGa_e`ezi@{`;o=fu45nkK-=_7BOVl)e$zBk~P#R zF@PyH*~@m@{d3vGruk7hb76%5`t^{W5|briVD+=ku5@)A!l4{?jr$g}0b#`X5I7U- zisetqm?6#c1m3%J7=SZS8;Aw2w)jQn)#_SA44D~N*&KJ1jP+u1k{*6jKbQ&`j?r;( z#f9}oNFKqhd~1uEi9q{dobsYAX0M9fdml${$Dm}YA-ihKx%3tKh@akPJMVb9%pANCt~ zV$?{JkN@Qu1=Ce`OA&)|3R!TxVztr@rn46;ERUnQkWD!iq-^88)T%_zdVwsOMI;tcD>ZiJFR`n{EE|(P2{mxPp1Uk9CH8D@{~+-ow~;F9HT)+$CzKo zr(U+KTywQ%kXdWS{$r;t2Db(cmtN|59rt}>?pxu{qY>A@Ne;tKZOW zDRaohcoxF_N=Mb@EJ$%syj>WVim9!W;k&yk;iwbY%94Jbm(sdgUqda;660u%D`vGr zBcX@`DI;0lxKKsy>Ur5Cl(FB(XCJq%TIlr73sATeyM#;27YxEMC+)urbekOfoBaD0 z%$J^JXSqQCXFDf6g}D#mo>lPPwm+hI*mwo@x4OGowx)6~yLHrsKraU!+(`*tD#BhL zSmb-wTPB5;EVT2z;#?6?hK4NM^ZVtkU!KEl zex)zV0^VfNb4A@shj8Uh<5p-K++CeGTbnkzJKU2gLmrkMJ^m-?a2=IV z^D9P|j(@c}`8x8xJa)#*3c7$PFj}D9=-)xY-THA6D(3Qgj&Ns3p3)Nq3(NQnvFKx; zQ*R3$l%~jn z`j>XsAZ`6vC?nu*(qyFjY=g6de&@@wO+x>(Y)E0G=b7WW(5{}GSqGkMwBgjmow1rr z0hjo}iOQgCmJ}Ispq%1$!7KW9IKCq7@S%7E*6v2&j*z?EuW$R2K3vXN=>oJ+U8(C) zFV!S_@vO^SUfcuA^He-CnG;JuEaTS=z8Zb43W*Vx+4k^ic`bKJ920JH#Z!Df$+X6N zh-2M0e0Ev+4EO8t0>Mv@kz13AZF?S{QeRPdia4VxK6%g$G?FEse&(t>P1c||`nS6Q|3mMnyvgGf^|0T63g@4BmOSt-eE0^!rfd*e z?-DYGOm=apZNVtV;a?r=o+G-{jyu)YI9eqKZ7cNChpSOJLeLej0hS#l*DbuEc65F6{enlSsG`elCIi_zP>q6;E zqs)F3ANuLdp8A9beIt!E<6i6zp^i7?E5w3dgl7CiruY$yuGD&s2A8_V7EUH6MqXeu-U-U}~u321dM z_QSlaZ$nI2LcWdnuY>i7%9$*uXA0%7=`FlXAXA8K22nh4ENlR#a58{Fle^rjwz7Ye z$+!#UXXQSJSN^(m1k-0qZQ8{6 zEjm@0Cav8|66+w^IGF-BomMmN3;tb}k4aJdFD15*ps$cg5|LA;YtRVXPQ)Q^R}(P8 zpG2=622jdrP2y57M;i%amt6Z$$MAeyOm>|Ws>%UPMQ%dZp^tb^?v=A4y51S$%@iIM zMV%!{tJ~k0+M4u430!<-R7Bui*qHrgYxU{|fO^JA(ry5CkVFQ^@FZ~sI#9@f{Vfw1g>>uOju3~jtd#y0V;Ro)Q zv2R!=aEb_(kZZXB9LCu&OlTns+c3j_*b=i$An;+a@5#PIp#U>T@P1H?x}Rwic@^eQ z=p2U(-2rJOdNi*{+%7dQb4>k2$6u}rL}YViRw}do_E@!?5KgjOE#GTFK{rB0K7kHB zBx#N=|4n5j!c+r%RPAYNS8{gqg|uNd_~gaTibM1ifdhW`>#4B*v4|F0;gsX%__B-h z_84~YQ@^4{>9JOIlRm8Do#_H6Lrb;2TKG3lmkE{Qr&qZAFQQ*P>7S^RxfAaN{N9RJ zRtMP)@HYB|v>aQjmdRS*{8ns&X6K|ke-nuHo^d;PI%l8d<&zk%8o4R!bUzhYeFfly8r+Oo=5u`P<^!k@E<76MCIoi)0)#`lqz;X_m%YWasWhrOsC2qxO z^ddkFci7l<)ZBs)HXjAyD?eJrab{l>^*erz-DH~pHrvSws*%+YapBWD?@wVmZ~FhB zl}4?GVNl2@qPw&5Hex13vxHG~wX56@d}>fedwDD8&2S0x5kNhybaOV-h<5cq`(b-3 zBraTwSx3A-Z&kY&X6!sfnh47}QJ-({33^st*~Ghv_SxskAW5O#Dv&nvSX6$>aJzp$ zl(=*H_mI@F$Gtt6K@d7_2NinxrcxvkR9U=lA}VM$`?$=r3p2&_dnFq;hj8)?;>Tw< zKF!=+qtOIC>fBa8Bk%+64lPYN&QHsD?00GYqif51#@D^t*&Xlyz3BHMNdWR`QEP(f zCntmvzW4*;&n=&5sWWm`Ibx!gYJ6Yh*nDmCOSZDbV^7jlsMVj@+pzMFr~jlgU+VXZ zT3$IQ08mqmbpGrrU}o>3H9aBqE4esc~~x0o=KzmQOBGqlirW@D}>{n6d5;;p~pCyt%}*B&?}|GZS74vXac+3tff z)pAD!nrYM(evUsLA3ZctQ^Zrqi_&b!{#NS}}J{ zF6quuT?tcOd1)J**n9cpDBKQ4B4)7mdxldC@p1TAaF5_UEwdkl^BAMH0C~ z3v6E-c2x{1Nl6cNyg=1Gg^(0Bp|#fT2D7183vEYT0!t&Qs%};qy76YvC7MbvKcak+aGr zr_|jK5&bB-M1Lx~a@=Wie`n(CLk{6vOM#-nZqP(ERDaca#DCoB#cRaqiVt$2pe?=W zRT_W#YbEH6+`=aODW_+028iCQxXr{+XWReJ4j zQPS_qn6|c>;IDk#vGSh!of`F+oqHEHOO=KeKkLbCs~*$IiFQzYGy5QhN>;eQ+B1!S z!CqffR7eHyXpQr}dPvt3CDR^2>043f&fy7zPFh0I`g%coef(l1S{H;(Hf*ovDV6K1;aBTVUMc@$ z`*8cxfitlPabGecHn@&kmckCW_vjdRhemCYxU_xNDU-7h|G0OB;OLhu`=yIsQIEHH z%Gv3Gi}6!NcxeC#lG8nSLMk)=(y+AY@uL1hFPfuO4r1oew#?m!W@d)O4Fb0tis$JS z>?TArHQr1t_()%q&Vflc8lNn69=(`YDvja4G!1(Oc9CekoghPuZV~^APmXI=O{!an zodzScQ2E$9@S`YMnAXIMYM>?e`W#tV2RGbz8yY1zQ^I`&SN|HY3bD%S$uM5%Vz0YS zWu3jijig7O0@0@iJ-wl#54sCubD_NE6oulz&uJ6G#L>9(scEa6^h6zuWqTRZ;fL)_cjji57WEayP1!xfF<)vLcrCTf%;kWeJ~KD6tH#4WZRg=T z=&urAkz82(5Pi|b(zTW}#i+2aPa2{asd1>}5GhqgrcUF>y~z(Ka$(lAt>FS}AU1(L z)fMkDcHeAra#o$52i^6w+q%UP(y_HHTfAn+bzHf46<_Wz5y_Y7+?>%xUmR7O!4hf!3dC;}=?P(WG$8zKlIA{|tE z2}lW%k_2@WQEAddN|fG_2ni5KEJzDQx=9F86FNyCKtd9de3^OYeaH8lbDbaGb-r_b z{D2=kZI`w8+Us8Ty`J~F2_w%;#f-i>?C-l6az)cE%ild31<1}Y@}f(js~8kPvz@1r zH<91*o_RB+mbl|mQFLVZ$%R=xsk=qSV^Ae@Tw*ae zG1tT^BlWRuudx#?HU1oO%;WMh->bVBBAvKcUfGt_h<&}8wLbC%arZvA*{m9{Mqfml zsV($QgUE{!q11>TUN}VU*N|J5WB62I%dY%PN9+(Me%}4Zi`Ao{ zrd2i4m7Ih?Nx1t9ul55?sfq&YVp2{&aFI^Il46`=r=Ik>F(e~Faz@#`H76&I*V`?{ zy2OqiUMrPl<#wU+xX*Bdw1?8T73reZkwr-VK-fo?N?~iQPWc{%(|Tk6>;644tvrvh z121lTH49p6_!3j)WUr_lVBLaP=0oDc-w^5#&pCD-hC~Fg>7CVfKYWoD+T78XirbUr z)B_9Y-)-j>on$wAmn3gsIxkUcSBGjJtUR*O&d&@-!}xQ_^iF8c=9Lpc+S}DK_&nS) z1`0HnXt<#;>aOw1Yz{0TjcaMRgsmRa$}G)um>|=eufB?AAqsL-xS!*B_4U%@6_gOO zJ%;na zxO9AF+$5!?U{b$2_S9;LtSOkGcHw@THFLsLvB!+%JEAre=jRVdx0TP2XPxKZFY-ev zX5G)P7^v1;2`hu`Z}qgxt#fuBaQg@_n$6;SXrnGK=H9*mC8T6zGYVaFK4^^J;_NNW9h7#ns>tq&b$ zmNgV|N_W44dA7ErscAKUN0g>cH&pBnjX!&$fcwrLkS3E0dYMppa@Ndh`}tz@Tj7Nq z*sX-sPB+Duz|GYuyCN{B5WP1GHvzZ8LMK*E=TI3_4eJ~8dSQlf`9Rhwovrq|Hq9wHWVhvy<%@Bdm*F~YvxmN6S6-ZD%Ul~K&9BKCc@8k@n{cGQM! zOWVh=<*@?dmve0F<}5*9;lE#(r}5#6DN+e9Dpw6-0*?zPJ{z-LVua;GAF?EWw6t+E z!Vd177*Ls#JgCCp{kCWeofWM+J&1+I4~UP`8>(vWbSqUq40Y(HuThVO%hov2)`L;h zd{g_y;SmW>Cz-rC`oW3)n0qJ#D5}J|wQoSBx*>q?8eq)zIg5G!K3>@ViAm_b8}+Nb zi!^w;_`Xk^^%O*3U2)xDDs>(+*e)|V0migx)VK6h)IQX%tFm%G3fD3nAvJfuxoL*$ z9mkIu_>`Nv94a696tQW5?7s=Ak6-`LGxu6e;JN){%{&FgI&v1M&zf)-%}_n77UBytJ> zW!rh#p?n=5n*lOBL%%v##q(Qiq}F>@XWAbpPG1vNOmaIMpc7Nsvof^NzOVr-ZJvCQ z_u@h8p8S!=skwBNCAFZVAvnGWvu}%!=G)YHnpAFi?7sDt2gpqIXGK`ym1HlzHZIg* z*0RKZ&O7prP3&Ku7HG!Og7O$~eP(`pXu*6xP2vUP78@$eK#kNp9j{`1%;?$9!+pch z$uo-Byowwn+BvsgL(p7wwN9iv5R8zYi@`tI0(l@}?avVZ3oe{ma)XdbmBw z=-G_eEVUWH>f6MGD4JmPJv9PaTuFZ(;UA}jDI6B+g>M>=F>asQh_UHLk!2og)05X? zJve~+eNFe@dtb9NmFob&2WzJG9)ghU|EFua?JVqAv+SUj|R)YQ&6)jL!Z z)vws5AfG6)J?+_bYCpN1dl~45-uC35x|Po5D;zVliB# z|AW_d6OC2JLS{d0cug`n?cTkr3p?)OhlvUG*S#4E?518JX zIx*(CjbYEgGKX%f4<+?})6d)-bVKW$tD#YycQ^|vq(b8@;GR*PawIDBpf3c1vY*mZ zJovSbOFP12Wudr-b!{A3 z&AnUM3HZuG_2>rp9<0{I)z*i4p|Bzmz6B~ir@ZwQ-fRLNirVxgl=Dx{#MrvXu_JJM za-_^R3$BeA^j%>4RDKU@u!_9D zX$#8B<7q?PKEArj-QDgsb@4eT%|Kj_en<>%hIOS|xn_}5+$XRg0}qtCc#5un97Dx`rHdF?bWttIu3Z`>S2ZF{LU}Za0%qZ&{UV~D@Q=(Ih@2t2fqC_ja0&E zza|3h@y!vO_}u5PSJfkaJQqCc@fBqC^bLKRH9eV8!0*M=WgddrHgUW^Yh;-z9vk-dyKhtja6MUf01Ys_9gxKm_}`F zoLf6Kjl%F$hrs2~Ia|Kzs&8tNTlP#DwE$jC+sH}9TgtW`tA{cSV*~*=$TRZYES-mvaku|P<8eOu z7uz<$wTw!|K$sm!5@J5GtMk63{21P_ngZ>b-GTJ{Y4CV z&-^c`%v=A(7&`D@%-zZ+HOE65P+Er9}^zWa9u&OLY^TG{h!CIV9OSrEJs za~5^#8>vbxf{Iep$~8`hV|~n&e&YPSelO}F-h=Xqa_T(R5k5cY5j!JpxMIwoR-8tK zL6q2PSciE#DZ9^G#$bzMaL6&CpHMzGTQIu{AA~M9Z2J0nzz~-F8Ec;SXN|ClE@qfa z2EyBJEf2f7-pJRlZrVbX!zvgo#zFg_=Ks}B#{=eqhix30b%uu%m3A#X!;Tg#u!ZbFz&>_UALIy@?*&gnqt1#Hn2NL4pSzCRl~Gajlpl7*U6+JbgH3(R zQGequ-!3!Q9r_K0b_FvBqhb;FO`F>99ZRAN!$zPN{>OJC?@zVMFx_}oPx*ZKMU-;f zqaA6*UFTs+YJN)+;{je=@DQ`J)C~6UZI{W`Zf)C_-x_Vh1YB?YZDuuceM6IXKKUm` zofuZsoc%2;;}T4@g?Bu*XFA+t(}QB`?d@uN`03Vam|$dQOdKjT35yv0zHl02zqzudOgidnxD579TbPmSaYWvl3|J0J7~@(HD0sb@`rB zD~1?7fmjt{Ga)zhe>N#-wJ7MZY42C>l>?U_`7jF08DI-;nV~R+8FJn-!<-r}&mWL! zK? zVAQV}2|bJwWj-uF(0yqtd=rz&hL=yVf3}+h^2yyw!Y~mW2=ARMho$8Xg1GI^3!h9S zh0x6fUK1t4Nli{I$F`JAdI6sYA6289EAY$bQl_!-{OrjuSk7AO8aoBYk2UQvPWkgN z#y_y+Z+3>^s*iP??<{fcstgWKKzfR~aF)F}4((ceDGE5m)2v-ZjSEyjfcMGn7$Wfs z$6D*rw;DzIpRgC;_r)I6KkQyH@-OOU3GP00$v6qbl}L`I z#h~B=l+BUV&5N~syT0zuVV~%k=3DqN2&uE0uJkaow*4e~zAtY7PtP!{Hu!1r5UY6f z^Dw{vd0`Pd^yMJN?i;4Z$?D#)(+f9%dhvk2oIneTq`A#6pQZwULEpdj_nM;z| z8JCa!mUQ80`v3T6xJXsLdQ`_+9zCjKBad@Wx#=tBBFhr3J7F>EkN+1p{PmRV^TRs* z)B7)bg0@g4iz$59NP0ppuB!^qjU41m6#!HK~%h7Uvr@}u} zUFV%qA*W;15GfF?QjsGuzW1KfOQV&qKM517C#8g|dKX&9$TFWwD=p?&p&yK*!2dkq z{gsUP%%+t4T3Mp|1ujCfuI+}g^H2G||Fa?9l#*YJ3b&IN_c*BzNZ4dsdL>IT-{lU{ z%Ky3MZN!{&`Lno%19R71R<=-0&0XH(GbsLGlRF@*Ysf`9&Z ztJGDh!S3gI_I9^M;#akwmpSJh+2@xs#1Ipi`9@JTt)hbIH3KYA+ee`tz!rp6G@ZTo+2pIfI%T-V~uw#<(mD^&X%{t5|)ZvV=YS}92*V) z^%3ubZ{LBh|7y-Ul+I^Qsj(-~E?hv9Vr{gOs9;rCq#NAkYiip$7^=o2T{*QjCvF^x zOSk6@U4IGCBr0C><-C_N1QDS(7s}Q|2f-Nll2@x%;!#w6_ld2W&gnBgb1r(SRSmv8 zw@B8zEdR}{XqQMvEIul#5BlKpyGT)4nXFmqyyz&qE>Z5dBBwS*|8FfxjXxeGLB`LE z;j3FRY9|KQGN-=cp!IsM&e)82|`s@|y`^HF@v+6#mF!NL~^2?T==iaGJ$I*9O#sfu1k6 zLX%JMG`KN2&hlf4=AWPv7G&ohj^J7xd3`EHEXtlC36CQB%gg zuh(q9ej#hZMw~2t<~DE8_vSf*z6MQLCi(`fmGPbSZSB@%&nGl4VxYG=pw|+i`8;Jr z=ktB+p4Kk-3;hwZ3dI_Y5jCT$Xvp%HUD!x)?3IDSgXu|2?*a8t%%L;F8(BpV-#72Y zm{oz1e~;Z(=a*moO}C}BzcR$fI_%KT5%zzUE$Y(KLVp|Pe6s&_spkVTqvH+Mt)Xi1 zZs1!3qm$we8-y3GCPpG$qH4c3B)bcUvBn>seHC3Qodt-ZTzZEKa;iZpwXM& zt62>$0~BMMgRe%7hpF3t>))PM?wCiPswBkb5d{^446|^RoYW+Xg02eE0ya1ktB{k@ zAG3%bz=Lgf%))1=ML}*{^nL5lcn8WK3fB67knv*TD|#ZN z_;xB2m{~6`3!hXb)$t9lW{o|!Y0I6{KI!Eqh1WNZb9fxZIo64#@tuYj`yv=kFcYC? zoQIl6RdNe3z=>Bk$&v^=@54RkWyF|4h1%Gr=&TbHtI79-*UI4&lPS7A&{v0uYxhcd zcRuJk@Nb3{6LPqn_nq$+=Iv4PXJ=W(dR25f6V1kflNxRyxUtNy=34)@1+ib0P#qtC zFEYk+D?(yz;D^W5B8p|^v;x8hQBpXU$eWnGXP7GTm!B#;Te73^^_S-q8aTE3__zAI zp1#arX^BNMV&~`VwgrX4vuo+cRx{#C7Qa}?IFE3Gx7C-Gp!@68dA67RT{SIXUh4`U zi^x}{E+_UR3h3z<3NzHI%6-0B$^8+Iwc1vz-+t}j?0;qQos11R0_&FSYaU!*dYsZ zo`HVF-9bWmiMHGm+==dI-#J<<~6UbB}FvK)%F`9C$a07&kG_4}gDP1ktKbsn8el9jB{!uLUM`Y790idVL_Z=d{ZG$gz+=|x$&JbQWw`AS_~Pho-EpKQjqB4$)2FHX1UoNizo zN1vVh@htTc3?5tGzK|nP1jy`zSLT#0x{Z;O2JW@lBs&BvW`q0;dsfQvtn>p6ab66G zR`DC#K~FVqwcUQ&7-V7TeRyr11hSKw*;?D*1aI9!UBV1oHKukP_$>@>t3s*3_W$jF z+}*Fra*^KRqYXxY+8f)`S~6Gzq8&yJIDr#LvQ8H-Yy)1r+p|4wjI7u*`CTurr3*Uo z%adlAX*b(U(jL*CjFBt2Hn5{8{|oz9F3dpHL#`MxH+KSK9Ta=l@^__46D1iiEs@Z8 z^7JY@wQTDnnf4*lof$Ukv^V$Z;RfG1NhR{Ta7#M9IY~i87N7ah(X&*P@nag~3^uN6 zSyy?esufmc!$W|h3$tm3;H6F?c_^cW2e$3>Y9KpK%}?W=WeBxu_>LnMX%b@*5g^k* zo~X1Y*w07bh2ELJoA#WrF>a9~n@0|7Nx0L{yyVIZAU*}q_0&dCroc|pn;iTO*_W|* zXK!&$>sOjfxSi_Wx&<0)deD$z+?6q4`})je0}ucTe;_AK@Dax4LcjWpS5>}#5$yDx zvb59~B+e4bm6Z@pNN-loy34-4;&E2DIy-Q@+@UNrRpB&kxv)ULo8C$BQ<$jFZn6;8 zp3I|9daSXqS98XS5&U~xNaMROTEqRWO^o+u7ArsmL!%^-;IgS;MrUiBzCxx09?i=m z?Qj&JZ3_IfcH7rU)02A1a^_NDigjk?+6Sr@W7GUn%tUi$%-e>g3pS6S^ZO4TNC6W_Ovgnv^7v`iMZ#GU$K z+ZQL^jro?)Tg(xO$_cGjm_{{d`6H9u-$0&+-mjwGFuy%Cu+fWErw6z#5lOJctsi^Tv|qBnRSAf4kcsAR<~~JgyBb4bxX?jSTmaudC@=MO zL^AGDyexPrtLd@l9;x%zMOj5)xu|Od>Su#Xv8XptUU%yDbOh8Bt5vm+?eH16=!&YP zum8H8QW=a(LeIDnCwiMBYy}<{q3yiM9k9H=J?pf_Qw@W$zbM7&$$YIavT)n`tEd1# zml~P0^R8?_8~b*k*(oJ|GtFJU<@^GXzWssW{>9h9uE+a01uc-`ieIPOI>;_XruJ$b zPgIdqnjlF*)W&mfAM7n{=#UQ#g(L&Vz%s8k>Fe9$dmpL_lnC_m)=eW8SkGxS;ppqpo(KA5uiKUGA8PexR?s;0$ zXOWFHucVaF&=)ZsAd_(woN_%~{~lu(IQvwBJJ{IIOn&vb@9Hq-y&pROi$@Zc#%yjCFNHNeO}Knf%n)!Q zubC3SJ(n8Q3|6RWq>Hp`#f0l?+EE5Ui(Jb&q*k_`~RdpIw)Ach2Q|JLM?bG_~l2LDG zcPnwPwtC)gI4!R-9PiVxuL9O%%#TT)=#LySszQC9*5iQpaYVXkvQ2*k92rM61f|ExT(;JS14 zGmr!Voe>92Tr$&9mGR3fA8m~*GPf@4dnRt_yT}^#>R%7ywwH5FYg^ckZjKa-fNSbM zhzek*w@@|uYxn%;gzk>Hw})elcy6BoT($*Y05+~`23gugJ)!>=?H#{l^w+D^W*ioF)TaenqPa zI?ag)aO4HjrKnFgv$v&5{%48J{Pz+oNLplKhkCb~T)8NQFNoKMxJS`-dO!bQ|9Z3S z9ZHl<`}SSbL3|g;FCWFQpE3!s(?@443c!1Kwtd=H#9CO-$X3bIZXf)r4IRSUACg@@PgZX=b0!^RvubQ52fV=XNC-p0q`X- z_&wPgO0P;g4N0ped!4cPal!Z<1sEsHY=2+08Q!0MB2P{D_4jaK>oKKTQHQv{ScJ$vx3?>p9AlR6}_J}Vq| zMc`4K%!nO?X5Khpt`+?E=}+v%->ynMSFKJ?jWkBSNA`9OAJzlhFTCedAL)M~I#=nI z<>w@k3hG*traAk;C94BsW~!NdRKY` z$%($l(;4$aTkx&+_1cg-m@~gPt0%a7CW27KuY&!1UMERzAS+o}nycy&9or`O78!Av zYQ@1kecqHsq^uv8KPEbZ673Hx$9xJaAp(Y11c7%ppZk8J4SH1zcw6=#acI2GqKL%PkI8i~q9olI~KZV%eT z*Yik(@+-U;%1UFR(h?H=E`(Gj$a6)tUz>smwRBMn$bxf#>^KZ+_pAhU3Q2S}SI_^JT?OOKN*U54*006!*92zw0!)V@mt+ zj9Wm-MMt|4CVDs6S>aGqFl7*Pa62k;3-v#-gx9zK4!Kmpei(6{ko0JOo;7r`qoPg-lkOL^C4pA#V9<7I{1=nA$uNg-=pL-dYeY8_(5Ctl?xDHI<9uI_g%8!{r1f`d4NQr-9=9m8rS zm^vTrb~8zTW&U*tBqH_jycsYX#M*qayWp$_FxD8cMOJq7ns1|T*r*!X^I%=LY|Qnc zufMKj#l9{mSj=<+>m zleaFdwiiG#SCVh%*~q!VTX|^KSz}`j^iqUTO5x2Ig^V`_5WxFYanXDC$wA3ZC&=C>z>!KpMdyoJdDE2xLkL9B(S)U~ z9gk$&CIOmmK1s>OfZ?=km+ z@c0$&{E1ykPV1|!MElR{4h1i!C#E~q#~3@V6Gy+!)-Im)>vGg96D0E>fNSpBgUL+7 zGSy;!LB5B)ojxtla*#+0kL&j?7%uH1$UqS4Itu>c-C6%}8bbb=g@l(TqG(>&w$p1n znRQfeZN~GSbZl%%_=EMSL|@!3QR%U3JEn}YckO>={^QNsPI3~)=hmQ#{8y8LW_0=9 zO{*R2=g8*|u+WAF8Dtr(;;4%J*?H@!p4hmOy#dJ?1B`^{af(URjByiHH)DdY1JMs3 z8(=;#wJh<)Ro48bC}_uu&g_w3Ox+hN3y-r!{gYmv;!grrz{NPy0<5j$iVD6 zwyxTe_WA{j{E%yRBCa7z7Q)*ng-%^QbDf#(ahUYMw=CHJBcir@tTO?*M^xlwai*d3 z(e@c$LDi%qZ0JLI^Hm#ZoWMuEwWRk)cL1x7ZrF0~OuOb{Vd%E*g%bzm&V;oru9q*` zunX$gb=?UuHNbyQp3VqKhbr<#ipB38SB`lZhuq08kf&LtCUZaT)6-9ZKcUC2g`)ed zwJsl)$T3Z=#~6LN7Z!cAHYOxB|0&}mE499}Kz$fB(k?rxLV~{lhaf9zL_i41LF(ib ztiG$&9eV>pe}DIm*A0I;4afv*z*euWx`E$gI+L;)$llW_vgKHB0lG9_AmWQg`h z>E-qL*#OyXNGsGE3=SWDc?hVw>Q)eC&Z$8aE=;>fFev05*q{$t@5-ejC`gi5d{w7c zd*LX+;O)N;x~KlNdr%+U^}keBZmRaAz-5qKsPulRQ9yd$H`Sy_?aO7TT}qt(QNpcd zyA*Q`dO$74hSds*@?7+e9P%*G$v2YEyle%LzY(DBg=#{=0n39rw+OEmq|X;SZ1*i$y^er{d)=r! z^-j{|W(=LaN>$FZ{tPUsf%Qeoxr^a>boR}s3*H})pL#v!?91Wv$8LWG;&B)89zL~EO?LY8>o?jHPpyHUoq#5)f^}4~rta?%YcM=W zsOA7Drw7#96siiyWgE>NN=?CI4LB@6fxa|X-3&@lU!JRqm}f=lpQAG zKlS!bDdLW>M5Q8IUbdf*9o&uklB=!@G~-^%D@b2iEiYxv>CB5Dg_Jqt7iQBdIe>TY zl*;I0!oajjv)f^@pqFEeOu&$T=X%}wA^DyWNj`n$qCUihflI{u{~ay~=#6*+soM}^ z7Am&?Ci`Q;3kEd%r^IAJ*7+_Yk4c9v^PFB01|#GTIZ+;LhRj6r{!^PzOswXx(fIt2 zLZcn6H*Us@as2th!?IKn;KXwHSKI&m?QHlngu*nQ)#}`iH&|Bx-#kZztA$%Eto;Q+ z{R8@l;oyIvLVv%_g(nnnYMW1aEy$nJe)*5|Yr?c`mpy7!_}n;iF=k83?o>DpeMkutn`Hu#?w;L=lkRT(DZ zRw7i3P_-KLBYn^hFkAOiEm-SwT_-_(*SoYb!1Cx4?*iP1s$ELK zMknF%`Fj5=Q1DOaPIIEfI}i7Lz}tUJq%_EPzsrvZ^xB^GKjMdfgNnlumyOC=Mj0jp zt|FY?QWl9B^ZnJ(7Rdc;d1GIF#>r{^0x34Z^KLb_fXMYB= z{=WcB|L?-H|380Q4NY8COpIq|b;07sUlZ;BGJ5@sQvErZhg~I$*D`HAniRFlM6eEW zk+C439>`l^>Z(!HVr>-AKiDogMBO+cem&~&@jX{?`Y-XW{?d~o&{3|GZ*8v! zm%5Dh5Sq%1N06XxHP00?Bs>&EQUT?doqPVVxQe$3@$OmauKUBU8%IC%briHn#`xc* ziA7YeUi>Lv#yR~LCG9fFMBn6o+_|ZP?#2m|3-Psoh#?~QHt;C377Q5iCnQdcxlu#yK>c@Uc9#Epm$(myT&6fI2P1RA(0|Qmkp}TSE zz`TBcORYH=JexKXR}f1r;#6OzggF`+`I(LRQSUGm0^Nv&;V|#?0>xyD_c`q-U&bgndF9yTK*~rMm@c zM4tkFo}RR+ishx*rF!ek(bXkt;QSSh)xtQ%>^<_v)NW2kK`*$BdIPcK=!yz|cQUmj z4ynENb-H@Zpxoj9+A~X1E76yC3mGa-G`}Oq!j>aB^s5K2!zSv?teXa(FOf+H(lO#m zKo{PVs0!@FRRjH6q*K$1Ca@J6xK&gy$3=YGs9?|}1SZcyN#adwR_yT+USfmYM+z$%h4V{W}9=HVaJ0rMR zDz3~LIcV5ayLa?TdH*oGl56$37%9iee}U=0h;!AJ=R2^#uJ|yy$}RBaQJweKh0s-AP`&8KU^v!=ZT=y;&h+^C$~jQMKV^m!I2$`eb=E2?#hA$!^Kap` z_(^4dHGiMj*h_U@3h54f@raw`S2632QSwG2d3!Lf-Hw2iKMkLcS_o>ac&6Q&5Rex_ zQ_PrmNyihthiMP|lim~7zNK6`#ky~67%}tI9UFdepl~i-GwGXOpqSw)FBwz$6*fC$ z@(3wRO5_(<;NibG*TqCPhj&$JC&V||5hndb>h18bNnclgv;$~40V5uJZTjN$Y{&P} z&tmAQXHc(-*M-`cZ^+84(FNChs}>?+W3Omc(P#>d_j@~xiw#VSk5deajNk|4MHuji z?p}UXrC3A(;&Rw|)$Kdd)=6VPVyusO&h0W=2A=5Lx&GlH0u%=4l3v=p)NMIIQIpbt zFi1AaZhmIG*W6Z9*m&4##{BQ8z>-Z+^DGE0RGA zF_U*|X?3EY{6oa{T?;YX3;u1p3qmen-_(Txx}<5Y`4IU%6GGSb~uJsE{zlDpMOzu z6D7A)78{pn9y~UH31-uuKgZ&g-4tQXD|uAq&$BY-QpcZ-GGxyrm?)PcTa4nJ3DUc} zPh{md@DodwF+8Z~3y=8zCxt2@=14-m<8RIy(n@MJtQhgA()$GbZ9JVLhdnVL8j0)0 z3Y-4wtyWR#=}_Wea(X8(kU`RbzzM1Ew)Bn~r%hN}di~HDZ$ifH74L31c#yygXqzlz z<^v+HDMaBSfyI9fW#*0txJ-V5_MpLz(oYbiCZ~|$19N*Viu(UN;Y2mSUWuX|fZDrpe{f86tDy!^=mq}OHO5LYa0Nlf-@9gebph=;>k}K{%rXl#b2@P> z;c#I+Pox-GUW_(n40PkqCxgF~J&41IO;Z!1IzG%$(P@i7_QxG*{?s3CpLC(cD-}V& z%>XptY2&^Lft!h5e)U%Ju8LcZNjx z85XXPUbk`X@%CLx6PhyrnYVqCTd4Ub=54pJcV#fNM%-Ps-6V>|8ujC5UbE#9;Q$AV zn_gEYr}J8?QD+}*OH*H6pT8A@`R#*!vC_A*)xAOIH^IOlj{Y?_Z?vp_LVl=OOXJE* z_Z!$NGe_WrL!zR@Qnp_I~cebZZKRs;K*aQ;Mq#fMcL^UoYMO8W$GXKkt z5M4{641eqGH453t0&!hvT**qepX?@gtue%|U3{XfiH2wwUg1Kpx@xki02Q`cPCIMw zeCsXjc<63xr$ql4c3lonxbQOn>QrDQGeba&#jhENM<8LAn=Y5d43B%YfG!4-C~+l> z2yP1LhghlWpk$J9dB*+O_cYJ1Vu)U{dTzwqK##=Uhmd&oQb1~y$!N2>v8{ASwpLtM z>uH^4<-KQ|tg?c;-rQ~h;GJPw^>2W;M135Tr_Jukrt)3`;b+&MR;O;?trQI6{&OOH zh3pmOK}CUW|J>D{Wt^Vxa*%B)h8h^Ep7(#;PcBgi%Rj9)GNUt;`#$)ETOrg0$pzw> ze*K88t1c%^y!^Gv8bXhEK_TpqL({JnlT9?v&(?RZKcJ0H*ActF!eAPAjAJco=`hPxk|Nmvi|9{`MlDtc4(B^qBPdR6L zJfAP-tV8duCC{;pRZg=q#@(KS8sAUAaZTx{>3a+jq1sCdM+NdY20fFS2Nmr>dMhpb zTU)N$RqE@Uq)gBW(r>91GQN+VI}z@%CbC5$A0P}Y(i($+H~toh_}ut_EBR%Yh^{P> z{+&r`SDUU)4`x2%-&5f&5PaV;;Q2_!Ob%Z!Mwpxt#Dg7CO9W)+*3)LKYsU5evY+h9 zUJ;_1f!Nnm;G@V8+>ei2ydAUnnB(6tZ$FQ3vWpg^;v^%6f3NN+LT0!z#{ncL&u0=k zEGjc(BN+U|EMQGawcyU>DP1KX_I3 zAg$%IZpH1}!ai+vnFro-e6`WExy<8Hzs!d*^Y@Ed?u-!~81My|wU_C~;+A`QtJS8B zxnZ(%B`0nsZ4XqNpt_5O#>pFRJeGYjVY4Ma&K`Di)n{dC{rRPND zVox28mK{4ctvq_J*6gg3<7i=!v(|^+uy4(qpTE{S@(jy^bi9u&_*C+)0Jo*dxqcaJ z7oEElG$*kV>OnaU5tG|c6+GYIM~txgJtpOZ2|x_ZfFDId3k; zE?i7zAmfZweyMiR6IO>TwPK+KM(= z(~Jd>?M*0XHj?weSozwUX&QCWetre{y>yq7x>tX%EEe7*{N+p$@5k2s!*y~`Tq@%K za9xNv9%84bQH=J$22z-{9~7r~#mHYlh*3zXzNirC&9zAFt=-j@l5EDCUcz*~D?{G% z+1vbDDj)d$D-HR`X30<%FT*H=906h1}6zL3L#by2eKu*v>`ZgCl zcQ<4?>M9^2l{AhU#MJjHtX+avlgY1iQG$iHEHzD|s!iSq)M z8&2f*6du1kQ-4yi2a(IOQSDlbFw=s_{%``ji{vFI5FqbunYSa_SqXZej}%;oQI%~d zmta+u@>|UK^uCB&A>w<`5`dI!d2RJbrh$E8ZT0K}nZDM(--y4fpQxVOHk3-GCUV0Z zt4>;L4*5+9zrDi3TFm=!%E-6RIQG+N8=K80P02f!n~aNbhR zeb*080^A`$1I(-5nyPeguo@XC)Abu?>Rv^^xsKSZCb%PnDoB!H7;t|IR^oVk6}oJ+kx;uaD_2Kmcv3Ph*Y`0jiw_a$Bu6j2+anD9?k?TI6uK-hisX zPVdkgNDNnM%6|?ven|T?B}<)%!0w@ixi|uCPLRwT*CrMqc{i_*Z{eE+$X5Z1xYrj? zd0T+Q@QpDB(Ve@v*UF?N27B_WxOq--i2aTIuAuQZ$QHfG%2zyaf3jRv%_=2y{pIy> zEk5m%RY;h<;??ALRWtIU?NEvPj_}H#bb~ z#S*)PRWyo!Jj}mQtAC5_k>vfTlN{4qe5>Z<;qpub<2m)~Z>TU>T&>pP`;}vNA&dQKV=PdjFBsZHz6bn!>!=OMAU7LEECCb{|H$AV2-HYF?ycbY{C)oLm$ z-WlD-msa9)mm-8IwkPTl6C_pJ}#s3;b{E; z6fs2^pW(*I@LbhM44#ePZx9PCskMFYNSFisi)9!vZlF$?`CK6UC>G%ucfE~&Wm@jg4AKNoKSg4vR{r!zFCQZFD4eR(6*NTT0dL@RXtTrCdjql<-`rJoiI<&Vn7jWvY&FR4*^pmOgx0=Rm=i{z z(cl$Q;?z}CuilmUjbme^J+>;=FQ7@PP0MF>m8;L3Gem}X$>qL4xnrLY*){Q*>XuD? zQ`XE!98b=5nj(UB4H&mz--AI`;bxQ9ZpmapR9`dH^AMb;y{jeuwi};doWA&KJw3&> zWS6UlB^+l5y=IJH3^lLvTdS*^W_xhK64B+bdP4V#^b(^Jn(lTpvxvz=vPFc?l|JZN zQUQc{-HF23JraFx<}p&LJ@Wn+?sDHjBT)+n=Pe^=SARwOE^6i+BDz<@_l2BK0V_Ir z%LOf2;)w74nFEqZgEBp}+N2%5T~z_XvQEhfOn&{?+1JFVp2eu3)c%XUqWtiku3q1u zms>!pMDSQFj1Zh+cBpIH7*4Waq%3vT)#NX?B!FOWDq&MRrfjh!Khh~)DDXB6wH@EQ z44qE-93k-$j%$Hk6W)~YlP!~R`UMtIyS6a?ZM||(>$y#jCRpX2E35W&JF`(hyk9wY zx<8aG17kl6h%vf*8hjP%o6Q#Ih`w~)CiU{*Y3?c@hFlPm4^T@Sz5i`QxQuj<e^n>g|MfCqRvOI)UZC8|f4)>*&oy3sO&Vd?+)CDL^ zfNSHITRAjo;cU}!@+-_!P6l;n)^74n8K)h_A{7J%LH(^GR84ro=tE=N7qUJ@y_K9i z<#sb(f*Fb@@sZEb)o;T@aIBSSoUQvw`&^ZUlA4+&N9wHSI85fAL2*9=g(a)cE=5B? zycca{ie}|Gx5Z^$U(HJU!;p@$)8wN+_FY@i9UK|4+(3SwIqJ*l`Vz8F5;Ii?L=ZCx4%p4e+51^m;D?T}c!(%6WZeBdOD@lbXyOnAy%IpR&3wT_bk1HAD{FeRnXQm@T6rZ3Yjn3-RA51;+G#+=7fd4 zBbGlBS$MDh@6CT&c;;)Yrsm=osAq$e6M&e~-6Jv$Oq(hN`@Hkv@Uxwx_ihoQ?+EEr z*xWrDmNAA$8DEuxm+$@R`jc%p!<;5D-*e$od2O%sLBUt*@Uhj09Ujb{PHH>G2C1wj zbdq=UJ&Je7S3!jI;;?RGZfFbn0zYP^4;O@OwUgpMlPhQRHhnn0yz>9B_nuKrtzEx2 zVqq&PTTu~_qNqq$6p$7~MMNZs^sYM~QUX##O8`3}1f)qv5NXmofy7FH0Fh1zNs!)> zNJ#<-31{KH@4fdu#``?uJ!72bd^-8Y7>l)%wdR`Fob#Ih-|Ss4^vtW$P{5=CFT1x# zu4ga2eUOx5w%i?Unu_-Cp0JF+=EEqAbM>%-d4)Sd^i_tz5JjpphGqfhf zqpmAP5LAo3?_@J1VRB_qq(RbmqMK60EwjmzSO6v0FE)vB-bPIA>~>4w)FmVL0V^zD z8gt)XsRENkw;rwFg96o!+wX-wOwq2`^LsN$k^_3*zkB8pRX*gnbs%?W*Qy02CZWDN zsGR4(JY`wS3Qt={Uo78it zQ{Ltz|IuyG)8!3#kwK5KOTtO8CW(2LO|8yp858&;mZ%=l)E;!nECpq zu(i)mKZzCi#8Ag0e)Nr~E!3a&D|*Cx%?YjdK8vdO{6+o!A+P5$%0E^j#u3?>g24ps zsqNf#rfB1FlG}qJ$t0`s@x)i3(UTpjJt?^^F7;ok;a(eUT~=l7<$)#m1QDF`MIFh` z7#lUG+Std%%dVL4>45dK)p-92pwsMU%-gi|8Q0drTtqx)R7dfI6+J7Y0$Skf^=6H@ zXfO2v^b(gp8>Cz^3+q~~?iEzYu;=yWMC8G80#*qtERUpeU^K0a*Fj%MxL%-qwR`*KU#n79WxGGw)7RK&U$=+ zbrdHP$ml3vP1=kaGmIZ&*f^1*$V3Qjan1Llrcb)Il-w{ncPf9#n=UcTuFB|#*`Mmw z(jAbws4d`c;}^yH!9`e-)o~^p4)@ke9#ivrn(zcH_^`z6i16;E_6MOeS!m%isWU7C zaK}nkfJM^1r4T^PbOB0K)ZJKrIE-2i6DZYpx$UbWonNsxTBzC13eO9e>`=)0um`7s zof?9jY|U!er!6~a_6AusHLTgjEZ8tCpT?cgJin5$ngJf_;cTw@j-fHv z7y7WF+t%SLMGvmN<;YN&JGjuhHb58D%ME?Km`+GxOax!m!CG;3Fx>M|hGvjA2*&ZX z+tn`o_3GJV(|s!B;2^|*9wJ$5;rv>(qrTw7`{?%D+b z&Dyw9Cvu868dY>PUt@$vKrc1R3O@6uB=cU50J)Ub^=aj^Kl^{VzAvBEj#*2VjcQLF zyl8c21LI+=yV5aek_ml-NA&-!iTq4CQWNvJvcn-R`L}l?V^F2BOw&seJ7c?Sxl5;< z;g&$!P@6O^c+$_sqSi^?!;IjfG&a2D&2m5h%$as~F!Y>?{16%LfLPOM*_%|SBcqFe z6py_#J{1IaDtTNivdDR?$!fpgB~H*j!K%F2|@z$a0TMD0fv1;=tS~;Pb#+~6axN3CIbTOVq#&EVURUrr@V#?Ag~!79;gJ~MNW z{weGa*ZSsw+NB$qWx5U(*OukKhlGC3?wyZScEQOP>zat3ro82@cEh780gEb~tKPRV z;<}@j{yNN=2l{|HeAeS?nYTGLJB%p2T7S>Q!8$f_UA~O-QMkfgrwL)asR|pvj(bTv z9t*x4?sHurv=2spy5+&F%=hb2-Oi6JY7YT`WQAth22_^CI=v8h1)DhT;<9pQu$u}y zOniGdMgNKgcWxb07E{zu`Rz#8tCsknO@ zV5`HZnzD2CLb+$wg6Ct!q4&(ZX9fEbKTwEjdx(*LY;UE}7H7-uI^9+;E!_7Eu%jiF zQCJLSw^Oz)WC~IEj;G^txW=iZy7M*LkD{veD^xB-@>RXodZVcI&=lPiXozs3Y+IcO z?;;Nj{@w&)-KYfkvM#k72L@@~hw+hihgtgzvtv6%qU7TrOQL2QUpM}|Jme6tC^6tl zeyA zt7TSS{qj2bE(?j!l_A*F;H=m(#4p7gfRQy*h|Dal#zZLWEz!!?S3%Z4OxDhE_L8vf z^f_+Z(z?#)ktFPaVEJnHa2T-SQBm*0RA5O@8TEV6zrr~$lkb#WiM5tJ_>yIjBs@?} z+s@Hb__r1EBtfw{u&d7fe=< zj5=6BZpi|oQAc|%p;UoGEKbh(4`)qiN-e$TWgvjIm%(e>VTA6J)alA=P@Y;5pHfGO zXHn(d?UeBNmdxOdD&Z#ja^VBK9#+p{UB2nU9o(SVJ;VmY+|;fO?j@;{9b)nFN0C5! z!F=Pr|FDwU_u0WN3kBV3ovym>K_iz9IgC2M&B!hH;4SPZ?>nw^ZSR~Y*)Fl<^p~@_ z3y=bV$(2CvQ#!ghr@T(d5pj~DKULn*k@0YE5bKA?j0!!}S4Q5CE@QMu z`AaT?eT$a>(g?gpmTfZnJ_LT*A@$DKjbPyS?Io~ES>W{-ev_^Cw9%*g3Cg<;A)GW* z8vM+w>C~G$HLl`%jiCRTx_K374u=J-pBMw+Fy+6vS}Z43f_bQ-)i%l9;xVz;~l zQf0iL#qENuFxyL{W164WHRjeGx>I+8xbY1|a@Rl!uEg`mbuezM>Pl&X?%bg|_-Pre zwj5RjFTDrycH)&zWeV59oIDp&*yozJycW5!M!JQnnQp=V=1%!G1&2yGIKAa6UMt?W zlbU@9SfzMS3mY+guJ*<7Vu@7>y;G+bw6Wtu5z(O>=V6cl30!p~xFUE>8loABo8OnD z8hFz^Sx54^xQnA{6UM``2waQ>}02qf%lmRM- zWRB<*Rbcrm8WfD1oT~on5R8di`pRj{U0w&6*5cs)Ppaz=X5TgYsjjEbt0)vFD7SXE zYfU>K0@t%&wHdMB_5MMLTm*+K(h^{uS|80(7lIW*pT1Xx0AtdGa31v7jt01iN8tJi zmnm`{s+x%ITO=Wc1%8S;6+aH+vVa2C+5_|OU)?I84U!cj5KX7OpKlorqFdJ)hX)uVrXIEBF|Xaan=U^ez7@CCb-(Yg zvIuTdG6CYO3h7rnh0)$B!M28o}#x z8oqz`X(a_8tas7rMtc!`fnhmy4rr89#QNCarl-Ib_n^f=q#lhX_ zE*T|KifztYZM??)R}x(p{*v$iSt=d{|l6%_IkQ!gkRa4;eaPPcCK$Q#lO&;6Qiz=WTu z?gfR3CE#v06FpkRU;@5j@k#ULI#&ZbH=XZ9OH|NU0bJ23AOR^L93GR*FL9IVOtGw~%Ym9&H z4Fk$X2)1A_WA?y$tUJEPL+c>p_e<&u9(ivW2U3U>?#YpQQrc@)%fhmJhFNV+c5v`K z;MaFh3*2kBalkXKj>!q`%@_RAq6#xZh}YXe7Y{n@Jy5%wqV;Yimr;l*I-YLS(bO7r zuo?ZGdpqn?A)6ZM7+hO#vY$#O1!cyFUA>x8(4X3;^mTZQt*`C4RgC`a3P4sDe=xKE z`l`c48r)ThnoQ!RtRO9K{^pns%AurM2Lk(Ny<%G!$IG`Qem@KZmQnl^Hl~4Hw{fXa zDLrdWLXnVc6YzZ~2v$I5W*ShE{kZH?knyqa)81QP%VtUNY4|wjmL}emj5wvUnP(L^ zlCWEIF5%Wp6@Dj&eIa;rhW5_(WI!?04;vBbVr?$t)Jzn^O!S`ic6_~+)<7$M@~JPB zgT=LYv<<5uG_zX&h^ClT-mXlYr8`P?l*_FN*5y=XlnR z`PRH#Hf_qV^X&$u_2d@_H7n7P85fZRKdvWv>S3t4qY=WjPng}4!<1>2`BKyrHV#lF zYU6**PFnX-4bzj5Y%zLZ07Zr}^I&acH6>+A6~>PvM;-5-e#v(F(cb;eGt&Vsts3~| zUF(wxOeOUFeCSk(5cs;x&^VpZ;A2DXK?Zkb#FdfJ{^+pUPu#Dh6ZDRihi~m)?`+ABNb)&h+}u>ve=#x-TV&e zrAzZU7>k=YTlu+}w+m}r7mcjqaFWRN+=$>Cd<2~VsZfLbVo0?Yp5#*7`Z#WD`^EN^ z8mh*xD2^NY7300OgzB-D)PCQeiQmz+eZK3d@5_1oo1}Ji`!VTw|DUakGoTbfg9JM3 zRqq8|4Vn7aoLd0d0U@=bH9&E^pf|fi2fgqylhaj4TE1Gl3E#|Kg?I=Pt$OObG7X1X z!1z-%Yftxoy$`k)yk^SgBsBF_?2o4|V}cS#>YwJ~F>4R4LmXd_8&Moda0jQpEO^9b zc(md}jQc%?k5$>ed}6N6(Cv#^$=ykby&41BoYa(hguCa}Hbn7#u?9x@T!3zPlV_)V zy1c>tXSvafSwX=yK9Md_4|GmI{Pb-EVr70T2#yN5ITeM>h1&$CvrHx9v)&@7qT?5j z+CqX=XKG3%#Kxna{MqnZ`-_^Ho?dIEUvlUn!$*f*c{7Aiy=+m6ol%`B(F)WuXUk3A zu;x_#L97;tm}c>)hLRtNP)uLL>yd?$YwMxmS`-!ka7jgoAwbk@(&oQtf!E{5-DIU6 zgP-p97Od0BzYnUpq?{i<^vL%ixA+eSQ$(6)iVIb?r`)#Z`jN7(b=AQcI?IBhUZ?xP zGo6ACex+O-(^;ZGLNDMV5Ek|24a^0*zyVNRlE0V`q4gs#*_`mKrh{u1^&O)q@1aKq%RY9c)AcsI!FTtZtE!@{ zE>N*sAs|EM0<9qE{1w{@@~p+4AIQhv>%;cvv-%yK5;#re-RqJz4j#et^`9WOjj({O zX)Cnc0wR{0g}55nvM-AOe|P3boMxsEb>;asnjMI@Y0SyKl}Cy9(k-eQhOFd%pfBJj z#kun-Up=&egZVxncEt5)W~}bu<9i_CCwsSNG-TpMm@5U>+s6?MwkXJBE>S7;gr&uj z-+y+g1c1T&_u<;JH`=t>Yu{7HS#a0V4Zh{m!HiIR`-%Y+^PPUV4ha$>sBe8UYn|Vu z@&XWkz0JCdz&;o~cxA2731d=ZNB(gXphHQ0w%=o|T@NrWNe1S+Bd(90n9#Kqp0f=m zk9~sJ!>!s=F*tc|1NuM<#9^O;j8}z zQS1ip#N3-{U%^x5O?=CnS`VLT#Tfnq%R+|NV1NhyuTR9cJV=t}{US(;=Cjlok9q4E-wJpBHb5nzFt%ATL7xOh0aEM# zeKa3mMcAzM`&hR#zy*GQC%2>;_?;%8I$MLqM&i-G4*Tf)9+K9MiVx`YE22a-%kj6d zr+Uk72P9^Vo&W2gh@{I{wFKD7h2fbywo3r8xvtC z$^qyXBDF^T20T>#uQTv{xY%xBv+yr!7&eQ|X^`6F6jlE>s+Vwfd8UsZIE=0J-^gBc zH)b}Eh`d95y7>JjYcw>QtNYg_@Ba8Fsm$5xh32->>;Gt(k9PT`G1`9mAG(LTm4DL6 za(4Vf=%J82^*aY>i%|8Xt-D7d9mguVN9 zCG_wK4_XU;$3eK8g8|aM84^yu0uZw%0eXF4nnp1j!Pv^qvY8ch3V{x*= zKS2999J5qm?>PspQ_nBIstALod#)w3>GiSg`W)j}L9)crO3AaZnMwAP9--D0UWWFd zXK!Zqx(dy@K$Aff(sv~xd{*+@T@p~48m8M$r)`&3A@_MbDo1s95|l55 z0pcCFD=mw56qvr6H$9pd*`@iL{ejEODZNw#y+RQu?(1GDQ9?TT4>E0q^$`W8&Gv1R z{H{XRB7gK^4LtI&lX}9(brf8w1|wf{5JDC3$!f&&Tq-9H zE2WQ^S4A3gIougIP}vK>>QR6`+&&EDL_r5xcX2nl8{PONEJYAxvcKbq*oT4033K#d zoy@X}WIl8`-Gt*%Yqcv*|Ghw7^Jq2IU+%J22`?}~2~&%_v85Ic*lMIaw3Du0IQ4Bk z_VEw7a!tBWjsAL_p7Y9!#R4s3o0+;f^8UHNPhJpkH~PERCRiXgk75w%Y+(gl@Ci4c z_qPWDO!rSzQTAM4)xZvs?AMX~;*FpfsRd^Jv2FK6E<5%ite=65cfFi(e&BjY%3TNOCcAHhP&k7Tu1@v-|yW9o-kaDq5E89&(GTj9sA4`8oSmH0HkUK^$U zFpWF!c9YG!vZ=NNzMG%Q=ev z&u=o1o6BBx+*zPsE*nnnWc}ya|4r#3dmI-y7d zoDYxreB%k{2^dp>WAuc50@v?+y64Jn`BJ4PAV!B82?Qho?5`;D+21n}tcPhFlxq8B zsLf9%EpeZwy2QOw`bR1|Sr_lisqs{eB!fj8pt=_h!l-PCIfvxuVqdB-I(u%G69P3I zVz=;^o22^v9Rw|A^-17isw?epn=)uz`y+jw_UWpr&g|yDP?o^AJM!hxH;@Ogh}{Qd z>)JVwlUeO)f1(p6`%~}zQi5&HAF#;-VP>`j_e&e%H4OeXvtH8s@a#s^C7g~@D8Q;r ztIcj4o14%AU=fwqM+mZF_GI+}dTy3QIE0_#L39bF&&}%KWMU0bT<$ab-$Q}-rdDr^ zsS_wJ;4=1_JCg9+fvARikF^&C$ckBu2}|~IL0~2H?>jx|!FQ_{>Gi=rE*sA2{*CVk zJ_Ccsy&2OFLI(qmCv2kg|Bq#v+aD#rM>@dJYPU=QeE)^_gO_q9h>q|C{xha*Va3mKJxiV#kMs-NP9mN_7 zBy!4ML>m{}0-$C{-HbJ=bZ@{XgjM2mff47vge`^=dhfCOljA)FlL)`(eww8K=wYvY zt*(a~pG{-l{J_pv!oWH3XK3ibe`pP(?|p(~Zv*zeo3v#55+J_CFr;Vir|y_c-^otn z@QQ$)shMcmi5aZ(A0cNv?P#;C^Te?LqoQTiVA1#`F?VqbWQ|vnO|6neInZ{#T9)t+ zZ153W?l+Lp@0Yz=0W9Tw1#F@WeoalMNOEB`rOEGb$@c#UU`|KD@Be-|>-k)d9%0kj zZX;-cYh<<8TIxSmi7`c2Ch}-N7r@j*O9q*$MO#bpTd_W{p2^L}XpZ}g;HNL$Ksl#CT z=lx$8osKSm^xGf@s+MR*((Ag2f{@w=$G(Pm8_jXI}gbc)qLAcfM;f zuLOwLW$B?6rW#r9ziJhnt{2-C{Oq5x!E_|f3XVz^Zn>s1Ej5e zGn}oJ;!;3%b|vMIn55^1V}Y3!RiqH06d^lwSY+3}5JLDT#0em^`2sKNjXc2lH~tJL zNK8Gj*b!IG@&@lXXA#nDa%K_cSZ{(Gtc{|S)P$>&uE81p(w9J&Ty#5)c9E|>qUk3) z@daP+W;R7{XHR-gBtQ7;HR3yM>B_fGW>hV7W^mQKa|@(bI0J_-qk*`hwJvD~R2f|X z;yHwF8gtx)Y4-8x%=BM`m=Ucr)yxSX6hyZ3*7zg0#J$|Vv-HbF7RN4I7R@S60&2OW zMvisCz@f`v(gFLUHJR~d#A8I=av-NWy+_Ifz`1&5{=?Nq+y!v(Vf4JJ%`l!45DILN zu$t@qZPf`7mDTBp<37m8gUArj`I8g%RH4_j?)KHyTZyz`yq8n_TVB?zH*$a5_o-FjWdnryW@3g9;roenR!vo7A| z=L`40-84Zxny?U~d*g<(pC%`r@DlNgnJhrk1ay6*lw+987LV}6bDX(18NLkv zLIXBgp(7!=8-uvU{Fqur`Frh^$Ic5%l{+YVjBe^`oGlunyr+Q><`TDd+&0@bS+c#C zcX2VJ3sea2V?jyc3Yzoq?d7f zqGy0SNjn7g>g&Fj+Ty3*l14j^9bsWu8ptl4Qr*e4HyPH%5FFjn7^V3uFk0W#?6Nv5`f*a(0eQfWW~ zOx%|XLARRrJjMbkgXdrN`5~+X5Io<#cAqjLOyQ#L6Wu~Zmf!e)gB@SU@z4amij>o_ z#4=u=ua641ZGr&Y*!YGo0UWz1EpxL^I0F|C{EJ&(kyR22H1i4-;V`8;@{(KmZpGeA z(L@Jm44oF-WB`A!Yc==TI5kOBRDF{cuSipugN|qouVsez*C|VJ0EK^Vq-9cFR-x!+ z#70HN9bD|A899u%MB=_B%3Kcb&3fyDGZ7yoMaxz;Z@P}70to@5UMV+em6Sf2gP6J5 z_@y;V##RACk>_QGZ21zpYCTao>;b5ICrhc-7l4T3&8>G{u)hOR%Pb4g%V3J)$bH%s z@UFd*{d&{49$q+nSt*g1ZhpJ^+zWRHYC_!_hx2YCNK?wz#1K@aX9rXF0kgrAo)LpL zpk}D!?V$T3yZ1@W0HlYj_%rl19R(4py7A7q%;Kio>&J!{(I%99ufnF0NgmlD;^B{n z@;yGvfF_0?Qjv*=CF~SH(Ndi0cjmq=r&AXC zoIzI})wM4FCS|gEdiy5mCJhrfOR zpM1ZZkW`B7Z&C#`a2IH#X`OF*(Ju5LY@aS5kY`4p?3$KdA?bu}2N1Rq%tr!oz@UMp zuPh=MSHnFca=Cl5+>$T27a@@j_}ftytNn5Dt79TZ`V;MkM!xv=ApVZeK3v-oN2RFp z*UWu%C(1Jqw8C7SH@<%A*LoPe9ne-cVPQ9{Hr+%uFDMj*u-;KJIYGeC0bTh)XOPOL zo~?lc$pGehAr4$1ykJcE5rzlKXsGp=n=R6&QuPDdCV|=twi_gR+eO9y{_Q5s*YrTg z?BE^#Aso65@dU?Y79*A%nU|RgJK)OS29&uzeWjEw3`6QS-}q-E$rjq7(|1qiU>wzS zNO{YuCnwbJJO6R9!-+)}uk!ewOnnOJt)u4nmuTB(WW>+8C3)G$N4gTn8SnVV{%ys4 zANO42Bk&xgBeZ2)g|tVk9S!9GmgxIhlVI8lhMS7yO&$ral)t@H#Oc-!-Gm~DRLCJe z;Fo(0o{?Z>7>b#<{?EJZ_qR1lSV-yy}l9#QHF>B2&wzFu^+A_;HHWpm+Kr z=A+i%fnG(`0RZHk5^`-7V2g2`muc3S63NV~(kh5Q0F|!~UvTwt4YG{gYdY4#tqZax z^^K8&Tv$Ih{VR{+^*b~H_dZ4^)j$ED=x2&oDJ_Y?)oENJSotzvqeGK&5kq`9!^Wvb zhpYwj7Q&SQOnR+i!aE)FBKL|I5(tGNd9#<=(;;{!-oZeN@rsYqa=h&Gmc!k+<>5 zAKx}2W z;_<^KKV#16oFu)6XD9FG95~YZDuWus9w{ne=IO6=9mOT5&#l1UqfxsG7G;3=k^5vu zJlf?4Yv7e|;d7tdq}gzaXTR=|{aE(ES?P}x^K%cfhO|yDrrmZ9^#53sAnockVv>xU z%BXKk-0SI)0(7_B>Lyo8D!Rf9-jx_n!Di-;Aa|>~%odV`ggVwfaA(Eb&(BE9uUjL4 z(AL2P#y}bdpfG<39Z5Nv6OjlMQMr+v$t;1uwjv_)f+#Q!r5I29leA#@wpw6SjVwdu z;sOdrj`exd;se~ZhT!!BTBvD7w=9r&Twots2xqhPBaP=4Ua&`a`V?bDdZniZv&*u9 zj3M;1bOf&d{WJ5)=%!Rb%MI$etfBjNSW)*H*XA;~hm)hf9XAn`NvnB@)M#~bOHl=M z{Kf{@MH$6IK|dhFl|hhKdo_!Kh^1NzAMG|L@yjKfQ!47|Xl(_!fl$X_Y#`yCi7lwn zpeYszQwO~N$SLpfy87B9ycWr5f%MCnRzN9s)0AV;xjXQ z&>g3^>Hv`W)VbdU9){d}w5k;6bYQY5EwmGiZ>s_CTokaPeI>y6~Rr?JDk!Nb)Dico?@kGf|ShY`Jkq|!AoIkd-{)v&v5SegYSW# z1E^-c-(&DpxIAlox@jeT{Z-3f5BIr$VMCR}l1WZF-v`%P)?o$yPE3JSCG;4t>=I&Znc&kL7A7Z-^%Ckhk}gSS6=zdzOEAjm zTI*ZeP;7ethD$HP9Q!Vvxbq$6XrZWmhAa8VFc4!n$BdNiQ$FJK>a|DSVZR^I&qu=s zHo4clpRe;iT@A@J>t%`5dCHsR?JbuK?+6?0Y-pu}$;lj<}M>RtI}a<`}Add&ffF7nO@?i|?ZS&N;O>tccVaZ3Zf= zZA&1wD>8EYS?}$&FDQt34~Gw_VCpO$I0o;zZOJq`eA!Wndcw_g+5AFIU$3@eS5*65 zL6T7NjkPD9Zu146l$7PsV1Tq ztuP+c4adCi|A*}!DnZHz- z|6bIH43r7`kB2>6K;FW#w6j!^)OgwjtH}`GO~2r4&&cVv&0}3Ent@StDZjZp*;EmM zDRZV)=*i+#2zTRX?F%_vC<6Mu9@>>?3dI$QmtO3%vdGrOynv%Suh3?a(~oVNOoC}s z8jju_3S~-9jYs!v-1`C(a5?Fx63%44$q?`Als_Zz?n}mylQL8}BYDaBX8=&>g{#|U zZT?ZaYJY0a{8T2X1XGUA!Aky)Z20(goqVDDTco}!Xh3kRaUJ(*x?8pt*4cFNjKK(F zd1R{X>Ew*&KudH`R$F{jBEaZbEOr2?6bT+T@I%<@{Qvskak}%~u7}ND0l=3Lbp6 zXwWfp(mFWVGsF4`$U#Hhd%gKy?QuVaoQ~jyjJ-M~^(IL_EJCp(6Z*){eh}w$&HGlH z4#0RKNBA;Wxlg?M`G5%*QZl73bhc)U>wO&zjb3Kl#ZfAU-c1E9j_){*S6r(^lvpIO z_-j7t%jQju#`0xrZks%e)v2766@3^f0;}hYJXSe$P!yHNBu)P@qDEj?_U!a9TRLyU zE4v}K*PeI+3e{i8eC@?0wYX>9sl2L?l|qDa2lJNi5?Ec@$-^YQ=HLod=+^-~`A6u| zZaYE!rJO23aa9vB#Z+Z*_N;k!iKbe(*(w*nL=kd7mT%_1Jg!bJgc}4^&Yp~7RBb-u zj){4mp8>|0rvUZWfWc3YDm@sOl4ndS)H9WQQv7(ttIu>Xjl;k`v*#-b*D5cdX_Fj& z+Nz!=egw?|J7Y>l%if87@x3+>6ME=o54-Qz+^gvpQ}O#U%Z2{hMC<3F_BQSjP3KR- zoA!Mp5@b1)PN$uR`YpHWN5byu^@I|V1m!@v)?&QbuQ^qXcF*1I(zCRay~IRv4ax%; zQxv~x@{b;FmLl#E?0Ki7L?YK@gz3TV0-(wL=#o=~P}zC|6-J+u-Tu98--@xApp`_g zlBN#53ce&S2=|uDg-?hPGhfr^Yy4`J#Wb6)jvVBW zft{YVhL$}IAy+J2o$>}5FT4GEq;I%RdLntC7D?kh1lGGV34O&G{mfcoWl+~u@v2%_ zCxw|VE_qOnNUnkJ7&~EsC&)LFLLaS$zPp0;Ry<3Yt89EIaStPO3>83N0u_}ggS^y$ zP_|FYdED+k5%!(nSJR_j;;CwMQ*&1S%<-Goh(9FNxsj_kn zQ(JcQtzM*@+SHqU&P@jM-dc(x02Hnf#uyA%{~);LIz3hGy1!V(P8k(K6_#(Nl&tG3 zRTM5PS{IiF9KVUQ@ghp}`xR>SgnfIZ)#NR%s4P<61L;|FJhIx=8GS39^~zYu+rylD zYA*1>h&ytg-mcs0*MBu;sw{X`cFuR^wIZot+(#y0|Li@w_52iVM_JSDPea!y);$8z zmrj#Hzy*+7_rooJ!sqn)(Gj%$A4r_YnmngYRWnH&{`X ztMiM#xO2G?uE~w5xpBBts*hvjAj8 z*=PTfji73zdoKpOUQu3g3{S$vM$Fu`Um$6kwGT6h zcu2A!cgzO^*eRwKm`G@irDTRb^8C%!{2=YvJ8r1LbQwl)vqZWKH!CyJeC$hY(dsqd z@gUd!0=44h7}s6ynAIzxklqR_bD=QKo^R9B@TcB4W>Srs1TM1+8Glu0H2#NEw;J*a(i3I;<<@G zd|Q@yjs>fiehe;1){jDJdczZrsEHWTSYi-Eh*#y@(>Q}-Lcr!JaCUfEO|8v#45jeTsKnHzbo#Y$Bc?N1*1yc5u=3xoPIw4|DI;YbE>kQ3yH7Xx z7%IzG(r?5-Xkcr2RhPJTVobokvgT@{1#F|V+9_bcb79zX#Idz3HMcL6DE0?zZ(lGoIh!`nV`H-lw6 z6L!p{W;*gYF#2SAJKI{;N2RfQjkp|W{t^0Rmj!-$vOyd&4h`CxX~(KjtHXC8dn5BS z{ffSZbd_xXjHBr>IL@Gnb?^6hwbq5zHR}>(yP*NZ=U0LRMj70CFqLXlFDU6vvdZ*3 z`=d_UKWpYuatznswMN%i+;4~gaHAwDCQNg?C)jBLUgw*t;eRYVhx|l5?p0%IKrwC{K-kS4Zd} z#+U0PfMZH~Y%$6SsMd3GW%@d8wEg4|VQoqSJO{h3UCR#SV^jzjK6ro;9cUpD^(e~% z-e9Z@gQ7fpxGv@MR*mcc5gA&%S&D^CF;$i8F|*&TI`}LaRsX5WDq6xuVx`tpRpPqI zs=LWh%D(1>rl>lt3(R4<(aH?}U}|963~<`?W8Gv@-|2{-ee=1q$o2 zKGLO=yCluEX04Gr+p%|v(HGTPR1QvEjnNa=6608|yvsEVcd#5Z0rzBXu!Bz8-sfHU zy%v7oj`>wYxWPv^sC!y0w03RxZq3FjB>O$Fpn+>s>W9F61*)ti;a>%IM`h*`&ky69 zg?Di!`0xY!Lj)4UE{{j8-q&~?Ecs<|N`m7+usCCBw&0mi$_1v`HO+r%ktrT8K1}U? z)j3VO=^M$Kyj-pdzI;UDT|?|d=930JaKIj}(rK>!Mt}7N{BaIv(Ubss)0k^Q4XaQ8 zbfU%VL%_Lv=AJ_zIvzWkc%7tzopev|?T& z)T9DHj|nW;=tIc$_M^$S(`0lsDv?GV5~H_P2??i*>e3{)pVz_Ka{c>nI}qLmf>IN-qJR; z3v$yxN$6A}_Tk>DMUKQ;T4mgal}hD~-illE-N|4oQTQG`}!QyfQyw{Vb@X z7m|;{T~-co%a3cO3;!brV!xfLc-?0YMWoZmpr5Z{P(QCxo({{n z3NBAS!syW>6^|B>cuJbd7SzG!XVRphiJUjCAKHBu39Tt`rp&f+ic|f5n{7)In+HgKqI}fCf8eS z*+R$hP;Jjf!(C#mPF8elp}$R#^1-&{T_1Et9hQcw}<}0tuG(J2R<#X_Z=jXTy z;tBKP7aOz$9|c|l)eg;_nM#c{ee8Y5GB~ber}(WyQ#g3`==)`i&$@lWY$31NAdR4; ze!iV{@uK?C5LlV)6!FK%U7M^H0ZkipU2ebavmX-o;>jnjEq0%*h6D5nEG6 z8-+acwJJR3btS1;?z}^GpSSqxE@YmeA=6u2onYJ?USPrDH_?4a#LRA+w55(p&iZxC zpDS(tFzS1Za}4%-oI|+>WSi9$s~T)?GpF@SFj7dBm~~%>Nn1~L$BN{lQ?yKTlU`96 z%MJtYap>})O}O8eDtJIvID887TzAu}#m-SQ`R#=m|KiQN{`qxeiiA+Rnaz44>ohFC zu0HEgLx2o6avP(O2um>r%`IF#an zRJFCqE^DuMIKgmAqrYst#bpj#Q$CCPT|B=lbZyYi)-qte>VrLLLw=xjKrJ<)azTf< z(D7Lj$0cUk`)vj?;<+#lN{~b7MrosyBGF)NA?Jh6S#;$!`O@ljyvb-_5HZ@SWulcm zWlnzPLESEgeRgJtLN!lq278u;0$yXm2ABIQ7MA4eZej|OM%)SSV9{?b&1y~(E?c;C zTc7TNAh8a16GnT()-I68wpeJ}`DkOpn-oax=+SyVIGc`U$1LB0cYne{pL-wg4tHJ1 zxp>3EHJrvw*a=5tfvHQdn_#$=fJ&Z>ZT`&N zz_500m-hcf)_caY{rGRAbkNDSUu{*bwpz2OU1D|7+I!V#OHi|BM1+>^BDShkjXi6R zkWj4^qqYd5B|<_%LLy?Ew7>g*|9|J4r+JW1@_D_-^wh`9=ewdfHMnOd% z%fz>yQ@ne~wb8vMn&woMw})sCJ^1)Iq4zSJijW%PYEm+}+YSY%TcusdtVLDp-8hdc z^FxsQjJ5aNXH|Nd6yJ|#a-W<`wLuEka~HqtYxrU%%P!@tu#m+kfe_=CE3@tviN28V zL+96of*lqR23<;DyCi}(;Rf+JX&YaXF9Lnh*>x@dNAc9s_PF)>X?nrdxu3lM8laKx zI-%SRzB_$*pEgG-%JfGOQ}f(b-dhUd=Z-AeGFyAOuP2I4a6ufzmn=X3VfVM=<%8O|En>0*viUIv zsWF5?QmZ?2qZ*z4EnL}@-Y#}#jrkF!JcYBueAe8h$2WGr&tUKq*+Se)<}Sxiw!tI; zChL)eY}+Od=#qlZ(p{sD<3rDzoBz5lDPBeIL2l*P7uWca2-|)ju~8q`0aO1Z7*iWT zl9esf2(h=QBoFsulHYG26&XF+w&&jgF?>!ta#>GP<(=l@^y^!2w&^dH1gl8#s1QaO zkaa9d*s3mwV)w;r3==_+*wF5tbdK;6QJau2qN+N2h?;4sDqnt-!Cv-I(i6gFn&W`y@lM|E2(Nnhp&wYYiOD_uFRP(~Px64My%r7+#VU51 z^+V9-1eV7B`0i=#KgqRIjfa2=3Q|+)(w>mgpKDD*mQ5Dd>VQzz2PU&jzj2H{i!M-r zcNn+byFI95W9S1KZt?K%!^~-IEck@XhB`f4a1MAjB%v*l`{@9?W~wE36Ed8P_F#+K zo zhMGuI>t4EW&8&8PIlMcl--|F=^5N0GqZXx-Y8n8`ZRMG%snhJ(QI5B=6Q zLITPMIck2-fqmwlrZ%@o=t#Xa%DTT=?&yHfCQA06DF3wDWWam#k@tXxx6u)@NpHIe zEAq?T5g7l^17py~_c4wYbuVoHlSbd80`Tj)t_f6QN#O$!o~@LtZ%=i4@gHB6yw+49 zSrC(CI)gMw^8YVK-tu?U?xRj^%gHg4&NkB8=|q3t2j_tJiR7ut z@5!Uz;U4fUYaM9~i#ZWP8d-qXJ2lgGpn)H8MStILbMG}WNyK-fQ&<^jn;eG18mO(Zqq3H;t*~s2Cb$A%fD`E!4@(up|W1CeteXa znVY|le78e=hPO;xs)ap6Gw_`(r{OR!%I|oRv+&JKeRX$HLq}IXGET&{5?C^v{vZF8 z8~gp&KO1aq_43xtH&(eFMI!bv2TqvK@v_D%$SqatZtYiiqRB)Zx^iJ9z-xKHmF{07 zA?9R%HNC(zbcMeDl|ALa6_E7;Q1ZpOr*L*8R{3R@gMjAL{4pnkYiP#gt$P6Z3x=g6 zpGY=(=8iqMEeLCJO3D8o;JOzm?ceDK21;q$R8`BLJpZ+S2fHc=|F(p8uJ6K8sj3Fp zM?dTwzWU<#Mz>Pm6rkshE>rDn3PT#oYyi?`t*0-$MuD9&7qbmjTte?{kQ z33Ail)BQ~z2!@apT@$o&44ovOqWkKML3dn%n#I4LBpp%XO3T4MSVTn_g@Ce)C_ZALscJn*6GH@diA{iUuTEzf~ z6rjqK_T^t#vxQZVpsRa+oCo=rkkP&iJS*Bk_bN#;#_>TycpYlt)y>|Yt4ojzJJL1upK~l1m!91RQYN4p5^ZIRha3bhY0Y@%`g)e zZCU-9{5xyPfiP?jb*ZErNi?#N>HCvxVdppIj{mX&w`pa#ZHn22KE;2wjmus zPYp}#$W70cOGgl z%!w{X4ImXt^X4}EW;YsJTjNGl?G)0^`#iK4C@?8U>_4Ubx03>)vz8+DOBMs^*{I01 zoBw4HYLXN66XD?6+Z=aV zyy(yyI>gDDe0#(Q^8;j`+QU9k#e1vcqM{cjSFwO(Cr4LHvSVWY#-c zVb=|swntl4-?;U{J8tocKL&_mBwKWE z2Az4n=L{1Zjws(aF@C#)-}-7_hnk#v9>@Xl;i@8Ot8M7!?}^+wcQp@_qgk`n$pn+9 z6iS5yERIo)^&?KDm0?}(`f7&XMF<|Q0YyyCHZr^Bs6jlZ3-(F}w^2uI{5k9qd~4;k ze5l?0&(%tOS{m(ZMoH)F6fgmN1yq^G4$Xt@@16@vj(r!0-V1}DDFPV%xK(L0-JYrb zQSu-&jPPkHk3|!C>W=8+YIugnn)^R5#n_~b-0Ce;SQ%)DyCV1Y>#rYY)V=3Y6SOwq zVO%!37zU3X0I@jOLY^1cX)^ZD=_AT~7QLF12Az#u6<6rsvqLS>#BM#36sb! zURo*IPn~9eBzwCEbdesIgpX_qpbo3^-wmbw-e?1L!OyV{$$s_c+A5p*n>RmhSK0tf zg@PfKW7mC2Qg|R9J9&YA1lIg}Y(J_8VI+2rl~eP-mFQAs@obpUV5w$?s#EAjg8y!1 zDy3A_iQZP!I(sXQF#G_?rw3#aHKX>rxcTPF8uyqCe1SR;zfk#6Uh<*!o5CDvk(ecu z^NZcyjpW6fX0^x@*EhAll<&6T&czpb?Yo=&Car}8se`!RTL<}(MJ0$^_-WTTn~5Um z`T37KKO#2T-GzC`gzPlJc;{gUVnzzLi??gIXdqI{Lsep-5?`7{^0d*q9+j0}AHd-xN<_tZ+2TBrJH^B2E;B}pVE zwOB3Pi>-*gg$?_1*VScFG>X(f+U~lD%MMf7akrn901rulo7UFjI)ONq{$5PmusTjM z!IoW$Mn3#!yR;TYUsEzb*OyjlYz^tyNck-sov};5=^lh`A|Q$k>BE+)VHy7NWD1Sd zEFci3D4o71e|O>bus53Os2ludQ+P5c*N3A~fg$kqMYqo*1wS0JTdSxk1U#Jq*?qSB z>QUMUr|oEJ!9rItbkZ+Eq#ZxNC1AZ5vJ8$U%%lrGY>~GeP@9=bQ4dv|ajF{+`u=kR zUKiKJ+1IgrsBM+Wi{;0%xZs*^HhKBiE5a9>utgqnZ+ngl17?^BV>j(Hky0gpXE3@osNm<=@FCnp450Hp=&bZGG z3eCd?rv27zXmL3-w;m$$Zq>OocTTEX_-D{pok->B<73luke|?@Ml1CUnG>1jB8$ap zy5l}F2F&ApqM#&8yp&tbW{H=f_}gc8a>U!Y)>wo&L1C{cjM7eA5P#d7?eP>#t%jkC zTcXjKMKui$p&TD=9q1vffQZ}OxcJ*Dxkc_f>2HeuPdoTs0mW;9Ez)kJ=U@i%v&ac= z{el<&S#lhL)Ru?`O?T6R`*go(!^_T&-!-gg^fB?Qd*br>6@B1yWa^%=tI*II_d@c; zce|55gkdo+a`I_uO0z2Sz1G)LQ*!CuKcU9og&&a<#q?`o#ibTVN{Lp6Psg@d*;>Xf zY40V`dkJb4MAW_15>~u1Xi(1#pZu)A7iU{LFT|7Nd$2lK+Z)e|=s1TWZw)k!b03N;uU{ zHD@~cu&+L(zaxs=_Em+jbZ_BqHqsGNK1>|!WxJ@Wc2I^MmR8?g09Yzk<6<>yzN+Jc z7so>*@E2jffD++Wn3ie@GN}^AKW?7JYV&XHp~X*z{B_On?jQ#?RJ~{zy@QKbk|>pJ z>9(s{OQ@vb7b0i>w21Px{l^1tW2SCE?{US`drNv(k$JcAVWa)3tS-si=V0*KM&p;( zdUi5w@Sohpo~L+gRow|#Q)nKFMOSnwJSD}e?Y$>8`z(<{_|fJ}PDKP86OIa;DF{qO!t)Z{|P?EP}idG|qi;UvUj zZJ>VCC>I4M)@!jTuSgw7*GFL;q5M}Dv3aaEkJW&!tO3TF%+mPHJW3;M(Ay`i0y`FE ziLT)!QpoReELJn_jLkKI38YG1&CIUdjt7qs5b5l*Ou zv-SP@KMR3dwC3#H0Y+l5>>AQfg%t~_t-0)NT}WFUTLBF^Id@Ay&BX>UqXYJfC>-tl zdsmQqAYFZ7)IfCwmU=BLmJBhEOv9aRnhzVo*Bb| z5I0t`FR^`kzs_u-J=~a;Q|!nioWco-F8zy^J;~4Sr}n0`H8?v9$cesmG_xDW7ZyR> z+Wlw=UShKl(0%M^<;?7nYwC~9jBlL|6@QzSb!m~yM&$u!LJG@1Zj)+TrHK`uCaVDo zwpR43Q|c-{$cOe!v_Vy2UIGMD!^Z6EOQtV9!nj%N*t3w|U}Hl!-gMQfzOfg?9ww@5 zTxk4}#}=FSe)z_xB>W|8A~+|-VXsVYFRfuX9C|}eOvSy9GPd@+Zd2Gdwp+FY0Q`ch z)W???#u+bfYjaC zj7f+*H^G>BV5GG#+<>xP=ow@mhpV{*sV-&N-L9!}Ra&8&jW}TxI?Q@0v_Tk z(5d>w=Qw#XuXk>en13m=x0tN|hHs(DKc3&t<<1ur$dt$KIY z%!;Akk&8`0wTXudSuy$*;GB!32KG{W{1iRFrowxf%~UeFcNzQ`oV^GB-RLbsN|9^x zX@fo39R92@(>UZg+#Eek5arvvM+-kl%(N^xq-Ngkl|9YxXWMP(C#v`p@^ynnN6tjb zX{SG-YjyjmWB20MaTM6>z@0#XeCM%!qQnv>^QzQ82RCh?>QICeT zei?3cI!S!#e&vGF^ufK#+7<)_{5&WTl@Up`b7Ia1^B3=#?Rv=hmwbp_8f(Bp)4bs1M)HHS7T?n!ZLiOyY$(y4dU_E)P8^8&L!Wn@ z>LQWPpV|o;o3YxLdqt#~OQ!-*mc2oV&tVX^VDL}e_^lqtrfM8!JwG$O1d5WI{I1}+ z`|{de*v>wuKn*&MwYxCPL=^j$goeyNs`Kp)e}+#yF^@R;ua$Ex|Kso||7IwpaCIwU zW>KQnR4Tvgj#{LIRkCv`##$yVuv-327M9qo#Vxwt+DNYmg1nwSV*ED`#CWuQDLl8-Y(Qx>~6 zzf8q81nG8-hc26Bl5T*y7VqzBCoVG{`gDTCxftI8-q{nHi(F&wJmRY!zFL9w5nb`B zog+nk-sBVJ^{(NUo#J)9PI9!3&2+)N~^gGcv z8nz^GD%0=tc-|^9T^O4y#9N+$H?lp_H(&iLueUaBJWaK=RTaV4b~p*A3fg(NEkB1u zSt^!91}R4k-!sR4TBeQ1`H2>lfhOiUkmVI=!W=s(DbVD-u-|uEgd9h>pO1r%dk!o; zC>uo)$Na4YD<-*vfNr##epNg3@L&g6qKSH)o0K9lP-X4Uv$kZbB}ddc2v zDN)?Z>jfFmxY3*K&`EyL%yO^!t&9|;z$65Qf ztU?Z^v;fn|IgKlOnV%Zta^Lb4TDZRA`P$_RC%WCnAg}1;WUOfhS;l3AGgo$5gc4)v zj1LzY$2G5jH(oukhF*FA%OoFhOX+WD1Ks25PwnqTI-`*9>z{}QIK+P}%c~_>EsQ0v zCPIw}Uv-#49Nv*ag#*XqY^b_1vUH z$o~^&Y4?Ik)xvDcfmpdz4+b~!5pf3n&->h(b764$YcOsy;l@ucc0&lRB zxR5q$=ie4&09IK7k9OAJ)CNle0g9iV!r7Rt88_{UHyz&zhMf946R6OzHDm3%cK+b6 z1%B?9t=}v8%+`@*Fd6m3)tIl2Lq}hTO%AyYb?Enw=h?Q;u8_Yqw(y_(;ftC-(^-j2 zIeLDpOec`=u?GJc+m*cYq;iw;rTWV|C{iZ5MxQ)KuZz-hcSAGVVunGONB$Aj-@`Hc zg=jbt1yOQsHo)uzftakEU<-QjqL7-X@hYiv+B1m+$UywgZo<8qJ4z<^$VRQUAwB>W zx$fN=pR621x?HQzoe5Vy12@RQnfdypqy34kZ}tHQ|F77zi;T9vtwh3=xTNQ(lV?3h zn61op1krlmSF~?0E?exZ({*!pL{W6fwV{f&{f9^*;Dh1ee1HwGHQym4Hyec1EzWCJT@>i;^95}e%k4w0F|sc`v1k^1Mds`*&)CgC8y9;A*VXdT!8;7z%iq$0RYxkqd5trk zL%p16BBJMu*D?ZSrHa4=gp|49gjDefN}Z&OyN_f4no;qm55<%!7ZEASD9|X=`MvKb zaC%kyi>9X*!fYXeQ;qBBRvV`IcLSoGl~}5sZS9Sy>)TK$?S3_-)6#0=i;HF-89Zx) zE~qH%%PsGh)MT?#8L0F9rb5XmJ!z+zXc0A=Ee5+gr|FbaG2mZz59^{%kTZkqp1$CM z#?EVg_pNMoQC8WPdj{~zXjkmXUaj0l%p4~bWWhA#!p`k@oyv6}2vNNTXqz|rDR7y{ zDw0@ml;09TTGl$VY{X}uyc{l&cG-#RT$JF}%5uDe*5IpgcqzoGYex?KQ^S#Lg&1~i zi~Rla=@5NEb22K#A#2Sq7E$pqcO~kBc@&vEx%!GzWqLX3ndu4d-zp~yk$P*}t~%%q z?c2`v6}>X&*8CNwI3O}hwT9mZP-($B*e6F4GS564mtu2tzFM^|pJSZmw7b=JxQFBG zmm4~q$TNN9G^$kF!qaz6n%2lkK8~dyZ8){ncdF>ltc!##ON;3-1tRgdE?4cXgM%mt zL-65`5V?JAN-2%(JX`kGRx**CdAGHxq=>9{M^nxE9Q^kM3=1d*Ak=uIVW59 z>dNQ5m%4|qJ$>=hvAm}w!hqE&`{vVCiI<0k)Xdx>wc`y>DRfkybliXWgxg^C@U0>C zP_Y8z?Ow%f#9-&J5jrFPhPl&MGgR0g)#unNkrBHJtYeoZqyLZ#F<=1qI$Zr_jPD$$ z%buJiM+KV|^!a)Hy(3MOIuj1&d!Zfc#?6n3O}{+LWfUK|98ZlHQsGc;|Bm>Dcoz*+BG{~}K@Ss2hw2;?0k=J;gOe{mcRcxroohyCm37}JoLaC5nCGk$VSnTxw8b}% z95vuv%pvemqU(AYJdfEttlsB~hg8|R+4Ub={?#r!=(#_BvYnHoT`0)+Zg@**Us}cN zh>~4-EthU>W}2Zy2o!1hx+>!V$4`UeTn$N9IIom@*Xkoc({9P&Zb1_ z?;!m`vK1#w`NR~>sn8!B9FOS#=>9KXCdZNgzQ*M^^k0k}931RA?SC&-pL6{8m9Fmd z|Dt8$xTO1EoJk!2{J&UPj{Sch2Y>lMV6M?P$Jaakm2|!QtkfI1kM^Ek@HPMtJ&|3* z`ktSmsAinC%tH?{q%>uW#CGAI&vjMI2Ksz6x~&eX?8y_BDVTNqkmEEicG%KggjlFD zShS=kGI(w5h5LX6cPFj5%!PPR+v~6RoHbe`nw4sc80yO`+V?B0E9|v&?TBpM>A>}$ zRsNR=rS#n4V86j*mxcoPD3!@?P}I+wyKOOysTEb(! zeG~cn^YtjJwF9^ezFkGB;+_!XfoLOl0d(k`640-u&cobJ&xNRFd9i9&eL`L^n&z1p ztY)~LSI|d4w_;y+Npp~fI)5ZEC!+2hHIOGGj`pAoN10g7tk5jCu3d!EQaOpbwZ!iY zHz0d|J-eoI3DjY9#vEdf>LFW@{ zGL-p&!f#AlfR7WnaS5_9?hYS3*%M=tdk&FzhsPe7-uQQ=UBW%uRW(`#KU8f`EUzr_ znGB7+=vA&i9kV+pei+oRto+^Qs1AvNP*M7{_9;ce8^WgV%>)A8KaJP;Ss<2etY#6a z*HChoef%AnT-z6AxF;?);xMTU%d0)2Oja5Y(9KEcgbekSamzgzCb-uJ-tZ$XY|MAX zfeyUH>z-!}Qo0D{kr{{xYS#2?1t#sZQeN@O$r=knssVaOT5QiloEM#Icv=B!O@9`| zCc2P~;|Q#6dK7(Si|mFBVz-Ajd)wPW!=~3*eX8p2;sX!VyMK*5VpHn-w3)ZEpRStS za8%=^lj@}fL8gjK$EOj()b*nY-qP55Vfbt5GxyuuGV13&+9Dg>?~ghq2fF!EjFzCa zKKhr9Ex1oap)*PEPAb(H11njw)XXgV{nRw3v0i>b z+wfe%`r?$`{_Ag@97=sGg-fLt80~K*32ASsWwd&WODQG4!4DO@Zc-FK(2T*eDNDyh zITzgn0yFzZvu_)Z^$G={*im`!=2)@R;huCz!5u6^xmBq?hb zVdi(v=;kO?1ZWQ+Z4lx>_D}apTa(O}BI@pJ?1c+{l6tOr2RrtYw7Q0?B$;N)D9IJuoTYT;Ls+t(suCsaU zpQ6FOJ4$xWZ1Ix4fp;9#?-JZVMk%o7YlUnWYV5F!{Uw-Yo000OU`gb6Y<(mK8JwtD zf|D&wgKn3Eg6Rb!0&m+~eJtYF?4;N$86wwd?Qq|kb*Ar#*2jo#bp9y{R(wc%ul~jj zIIf$yYoeY~oEJwYmut@XKXK#<_D#7a{K2jBOg++DEYQ=X(Z_!JOys1JOiXv~(O&S~ z*|7{~%z6YuQxQkTU9qo$o5~qy933fcJwAcgZV3J25~@Ec4&0nIsn>F!^%9*<3q|X0 z{@96UI%C?Fj)JfEV0rAHG|Dr3zP&rMf^q0=1iSdA(+je#nU}v%+cBv5?Y3g=$!cSs zqog1Lc1@|*V#{gF)iBmS6d(Sj{=Fa zA{amP7@s^_E`D-u=#BW`<^$98z6FnO(5DZ*bZRX_bB_%T*nQO_z_el6)arb1NsXc> z!I<&xj#ZBY*u!zA_2QXcWKjRdn*~D;C8}a*dGheume<|}&H|+cJ_Hf?Q-L|beP5dP z)09nMo34@-cJlP8Q%qj5#9@7;Z;MwAl@<1 z_k;Siu?hjVvt@_~C|*O|pI-G~BQP(D6ukcu=(smn5{`aR{p>+S58d5qXohwl1&Mf! zRkWYOFGh7lR6+rLYyOMzJB}&or89MzICq*b(p6Z>l3SVuvEPo!VW(MM14ew@$i~aL z*Z%jrFCtE-cH^h10=vROA582ksRRu925%=WE~T3kP5_R-`rw;fAQ~h*4vW^9(pb^P zqd_#m3wt>kLA&?gaRllK_`Sw0-o~Rg{cGBmSTO%**8y9*MDHB5?48HX*3(?bJvoOo zdEphFz9(U86O?~UpTe8hlBZN|_)Pk4jFlK3Ak&*gly^V5k4;5NN1VQ1>chb#s#WZGtYm4ZCkm8i!eq!$PcC>nj^U zL;$<%9WEMK+~7U*<5~XvW{7%uBX$*cr|dNl56QKzS2~>Ql%j?+!`AfqeTX`Ef)kE4 zYQ5x-WLEFe#8dr;;Q^E*FmznQgMupmi-}quGBDJD)fJQs=ORfF>}90tTejG#gHl++ zM8a41Lvzzj2U6aD*G$F5ba%Vi5}q>k+fJ96qD`ZjPjjo@9$nbnr&xoDLXE(vRw2PX z0jaN|mL8qm5~!X1@$c0K7AA~WSjN&LYIE1paK|j17;z){U-53aKBP`gDp2qnWq(3` z4OzOC9SEzJ<-QkUPBTEOhx8kqa@M74Hokk}8dbKj-x!S_<#&U5@k2f8ox7!& zCLTb+Rk8Zos)teOI-<{(1pP!zoSH5nBGrXNaCIb4_+WvcEie}u|0(EFlTESrJbrPK zU-nLA@6h7DcbnCZdchhAO68Dp?J zwpiDyI2T*+9szX?2`|Kz-)$a3ygtP7^U0Df8_NcRieJ}~XWnY4_)7eUp)Pt4R=l6& z=}UUl;^$Unc^WL-b6Rjt@Qc&Ol*5L;1e~IMtFZ1wO=t+y9G^- zk;f#Cn}5~wubQS8U)RHTDxCmGBL+i$WvtuvKOEx=opayFc6~pHnr{t(nFq&)804UU zRZ>UMX0kv;yTT`p8ioE*0;CM^0(igS$gQK+CQsA|Rx*x*HFPofj3;pLoP4Gza{iUS z^RRd5uNsedQ=&@kbh|h1SlUy|IH$?G6ayM26q9{SSqLK4pNyxx0T!jvN@haDUTIB` z)ve#)Iy@o4?;~?<`Z$YXr=fJMipzh4B)!!dg%=J-5~lZGYN++|nkB9oBXU+iF#Rol z7Jz>>Ci&nft(m?i*@$`}6(T#bbxcdXl=~%Wh_?*aIR)A|TYh+a^G}de-J0=i4y)Ok zERH}<$d=^>rYV3uX>As`isGDfTYk9)V~w8?K0%PLu#VGw^5hiRGUpp10}Xu?D_vQZ z#lxofVmZ9f!|aI3`TP{cnd_+DSA9{ZQN3`dUjx=K->p-_Erpd*;g~E2Wm<7_%F>tk zQJv|A4t#>5p#$;T2tt{!w`Mt!w^}1@c1U7+@d0Hk@I~`jB??>!&upUqq8tMDEyMxkfl%XYb^y&?`$d@csk`nxqJtYujPAw(D9 zuL@Y;VPo8Mr~|SD<-+}7Q&Z5)az#R7fs|{(Jb%4x=^mCXNB^b>n48Q$4653;o0|b? zICucv7G#-0j1q%++CVLpC|G1XZ$`=FiFPZyh7#R*+{ET`L1RDn>XfU?MD2gO?lV@0 z!r77(ET#XYt-AWP^)i_6B`*{;>icH$(2rp8LXC@(q;IT%h1Tn%qc*WUzozm~(p6ly z?xoH({lhDVg@OZ=Rn~oJbLrAp2Pxk07Ab5aKU0Rdg zH;c-u&H?)<>C_cSYS1MO_niwL&(!{)_ITW;`&gh$D5obfdK#+^$X-o$ei=%njlrte zw`^f5OvrbAd3|v4ph|Z4Fw+bD=*o~_pq$gi^dIJzLhd@Ri6jE$Uq|WGh4f23WV=Js zp7F*t53As2@AtU_Ls3@D3oPGf)Szl9oN5)EH1m2J?0{C;B(dqNq6VmJQ5p^ohhZT$ z{Tlkais_w=WWT2;FOH-R9>ywASCLbDegO@%Z-Qq_zLMB=ci6LM#F)5_<>z4Uoi8iq z-QRXY?dQhj;e5%8dC9a}2xMve(QCWAYHsMy8D_7mI_jymtH6*7ZC_E*WG|U-;c;Z~S-B^Ks5@yCYg+Wv zyb{J_hDrXt8ZCt@5!<$F9U88zaQ#%+-A7g*CTcey`Rv(u=at?W`pGHKR{7Z#H-J7~ zAMx{@An!3O^+pvmQ>bM=ZT6{po%HI|r$)>u=f@l8@af);q1Cl$(L7$2hpKbK-*9ZwWNd#+9qFA&WaS@f5|Ow1F$a-x3Xq>Z|xPH6l$b%EODKu`Nj9OaZH{Cg>^SZpQRFf9+4@SZH#VNi@{aMcRy%AQ z+Y?ILL%KR$tL3pGQGoAg>W_2?yvq8(H5r&8BJx{1&~j2aB!)!%K)x0KLU z<*ay&IVWh(D9GA}Ubys@d$zK#?AH2@m9l|Gu)a35`$+c_7_1&w(ZHrRpf3H~dUoJ9 zbAo!G+ah}R!%_bfL-9)~$AY)Vl5hvxUEpRP>dj}2ATT5DS=6knJ!}8`v2gnap|r47 zzq7FqX#r2}F0#Xdwvs<73W>8@W!EpYtc7-^McW5NL*Ek0$^ z!h#q&dH1(YF`X$vy?(ZeU!x57ciqFt`fBL2*Y7+X=`;Misq&*LDVMM~L|$H7o+dO8 zLIWD97h}11~rNKM@D{u?m3{&cy)CY~iHSif7f0>~*#_#F||nF+Wzr z_lfYyJP7e7BgD=v^yPGfVKA3FR2)8P0E*w#tkSU+7*E>~PK;&RV}Gq>J$O8sy!;Za z!Glyx<$w8Us`0ubu9O(B=K}88-+xl75uMtv=t+AL2}He*lMB(mu|w@L$VeYQ^GO;J zBd2r_fh+1G-_{yX*FMAd9MTVc{{mJt10>{DMNCpYC8crW(G5vKv0M$W)kLpWmHfIt zvFmNa3@jY8^4pCdytnP!x-y@^U#aGCV3?}qlF{o*^Dhv3s|dQU+CNEJ;~_Mw{S0d; zT4h>|ZftI3S-zsyT}4EZ!Hb#hOv1pDid30nzOU`+TRbWi8pj+QWtmH}@guBErzOQG z{$xd>Nd19xntE>i>JTtZ12 z7z8_`ooOa}5F_L;f|ruugnC$K&AC*@ZJ?yn1Tqa(xDABr?`&*{W-4zr{Xy}iOI95A zxK|=`%t~)$4%CgDoX#6;I>^FwK;k7-Ntf_#$6e72=B)|Sv3$Eu<>ORg`Jx~F$T z4=i^fAA$|sLZWSmvo&A<|fb(X^&6P7Ze<9ED zzIN*$nhwPwHNH^u^cSYKu4?=W1PmqNe9_-*Rl}(k)o>rO!gl)8Qj7gy`wFr$S|+B! zvLXow&;I2}rhk8Xj5PJ(*N!w?UK7msAR`@f=94%g=DN~>Ce8!xhpl@3MKgA!guFh5 z7d~m)j2_f6WmYbzT$ANBNcWYcT)=pH`5+zA$!_$}w_U079tOtvF3D$=VFixzhjPI8 zDlz!JoTC1-j}Gse6N3K9a{Oo2f9i}&vmb_PzEUg~r9B?33DqQwY3=bi?7TZG4%;eL z{Qny@^U@ow%9DV-?s|h45tTrI0fqAYmi@oiDJ-WxWV}spF=T8XVo#13WI4LqTh>&9 z#%U+UULCf_S{?r;(v&8NmKL^Kh#ZtF+oy;88$Ot7B>-#!M4;zcFEA&ZX{6*;=EU(+$BMtw}06N|*SO&zzDL(A^Jq zx%q817uW1p*n~{cK?(R#YP110ax(t_W5UF!WLy$+2Lx6-CVu{8@DZ{)%6R@Kb8wo` zXmYFSY)1E7EpmjVpf2}eOXJILJ97^7&#}Ug-nqy&dvB=DWGV znamUW=i}NV?xH?~Er)L{_azbPbWrFN7sP5C7lsxgWf`T0T?fq~OX~Z9+3XcC^V6J* zQ^g>ql0iaJ zMnA-=&<2?$RiBdiFX4T`O=9`?Ip6auHL&8*(U{E>&oTAO1J}@4X zIv7@EFQuxg9T~)Z3_Ex0#bkiwJ+v9{Zb0HfZlIA8Z8mC9k453?{IHLl4Ak;mSCN%R zl@UDfPn|QQ+xaeSy^k&z=oNkuu~4(RgK_z0?rsv^(@Lue^N67Du0D^I5xZce_}noP zQhUfe)Y(S*#-V0Erql76ws4Is3wHRGSWXqEO+hAXBX#^fG7e`hxJQ5gb_~w?TgJh*m#oaqPu4bdt;~40jO|}vuVW$Ra#$SguT`$m-L5^1H1vVEixe;|#7(o4 zDN~Gz>HK*6kK91CBb|O80Q;RgfN;jJhmyRIZ&=^rq2{yDD7`@a8A4j#DSMW~zT;-u z8o=UE&*|2`G1x)pxsQJP043ox>vcctRX1?{evzi2a?PIbQ9cizK6*ied0h;@%8b9uYx?G1sDyz5 z;cgdO02Z3J0}#Uhk8!e3UB;#@Wq^#tGtK$10sI;D29WFa$Dem49O(gHvG|Ba*^^TE z{>C;u;39N&`O=<9owLA&ljzyyN4Y*OLY25R-9EXPLCG`8xWk#yY}a$+B-*0!RiLw< zez9pNx4rv57&(;YMDf(g-0iHC*2K#J4m9zI_{o$yO-ZMQ`a|74Ij)b}r?hJn*Jk2n zTn1A{@P#wYzkx%pIFS1Qy2(9V29l#_`Ic2|&3Cl{`&7^MDBNJp6YJY2fbN19fz(V1knjKRU4^m>v+&a>sZUPOWv8^^p}d_ba|4s zKx;Kp;NR-D7O8TbIZ)5-zev8JWY<4%JI6)vhAJv*P{yFfE&Xyxd?skwwxPLa!&JQx zIpjXRk?Q%~uMT=G5@+bbdojwm%%3GyWpr--ctSW-RSq|d2J6dwIvYzLl@^;sjzgWf z8vBAs;$ulzM>&8cjpmctg^{pgpm)=Rp-L^}iuTlF4j(XaxX z-VOEiy$aKxGR8~QjPk18$hSr!@F}dvEIRiLtT;= zS@Q*$T5vWww-*7?N%P;ku{*fz^rK*KrEXWwGLl9gu)f2=j0R6`ynl=d-Yf-6Y=j61 zT{x|ulr9&90cS%+#{XrDZ5{?OFn)KSg9YnnR;9!ed;@VS-UX?DtsLFFoV+ExLRuHj z>~g-t$>C`&E2?V}RrkbzV3dN{44;XgC=GsZjS{SIu<1@>N7!`bt&Xns*~etS zb!bHP*9>80scb&`+-iz~;mXe%%5@T(4_~M3@LlxB+{tI)=_L(VUe@uddL-aD|X7H^k_{- ztlgkCjy*qEK30+TH{v4MVxRFa3KV`1JXl?9`IBXL+l5()`-3C;(tQhh6h0A?$HTF? z=D^{7R6AU;o{Be;dgy16BjYSJ`9XI=Q-53qVTGZkW<2@UZP$n#(mQKPqC?OZOB$wr3V`rDCT-& z{uHPF@l+H5Km#dA!O7+<3J^n6X9Z;djeA?>&LPf=lfF676;|x?2~3>2phr5?%qHrQ zcyk27;8VHcj54ZM9j`N8crh}0Ag-P^QA``(J*cku5k6asPM`>Xv+u@fW3EK_-aZF0 z8Nk^*jRIzQup5KFyam4Csx45IYgODz0mfzC|6{&8n0fXqDmhNq%FO9zPRBETXK!F= zwTBfeV;`CIa@4Rn$nVTif)BYA_2-vU(uROI8?7qO^hV#bFI{wbG*=0Hv?oI;_uE@~1?zk-_=0dLrZb_~?pdBZ`nV{JktmuIceXCD< zXKDbgk!x7=O_2oU4m@N17ZXne%Z0oB#l%9HTrU4(rtx~`uHw8yi-uYsqH)K~AJ28* zLm!2`qU1dpSSg%x?Uuxh z;>x=@`;2kUFF-c*jW2}`EGGylQId>;r_YkyVxtUH61$KXK6)+J!sHbFHx%FCXn^2WX3_9L zL`*P$rsfVzPmW&Pue%ahxE=4Bmc%abf@e35@R@{!=enC+0}seq)2Wpi0!G{+tdUeA zF030Ic6h?T9%+!?wrN8BMzECa9_%I1+1SZf^{c)o^gFdBVI{ciR-V3hP;@kKK`iTz zCFK(ccb;7WrT!{p{(&2e&HsnJ_l#<4`}#(M3fO?7*pTKC0qIH=Li4B~U4hUcD!nT$ z1PDPn!m&`K#n2V$Ob825cY+;REF z&faU!z2;hT&GMUbX81tms!TETAKP@?qs#iW<>b;9DaodX`ea$R0!k`n?roUgnm}l| z+}raf{Pd}44OEh7L-CmRP5ai-oFqIwzk*vSz@*fjB}GZsxqev-+(h|g^E3?2qZ$fc zbLK4oKu=EaqE{`zvP;!AKLZnmu*_VMd zz>Z^==#~W4s{I4c(ovY!Wn8sZur{gy;&hv3DGQxWa=n@*Oxxuvaj-0&cPO)}2LQocyx#;y|%=2)@C5 z?A&?5Cl{~h9SM^BQgaXou!rnGa_k5IDyGRejXwA0a2VSwJieGd@}mNbIoFmn>0%=D z88A%+PMXeVw(Y*w;9UrRrkPHbCt`VH;8p(aK|;Si58}G}fBRQPtx53hPZomttiPp2 zC3il!6BKPP2!T_RvfdOEZq|@ex0W-!!hWoN==j3d)H?kkzBetN&;=tLmZ&?jUvm3q z3};`}bgne>R=^w(C4Ydo5U)Sn9$9F*(@ZYKhDB5AW&IMmbFyzcB`m}L1mZ-OM;~>^ z9(G(bo)jl$(>_Mro2~O#qDE_+w`#tWFoH9k&8Xq?)wu>|KdL;LG3qHz2tt<)<=k&? zA!sV?`)uD83KX{CVdOeyPrO?b9|>`c#JX<$hC zb^0M$&Kr#dA7*a?VWYY0FNey_KkK{NQ995`0YVn3n%28MlKxv)iBm$uRI~MqM_}PE zp*62i%{Xtja~rnyvq^;SM^Mr5>?lt;s>S^DyhX6-1d*PL_*$$H;vF{gR%36chD56~ z%O8QCp%`SyUdOv~Z!V>X_gHoqt>H47z0Iu}?~2By)iv)e+KP`bKJ8W-5K2tvBdytK zAwX%Cn!6b8&tH?a%TmbkcAGGVrt{CA>Sl>VmQ3tQ)U_vX9KR$(=|GfI1I3HfD-n*N zT9Zxp!;A@zPVCQIj4#$Lf0IV?Fjdo~sk<-MDm)x-xM#R{wGAX#PQrXnbePy=A4K7U z*UIdyQ*yei8QD$}_M1fvGZeh=aH1)LE#aQFU-WulGef8@E=YREzW6q&qz_lw z@}Q!zNxr^qcc`vCCfVJR)tqKOW8Ax|$uRs8;~u5H zWSt(4Ui@tA&_5twG{51gvt99YVOQDgk#rCvji;8qk`lrAmQp)>q_pBS5%z4V6$rXl zW+fvIpQk)d>?UUTN6M1Jd^JxF-MRS^-v--sO8lHq+3|DQxw`$ebbtG>09g@es&^%n z9(3U`V5{K5lsjW#`&(5J{Y%VhZD#(rQ4SZh6=V4CoN$-^f0oq!7#q))M!}a~4ToZg z5a&p4GV>Q_LNyA3(U*_}G^zL{eE#{w@M(A9Fz-ddZ z^&wdR1`ZMy=uqwSr=3QWLzvEAz09IB3el;(U%u&0S&if_0h@VOCp-|aPP23E`-%hC%AxUX8E&Hc5ew!Yb8bHHi{pPQ6K3iyZPrQ`O-uC( zC$me@P6fM@&C-?WuA+9qc2>*6$*>Jra6((Pi5Ir>k)4|e+&D|+*`p@$F2!sI z8J?p@7Eh@>5nz;_ibs&Ui?FMNJ6_P zDD<`g?4Kn810Q#%Sc~twNgOT{96_H#EYa&LN{b&@#>fkQlq}d7fqBy> zxFSO0SiUlGbMI+kT}gMWyE6g#RC7%MO!+~1q9mQCLDmZ&zC(u$curcM2zoprltk-g znFWVAWYc&U)oBmnRGSo9gjG3*llax;7%8SVg)Pm}@*g1dD~bZ`pw55+$UB^}u31#> za~`ahDtPpzwsg&V7j@!|c+ZYZ8P6a|{|G@*6b7=en|%*nSg233SWb5=TcS8B)r=Az zSaHAT!j!@x3ES3Q;2c8{vz(H^1ra1SfwyC=aDp5hxHRBzbxi{tB4R?U>RR=lIh+u3 z1n~X^6x8x|8*w? zmcQ_2o^Y{GAP?OCA&oRdDCPmndZXu-zGCp4@bv9`~NzS zAC*sA!CwR=Bl13#j_BH31%RmvuZbN~?D!Y8zZBN8$n)oXJQmi~B_BJ_(i^W9Cd4Gj zZv=m@HwB6eh!>JekAUBQi2f6Dvmz5z9r7P9%G9mPh(*+NV_pD}%9I*a34&~nTM-=a3|I! zvEJRG6s3PdbTg5wwu4o@K!ex)-TFgf`uiFZWZSd*Wu`k@Eg3>^ zyOqqLr@n%n15&Do>WsGsS?4&7W#+4L#PyJ~l>4dniVbQlPQo7$!Ba}3=a1}oUkyZc z6Bv4w_EL${8Gx?Bd#Q4Xl_4~l+!ieWMlH7$>Q6Idh{d}a8_dU5imq)&qI_yU$~)-Z z)GS6-OyKo*ejG0O0Gfpiz53)JK(o>L6jXg(MT(zagQE4`Tf@dL=%X3e_klGjtsaXo zN9S7s9*;GVS!xrmk_>Q-(sPnpFk#noqPM@YZRJIzK+6)Ee7oQoO(>~1y!(|#AK|WO z|LtpPjvY_h@>-~U=)KNr2=r%2nmp`z&v_Fhq2Xlag*QfU;$lEa_j70Wij+3*z?Rgm z$_Jt^eUMMW!0)|pH4h1AV#SB8hrJEWeOLvK`IQa;z-_%>$DozHT54+5i*w}gaXIJ{`MZ6 zTYP(Jz|+fq-|_|RM7%4y>G6=_&JC!@8|Tk3YDz+1Fy?eRO>Nt$yLEu)dY(JgUv{0> zy;OR{(a0&kmxZ?0SsyRDzZCYUzGl-oIaup$vA12`m{}NW(atToWeaQU)F2(J(;}a& z=GUI$uRJ#4sbVIFQbo!i-CS)tnZ08yPcFI@Z$?gP@6k@y;a+5gudWpirjvKT8`M3g z+}*TMGT7p#z&2xqs)dBzEP?7m3n_r^2b`|H!M6hr^?-8W48 zQ#8=gQ0_!mfV>xHO>mNa6h2x#4 zX7BGZ%=PnFl!QnA9}k&Fa1(>(`D|VIsGf=BJgsc z&J>I0&)A^WQ{xhG8+R%*|7kWm>){F;@UPxujwLSfPBKUm_SM1cJGMN`7-6I~J@6HhPm7&D=iWnu8(hF77_u-G38 zD}IWd*N62!6dIvc{pJO5k0jERf*;=H6`oH9aR2k3mrI|{|9jW|L*4n`rncr@c+LK=mPuyR;tDSmnU0v|f!-?-ZdQ!wH@29|0CuX9uj!FQ z?~>bDBNBWOl+V|i2mB>epT3B${^~bu-SVeBS69#n0Q;D52aYl4J>z-RY3@x33mq@g z=psR`SL~RmLM^RxyB_8fJa}!?koh`S7_6~8D`4&!+UXn5&_Zzh+xbX-$uAkHtwHzn zy4EdKCRPx4n!rA!;5R{qeymQxP@3TVjGd?X-0p0yO{3`MYSy>ZzR4l^6VbJI({LkF z6Z+o;zFu3DpnNj7j~7iLI0-8D&;KSJ=qP+ZdY2nW-75vY{IcuhC2(A=grJI6>2fqE zASn5^*YvgsQBUbeVompn-}B;od=q)nC-_j7bmQmJ8)`PC{fhGj!nWWm_Spfb2?;`H zrlm^Vu)9)J=7dPk$xA&h;4QnHvdFNTuJ$G7Pn|9Fx7k7_MW0ri>e*gEq7_2vcf;ng z{*&B^3N*y$hRfgl7Oy!Ur%quT7tFk zruP@kHC(Bg{KWPCGdpeo$;M()2Q)i#tCGOlMpobDnT7;eUq)uXIfqN(^>j=*kF225 z;N9YF+yPaf4>EoG@6wJPZa(pWh7PHT81t?xIo!tA36go6PR=vg}d)0s)>^6n~GB~y#6l$^trrpp4 zN;?(S@lH!HugB7QrO-8$tV&hl>%dipw5@50y&&|QY!3;npRJjgUU>DL@+m&GZxdoa z8s;!&1(~ED91~$pswErgbO=w4el~`lX)DPsznCw*SZ17&@)HKsx!}`~hAnH4xuxCr zBqVw*(Na`dOokSOe&!<0>6{$7H+41gJ(1hB(blh(J2_zfZlNsv`)u^sB=SD|yic;& zroiCT57=-?#L>yZyn4C!o2|)}Mj;I_h|`;&J^HL~}bL&C3# z6Fp1}epz3!Ai5YS9}2aT&l;dh*h!dakRCGJe)92_(B$u_rWiFZ zb}A3r3@fNKjZ2bH^2ZB&b&63dsn~lshfW*64=q4szDsl&ImFoSB~f{Ot=VER zL1)^;wZT85A_8wWSwqI2KSXxj9Njb91V=orG*CacSZRR4-)hG&^7*x@TAsq8h?^L` zvB;OzwAGH<%d{z@aBC~=`bM4A$X}l7m{EDMd?~r-=w4)>oNoxLr7tbOBFd~vvvh&K zk1gzn{|xwJV#nx@S+CXuEtU1j#&4z}kMYOXbMCO-_pMEKs47Fq#=X^m2(uf@cvnf>`V3Wg6`U%8F(qlx>{%yehyBJZC8Dq85~v! zH~+|9o-P=3WlHV@rjZ&J?{*qJzUajeL5%0X7|_J!>ovI9h}o+1SXZO){6n_wq$l%E zGsb2Gg_hGxZVfYETU>kB0SM-!xGU_fQjcuMdQyY2vR&6%OcoG;D4tInU8vPf3Y>_)MBfyW+6}E*+(CCKm3v)cJas_xV09L_Unf#R&(HB8V<8geNqRc|tEQ z#&pk3yAQRmU2RyjhyG;++Ai?I>Ty)mruZbdZ|KV=#%ra1swai`d7I4(zSOfv`6d(^ zmm0dUDmOZ6dTWDCC%qQ1wCk@Z;dQ-!RBQwXyz&?P+#~NXlIfyaF7U{>=Q*Zs z`-xj5j5$8iK@HnHmU+VHX|9I%VlYmD93mthsKrYJ4TRJ};{qqf=)d z!o8hhQ^<3!^!s7})~BpWLoRk`gp#H2372m9b8s$rIn!b5QNk!Hy07_rpx)7saBwF0KT{^OATHs!^OC+e8i#?e39 z$Oh^KFKXb3_{_Ny8hl)4m zOSs4J`O-QQ(aDPW@x-qWU}r2%C;x3celOrq+w$F?*V+n6PcgJ+T`SRJ(H>|0GR*20 zxnNdxsNfX^AHu?=@w*Y*4_=(~!(Q)=y}n|XU+Fs8F9;z$c98fU1Ng?{x`C7+RbPsd zZ?#KLqH$5o^uR&(aP$LHkm^uKq@~XFa_is9I1BU5@2eC0sZ&$TW<&e_Bie&{K9`#~ z-}1HbP5#?z!-fBB*w4s%r?%IGg7=?z+K)+TY4n^%X!GHU@YuULv3-^Zr91J~pV`ts zkh9B1b|3&n=VqAp@0tk$ZTC%{e?JfTEbf1J0XQQS`?E&`kZ0Cx@&jB2Emw2x-=CV1 z70sbqO+}m?UDtJ5c5L?=?CmP)&%X~=q-5cWFs#aMPbTzqVLbz7bGpi7;1 zdHSn9m@#SLcqae6{jaX zi<1M-7r?d`jz^rb;19bUks|~Sydxn2$SzxJSy9HCwM_2=6V+$8>Npdf$$~1A3*@^` z>hZqC;SM1kr&%_&GwQ!p*)~6g0<9|9O_z@||NK?Yb{l(W8s3bUH)J5m&aY0?lKRFz zEw6XBa2A@(M}8L;E=yJl7{S;p9d0uvg?;jvg9b^?MB(-vpQZiIUJ zO{UCIJvv&@mkBcN_yDSmCq*_;)V;`GVzcq`zmvq0h|08Wd?~%+_lKO;C@fbQ3bKWS zW$BweClwF5FZ0T-|3mKV@G+z)RUXPzA|o?1^^&%YDZC`tK7O2k+uioX&Row9)kacM z`ZL&H5Cv$-vxsstRZT`{M6+K2LrMWzcbaD?hBGnGw-hNRJ~U-&v|JQ)Amnwg<~0{V zr_Xl1;{1DDf3%5xDV-EqL(^c!gd{)fC8YarpY-&d>cl)T%upQSGBKj{dd$wAxP+~g zQ6kMRSuD-&oH?A4MYs!Q3ltm9+Ri>%-4wWrCR7`+++GS*X0ki7DnF#wxXop}K+4Oh z|M%Al`7d3aJl?{8+neMuIclC2lQ-qc;7pwOJ&Gl_!HHwRV;c;S#z#`~& zZiNISK=a>x&^HCcMkGX&laq%1#N;l1^U3!K%`aje?otV#V;q=ewV|V^CMcS{mB|0d^wY!}JW?`?7W7_bC z&h`a={D{e+JCkPiiaq8DsM%SQ7m@J=O9#hRz@`kWCCREg{oVh>a9~$dytawM%ScR> zPXSu3s*-QyQ#}(4uEZ=@P7z{+EtAZBhs>7&K?jRIOx@&lfpXs1Z2UU+uo>SAetnv? zSOx>~#2CH@|BhRGqmHbP?=Zy)*Fy-ITWg=ARCj%kRLdj~|b49VjiaL{{o^ zRj7aN$VgVy2))Pk{&t_z3-JjJ!IM$VyLv*Ulo470gCItsN@RoU=C@fW`hj&j98qYppYIRCO zhlNhk^>9j31dImZ-9k;OULS6ImeGQB?O(IQ6Qz!uDkR2t|5>A8?UGAsNj4B?hUeid z=B1kVlT+`P!wOs<`P}6#(ya3G`f!7%2<|t%8eo=xpX%37ahm_w4?&MqB)pJU7|!%1 zN(llXy!z$=$vpnBENKNUY`$0rS#>m0+QCV*{;-iu&WnqM7Rjp-3V}{VdL3RYM+VrX z_05U{Z?SKq=4FER1%;u|f0wC&VN}1bf4u>Q!04;`?9)4K88#WH{@tazx+?~g7M z2v75jbCDqqc?B~e<+*pFPs=TB__$>hZ4TL)0HyZB;&9AKT&Cq zNDjH3H?|!u#KcdHM9$2I*lw*4{~`&H3PSTHu*RmNMb;p7x%rs818*&MT{Y1inddp< zUF}8>oH$V|v|7{>MyVePr^Ne|y$;PP2URN$B~R4<@!>YqaM@j&IDAG|zE{L-lRQ%w zEhAkibE3a#SN}fYHSsB(!c4fsz9_yX%LvWqObleHr&swGw5@iGRvu!zds5150i`1K zU!@`xWZR$TaK63O)YWaWABa@lPLQqYKYcb7ec{crXl-~jgioi&Jna1gA774{++Qsv zVi*%X%_d`BhamzS(7a zKr1a?+v@r?Z3-YDI=-?5fvmcHmHCk|NiBtR=Zx`!s_5!nbm*iOZtH;$x~%#>3beNC z8!%^_Ad4Jh#}o1qrPNhxHOMq(!m(S3YOxRz(QXPX*}vt5N2O>98VujQZKhqfbHi`p z5;+4L5@MP)&)#@7KJN{{l;3#8;o{msk_U8cu+K*l|EH#LDlOsYSl52FMLhbuiwO{* z@Ce71>=)~TM_xKv7xdv&5LLPl@1x>_I+AXapPBIK)EPHTeCFn49B_gwF?BpLUgEci zt==rv-M6(<_bzBbfBBEvaY|R-r9(47JoKy4%^jtk-Udm%FZ!4Pb8ydlQEcAuqULgb zkrd-7dcfr3xPVstchPIcKTA8uXtK#LTfdUvIG*+@rJeiQ!FKN1>6vqvr57DMNbe}$=b9SHEc!N%<`^?i_v-|HCJ;uFUCy$qo zE@ya#jsg$YEbJY-M79RXi*~qApYsc5&dlYggP%a4Ys8ASr=oweHO(|C1Ee=n)PZZcdPfqee=xPA zG`hmWGK6GUp+5grxTdBP0SkI764_#{*X3|<>l>id%bylNtAht-g+8NWfWu7B<$W3~ z!PxQ5Q!zxq-NIz+i#sBY2d@HwwoEb?lCvwas$IS7*H8B813NJaed~X{?>ykv_?uEu zo{m`dw4!H0Zf5)aETsF)LM=L~?>Ob>*9JScdoc==*ZJ=$@JO}xTf5o_SMurmzx{3V z{s{A6)XT?Du;ZrrK%dyo@tldiQz7@hOLTq^xVGs}n!)OfiR&w591DOn6%P=tM zpX~|0Wx5<`+k)L;DmoNK*J&! z!&gYecjK}U?>Q~VPq6&?E^q1t0O^n9)cnN1NB4gd)Q2SDmMhT_W|c z`T{ffh=W+Sn+Gd~*$55@i1kz`+iK1<@s@F^!+LopBdVb-rTD;Rubj6Aab64*y}w;a zJ{)OD_T^zt&~ClNjxYj3U#Iz?@+L1aq~J1d_nmDAmHY}I*kGK@Tu&Q01l#fmVFL*N z!29tqw$-G7A(tnckhe#e*m~qJIf_$lTU;1uyD7Fo-zS8ORxl<}Q$VcKvJ2mp&vCB2%1dE6%7 zkaEb0q&U>DkQX z*qT6Uxl0^Ki-t;*^>&Fty^(c><4yZN<)YA|%OzDNA*@-RM#}38K9(8y0_`l#ev5!b zH?|Y&%yPKl9$8BaZ@cPjTNeMukF`yD0TeZRV`eAh?C*xXF1nizh z|0X$5^J2g_-6@p`3P!6fm2R4QHGS48b#Xwr z?^NJbfamdkR;h2h5Q^Kqbl0k#Q%LsT_-CS4Ax$$4B|;N@^RGGriW$asn`qlKB=Xt`_ zmk_`Htro(BS~G&$!NU9|F;hL;y1 z8Z^8_4r_*KX`3CpSknEZmY6NK*7kt@zF8(S9^-mGVNZG9{CJ z0E|yd? z<_OFPOU^5L{!&77?<9s+vg2eN-tNiV5~*`2;K>>*bUy0^C2*4Iycdt|9Fu0BuJ?Ca z-wyqo^!Bta?@rAS(On zuGF%zk+6p^WAsX@=q!Zp5|@ze({#N2cIByeW$^gdEzM=VuW#p=&F7iS7~p!OQ)~-B zAdioY{JPrvm@;#n@eJPLmxYba3=(+9IqqG1^v{1Z9q%WILj*e0&mTSHTXLGLBTwI7 zqdc}{Y~?R>B=cPIPlk@T`r7Th^g4Rutgyw;qT?dp^kULuqOl^$(me4}>R5OCLG7}+ zj^ep6y<9F<&3pSvIM&EY?o}ndaX7vZ&#$i%goDp%78uHlprB=j@-U!-l1@B~1!$Q5HP&0R%(5o&MWv;Tm{n21U0LrmS(mkj^5?Qeq9&8IY zB{%%hS?=TR6FHEpM4Fy8_@vBxx}U)`>xF%j5Gh_CXTsVgEVz^eU%KsE?MA=`nGx2) ziz};y+1c0PSW9QwEz9Rpc-w^6Jqj6WGodR3QM9!di<4g>oD{Oy3lYV2J^<-TvLrl; zPe)xyPEdq&nli(P+`ezZ7fv|mty`xWdqzTrYV4MB~@&|5z@L!F?> zVb5=Xg-h-5r$oC~qc&|KY6IWKJi zC^sXS$1Xv4qgzU=&83bC-g?3Ob_6z_mCW9`eyttMUo-1jptv#KS63ZEAO%>G*&Drs zmvkM4uU4PEIJmOiDis(zB8=8#V|FdM|4!40Q?~Fl;7UkJt)Jq>CXmzWn!Zdm9=_g$ zT_-D~gNK*fzD<6-oTYjiJXL&U?0e@+ITod%SaX`0wPS?~ zWMAvo7EP&t=9vn{_>M*{vq&==I_uA2y9fbTUJ(BnMxD49o3+m_Lp+_RObE%{m!`9n>UpzHKK%&$}6;2C5{(rohMY?KC1>f z<(Pin3|1jo83WRrYDG(GMk<;?`YTWEIF6{=lLX0qSFm(X--d6SDz_y-cEU5&fOO0$ zkZZPKlb3Ie=$&L-+eJEI2Sjz{$A|A#Yh_OiyXeL270cLQ!h+m?g}R8q_!BFSUrNuA z!sTJ*7`H2LXMZ@xSU9`gm8+g(3Ez4QyCEk{x-I^A2cT*tJn(g-M|VX z6{f4}CXM3je3`x;Swa&6*MdXO<65f3j<1t6SJ(e*EejpHl<_hv-1^;iRf0;)q3jOi z73b{j`%IN1C5P|KFCL>`3YJ#jJlw`%mM5bu&$2F^@4afX_!^gg_%4J9)+8sN+d58` zn#LNb%F`H_Usl1!KDk8CKdgq{N!!jkR#Z(@1yoU8>x_R%aJV)YA%|uWJ5^gNJo_Qv zuP_Kght=*~a85(A8;X^!uahh;MLBrv`%FTFS?kk(Ov|{Z3xD$$Mf&W=Bh23DS+7>Z z7ej5dBX>3h)JycQ?BAt1|1w<}sLt13#D<5ikvF!jY_)fBzHghBt1{oh$d<5wW+F^i zITKsIzozaPB?JwDWdK^%d3fy$&j)m5N|JB;031`k z7E{>zsXyMpG2xhx{>_2YzH?*$9m6`Pee!BBCZ)W&<7DR_3=yQ{Sfd< zE&4&ukgMJm>l;8*O|I5wZ#q>ty-c3*^YoZnBPGt;5dn{IwGV8=T;AzebMrCRXHMVa~&}sG=97nmf=rsGA z8IZmY;A+&AEvW_&Xkf1*CrCHCD-Kj${Kxmh;sw_&2iw|;Y}~qx%5huL(gKSD2yo~T z-+>E?sZAvtJ1q+3hdlMZMTQgi9^7^n-!Lewu(5*N5YDC>ln-R+LdrR2K7L*Z-|Y*A z@4K?mhLO(~L+@z7GNzvNg#LPStKiT4i=SA|EX}L>1L*+S>Ia@S((YBIRRD%tmsoS zz1k^KYM!pe9->B{t1lS%*&mKa7PA$Cca^3T`fVmep@iy@mn!{Ig_WQD4k}@Fqctid1?4PEa|Km12!0jAfv1} zYWq>;2{dHN=7;9~TdNUf#fHuLW7Hbypr1H^f5=5b!{0duqSu?OS{6yvL6%9L4BN)V z*X%1ysHNd5A&WVqUGG(o+c%)Bk^*S2aW#2s*-6x)eJ5?4+wADSjKiB#`tmxdCgLP{ zLDeSBo2J(7)o?5xTy$lTd6_4CC<9}L!Ck53csM4f-?f}iHFy#5tA+b6eVExw=S>Rq zD?nO11cTHO_7TG%794h@Ix+|-^9ceS=`>;XAar`IcJ7Z<7{q_=^df%fHd?Iwp~>jO zi{<-9m~ps(wJP^N5o)??LxQYCZhS$Qt(T85HzY{ir9)hZ6RQND3rc^Lz6FGsFlu+~yYM zhdu<#{d|y1EXq?Ig2D{~y`skICIW}8t-dKbJLz%eHoZ@(5(zwSyB>Pl;=Z)y&%33d zF>uf;tCNn|bSX$N^DZl5tL-ZDiLq614e8(Sn(c# z`avJ#9_Gog9Pb;Vt38)jB1}~@*25pZXNrQWiB{b$((`b0T;|_#aT|T`FOBwf6$u|J zMA*Ws4u@Z6qkeBA{Sw5(NxmkPQTM(APaT&<65VYV}kHQ0j;ol z4?#O4@8PpFot4!xrE=k{RPOl4*W{`Nz!mde?X+jE*OSIE zTtfTiEa<{kA*%cy55iX7pPZe9i4%ZZLxuu}?l{D3`Jrt?2wHfPV$@%hZ=88 zC&?(z=36;MoK0QtSo}8i6qz7LMmOMprL1-{1^wDYVR=6pM&W zEc{i_VkBA$X(u#{fPJ$Fp5HJ(-;dFA-w(-&YH+BKK9z)-`55n1wN*U0C_tEK+9;gx zLe~|Ou5W@F4Vjlfei+GB8)@it{g1r~NX`kr+>esuE%vww4;0OMiDQy@3CNqI20uytzTADd&-EaX{7M1GmWEVa^wCX~t z2o=;QH7m5)2kOq0za5J2?l`R9K=%{uuFc?o8X*%wD9ex>r1dC248LCK=ru%Lc7D+k z6YiT3PO80y=NYn{I6v);b>Cok76?~vQX1sxcUaw~``QhSj?6ne;G5gh0`wE{QWk#8 zb^DbMY+qlgFXtfO2lh}JdtMoe6}EQUEoEM-En4Eff)vFu&DbR!d22q#_-E4JfvtSuIo4 z5W!SoJ54UmUdMPjvSTS(d$08~LN`kRrnk2AI}iFXD&lprPB5)?cC4)zP%W}qvEL~r zliwN9YgQ{Zxm#fWQq0fY@cVzLmo%6a;Z79LtXLjHg?)p)H{ttaE)#Jgv~i$sQ%M4? zGwn6ug_KXHHwABGF7a(j2|bPQo@)>iF7Y9jGuUfQBJYGI@;!)4VQ}_8^5?_CS+4YR z3>%^PReO*9plB%S33Vh#M^c};lyr8dhLcGr5itf-QnX@-%D4#m`mwi$J}VxpDc^m~ z-&Dhmd}FoMB6sL+bb59&`N;M;|Dt@9T+MEu^-TG#?$u*!?-iPEDYM_6SCCX~@J%3> zGYV(2py|_8<&hW;Z=VcJtu^~A@17<&Dy9h=!-FGm(V z_|d%_J`h6;b@$4Zeye;KaI-&#wrXJr&AxVmx{f3{{f#F}bX3h}>aH)dEK<9ROFbB> z=cOI)fCvw_=}rUeNOCC2hnOpb495rU;bg)z14qnOoNY;ilJ3zhT3PZyn+d?Omi(zm z>FCnh+&?S(>QoPAkaeIsB>_c<($8KUMWvGK3qSZd=a0|9E-Xf>I-b*B3KQ4#b99$h zV|<{zFfaPO6w3jnLd?2m((%#7TUCT)2W@%$H4eM1>_GaQVFqe7&&lza>e=*RUSe#x zG`)jos6G;(88^`ws^7hQOy*RtVkvfp{jO!IO1Yhm-O0h4xXKx4@QzKbq`Ynx&N+WY zxQy1*aNZbpP5 z8$^4l(6nK)wwV5gSl#J3@-EwAc{1@Kq+1%^WMxIWAuAak#M#ug*DM>JP_%{_Q+F#F z-~Dwr*migcOh~4;8=@>!@fT9M&r0X4$DLiCK+pP-zxm%_r9&_kJRLxkRYI$Nues<+ zVq~XLO0t6G^q7{!=T)$Lc<_%2-xUYt1n4j+_u^4c9ES@n0=jFrjzDCuKaaah4ga@Z z{Ys74Wc4J|Q%_kwIIZ0amfuA@ZUdj?q?HY_C|mC;Yy`ohkwYD|?`n3!kJnX}hK{}T zWZ&Y94tXe8(-(7sG@?M<>s_IHr4kbHflm8cN*puh2p;AS5oWz75D3ZMg2f)bWj?lS z%Z?bEP+AjYH*8+zd(|XnZMK9e_d~v5^Ri1+z)9=N!P_gt%bV%7#fYm}@Sb70>Z zIR7I^R@7;z-@cK^ewlaL{Q`y3yJV*wRWFMG)n3suY9)Ik*SLx8A#{xHTa z?^m5{@f@}$OsBnDLs$f07piXV0IMK;!U~?OqVw*@-e_<^$jLK*2%RTuL;lX&sVDXx z1B$1IrFH$~YLp+|{>pgsf;$zW^*13B$oU7h>%d_7JLXJz1&~^l8)ch1xZII$o$d*p z=$zw|8ja~*=ts}*MWDzlGYyAzpP98@gh^5dQW3 zy1vz(2KiJvQTj)Hp{sA6g@{+n&_FY=Q|^tkg>|{^bx%AQtrT?ZW|aWYL{Lg#oi)tG zT8GUA`T@%O*?+8Fq&@U6(OLPOY9LGE7?2;)=*J_R#^e)DBl`>`?Aj{e)qUL#WQ>y3 zg%{2_hXVEepu(u1dp8AC=`knAo5hmz+@CQoWjD_Wl;`Q6K=*JGGnubt`|^sG?&i!d zDyn`!X-Qi5>scb6-0$XE1WTSj@%oSBqLeXl04U(C+vIsO~T}UQGeL>w^Q}n zn&PdF3f9eeD~-^c>x^j$KEKMyoOh<(SW$mOEp$j?^Cq6OCdcwK0_k$7&CFDwTvz+* z)+V|p0+L`{_MfL@Z9L4~z-BOG`-88A zzK3d9&&^M)z2o6c$Vtj8RIt)JPj30s9a%58wX{f($%|?|^+hMG&XKJcB9|G-dW6SS z=vT>&O3kR(#iH!)I!QHHCd?%8|`G^9uQcuIHqH-)=Mh*d0r!M|2Am z{|*`I=Kc2^Gy&!K+h{!-;8#6uBZGng-n&}co{zGMIcDY~;f``FT8=2n{xjKqMovo_ zK5w@@U&-2~J5(f{({1^afUGElwYQhR?wm~0dU+l`Gm!I^jm;iN$43aHF_0}HX7jNTpJAroVVJ2fk7K><5$Gae%Ue)^}A z|LL0H!NWYG+ae|jdyd2hP6|jl%$^zo=qlH^x2yN-RV_))WyuVmTK5_Jnn`?%c94_1 zSBCMA&2BM@NBT+J(R}KCKo#iX-~aaK$WBsdh`fCKW z8W*c>VmB6QNEDBSt22vhd&DsIpjaF&5*HcKVSK$4i#or*sIGLdH9=9||NJ)s`4}^(I^Vn+{8{VZu0+FUV@lE!VbWv1k4iu($e%~sl3;fcbM;MiND{L?B z0iwQ}NnG5?YD0@94(?#rcZP{W*^%2Hk@vKPF7T0y%S5Znb?`peC1KnJzv=nbwO3PG zL{h2#?E?q|AQS%6oTU7x6ZvVx>PMe|$?)BAW_`QAsZiQ5|Kdp<=F6ZxZ&XX25`%EBqu)ou*=(=TpceslNA=@$dJ9~Q@(mdh8Xn&c}M zXLKzZ!zG2}cHv>Vsv@B+V)YwqYFSJP!rN{2#r2(EF~DiOm-CoaVC%lXJj9IA=KrsO zJl!m0Hqf0w^_A|G{Z#_9nLGABZ@7KA%cn0m@KC#lI7AHfRQ>P&@lY|`yk-;K*$7%| z|NL+{UHmsiz+>sM^BPSRrH9Lb&MdRiJH`iu9*p*3)~IX5U9s>`TUY~3u^$^g`R22Q zSO8)zX1qCkSoRq3)w!pFvh0VOgM}T2za?)3I=XYGPmF3Q5MK^rDIU8JqOMV1&k^9h zw~pll?uzb*+B6jDZflE{!>t%Lnq%{LiREuMrXlx!m_dGu~;e9zA$ESAD*z$sXo@MiHcZ?%(me zJuuqIfGxLp-jLKea0_>^jFlCbRmM&7z*s{6jy2S4{Clj(z#h@OP9aT|M+FDrOAo!K zZoftP|J9v)qw)3cJ8|0ZR^tQ2>W|k!SrbF#U`G+qj~nY~;0mZb54~e-ryYe`PKDk< z7ef^RWDO`6KCgi-$1gT%f^whC{oYe{`brz<+6d67+XvHw=h8)kLqTr^9Q*-FqlWrq zgG2vSpxw^=-@hK%-5@m5WP$Oar8)DvnV(W)x!khH$~p|lwZb}U(`HEfGJQ3cG<%Za zeB%QN;6)FH?!|IPp+9e6#yl#Ql}4nnX2$7K05!S{k2DQUj+rxKJiJ}nJ&YYq8<1S;P(fwk6 z(#&-g#AJy!TCpD({u=lqB$gZWRb?rR)qc}o$3S)?KI6GN@gE;#*i+4Gct;Fhx**i5j6TAOp04tWp9jseimjHa5RvKI&YS z0dl#3PXtP4j{6XkCObTwe^0)L8&7E~>NZIIx$nKQNSL{V#IC0oMsx!xsd`dqKKUte zmae-ETKnW3w*JIhHCvu%v;Eyo7`C5@d_=B(pd(7sa47%?@AO4!HGPX zJ9wx6qql1hhjLrvBgNirQQ0b^F=ceyh3rAO%$QDXa*0X^hpEOb%t)Cqu5Cr_GK8Hd zMidFtMv<6sbPR?tjBy<*mzXr=HjK-hHRD##dCuiI&pBuPGxL1w`_}#Yz3*>*>wVw3 zBkJZH9nY*XBi369h|jtbP6uQ(DV#GOyRBP`@h0ttrJ%p@hRi4gc7ra~|8VC-NL3N@3>BgSNnH zrcyB@xYW**%Glsy%R&uDRm)+&b<&-syW8OWPmXi`A0$coF9ob|6UE>nD}1QK=MY!g zNCSb@{Cn2ki;q2%4ZXLDT;pw;NCqaqz}(I!ARqV0%P`ifE0NbtYHXj(nS&>E<4Gwq z)j;Hh6?11_9D=3dF6Nl=6@3|+neyRc z@u(#*&)S?HVY;hP&LE8h}w zGT6-}U?$n448-AMjlM0sC-uM--=OgWyT9fh%Q&N+q*bsGzTg~B?Mcv6{j`ID!V#a5 zHnYPUfT0mQWFoUHK*_*vC`xYL72Ulh>Pe*}|y<$3Sv(mr=vBty3wPO&6Q_ zgnp5)aha|v=wae_VE+qlIBEZmR&M2i5;V1nt$UDa`w7r9gx=1O!2{0IoT-v)862z| zH29|T%$cBP6Q7@Ug!9OFVe)xiU~JmNKGcVto)GUZkWqJjTCe^fegFk_1A6E4J|_&8 zMk!;N3?2LQ;m?q;7ZHx$_|VtyEG#J|6q(loL)Ywvh1g=FO>Xau#c$q}mC8ZIH8Ch& z>+`55VslEngvqNFbt+Mtc=@2YncDY#-rMa4Tb-h^SYYHnpD+h>IqnY_aFb^nESO zTm_7JOEnOJcO96@3@xkZv-!)Iu5TvMcQIH>3|+^!2JiF%KvQQ533y_8N1AK5D{^Bc zj+XvA7sQx)#=mv}cEfK~=g=zM{T{VVbm1V05h^0c9x_(n zp>$ZtlRXT(|UHrXE{Yx0Fii9VLqAYAs4$%$s)-FAUA(I&=>?lWbX1b z7Hq_*ce*VEyz6gr+qfW(fUhIRO@-6VmzA#O*h1{8T=>Yhd~|V!F?pSAO&)@lAM6u2 zbv>gk|F@zFSEZvKumBJNMN7!9E{RVA0aTzRFN7EAQqnrqnd7HAq544a~z1cpuq z2;qx~oY_!{F>gnr<}zqJADK4pES=kNs6*3v6MzrNP>3$+ISUw0PP7tqLBs(dXTxS> zf_H9TRlUaxqPzE(^f>M&j7^ouWlJSrE^-K%DX|ch@T-VxW0KV>Rvx4lfBP1P37QGr zX>FOe3GZRzxns5EO4N6uX6sCcreE)~p;x8KropEU?Kq>RV(L!g8^PnyJpX$N>g+&@p;4l)zsKu;rOF14PhsK{yHUKm zS)!IF-KG|F3QDL9NeDC&Ef21w61A)-CZL^99Vxedw#u{=lA7v78h4|)uVZ&^$v1lM z;R3PVYc~TA4Kl24WS5YBO)wWxJa^@nWGZ*KkVEAH$xyXGI@}2&`U2cQ>#Z#lY1E3@ zk^arwMCxEtIQ3ph^jRj+&j>DAUY9E7DDF=69pc+NYAW9DzC>i+CMnm8$V;8N<1Rm5 z8q0*;EdfC;HhWs@5~T*5$ng|hV-j|9AEr-+XBzbh`qq8=L!{k9&Dq7oZU=Tnx4t`` zNxTdxult$_0Zx@ft}BUlU7&>`wpBp!g(csnL-v<^KyF{AW*XW!P|XjZn)Y77n&wyG znB^y2b%tK*@(iTH1~8QGmkFjpmfei`fHS0>sYs0sEGr(29xZ@*`y{9>-_g55K`nZ> zK$7HxcPRc2j=%`h^td0}G#bOR&|Kw!~)ET;cWWKS_oU#Q{#5lHkusxDPsqA%32 zL&NV=(D`}MDq2j>ps+DkUXKBQQUqPPzjbr-fW}fD7{2T#O)PAtK28aP{({ZyFDN^f zRJM{0$u*(}5kDTVBtWLqZ)+;fad(VuUdc{neYpFSJU39YZX5Q+c;YNOtKc6LK7Vew ztp7}pP%HGS$+C|kPY<_wr*uK`Co5{KN~MA1UrP2dbuv84yy-2Ee_6%AF4LsDj0v!eCC znA|VxRb}I7zbME8HvJQ~dOTMnqyERGTrfHX%sfZfdsZGNZ7uL8RX}ly5$X|JzbV2- zuP_@|>H^q?C;Yy_j`y3XcfTIMdLz0o(W@wjDbZJ>6e<^?i=~vF7g49Blyr^UKYW); z9=T%;z5+XfVcd$I#Fol^H5N(N$!~{GQ^`ZEX&GRsz}`enXv!9q>*8&|g>sHz=mesS zE&ZaW^(A2Gg3U>18@z!o)d99KqRH*UZ6mbR(a!@xOGzIJLP82dzDKUyamID%bS}BQ zRnX?aMoGtL&yDuWS){~*{@yXRUs;jmGL3n5uyj_QJ**%%5^Ox?f>HTSrPB>Pooz1U z zHOzsfX#?}bzjnt_6u$=^kd{*t{2K)NClP~Fug?l=-6Byh_xT?YJ#O-g#S!YC&iwi} DGcc=2 literal 0 HcmV?d00001 diff --git a/lambdas/qna_bot_qbusiness_lambdahook/README.md b/lambdas/qna_bot_qbusiness_lambdahook/README.md index 76f6f92..0c8ef40 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/README.md +++ b/lambdas/qna_bot_qbusiness_lambdahook/README.md @@ -1,6 +1,6 @@ # QnABot LambdaHook for Amazon Q Business (preview) -| :zap: If you have created a new Amazon Q Business application on or after April 30th, 2024, you will not be able to set up a QnAbot LambdaHook for Amazon Q Business using the instructions provided below. This is because new Amazon Q Business applications require integration with IAM Identity Center. We don't currently have a plan to update the plugin to accommodate the setup for new applications created since April 30th, 2024. We'd be delighted to accept a Pull Request from community members if you make it work in the meantime. | +| :zap: The QnAbot LambdaHook for Amazon Q Business has been updated to accomodate migration to IAM Identicy Center. Please note some manual configuration steps are required and outlined below as part of the deployment process. | |-----------------------------------------| Amazon Q is a new generative AI-powered application that helps users get work done. Amazon Q can become your tailored business expert and let you discover content, brainstorm ideas, or create summaries using your company’s data safely and securely. For more information see: [Introducing Amazon Q, a new generative AI-powered assistant (preview)](https://aws.amazon.com/blogs/aws/introducing-amazon-q-a-new-generative-ai-powered-assistant-preview) @@ -15,26 +15,40 @@ It's pretty cool. It's easy to deploy in your own AWS Account, and add to your o ## Deploy Amazon Q (your business expert) as a fallback source of answers, using Lambda hooks with CustomNoMatches/no_hits +### Prerequisites + +1. A deployment of the Lex Web UI with login enabled is required for this stack. To learn more about deploying the Web UI see the [Github repo for the solution](https://github.com/aws-samples/aws-lex-web-ui). This Cognito should be integrated with the same identity provider as your Identity Center (in the below example we will use IAM Identity Center as the IDP). +2. The Cognito user pool created by the Web UI will need to be added as **Trusted token issuer** to Identity Center by doing the following steps + 1. Go to Identity Center and click on `Settings`, then `Create trusted token issuer` + 2. The issuer URL will be `https://cognito-idp.[region].amazonaws.com/[cognito-pool-id]` and you will need to provide which attributes should map between the two. + ![Issuer](../../images/token-issuer.PNG) +3. A custom application will need to be created in Identity Center to handle the connection between your Q Business application and your Cognito pool. Follow these steps to create the application. + 1. Go to Identity Center and click on `Applications` then `Add application` + 2. Select `I have an application I want to set up` and `OAuth 2.0` on the next page for Selecting Application type, then hit `Next` + 3. For `Application URL`, provide the **Web experience URL** of your Q Business application. You can either opt to assign specific users/groups to this application or allow any Identity Center users/groups to access the application. Your Q Business subscriptions will still apply however so only users with a subscription can successfully chat with the application. Then hit `Next` + 4. Select the Trusted token issuer that was created in Step 2 of this guide, you will now need an aud claim so that the token issuer can identify the application. This aud claim is created when you deploy the Lex Web UI and can be found within the Coginto User pool. To find this value go to your Cognito user pool and select the `App integration` tab and scroll to the bottom. The aud claim is the **Client ID** value found under the App client list. Take this value and paste it into the aud claim field, then select `Next` + ![Claim](../../images/aud-claim.PNG) + 5. You will need to wait until after you deploy the CloudFormation stack to provide the role on the Specify application credentials page. For now, provide any existing IAM role in your environment and hit `Next`. + ### Deploy a new Amazon Q (Business) Plugin stack Use AWS CloudFormation to deploy one or more of the sample plugin Lambdas in your own AWS account (if you do not have an AWS account, please see [How do I create and activate a new Amazon Web Services account?](https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account/)): 1. Log into the [AWS console](https://console.aws.amazon.com/) if you are not already. -*Note: Ensure that your IAM Role/User have permissions to create and manage the necessary resources and components for this application.* 2. Choose one of the **Launch Stack** buttons below for your desired AWS region to open the AWS CloudFormation console and create a new stack. 3. On the CloudFormation `Create Stack` page, click `Next` 4. Enter the following parameters: 1. `Stack Name`: Name your stack, e.g. QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK. 2. `AmazonQAppId`: Existing Amazon Q Application ID (copy from AWS console) - 3. `AmazonQUserId`: Amazon Q User ID (leave empty to use authenticated bot users' email as user Id) - see note below - 4. `AmazonQRegion`: Amazon Q Region (us-east-1, or us-west-2) - 5. `AmazonQEndpointUrl`: (Optional) Amazon Q Endpoint (leave empty for default endpoint) - -*Note on UserId:* -You have two options: -1. (Default) Map each bot user's email to a Q Business userid. This means that each QnAbot user must be an authenticated user (e.g. logged in via Cognito using Lex Web UI). ACLs will be observed per user. This is the default setup. -2. (Proxy) Alternatively, when you deploy you can choose a single email to use when QnABot invokes Amazon Q. This removes the need for QnABot users to be authenticated (logged in), but it also means that no per-user ACLs are supported since ACLS will be based on the single proxy userId. - + 3. `AmazonQRegion`: Amazon Q Region (us-east-1, or us-west-2) + 4. `DynamoDBTableName`: DynamoDB table that will be used to cache user credential for question answering with QBusiness. + 5. `IDCApplicationARN`: ARN of the Identity Center customer managed application created for QBusiness (see prerequisites for steps to create) +5. Launch the stack. +6. When your QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK Plugin CloudFormation stack status is CREATE_COMPLETE, choose the **Outputs** tab. Look for the output `QnAItemLambdaFunctionRoleArn` and modify your existing Identity Center application with this value by following these steps. + 1. Go to Identity Center and click on `Applications` and find the application created for the QBusiness plugin. Click on the application to view more details. + 2. Select `Actions->Edit configuration` to modify the settings of the application + 3. Expand the Application credentials and paste the ARN obtained from the Outputs section. + 4. Hit `Save changes` #### N. Virginia (us-east-1) Plugin | Launch Stack | Template URL diff --git a/lambdas/qna_bot_qbusiness_lambdahook/template.yml b/lambdas/qna_bot_qbusiness_lambdahook/template.yml index 64dbc3f..3f71849 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/template.yml +++ b/lambdas/qna_bot_qbusiness_lambdahook/template.yml @@ -8,28 +8,15 @@ Parameters: AmazonQAppId: Type: String AllowedPattern: '^[a-zA-Z0-9][a-zA-Z0-9-]{35}$' - Description: Amazon Q Application ID (copy from AWS console) + Description: Amazon Q Application ID - AmazonQRoleARN: + IDCApplicationARN: Type: String - Description: Amazon Q Business Role ARN to Assume (copy from AWS console) - - IDCClientId: - Type: String - Description: Amazon Q Business IDC Client ID (copy from AWS console) + Description: ARN of the Identity Center customer managed application created for QBusiness DynamoDBTableName: Type: String - Description: DynamoDB Table Name used for caching QBusiness credentials (copy from AWS console) - - KMSKeyId: - Type: String - Description: KMS Key ID used for encrypting and decrypting QBusiness credentials (copy from AWS console) - - AmazonQUserId: - Type: String - Default: "" - Description: Amazon Q User ID (leave empty to use authenticated bot users' email as user Id) + Description: DynamoDB Table Name used for caching QBusiness credentials AmazonQRegion: Type: String @@ -44,12 +31,72 @@ Parameters: Resources: + QManagedPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: AllowQChat + Effect: Allow + Action: + - "qbusiness:ChatSync" + Resource: !Sub "arn:${AWS::Partition}:qbusiness:${AWS::Region}:${AWS::AccountId}:application/${AmazonQAppId}" + + QServiceRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root + Action: + - sts:AssumeRole + - sts:SetContext + Path: / + ManagedPolicyArns: + - !Ref QManagedPolicy + QBusinessModelLayer: Type: "AWS::Lambda::LayerVersion" Properties: Content: ../../layers/qbusiness_boto3_model CompatibleRuntimes: - - python3.11 + - python3.12 + + KMSKey: + Type: 'AWS::KMS::Key' + Properties: + KeySpec: 'SYMMETRIC_DEFAULT' + KeyUsage: 'ENCRYPT_DECRYPT' + KeyPolicy: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' + Action: 'kms:*' + Resource: '*' + + CredentialsTable: + Type: AWS::DynamoDB::Table + Properties: + AttributeDefinitions: + - AttributeName: "jti" + AttributeType: "S" + KeySchema: + - AttributeName: "jti" + KeyType: "HASH" + BillingMode: PAY_PER_REQUEST + SSESpecification: + SSEEnabled: True + TableName: !Ref DynamoDBTableName + TimeToLiveSpecification: + AttributeName: ExpiresAt + Enabled: true LambdaFunctionRole: Type: AWS::IAM::Role @@ -78,8 +125,46 @@ Resources: - Effect: Allow Action: - "s3:GetObject" - Resource: "arn:aws:s3:::*-importbucket-*/*" + Resource: "arn:aws:s3:::*/*" PolicyName: S3ImportBucketPolicy + - PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - "dynamodb:PutItem" + - "dynamodb:GetItem" + Resource: + - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDBTableName}" + PolicyName: DynamoDbPolicy + - PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - "kms:Decrypt" + - "kms:Encrypt" + Resource: + - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${KMSKey}" + PolicyName: KmsPolicy + - PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - "sso-oauth:CreateTokenWithIAM" + Resource: "*" + PolicyName: OICDPolicy + - PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - "sts:AssumeRole" + - "sts:SetContext" + Resource: + - !GetAtt QServiceRole.Arn + PolicyName: AllowAssumeQRole QnaItemLambdaHookFunction: Type: AWS::Lambda::Function @@ -88,7 +173,7 @@ Resources: FunctionName: !Sub "QNA-LAMBDAHOOK-${AWS::StackName}" Handler: lambdahook.lambda_handler Role: !GetAtt 'LambdaFunctionRole.Arn' - Runtime: python3.11 + Runtime: python3.12 Layers: - !Ref QBusinessModelLayer Timeout: 60 @@ -97,11 +182,10 @@ Resources: Variables: AWS_DATA_PATH: /opt/model AMAZONQ_APP_ID: !Ref AmazonQAppId - AMAZONQ_ROLE_ARN: !Ref AmazonQRoleARN - DYNAMODB_CACHE_TABLE_NAME: !Ref DynamoDBTableName - KMS_KEY_ID: !Ref KMSKeyId - IDC_CLIENT_ID: !Ref IDCClientId - AMAZONQ_USER_ID: !Ref AmazonQUserId + AMAZONQ_ROLE_ARN: !GetAtt QServiceRole.Arn + DYNAMODB_CACHE_TABLE_NAME: !Ref CredentialsTable + KMS_KEY_ID: !Ref KMSKey + IDC_CLIENT_ID: !Ref IDCApplicationARN AMAZONQ_REGION: !Ref AmazonQRegion AMAZONQ_ENDPOINT_URL: !Ref AmazonQEndpointUrl Code: ./src @@ -123,4 +207,8 @@ Outputs: QnAItemLambdaHookArgs: Description: QnA Item Lambda Hook Args (use with no_hits item for optional ask-the-LLM fallback) Value: '{"Prefix":"Amazon Q Answer:", "ShowContextText":true, "ShowSourceLinks":true}' + + QnAItemLambdaFunctionRoleArn: + Description: ARN of the Role created for executing the Lambda function + Value: !GetAtt LambdaFunctionRole.Arn diff --git a/layers/qbusiness_boto3_model/model/qbusiness/2023-11-27/service-2.json b/layers/qbusiness_boto3_model/model/qbusiness/2023-11-27/service-2.json index 20eb3b1..65f73b1 100644 --- a/layers/qbusiness_boto3_model/model/qbusiness/2023-11-27/service-2.json +++ b/layers/qbusiness_boto3_model/model/qbusiness/2023-11-27/service-2.json @@ -2,10 +2,11 @@ "version":"2.0", "metadata":{ "apiVersion":"2023-11-27", + "auth":["aws.auth#sigv4"], "endpointPrefix":"qbusiness", - "jsonVersion":"1.1", "protocol":"rest-json", "protocolSettings":{"h2":"eventstream"}, + "protocols":["rest-json"], "serviceFullName":"QBusiness", "serviceId":"QBusiness", "signatureVersion":"v4", @@ -29,7 +30,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Asynchronously deletes one or more documents added using the BatchPutDocument API from an Amazon Q Business index.

You can see the progress of the deletion, and any error messages related to the process, by using CloudWatch.

" }, "BatchPutDocument":{ "name":"BatchPutDocument", @@ -48,7 +50,28 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} - ] + ], + "documentation":"

Adds one or more documents to an Amazon Q Business index.

You use this API to:

  • ingest your structured and unstructured documents and documents stored in an Amazon S3 bucket into an Amazon Q Business index.

  • add custom attributes to documents in an Amazon Q Business index.

  • attach an access control list to the documents added to an Amazon Q Business index.

You can see the progress of the deletion, and any error messages related to the process, by using CloudWatch.

" + }, + "Chat":{ + "name":"Chat", + "http":{ + "method":"POST", + "requestUri":"/applications/{applicationId}/conversations", + "responseCode":200 + }, + "input":{"shape":"ChatInput"}, + "output":{"shape":"ChatOutput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"LicenseNotFoundException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

Starts or continues a streaming Amazon Q Business conversation.

" }, "ChatSync":{ "name":"ChatSync", @@ -67,7 +90,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Starts or continues a non-streaming Amazon Q Business conversation.

" }, "CreateApplication":{ "name":"CreateApplication", @@ -87,6 +111,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Creates an Amazon Q Business application.

There are new tiers for Amazon Q Business. Not all features in Amazon Q Business Pro are also available in Amazon Q Business Lite. For information on what's included in Amazon Q Business Lite and what's included in Amazon Q Business Pro, see Amazon Q Business tiers. You must use the Amazon Q Business console to assign subscription tiers to users.

", "idempotent":true }, "CreateDataSource":{ @@ -107,6 +132,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Creates a data source connector for an Amazon Q Business application.

CreateDataSource is a synchronous operation. The operation returns 200 if the data source was successfully created. Otherwise, an exception is raised.

", "idempotent":true }, "CreateIndex":{ @@ -126,7 +152,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} - ] + ], + "documentation":"

Creates an Amazon Q Business index.

To determine if index creation has completed, check the Status field returned from a call to DescribeIndex. The Status field is set to ACTIVE when the index is ready to use.

Once the index is active, you can index your documents using the BatchPutDocument API or the CreateDataSource API.

" }, "CreatePlugin":{ "name":"CreatePlugin", @@ -146,6 +173,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Creates an Amazon Q Business plugin.

", "idempotent":true }, "CreateRetriever":{ @@ -165,7 +193,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} - ] + ], + "documentation":"

Adds a retriever to your Amazon Q Business application.

" }, "CreateUser":{ "name":"CreateUser", @@ -185,6 +214,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Creates a universally unique identifier (UUID) mapped to a list of local user ids within an application.

", "idempotent":true }, "CreateWebExperience":{ @@ -204,7 +234,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} - ] + ], + "documentation":"

Creates an Amazon Q Business web experience.

" }, "DeleteApplication":{ "name":"DeleteApplication", @@ -223,6 +254,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes an Amazon Q Business application.

", "idempotent":true }, "DeleteChatControlsConfiguration":{ @@ -241,6 +273,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes chat controls configured for an existing Amazon Q Business application.

", "idempotent":true }, "DeleteConversation":{ @@ -260,6 +293,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes an Amazon Q Business web experience conversation.

", "idempotent":true }, "DeleteDataSource":{ @@ -279,6 +313,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes an Amazon Q Business data source connector. While the data source is being deleted, the Status field returned by a call to the DescribeDataSource API is set to DELETING.

", "idempotent":true }, "DeleteGroup":{ @@ -298,6 +333,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes a group so that all users and sub groups that belong to the group can no longer access documents only available to that group. For example, after deleting the group \"Summer Interns\", all interns who belonged to that group no longer see intern-only documents in their chat results.

If you want to delete, update, or replace users or sub groups of a group, you need to use the PutGroup operation. For example, if a user in the group \"Engineering\" leaves the engineering team and another user takes their place, you provide an updated list of users or sub groups that belong to the \"Engineering\" group when calling PutGroup.

", "idempotent":true }, "DeleteIndex":{ @@ -317,6 +353,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes an Amazon Q Business index.

", "idempotent":true }, "DeletePlugin":{ @@ -336,6 +373,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes an Amazon Q Business plugin.

", "idempotent":true }, "DeleteRetriever":{ @@ -355,6 +393,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes the retriever used by an Amazon Q Business application.

", "idempotent":true }, "DeleteUser":{ @@ -374,6 +413,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes a user by email id.

", "idempotent":true }, "DeleteWebExperience":{ @@ -393,6 +433,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Deletes an Amazon Q Business web experience.

", "idempotent":true }, "GetApplication":{ @@ -410,7 +451,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an existing Amazon Q Business application.

" }, "GetChatControlsConfiguration":{ "name":"GetChatControlsConfiguration", @@ -427,7 +469,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an chat controls configured for an existing Amazon Q Business application.

" }, "GetDataSource":{ "name":"GetDataSource", @@ -444,7 +487,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an existing Amazon Q Business data source connector.

" }, "GetGroup":{ "name":"GetGroup", @@ -462,7 +506,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Describes a group by group name.

" }, "GetIndex":{ "name":"GetIndex", @@ -479,7 +524,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an existing Amazon Q Business index.

" }, "GetPlugin":{ "name":"GetPlugin", @@ -496,7 +542,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an existing Amazon Q Business plugin.

" }, "GetRetriever":{ "name":"GetRetriever", @@ -513,7 +560,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an existing retriever used by an Amazon Q Business application.

" }, "GetUser":{ "name":"GetUser", @@ -531,7 +579,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Describes the universally unique identifier (UUID) associated with a local user in a data source.

" }, "GetWebExperience":{ "name":"GetWebExperience", @@ -548,7 +597,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets information about an existing Amazon Q Business web experience.

" }, "ListApplications":{ "name":"ListApplications", @@ -564,7 +614,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists Amazon Q Business applications.

" }, "ListConversations":{ "name":"ListConversations", @@ -582,7 +633,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists one or more Amazon Q Business conversations.

" }, "ListDataSourceSyncJobs":{ "name":"ListDataSourceSyncJobs", @@ -599,7 +651,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Get information about an Amazon Q Business data source connector synchronization.

" }, "ListDataSources":{ "name":"ListDataSources", @@ -616,7 +669,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists the Amazon Q Business data source connectors that you have created.

" }, "ListDocuments":{ "name":"ListDocuments", @@ -633,7 +687,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

A list of documents attached to an index.

" }, "ListGroups":{ "name":"ListGroups", @@ -651,7 +706,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Provides a list of groups that are mapped to users.

" }, "ListIndices":{ "name":"ListIndices", @@ -668,7 +724,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists the Amazon Q Business indices you have created.

" }, "ListMessages":{ "name":"ListMessages", @@ -686,7 +743,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets a list of messages associated with an Amazon Q Business web experience.

" }, "ListPlugins":{ "name":"ListPlugins", @@ -703,7 +761,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists configured Amazon Q Business plugins.

" }, "ListRetrievers":{ "name":"ListRetrievers", @@ -720,7 +779,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists the retriever used by an Amazon Q Business application.

" }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -737,7 +797,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Gets a list of tags associated with a specified resource. Amazon Q Business applications and data sources can have tags associated with them.

" }, "ListWebExperiences":{ "name":"ListWebExperiences", @@ -754,7 +815,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Lists one or more Amazon Q Business Web Experiences.

" }, "PutFeedback":{ "name":"PutFeedback", @@ -770,7 +832,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Enables your end user to provide feedback on their Amazon Q Business generated chat responses.

" }, "PutGroup":{ "name":"PutGroup", @@ -790,6 +853,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Create, or updates, a mapping of users—who have access to a document—to groups.

You can also map sub groups to groups. For example, the group \"Company Intellectual Property Teams\" includes sub groups \"Research\" and \"Engineering\". These sub groups include their own list of users or people who work in these teams. Only users who work in research and engineering, and therefore belong in the intellectual property group, can see top-secret company documents in their Amazon Q Business chat results.

", "idempotent":true }, "StartDataSourceSyncJob":{ @@ -809,7 +873,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} - ] + ], + "documentation":"

Starts a data source connector synchronization job. If a synchronization job is already in progress, Amazon Q Business returns a ConflictException.

" }, "StopDataSourceSyncJob":{ "name":"StopDataSourceSyncJob", @@ -826,7 +891,8 @@ {"shape":"ThrottlingException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} - ] + ], + "documentation":"

Stops an Amazon Q Business data source connector synchronization job already in progress.

" }, "TagResource":{ "name":"TagResource", @@ -845,6 +911,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Adds the specified tag to the specified Amazon Q Business application or data source resource. If the tag already exists, the existing value is replaced with the new value.

", "idempotent":true }, "UntagResource":{ @@ -863,6 +930,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Removes a tag from an Amazon Q Business application or a data source.

", "idempotent":true }, "UpdateApplication":{ @@ -882,6 +950,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Updates an existing Amazon Q Business application.

", "idempotent":true }, "UpdateChatControlsConfiguration":{ @@ -902,6 +971,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Updates an set of chat controls configured for an existing Amazon Q Business application.

", "idempotent":true }, "UpdateDataSource":{ @@ -921,6 +991,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Updates an existing Amazon Q Business data source connector.

", "idempotent":true }, "UpdateIndex":{ @@ -941,6 +1012,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Updates an Amazon Q Business index.

", "idempotent":true }, "UpdatePlugin":{ @@ -961,6 +1033,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Updates an Amazon Q Business plugin.

", "idempotent":true }, "UpdateRetriever":{ @@ -981,6 +1054,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Updates the retriever used for your Amazon Q Business application.

", "idempotent":true }, "UpdateUser":{ @@ -1000,6 +1074,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], + "documentation":"

Updates a information associated with a user id.

", "idempotent":true }, "UpdateWebExperience":{ @@ -1019,25 +1094,59 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], + "documentation":"

Updates an Amazon Q Business web experience.

", "idempotent":true } }, "shapes":{ + "APISchema":{ + "type":"structure", + "members":{ + "payload":{ + "shape":"Payload", + "documentation":"

The JSON or YAML-formatted payload defining the OpenAPI schema for a custom plugin.

" + }, + "s3":{ + "shape":"S3", + "documentation":"

Contains details about the S3 object containing the OpenAPI schema for a custom plugin. The schema could be in either JSON or YAML format.

" + } + }, + "documentation":"

Contains details about the OpenAPI schema for a custom plugin. For more information, see custom plugin OpenAPI schemas. You can either include the schema directly in the payload field or you can upload it to an S3 bucket and specify the S3 bucket location in the s3 field.

", + "union":true + }, + "APISchemaType":{ + "type":"string", + "enum":["OPEN_API_V3"] + }, "AccessConfiguration":{ "type":"structure", "required":["accessControls"], "members":{ - "accessControls":{"shape":"AccessControls"}, - "memberRelation":{"shape":"MemberRelation"} - } + "accessControls":{ + "shape":"AccessControls", + "documentation":"

A list of AccessControlList objects.

" + }, + "memberRelation":{ + "shape":"MemberRelation", + "documentation":"

Describes the member relation within the AccessControlList object.

" + } + }, + "documentation":"

Used to configure access permissions for a document.

" }, "AccessControl":{ "type":"structure", "required":["principals"], "members":{ - "principals":{"shape":"Principals"}, - "memberRelation":{"shape":"MemberRelation"} - } + "principals":{ + "shape":"Principals", + "documentation":"

Contains a list of principals, where a principal can be either a USER or a GROUP. Each principal can be have the following type of document access: ALLOW or DENY.

" + }, + "memberRelation":{ + "shape":"MemberRelation", + "documentation":"

Describes the member relation within a principal list.

" + } + }, + "documentation":"

A list of principals. Each principal can be either a USER or a GROUP and can be designated document access permissions of either ALLOW or DENY.

" }, "AccessControls":{ "type":"list", @@ -1049,6 +1158,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, + "documentation":"

You don't have access to perform this action. Make sure you have the required permission policies and user accounts and try again.

", "error":{ "httpStatusCode":403, "senderFault":true @@ -1063,10 +1173,44 @@ "payloadFieldNameSeparator" ], "members":{ - "pluginId":{"shape":"PluginId"}, - "payload":{"shape":"ActionExecutionPayload"}, - "payloadFieldNameSeparator":{"shape":"ActionPayloadFieldNameSeparator"} - } + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin the action is attached to.

" + }, + "payload":{ + "shape":"ActionExecutionPayload", + "documentation":"

A mapping of field names to the field values in input that an end user provides to Amazon Q Business requests to perform their plugin action.

" + }, + "payloadFieldNameSeparator":{ + "shape":"ActionPayloadFieldNameSeparator", + "documentation":"

A string used to retain information about the hierarchical contexts within an action execution event payload.

" + } + }, + "documentation":"

Performs an Amazon Q Business plugin action during a non-streaming chat conversation.

" + }, + "ActionExecutionEvent":{ + "type":"structure", + "required":[ + "pluginId", + "payload", + "payloadFieldNameSeparator" + ], + "members":{ + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin for which the action is being requested.

" + }, + "payload":{ + "shape":"ActionExecutionPayload", + "documentation":"

A mapping of field names to the field values in input that an end user provides to Amazon Q Business requests to perform their plugin action.

" + }, + "payloadFieldNameSeparator":{ + "shape":"ActionPayloadFieldNameSeparator", + "documentation":"

A string used to retain information about the hierarchical contexts within a action execution event payload.

" + } + }, + "documentation":"

A request from an end user signalling an intent to perform an Amazon Q Business plugin action during a streaming chat.

", + "event":true }, "ActionExecutionPayload":{ "type":"map", @@ -1077,8 +1221,12 @@ "type":"structure", "required":["value"], "members":{ - "value":{"shape":"ActionPayloadFieldValue"} - } + "value":{ + "shape":"ActionPayloadFieldValue", + "documentation":"

The content of a user input field in an plugin action execution payload.

" + } + }, + "documentation":"

A user input field in an plugin action execution payload.

" }, "ActionPayloadFieldKey":{ "type":"string", @@ -1107,11 +1255,59 @@ "ActionReview":{ "type":"structure", "members":{ - "pluginId":{"shape":"PluginId"}, - "pluginType":{"shape":"PluginType"}, - "payload":{"shape":"ActionReviewPayload"}, - "payloadFieldNameSeparator":{"shape":"ActionPayloadFieldNameSeparator"} - } + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin associated with the action review.

" + }, + "pluginType":{ + "shape":"PluginType", + "documentation":"

The type of plugin.

" + }, + "payload":{ + "shape":"ActionReviewPayload", + "documentation":"

Field values that an end user needs to provide to Amazon Q Business for Amazon Q Business to perform the requested plugin action.

" + }, + "payloadFieldNameSeparator":{ + "shape":"ActionPayloadFieldNameSeparator", + "documentation":"

A string used to retain information about the hierarchical contexts within an action review payload.

" + } + }, + "documentation":"

An output event that Amazon Q Business returns to an user who wants to perform a plugin action during a non-streaming chat conversation. It contains information about the selected action with a list of possible user input fields, some pre-populated by Amazon Q Business.

" + }, + "ActionReviewEvent":{ + "type":"structure", + "members":{ + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the conversation with which the action review event is associated.

" + }, + "userMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of the conversation with which the plugin action is associated.

" + }, + "systemMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an Amazon Q Business AI generated associated with the action review event.

" + }, + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin associated with the action review event.

" + }, + "pluginType":{ + "shape":"PluginType", + "documentation":"

The type of plugin.

" + }, + "payload":{ + "shape":"ActionReviewPayload", + "documentation":"

Field values that an end user needs to provide to Amazon Q Business for Amazon Q Business to perform the requested plugin action.

" + }, + "payloadFieldNameSeparator":{ + "shape":"ActionPayloadFieldNameSeparator", + "documentation":"

A string used to retain information about the hierarchical contexts within an action review event payload.

" + } + }, + "documentation":"

An output event that Amazon Q Business returns to an user who wants to perform a plugin action during a streaming chat conversation. It contains information about the selected action with a list of possible user input fields, some pre-populated by Amazon Q Business.

", + "event":true }, "ActionReviewPayload":{ "type":"map", @@ -1121,20 +1317,54 @@ "ActionReviewPayloadField":{ "type":"structure", "members":{ - "displayName":{"shape":"String"}, - "displayOrder":{"shape":"Integer"}, - "type":{"shape":"ActionPayloadFieldType"}, - "value":{"shape":"ActionPayloadFieldValue"}, - "allowedValues":{"shape":"ActionReviewPayloadFieldAllowedValues"}, - "required":{"shape":"Boolean"} - } + "displayName":{ + "shape":"String", + "documentation":"

The name of the field.

" + }, + "displayOrder":{ + "shape":"Integer", + "documentation":"

The display order of fields in a payload.

" + }, + "displayDescription":{ + "shape":"String", + "documentation":"

The field level description of each action review input field. This could be an explanation of the field. In the Amazon Q Business web experience, these descriptions could be used to display as tool tips to help users understand the field.

" + }, + "type":{ + "shape":"ActionPayloadFieldType", + "documentation":"

The type of field.

" + }, + "value":{ + "shape":"ActionPayloadFieldValue", + "documentation":"

The field value.

" + }, + "allowedValues":{ + "shape":"ActionReviewPayloadFieldAllowedValues", + "documentation":"

Information about the field values that an end user can use to provide to Amazon Q Business for Amazon Q Business to perform the requested plugin action.

" + }, + "allowedFormat":{ + "shape":"String", + "documentation":"

The expected data format for the action review input field value. For example, in PTO request, from and to would be of datetime allowed format.

" + }, + "required":{ + "shape":"Boolean", + "documentation":"

Information about whether the field is required.

" + } + }, + "documentation":"

A user input field in an plugin action review payload.

" }, "ActionReviewPayloadFieldAllowedValue":{ "type":"structure", "members":{ - "value":{"shape":"ActionPayloadFieldValue"}, - "displayValue":{"shape":"ActionPayloadFieldValue"} - } + "value":{ + "shape":"ActionPayloadFieldValue", + "documentation":"

The field value.

" + }, + "displayValue":{ + "shape":"ActionPayloadFieldValue", + "documentation":"

The name of the field.

" + } + }, + "documentation":"

Information about the field values that an end user can use to provide to Amazon Q Business for Amazon Q Business to perform the requested plugin action.

" }, "ActionReviewPayloadFieldAllowedValues":{ "type":"list", @@ -1148,12 +1378,28 @@ "Application":{ "type":"structure", "members":{ - "displayName":{"shape":"ApplicationName"}, - "applicationId":{"shape":"ApplicationId"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "status":{"shape":"ApplicationStatus"} - } + "displayName":{ + "shape":"ApplicationName", + "documentation":"

The name of the Amazon Q Business application.

" + }, + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier for the Amazon Q Business application.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was last updated.

" + }, + "status":{ + "shape":"ApplicationStatus", + "documentation":"

The status of the Amazon Q Business application. The application is ready to use when the status is ACTIVE.

" + } + }, + "documentation":"

Summary information for an Amazon Q Business application.

" }, "ApplicationArn":{ "type":"string", @@ -1190,8 +1436,23 @@ "AppliedAttachmentsConfiguration":{ "type":"structure", "members":{ - "attachmentsControlMode":{"shape":"AttachmentsControlMode"} - } + "attachmentsControlMode":{ + "shape":"AttachmentsControlMode", + "documentation":"

Information about whether file upload during chat functionality is activated for your application.

" + } + }, + "documentation":"

Configuration information about the file upload during chat feature for your application.

" + }, + "AppliedCreatorModeConfiguration":{ + "type":"structure", + "required":["creatorModeControl"], + "members":{ + "creatorModeControl":{ + "shape":"CreatorModeControl", + "documentation":"

Information about whether creator mode is enabled or disabled for an Amazon Q Business application.

" + } + }, + "documentation":"

The creator mode specific admin controls configured for an Amazon Q Business application. Determines whether an end user can generate LLM-only responses when they use the web experience.

For more information, see Admin controls and guardrails and Conversation settings.

" }, "AttachmentInput":{ "type":"structure", @@ -1200,9 +1461,24 @@ "data" ], "members":{ - "name":{"shape":"AttachmentName"}, - "data":{"shape":"Blob"} - } + "name":{ + "shape":"AttachmentName", + "documentation":"

The name of the file.

" + }, + "data":{ + "shape":"Blob", + "documentation":"

The data contained within the uploaded file.

" + } + }, + "documentation":"

A file directly uploaded into a web experience chat.

" + }, + "AttachmentInputEvent":{ + "type":"structure", + "members":{ + "attachment":{"shape":"AttachmentInput"} + }, + "documentation":"

A file input event activated by a end user request to upload files into their web experience chat.

", + "event":true }, "AttachmentName":{ "type":"string", @@ -1213,10 +1489,20 @@ "AttachmentOutput":{ "type":"structure", "members":{ - "name":{"shape":"AttachmentName"}, - "status":{"shape":"AttachmentStatus"}, - "error":{"shape":"ErrorDetail"} - } + "name":{ + "shape":"AttachmentName", + "documentation":"

The name of a file uploaded during chat.

" + }, + "status":{ + "shape":"AttachmentStatus", + "documentation":"

The status of a file uploaded during chat.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

An error associated with a file uploaded during chat.

" + } + }, + "documentation":"

The details of a file uploaded during chat.

" }, "AttachmentStatus":{ "type":"string", @@ -1229,8 +1515,12 @@ "type":"structure", "required":["attachmentsControlMode"], "members":{ - "attachmentsControlMode":{"shape":"AttachmentsControlMode"} - } + "attachmentsControlMode":{ + "shape":"AttachmentsControlMode", + "documentation":"

Status information about whether file upload functionality is activated or deactivated for your end user.

" + } + }, + "documentation":"

Configuration information for the file upload during chat feature.

" }, "AttachmentsControlMode":{ "type":"string", @@ -1251,17 +1541,48 @@ "AttributeFilter":{ "type":"structure", "members":{ - "andAllFilters":{"shape":"AttributeFilters"}, - "orAllFilters":{"shape":"AttributeFilters"}, - "notFilter":{"shape":"AttributeFilter"}, - "equalsTo":{"shape":"DocumentAttribute"}, - "containsAll":{"shape":"DocumentAttribute"}, - "containsAny":{"shape":"DocumentAttribute"}, - "greaterThan":{"shape":"DocumentAttribute"}, - "greaterThanOrEquals":{"shape":"DocumentAttribute"}, - "lessThan":{"shape":"DocumentAttribute"}, - "lessThanOrEquals":{"shape":"DocumentAttribute"} - } + "andAllFilters":{ + "shape":"AttributeFilters", + "documentation":"

Performs a logical AND operation on all supplied filters.

" + }, + "orAllFilters":{ + "shape":"AttributeFilters", + "documentation":"

Performs a logical OR operation on all supplied filters.

" + }, + "notFilter":{ + "shape":"AttributeFilter", + "documentation":"

Performs a logical NOT operation on all supplied filters.

" + }, + "equalsTo":{ + "shape":"DocumentAttribute", + "documentation":"

Performs an equals operation on two document attributes or metadata fields. Supported for the following document attribute value types: dateValue, longValue, stringListValue and stringValue.

" + }, + "containsAll":{ + "shape":"DocumentAttribute", + "documentation":"

Returns true when a document contains all the specified document attributes or metadata fields. Supported for the following document attribute value types: stringListValue.

" + }, + "containsAny":{ + "shape":"DocumentAttribute", + "documentation":"

Returns true when a document contains any of the specified document attributes or metadata fields. Supported for the following document attribute value types: stringListValue.

" + }, + "greaterThan":{ + "shape":"DocumentAttribute", + "documentation":"

Performs a greater than operation on two document attributes or metadata fields. Supported for the following document attribute value types: dateValue and longValue.

" + }, + "greaterThanOrEquals":{ + "shape":"DocumentAttribute", + "documentation":"

Performs a greater or equals than operation on two document attributes or metadata fields. Supported for the following document attribute value types: dateValue and longValue.

" + }, + "lessThan":{ + "shape":"DocumentAttribute", + "documentation":"

Performs a less than operation on two document attributes or metadata fields. Supported for the following document attribute value types: dateValue and longValue.

" + }, + "lessThanOrEquals":{ + "shape":"DocumentAttribute", + "documentation":"

Performs a less than or equals operation on two document attributes or metadata fields.Supported for the following document attribute value type: dateValue and longValue.

" + } + }, + "documentation":"

Enables filtering of responses based on document attributes or metadata fields.

" }, "AttributeFilters":{ "type":"list", @@ -1280,6 +1601,67 @@ "type":"string", "enum":["DELETE"] }, + "AuthChallengeRequest":{ + "type":"structure", + "required":["authorizationUrl"], + "members":{ + "authorizationUrl":{ + "shape":"Url", + "documentation":"

The URL sent by Amazon Q Business to the third party authentication server to authenticate a custom plugin user through an OAuth protocol.

" + } + }, + "documentation":"

A request made by Amazon Q Business to a third paty authentication server to authenticate a custom plugin user.

" + }, + "AuthChallengeRequestEvent":{ + "type":"structure", + "required":["authorizationUrl"], + "members":{ + "authorizationUrl":{ + "shape":"Url", + "documentation":"

The URL sent by Amazon Q Business to a third party authentication server in response to an authentication verification event activated by an end user request to use a custom plugin.

" + } + }, + "documentation":"

An authentication verification event activated by an end user request to use a custom plugin.

", + "event":true + }, + "AuthChallengeResponse":{ + "type":"structure", + "required":["responseMap"], + "members":{ + "responseMap":{ + "shape":"AuthorizationResponseMap", + "documentation":"

The mapping of key-value pairs in an authentication challenge response.

" + } + }, + "documentation":"

Contains details of the authentication information received from a third party authentication server in response to an authentication challenge.

" + }, + "AuthChallengeResponseEvent":{ + "type":"structure", + "required":["responseMap"], + "members":{ + "responseMap":{ + "shape":"AuthorizationResponseMap", + "documentation":"

The mapping of key-value pairs in an authentication challenge response.

" + } + }, + "documentation":"

An authentication verification event response by a third party authentication server to Amazon Q Business.

", + "event":true + }, + "AuthResponseKey":{ + "type":"string", + "max":100, + "min":1 + }, + "AuthResponseValue":{ + "type":"string", + "max":2048, + "min":1 + }, + "AuthorizationResponseMap":{ + "type":"map", + "key":{"shape":"AuthResponseKey"}, + "value":{"shape":"AuthResponseValue"} + }, "BasicAuthConfiguration":{ "type":"structure", "required":[ @@ -1287,9 +1669,16 @@ "roleArn" ], "members":{ - "secretArn":{"shape":"SecretArn"}, - "roleArn":{"shape":"RoleArn"} - } + "secretArn":{ + "shape":"SecretArn", + "documentation":"

The ARN of the Secrets Manager secret that stores the basic authentication credentials used for plugin configuration..

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The ARN of an IAM role used by Amazon Q Business to access the basic authentication credentials stored in a Secrets Manager secret.

" + } + }, + "documentation":"

Information about the basic authentication credentials used to configure a plugin.

" }, "BatchDeleteDocumentRequest":{ "type":"structure", @@ -1301,22 +1690,33 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the Amazon Q Business index that contains the documents to delete.

", "location":"uri", "locationName":"indexId" }, - "documents":{"shape":"DeleteDocuments"}, - "dataSourceSyncId":{"shape":"ExecutionId"} + "documents":{ + "shape":"DeleteDocuments", + "documentation":"

Documents deleted from the Amazon Q Business index.

" + }, + "dataSourceSyncId":{ + "shape":"ExecutionId", + "documentation":"

The identifier of the data source sync during which the documents were deleted.

" + } } }, "BatchDeleteDocumentResponse":{ "type":"structure", "members":{ - "failedDocuments":{"shape":"FailedDocuments"} + "failedDocuments":{ + "shape":"FailedDocuments", + "documentation":"

A list of documents that couldn't be removed from the Amazon Q Business index. Each entry contains an error message that indicates why the document couldn't be removed from the index.

" + } } }, "BatchPutDocumentRequest":{ @@ -1329,23 +1729,37 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the Amazon Q Business index to add the documents to.

", "location":"uri", "locationName":"indexId" }, - "documents":{"shape":"Documents"}, - "roleArn":{"shape":"RoleArn"}, - "dataSourceSyncId":{"shape":"ExecutionId"} + "documents":{ + "shape":"Documents", + "documentation":"

One or more documents to add to the index.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role with permission to access your S3 bucket.

" + }, + "dataSourceSyncId":{ + "shape":"ExecutionId", + "documentation":"

The identifier of the data source sync during which the documents were added.

" + } } }, "BatchPutDocumentResponse":{ "type":"structure", "members":{ - "failedDocuments":{"shape":"FailedDocuments"} + "failedDocuments":{ + "shape":"FailedDocuments", + "documentation":"

A list of documents that were not added to the Amazon Q Business index because the document failed a validation check. Each document contains an error message that indicates why the document couldn't be added to the index.

" + } } }, "Blob":{"type":"blob"}, @@ -1364,52 +1778,241 @@ "BlockedPhrasesConfiguration":{ "type":"structure", "members":{ - "blockedPhrases":{"shape":"BlockedPhrases"}, - "systemMessageOverride":{"shape":"SystemMessageOverride"} - } + "blockedPhrases":{ + "shape":"BlockedPhrases", + "documentation":"

A list of phrases blocked from a Amazon Q Business web experience chat.

" + }, + "systemMessageOverride":{ + "shape":"SystemMessageOverride", + "documentation":"

The configured custom message displayed to an end user informing them that they've used a blocked phrase during chat.

" + } + }, + "documentation":"

Provides information about the phrases blocked from chat by your chat control configuration.

" }, "BlockedPhrasesConfigurationUpdate":{ "type":"structure", "members":{ - "blockedPhrasesToCreateOrUpdate":{"shape":"BlockedPhrases"}, - "blockedPhrasesToDelete":{"shape":"BlockedPhrases"}, - "systemMessageOverride":{"shape":"SystemMessageOverride"} - } + "blockedPhrasesToCreateOrUpdate":{ + "shape":"BlockedPhrases", + "documentation":"

Creates or updates a blocked phrases configuration in your Amazon Q Business application.

" + }, + "blockedPhrasesToDelete":{ + "shape":"BlockedPhrases", + "documentation":"

Deletes a blocked phrases configuration in your Amazon Q Business application.

" + }, + "systemMessageOverride":{ + "shape":"SystemMessageOverride", + "documentation":"

The configured custom message displayed to your end user when they use blocked phrase during chat.

" + } + }, + "documentation":"

Updates a blocked phrases configuration in your Amazon Q Business application.

" }, "Boolean":{ "type":"boolean", "box":true }, - "ChatSyncInput":{ - "type":"structure", - "required":[ - "applicationId", - "userId" - ], + "BoostingDurationInSeconds":{ + "type":"long", + "box":true, + "max":999999999, + "min":0 + }, + "ChatInput":{ + "type":"structure", + "required":["applicationId"], "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to a streaming Amazon Q Business conversation.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"UserId", + "documentation":"

The identifier of the user attached to the chat input.

", "location":"querystring", "locationName":"userId" }, "userGroups":{ "shape":"UserGroups", + "documentation":"

The groups that a user associated with the chat input belongs to.

", "location":"querystring", "locationName":"userGroups" }, - "userMessage":{"shape":"UserMessage"}, - "attachments":{"shape":"AttachmentsInput"}, - "actionExecution":{"shape":"ActionExecution"}, - "conversationId":{"shape":"ConversationId"}, - "parentMessageId":{"shape":"MessageId"}, - "attributeFilter":{"shape":"AttributeFilter"}, + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the Amazon Q Business conversation.

", + "location":"querystring", + "locationName":"conversationId" + }, + "parentMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier used to associate a user message with a AI generated response.

", + "location":"querystring", + "locationName":"parentMessageId" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the chat input.

", + "idempotencyToken":true, + "location":"querystring", + "locationName":"clientToken" + }, + "inputStream":{ + "shape":"ChatInputStream", + "documentation":"

The streaming input for the Chat API.

" + } + }, + "payload":"inputStream" + }, + "ChatInputStream":{ + "type":"structure", + "members":{ + "configurationEvent":{ + "shape":"ConfigurationEvent", + "documentation":"

A configuration event activated by an end user request to select a specific chat mode.

" + }, + "textEvent":{ + "shape":"TextInputEvent", + "documentation":"

Information about the payload of the ChatInputStream event containing the end user message input.

" + }, + "attachmentEvent":{ + "shape":"AttachmentInputEvent", + "documentation":"

A request by an end user to upload a file during chat.

" + }, + "actionExecutionEvent":{ + "shape":"ActionExecutionEvent", + "documentation":"

A request from an end user to perform an Amazon Q Business plugin action.

" + }, + "endOfInputEvent":{ + "shape":"EndOfInputEvent", + "documentation":"

The end of the streaming input for the Chat API.

" + }, + "authChallengeResponseEvent":{ + "shape":"AuthChallengeResponseEvent", + "documentation":"

An authentication verification event response by a third party authentication server to Amazon Q Business.

" + } + }, + "documentation":"

The streaming input for the Chat API.

", + "eventstream":true + }, + "ChatMode":{ + "type":"string", + "enum":[ + "RETRIEVAL_MODE", + "CREATOR_MODE", + "PLUGIN_MODE" + ] + }, + "ChatModeConfiguration":{ + "type":"structure", + "members":{ + "pluginConfiguration":{ + "shape":"PluginConfiguration", + "documentation":"

Configuration information required to invoke chat in PLUGIN_MODE.

" + } + }, + "documentation":"

Configuration information for Amazon Q Business conversation modes.

For more information, see Admin controls and guardrails and Conversation settings.

", + "union":true + }, + "ChatOutput":{ + "type":"structure", + "members":{ + "outputStream":{ + "shape":"ChatOutputStream", + "documentation":"

The streaming output for the Chat API.

" + } + }, + "payload":"outputStream" + }, + "ChatOutputStream":{ + "type":"structure", + "members":{ + "textEvent":{ + "shape":"TextOutputEvent", + "documentation":"

Information about the payload of the ChatOutputStream event containing the AI-generated message output.

" + }, + "metadataEvent":{ + "shape":"MetadataEvent", + "documentation":"

A metadata event for a AI-generated text output message in a Amazon Q Business conversation.

" + }, + "actionReviewEvent":{ + "shape":"ActionReviewEvent", + "documentation":"

A request from Amazon Q Business to the end user for information Amazon Q Business needs to successfully complete a requested plugin action.

" + }, + "failedAttachmentEvent":{ + "shape":"FailedAttachmentEvent", + "documentation":"

A failed file upload event during a web experience chat.

" + }, + "authChallengeRequestEvent":{ + "shape":"AuthChallengeRequestEvent", + "documentation":"

An authentication verification event activated by an end user request to use a custom plugin.

" + } + }, + "documentation":"

The streaming output for the Chat API.

", + "eventstream":true + }, + "ChatSyncInput":{ + "type":"structure", + "required":["applicationId"], + "members":{ + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to the Amazon Q Business conversation.

", + "location":"uri", + "locationName":"applicationId" + }, + "userId":{ + "shape":"UserId", + "documentation":"

The identifier of the user attached to the chat input.

", + "location":"querystring", + "locationName":"userId" + }, + "userGroups":{ + "shape":"UserGroups", + "documentation":"

The groups that a user associated with the chat input belongs to.

", + "location":"querystring", + "locationName":"userGroups" + }, + "userMessage":{ + "shape":"UserMessage", + "documentation":"

A end user message in a conversation.

" + }, + "attachments":{ + "shape":"AttachmentsInput", + "documentation":"

A list of files uploaded directly during chat. You can upload a maximum of 5 files of upto 10 MB each.

" + }, + "actionExecution":{ + "shape":"ActionExecution", + "documentation":"

A request from an end user to perform an Amazon Q Business plugin action.

" + }, + "authChallengeResponse":{ + "shape":"AuthChallengeResponse", + "documentation":"

An authentication verification event response by a third party authentication server to Amazon Q Business.

" + }, + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the Amazon Q Business conversation.

" + }, + "parentMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of the previous system message in a conversation.

" + }, + "attributeFilter":{ + "shape":"AttributeFilter", + "documentation":"

Enables filtering of Amazon Q Business web experience responses based on document attributes or metadata fields.

" + }, + "chatMode":{ + "shape":"ChatMode", + "documentation":"

The chat modes available to an Amazon Q Business end user.

  • RETRIEVAL_MODE - The default chat mode for an Amazon Q Business application. When this mode is enabled, Amazon Q Business generates responses only from data sources connected to an Amazon Q Business application.

  • CREATOR_MODE - By selecting this mode, users can choose to generate responses only from the LLM knowledge, without consulting connected data sources, for a chat request.

  • PLUGIN_MODE - By selecting this mode, users can choose to use plugins in chat.

For more information, see Admin controls and guardrails, Plugins, and Conversation settings.

" + }, + "chatModeConfiguration":{ + "shape":"ChatModeConfiguration", + "documentation":"

The chat mode configuration for an Amazon Q Business application.

" + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

A token that you provide to identify a chat request.

", "idempotencyToken":true } } @@ -1417,13 +2020,38 @@ "ChatSyncOutput":{ "type":"structure", "members":{ - "conversationId":{"shape":"ConversationId"}, - "systemMessage":{"shape":"String"}, - "systemMessageId":{"shape":"MessageId"}, - "userMessageId":{"shape":"MessageId"}, - "actionReview":{"shape":"ActionReview"}, - "sourceAttributions":{"shape":"SourceAttributions"}, - "failedAttachments":{"shape":"AttachmentsOutput"} + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the Amazon Q Business conversation.

" + }, + "systemMessage":{ + "shape":"String", + "documentation":"

An AI-generated message in a conversation.

" + }, + "systemMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an Amazon Q Business AI generated message within the conversation.

" + }, + "userMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an Amazon Q Business end user text input message within the conversation.

" + }, + "actionReview":{ + "shape":"ActionReview", + "documentation":"

A request from Amazon Q Business to the end user for information Amazon Q Business needs to successfully complete a requested plugin action.

" + }, + "authChallengeRequest":{ + "shape":"AuthChallengeRequest", + "documentation":"

An authentication verification event activated by an end user request to use a custom plugin.

" + }, + "sourceAttributions":{ + "shape":"SourceAttributions", + "documentation":"

The source documents used to generate the conversation response.

" + }, + "failedAttachments":{ + "shape":"AttachmentsOutput", + "documentation":"

A list of files which failed to upload during chat.

" + } } }, "ClientToken":{ @@ -1431,6 +2059,19 @@ "max":100, "min":1 }, + "ConfigurationEvent":{ + "type":"structure", + "members":{ + "chatMode":{ + "shape":"ChatMode", + "documentation":"

The chat modes available to an Amazon Q Business end user.

  • RETRIEVAL_MODE - The default chat mode for an Amazon Q Business application. When this mode is enabled, Amazon Q Business generates responses only from data sources connected to an Amazon Q Business application.

  • CREATOR_MODE - By selecting this mode, users can choose to generate responses only from the LLM knowledge, without consulting connected data sources, for a chat request.

  • PLUGIN_MODE - By selecting this mode, users can choose to use plugins in chat.

For more information, see Admin controls and guardrails, Plugins, and Conversation settings.

" + }, + "chatModeConfiguration":{"shape":"ChatModeConfiguration"}, + "attributeFilter":{"shape":"AttributeFilter"} + }, + "documentation":"

A configuration event activated by an end user request to select a specific chat mode.

", + "event":true + }, "ConflictException":{ "type":"structure", "required":[ @@ -1439,10 +2080,20 @@ "resourceType" ], "members":{ - "message":{"shape":"ErrorMessage"}, - "resourceId":{"shape":"String"}, - "resourceType":{"shape":"String"} + "message":{ + "shape":"ErrorMessage", + "documentation":"

The message describing a ConflictException.

" + }, + "resourceId":{ + "shape":"String", + "documentation":"

The identifier of the resource affected.

" + }, + "resourceType":{ + "shape":"String", + "documentation":"

The type of the resource affected.

" + } }, + "documentation":"

You are trying to perform an action that conflicts with the current status of your resource. Fix any inconsistences with your resources and try again.

", "error":{ "httpStatusCode":409, "senderFault":true @@ -1452,14 +2103,22 @@ "ContentBlockerRule":{ "type":"structure", "members":{ - "systemMessageOverride":{"shape":"SystemMessageOverride"} - } + "systemMessageOverride":{ + "shape":"SystemMessageOverride", + "documentation":"

The configured custom message displayed to an end user informing them that they've used a blocked phrase during chat.

" + } + }, + "documentation":"

A rule for configuring how Amazon Q Business responds when it encounters a a blocked topic. You can configure a custom message to inform your end users that they have asked about a restricted topic and suggest any next steps they should take.

" }, "ContentRetrievalRule":{ "type":"structure", "members":{ - "eligibleDataSources":{"shape":"EligibleDataSources"} - } + "eligibleDataSources":{ + "shape":"EligibleDataSources", + "documentation":"

Specifies data sources in a Amazon Q Business application to use for content generation.

" + } + }, + "documentation":"

Rules for retrieving content from data sources connected to a Amazon Q Business application for a specific topic control configuration.

" }, "ContentType":{ "type":"string", @@ -1481,10 +2140,20 @@ "Conversation":{ "type":"structure", "members":{ - "conversationId":{"shape":"ConversationId"}, - "title":{"shape":"ConversationTitle"}, - "startTime":{"shape":"Timestamp"} - } + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the Amazon Q Business conversation.

" + }, + "title":{ + "shape":"ConversationTitle", + "documentation":"

The title of the conversation.

" + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

The start time of the conversation.

" + } + }, + "documentation":"

A conversation in an Amazon Q Business application.

" }, "ConversationId":{ "type":"string", @@ -1499,28 +2168,58 @@ }, "CreateApplicationRequest":{ "type":"structure", - "required":[ - "displayName", - "roleArn" - ], + "required":["displayName"], "members":{ - "displayName":{"shape":"ApplicationName"}, - "roleArn":{"shape":"RoleArn"}, - "description":{"shape":"Description"}, - "encryptionConfiguration":{"shape":"EncryptionConfiguration"}, - "tags":{"shape":"Tags"}, + "displayName":{ + "shape":"ApplicationName", + "documentation":"

A name for the Amazon Q Business application.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role with permissions to access your Amazon CloudWatch logs and metrics.

" + }, + "identityCenterInstanceArn":{ + "shape":"InstanceArn", + "documentation":"

The Amazon Resource Name (ARN) of the IAM Identity Center instance you are either creating for—or connecting to—your Amazon Q Business application.

" + }, + "description":{ + "shape":"Description", + "documentation":"

A description for the Amazon Q Business application.

" + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

The identifier of the KMS key that is used to encrypt your data. Amazon Q Business doesn't support asymmetric keys.

" + }, + "tags":{ + "shape":"Tags", + "documentation":"

A list of key-value pairs that identify or categorize your Amazon Q Business application. You can also use tags to help control access to the application. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the request to create your Amazon Q Business application.

", "idempotencyToken":true }, - "attachmentsConfiguration":{"shape":"AttachmentsConfiguration"} + "attachmentsConfiguration":{ + "shape":"AttachmentsConfiguration", + "documentation":"

An option to allow end users to upload files directly during chat.

" + }, + "qAppsConfiguration":{ + "shape":"QAppsConfiguration", + "documentation":"

An option to allow end users to create and use Amazon Q Apps in the web experience.

" + } } }, "CreateApplicationResponse":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "applicationArn":{"shape":"ApplicationArn"} + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

" + }, + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

The Amazon Resource Name (ARN) of the Amazon Q Business application.

" + } } }, "CreateDataSourceRequest":{ @@ -1534,23 +2233,47 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application the data source will be attached to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index that you want to use with the data source connector.

", "location":"uri", "locationName":"indexId" }, - "displayName":{"shape":"DataSourceName"}, - "configuration":{"shape":"DataSourceConfiguration"}, - "vpcConfiguration":{"shape":"DataSourceVpcConfiguration"}, - "description":{"shape":"Description"}, - "tags":{"shape":"Tags"}, - "syncSchedule":{"shape":"SyncSchedule"}, - "roleArn":{"shape":"RoleArn"}, + "displayName":{ + "shape":"DataSourceName", + "documentation":"

A name for the data source connector.

" + }, + "configuration":{ + "shape":"DataSourceConfiguration", + "documentation":"

Configuration information to connect to your data source repository. For configuration templates for your specific data source, see Supported connectors.

" + }, + "vpcConfiguration":{ + "shape":"DataSourceVpcConfiguration", + "documentation":"

Configuration information for an Amazon VPC (Virtual Private Cloud) to connect to your data source. For more information, see Using Amazon VPC with Amazon Q Business connectors.

" + }, + "description":{ + "shape":"Description", + "documentation":"

A description for the data source connector.

" + }, + "tags":{ + "shape":"Tags", + "documentation":"

A list of key-value pairs that identify or categorize the data source connector. You can also use tags to help control access to the data source connector. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" + }, + "syncSchedule":{ + "shape":"SyncSchedule", + "documentation":"

Sets the frequency for Amazon Q Business to check the documents in your data source repository and update your index. If you don't set a schedule, Amazon Q Business won't periodically update the index.

Specify a cron- format schedule string or an empty string to indicate that the index is updated on demand. You can't specify the Schedule parameter when the Type parameter is set to CUSTOM. If you do, you receive a ValidationException exception.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role with permission to access the data source and required resources.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token you provide to identify a request to create a data source connector. Multiple calls to the CreateDataSource API with the same client token will create only one data source connector.

", "idempotencyToken":true }, "documentEnrichmentConfiguration":{"shape":"DocumentEnrichmentConfiguration"} @@ -1559,8 +2282,14 @@ "CreateDataSourceResponse":{ "type":"structure", "members":{ - "dataSourceId":{"shape":"DataSourceId"}, - "dataSourceArn":{"shape":"DataSourceArn"} + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

" + }, + "dataSourceArn":{ + "shape":"DataSourceArn", + "documentation":"

The Amazon Resource Name (ARN) of a data source in an Amazon Q Business application.

" + } } }, "CreateIndexRequest":{ @@ -1572,15 +2301,33 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application using the index.

", "location":"uri", "locationName":"applicationId" }, - "displayName":{"shape":"IndexName"}, - "description":{"shape":"Description"}, - "tags":{"shape":"Tags"}, - "capacityConfiguration":{"shape":"IndexCapacityConfiguration"}, + "displayName":{ + "shape":"IndexName", + "documentation":"

A name for the Amazon Q Business index.

" + }, + "type":{ + "shape":"IndexType", + "documentation":"

The index type that's suitable for your needs. For more information on what's included in each type of index, see Amazon Q Business tiers.

" + }, + "description":{ + "shape":"Description", + "documentation":"

A description for the Amazon Q Business index.

" + }, + "tags":{ + "shape":"Tags", + "documentation":"

A list of key-value pairs that identify or categorize the index. You can also use tags to help control access to the index. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" + }, + "capacityConfiguration":{ + "shape":"IndexCapacityConfiguration", + "documentation":"

The capacity units you want to provision for your index. You can add and remove capacity to fit your usage needs.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the request to create an index. Multiple calls to the CreateIndex API with the same client token will create only one index.

", "idempotencyToken":true } } @@ -1588,8 +2335,14 @@ "CreateIndexResponse":{ "type":"structure", "members":{ - "indexId":{"shape":"IndexId"}, - "indexArn":{"shape":"IndexArn"} + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier for the Amazon Q Business index.

" + }, + "indexArn":{ + "shape":"IndexArn", + "documentation":"

The Amazon Resource Name (ARN) of an Amazon Q Business index.

" + } } }, "CreatePluginRequest":{ @@ -1598,22 +2351,39 @@ "applicationId", "displayName", "type", - "serverUrl", "authConfiguration" ], "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application that will contain the plugin.

", "location":"uri", "locationName":"applicationId" }, - "displayName":{"shape":"PluginName"}, - "type":{"shape":"PluginType"}, - "serverUrl":{"shape":"Url"}, + "displayName":{ + "shape":"PluginName", + "documentation":"

A the name for your plugin.

" + }, + "type":{ + "shape":"PluginType", + "documentation":"

The type of plugin you want to create.

" + }, "authConfiguration":{"shape":"PluginAuthConfiguration"}, - "tags":{"shape":"Tags"}, + "serverUrl":{ + "shape":"Url", + "documentation":"

The source URL used for plugin configuration.

" + }, + "customPluginConfiguration":{ + "shape":"CustomPluginConfiguration", + "documentation":"

Contains configuration for a custom plugin.

" + }, + "tags":{ + "shape":"Tags", + "documentation":"

A list of key-value pairs that identify or categorize the data source connector. You can also use tags to help control access to the data source connector. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the request to create your Amazon Q Business plugin.

", "idempotencyToken":true } } @@ -1621,8 +2391,18 @@ "CreatePluginResponse":{ "type":"structure", "members":{ - "pluginId":{"shape":"PluginId"}, - "pluginArn":{"shape":"PluginArn"} + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin created.

" + }, + "pluginArn":{ + "shape":"PluginArn", + "documentation":"

The Amazon Resource Name (ARN) of a plugin.

" + }, + "buildStatus":{ + "shape":"PluginBuildStatus", + "documentation":"

The current status of a plugin. A plugin is modified asynchronously.

" + } } }, "CreateRetrieverRequest":{ @@ -1636,25 +2416,45 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of your Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, - "type":{"shape":"RetrieverType"}, - "displayName":{"shape":"RetrieverName"}, + "type":{ + "shape":"RetrieverType", + "documentation":"

The type of retriever you are using.

" + }, + "displayName":{ + "shape":"RetrieverName", + "documentation":"

The name of your retriever.

" + }, "configuration":{"shape":"RetrieverConfiguration"}, - "roleArn":{"shape":"RoleArn"}, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The ARN of an IAM role used by Amazon Q Business to access the basic authentication credentials stored in a Secrets Manager secret.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the request to create your Amazon Q Business application retriever.

", "idempotencyToken":true }, - "tags":{"shape":"Tags"} + "tags":{ + "shape":"Tags", + "documentation":"

A list of key-value pairs that identify or categorize the retriever. You can also use tags to help control access to the retriever. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" + } } }, "CreateRetrieverResponse":{ "type":"structure", "members":{ - "retrieverId":{"shape":"RetrieverId"}, - "retrieverArn":{"shape":"RetrieverArn"} + "retrieverId":{ + "shape":"RetrieverId", + "documentation":"

The identifier of the retriever you are using.

" + }, + "retrieverArn":{ + "shape":"RetrieverArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role associated with a retriever.

" + } } }, "CreateUserRequest":{ @@ -1666,13 +2466,21 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application for which the user mapping will be created.

", "location":"uri", "locationName":"applicationId" }, - "userId":{"shape":"String"}, - "userAliases":{"shape":"CreateUserRequestUserAliasesList"}, + "userId":{ + "shape":"String", + "documentation":"

The user emails attached to a user mapping.

" + }, + "userAliases":{ + "shape":"CreateUserRequestUserAliasesList", + "documentation":"

The list of user aliases in the mapping.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the request to create your Amazon Q Business user mapping.

", "idempotencyToken":true } } @@ -1694,16 +2502,37 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business web experience.

", "location":"uri", "locationName":"applicationId" }, - "title":{"shape":"WebExperienceTitle"}, - "subtitle":{"shape":"WebExperienceSubtitle"}, - "welcomeMessage":{"shape":"WebExperienceWelcomeMessage"}, - "samplePromptsControlMode":{"shape":"WebExperienceSamplePromptsControlMode"}, - "tags":{"shape":"Tags"}, + "title":{ + "shape":"WebExperienceTitle", + "documentation":"

The title for your Amazon Q Business web experience.

" + }, + "subtitle":{ + "shape":"WebExperienceSubtitle", + "documentation":"

A subtitle to personalize your Amazon Q Business web experience.

" + }, + "welcomeMessage":{ + "shape":"WebExperienceWelcomeMessage", + "documentation":"

The customized welcome message for end users of an Amazon Q Business web experience.

" + }, + "samplePromptsControlMode":{ + "shape":"WebExperienceSamplePromptsControlMode", + "documentation":"

Determines whether sample prompts are enabled in the web experience for an end user.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of the service role attached to your web experience.

" + }, + "tags":{ + "shape":"Tags", + "documentation":"

A list of key-value pairs that identify or categorize your Amazon Q Business web experience. You can also use tags to help control access to the web experience. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" + }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token you provide to identify a request to create an Amazon Q Business web experience.

", "idempotencyToken":true } } @@ -1711,20 +2540,86 @@ "CreateWebExperienceResponse":{ "type":"structure", "members":{ - "webExperienceId":{"shape":"WebExperienceId"}, - "webExperienceArn":{"shape":"WebExperienceArn"} + "webExperienceId":{ + "shape":"WebExperienceId", + "documentation":"

The identifier of the Amazon Q Business web experience.

" + }, + "webExperienceArn":{ + "shape":"WebExperienceArn", + "documentation":"

The Amazon Resource Name (ARN) of an Amazon Q Business web experience.

" + } } }, + "CreatorModeConfiguration":{ + "type":"structure", + "required":["creatorModeControl"], + "members":{ + "creatorModeControl":{ + "shape":"CreatorModeControl", + "documentation":"

Status information about whether CREATOR_MODE has been enabled or disabled. The default status is DISABLED.

" + } + }, + "documentation":"

Configuration information required to invoke chat in CREATOR_MODE.

For more information, see Admin controls and guardrails and Conversation settings.

" + }, + "CreatorModeControl":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, + "CustomPluginConfiguration":{ + "type":"structure", + "required":[ + "description", + "apiSchemaType", + "apiSchema" + ], + "members":{ + "description":{ + "shape":"PluginDescription", + "documentation":"

A description for your custom plugin configuration.

" + }, + "apiSchemaType":{ + "shape":"APISchemaType", + "documentation":"

The type of OpenAPI schema to use.

" + }, + "apiSchema":{ + "shape":"APISchema", + "documentation":"

Contains either details about the S3 object containing the OpenAPI schema for the action group or the JSON or YAML-formatted payload defining the schema.

" + } + }, + "documentation":"

Configuration information required to create a custom plugin.

" + }, "DataSource":{ "type":"structure", "members":{ - "displayName":{"shape":"DataSourceName"}, - "dataSourceId":{"shape":"DataSourceId"}, - "type":{"shape":"String"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "status":{"shape":"DataSourceStatus"} - } + "displayName":{ + "shape":"DataSourceName", + "documentation":"

The name of the Amazon Q Business data source.

" + }, + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the Amazon Q Business data source.

" + }, + "type":{ + "shape":"String", + "documentation":"

The type of the Amazon Q Business data source.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business data source was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business data source was last updated.

" + }, + "status":{ + "shape":"DataSourceStatus", + "documentation":"

The status of the Amazon Q Business data source.

" + } + }, + "documentation":"

A data source in an Amazon Q Business application.

" }, "DataSourceArn":{ "type":"string", @@ -1736,6 +2631,7 @@ "type":"structure", "members":{ }, + "documentation":"

Provides the configuration information for an Amazon Q Business data source.

", "document":true }, "DataSourceId":{ @@ -1770,24 +2666,62 @@ "DataSourceSyncJob":{ "type":"structure", "members":{ - "executionId":{"shape":"ExecutionId"}, - "startTime":{"shape":"Timestamp"}, - "endTime":{"shape":"Timestamp"}, - "status":{"shape":"DataSourceSyncJobStatus"}, - "error":{"shape":"ErrorDetail"}, - "dataSourceErrorCode":{"shape":"String"}, - "metrics":{"shape":"DataSourceSyncJobMetrics"} - } + "executionId":{ + "shape":"ExecutionId", + "documentation":"

The identifier of a data source synchronization job.

" + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

The Unix time stamp when the data source synchronization job started.

" + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the synchronization job completed.

" + }, + "status":{ + "shape":"DataSourceSyncJobStatus", + "documentation":"

The status of the synchronization job. When the Status field is set to SUCCEEDED, the synchronization job is done. If the status code is FAILED, the ErrorCode and ErrorMessage fields give you the reason for the failure.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

If the Status field is set to FAILED, the ErrorCode field indicates the reason the synchronization failed.

" + }, + "dataSourceErrorCode":{ + "shape":"String", + "documentation":"

If the reason that the synchronization failed is due to an error with the underlying data source, this field contains a code that identifies the error.

" + }, + "metrics":{ + "shape":"DataSourceSyncJobMetrics", + "documentation":"

Maps a batch delete document request to a specific data source sync job. This is optional and should only be supplied when documents are deleted by a data source connector.

" + } + }, + "documentation":"

Provides information about an Amazon Q Business data source connector synchronization job.

" }, "DataSourceSyncJobMetrics":{ "type":"structure", "members":{ - "documentsAdded":{"shape":"MetricValue"}, - "documentsModified":{"shape":"MetricValue"}, - "documentsDeleted":{"shape":"MetricValue"}, - "documentsFailed":{"shape":"MetricValue"}, - "documentsScanned":{"shape":"MetricValue"} - } + "documentsAdded":{ + "shape":"MetricValue", + "documentation":"

The current count of documents added from the data source during the data source sync.

" + }, + "documentsModified":{ + "shape":"MetricValue", + "documentation":"

The current count of documents modified in the data source during the data source sync.

" + }, + "documentsDeleted":{ + "shape":"MetricValue", + "documentation":"

The current count of documents deleted from the data source during the data source sync.

" + }, + "documentsFailed":{ + "shape":"MetricValue", + "documentation":"

The current count of documents that failed to sync from the data source during the data source sync.

" + }, + "documentsScanned":{ + "shape":"MetricValue", + "documentation":"

The current count of documents crawled by the ongoing sync job in the data source.

" + } + }, + "documentation":"

Maps a batch delete document request to a specific Amazon Q Business data source connector sync job.

" }, "DataSourceSyncJobStatus":{ "type":"string", @@ -1818,20 +2752,43 @@ "securityGroupIds" ], "members":{ - "subnetIds":{"shape":"SubnetIds"}, - "securityGroupIds":{"shape":"SecurityGroupIds"} - } + "subnetIds":{ + "shape":"SubnetIds", + "documentation":"

A list of identifiers for subnets within your Amazon VPC. The subnets should be able to connect to each other in the VPC, and they should have outgoing access to the Internet through a NAT device.

" + }, + "securityGroupIds":{ + "shape":"SecurityGroupIds", + "documentation":"

A list of identifiers of security groups within your Amazon VPC. The security groups should enable Amazon Q Business to connect to the data source.

" + } + }, + "documentation":"

Provides configuration information needed to connect to an Amazon VPC (Virtual Private Cloud).

" }, "DataSources":{ "type":"list", "member":{"shape":"DataSource"} }, + "DateAttributeBoostingConfiguration":{ + "type":"structure", + "required":["boostingLevel"], + "members":{ + "boostingLevel":{ + "shape":"DocumentAttributeBoostingLevel", + "documentation":"

Specifies how much a document attribute is boosted.

" + }, + "boostingDurationInSeconds":{ + "shape":"BoostingDurationInSeconds", + "documentation":"

Specifies the duration, in seconds, of a boost applies to a DATE type document attribute.

" + } + }, + "documentation":"

Provides information on boosting DATE type document attributes.

For more information on how boosting document attributes work in Amazon Q Business, see Boosting using document attributes.

" + }, "DeleteApplicationRequest":{ "type":"structure", "required":["applicationId"], "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" } @@ -1848,6 +2805,7 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application the chat controls have been configured for.

", "location":"uri", "locationName":"applicationId" } @@ -1862,22 +2820,24 @@ "type":"structure", "required":[ "conversationId", - "applicationId", - "userId" + "applicationId" ], "members":{ "conversationId":{ "shape":"ConversationId", + "documentation":"

The identifier of the Amazon Q Business web experience conversation being deleted.

", "location":"uri", "locationName":"conversationId" }, "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application associated with the conversation.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"UserId", + "documentation":"

The identifier of the user who is deleting the conversation.

", "location":"querystring", "locationName":"userId" } @@ -1898,16 +2858,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application used with the data source connector.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index used with the data source connector.

", "location":"uri", "locationName":"indexId" }, "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector that you want to delete.

", "location":"uri", "locationName":"dataSourceId" } @@ -1922,8 +2885,12 @@ "type":"structure", "required":["documentId"], "members":{ - "documentId":{"shape":"DocumentId"} - } + "documentId":{ + "shape":"DocumentId", + "documentation":"

The identifier of the deleted document.

" + } + }, + "documentation":"

A document deleted from an Amazon Q Business data source connector.

" }, "DeleteDocuments":{ "type":"list", @@ -1939,21 +2906,25 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application in which the group mapping belongs.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index you want to delete the group from.

", "location":"uri", "locationName":"indexId" }, "groupName":{ "shape":"GroupName", + "documentation":"

The name of the group you want to delete.

", "location":"uri", "locationName":"groupName" }, "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source linked to the group

A group can be tied to multiple data sources. You can delete a group from accessing documents in a certain data source. For example, the groups \"Research\", \"Engineering\", and \"Sales and Marketing\" are all tied to the company's documents stored in the data sources Confluence and Salesforce. You want to delete \"Research\" and \"Engineering\" groups from Salesforce, so that these groups cannot access customer-related documents stored in Salesforce. Only \"Sales and Marketing\" should access documents in the Salesforce data source.

", "location":"querystring", "locationName":"dataSourceId" } @@ -1973,11 +2944,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application the Amazon Q Business index is linked to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the Amazon Q Business index.

", "location":"uri", "locationName":"indexId" } @@ -1997,11 +2970,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier the application attached to the Amazon Q Business plugin.

", "location":"uri", "locationName":"applicationId" }, "pluginId":{ "shape":"PluginId", + "documentation":"

The identifier of the plugin being deleted.

", "location":"uri", "locationName":"pluginId" } @@ -2021,11 +2996,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application using the retriever.

", "location":"uri", "locationName":"applicationId" }, "retrieverId":{ "shape":"RetrieverId", + "documentation":"

The identifier of the retriever being deleted.

", "location":"uri", "locationName":"retrieverId" } @@ -2045,11 +3022,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application from which the user is being deleted.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"String", + "documentation":"

The user email being deleted.

", "location":"uri", "locationName":"userId" } @@ -2069,11 +3048,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to the Amazon Q Business web experience.

", "location":"uri", "locationName":"applicationId" }, "webExperienceId":{ "shape":"WebExperienceId", + "documentation":"

The identifier of the Amazon Q Business web experience being deleted.

", "location":"uri", "locationName":"webExperienceId" } @@ -2094,14 +3075,36 @@ "type":"structure", "required":["id"], "members":{ - "id":{"shape":"DocumentId"}, - "attributes":{"shape":"DocumentAttributes"}, - "content":{"shape":"DocumentContent"}, - "contentType":{"shape":"ContentType"}, - "title":{"shape":"Title"}, - "accessConfiguration":{"shape":"AccessConfiguration"}, - "documentEnrichmentConfiguration":{"shape":"DocumentEnrichmentConfiguration"} - } + "id":{ + "shape":"DocumentId", + "documentation":"

The identifier of the document.

" + }, + "attributes":{ + "shape":"DocumentAttributes", + "documentation":"

Custom attributes to apply to the document for refining Amazon Q Business web experience responses.

" + }, + "content":{ + "shape":"DocumentContent", + "documentation":"

The contents of the document.

" + }, + "contentType":{ + "shape":"ContentType", + "documentation":"

The file type of the document in the Blob field.

If you want to index snippets or subsets of HTML documents instead of the entirety of the HTML documents, you add the HTML start and closing tags (<HTML>content</HTML>) around the content.

" + }, + "title":{ + "shape":"Title", + "documentation":"

The title of the document.

" + }, + "accessConfiguration":{ + "shape":"AccessConfiguration", + "documentation":"

Configuration information for access permission to a document.

" + }, + "documentEnrichmentConfiguration":{ + "shape":"DocumentEnrichmentConfiguration", + "documentation":"

The configuration information for altering document metadata and content during the document ingestion process.

" + } + }, + "documentation":"

A document in an Amazon Q Business application.

" }, "DocumentAttribute":{ "type":"structure", @@ -2110,9 +3113,55 @@ "value" ], "members":{ - "name":{"shape":"DocumentAttributeKey"}, - "value":{"shape":"DocumentAttributeValue"} - } + "name":{ + "shape":"DocumentAttributeKey", + "documentation":"

The identifier for the attribute.

" + }, + "value":{ + "shape":"DocumentAttributeValue", + "documentation":"

The value of the attribute.

" + } + }, + "documentation":"

A document attribute or metadata field.

" + }, + "DocumentAttributeBoostingConfiguration":{ + "type":"structure", + "members":{ + "numberConfiguration":{ + "shape":"NumberAttributeBoostingConfiguration", + "documentation":"

Provides information on boosting NUMBER type document attributes.

" + }, + "stringConfiguration":{ + "shape":"StringAttributeBoostingConfiguration", + "documentation":"

Provides information on boosting STRING type document attributes.

" + }, + "dateConfiguration":{ + "shape":"DateAttributeBoostingConfiguration", + "documentation":"

Provides information on boosting DATE type document attributes.

" + }, + "stringListConfiguration":{ + "shape":"StringListAttributeBoostingConfiguration", + "documentation":"

Provides information on boosting STRING_LIST type document attributes.

" + } + }, + "documentation":"

Provides information on boosting supported Amazon Q Business document attribute types. When an end user chat query matches document attributes that have been boosted, Amazon Q Business prioritizes generating responses from content that matches the boosted document attributes.

For STRING and STRING_LIST type document attributes to be used for boosting on the console and the API, they must be enabled for search using the DocumentAttributeConfiguration object of the UpdateIndex API. If you haven't enabled searching on these attributes, you can't boost attributes of these data types on either the console or the API.

For more information on how boosting document attributes work in Amazon Q Business, see Boosting using document attributes.

", + "union":true + }, + "DocumentAttributeBoostingLevel":{ + "type":"string", + "enum":[ + "NONE", + "LOW", + "MEDIUM", + "HIGH", + "VERY_HIGH" + ] + }, + "DocumentAttributeBoostingOverrideMap":{ + "type":"map", + "key":{"shape":"DocumentAttributeKey"}, + "value":{"shape":"DocumentAttributeBoostingConfiguration"}, + "min":1 }, "DocumentAttributeCondition":{ "type":"structure", @@ -2121,18 +3170,35 @@ "operator" ], "members":{ - "key":{"shape":"DocumentAttributeKey"}, - "operator":{"shape":"DocumentEnrichmentConditionOperator"}, + "key":{ + "shape":"DocumentAttributeKey", + "documentation":"

The identifier of the document attribute used for the condition.

For example, 'Source_URI' could be an identifier for the attribute or metadata field that contains source URIs associated with the documents.

Amazon Q Business currently doesn't support _document_body as an attribute key used for the condition.

" + }, + "operator":{ + "shape":"DocumentEnrichmentConditionOperator", + "documentation":"

The identifier of the document attribute used for the condition.

For example, 'Source_URI' could be an identifier for the attribute or metadata field that contains source URIs associated with the documents.

Amazon Q Business currently does not support _document_body as an attribute key used for the condition.

" + }, "value":{"shape":"DocumentAttributeValue"} - } + }, + "documentation":"

The condition used for the target document attribute or metadata field when ingesting documents into Amazon Q Business. You use this with DocumentAttributeTarget to apply the condition.

For example, you can create the 'Department' target field and have it prefill department names associated with the documents based on information in the 'Source_URI' field. Set the condition that if the 'Source_URI' field contains 'financial' in its URI value, then prefill the target field 'Department' with the target value 'Finance' for the document.

Amazon Q Business can't create a target field if it has not already been created as an index field. After you create your index field, you can create a document metadata field using DocumentAttributeTarget. Amazon Q Business then will map your newly created metadata field to your index field.

" }, "DocumentAttributeConfiguration":{ "type":"structure", "members":{ - "name":{"shape":"String"}, - "type":{"shape":"AttributeType"}, - "search":{"shape":"Status"} - } + "name":{ + "shape":"DocumentMetadataConfigurationName", + "documentation":"

The name of the document attribute.

" + }, + "type":{ + "shape":"AttributeType", + "documentation":"

The type of document attribute.

" + }, + "search":{ + "shape":"Status", + "documentation":"

Information about whether the document attribute can be used by an end user to search for information on their web experience.

" + } + }, + "documentation":"

Configuration information for document attributes. Document attributes are metadata or fields associated with your documents. For example, the company department name associated with each document.

For more information, see Understanding document attributes.

" }, "DocumentAttributeConfigurations":{ "type":"list", @@ -2154,19 +3220,39 @@ "type":"structure", "required":["key"], "members":{ - "key":{"shape":"DocumentAttributeKey"}, + "key":{ + "shape":"DocumentAttributeKey", + "documentation":"

The identifier of the target document attribute or metadata field. For example, 'Department' could be an identifier for the target attribute or metadata field that includes the department names associated with the documents.

" + }, "value":{"shape":"DocumentAttributeValue"}, - "attributeValueOperator":{"shape":"AttributeValueOperator"} - } + "attributeValueOperator":{ + "shape":"AttributeValueOperator", + "documentation":"

TRUE to delete the existing target value for your specified target attribute key. You cannot create a target value and set this to TRUE.

" + } + }, + "documentation":"

The target document attribute or metadata field you want to alter when ingesting documents into Amazon Q Business.

For example, you can delete all customer identification numbers associated with the documents, stored in the document metadata field called 'Customer_ID' by setting the target key as 'Customer_ID' and the deletion flag to TRUE. This removes all customer ID values in the field 'Customer_ID'. This would scrub personally identifiable information from each document's metadata.

Amazon Q Business can't create a target field if it has not already been created as an index field. After you create your index field, you can create a document metadata field using DocumentAttributeTarget . Amazon Q Business will then map your newly created document attribute to your index field.

You can also use this with DocumentAttributeCondition .

" }, "DocumentAttributeValue":{ "type":"structure", "members":{ - "stringValue":{"shape":"DocumentAttributeValueStringValueString"}, - "stringListValue":{"shape":"DocumentAttributeStringListValue"}, - "longValue":{"shape":"Long"}, - "dateValue":{"shape":"Timestamp"} + "stringValue":{ + "shape":"DocumentAttributeValueStringValueString", + "documentation":"

A string.

" + }, + "stringListValue":{ + "shape":"DocumentAttributeStringListValue", + "documentation":"

A list of strings.

" + }, + "longValue":{ + "shape":"Long", + "documentation":"

A long integer value.

" + }, + "dateValue":{ + "shape":"Timestamp", + "documentation":"

A date expressed as an ISO 8601 string.

It's important for the time zone to be included in the ISO 8601 date-time format. For example, 2012-03-25T12:30:10+01:00 is the ISO 8601 date-time format for March 25th 2012 at 12:30PM (plus 10 seconds) in Central European Time.

" + } }, + "documentation":"

The value of a document attribute. You can only provide one value for a document attribute.

", "union":true }, "DocumentAttributeValueStringValueString":{ @@ -2183,9 +3269,16 @@ "DocumentContent":{ "type":"structure", "members":{ - "blob":{"shape":"Blob"}, - "s3":{"shape":"S3"} + "blob":{ + "shape":"Blob", + "documentation":"

The contents of the document. Documents passed to the blob parameter must be base64 encoded. Your code might not need to encode the document file bytes if you're using an Amazon Web Services SDK to call Amazon Q Business APIs. If you are calling the Amazon Q Business endpoint directly using REST, you must base64 encode the contents before sending.

" + }, + "s3":{ + "shape":"S3", + "documentation":"

The path to the document in an Amazon S3 bucket.

" + } }, + "documentation":"

The contents of a document.

", "union":true }, "DocumentContentOperator":{ @@ -2199,12 +3292,28 @@ "DocumentDetails":{ "type":"structure", "members":{ - "documentId":{"shape":"DocumentId"}, - "status":{"shape":"DocumentStatus"}, - "error":{"shape":"ErrorDetail"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"} - } + "documentId":{ + "shape":"DocumentId", + "documentation":"

The identifier of the document.

" + }, + "status":{ + "shape":"DocumentStatus", + "documentation":"

The current status of the document.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

An error message associated with the document.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the document was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the document was last updated.

" + } + }, + "documentation":"

The details of a document within an Amazon Q Business index.

" }, "DocumentEnrichmentConditionOperator":{ "type":"string", @@ -2225,10 +3334,14 @@ "DocumentEnrichmentConfiguration":{ "type":"structure", "members":{ - "inlineConfigurations":{"shape":"InlineDocumentEnrichmentConfigurations"}, + "inlineConfigurations":{ + "shape":"InlineDocumentEnrichmentConfigurations", + "documentation":"

Configuration information to alter document attributes or metadata fields and content when ingesting documents into Amazon Q Business.

" + }, "preExtractionHookConfiguration":{"shape":"HookConfiguration"}, "postExtractionHookConfiguration":{"shape":"HookConfiguration"} - } + }, + "documentation":"

Provides the configuration information for altering document metadata and content during the document ingestion process.

For more information, see Custom document enrichment.

" }, "DocumentId":{ "type":"string", @@ -2236,6 +3349,12 @@ "min":1, "pattern":"\\P{C}*" }, + "DocumentMetadataConfigurationName":{ + "type":"string", + "max":30, + "min":1, + "pattern":"[a-zA-Z0-9_][a-zA-Z0-9_-]*" + }, "DocumentStatus":{ "type":"string", "enum":[ @@ -2258,9 +3377,16 @@ "EligibleDataSource":{ "type":"structure", "members":{ - "indexId":{"shape":"IndexId"}, - "dataSourceId":{"shape":"DataSourceId"} - } + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier of the index the data source is attached to.

" + }, + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the data source.

" + } + }, + "documentation":"

The identifier of the data source Amazon Q Business will generate responses from.

" }, "EligibleDataSources":{ "type":"list", @@ -2271,8 +3397,19 @@ "EncryptionConfiguration":{ "type":"structure", "members":{ - "kmsKeyId":{"shape":"KmsKeyId"} - } + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

The identifier of the KMS key. Amazon Q Business doesn't support asymmetric keys.

" + } + }, + "documentation":"

Provides the identifier of the KMS key used to encrypt data indexed by Amazon Q Business. Amazon Q Business doesn't support asymmetric keys.

" + }, + "EndOfInputEvent":{ + "type":"structure", + "members":{ + }, + "documentation":"

The end of the streaming input for the Chat API.

", + "event":true }, "ErrorCode":{ "type":"string", @@ -2286,9 +3423,16 @@ "ErrorDetail":{ "type":"structure", "members":{ - "errorMessage":{"shape":"ErrorMessage"}, - "errorCode":{"shape":"ErrorCode"} - } + "errorMessage":{ + "shape":"ErrorMessage", + "documentation":"

The message explaining the data source sync error.

" + }, + "errorCode":{ + "shape":"ErrorCode", + "documentation":"

The code associated with the data source sync error.

" + } + }, + "documentation":"

Provides information about a data source sync error.

" }, "ErrorMessage":{ "type":"string", @@ -2314,13 +3458,43 @@ "min":36, "pattern":"[a-zA-Z0-9][a-zA-Z0-9-]{35}" }, + "FailedAttachmentEvent":{ + "type":"structure", + "members":{ + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the conversation associated with the failed file upload.

" + }, + "userMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of the end user chat message associated with the file upload.

" + }, + "systemMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of the AI-generated message associated with the file upload.

" + }, + "attachment":{"shape":"AttachmentOutput"} + }, + "documentation":"

A failed file upload during web experience chat.

", + "event":true + }, "FailedDocument":{ "type":"structure", "members":{ - "id":{"shape":"DocumentId"}, - "error":{"shape":"ErrorDetail"}, - "dataSourceId":{"shape":"DataSourceId"} - } + "id":{ + "shape":"DocumentId", + "documentation":"

The identifier of the document that couldn't be removed from the Amazon Q Business index.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

An explanation for why the document couldn't be removed from the index.

" + }, + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the Amazon Q Business data source connector that contains the failed document.

" + } + }, + "documentation":"

A list of documents that could not be removed from an Amazon Q Business index. Each entry contains an error message that indicates why the document couldn't be removed from the index.

" }, "FailedDocuments":{ "type":"list", @@ -2332,6 +3506,7 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" } @@ -2340,17 +3515,58 @@ "GetApplicationResponse":{ "type":"structure", "members":{ - "displayName":{"shape":"ApplicationName"}, - "applicationId":{"shape":"ApplicationId"}, - "applicationArn":{"shape":"ApplicationArn"}, - "roleArn":{"shape":"RoleArn"}, - "status":{"shape":"ApplicationStatus"}, - "description":{"shape":"Description"}, - "encryptionConfiguration":{"shape":"EncryptionConfiguration"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "error":{"shape":"ErrorDetail"}, - "attachmentsConfiguration":{"shape":"AppliedAttachmentsConfiguration"} + "displayName":{ + "shape":"ApplicationName", + "documentation":"

The name of the Amazon Q Business application.

" + }, + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

" + }, + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

The Amazon Resource Name (ARN) of the Amazon Q Business application.

" + }, + "identityCenterApplicationArn":{ + "shape":"IdcApplicationArn", + "documentation":"

The Amazon Resource Name (ARN) of the AWS IAM Identity Center instance attached to your Amazon Q Business application.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of the IAM with permissions to access your CloudWatch logs and metrics.

" + }, + "status":{ + "shape":"ApplicationStatus", + "documentation":"

The status of the Amazon Q Business application.

" + }, + "description":{ + "shape":"Description", + "documentation":"

A description for the Amazon Q Business application.

" + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

The identifier of the Amazon Web Services KMS key that is used to encrypt your data. Amazon Q Business doesn't support asymmetric keys.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was last updated.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was last updated.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

If the Status field is set to ERROR, the ErrorMessage field contains a description of the error that caused the synchronization to fail.

" + }, + "attachmentsConfiguration":{ + "shape":"AppliedAttachmentsConfiguration", + "documentation":"

Settings for whether end users can upload files directly during chat.

" + }, + "qAppsConfiguration":{ + "shape":"QAppsConfiguration", + "documentation":"

Settings for whether end users can create and use Amazon Q Apps in the web experience.

" + } } }, "GetChatControlsConfigurationRequest":{ @@ -2359,16 +3575,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application for which the chat controls are configured.

", "location":"uri", "locationName":"applicationId" }, "maxResults":{ "shape":"MaxResultsIntegerForGetTopicConfigurations", + "documentation":"

The maximum number of configured chat controls to return.

", "location":"querystring", "locationName":"maxResults" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business chat controls configured.

", "location":"querystring", "locationName":"nextToken" } @@ -2377,10 +3596,26 @@ "GetChatControlsConfigurationResponse":{ "type":"structure", "members":{ - "responseScope":{"shape":"ResponseScope"}, - "blockedPhrases":{"shape":"BlockedPhrasesConfiguration"}, - "topicConfigurations":{"shape":"TopicConfigurations"}, - "nextToken":{"shape":"NextToken"} + "responseScope":{ + "shape":"ResponseScope", + "documentation":"

The response scope configured for a Amazon Q Business application. This determines whether your application uses its retrieval augmented generation (RAG) system to generate answers only from your enterprise data, or also uses the large language models (LLM) knowledge to respons to end user questions in chat.

" + }, + "blockedPhrases":{ + "shape":"BlockedPhrasesConfiguration", + "documentation":"

The phrases blocked from chat by your chat control configuration.

" + }, + "topicConfigurations":{ + "shape":"TopicConfigurations", + "documentation":"

The topic specific controls configured for a Amazon Q Business application.

" + }, + "creatorModeConfiguration":{ + "shape":"AppliedCreatorModeConfiguration", + "documentation":"

The configuration details for CREATOR_MODE.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business chat controls configured.

" + } } }, "GetDataSourceRequest":{ @@ -2393,16 +3628,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identfier of the index used with the data source connector.

", "location":"uri", "locationName":"indexId" }, "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

", "location":"uri", "locationName":"dataSourceId" } @@ -2411,21 +3649,66 @@ "GetDataSourceResponse":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "indexId":{"shape":"IndexId"}, - "dataSourceId":{"shape":"DataSourceId"}, - "dataSourceArn":{"shape":"DataSourceArn"}, - "displayName":{"shape":"DataSourceName"}, - "type":{"shape":"String"}, - "configuration":{"shape":"DataSourceConfiguration"}, - "vpcConfiguration":{"shape":"DataSourceVpcConfiguration"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "description":{"shape":"Description"}, - "status":{"shape":"DataSourceStatus"}, - "syncSchedule":{"shape":"SyncSchedule"}, - "roleArn":{"shape":"RoleArn"}, - "error":{"shape":"ErrorDetail"}, + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

" + }, + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier of the index linked to the data source connector.

" + }, + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

" + }, + "dataSourceArn":{ + "shape":"DataSourceArn", + "documentation":"

The Amazon Resource Name (ARN) of the data source.

" + }, + "displayName":{ + "shape":"DataSourceName", + "documentation":"

The name for the data source connector.

" + }, + "type":{ + "shape":"String", + "documentation":"

The type of the data source connector. For example, S3.

" + }, + "configuration":{ + "shape":"DataSourceConfiguration", + "documentation":"

The details of how the data source connector is configured.

" + }, + "vpcConfiguration":{ + "shape":"DataSourceVpcConfiguration", + "documentation":"

Configuration information for an Amazon VPC (Virtual Private Cloud) to connect to your data source.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the data source connector was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the data source connector was last updated.

" + }, + "description":{ + "shape":"Description", + "documentation":"

The description for the data source connector.

" + }, + "status":{ + "shape":"DataSourceStatus", + "documentation":"

The current status of the data source connector. When the Status field value is FAILED, the ErrorMessage field contains a description of the error that caused the data source connector to fail.

" + }, + "syncSchedule":{ + "shape":"SyncSchedule", + "documentation":"

The schedule for Amazon Q Business to update the index.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of the role with permission to access the data source and required resources.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

When the Status field value is FAILED, the ErrorMessage field contains a description of the error that caused the data source connector to fail.

" + }, "documentEnrichmentConfiguration":{"shape":"DocumentEnrichmentConfiguration"} } }, @@ -2439,21 +3722,25 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application id the group is attached to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index the group is attached to.

", "location":"uri", "locationName":"indexId" }, "groupName":{ "shape":"GroupName", + "documentation":"

The name of the group.

", "location":"uri", "locationName":"groupName" }, "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source the group is attached to.

", "location":"querystring", "locationName":"dataSourceId" } @@ -2462,8 +3749,14 @@ "GetGroupResponse":{ "type":"structure", "members":{ - "status":{"shape":"GroupStatusDetail"}, - "statusHistory":{"shape":"GroupStatusDetails"} + "status":{ + "shape":"GroupStatusDetail", + "documentation":"

The current status of the group.

" + }, + "statusHistory":{ + "shape":"GroupStatusDetails", + "documentation":"

The status history of the group.

" + } } }, "GetIndexRequest":{ @@ -2475,11 +3768,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application connected to the index.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the Amazon Q Business index you want information on.

", "location":"uri", "locationName":"indexId" } @@ -2488,18 +3783,58 @@ "GetIndexResponse":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "indexId":{"shape":"IndexId"}, - "displayName":{"shape":"IndexName"}, - "indexArn":{"shape":"IndexArn"}, - "status":{"shape":"IndexStatus"}, - "description":{"shape":"Description"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "capacityConfiguration":{"shape":"IndexCapacityConfiguration"}, - "documentAttributeConfigurations":{"shape":"DocumentAttributeConfigurations"}, - "error":{"shape":"ErrorDetail"}, - "indexStatistics":{"shape":"IndexStatistics"} + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application associated with the index.

" + }, + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier of the Amazon Q Business index.

" + }, + "displayName":{ + "shape":"IndexName", + "documentation":"

The name of the Amazon Q Business index.

" + }, + "type":{ + "shape":"IndexType", + "documentation":"

The type of index attached to your Amazon Q Business application.

" + }, + "indexArn":{ + "shape":"IndexArn", + "documentation":"

The Amazon Resource Name (ARN) of the Amazon Q Business index.

" + }, + "status":{ + "shape":"IndexStatus", + "documentation":"

The current status of the index. When the value is ACTIVE, the index is ready for use. If the Status field value is FAILED, the ErrorMessage field contains a message that explains why.

" + }, + "description":{ + "shape":"Description", + "documentation":"

The description for the Amazon Q Business index.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business index was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business index was last updated.

" + }, + "capacityConfiguration":{ + "shape":"IndexCapacityConfiguration", + "documentation":"

The storage capacity units chosen for your Amazon Q Business index.

" + }, + "documentAttributeConfigurations":{ + "shape":"DocumentAttributeConfigurations", + "documentation":"

Configuration information for document attributes or metadata. Document metadata are fields associated with your documents. For example, the company department name associated with each document. For more information, see Understanding document attributes.

" + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

When the Status field value is FAILED, the ErrorMessage field contains a message that explains why.

" + }, + "indexStatistics":{ + "shape":"IndexStatistics", + "documentation":"

Provides information about the number of documents indexed.

" + } } }, "GetPluginRequest":{ @@ -2511,11 +3846,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application which contains the plugin.

", "location":"uri", "locationName":"applicationId" }, "pluginId":{ "shape":"PluginId", + "documentation":"

The identifier of the plugin.

", "location":"uri", "locationName":"pluginId" } @@ -2524,16 +3861,51 @@ "GetPluginResponse":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "pluginId":{"shape":"PluginId"}, - "displayName":{"shape":"PluginName"}, - "type":{"shape":"PluginType"}, - "serverUrl":{"shape":"Url"}, + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the application which contains the plugin.

" + }, + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin.

" + }, + "displayName":{ + "shape":"PluginName", + "documentation":"

The name of the plugin.

" + }, + "type":{ + "shape":"PluginType", + "documentation":"

The type of the plugin.

" + }, + "serverUrl":{ + "shape":"Url", + "documentation":"

The source URL used for plugin configuration.

" + }, "authConfiguration":{"shape":"PluginAuthConfiguration"}, - "pluginArn":{"shape":"PluginArn"}, - "state":{"shape":"PluginState"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"} + "customPluginConfiguration":{ + "shape":"CustomPluginConfiguration", + "documentation":"

Configuration information required to create a custom plugin.

" + }, + "buildStatus":{ + "shape":"PluginBuildStatus", + "documentation":"

The current status of a plugin. A plugin is modified asynchronously.

" + }, + "pluginArn":{ + "shape":"PluginArn", + "documentation":"

The Amazon Resource Name (ARN) of the role with permission to access resources needed to create the plugin.

" + }, + "state":{ + "shape":"PluginState", + "documentation":"

The current state of the plugin.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the plugin was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the plugin was last updated.

" + } } }, "GetRetrieverRequest":{ @@ -2545,11 +3917,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application using the retriever.

", "location":"uri", "locationName":"applicationId" }, "retrieverId":{ "shape":"RetrieverId", + "documentation":"

The identifier of the retriever.

", "location":"uri", "locationName":"retrieverId" } @@ -2558,16 +3932,43 @@ "GetRetrieverResponse":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "retrieverId":{"shape":"RetrieverId"}, - "retrieverArn":{"shape":"RetrieverArn"}, - "type":{"shape":"RetrieverType"}, - "status":{"shape":"RetrieverStatus"}, - "displayName":{"shape":"RetrieverName"}, + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application using the retriever.

" + }, + "retrieverId":{ + "shape":"RetrieverId", + "documentation":"

The identifier of the retriever.

" + }, + "retrieverArn":{ + "shape":"RetrieverArn", + "documentation":"

The Amazon Resource Name (ARN) of the IAM role associated with the retriever.

" + }, + "type":{ + "shape":"RetrieverType", + "documentation":"

The type of the retriever.

" + }, + "status":{ + "shape":"RetrieverStatus", + "documentation":"

The status of the retriever.

" + }, + "displayName":{ + "shape":"RetrieverName", + "documentation":"

The name of the retriever.

" + }, "configuration":{"shape":"RetrieverConfiguration"}, - "roleArn":{"shape":"RoleArn"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"} + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of the role with the permission to access the retriever and required resources.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the retriever was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the retriever was last updated.

" + } } }, "GetUserRequest":{ @@ -2579,11 +3980,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application connected to the user.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"String", + "documentation":"

The user email address attached to the user.

", "location":"uri", "locationName":"userId" } @@ -2592,7 +3995,10 @@ "GetUserResponse":{ "type":"structure", "members":{ - "userAliases":{"shape":"UserAliases"} + "userAliases":{ + "shape":"UserAliases", + "documentation":"

A list of user aliases attached to a user.

" + } } }, "GetWebExperienceRequest":{ @@ -2604,11 +4010,13 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to the web experience.

", "location":"uri", "locationName":"applicationId" }, "webExperienceId":{ "shape":"WebExperienceId", + "documentation":"

The identifier of the Amazon Q Business web experience.

", "location":"uri", "locationName":"webExperienceId" } @@ -2617,27 +4025,79 @@ "GetWebExperienceResponse":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "webExperienceId":{"shape":"WebExperienceId"}, - "webExperienceArn":{"shape":"WebExperienceArn"}, - "defaultEndpoint":{"shape":"Url"}, - "status":{"shape":"WebExperienceStatus"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "title":{"shape":"WebExperienceTitle"}, - "subtitle":{"shape":"WebExperienceSubtitle"}, - "welcomeMessage":{"shape":"WebExperienceWelcomeMessage"}, - "samplePromptsControlMode":{"shape":"WebExperienceSamplePromptsControlMode"}, - "authenticationConfiguration":{"shape":"WebExperienceAuthConfiguration"}, - "error":{"shape":"ErrorDetail"} + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to the web experience.

" + }, + "webExperienceId":{ + "shape":"WebExperienceId", + "documentation":"

The identifier of the Amazon Q Business web experience.

" + }, + "webExperienceArn":{ + "shape":"WebExperienceArn", + "documentation":"

The Amazon Resource Name (ARN) of the role with the permission to access the Amazon Q Business web experience and required resources.

" + }, + "defaultEndpoint":{ + "shape":"Url", + "documentation":"

The endpoint of your Amazon Q Business web experience.

" + }, + "status":{ + "shape":"WebExperienceStatus", + "documentation":"

The current status of the Amazon Q Business web experience. When the Status field value is FAILED, the ErrorMessage field contains a description of the error that caused the data source connector to fail.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business web experience was last created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business web experience was last updated.

" + }, + "title":{ + "shape":"WebExperienceTitle", + "documentation":"

The title for your Amazon Q Business web experience.

" + }, + "subtitle":{ + "shape":"WebExperienceSubtitle", + "documentation":"

The subtitle for your Amazon Q Business web experience.

" + }, + "welcomeMessage":{ + "shape":"WebExperienceWelcomeMessage", + "documentation":"

The customized welcome message for end users of an Amazon Q Business web experience.

" + }, + "samplePromptsControlMode":{ + "shape":"WebExperienceSamplePromptsControlMode", + "documentation":"

Determines whether sample prompts are enabled in the web experience for an end user.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of the service role attached to your web experience.

" + }, + "authenticationConfiguration":{ + "shape":"WebExperienceAuthConfiguration", + "documentation":"

The authentication configuration information for your Amazon Q Business web experience.

", + "deprecated":true, + "deprecatedMessage":"Property associated with legacy SAML IdP flow. Deprecated in favor of using AWS IAM Identity Center for user management." + }, + "error":{ + "shape":"ErrorDetail", + "documentation":"

When the Status field value is FAILED, the ErrorMessage field contains a description of the error that caused the data source connector to fail.

" + } } }, "GroupMembers":{ "type":"structure", "members":{ - "memberGroups":{"shape":"MemberGroups"}, - "memberUsers":{"shape":"MemberUsers"} - } + "memberGroups":{ + "shape":"MemberGroups", + "documentation":"

A list of sub groups that belong to a group. For example, the sub groups \"Research\", \"Engineering\", and \"Sales and Marketing\" all belong to the group \"Company\".

" + }, + "memberUsers":{ + "shape":"MemberUsers", + "documentation":"

A list of users that belong to a group. For example, a list of interns all belong to the \"Interns\" group.

" + } + }, + "documentation":"

A list of users or sub groups that belong to a group. This is for generating Amazon Q Business chat results only from document a user has access to.

" }, "GroupName":{ "type":"string", @@ -2658,10 +4118,20 @@ "GroupStatusDetail":{ "type":"structure", "members":{ - "status":{"shape":"GroupStatus"}, - "lastUpdatedAt":{"shape":"Timestamp"}, - "errorDetail":{"shape":"ErrorDetail"} - } + "status":{ + "shape":"GroupStatus", + "documentation":"

The status of a group.

" + }, + "lastUpdatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was last updated.

" + }, + "errorDetail":{ + "shape":"ErrorDetail", + "documentation":"

The details of an error associated a group status.

" + } + }, + "documentation":"

Provides the details of a group's status.

" }, "GroupStatusDetails":{ "type":"list", @@ -2670,8 +4140,12 @@ "GroupSummary":{ "type":"structure", "members":{ - "groupName":{"shape":"GroupName"} - } + "groupName":{ + "shape":"GroupName", + "documentation":"

The name of the group the summary information is for.

" + } + }, + "documentation":"

Summary information for groups.

" }, "GroupSummaryList":{ "type":"list", @@ -2680,21 +4154,56 @@ "HookConfiguration":{ "type":"structure", "members":{ - "invocationCondition":{"shape":"DocumentAttributeCondition"}, - "lambdaArn":{"shape":"LambdaArn"}, - "s3BucketName":{"shape":"S3BucketName"}, - "roleArn":{"shape":"RoleArn"} - } + "invocationCondition":{ + "shape":"DocumentAttributeCondition", + "documentation":"

The condition used for when a Lambda function should be invoked.

For example, you can specify a condition that if there are empty date-time values, then Amazon Q Business should invoke a function that inserts the current date-time.

" + }, + "lambdaArn":{ + "shape":"LambdaArn", + "documentation":"

The Amazon Resource Name (ARN) of a role with permission to run a Lambda function during ingestion. For more information, see IAM roles for Custom Document Enrichment (CDE).

" + }, + "s3BucketName":{ + "shape":"S3BucketName", + "documentation":"

Stores the original, raw documents or the structured, parsed documents before and after altering them. For more information, see Data contracts for Lambda functions.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of a role with permission to run PreExtractionHookConfiguration and PostExtractionHookConfiguration for altering document metadata and content during the document ingestion process.

" + } + }, + "documentation":"

Provides the configuration information for invoking a Lambda function in Lambda to alter document metadata and content when ingesting documents into Amazon Q Business.

You can configure your Lambda function using the PreExtractionHookConfiguration parameter if you want to apply advanced alterations on the original or raw documents.

If you want to apply advanced alterations on the Amazon Q Business structured documents, you must configure your Lambda function using PostExtractionHookConfiguration.

You can only invoke one Lambda function. However, this function can invoke other functions it requires.

For more information, see Custom document enrichment.

" + }, + "IdcApplicationArn":{ + "type":"string", + "max":1224, + "min":10, + "pattern":"arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):sso::\\d{12}:application/(sso)?ins-[a-zA-Z0-9-.]{16}/apl-[a-zA-Z0-9]{16}" }, "Index":{ "type":"structure", "members":{ - "displayName":{"shape":"IndexName"}, - "indexId":{"shape":"IndexId"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "status":{"shape":"IndexStatus"} - } + "displayName":{ + "shape":"IndexName", + "documentation":"

The name of the index.

" + }, + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier for the index.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the index was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the index was last updated.

" + }, + "status":{ + "shape":"IndexStatus", + "documentation":"

The current status of the index. When the status is ACTIVE, the index is ready.

" + } + }, + "documentation":"

Summary information for your Amazon Q Business index.

" }, "IndexArn":{ "type":"string", @@ -2705,8 +4214,12 @@ "IndexCapacityConfiguration":{ "type":"structure", "members":{ - "units":{"shape":"IndexCapacityInteger"} - } + "units":{ + "shape":"IndexCapacityInteger", + "documentation":"

The number of storage units configured for an Amazon Q Business index.

" + } + }, + "documentation":"

Provides information about index capacity configuration.

" }, "IndexCapacityInteger":{ "type":"integer", @@ -2728,8 +4241,12 @@ "IndexStatistics":{ "type":"structure", "members":{ - "textDocumentStatistics":{"shape":"TextDocumentStatistics"} - } + "textDocumentStatistics":{ + "shape":"TextDocumentStatistics", + "documentation":"

The number of documents indexed.

" + } + }, + "documentation":"

Provides information about the number of documents in an index.

" }, "IndexStatus":{ "type":"string", @@ -2741,6 +4258,13 @@ "UPDATING" ] }, + "IndexType":{ + "type":"string", + "enum":[ + "ENTERPRISE", + "STARTER" + ] + }, "IndexedTextBytes":{ "type":"long", "box":true, @@ -2760,8 +4284,12 @@ "members":{ "condition":{"shape":"DocumentAttributeCondition"}, "target":{"shape":"DocumentAttributeTarget"}, - "documentContentOperator":{"shape":"DocumentContentOperator"} - } + "documentContentOperator":{ + "shape":"DocumentContentOperator", + "documentation":"

TRUE to delete content if the condition used for the target attribute is met.

" + } + }, + "documentation":"

Provides the configuration information for applying basic logic to alter document metadata and content when ingesting documents into Amazon Q Business.

To apply advanced logic, to go beyond what you can do with basic logic, see HookConfiguration .

For more information, see Custom document enrichment.

" }, "InlineDocumentEnrichmentConfigurations":{ "type":"list", @@ -2769,6 +4297,12 @@ "max":100, "min":1 }, + "InstanceArn":{ + "type":"string", + "max":1224, + "min":10, + "pattern":"arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}" + }, "Integer":{ "type":"integer", "box":true @@ -2779,6 +4313,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, + "documentation":"

An issue occurred with the internal server used for your Amazon Q Business service. Wait some minutes and try again, or contact Support for help.

", "error":{"httpStatusCode":500}, "exception":true, "fault":true @@ -2787,8 +4322,12 @@ "type":"structure", "required":["indexId"], "members":{ - "indexId":{"shape":"KendraIndexId"} - } + "indexId":{ + "shape":"KendraIndexId", + "documentation":"

The identifier of the Amazon Kendra index.

" + } + }, + "documentation":"

Stores an Amazon Kendra index as a retriever.

" }, "KendraIndexId":{ "type":"string", @@ -2814,6 +4353,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, + "documentation":"

You don't have permissions to perform the action because your license is inactive. Ask your admin to activate your license and try again after your licence is active.

", "error":{ "httpStatusCode":400, "senderFault":true @@ -2825,11 +4365,13 @@ "members":{ "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business applications.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListApplications", + "documentation":"

The maximum number of Amazon Q Business applications to return.

", "location":"querystring", "locationName":"maxResults" } @@ -2838,34 +4380,41 @@ "ListApplicationsResponse":{ "type":"structure", "members":{ - "nextToken":{"shape":"NextToken"}, - "applications":{"shape":"Applications"} + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token. You can use this token in a subsequent request to retrieve the next set of applications.

" + }, + "applications":{ + "shape":"Applications", + "documentation":"

An array of summary information on the configuration of one or more Amazon Q Business applications.

" + } } }, "ListConversationsRequest":{ "type":"structure", - "required":[ - "applicationId", - "userId" - ], + "required":["applicationId"], "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"UserId", + "documentation":"

The identifier of the user involved in the Amazon Q Business web experience conversation.

", "location":"querystring", "locationName":"userId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business conversations.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListConversations", + "documentation":"

The maximum number of Amazon Q Business conversations to return.

", "location":"querystring", "locationName":"maxResults" } @@ -2874,8 +4423,14 @@ "ListConversationsResponse":{ "type":"structure", "members":{ - "nextToken":{"shape":"NextToken"}, - "conversations":{"shape":"Conversations"} + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token, which you can use in a later request to list the next set of messages.

" + }, + "conversations":{ + "shape":"Conversations", + "documentation":"

An array of summary information on the configuration of one or more Amazon Q Business web experiences.

" + } } }, "ListDataSourceSyncJobsRequest":{ @@ -2888,41 +4443,49 @@ "members":{ "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

", "location":"uri", "locationName":"dataSourceId" }, "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application connected to the data source.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index used with the Amazon Q Business data source connector.

", "location":"uri", "locationName":"indexId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incpmplete because there is more data to retriever, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of responses.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListDataSourcesSyncJobs", + "documentation":"

The maximum number of synchronization jobs to return in the response.

", "location":"querystring", "locationName":"maxResults" }, "startTime":{ "shape":"Timestamp", + "documentation":"

The start time of the data source connector sync.

", "location":"querystring", "locationName":"startTime" }, "endTime":{ "shape":"Timestamp", + "documentation":"

The end time of the data source connector sync.

", "location":"querystring", "locationName":"endTime" }, "statusFilter":{ "shape":"DataSourceSyncJobStatus", + "documentation":"

Only returns synchronization jobs with the Status field equal to the specified status.

", "location":"querystring", "locationName":"syncStatus" } @@ -2931,8 +4494,14 @@ "ListDataSourceSyncJobsResponse":{ "type":"structure", "members":{ - "history":{"shape":"DataSourceSyncJobs"}, - "nextToken":{"shape":"NextToken"} + "history":{ + "shape":"DataSourceSyncJobs", + "documentation":"

A history of synchronization jobs for the data source connector.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token. You can use this token in any subsequent request to retrieve the next set of jobs.

" + } } }, "ListDataSourcesRequest":{ @@ -2944,21 +4513,25 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to the data source connectors.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index used with one or more data source connectors.

", "location":"uri", "locationName":"indexId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business data source connectors.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListDataSources", + "documentation":"

The maximum number of data source connectors to return.

", "location":"querystring", "locationName":"maxResults" } @@ -2967,8 +4540,14 @@ "ListDataSourcesResponse":{ "type":"structure", "members":{ - "dataSources":{"shape":"DataSources"}, - "nextToken":{"shape":"NextToken"} + "dataSources":{ + "shape":"DataSources", + "documentation":"

An array of summary information for one or more data source connector.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token. You can use this token in a subsequent request to retrieve the next set of data source connectors.

" + } } }, "ListDocumentsRequest":{ @@ -2980,26 +4559,31 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application id the documents are attached to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index the documents are attached to.

", "location":"uri", "locationName":"indexId" }, "dataSourceIds":{ "shape":"DataSourceIds", + "documentation":"

The identifier of the data sources the documents are attached to.

", "location":"querystring", "locationName":"dataSourceIds" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of documents.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListDocuments", + "documentation":"

The maximum number of documents to return.

", "location":"querystring", "locationName":"maxResults" } @@ -3008,8 +4592,14 @@ "ListDocumentsResponse":{ "type":"structure", "members":{ - "documentDetailList":{"shape":"DocumentDetailList"}, - "nextToken":{"shape":"NextToken"} + "documentDetailList":{ + "shape":"DocumentDetailList", + "documentation":"

A list of document details.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of documents.

" + } } }, "ListGroupsRequest":{ @@ -3022,31 +4612,37 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application for getting a list of groups mapped to users.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index for getting a list of groups mapped to users.

", "location":"uri", "locationName":"indexId" }, "updatedEarlierThan":{ "shape":"Timestamp", + "documentation":"

The timestamp identifier used for the latest PUT or DELETE action for mapping users to their groups.

", "location":"querystring", "locationName":"updatedEarlierThan" }, "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source for getting a list of groups mapped to users.

", "location":"querystring", "locationName":"dataSourceId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the previous response was incomplete (because there is more data to retrieve), Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of groups that are mapped to users.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListGroupsRequest", + "documentation":"

The maximum number of returned groups that are mapped to users.

", "location":"querystring", "locationName":"maxResults" } @@ -3055,8 +4651,14 @@ "ListGroupsResponse":{ "type":"structure", "members":{ - "nextToken":{"shape":"NextToken"}, - "items":{"shape":"GroupSummaryList"} + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token that you can use in the subsequent request to retrieve the next set of groups that are mapped to users.

" + }, + "items":{ + "shape":"GroupSummaryList", + "documentation":"

Summary information for list of groups that are mapped to users.

" + } } }, "ListIndicesRequest":{ @@ -3065,16 +4667,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application connected to the index.

", "location":"uri", "locationName":"applicationId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business indices.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListIndices", + "documentation":"

The maximum number of indices to return.

", "location":"querystring", "locationName":"maxResults" } @@ -3083,40 +4688,50 @@ "ListIndicesResponse":{ "type":"structure", "members":{ - "nextToken":{"shape":"NextToken"}, - "indices":{"shape":"Indices"} + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token that you can use in the subsequent request to retrieve the next set of indexes.

" + }, + "indices":{ + "shape":"Indices", + "documentation":"

An array of information on the items in one or more indexes.

" + } } }, "ListMessagesRequest":{ "type":"structure", "required":[ "conversationId", - "applicationId", - "userId" + "applicationId" ], "members":{ "conversationId":{ "shape":"ConversationId", + "documentation":"

The identifier of the Amazon Q Business web experience conversation.

", "location":"uri", "locationName":"conversationId" }, "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier for the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"UserId", + "documentation":"

The identifier of the user involved in the Amazon Q Business web experience conversation.

", "location":"querystring", "locationName":"userId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the number of retrievers returned exceeds maxResults, Amazon Q Business returns a next token as a pagination token to retrieve the next set of messages.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListMessages", + "documentation":"

The maximum number of messages to return.

", "location":"querystring", "locationName":"maxResults" } @@ -3125,8 +4740,14 @@ "ListMessagesResponse":{ "type":"structure", "members":{ - "messages":{"shape":"Messages"}, - "nextToken":{"shape":"NextToken"} + "messages":{ + "shape":"Messages", + "documentation":"

An array of information on one or more messages.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token, which you can use in a later request to list the next set of messages.

" + } } }, "ListPluginsRequest":{ @@ -3135,16 +4756,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application the plugin is attached to.

", "location":"uri", "locationName":"applicationId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of plugins.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListPlugins", + "documentation":"

The maximum number of documents to return.

", "location":"querystring", "locationName":"maxResults" } @@ -3153,8 +4777,14 @@ "ListPluginsResponse":{ "type":"structure", "members":{ - "nextToken":{"shape":"NextToken"}, - "plugins":{"shape":"Plugins"} + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of plugins.

" + }, + "plugins":{ + "shape":"Plugins", + "documentation":"

Information about a configured plugin.

" + } } }, "ListRetrieversRequest":{ @@ -3163,16 +4793,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application using the retriever.

", "location":"uri", "locationName":"applicationId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the number of retrievers returned exceeds maxResults, Amazon Q Business returns a next token as a pagination token to retrieve the next set of retrievers.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListRetrieversRequest", + "documentation":"

The maximum number of retrievers returned.

", "location":"querystring", "locationName":"maxResults" } @@ -3181,8 +4814,14 @@ "ListRetrieversResponse":{ "type":"structure", "members":{ - "retrievers":{"shape":"Retrievers"}, - "nextToken":{"shape":"NextToken"} + "retrievers":{ + "shape":"Retrievers", + "documentation":"

An array of summary information for one or more retrievers.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token, which you can use in a later request to list the next set of retrievers.

" + } } }, "ListTagsForResourceRequest":{ @@ -3191,6 +4830,7 @@ "members":{ "resourceARN":{ "shape":"AmazonResourceName", + "documentation":"

The Amazon Resource Name (ARN) of the Amazon Q Business application or data source to get a list of tags for.

", "location":"uri", "locationName":"resourceARN" } @@ -3199,7 +4839,10 @@ "ListTagsForResourceResponse":{ "type":"structure", "members":{ - "tags":{"shape":"Tags"} + "tags":{ + "shape":"Tags", + "documentation":"

A list of tags associated with the Amazon Q Business application or data source.

" + } } }, "ListWebExperiencesRequest":{ @@ -3208,16 +4851,19 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application linked to the listed web experiences.

", "location":"uri", "locationName":"applicationId" }, "nextToken":{ "shape":"NextToken", + "documentation":"

If the maxResults response was incomplete because there is more data to retrieve, Amazon Q Business returns a pagination token in the response. You can use this pagination token to retrieve the next set of Amazon Q Business conversations.

", "location":"querystring", "locationName":"nextToken" }, "maxResults":{ "shape":"MaxResultsIntegerForListWebExperiencesRequest", + "documentation":"

The maximum number of Amazon Q Business Web Experiences to return.

", "location":"querystring", "locationName":"maxResults" } @@ -3226,8 +4872,14 @@ "ListWebExperiencesResponse":{ "type":"structure", "members":{ - "webExperiences":{"shape":"WebExperiences"}, - "nextToken":{"shape":"NextToken"} + "webExperiences":{ + "shape":"WebExperiences", + "documentation":"

An array of summary information for one or more Amazon Q Business experiences.

" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

If the response is truncated, Amazon Q Business returns this token, which you can use in a later request to list the next set of messages.

" + } } }, "Long":{ @@ -3310,9 +4962,16 @@ "type":"structure", "required":["groupName"], "members":{ - "groupName":{"shape":"GroupName"}, - "type":{"shape":"MembershipType"} - } + "groupName":{ + "shape":"GroupName", + "documentation":"

The name of the sub group.

" + }, + "type":{ + "shape":"MembershipType", + "documentation":"

The type of the sub group.

" + } + }, + "documentation":"

The sub groups that belong to a group.

" }, "MemberGroups":{ "type":"list", @@ -3331,9 +4990,16 @@ "type":"structure", "required":["userId"], "members":{ - "userId":{"shape":"DataSourceUserId"}, - "type":{"shape":"MembershipType"} - } + "userId":{ + "shape":"DataSourceUserId", + "documentation":"

The identifier of the user you want to map to a group.

" + }, + "type":{ + "shape":"MembershipType", + "documentation":"

The type of the user.

" + } + }, + "documentation":"

The users that belong to a group.

" }, "MemberUsers":{ "type":"list", @@ -3351,15 +5017,34 @@ "Message":{ "type":"structure", "members":{ - "messageId":{"shape":"String"}, - "body":{"shape":"MessageBody"}, - "time":{"shape":"Timestamp"}, - "type":{"shape":"MessageType"}, - "attachments":{"shape":"AttachmentsOutput"}, - "sourceAttribution":{"shape":"SourceAttributions"}, + "messageId":{ + "shape":"String", + "documentation":"

The identifier of the Amazon Q Business web experience message.

" + }, + "body":{ + "shape":"MessageBody", + "documentation":"

The content of the Amazon Q Business web experience message.

" + }, + "time":{ + "shape":"Timestamp", + "documentation":"

The timestamp of the first Amazon Q Business web experience message.

" + }, + "type":{ + "shape":"MessageType", + "documentation":"

The type of Amazon Q Business message, whether HUMAN or AI generated.

" + }, + "attachments":{ + "shape":"AttachmentsOutput", + "documentation":"

A file directly uploaded into an Amazon Q Business web experience chat.

" + }, + "sourceAttribution":{ + "shape":"SourceAttributions", + "documentation":"

The source documents used to generate Amazon Q Business web experience message.

" + }, "actionReview":{"shape":"ActionReview"}, "actionExecution":{"shape":"ActionExecution"} - } + }, + "documentation":"

A message in an Amazon Q Business web experience.

" }, "MessageBody":{ "type":"string", @@ -3400,11 +5085,24 @@ "submittedAt" ], "members":{ - "usefulness":{"shape":"MessageUsefulness"}, - "reason":{"shape":"MessageUsefulnessReason"}, - "comment":{"shape":"MessageUsefulnessComment"}, - "submittedAt":{"shape":"Timestamp"} - } + "usefulness":{ + "shape":"MessageUsefulness", + "documentation":"

The usefulness value assigned by an end user to a message.

" + }, + "reason":{ + "shape":"MessageUsefulnessReason", + "documentation":"

The reason for a usefulness rating.

" + }, + "comment":{ + "shape":"MessageUsefulnessComment", + "documentation":"

A comment given by an end user on the usefulness of an AI-generated chat message.

" + }, + "submittedAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the feedback was submitted.

" + } + }, + "documentation":"

End user feedback on an AI-generated web experience chat message usefulness.

" }, "MessageUsefulnessReason":{ "type":"string", @@ -3416,13 +5114,44 @@ "FACTUALLY_CORRECT", "COMPLETE", "RELEVANT_SOURCES", - "HELPFUL" + "HELPFUL", + "NOT_BASED_ON_DOCUMENTS", + "NOT_COMPLETE", + "NOT_CONCISE", + "OTHER" ] }, "Messages":{ "type":"list", "member":{"shape":"Message"} }, + "MetadataEvent":{ + "type":"structure", + "members":{ + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the conversation with which the generated metadata is associated.

" + }, + "userMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an Amazon Q Business end user text input message within the conversation.

" + }, + "systemMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an Amazon Q Business AI generated message within the conversation.

" + }, + "sourceAttributions":{ + "shape":"SourceAttributions", + "documentation":"

The source documents used to generate the conversation response.

" + }, + "finalTextMessage":{ + "shape":"String", + "documentation":"

The final text output message generated by the system.

" + } + }, + "documentation":"

A metadata event for a AI-generated text output message in a Amazon Q Business conversation, containing associated metadata generated.

", + "event":true + }, "MetricValue":{ "type":"string", "pattern":"(([1-9][0-9]*)|0)" @@ -3431,14 +5160,50 @@ "type":"structure", "required":["indexId"], "members":{ - "indexId":{"shape":"IndexId"} - } + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier for the Amazon Q Business index.

" + }, + "boostingOverride":{ + "shape":"DocumentAttributeBoostingOverrideMap", + "documentation":"

Overrides the default boosts applied by Amazon Q Business to supported document attribute data types.

" + } + }, + "documentation":"

Configuration information for an Amazon Q Business index.

" }, "NextToken":{ "type":"string", "max":800, "min":1 }, + "NoAuthConfiguration":{ + "type":"structure", + "members":{ + }, + "documentation":"

Information about invoking a custom plugin without any authentication or authorization requirement.

" + }, + "NumberAttributeBoostingConfiguration":{ + "type":"structure", + "required":["boostingLevel"], + "members":{ + "boostingLevel":{ + "shape":"DocumentAttributeBoostingLevel", + "documentation":"

Specifies the duration, in seconds, of a boost applies to a NUMBER type document attribute.

" + }, + "boostingType":{ + "shape":"NumberAttributeBoostingType", + "documentation":"

Specifies how much a document attribute is boosted.

" + } + }, + "documentation":"

Provides information on boosting NUMBER type document attributes.

For more information on how boosting document attributes work in Amazon Q Business, see Boosting using document attributes.

" + }, + "NumberAttributeBoostingType":{ + "type":"string", + "enum":[ + "PRIORITIZE_LARGER_VALUES", + "PRIORITIZE_SMALLER_VALUES" + ] + }, "OAuth2ClientCredentialConfiguration":{ "type":"structure", "required":[ @@ -3446,21 +5211,58 @@ "roleArn" ], "members":{ - "secretArn":{"shape":"SecretArn"}, - "roleArn":{"shape":"RoleArn"} - } + "secretArn":{ + "shape":"SecretArn", + "documentation":"

The ARN of the Secrets Manager secret that stores the OAuth 2.0 credentials/token used for plugin configuration.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The ARN of an IAM role used by Amazon Q Business to access the OAuth 2.0 authentication credentials stored in a Secrets Manager secret.

" + } + }, + "documentation":"

Information about the OAuth 2.0 authentication credential/token used to configure a plugin.

" + }, + "Payload":{ + "type":"string", + "sensitive":true }, "Plugin":{ "type":"structure", "members":{ - "pluginId":{"shape":"PluginId"}, - "displayName":{"shape":"PluginName"}, - "type":{"shape":"PluginType"}, - "serverUrl":{"shape":"Url"}, - "state":{"shape":"PluginState"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"} - } + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin.

" + }, + "displayName":{ + "shape":"PluginName", + "documentation":"

The name of the plugin.

" + }, + "type":{ + "shape":"PluginType", + "documentation":"

The type of the plugin.

" + }, + "serverUrl":{ + "shape":"Url", + "documentation":"

The plugin server URL used for configuration.

" + }, + "state":{ + "shape":"PluginState", + "documentation":"

The current status of the plugin.

" + }, + "buildStatus":{ + "shape":"PluginBuildStatus", + "documentation":"

The status of the plugin.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the plugin was created.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the plugin was last updated.

" + } + }, + "documentation":"

Information about an Amazon Q Business plugin and its configuration.

" }, "PluginArn":{ "type":"string", @@ -3471,11 +5273,50 @@ "PluginAuthConfiguration":{ "type":"structure", "members":{ - "basicAuthConfiguration":{"shape":"BasicAuthConfiguration"}, - "oAuth2ClientCredentialConfiguration":{"shape":"OAuth2ClientCredentialConfiguration"} + "basicAuthConfiguration":{ + "shape":"BasicAuthConfiguration", + "documentation":"

Information about the basic authentication credentials used to configure a plugin.

" + }, + "oAuth2ClientCredentialConfiguration":{ + "shape":"OAuth2ClientCredentialConfiguration", + "documentation":"

Information about the OAuth 2.0 authentication credential/token used to configure a plugin.

" + }, + "noAuthConfiguration":{ + "shape":"NoAuthConfiguration", + "documentation":"

Information about invoking a custom plugin without any authentication.

" + } }, + "documentation":"

Authentication configuration information for an Amazon Q Business plugin.

", "union":true }, + "PluginBuildStatus":{ + "type":"string", + "enum":[ + "READY", + "CREATE_IN_PROGRESS", + "CREATE_FAILED", + "UPDATE_IN_PROGRESS", + "UPDATE_FAILED", + "DELETE_IN_PROGRESS", + "DELETE_FAILED" + ] + }, + "PluginConfiguration":{ + "type":"structure", + "required":["pluginId"], + "members":{ + "pluginId":{ + "shape":"PluginId", + "documentation":"

The identifier of the plugin you want to use.

" + } + }, + "documentation":"

Configuration information required to invoke chat in PLUGIN_MODE.

For more information, see Admin controls and guardrails, Plugins, and Conversation settings.

" + }, + "PluginDescription":{ + "type":"string", + "max":200, + "min":1 + }, "PluginId":{ "type":"string", "max":36, @@ -3501,7 +5342,8 @@ "SERVICE_NOW", "SALESFORCE", "JIRA", - "ZENDESK" + "ZENDESK", + "CUSTOM" ] }, "Plugins":{ @@ -3511,28 +5353,55 @@ "Principal":{ "type":"structure", "members":{ - "user":{"shape":"PrincipalUser"}, - "group":{"shape":"PrincipalGroup"} + "user":{ + "shape":"PrincipalUser", + "documentation":"

The user associated with the principal.

" + }, + "group":{ + "shape":"PrincipalGroup", + "documentation":"

The group associated with the principal.

" + } }, + "documentation":"

Provides user and group information used for filtering documents to use for generating Amazon Q Business conversation responses.

", "union":true }, "PrincipalGroup":{ "type":"structure", "required":["access"], "members":{ - "name":{"shape":"GroupName"}, - "access":{"shape":"ReadAccessType"}, - "membershipType":{"shape":"MembershipType"} - } + "name":{ + "shape":"GroupName", + "documentation":"

The name of the group.

" + }, + "access":{ + "shape":"ReadAccessType", + "documentation":"

Provides information about whether to allow or deny access to the principal.

" + }, + "membershipType":{ + "shape":"MembershipType", + "documentation":"

The type of group.

" + } + }, + "documentation":"

Provides information about a group associated with the principal.

" }, "PrincipalUser":{ "type":"structure", "required":["access"], "members":{ - "id":{"shape":"UserId"}, - "access":{"shape":"ReadAccessType"}, - "membershipType":{"shape":"MembershipType"} - } + "id":{ + "shape":"UserId", + "documentation":"

The identifier of the user.

" + }, + "access":{ + "shape":"ReadAccessType", + "documentation":"

Provides information about whether to allow or deny access to the principal.

" + }, + "membershipType":{ + "shape":"MembershipType", + "documentation":"

The type of group.

" + } + }, + "documentation":"

Provides information about a user associated with a principal.

" }, "Principals":{ "type":"list", @@ -3542,33 +5411,42 @@ "type":"structure", "required":[ "applicationId", - "userId", "conversationId", "messageId" ], "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application associated with the feedback.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"UserId", + "documentation":"

The identifier of the user giving the feedback.

", "location":"querystring", "locationName":"userId" }, "conversationId":{ "shape":"ConversationId", + "documentation":"

The identifier of the conversation the feedback is attached to.

", "location":"uri", "locationName":"conversationId" }, "messageId":{ "shape":"SystemMessageId", + "documentation":"

The identifier of the chat message that the feedback was given for.

", "location":"uri", "locationName":"messageId" }, - "messageCopiedAt":{"shape":"Timestamp"}, - "messageUsefulness":{"shape":"MessageUsefulnessFeedback"} + "messageCopiedAt":{ + "shape":"Timestamp", + "documentation":"

The timestamp for when the feedback was recorded.

" + }, + "messageUsefulness":{ + "shape":"MessageUsefulnessFeedback", + "documentation":"

The feedback usefulness value given by the user to the chat message.

" + } } }, "PutGroupRequest":{ @@ -3583,17 +5461,28 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application in which the user and group mapping belongs.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index in which you want to map users to their groups.

", "location":"uri", "locationName":"indexId" }, - "groupName":{"shape":"GroupName"}, - "dataSourceId":{"shape":"DataSourceId"}, - "type":{"shape":"MembershipType"}, + "groupName":{ + "shape":"GroupName", + "documentation":"

The list that contains your users or sub groups that belong the same group. For example, the group \"Company\" includes the user \"CEO\" and the sub groups \"Research\", \"Engineering\", and \"Sales and Marketing\".

If you have more than 1000 users and/or sub groups for a single group, you need to provide the path to the S3 file that lists your users and sub groups for a group. Your sub groups can contain more than 1000 users, but the list of sub groups that belong to a group (and/or users) must be no more than 1000.

" + }, + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the data source for which you want to map users to their groups. This is useful if a group is tied to multiple data sources, but you only want the group to access documents of a certain data source. For example, the groups \"Research\", \"Engineering\", and \"Sales and Marketing\" are all tied to the company's documents stored in the data sources Confluence and Salesforce. However, \"Sales and Marketing\" team only needs access to customer-related documents stored in Salesforce.

" + }, + "type":{ + "shape":"MembershipType", + "documentation":"

The type of the group.

" + }, "groupMembers":{"shape":"GroupMembers"} } }, @@ -3602,6 +5491,24 @@ "members":{ } }, + "QAppsConfiguration":{ + "type":"structure", + "required":["qAppsControlMode"], + "members":{ + "qAppsControlMode":{ + "shape":"QAppsControlMode", + "documentation":"

Status information about whether end users can create and use Amazon Q Apps in the web experience.

" + } + }, + "documentation":"

Configuration information about Amazon Q Apps. (preview feature)

" + }, + "QAppsControlMode":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, "ReadAccessType":{ "type":"string", "enum":[ @@ -3617,10 +5524,20 @@ "resourceType" ], "members":{ - "message":{"shape":"ErrorMessage"}, - "resourceId":{"shape":"String"}, - "resourceType":{"shape":"String"} + "message":{ + "shape":"ErrorMessage", + "documentation":"

The message describing a ResourceNotFoundException.

" + }, + "resourceId":{ + "shape":"String", + "documentation":"

The identifier of the resource affected.

" + }, + "resourceType":{ + "shape":"String", + "documentation":"

The type of the resource affected.

" + } }, + "documentation":"

The resource you want to use doesn’t exist. Make sure you have provided the correct resource and try again.

", "error":{ "httpStatusCode":404, "senderFault":true @@ -3637,12 +5554,28 @@ "Retriever":{ "type":"structure", "members":{ - "applicationId":{"shape":"ApplicationId"}, - "retrieverId":{"shape":"RetrieverId"}, - "type":{"shape":"RetrieverType"}, - "status":{"shape":"RetrieverStatus"}, - "displayName":{"shape":"RetrieverName"} - } + "applicationId":{ + "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application using the retriever.

" + }, + "retrieverId":{ + "shape":"RetrieverId", + "documentation":"

The identifier of the retriever used by your Amazon Q Business application.

" + }, + "type":{ + "shape":"RetrieverType", + "documentation":"

The type of your retriever.

" + }, + "status":{ + "shape":"RetrieverStatus", + "documentation":"

The status of your retriever.

" + }, + "displayName":{ + "shape":"RetrieverName", + "documentation":"

The name of your retriever.

" + } + }, + "documentation":"

Summary information for the retriever used for your Amazon Q Business application.

" }, "RetrieverArn":{ "type":"string", @@ -3653,9 +5586,16 @@ "RetrieverConfiguration":{ "type":"structure", "members":{ - "nativeIndexConfiguration":{"shape":"NativeIndexConfiguration"}, - "kendraIndexConfiguration":{"shape":"KendraIndexConfiguration"} + "nativeIndexConfiguration":{ + "shape":"NativeIndexConfiguration", + "documentation":"

Provides information on how a Amazon Q Business index used as a retriever for your Amazon Q Business application is configured.

" + }, + "kendraIndexConfiguration":{ + "shape":"KendraIndexConfiguration", + "documentation":"

Provides information on how the Amazon Kendra index used as a retriever for your Amazon Q Business application is configured.

" + } }, + "documentation":"

Provides information on how the retriever used for your Amazon Q Business application is configured.

", "union":true }, "RetrieverId":{ @@ -3697,19 +5637,37 @@ }, "Rule":{ "type":"structure", + "required":["ruleType"], "members":{ - "includedUsersAndGroups":{"shape":"UsersAndGroups"}, - "excludedUsersAndGroups":{"shape":"UsersAndGroups"}, - "ruleType":{"shape":"RuleType"}, - "ruleConfiguration":{"shape":"RuleConfiguration"} - } + "includedUsersAndGroups":{ + "shape":"UsersAndGroups", + "documentation":"

Users and groups to be included in a rule.

" + }, + "excludedUsersAndGroups":{ + "shape":"UsersAndGroups", + "documentation":"

Users and groups to be excluded from a rule.

" + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

The type of rule.

" + }, + "ruleConfiguration":{ + "shape":"RuleConfiguration", + "documentation":"

The configuration information for a rule.

" + } + }, + "documentation":"

Guardrail rules for an Amazon Q Business application. Amazon Q Business supports only one rule at a time.

" }, "RuleConfiguration":{ "type":"structure", "members":{ - "contentBlockerRule":{"shape":"ContentBlockerRule"}, + "contentBlockerRule":{ + "shape":"ContentBlockerRule", + "documentation":"

A rule for configuring how Amazon Q Business responds when it encounters a a blocked topic.

" + }, "contentRetrievalRule":{"shape":"ContentRetrievalRule"} }, + "documentation":"

Provides configuration information about a rule.

", "union":true }, "RuleType":{ @@ -3732,9 +5690,16 @@ "key" ], "members":{ - "bucket":{"shape":"S3BucketName"}, - "key":{"shape":"S3ObjectKey"} - } + "bucket":{ + "shape":"S3BucketName", + "documentation":"

The name of the S3 bucket that contains the file.

" + }, + "key":{ + "shape":"S3ObjectKey", + "documentation":"

The name of the file.

" + } + }, + "documentation":"

Information required for Amazon Q Business to find a specific file in an Amazon S3 bucket.

" }, "S3BucketName":{ "type":"string", @@ -3760,11 +5725,24 @@ "userIdAttribute" ], "members":{ - "metadataXML":{"shape":"SamlMetadataXML"}, - "roleArn":{"shape":"RoleArn"}, - "userIdAttribute":{"shape":"SamlAttribute"}, - "userGroupAttribute":{"shape":"SamlAttribute"} - } + "metadataXML":{ + "shape":"SamlMetadataXML", + "documentation":"

The metadata XML that your IdP generated.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role assumed by users when they authenticate into their Amazon Q Business web experience, containing the relevant Amazon Q Business permissions for conversing with Amazon Q Business.

" + }, + "userIdAttribute":{ + "shape":"SamlAttribute", + "documentation":"

The user attribute name in your IdP that maps to the user email.

" + }, + "userGroupAttribute":{ + "shape":"SamlAttribute", + "documentation":"

The group attribute name in your IdP that maps to user groups.

" + } + }, + "documentation":"

Provides the SAML 2.0 compliant identity provider (IdP) configuration information Amazon Q Business needs to deploy a Amazon Q Business web experience.

" }, "SamlMetadataXML":{ "type":"string", @@ -3798,26 +5776,66 @@ "resourceType" ], "members":{ - "message":{"shape":"ErrorMessage"}, - "resourceId":{"shape":"String"}, - "resourceType":{"shape":"String"} + "message":{ + "shape":"ErrorMessage", + "documentation":"

The message describing a ServiceQuotaExceededException.

" + }, + "resourceId":{ + "shape":"String", + "documentation":"

The identifier of the resource affected.

" + }, + "resourceType":{ + "shape":"String", + "documentation":"

The type of the resource affected.

" + } }, + "documentation":"

You have exceeded the set limits for your Amazon Q Business service.

", "error":{ "httpStatusCode":402, "senderFault":true }, "exception":true }, + "SnippetExcerpt":{ + "type":"structure", + "members":{ + "text":{ + "shape":"SnippetExcerptText", + "documentation":"

The relevant text excerpt from a source that was used to generate a citation text segment in an Amazon Q chat response.

" + } + }, + "documentation":"

Contains the relevant text excerpt from a source that was used to generate a citation text segment in an Amazon Q Business chat response.

" + }, + "SnippetExcerptText":{"type":"string"}, "SourceAttribution":{ "type":"structure", "members":{ - "title":{"shape":"String"}, - "snippet":{"shape":"String"}, - "url":{"shape":"String"}, - "citationNumber":{"shape":"Integer"}, - "updatedAt":{"shape":"Timestamp"}, - "textMessageSegments":{"shape":"TextSegmentList"} - } + "title":{ + "shape":"String", + "documentation":"

The title of the document which is the source for the Amazon Q Business generated response.

" + }, + "snippet":{ + "shape":"String", + "documentation":"

The content extract from the document on which the generated response is based.

" + }, + "url":{ + "shape":"String", + "documentation":"

The URL of the document which is the source for the Amazon Q Business generated response.

" + }, + "citationNumber":{ + "shape":"Integer", + "documentation":"

The number attached to a citation in an Amazon Q Business generated response.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was last updated.

" + }, + "textMessageSegments":{ + "shape":"TextSegmentList", + "documentation":"

A text extract from a source document that is used for source attribution.

" + } + }, + "documentation":"

The documents used to generate an Amazon Q Business web experience response.

" }, "SourceAttributions":{ "type":"list", @@ -3833,16 +5851,19 @@ "members":{ "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

", "location":"uri", "locationName":"dataSourceId" }, "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of Amazon Q Business application the data source is connected to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index used with the data source connector.

", "location":"uri", "locationName":"indexId" } @@ -3851,7 +5872,10 @@ "StartDataSourceSyncJobResponse":{ "type":"structure", "members":{ - "executionId":{"shape":"ExecutionId"} + "executionId":{ + "shape":"ExecutionId", + "documentation":"

The identifier for a particular synchronization job.

" + } } }, "Status":{ @@ -3871,16 +5895,19 @@ "members":{ "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

", "location":"uri", "locationName":"dataSourceId" }, "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application that the data source is connected to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index used with the Amazon Q Business data source connector.

", "location":"uri", "locationName":"indexId" } @@ -3896,6 +5923,48 @@ "max":2048, "min":1 }, + "StringAttributeBoostingConfiguration":{ + "type":"structure", + "required":["boostingLevel"], + "members":{ + "boostingLevel":{ + "shape":"DocumentAttributeBoostingLevel", + "documentation":"

Specifies how much a document attribute is boosted.

" + }, + "attributeValueBoosting":{ + "shape":"StringAttributeValueBoosting", + "documentation":"

Specifies specific values of a STRING type document attribute being boosted.

" + } + }, + "documentation":"

Provides information on boosting STRING type document attributes.

For STRING and STRING_LIST type document attributes to be used for boosting on the console and the API, they must be enabled for search using the DocumentAttributeConfiguration object of the UpdateIndex API. If you haven't enabled searching on these attributes, you can't boost attributes of these data types on either the console or the API.

For more information on how boosting document attributes work in Amazon Q Business, see Boosting using document attributes.

" + }, + "StringAttributeValueBoosting":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"StringAttributeValueBoostingLevel"}, + "max":10, + "min":1 + }, + "StringAttributeValueBoostingLevel":{ + "type":"string", + "enum":[ + "LOW", + "MEDIUM", + "HIGH", + "VERY_HIGH" + ] + }, + "StringListAttributeBoostingConfiguration":{ + "type":"structure", + "required":["boostingLevel"], + "members":{ + "boostingLevel":{ + "shape":"DocumentAttributeBoostingLevel", + "documentation":"

Specifies how much a document attribute is boosted.

" + } + }, + "documentation":"

Provides information on boosting STRING_LIST type document attributes.

For STRING and STRING_LIST type document attributes to be used for boosting on the console and the API, they must be enabled for search using the DocumentAttributeConfiguration object of the UpdateIndex API. If you haven't enabled searching on these attributes, you can't boost attributes of these data types on either the console or the API.

For more information on how boosting document attributes work in Amazon Q Business, see Boosting using document attributes.

" + }, "SubnetId":{ "type":"string", "max":200, @@ -3931,9 +6000,16 @@ "value" ], "members":{ - "key":{"shape":"TagKey"}, - "value":{"shape":"TagValue"} - } + "key":{ + "shape":"TagKey", + "documentation":"

The key for the tag. Keys are not case sensitive and must be unique for the Amazon Q Business application or data source.

" + }, + "value":{ + "shape":"TagValue", + "documentation":"

The value associated with the tag. The value may be an empty string but it can't be null.

" + } + }, + "documentation":"

A list of key/value pairs that identify an index, FAQ, or data source. Tag keys and values can consist of Unicode letters, digits, white space, and any of the following symbols: _ . : / = + - @.

" }, "TagKey":{ "type":"string", @@ -3955,10 +6031,14 @@ "members":{ "resourceARN":{ "shape":"AmazonResourceName", + "documentation":"

The Amazon Resource Name (ARN) of the Amazon Q Business application or data source to tag.

", "location":"uri", "locationName":"resourceARN" }, - "tags":{"shape":"Tags"} + "tags":{ + "shape":"Tags", + "documentation":"

A list of tag keys to add to the Amazon Q Business application or data source. If a tag already exists, the existing value is replaced with the new value.

" + } } }, "TagResourceResponse":{ @@ -3980,16 +6060,69 @@ "TextDocumentStatistics":{ "type":"structure", "members":{ - "indexedTextBytes":{"shape":"IndexedTextBytes"}, - "indexedTextDocumentCount":{"shape":"IndexedTextDocument"} - } + "indexedTextBytes":{ + "shape":"IndexedTextBytes", + "documentation":"

The total size, in bytes, of the indexed documents.

" + }, + "indexedTextDocumentCount":{ + "shape":"IndexedTextDocument", + "documentation":"

The number of text documents indexed.

" + } + }, + "documentation":"

Provides information about text documents in an index.

" + }, + "TextInputEvent":{ + "type":"structure", + "required":["userMessage"], + "members":{ + "userMessage":{ + "shape":"UserMessage", + "documentation":"

A user message in a text message input event.

" + } + }, + "documentation":"

An input event for a end user message in an Amazon Q Business web experience.

", + "event":true + }, + "TextOutputEvent":{ + "type":"structure", + "members":{ + "conversationId":{ + "shape":"ConversationId", + "documentation":"

The identifier of the conversation with which the text output event is associated.

" + }, + "userMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an end user message in a TextOutputEvent.

" + }, + "systemMessageId":{ + "shape":"MessageId", + "documentation":"

The identifier of an AI-generated message in a TextOutputEvent.

" + }, + "systemMessage":{ + "shape":"String", + "documentation":"

An AI-generated message in a TextOutputEvent.

" + } + }, + "documentation":"

An output event for an AI-generated response in an Amazon Q Business web experience.

", + "event":true }, "TextSegment":{ "type":"structure", "members":{ - "beginOffset":{"shape":"Integer"}, - "endOffset":{"shape":"Integer"} - } + "beginOffset":{ + "shape":"Integer", + "documentation":"

The zero-based location in the response string where the source attribution starts.

" + }, + "endOffset":{ + "shape":"Integer", + "documentation":"

The zero-based location in the response string where the source attribution ends.

" + }, + "snippetExcerpt":{ + "shape":"SnippetExcerpt", + "documentation":"

The relevant text excerpt from a source that was used to generate a citation text segment in an Amazon Q Business chat response.

" + } + }, + "documentation":"

Provides information about a text extract in a chat response that can be attributed to a source document.

" }, "TextSegmentList":{ "type":"list", @@ -4001,6 +6134,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, + "documentation":"

The request was denied due to throttling. Reduce the number of requests and try again.

", "error":{ "httpStatusCode":429, "senderFault":true @@ -4015,12 +6149,29 @@ }, "TopicConfiguration":{ "type":"structure", + "required":[ + "name", + "rules" + ], "members":{ - "name":{"shape":"TopicConfigurationName"}, - "description":{"shape":"TopicDescription"}, - "exampleChatMessages":{"shape":"ExampleChatMessages"}, - "rules":{"shape":"Rules"} - } + "name":{ + "shape":"TopicConfigurationName", + "documentation":"

A name for your topic control configuration.

" + }, + "description":{ + "shape":"TopicDescription", + "documentation":"

A description for your topic control configuration. Use this to outline how the large language model (LLM) should use this topic control configuration.

" + }, + "exampleChatMessages":{ + "shape":"ExampleChatMessages", + "documentation":"

A list of example phrases that you expect the end user to use in relation to the topic.

" + }, + "rules":{ + "shape":"Rules", + "documentation":"

Rules defined for a topic configuration.

" + } + }, + "documentation":"

The topic specific controls configured for an Amazon Q Business application.

" }, "TopicConfigurationName":{ "type":"string", @@ -4049,11 +6200,13 @@ "members":{ "resourceARN":{ "shape":"AmazonResourceName", + "documentation":"

The Amazon Resource Name (ARN) of the Amazon Q Business application, or data source to remove the tag from.

", "location":"uri", "locationName":"resourceARN" }, "tagKeys":{ "shape":"TagKeys", + "documentation":"

A list of tag keys to remove from the Amazon Q Business application or data source. If a tag key does not exist on the resource, it is ignored.

", "location":"querystring", "locationName":"tagKeys" } @@ -4070,13 +6223,34 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, - "displayName":{"shape":"ApplicationName"}, - "description":{"shape":"Description"}, - "roleArn":{"shape":"RoleArn"}, - "attachmentsConfiguration":{"shape":"AttachmentsConfiguration"} + "identityCenterInstanceArn":{ + "shape":"InstanceArn", + "documentation":"

The Amazon Resource Name (ARN) of the IAM Identity Center instance you are either creating for—or connecting to—your Amazon Q Business application.

" + }, + "displayName":{ + "shape":"ApplicationName", + "documentation":"

A name for the Amazon Q Business application.

" + }, + "description":{ + "shape":"Description", + "documentation":"

A description for the Amazon Q Business application.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

An Amazon Web Services Identity and Access Management (IAM) role that gives Amazon Q Business permission to access Amazon CloudWatch logs and metrics.

" + }, + "attachmentsConfiguration":{ + "shape":"AttachmentsConfiguration", + "documentation":"

An option to allow end users to upload files directly during chat.

" + }, + "qAppsConfiguration":{ + "shape":"QAppsConfiguration", + "documentation":"

An option to allow end users to create and use Amazon Q Apps in the web experience.

" + } } }, "UpdateApplicationResponse":{ @@ -4090,17 +6264,35 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application for which the chat controls are configured.

", "location":"uri", "locationName":"applicationId" }, "clientToken":{ "shape":"ClientToken", + "documentation":"

A token that you provide to identify the request to update a Amazon Q Business application chat configuration.

", "idempotencyToken":true }, - "responseScope":{"shape":"ResponseScope"}, - "blockedPhrasesConfigurationUpdate":{"shape":"BlockedPhrasesConfigurationUpdate"}, - "topicConfigurationsToCreateOrUpdate":{"shape":"TopicConfigurations"}, - "topicConfigurationsToDelete":{"shape":"TopicConfigurations"} + "responseScope":{ + "shape":"ResponseScope", + "documentation":"

The response scope configured for your application. This determines whether your application uses its retrieval augmented generation (RAG) system to generate answers only from your enterprise data, or also uses the large language models (LLM) knowledge to respons to end user questions in chat.

" + }, + "blockedPhrasesConfigurationUpdate":{ + "shape":"BlockedPhrasesConfigurationUpdate", + "documentation":"

The phrases blocked from chat by your chat control configuration.

" + }, + "topicConfigurationsToCreateOrUpdate":{ + "shape":"TopicConfigurations", + "documentation":"

The configured topic specific chat controls you want to update.

" + }, + "topicConfigurationsToDelete":{ + "shape":"TopicConfigurations", + "documentation":"

The configured topic specific chat controls you want to delete.

" + }, + "creatorModeConfiguration":{ + "shape":"CreatorModeConfiguration", + "documentation":"

The configuration details for CREATOR_MODE.

" + } } }, "UpdateChatControlsConfigurationResponse":{ @@ -4118,25 +6310,40 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application the data source is attached to.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the index attached to the data source connector.

", "location":"uri", "locationName":"indexId" }, "dataSourceId":{ "shape":"DataSourceId", + "documentation":"

The identifier of the data source connector.

", "location":"uri", "locationName":"dataSourceId" }, - "displayName":{"shape":"DataSourceName"}, + "displayName":{ + "shape":"DataSourceName", + "documentation":"

A name of the data source connector.

" + }, "configuration":{"shape":"DataSourceConfiguration"}, "vpcConfiguration":{"shape":"DataSourceVpcConfiguration"}, - "description":{"shape":"Description"}, - "syncSchedule":{"shape":"SyncSchedule"}, - "roleArn":{"shape":"RoleArn"}, + "description":{ + "shape":"Description", + "documentation":"

The description of the data source connector.

" + }, + "syncSchedule":{ + "shape":"SyncSchedule", + "documentation":"

The chosen update frequency for your data source.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role with permission to access the data source and required resources.

" + }, "documentEnrichmentConfiguration":{"shape":"DocumentEnrichmentConfiguration"} } }, @@ -4154,18 +6361,32 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application connected to the index.

", "location":"uri", "locationName":"applicationId" }, "indexId":{ "shape":"IndexId", + "documentation":"

The identifier of the Amazon Q Business index.

", "location":"uri", "locationName":"indexId" }, - "displayName":{"shape":"ApplicationName"}, - "description":{"shape":"Description"}, - "capacityConfiguration":{"shape":"IndexCapacityConfiguration"}, - "documentAttributeConfigurations":{"shape":"DocumentAttributeConfigurations"} + "displayName":{ + "shape":"ApplicationName", + "documentation":"

The name of the Amazon Q Business index.

" + }, + "description":{ + "shape":"Description", + "documentation":"

The description of the Amazon Q Business index.

" + }, + "capacityConfiguration":{ + "shape":"IndexCapacityConfiguration", + "documentation":"

The storage capacity units you want to provision for your Amazon Q Business index. You can add and remove capacity to fit your usage needs.

" + }, + "documentAttributeConfigurations":{ + "shape":"DocumentAttributeConfigurations", + "documentation":"

Configuration information for document metadata or fields. Document metadata are fields or attributes associated with your documents. For example, the company department name associated with each document. For more information, see Understanding document attributes.

" + } } }, "UpdateIndexResponse":{ @@ -4182,18 +6403,36 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application the plugin is attached to.

", "location":"uri", "locationName":"applicationId" }, "pluginId":{ "shape":"PluginId", + "documentation":"

The identifier of the plugin.

", "location":"uri", "locationName":"pluginId" }, - "displayName":{"shape":"PluginName"}, - "state":{"shape":"PluginState"}, - "serverUrl":{"shape":"Url"}, - "authConfiguration":{"shape":"PluginAuthConfiguration"} + "displayName":{ + "shape":"PluginName", + "documentation":"

The name of the plugin.

" + }, + "state":{ + "shape":"PluginState", + "documentation":"

The status of the plugin.

" + }, + "serverUrl":{ + "shape":"Url", + "documentation":"

The source URL used for plugin configuration.

" + }, + "customPluginConfiguration":{ + "shape":"CustomPluginConfiguration", + "documentation":"

The configuration for a custom plugin.

" + }, + "authConfiguration":{ + "shape":"PluginAuthConfiguration", + "documentation":"

The authentication configuration the plugin is using.

" + } } }, "UpdatePluginResponse":{ @@ -4210,17 +6449,25 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of your Amazon Q Business application.

", "location":"uri", "locationName":"applicationId" }, "retrieverId":{ "shape":"RetrieverId", + "documentation":"

The identifier of your retriever.

", "location":"uri", "locationName":"retrieverId" }, "configuration":{"shape":"RetrieverConfiguration"}, - "displayName":{"shape":"RetrieverName"}, - "roleArn":{"shape":"RoleArn"} + "displayName":{ + "shape":"RetrieverName", + "documentation":"

The name of your retriever.

" + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of an IAM role with permission to access the retriever and required resources.

" + } } }, "UpdateRetrieverResponse":{ @@ -4237,24 +6484,41 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the application the user is attached to.

", "location":"uri", "locationName":"applicationId" }, "userId":{ "shape":"String", + "documentation":"

The email id attached to the user.

", "location":"uri", "locationName":"userId" }, - "userAliasesToUpdate":{"shape":"UserAliases"}, - "userAliasesToDelete":{"shape":"UserAliases"} + "userAliasesToUpdate":{ + "shape":"UserAliases", + "documentation":"

The user aliases attached to the user id that are to be updated.

" + }, + "userAliasesToDelete":{ + "shape":"UserAliases", + "documentation":"

The user aliases attached to the user id that are to be deleted.

" + } } }, "UpdateUserResponse":{ "type":"structure", "members":{ - "userAliasesAdded":{"shape":"UserAliases"}, - "userAliasesUpdated":{"shape":"UserAliases"}, - "userAliasesDeleted":{"shape":"UserAliases"} + "userAliasesAdded":{ + "shape":"UserAliases", + "documentation":"

The user aliases that have been to be added to a user id.

" + }, + "userAliasesUpdated":{ + "shape":"UserAliases", + "documentation":"

The user aliases attached to a user id that have been updated.

" + }, + "userAliasesDeleted":{ + "shape":"UserAliases", + "documentation":"

The user aliases that have been deleted from a user id.

" + } } }, "UpdateWebExperienceRequest":{ @@ -4266,19 +6530,42 @@ "members":{ "applicationId":{ "shape":"ApplicationId", + "documentation":"

The identifier of the Amazon Q Business application attached to the web experience.

", "location":"uri", "locationName":"applicationId" }, "webExperienceId":{ "shape":"WebExperienceId", + "documentation":"

The identifier of the Amazon Q Business web experience.

", "location":"uri", "locationName":"webExperienceId" }, - "authenticationConfiguration":{"shape":"WebExperienceAuthConfiguration"}, - "title":{"shape":"WebExperienceTitle"}, - "subtitle":{"shape":"WebExperienceSubtitle"}, - "welcomeMessage":{"shape":"WebExperienceWelcomeMessage"}, - "samplePromptsControlMode":{"shape":"WebExperienceSamplePromptsControlMode"} + "roleArn":{ + "shape":"RoleArn", + "documentation":"

The Amazon Resource Name (ARN) of the role with permission to access the Amazon Q Business web experience and required resources.

" + }, + "authenticationConfiguration":{ + "shape":"WebExperienceAuthConfiguration", + "documentation":"

The authentication configuration of the Amazon Q Business web experience.

", + "deprecated":true, + "deprecatedMessage":"Property associated with legacy SAML IdP flow. Deprecated in favor of using AWS IAM Identity Center for user management." + }, + "title":{ + "shape":"WebExperienceTitle", + "documentation":"

The title of the Amazon Q Business web experience.

" + }, + "subtitle":{ + "shape":"WebExperienceSubtitle", + "documentation":"

The subtitle of the Amazon Q Business web experience.

" + }, + "welcomeMessage":{ + "shape":"WebExperienceWelcomeMessage", + "documentation":"

A customized welcome message for an end user in an Amazon Q Business web experience.

" + }, + "samplePromptsControlMode":{ + "shape":"WebExperienceSamplePromptsControlMode", + "documentation":"

Determines whether sample prompts are enabled in the web experience for an end user.

" + } } }, "UpdateWebExperienceResponse":{ @@ -4296,10 +6583,20 @@ "type":"structure", "required":["userId"], "members":{ - "indexId":{"shape":"IndexId"}, - "dataSourceId":{"shape":"DataSourceId"}, - "userId":{"shape":"String"} - } + "indexId":{ + "shape":"IndexId", + "documentation":"

The identifier of the index that the user aliases are associated with.

" + }, + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

The identifier of the data source that the user aliases are associated with.

" + }, + "userId":{ + "shape":"String", + "documentation":"

The identifier of the user id associated with the user aliases.

" + } + }, + "documentation":"

Aliases attached to a user id within an Amazon Q Business application.

" }, "UserAliases":{ "type":"list", @@ -4327,9 +6624,16 @@ "UsersAndGroups":{ "type":"structure", "members":{ - "userIds":{"shape":"UserIds"}, - "userGroups":{"shape":"UserGroups"} - } + "userIds":{ + "shape":"UserIds", + "documentation":"

The user ids associated with a topic control rule.

" + }, + "userGroups":{ + "shape":"UserGroups", + "documentation":"

The user groups associated with a topic control rule.

" + } + }, + "documentation":"

Provides information about users and groups associated with a topic control rule.

" }, "ValidationException":{ "type":"structure", @@ -4338,10 +6642,20 @@ "reason" ], "members":{ - "message":{"shape":"ErrorMessage"}, - "reason":{"shape":"ValidationExceptionReason"}, - "fields":{"shape":"ValidationExceptionFields"} + "message":{ + "shape":"ErrorMessage", + "documentation":"

The message describing the ValidationException.

" + }, + "reason":{ + "shape":"ValidationExceptionReason", + "documentation":"

The reason for the ValidationException.

" + }, + "fields":{ + "shape":"ValidationExceptionFields", + "documentation":"

The input field(s) that failed validation.

" + } }, + "documentation":"

The input doesn't meet the constraints set by the Amazon Q Business service. Provide the correct input and try again.

", "error":{ "httpStatusCode":400, "senderFault":true @@ -4355,9 +6669,16 @@ "message" ], "members":{ - "name":{"shape":"String"}, - "message":{"shape":"String"} - } + "name":{ + "shape":"String", + "documentation":"

The field name where the invalid entry was detected.

" + }, + "message":{ + "shape":"String", + "documentation":"

A message about the validation exception.

" + } + }, + "documentation":"

The input failed to meet the constraints specified by Amazon Q Business in a specified field.

" }, "ValidationExceptionFields":{ "type":"list", @@ -4374,12 +6695,28 @@ "WebExperience":{ "type":"structure", "members":{ - "webExperienceId":{"shape":"WebExperienceId"}, - "createdAt":{"shape":"Timestamp"}, - "updatedAt":{"shape":"Timestamp"}, - "defaultEndpoint":{"shape":"Url"}, - "status":{"shape":"WebExperienceStatus"} - } + "webExperienceId":{ + "shape":"WebExperienceId", + "documentation":"

The identifier of your Amazon Q Business web experience.

" + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when the Amazon Q Business application was last updated.

" + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

The Unix timestamp when your Amazon Q Business web experience was updated.

" + }, + "defaultEndpoint":{ + "shape":"Url", + "documentation":"

The endpoint URLs for your Amazon Q Business web experience. The URLs are unique and fully hosted by Amazon Web Services.

" + }, + "status":{ + "shape":"WebExperienceStatus", + "documentation":"

The status of your Amazon Q Business web experience.

" + } + }, + "documentation":"

Provides information for an Amazon Q Business web experience.

" }, "WebExperienceArn":{ "type":"string", @@ -4392,6 +6729,7 @@ "members":{ "samlConfiguration":{"shape":"SamlConfiguration"} }, + "documentation":"

Provides the authorization configuration information needed to deploy a Amazon Q Business web experience to end users.

", "union":true }, "WebExperienceId":{ @@ -4438,5 +6776,6 @@ "type":"list", "member":{"shape":"WebExperience"} } - } + }, + "documentation":"

This is the Amazon Q Business API Reference. Amazon Q Business is a fully managed, generative-AI powered enterprise chat assistant that you can deploy within your organization. Amazon Q Business enhances employee productivity by supporting key tasks such as question-answering, knowledge discovery, writing email messages, summarizing text, drafting document outlines, and brainstorming ideas. Users ask questions of Amazon Q Business and get answers that are presented in a conversational manner. For an introduction to the service, see the Amazon Q Business User Guide .

For an overview of the Amazon Q Business APIs, see Overview of Amazon Q Business API operations.

For information about the IAM access control permissions you need to use this API, see IAM roles for Amazon Q Business in the Amazon Q Business User Guide.

You can use the following AWS SDKs to access Amazon Q Business APIs:

The following resources provide additional information about using the Amazon Q Business API:

" } From 511601bfeec63988a10d0bd97db73d380d370988 Mon Sep 17 00:00:00 2001 From: Austin Johnson Date: Mon, 8 Jul 2024 15:33:55 -0400 Subject: [PATCH 3/5] Update version & changelog --- CHANGELOG.md | 5 +++++ lambdas/qna_bot_qbusiness_lambdahook/template.yml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5cbede..6d11c38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.1.16] - 2024-03-07 +### Added +- Amazon Q Business Expert plugin now supports Identity Center authentication + ## [0.1.15] - 2024-03-07 ### Added - Amazon Bedrock LLM plugin now suports anthropic.claude-3-sonnet model, and deprecates anthropic.claude-v1 - PR #26 & PR #27. @@ -85,6 +89,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial release [Unreleased]: https://github.com/aws-samples/qnabot-on-aws-plugin-samples/compare/v0.1.14...develop +[0.1.16]: https://github.com/aws-samples/qnabot-on-aws-plugin-samples/releases/tag/v0.1.16 [0.1.15]: https://github.com/aws-samples/qnabot-on-aws-plugin-samples/releases/tag/v0.1.15 [0.1.14]: https://github.com/aws-samples/qnabot-on-aws-plugin-samples/releases/tag/v0.1.14 [0.1.13]: https://github.com/aws-samples/qnabot-on-aws-plugin-samples/releases/tag/v0.1.13 diff --git a/lambdas/qna_bot_qbusiness_lambdahook/template.yml b/lambdas/qna_bot_qbusiness_lambdahook/template.yml index 3f71849..4cc554d 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/template.yml +++ b/lambdas/qna_bot_qbusiness_lambdahook/template.yml @@ -1,7 +1,7 @@ AWSTemplateFormatVersion: "2010-09-09" Description: > Amazon Q (Business) Lambda Hook function for using with 'QnABot on AWS'. - Use with the 'no_hits' (CustomNoMatches) item to use Amazon Q when no good answers are found by other methods - v0.1.14 + Use with the 'no_hits' (CustomNoMatches) item to use Amazon Q when no good answers are found by other methods - v0.1.16 Parameters: From 63e5b7924c6e3b8f5d57e80e6e11e26d0a4cc4ed Mon Sep 17 00:00:00 2001 From: Austin Johnson Date: Wed, 10 Jul 2024 10:19:56 -0400 Subject: [PATCH 4/5] Fix some issues with the README --- lambdas/qna_bot_qbusiness_lambdahook/README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lambdas/qna_bot_qbusiness_lambdahook/README.md b/lambdas/qna_bot_qbusiness_lambdahook/README.md index 0c8ef40..d53479c 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/README.md +++ b/lambdas/qna_bot_qbusiness_lambdahook/README.md @@ -17,15 +17,16 @@ It's pretty cool. It's easy to deploy in your own AWS Account, and add to your o ### Prerequisites -1. A deployment of the Lex Web UI with login enabled is required for this stack. To learn more about deploying the Web UI see the [Github repo for the solution](https://github.com/aws-samples/aws-lex-web-ui). This Cognito should be integrated with the same identity provider as your Identity Center (in the below example we will use IAM Identity Center as the IDP). -2. The Cognito user pool created by the Web UI will need to be added as **Trusted token issuer** to Identity Center by doing the following steps +1. An existing deployment of a Q Business application. Please reference the AWS docs for creating a new [Q Business application](https://docs.aws.amazon.com/amazonq/latest/qbusiness-ug/create-application.html) +2. A deployment of the Lex Web UI with login enabled is required for this stack. To learn more about deploying the Web UI see the [Github repo for the solution](https://github.com/aws-samples/aws-lex-web-ui). This Cognito should be integrated with the same identity provider as your Identity Center (in the below example we will use IAM Identity Center as the IDP). +3. The Cognito user pool created by the Web UI will need to be added as **Trusted token issuer** to Identity Center by doing the following steps 1. Go to Identity Center and click on `Settings`, then `Create trusted token issuer` 2. The issuer URL will be `https://cognito-idp.[region].amazonaws.com/[cognito-pool-id]` and you will need to provide which attributes should map between the two. ![Issuer](../../images/token-issuer.PNG) -3. A custom application will need to be created in Identity Center to handle the connection between your Q Business application and your Cognito pool. Follow these steps to create the application. +4. A custom application will need to be created in Identity Center to handle the connection between your Q Business application and your Cognito pool. Follow these steps to create the application. 1. Go to Identity Center and click on `Applications` then `Add application` 2. Select `I have an application I want to set up` and `OAuth 2.0` on the next page for Selecting Application type, then hit `Next` - 3. For `Application URL`, provide the **Web experience URL** of your Q Business application. You can either opt to assign specific users/groups to this application or allow any Identity Center users/groups to access the application. Your Q Business subscriptions will still apply however so only users with a subscription can successfully chat with the application. Then hit `Next` + 3. For `Application URL`, provide the **Web experience URL** of your Q Business application (if you have a custom domain for your Q Business application, you would use the URL of that domain). You can either opt to assign specific users/groups to this application or allow any Identity Center users/groups to access the application. Your Q Business subscriptions will still apply however so only users with a subscription can successfully chat with the application. Then hit `Next` 4. Select the Trusted token issuer that was created in Step 2 of this guide, you will now need an aud claim so that the token issuer can identify the application. This aud claim is created when you deploy the Lex Web UI and can be found within the Coginto User pool. To find this value go to your Cognito user pool and select the `App integration` tab and scroll to the bottom. The aud claim is the **Client ID** value found under the App client list. Take this value and paste it into the aud claim field, then select `Next` ![Claim](../../images/aud-claim.PNG) 5. You will need to wait until after you deploy the CloudFormation stack to provide the role on the Specify application credentials page. For now, provide any existing IAM role in your environment and hit `Next`. @@ -41,7 +42,7 @@ Use AWS CloudFormation to deploy one or more of the sample plugin Lambdas in you 1. `Stack Name`: Name your stack, e.g. QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK. 2. `AmazonQAppId`: Existing Amazon Q Application ID (copy from AWS console) 3. `AmazonQRegion`: Amazon Q Region (us-east-1, or us-west-2) - 4. `DynamoDBTableName`: DynamoDB table that will be used to cache user credential for question answering with QBusiness. + 4. `DynamoDBTableName`: DynamoDB table that will be used to cache encrypted user credentials for question answering with QBusiness. 5. `IDCApplicationARN`: ARN of the Identity Center customer managed application created for QBusiness (see prerequisites for steps to create) 5. Launch the stack. 6. When your QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK Plugin CloudFormation stack status is CREATE_COMPLETE, choose the **Outputs** tab. Look for the output `QnAItemLambdaFunctionRoleArn` and modify your existing Identity Center application with this value by following these steps. @@ -61,9 +62,7 @@ Plugin | Launch Stack | Template URL QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK | [![Launch Stack](https://cdn.rawgit.com/buildkite/cloudformation-launch-stack-button-svg/master/launch-stack.svg)](https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/create/review?templateURL=https://s3.us-west-2.amazonaws.com/aws-ml-blog-us-west-2/artifacts/qnabot-on-aws-plugin-samples/qna_bot_qbusiness_lambdahook.yaml&stackName=QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK) | https://s3.us-west-2.amazonaws.com/aws-ml-blog-us-west-2/artifacts/qnabot-on-aws-plugin-samples/qna_bot_qbusiness_lambdahook.yaml ## After your Amazon Q Plugin stack is deployed -Configure QnAbot to prompt Amazon Q directly by configuring the AmazonQ LambdaHook function `QnAItemLambdaHookFunctionName` as a Lambda Hook for the QnABot [CustomNoMatches](https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/keyword-filters-and-custom-dont-know-answers.html) `no_hits` item. When QnABot cannot answer a question by any other means, it reverts to the `no_hits` item, which, when configured with this Lambda Hook function, will relay the question to Amazon Q. - -***When integrating Amazon Q in this way, you will (almost definately) want to use it instead of using the Kendra/LLM RAG approach, since Amazon Q offers an alternive approach - you are unlikely to need both. Use QnABot Content Designer Settings to remove any Kendra index specified in the setting: `ALT_SEARCH_KENDRA_INDEXES`*** +Configure QnAbot to prompt Amazon Q directly by configuring the AmazonQ LambdaHook function `QnAItemLambdaHookFunctionName` as a Lambda Hook for the QnABot [CustomNoMatches](https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/using-keyword-filters-for.html) `no_hits` item. When QnABot cannot answer a question by any other means, it reverts to the `no_hits` item, which, when configured with this Lambda Hook function, will relay the question to Amazon Q. When your QNABOTPLUGIN-QNA-BOT-QBUSINESS-LAMBDAHOOK Plugin CloudFormation stack status is CREATE_COMPLETE, choose the **Outputs** tab. Look for the outputs `QnAItemLambdaHookFunctionName` and `QnAItemLambdaHookArgs`. Use these values in the LambdaHook section of your no_hits item. You can change the value of "Prefix', or use "None" if you don't want to prefix the LLM answer. From 3d2df13cc017e27be19e18c5da078e5ed037feba Mon Sep 17 00:00:00 2001 From: rstrahan Date: Wed, 10 Jul 2024 19:48:36 +0000 Subject: [PATCH 5/5] v0.1.17 --- .../qna_bot_qbusiness_lambdahook/template.yml | 97 +++++++++---------- 1 file changed, 46 insertions(+), 51 deletions(-) diff --git a/lambdas/qna_bot_qbusiness_lambdahook/template.yml b/lambdas/qna_bot_qbusiness_lambdahook/template.yml index 4cc554d..4a40918 100644 --- a/lambdas/qna_bot_qbusiness_lambdahook/template.yml +++ b/lambdas/qna_bot_qbusiness_lambdahook/template.yml @@ -1,13 +1,12 @@ AWSTemplateFormatVersion: "2010-09-09" Description: > Amazon Q (Business) Lambda Hook function for using with 'QnABot on AWS'. - Use with the 'no_hits' (CustomNoMatches) item to use Amazon Q when no good answers are found by other methods - v0.1.16 + Use with the 'no_hits' (CustomNoMatches) item to use Amazon Q when no good answers are found by other methods - v0.1.17 Parameters: - AmazonQAppId: Type: String - AllowedPattern: '^[a-zA-Z0-9][a-zA-Z0-9-]{35}$' + AllowedPattern: "^[a-zA-Z0-9][a-zA-Z0-9-]{35}$" Description: Amazon Q Application ID IDCApplicationARN: @@ -21,7 +20,7 @@ Parameters: AmazonQRegion: Type: String Default: "us-east-1" - AllowedPattern: '^[a-z]{2}-[a-z]+-[0-9]+$' + AllowedPattern: "^[a-z]{2}-[a-z]+-[0-9]+$" Description: Amazon Q Region AmazonQEndpointUrl: @@ -30,35 +29,34 @@ Parameters: Description: (Optional) Amazon Q Endpoint (leave empty for default endpoint) Resources: - QManagedPolicy: Type: AWS::IAM::ManagedPolicy Properties: PolicyDocument: - Version: '2012-10-17' + Version: "2012-10-17" Statement: - - Sid: AllowQChat - Effect: Allow - Action: - - "qbusiness:ChatSync" - Resource: !Sub "arn:${AWS::Partition}:qbusiness:${AWS::Region}:${AWS::AccountId}:application/${AmazonQAppId}" - + - Sid: AllowQChat + Effect: Allow + Action: + - "qbusiness:ChatSync" + Resource: !Sub "arn:${AWS::Partition}:qbusiness:${AWS::Region}:${AWS::AccountId}:application/${AmazonQAppId}" + QServiceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - - Effect: Allow - Principal: - AWS: - - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root - Action: - - sts:AssumeRole - - sts:SetContext + - Effect: Allow + Principal: + AWS: + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root + Action: + - sts:AssumeRole + - sts:SetContext Path: / ManagedPolicyArns: - - !Ref QManagedPolicy + - !Ref QManagedPolicy QBusinessModelLayer: Type: "AWS::Lambda::LayerVersion" @@ -68,28 +66,28 @@ Resources: - python3.12 KMSKey: - Type: 'AWS::KMS::Key' + Type: "AWS::KMS::Key" Properties: - KeySpec: 'SYMMETRIC_DEFAULT' - KeyUsage: 'ENCRYPT_DECRYPT' + KeySpec: "SYMMETRIC_DEFAULT" + KeyUsage: "ENCRYPT_DECRYPT" KeyPolicy: - Version: '2012-10-17' + Version: "2012-10-17" Statement: - - Effect: Allow - Principal: - AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' - Action: 'kms:*' - Resource: '*' + - Effect: Allow + Principal: + AWS: !Sub "arn:aws:iam::${AWS::AccountId}:root" + Action: "kms:*" + Resource: "*" CredentialsTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - - AttributeName: "jti" - AttributeType: "S" + - AttributeName: "jti" + AttributeType: "S" KeySchema: - - AttributeName: "jti" - KeyType: "HASH" + - AttributeName: "jti" + KeyType: "HASH" BillingMode: PAY_PER_REQUEST SSESpecification: SSEEnabled: True @@ -102,7 +100,7 @@ Resources: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: - Version: '2012-10-17' + Version: "2012-10-17" Statement: - Effect: Allow Principal: @@ -132,27 +130,27 @@ Resources: Statement: - Effect: Allow Action: - - "dynamodb:PutItem" - - "dynamodb:GetItem" + - "dynamodb:PutItem" + - "dynamodb:GetItem" Resource: - - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDBTableName}" + - !Sub "arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${DynamoDBTableName}" PolicyName: DynamoDbPolicy - PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - - "kms:Decrypt" - - "kms:Encrypt" + - "kms:Decrypt" + - "kms:Encrypt" Resource: - - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${KMSKey}" + - !Sub "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/${KMSKey}" PolicyName: KmsPolicy - PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - - "sso-oauth:CreateTokenWithIAM" + - "sso-oauth:CreateTokenWithIAM" Resource: "*" PolicyName: OICDPolicy - PolicyDocument: @@ -160,21 +158,21 @@ Resources: Statement: - Effect: Allow Action: - - "sts:AssumeRole" - - "sts:SetContext" + - "sts:AssumeRole" + - "sts:SetContext" Resource: - - !GetAtt QServiceRole.Arn + - !GetAtt QServiceRole.Arn PolicyName: AllowAssumeQRole QnaItemLambdaHookFunction: Type: AWS::Lambda::Function Properties: - # LambdaHook name must start with 'QNA-' to match QnAbot invoke policy + # LambdaHook name must start with 'QNA-' to match QnAbot invoke policy FunctionName: !Sub "QNA-LAMBDAHOOK-${AWS::StackName}" Handler: lambdahook.lambda_handler - Role: !GetAtt 'LambdaFunctionRole.Arn' + Role: !GetAtt "LambdaFunctionRole.Arn" Runtime: python3.12 - Layers: + Layers: - !Ref QBusinessModelLayer Timeout: 60 MemorySize: 128 @@ -197,12 +195,10 @@ Resources: - id: W92 reason: No requirements to set reserved concurrencies. - Outputs: - QnAItemLambdaHookFunctionName: Description: QnA Item Lambda Hook Function Name (use with no_hits item for optional ask-Amazon-Q-Business fallback) - Value: !Ref 'QnaItemLambdaHookFunction' + Value: !Ref "QnaItemLambdaHookFunction" QnAItemLambdaHookArgs: Description: QnA Item Lambda Hook Args (use with no_hits item for optional ask-the-LLM fallback) @@ -211,4 +207,3 @@ Outputs: QnAItemLambdaFunctionRoleArn: Description: ARN of the Role created for executing the Lambda function Value: !GetAtt LambdaFunctionRole.Arn -